Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Thu, 07 Jun 2012 12:07:02 -0700
changeset 96563 ab5dc52e152a95eefa3bccf0bf40ab59a4f65048
parent 96562 3322cbca14139612761f241868be77e974c739c0 (current diff)
parent 96053 0099fbd7c5f3329c5314e0e22aa1fdb31fcab4c6 (diff)
child 96564 a20a6e06991442f2e5aadd2fa2225cb584e061dc
push id22914
push usergszorc@mozilla.com
push dateWed, 13 Jun 2012 15:37:56 +0000
treeherdermozilla-central@a42d6b7ef3fe [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 s-c.
accessible/src/html/nsHTMLCanvasAccessible.cpp
accessible/src/html/nsHTMLCanvasAccessible.h
accessible/src/html/nsHTMLSelectAccessible.cpp
accessible/src/html/nsHTMLSelectAccessible.h
dom/plugins/base/nsIPluginStreamInfo.idl
dom/wifi/libnetutils.js
embedding/examples/Makefile.in
embedding/examples/readme.txt
ipc/chromium/src/base/third_party/nspr/README.chromium
ipc/chromium/src/base/third_party/nspr/prcpucfg.h
ipc/chromium/src/base/third_party/nspr/prcpucfg_linux.h
ipc/chromium/src/base/third_party/nspr/prcpucfg_mac.h
ipc/chromium/src/base/third_party/nspr/prcpucfg_openbsd.h
ipc/chromium/src/base/third_party/nspr/prcpucfg_win.h
ipc/chromium/src/base/third_party/nspr/prtime.cc
ipc/chromium/src/base/third_party/nspr/prtime.h
ipc/chromium/src/base/third_party/nspr/prtypes.h
layout/forms/test/test_bug377624.html
memory/jemalloc/jemalloc.c
memory/jemalloc/jemalloc.h
memory/jemalloc/jemalloc_types.h
memory/jemalloc/linkedlist.h
memory/jemalloc/osx_zone_types.h
memory/jemalloc/ql.h
memory/jemalloc/qr.h
memory/jemalloc/rb.h
--- a/Makefile.in
+++ b/Makefile.in
@@ -42,17 +42,20 @@ tier_base_dirs += \
 endif
 ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 tier_base_dirs += \
   other-licenses/android \
   $(NULL)
 endif
 
 ifdef MOZ_MEMORY
+tier_base_dirs += memory/mozjemalloc
+ifdef MOZ_JEMALLOC
 tier_base_dirs += memory/jemalloc
+endif
 tier_base_dirs += memory/build
 endif
 tier_base_dirs += \
   mozglue \
   memory/mozalloc \
   $(NULL)
 endif
 
--- a/accessible/public/nsIAccessibilityService.h
+++ b/accessible/public/nsIAccessibilityService.h
@@ -17,35 +17,25 @@ class nsINode;
 class nsIContent;
 class nsIDocument;
 class nsIFrame;
 class nsIPresShell;
 class nsObjectFrame;
 
 // 10ff6dca-b219-4b64-9a4c-67a62b86edce
 #define NS_IACCESSIBILITYSERVICE_IID \
-{ 0x10ff6dca, 0xb219, 0x4b64, \
- { 0x9a, 0x4c, 0x67, 0xa6, 0x2b, 0x86, 0xed, 0xce } }
+{ 0x84dd9182, 0x6639, 0x4377, \
+ { 0xa4, 0x13, 0xad, 0xe1, 0xae, 0x4e, 0x52, 0xdd } }
 
 class nsIAccessibilityService : public nsIAccessibleRetrieval
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IACCESSIBILITYSERVICE_IID)
 
   /**
-   * Return an accessible object for a DOM node in the given pres shell.
-   *
-   * @param  aNode      [in] the DOM node to get an accessible for
-   * @param  aPresShell [in] the presentation shell which contains layout info
-   *                         for the DOM node
-   */
-  virtual Accessible* GetAccessible(nsINode* aNode,
-                                    nsIPresShell* aPresShell) = 0;
-
-  /**
    * Return root document accessible that is or contains a document accessible
    * for the given presshell.
    *
    * @param aPresShell  [in] the presshell
    * @param aCanCreate  [in] points whether the root document accessible
    *                        should be returned from the cache or can be created
    */
   virtual Accessible* GetRootDocumentAccessible(nsIPresShell* aPresShell,
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -9,27 +9,27 @@
 #include "Accessible-inl.h"
 #include "ApplicationAccessibleWrap.h"
 #include "ARIAGridAccessibleWrap.h"
 #ifdef MOZ_ACCESSIBILITY_ATK
 #include "AtkSocketAccessible.h"
 #endif
 #include "DocAccessible-inl.h"
 #include "FocusManager.h"
+#include "HTMLCanvasAccessible.h"
 #include "HTMLElementAccessibles.h"
 #include "HTMLImageMapAccessible.h"
 #include "HTMLLinkAccessible.h"
 #include "HTMLListAccessible.h"
+#include "HTMLSelectAccessible.h"
 #include "HyperTextAccessibleWrap.h"
 #include "nsAccessiblePivot.h"
 #include "nsAccUtils.h"
 #include "nsARIAMap.h"
 #include "nsIAccessibleProvider.h"
-#include "nsHTMLCanvasAccessible.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"
 #include "Statistics.h"
@@ -221,27 +221,27 @@ nsAccessibilityService::CreateHTMLCheckb
   return accessible;
 }
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLComboboxAccessible(nsIContent* aContent,
                                                      nsIPresShell* aPresShell)
 {
   Accessible* accessible =
-    new nsHTMLComboboxAccessible(aContent, GetDocAccessible(aPresShell));
+    new HTMLComboboxAccessible(aContent, GetDocAccessible(aPresShell));
   NS_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLCanvasAccessible(nsIContent* aContent,
                                                    nsIPresShell* aPresShell)
 {
   Accessible* accessible =
-    new nsHTMLCanvasAccessible(aContent, GetDocAccessible(aPresShell));
+    new HTMLCanvasAccessible(aContent, GetDocAccessible(aPresShell));
   NS_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLFileInputAccessible(nsIContent* aContent,
                                                       nsIPresShell* aPresShell)
 {
@@ -281,17 +281,17 @@ nsAccessibilityService::CreateHTMLGroupb
   return accessible;
 }
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLListboxAccessible(nsIContent* aContent,
                                                     nsIPresShell* aPresShell)
 {
   Accessible* accessible =
-    new nsHTMLSelectListAccessible(aContent, GetDocAccessible(aPresShell));
+    new HTMLSelectListAccessible(aContent, GetDocAccessible(aPresShell));
   NS_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLMediaAccessible(nsIContent* aContent,
                                                   nsIPresShell* aPresShell)
 {
@@ -644,17 +644,20 @@ nsAccessibilityService::GetAccessibleFor
   *aAccessible = nsnull;
   if (!aNode)
     return NS_OK;
 
   nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
   if (!node)
     return NS_ERROR_INVALID_ARG;
 
-  NS_IF_ADDREF(*aAccessible = GetAccessible(node, nsnull));
+  DocAccessible* document = GetDocAccessible(node->OwnerDoc());
+  if (document)
+    NS_IF_ADDREF(*aAccessible = document->GetAccessible(node));
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessibilityService::GetStringRole(PRUint32 aRole, nsAString& aString)
 {
 #define ROLE(geckoRole, stringRole, atkRole, macRole, msaaRole, ia2Role) \
   case roles::geckoRole: \
@@ -873,26 +876,16 @@ nsAccessibilityService::SetLogging(const
   logging::Enable(PromiseFlatCString(aModules));
 #endif
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibilityService public
 
-Accessible*
-nsAccessibilityService::GetAccessible(nsINode* aNode, nsIPresShell* aPresShell)
-{
-  NS_PRECONDITION(aNode, "Getting an accessible for null node! Crash.");
-
-  // XXX handle the presshell
-  DocAccessible* document = GetDocAccessible(aNode->OwnerDoc());
-  return document ? document->GetAccessible(aNode) : nsnull;
-}
-
 static bool HasRelatedContent(nsIContent *aContent)
 {
   nsAutoString id;
   if (!aContent || !nsCoreUtils::GetID(aContent, id) || id.IsEmpty()) {
     return false;
   }
 
   // If the given ID is referred by relation attribute then create an accessible
@@ -1599,23 +1592,23 @@ nsAccessibilityService::CreateHTMLAccess
 
   if (tag == nsGkAtoms::legend) {
     Accessible* accessible = new HTMLLegendAccessible(aContent, aDoc);
     NS_IF_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::option) {
-    Accessible* accessible = new nsHTMLSelectOptionAccessible(aContent, aDoc);
+    Accessible* accessible = new HTMLSelectOptionAccessible(aContent, aDoc);
     NS_IF_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::optgroup) {
-    Accessible* accessible = new nsHTMLSelectOptGroupAccessible(aContent, aDoc);
+    Accessible* accessible = new HTMLSelectOptGroupAccessible(aContent, aDoc);
     NS_IF_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::ul || tag == nsGkAtoms::ol ||
       tag == nsGkAtoms::dl) {
     Accessible* accessible = new HTMLListAccessible(aContent, aDoc);
     NS_IF_ADDREF(accessible);
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -28,20 +28,22 @@ FocusManager* FocusMgr();
 
 #ifdef MOZ_ACCESSIBILITY_ATK
 /**
  * Perform initialization that should be done as soon as possible, in order
  * to minimize startup time.
  * XXX: this function and the next defined in ApplicationAccessibleWrap.cpp
  */
 void PreInit();
+#endif
 
+#if defined(MOZ_ACCESSIBILITY_ATK) || defined(XP_MACOSX)
 /**
  * Is platform accessibility enabled.
- * Only used on linux with atk for now.
+ * Only used on linux with atk and MacOS for now.
  */
 bool ShouldA11yBeEnabled();
 #endif
 
 } // namespace a11y
 } // namespace mozilla
 
 class nsAccessibilityService : public nsAccDocManager,
@@ -170,22 +172,16 @@ public:
    * @param  aNode             [in] the given node
    * @param  aDoc              [in] the doc accessible of the node  
    * @param  aIsSubtreeHidden  [out, optional] indicates whether the node's
    *                             frame and its subtree is hidden
    */
   Accessible* GetOrCreateAccessible(nsINode* aNode, DocAccessible* aDoc,
                                     bool* aIsSubtreeHidden = nsnull);
 
-  /**
-   * Return an accessible for the given DOM node and eventually a presentation
-   * shell.
-   */
-  Accessible* GetAccessible(nsINode* aNode, nsIPresShell* aPresShell);
-
 private:
   // nsAccessibilityService creation is controlled by friend
   // NS_GetAccessibilityService, keep constructors private.
   nsAccessibilityService();
   nsAccessibilityService(const nsAccessibilityService&);
   nsAccessibilityService& operator =(const nsAccessibilityService&);
 
 private:
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -27,17 +27,16 @@
 #include "nsIDOMDocumentType.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMXULPopupElement.h"
 #include "nsIEditingSession.h"
 #include "nsEventStateManager.h"
 #include "nsIFrame.h"
-#include "nsHTMLSelectAccessible.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsINameSpaceManager.h"
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsIViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
--- a/accessible/src/generic/RootAccessible.cpp
+++ b/accessible/src/generic/RootAccessible.cpp
@@ -15,17 +15,17 @@
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "Relation.h"
 #include "Role.h"
 #include "States.h"
 
 #include "mozilla/dom/Element.h"
-#include "nsHTMLSelectAccessible.h"
+
 #include "nsIAccessibleRelation.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMEventTarget.h"
rename from accessible/src/html/nsHTMLCanvasAccessible.cpp
rename to accessible/src/html/HTMLCanvasAccessible.cpp
--- a/accessible/src/html/nsHTMLCanvasAccessible.cpp
+++ b/accessible/src/html/HTMLCanvasAccessible.cpp
@@ -1,22 +1,22 @@
 /* -*- 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 "nsHTMLCanvasAccessible.h"
+#include "HTMLCanvasAccessible.h"
 
 #include "Role.h"
 
 using namespace mozilla::a11y;
 
-nsHTMLCanvasAccessible::
-  nsHTMLCanvasAccessible(nsIContent* aContent, DocAccessible* aDoc) :
+HTMLCanvasAccessible::
+  HTMLCanvasAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   HyperTextAccessible(aContent, aDoc)
 {
 }
 
 role
-nsHTMLCanvasAccessible::NativeRole()
+HTMLCanvasAccessible::NativeRole()
 {
   return roles::CANVAS;
 }
rename from accessible/src/html/nsHTMLCanvasAccessible.h
rename to accessible/src/html/HTMLCanvasAccessible.h
--- a/accessible/src/html/nsHTMLCanvasAccessible.h
+++ b/accessible/src/html/HTMLCanvasAccessible.h
@@ -1,24 +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/. */
 
 #include "HyperTextAccessible.h"
 
-#ifndef _nsHTMLCanvasAccessible_H_
-#define _nsHTMLCanvasAccessible_H_
+#ifndef mozilla_a11y_HTMLCanvasAccessible_h__
+#define mozilla_a11y_HTMLCanvasAccessible_h__
+
+namespace mozilla {
+namespace a11y {
 
 /**
  * HTML canvas accessible (html:canvas).
  */
-class nsHTMLCanvasAccessible : public HyperTextAccessible
+class HTMLCanvasAccessible : public HyperTextAccessible
 {
 public:
-  nsHTMLCanvasAccessible(nsIContent* aContent, DocAccessible* aDoc);
-  virtual ~nsHTMLCanvasAccessible() { }
+  HTMLCanvasAccessible(nsIContent* aContent, DocAccessible* aDoc);
+  virtual ~HTMLCanvasAccessible() { }
 
   // Accessible
-  virtual mozilla::a11y::role NativeRole();
+  virtual a11y::role NativeRole();
 };
 
+} // namespace a11y
+} // namespace mozilla
+
 #endif
rename from accessible/src/html/nsHTMLSelectAccessible.cpp
rename to accessible/src/html/HTMLSelectAccessible.cpp
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/HTMLSelectAccessible.cpp
@@ -1,14 +1,14 @@
 /* -*- 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/. */
 
-#include "nsHTMLSelectAccessible.h"
+#include "HTMLSelectAccessible.h"
 
 #include "Accessible-inl.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "DocAccessible.h"
 #include "nsEventShell.h"
 #include "nsIAccessibleEvent.h"
 #include "nsTextEquivUtils.h"
@@ -24,130 +24,130 @@
 #include "nsIDOMHTMLSelectElement.h"
 #include "nsIListControlFrame.h"
 #include "nsIServiceManager.h"
 #include "nsIMutableArray.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLSelectListAccessible
+// HTMLSelectListAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsHTMLSelectListAccessible::
-  nsHTMLSelectListAccessible(nsIContent* aContent, DocAccessible* aDoc) :
+HTMLSelectListAccessible::
+  HTMLSelectListAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   AccessibleWrap(aContent, aDoc)
 {
   mFlags |= eListControlAccessible;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLSelectListAccessible: Accessible public
+// HTMLSelectListAccessible: Accessible public
 
 PRUint64
-nsHTMLSelectListAccessible::NativeState()
+HTMLSelectListAccessible::NativeState()
 {
   PRUint64 state = AccessibleWrap::NativeState();
   if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple))
     state |= states::MULTISELECTABLE | states::EXTSELECTABLE;
 
   return state;
 }
 
 role
-nsHTMLSelectListAccessible::NativeRole()
+HTMLSelectListAccessible::NativeRole()
 {
   return roles::LISTBOX;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLSelectListAccessible: SelectAccessible
+// HTMLSelectListAccessible: SelectAccessible
 
 bool
-nsHTMLSelectListAccessible::IsSelect()
+HTMLSelectListAccessible::IsSelect()
 {
   return true;
 }
 
 bool
-nsHTMLSelectListAccessible::SelectAll()
+HTMLSelectListAccessible::SelectAll()
 {
   return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ?
     AccessibleWrap::SelectAll() : false;
 }
 
 bool
-nsHTMLSelectListAccessible::UnselectAll()
+HTMLSelectListAccessible::UnselectAll()
 {
   return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ?
     AccessibleWrap::UnselectAll() : false;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLSelectListAccessible: Widgets
+// HTMLSelectListAccessible: Widgets
 
 bool
-nsHTMLSelectListAccessible::IsWidget() const
+HTMLSelectListAccessible::IsWidget() const
 {
   return true;
 }
 
 bool
-nsHTMLSelectListAccessible::IsActiveWidget() const
+HTMLSelectListAccessible::IsActiveWidget() const
 {
   return FocusMgr()->HasDOMFocus(mContent);
 }
 
 bool
-nsHTMLSelectListAccessible::AreItemsOperable() const
+HTMLSelectListAccessible::AreItemsOperable() const
 {
   return true;
 }
 
 Accessible*
-nsHTMLSelectListAccessible::CurrentItem()
+HTMLSelectListAccessible::CurrentItem()
 {
   nsIListControlFrame* listControlFrame = do_QueryFrame(GetFrame());
   if (listControlFrame) {
     nsCOMPtr<nsIContent> activeOptionNode = listControlFrame->GetCurrentOption();
     if (activeOptionNode) {
       DocAccessible* document = Document();
       if (document)
         return document->GetAccessible(activeOptionNode);
     }
   }
   return nsnull;
 }
 
 void
-nsHTMLSelectListAccessible::SetCurrentItem(Accessible* aItem)
+HTMLSelectListAccessible::SetCurrentItem(Accessible* aItem)
 {
   aItem->GetContent()->SetAttr(kNameSpaceID_None,
                                nsGkAtoms::selected, NS_LITERAL_STRING("true"),
                                true);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLSelectListAccessible: Accessible protected
+// HTMLSelectListAccessible: Accessible protected
 
 void
-nsHTMLSelectListAccessible::CacheChildren()
+HTMLSelectListAccessible::CacheChildren()
 {
   // Cache accessibles for <optgroup> and <option> DOM decendents as children,
   // as well as the accessibles for them. Avoid whitespace text nodes. We want
   // to count all the <optgroup>s and <option>s as children because we want
   // a flat tree under the Select List.
   CacheOptSiblings(mContent);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLSelectListAccessible protected
+// HTMLSelectListAccessible protected
 
 void
-nsHTMLSelectListAccessible::CacheOptSiblings(nsIContent *aParentContent)
+HTMLSelectListAccessible::CacheOptSiblings(nsIContent* aParentContent)
 {
   for (nsIContent* childContent = aParentContent->GetFirstChild(); childContent;
        childContent = childContent->GetNextSibling()) {
     if (!childContent->IsHTML()) {
       continue;
     }
 
     nsIAtom* tag = childContent->Tag();
@@ -164,39 +164,39 @@ nsHTMLSelectListAccessible::CacheOptSibl
       if (tag == nsGkAtoms::optgroup)
         CacheOptSiblings(childContent);
     }
   }
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLSelectOptionAccessible
+// HTMLSelectOptionAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsHTMLSelectOptionAccessible::
-  nsHTMLSelectOptionAccessible(nsIContent* aContent, DocAccessible* aDoc) :
+HTMLSelectOptionAccessible::
+  HTMLSelectOptionAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   HyperTextAccessibleWrap(aContent, aDoc)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLSelectOptionAccessible: Accessible public
+// HTMLSelectOptionAccessible: Accessible public
 
 role
-nsHTMLSelectOptionAccessible::NativeRole()
+HTMLSelectOptionAccessible::NativeRole()
 {
   if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
     return roles::COMBOBOX_OPTION;
 
   return roles::OPTION;
 }
 
 nsresult
-nsHTMLSelectOptionAccessible::GetNameInternal(nsAString& aName)
+HTMLSelectOptionAccessible::GetNameInternal(nsAString& aName)
 {
   // CASE #1 -- great majority of the cases
   // find the label attribute - this is what the W3C says we should use
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
   if (!aName.IsEmpty())
     return NS_OK;
 
   // CASE #2 -- no label parameter, get the first child, 
@@ -216,19 +216,19 @@ nsHTMLSelectOptionAccessible::GetNameInt
     aName.Assign(txtValue);
     return NS_OK;
   }
 
   return NS_OK;
 }
 
 PRUint64
-nsHTMLSelectOptionAccessible::NativeState()
+HTMLSelectOptionAccessible::NativeState()
 {
-  // As a nsHTMLSelectOptionAccessible we can have the following states:
+  // As a HTMLSelectOptionAccessible we can have the following states:
   // SELECTABLE, SELECTED, FOCUSED, FOCUSABLE, OFFSCREEN
   // Upcall to Accessible, but skip HyperTextAccessible impl
   // because we don't want EDITABLE or SELECTABLE_TEXT
   PRUint64 state = Accessible::NativeState();
 
   Accessible* select = GetSelect();
   if (!select)
     return state;
@@ -277,270 +277,271 @@ nsHTMLSelectOptionAccessible::NativeStat
       }
     }
   }
  
   return state;
 }
 
 PRUint64
-nsHTMLSelectOptionAccessible::NativeInteractiveState() const
+HTMLSelectOptionAccessible::NativeInteractiveState() const
 {
   return NativelyUnavailable() ?
     states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
 }
 
 PRInt32
-nsHTMLSelectOptionAccessible::GetLevelInternal()
+HTMLSelectOptionAccessible::GetLevelInternal()
 {
   nsIContent *parentContent = mContent->GetParent();
 
   PRInt32 level =
     parentContent->NodeInfo()->Equals(nsGkAtoms::optgroup) ? 2 : 1;
 
   if (level == 1 && Role() != roles::HEADING)
     level = 0; // In a single level list, the level is irrelevant
 
   return level;
 }
 
 void
-nsHTMLSelectOptionAccessible::GetBoundsRect(nsRect& aTotalBounds,
-                                            nsIFrame** aBoundingFrame)
+HTMLSelectOptionAccessible::GetBoundsRect(nsRect& aTotalBounds,
+                                          nsIFrame** aBoundingFrame)
 {
   Accessible* combobox = GetCombobox();
   if (combobox && (combobox->State() & states::COLLAPSED))
     combobox->GetBoundsRect(aTotalBounds, aBoundingFrame);
   else
     HyperTextAccessibleWrap::GetBoundsRect(aTotalBounds, aBoundingFrame);
 }
 
-/** select us! close combo box if necessary*/
-NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+NS_IMETHODIMP
+HTMLSelectOptionAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
 {
   if (aIndex == eAction_Select) {
     aName.AssignLiteral("select"); 
     return NS_OK;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
 PRUint8
-nsHTMLSelectOptionAccessible::ActionCount()
+HTMLSelectOptionAccessible::ActionCount()
 {
   return 1;
 }
 
 NS_IMETHODIMP
-nsHTMLSelectOptionAccessible::DoAction(PRUint8 aIndex)
+HTMLSelectOptionAccessible::DoAction(PRUint8 aIndex)
 {
   if (aIndex != eAction_Select)
     return NS_ERROR_INVALID_ARG;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   DoCommand();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLSelectOptionAccessible::SetSelected(bool aSelect)
+HTMLSelectOptionAccessible::SetSelected(bool aSelect)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIDOMHTMLOptionElement> optionElm(do_QueryInterface(mContent));
   return optionElm->SetSelected(aSelect);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLSelectOptionAccessible: Widgets
+// HTMLSelectOptionAccessible: Widgets
 
 Accessible*
-nsHTMLSelectOptionAccessible::ContainerWidget() const
+HTMLSelectOptionAccessible::ContainerWidget() const
 {
   return mParent && mParent->IsListControl() ? mParent : nsnull;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLSelectOptGroupAccessible
+// HTMLSelectOptGroupAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsHTMLSelectOptGroupAccessible::
-  nsHTMLSelectOptGroupAccessible(nsIContent* aContent,
-                                 DocAccessible* aDoc) :
-  nsHTMLSelectOptionAccessible(aContent, aDoc)
+HTMLSelectOptGroupAccessible::
+  HTMLSelectOptGroupAccessible(nsIContent* aContent, DocAccessible* aDoc) :
+  HTMLSelectOptionAccessible(aContent, aDoc)
 {
 }
 
 role
-nsHTMLSelectOptGroupAccessible::NativeRole()
+HTMLSelectOptGroupAccessible::NativeRole()
 {
   return roles::HEADING;
 }
 
 PRUint64
-nsHTMLSelectOptGroupAccessible::NativeInteractiveState() const
+HTMLSelectOptGroupAccessible::NativeInteractiveState() const
 {
   return NativelyUnavailable() ? states::UNAVAILABLE : 0;
 }
 
-NS_IMETHODIMP nsHTMLSelectOptGroupAccessible::DoAction(PRUint8 index)
+NS_IMETHODIMP
+HTMLSelectOptGroupAccessible::DoAction(PRUint8 index)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-NS_IMETHODIMP nsHTMLSelectOptGroupAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+NS_IMETHODIMP
+HTMLSelectOptGroupAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 PRUint8
-nsHTMLSelectOptGroupAccessible::ActionCount()
+HTMLSelectOptGroupAccessible::ActionCount()
 {
   return 0;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLSelectOptGroupAccessible: Accessible protected
+// HTMLSelectOptGroupAccessible: Accessible protected
 
 void
-nsHTMLSelectOptGroupAccessible::CacheChildren()
+HTMLSelectOptGroupAccessible::CacheChildren()
 {
   // XXX To do (bug 378612) - create text child for the anonymous attribute
   // content, so that nsIAccessibleText is supported for the <optgroup> as it is
   // for an <option>. Attribute content is what layout creates for
   // the label="foo" on the <optgroup>. See eStyleContentType_Attr and
   // CreateAttributeContent() in nsCSSFrameConstructor
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLComboboxAccessible
+// HTMLComboboxAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsHTMLComboboxAccessible::
-  nsHTMLComboboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
+HTMLComboboxAccessible::
+  HTMLComboboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   AccessibleWrap(aContent, aDoc)
 {
   mFlags |= eComboboxAccessible;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLComboboxAccessible: Accessible
+// HTMLComboboxAccessible: Accessible
 
 role
-nsHTMLComboboxAccessible::NativeRole()
+HTMLComboboxAccessible::NativeRole()
 {
   return roles::COMBOBOX;
 }
 
 void
-nsHTMLComboboxAccessible::InvalidateChildren()
+HTMLComboboxAccessible::InvalidateChildren()
 {
   AccessibleWrap::InvalidateChildren();
 
   if (mListAccessible)
     mListAccessible->InvalidateChildren();
 }
 
 void
-nsHTMLComboboxAccessible::CacheChildren()
+HTMLComboboxAccessible::CacheChildren()
 {
   nsIFrame* frame = GetFrame();
   if (!frame)
     return;
 
   nsIComboboxControlFrame *comboFrame = do_QueryFrame(frame);
   if (!comboFrame)
     return;
 
   nsIFrame *listFrame = comboFrame->GetDropDown();
   if (!listFrame)
     return;
 
   if (!mListAccessible) {
     mListAccessible = 
-      new nsHTMLComboboxListAccessible(mParent, mContent, mDoc);
+      new HTMLComboboxListAccessible(mParent, mContent, mDoc);
 
     // Initialize and put into cache.
     if (!Document()->BindToDocument(mListAccessible, nsnull))
       return;
   }
 
   if (AppendChild(mListAccessible)) {
     // Cache combobox option accessibles so that we build complete accessible
     // tree for combobox.
     mListAccessible->EnsureChildren();
   }
 }
 
 void
-nsHTMLComboboxAccessible::Shutdown()
+HTMLComboboxAccessible::Shutdown()
 {
   AccessibleWrap::Shutdown();
 
   if (mListAccessible) {
     mListAccessible->Shutdown();
     mListAccessible = nsnull;
   }
 }
 
 PRUint64
-nsHTMLComboboxAccessible::NativeState()
+HTMLComboboxAccessible::NativeState()
 {
-  // As a nsHTMLComboboxAccessible we can have the following states:
+  // As a HTMLComboboxAccessible we can have the following states:
   // FOCUSED, FOCUSABLE, HASPOPUP, EXPANDED, COLLAPSED
   // Get focus status from base class
   PRUint64 state = Accessible::NativeState();
 
   nsIComboboxControlFrame* comboFrame = do_QueryFrame(GetFrame());
   if (comboFrame && comboFrame->IsDroppedDown())
     state |= states::EXPANDED;
   else
     state |= states::COLLAPSED;
 
   state |= states::HASPOPUP;
   return state;
 }
 
 void
-nsHTMLComboboxAccessible::Description(nsString& aDescription)
+HTMLComboboxAccessible::Description(nsString& aDescription)
 {
   aDescription.Truncate();
   // First check to see if combo box itself has a description, perhaps through
   // tooltip (title attribute) or via aria-describedby
   Accessible::Description(aDescription);
   if (!aDescription.IsEmpty())
     return;
 
   // Otherwise use description of selected option.
   Accessible* option = SelectedOption();
   if (option)
     option->Description(aDescription);
 }
 
 void
-nsHTMLComboboxAccessible::Value(nsString& aValue)
+HTMLComboboxAccessible::Value(nsString& aValue)
 {
   // Use accessible name of selected option.
   Accessible* option = SelectedOption();
   if (option)
     option->Name(aValue);
 }
 
 PRUint8
-nsHTMLComboboxAccessible::ActionCount()
+HTMLComboboxAccessible::ActionCount()
 {
   return 1;
 }
 
 NS_IMETHODIMP
-nsHTMLComboboxAccessible::DoAction(PRUint8 aIndex)
+HTMLComboboxAccessible::DoAction(PRUint8 aIndex)
 {
   if (aIndex != eAction_Click)
     return NS_ERROR_INVALID_ARG;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   DoCommand();
@@ -548,19 +549,20 @@ nsHTMLComboboxAccessible::DoAction(PRUin
 }
 
 /**
   * Our action name is the reverse of our state: 
   *     if we are closed -> open is our name.
   *     if we are open -> closed is our name.
   * Uses the frame to get the state, updated on every click
   */
-NS_IMETHODIMP nsHTMLComboboxAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+NS_IMETHODIMP
+HTMLComboboxAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
 {
-  if (aIndex != nsHTMLComboboxAccessible::eAction_Click) {
+  if (aIndex != HTMLComboboxAccessible::eAction_Click) {
     return NS_ERROR_INVALID_ARG;
   }
   nsIFrame *frame = GetFrame();
   if (!frame) {
     return NS_ERROR_FAILURE;
   }
   nsIComboboxControlFrame *comboFrame = do_QueryFrame(frame);
   if (!comboFrame) {
@@ -570,55 +572,55 @@ NS_IMETHODIMP nsHTMLComboboxAccessible::
     aName.AssignLiteral("close"); 
   else
     aName.AssignLiteral("open"); 
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLComboboxAccessible: Widgets
+// HTMLComboboxAccessible: Widgets
 
 bool
-nsHTMLComboboxAccessible::IsWidget() const
+HTMLComboboxAccessible::IsWidget() const
 {
   return true;
 }
 
 bool
-nsHTMLComboboxAccessible::IsActiveWidget() const
+HTMLComboboxAccessible::IsActiveWidget() const
 {
   return FocusMgr()->HasDOMFocus(mContent);
 }
 
 bool
-nsHTMLComboboxAccessible::AreItemsOperable() const
+HTMLComboboxAccessible::AreItemsOperable() const
 {
   nsIComboboxControlFrame* comboboxFrame = do_QueryFrame(GetFrame());
   return comboboxFrame && comboboxFrame->IsDroppedDown();
 }
 
 Accessible*
-nsHTMLComboboxAccessible::CurrentItem()
+HTMLComboboxAccessible::CurrentItem()
 {
   return AreItemsOperable() ? mListAccessible->CurrentItem() : nsnull;
 }
 
 void
-nsHTMLComboboxAccessible::SetCurrentItem(Accessible* aItem)
+HTMLComboboxAccessible::SetCurrentItem(Accessible* aItem)
 {
   if (AreItemsOperable())
     mListAccessible->SetCurrentItem(aItem);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLComboboxAccessible: protected
+// HTMLComboboxAccessible: protected
 
 Accessible*
-nsHTMLComboboxAccessible::SelectedOption() const
+HTMLComboboxAccessible::SelectedOption() const
 {
   nsIFrame* frame = GetFrame();
   nsIComboboxControlFrame* comboboxFrame = do_QueryFrame(frame);
   if (!comboboxFrame)
     return nsnull;
 
   nsIListControlFrame* listControlFrame =
     do_QueryFrame(comboboxFrame->GetDropDown());
@@ -631,63 +633,63 @@ nsHTMLComboboxAccessible::SelectedOption
     }
   }
 
   return nsnull;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLComboboxListAccessible
+// HTMLComboboxListAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsHTMLComboboxListAccessible::
-  nsHTMLComboboxListAccessible(nsIAccessible* aParent, nsIContent* aContent,
-                               DocAccessible* aDoc) :
-  nsHTMLSelectListAccessible(aContent, aDoc)
+HTMLComboboxListAccessible::
+  HTMLComboboxListAccessible(nsIAccessible* aParent, nsIContent* aContent,
+                             DocAccessible* aDoc) :
+  HTMLSelectListAccessible(aContent, aDoc)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLComboboxAccessible: nsAccessNode
+// HTMLComboboxAccessible: nsAccessNode
 
 nsIFrame*
-nsHTMLComboboxListAccessible::GetFrame() const
+HTMLComboboxListAccessible::GetFrame() const
 {
-  nsIFrame* frame = nsHTMLSelectListAccessible::GetFrame();
+  nsIFrame* frame = HTMLSelectListAccessible::GetFrame();
 
   if (frame) {
     nsIComboboxControlFrame* comboBox = do_QueryFrame(frame);
     if (comboBox) {
       return comboBox->GetDropDown();
     }
   }
 
   return nsnull;
 }
 
 bool
-nsHTMLComboboxListAccessible::IsPrimaryForNode() const
+HTMLComboboxListAccessible::IsPrimaryForNode() const
 {
   return false;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLComboboxAccessible: Accessible
+// HTMLComboboxAccessible: Accessible
 
 role
-nsHTMLComboboxListAccessible::NativeRole()
+HTMLComboboxListAccessible::NativeRole()
 {
   return roles::COMBOBOX_LIST;
 }
 
 PRUint64
-nsHTMLComboboxListAccessible::NativeState()
+HTMLComboboxListAccessible::NativeState()
 {
-  // As a nsHTMLComboboxListAccessible we can have the following states:
+  // As a HTMLComboboxListAccessible we can have the following states:
   // FOCUSED, FOCUSABLE, FLOATING, INVISIBLE
   // Get focus status from base class
   PRUint64 state = Accessible::NativeState();
 
   nsIComboboxControlFrame* comboFrame = do_QueryFrame(mParent->GetFrame());
   if (comboFrame && comboFrame->IsDroppedDown())
     state |= states::FLOATING;
   else
@@ -695,26 +697,27 @@ nsHTMLComboboxListAccessible::NativeStat
 
   return state;
 }
 
 /**
   * Gets the bounds for the areaFrame.
   *     Walks the Frame tree and checks for proper frames.
   */
-void nsHTMLComboboxListAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame)
+void
+HTMLComboboxListAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame)
 {
   *aBoundingFrame = nsnull;
 
   Accessible* comboAcc = Parent();
   if (!comboAcc)
     return;
 
   if (0 == (comboAcc->State() & states::COLLAPSED)) {
-    nsHTMLSelectListAccessible::GetBoundsRect(aBounds, aBoundingFrame);
+    HTMLSelectListAccessible::GetBoundsRect(aBounds, aBoundingFrame);
     return;
   }
 
   // Get the first option.
   nsIContent* content = mContent->GetFirstChild();
   if (!content) {
     return;
   }
@@ -724,22 +727,22 @@ void nsHTMLComboboxListAccessible::GetBo
     return;
   }
 
   *aBoundingFrame = frame->GetParent();
   aBounds = (*aBoundingFrame)->GetRect();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLComboboxListAccessible: Widgets
+// HTMLComboboxListAccessible: Widgets
 
 bool
-nsHTMLComboboxListAccessible::IsActiveWidget() const
+HTMLComboboxListAccessible::IsActiveWidget() const
 {
   return mParent && mParent->IsActiveWidget();
 }
 
 bool
-nsHTMLComboboxListAccessible::AreItemsOperable() const
+HTMLComboboxListAccessible::AreItemsOperable() const
 {
   return mParent && mParent->AreItemsOperable();
 }
 
rename from accessible/src/html/nsHTMLSelectAccessible.h
rename to accessible/src/html/HTMLSelectAccessible.h
--- a/accessible/src/html/nsHTMLSelectAccessible.h
+++ b/accessible/src/html/HTMLSelectAccessible.h
@@ -1,49 +1,53 @@
 /* -*- 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 __nsHTMLSelectAccessible_h__
-#define __nsHTMLSelectAccessible_h__
+
+#ifndef mozilla_a11y_HTMLSelectAccessible_h__
+#define mozilla_a11y_HTMLSelectAccessible_h__
 
 #include "HTMLFormControlAccessible.h"
 #include "nsIDOMHTMLOptionsCollection.h"
 #include "nsIDOMHTMLOptionElement.h"
 #include "nsIDOMNode.h"
 
 class nsIMutableArray;
 
+namespace mozilla {
+namespace a11y {
+
 /**
   *  Selects, Listboxes and Comboboxes, are made up of a number of different
   *  widgets, some of which are shared between the two. This file contains
-	*  all of the widgets for both of the Selects, for HTML only.
+  *  all of the widgets for both of the Selects, for HTML only.
   *
   *  Listbox:
-  *     - nsHTMLSelectListAccessible
-  *        - nsHTMLSelectOptionAccessible
+  *     - HTMLSelectListAccessible
+  *        - HTMLSelectOptionAccessible
   *
   *  Comboboxes:
-  *     - nsHTMLComboboxAccessible
-  *        - nsHTMLComboboxListAccessible  [ inserted in accessible tree ]
-  *           - nsHTMLSelectOptionAccessible(s)
+  *     - HTMLComboboxAccessible
+  *        - HTMLComboboxListAccessible  [ inserted in accessible tree ]
+  *           - HTMLSelectOptionAccessible(s)
   */
 
 /*
  * The list that contains all the options in the select.
  */
-class nsHTMLSelectListAccessible : public AccessibleWrap
+class HTMLSelectListAccessible : public AccessibleWrap
 {
 public:
-  
-  nsHTMLSelectListAccessible(nsIContent* aContent, DocAccessible* aDoc);
-  virtual ~nsHTMLSelectListAccessible() {}
+
+  HTMLSelectListAccessible(nsIContent* aContent, DocAccessible* aDoc);
+  virtual ~HTMLSelectListAccessible() {}
 
   // Accessible
-  virtual mozilla::a11y::role NativeRole();
+  virtual a11y::role NativeRole();
   virtual PRUint64 NativeState();
 
   // SelectAccessible
   virtual bool IsSelect();
   virtual bool SelectAll();
   virtual bool UnselectAll();
 
   // Widgets
@@ -53,60 +57,60 @@ public:
   virtual Accessible* CurrentItem();
   virtual void SetCurrentItem(Accessible* aItem);
 
 protected:
 
   // Accessible
   virtual void CacheChildren();
 
-  // nsHTMLSelectListAccessible
+  // HTMLSelectListAccessible
 
   /**
    * Recursive helper for CacheChildren().
    */
-  void CacheOptSiblings(nsIContent *aParentContent);
+  void CacheOptSiblings(nsIContent* aParentContent);
 };
 
 /*
  * Options inside the select, contained within the list
  */
-class nsHTMLSelectOptionAccessible : public HyperTextAccessibleWrap
+class HTMLSelectOptionAccessible : public HyperTextAccessibleWrap
 {
 public:
-  enum { eAction_Select = 0 };  
-  
-  nsHTMLSelectOptionAccessible(nsIContent* aContent, DocAccessible* aDoc);
-  virtual ~nsHTMLSelectOptionAccessible() {}
+  enum { eAction_Select = 0 };
+
+  HTMLSelectOptionAccessible(nsIContent* aContent, DocAccessible* aDoc);
+  virtual ~HTMLSelectOptionAccessible() {}
 
   // nsIAccessible
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD SetSelected(bool aSelect);
 
   // Accessible
   virtual nsresult GetNameInternal(nsAString& aName);
-  virtual mozilla::a11y::role NativeRole();
+  virtual a11y::role NativeRole();
   virtual PRUint64 NativeState();
   virtual PRUint64 NativeInteractiveState() const;
 
   virtual PRInt32 GetLevelInternal();
   virtual void GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame);
 
   // ActionAccessible
   virtual PRUint8 ActionCount();
 
   // Widgets
   virtual Accessible* ContainerWidget() const;
 
 private:
-  
+
   /**
    * Return a select accessible the option belongs to if any.
-   */ 
+   */
   Accessible* GetSelect() const
   {
     if (mParent && mParent->IsListControl()) {
       Accessible* combobox = mParent->Parent();
       return combobox && combobox->IsCombobox() ? combobox : mParent.get();
     }
 
     return nsnull;
@@ -124,67 +128,67 @@ private:
 
     return nsnull;
   }
 };
 
 /*
  * Opt Groups inside the select, contained within the list
  */
-class nsHTMLSelectOptGroupAccessible : public nsHTMLSelectOptionAccessible
+class HTMLSelectOptGroupAccessible : public HTMLSelectOptionAccessible
 {
 public:
 
-  nsHTMLSelectOptGroupAccessible(nsIContent* aContent, DocAccessible* aDoc);
-  virtual ~nsHTMLSelectOptGroupAccessible() {}
+  HTMLSelectOptGroupAccessible(nsIContent* aContent, DocAccessible* aDoc);
+  virtual ~HTMLSelectOptGroupAccessible() {}
 
   // nsIAccessible
-  NS_IMETHOD DoAction(PRUint8 index);  
+  NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
 
   // Accessible
-  virtual mozilla::a11y::role NativeRole();
+  virtual a11y::role NativeRole();
   virtual PRUint64 NativeInteractiveState() const;
 
   // ActionAccessible
   virtual PRUint8 ActionCount();
 
 protected:
   // Accessible
   virtual void CacheChildren();
 };
 
 /** ------------------------------------------------------ */
 /**  Finally, the Combobox widgets                         */
 /** ------------------------------------------------------ */
 
-class nsHTMLComboboxListAccessible;
+class HTMLComboboxListAccessible;
 
 /*
  * A class the represents the HTML Combobox widget.
  */
-class nsHTMLComboboxAccessible : public AccessibleWrap
+class HTMLComboboxAccessible : public AccessibleWrap
 {
 public:
   enum { eAction_Click = 0 };
 
-  nsHTMLComboboxAccessible(nsIContent* aContent, DocAccessible* aDoc);
-  virtual ~nsHTMLComboboxAccessible() {}
+  HTMLComboboxAccessible(nsIContent* aContent, DocAccessible* aDoc);
+  virtual ~HTMLComboboxAccessible() {}
 
   // nsIAccessible
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
 
   // nsAccessNode
   virtual void Shutdown();
 
   // Accessible
   virtual void Description(nsString& aDescription);
   virtual void Value(nsString& aValue);
-  virtual mozilla::a11y::role NativeRole();
+  virtual a11y::role NativeRole();
   virtual PRUint64 NativeState();
   virtual void InvalidateChildren();
 
   // ActionAccessible
   virtual PRUint8 ActionCount();
 
   // Widgets
   virtual bool IsWidget() const;
@@ -198,40 +202,42 @@ protected:
   virtual void CacheChildren();
 
   /**
    * Return selected option.
    */
   Accessible* SelectedOption() const;
 
 private:
-  nsRefPtr<nsHTMLComboboxListAccessible> mListAccessible;
+  nsRefPtr<HTMLComboboxListAccessible> mListAccessible;
 };
 
 /*
  * A class that represents the window that lives to the right
  * of the drop down button inside the Select. This is the window
  * that is made visible when the button is pressed.
  */
-class nsHTMLComboboxListAccessible : public nsHTMLSelectListAccessible
+class HTMLComboboxListAccessible : public HTMLSelectListAccessible
 {
 public:
 
-  nsHTMLComboboxListAccessible(nsIAccessible* aParent, 
-                               nsIContent* aContent, 
-                               DocAccessible* aDoc);
-  virtual ~nsHTMLComboboxListAccessible() {}
+  HTMLComboboxListAccessible(nsIAccessible* aParent, nsIContent* aContent,
+                             DocAccessible* aDoc);
+  virtual ~HTMLComboboxListAccessible() {}
 
   // nsAccessNode
   virtual nsIFrame* GetFrame() const;
   virtual bool IsPrimaryForNode() const;
 
   // Accessible
-  virtual mozilla::a11y::role NativeRole();
+  virtual a11y::role NativeRole();
   virtual PRUint64 NativeState();
   virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame);
 
   // Widgets
   virtual bool IsActiveWidget() const;
   virtual bool AreItemsOperable() const;
 };
 
+} // namespace a11y
+} // namespace mozilla
+
 #endif
--- a/accessible/src/html/Makefile.in
+++ b/accessible/src/html/Makefile.in
@@ -12,23 +12,23 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_html_s
 LIBXUL_LIBRARY = 1
 
 
 
 CPPSRCS = \
+  HTMLCanvasAccessible.cpp \
   HTMLElementAccessibles.cpp \
   HTMLFormControlAccessible.cpp \
   HTMLImageMapAccessible.cpp \
   HTMLLinkAccessible.cpp \
   HTMLListAccessible.cpp \
-  nsHTMLCanvasAccessible.cpp \
-  nsHTMLSelectAccessible.cpp \
+  HTMLSelectAccessible.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/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -217,29 +217,16 @@ var AccessFu = {
           let position = pivot.position;
           let doc = aEvent.DOMNode;
 
           let presenterContext =
             new PresenterContext(position, event.oldAccessible);
           this.presenters.forEach(
             function(p) { p.pivotChanged(presenterContext); });
 
-          if (position && position.DOMNode &&
-              doc instanceof Ci.nsIDOMDocument) {
-            // Set the caret to the start of the pivot position, and move
-            // the focus in the same manner as browse with caret mode.
-            // This blurs the focus on the previous pivot position (if it
-            // was activated), and keeps us in a predictable spot for tab
-            // focus.
-            let sel = doc.getSelection();
-            sel.collapse(position.DOMNode, 0);
-            Cc["@mozilla.org/focus-manager;1"]
-              .getService(Ci.nsIFocusManager).moveFocus(
-                doc.defaultView, null, Ci.nsIFocusManager.MOVEFOCUS_CARET, 0);
-          }
           break;
         }
       case Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE:
         {
           let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
           if (event.state == Ci.nsIAccessibleStates.STATE_CHECKED &&
               !(event.isExtraState())) {
             this.presenters.forEach(
@@ -351,16 +338,25 @@ var AccessFu = {
         }
         break;
       }
       case Ci.nsIAccessibleEvent.EVENT_SCROLLING_START:
       {
         VirtualCursorController.moveCursorToObject(aEvent.accessible);
         break;
       }
+      case Ci.nsIAccessibleEvent.EVENT_FOCUS:
+      {
+        let acc = aEvent.accessible;
+        let doc = aEvent.accessibleDocument;
+        if (acc.role != Ci.nsIAccessibleRole.ROLE_DOCUMENT &&
+            doc.role != Ci.nsIAccessibleRole.ROLE_CHROME_WINDOW)
+          VirtualCursorController.moveCursorToObject(acc);
+        break;
+      }
       default:
         break;
     }
   },
 
   /**
    * Check if accessible is a top-level content document (i.e. a child of a XUL
    * browser node).
--- a/accessible/src/jsat/VirtualCursorController.jsm
+++ b/accessible/src/jsat/VirtualCursorController.jsm
@@ -47,36 +47,46 @@ var VirtualCursorController = {
     switch (aEvent.keyCode) {
       case aEvent.DOM_VK_END:
         this.moveForward(document, true);
         break;
       case aEvent.DOM_VK_HOME:
         this.moveBackward(document, true);
         break;
       case aEvent.DOM_VK_RIGHT:
-        if (this._isEditableText(target) &&
-            target.selectionEnd != target.textLength)
-          // Don't move forward if caret is not at end of entry.
-          // XXX: Fix for rtl
-          return;
+        if (this._isEditableText(target)) {
+          if (target.selectionEnd != target.textLength)
+            // Don't move forward if caret is not at end of entry.
+            // XXX: Fix for rtl
+            return;
+          else
+            target.blur();
+        }
         this.moveForward(document, aEvent.shiftKey);
         break;
       case aEvent.DOM_VK_LEFT:
-        if (this._isEditableText(target) &&
-            target.selectionEnd != 0)
-          // Don't move backward if caret is not at start of entry.
-          // XXX: Fix for rtl
-          return;
+        if (this._isEditableText(target)) {
+          if (target.selectionEnd != 0)
+            // Don't move backward if caret is not at start of entry.
+            // XXX: Fix for rtl
+            return;
+          else
+            target.blur();
+        }
         this.moveBackward(document, aEvent.shiftKey);
         break;
       case aEvent.DOM_VK_UP:
-        if (this._isEditableText(target) == this.MULTI_LINE_EDITABLE &&
-            target.selectionEnd != 0)
-          // Don't blur content if caret is not at start of text area.
-          return;
+        if (this._isEditableText(target) == this.MULTI_LINE_EDITABLE) {
+          if (target.selectionEnd != 0)
+            // Don't blur content if caret is not at start of text area.
+            return;
+          else
+            target.blur();
+        }
+
         if (Services.appinfo.OS == 'Android')
           // Return focus to native Android browser chrome.
           Cc['@mozilla.org/android/bridge;1'].
             getService(Ci.nsIAndroidBridge).handleGeckoMessage(
               JSON.stringify({ gecko: { type: 'ToggleChrome:Focus' } }));
         break;
       case aEvent.DOM_VK_RETURN:
       case aEvent.DOM_VK_ENTER:
@@ -107,32 +117,32 @@ var VirtualCursorController = {
   moveForward: function moveForward(document, last) {
     let virtualCursor = this.getVirtualCursor(document);
     if (last) {
       virtualCursor.moveLast(this.SimpleTraversalRule);
     } else {
       try {
         virtualCursor.moveNext(this.SimpleTraversalRule);
       } catch (x) {
-        virtualCursor.position =
-          gAccRetrieval.getAccessibleFor(document.activeElement);
+        this.moveCursorToObject(
+          gAccRetrieval.getAccessibleFor(document.activeElement));
       }
     }
   },
 
   moveBackward: function moveBackward(document, first) {
     let virtualCursor = this.getVirtualCursor(document);
     if (first) {
       virtualCursor.moveFirst(this.SimpleTraversalRule);
     } else {
       try {
         virtualCursor.movePrevious(this.SimpleTraversalRule);
       } catch (x) {
-        virtualCursor.position =
-          gAccRetrieval.getAccessibleFor(document.activeElement);
+        this.moveCursorToObject(
+          gAccRetrieval.getAccessibleFor(document.activeElement));
       }
     }
   },
 
   activateCurrent: function activateCurrent(document) {
     let virtualCursor = this.getVirtualCursor(document);
     let acc = virtualCursor.position;
 
new file mode 100644
--- /dev/null
+++ b/accessible/src/mac/ApplicationAccessibleWrap.mm
@@ -0,0 +1,42 @@
+/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#import <Cocoa/Cocoa.h>
+
+#include "ApplicationAccessibleWrap.h"
+
+#include "nsAppShell.h"
+
+namespace mozilla {
+namespace a11y {
+
+static bool sA11yShouldBeEnabled = false;
+
+bool
+ShouldA11yBeEnabled()
+{
+  return sA11yShouldBeEnabled;
+}
+
+}
+}
+
+@interface GeckoNSApplication(a11y)
+-(void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute;
+@end
+
+@implementation GeckoNSApplication(a11y)
+
+-(void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute
+{
+  if ([attribute isEqualToString:@"AXEnhancedUserInterface"])
+    mozilla::a11y::sA11yShouldBeEnabled = ([value intValue] == 1);
+
+  return [super accessibilitySetValue:value forAttribute:attribute];
+}
+
+@end
+
--- a/accessible/src/mac/Makefile.in
+++ b/accessible/src/mac/Makefile.in
@@ -13,16 +13,17 @@ MODULE = accessibility
 LIBRARY_NAME = accessibility_toolkit_s
 EXPORT_LIBRARY = ..
 LIBXUL_LIBRARY = 1
 
   
   
 CMMSRCS = \
           AccessibleWrap.mm \
+          ApplicationAccessibleWrap.mm \
           DocAccessibleWrap.mm \
           nsAccessNodeWrap.mm \
           mozAccessible.mm \
           mozDocAccessible.mm \
           mozActionElements.mm \
           mozTextAccessible.mm \
           mozHTMLAccessible.mm \
           MacUtils.mm \
@@ -40,10 +41,12 @@ FORCE_STATIC_LIB = 1
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../base \
   -I$(srcdir)/../generic \
   -I$(srcdir)/../html \
   -I$(srcdir)/../xul \
+  -I$(topsrcdir)/widget/cocoa \
+  -I$(topsrcdir)/widget/xpwidgets \
   $(NULL)
 
--- a/accessible/src/xul/nsXULListboxAccessible.cpp
+++ b/accessible/src/xul/nsXULListboxAccessible.cpp
@@ -885,17 +885,17 @@ nsXULListitemAccessible::NativeState()
   }
 
   return states;
 }
 
 PRUint64
 nsXULListitemAccessible::NativeInteractiveState() const
 {
-  return NativelyUnavailable() || mParent->NativelyUnavailable() ?
+  return NativelyUnavailable() || (mParent && mParent->NativelyUnavailable()) ?
     states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
 }
 
 NS_IMETHODIMP nsXULListitemAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
 {
   if (aIndex == eAction_Click && mIsCheckbox) {
     // check or uncheck
     PRUint64 states = NativeState();
--- a/allmakefiles.sh
+++ b/allmakefiles.sh
@@ -54,19 +54,24 @@ if [ ! "$LIBXUL_SDK" ]; then
       build/stlport/stl/config/_android.h
     "
   fi
   add_makefiles "
     memory/mozalloc/Makefile
     mozglue/Makefile
     mozglue/build/Makefile
   "
+  if [ "$MOZ_JEMALLOC" ]; then
+    add_makefiles "
+      memory/jemalloc/Makefile
+    "
+  fi
   if [ "$MOZ_MEMORY" ]; then
     add_makefiles "
-      memory/jemalloc/Makefile
+      memory/mozjemalloc/Makefile
       memory/build/Makefile
     "
   fi
   if [ "$MOZ_WIDGET_TOOLKIT" = "android" ]; then
     add_makefiles "
       other-licenses/android/Makefile
       other-licenses/skia-npapi/Makefile
       mozglue/android/Makefile
--- a/b2g/Makefile.in
+++ b/b2g/Makefile.in
@@ -6,10 +6,14 @@ DEPTH      = ..
 topsrcdir  = @top_srcdir@
 srcdir     = @srcdir@
 VPATH      = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = chrome components locales app
 
+ifeq ($(OS_ARCH),WINNT)
+DIRS += $(DEPTH)/xulrunner/tools/redit
+endif
+
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/testing/testsuite-targets.mk
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -392,21 +392,17 @@ pref("browser.link.open_newwindow", 3);
 // 2: don't divert window.open with features
 pref("browser.link.open_newwindow.restriction", 0);
 
 // Enable browser frames (including OOP, except on Windows, where it doesn't
 // work), but make in-process browser frames the default.
 pref("dom.mozBrowserFramesEnabled", true);
 pref("dom.mozBrowserFramesWhitelist", "http://homescreen.gaiamobile.org,http://browser.gaiamobile.org");
 
-#ifdef XP_WIN
-pref("dom.ipc.tabs.disabled", true);
-#else
 pref("dom.ipc.tabs.disabled", false);
-#endif
 
 pref("dom.ipc.browser_frames.oop_by_default", false);
 
 // Temporary permission hack for WebSMS
 pref("dom.sms.enabled", true);
 pref("dom.sms.whitelist", "file://,http://homescreen.gaiamobile.org,http://sms.gaiamobile.org");
 
 // Temporary permission hack for WebMobileConnection
--- a/b2g/app/nsBrowserApp.cpp
+++ b/b2g/app/nsBrowserApp.cpp
@@ -13,17 +13,17 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 #endif
 
 #include <stdio.h>
 #include <stdarg.h>
 
 #include "nsCOMPtr.h"
-#include "nsILocalFile.h"
+#include "nsIFile.h"
 #include "nsStringGlue.h"
 
 #ifdef XP_WIN
 // we want a wmain entry point
 #include "nsWindowsWMain.cpp"
 #define snprintf _snprintf
 #define strcasecmp _stricmp
 #endif
@@ -97,17 +97,17 @@ static const nsDynamicFunctionLoad kXULF
 #endif
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
     { nsnull, nsnull }
 };
 
 static int do_main(int argc, char* argv[])
 {
-  nsCOMPtr<nsILocalFile> appini;
+  nsCOMPtr<nsIFile> appini;
   nsresult rv;
 
   // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
   // Note that -app must be the *first* argument.
   const char *appDataFile = getenv("XUL_APP_FILE");
   if (appDataFile && *appDataFile) {
     rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
     if (NS_FAILED(rv)) {
new file mode 100644
--- /dev/null
+++ b/b2g/chrome/content/forms.js
@@ -0,0 +1,237 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* 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/. */
+
+dump("###################################### forms.js loaded\n");
+
+"use strict";
+
+let Ci = Components.interfaces;
+let Cc = Components.classes;
+let Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+XPCOMUtils.defineLazyServiceGetter(Services, "fm",
+                                   "@mozilla.org/focus-manager;1",
+                                   "nsIFocusManager");
+
+let HTMLInputElement = Ci.nsIDOMHTMLInputElement;
+let HTMLTextAreaElement = Ci.nsIDOMHTMLTextAreaElement;
+let HTMLSelectElement = Ci.nsIDOMHTMLSelectElement;
+let HTMLOptGroupElement = Ci.nsIDOMHTMLOptGroupElement;
+let HTMLOptionElement = Ci.nsIDOMHTMLOptionElement;
+
+let FormAssistant = {
+  init: function fa_init() {
+    addEventListener("focus", this, true, false);
+    addEventListener("keypress", this, true, false);
+    addEventListener("mousedown", this, true, false);
+    addEventListener("resize", this, true, false);
+    addEventListener("click", this, true, false);
+    addEventListener("blur", this, true, false);
+    addMessageListener("Forms:Select:Choice", this);
+    addMessageListener("Forms:Input:Value", this);
+    Services.obs.addObserver(this, "ime-enabled-state-changed", false);
+    Services.obs.addObserver(this, "xpcom-shutdown", false);
+  },
+
+  isKeyboardOpened: false,
+  previousTarget : null,
+  handleEvent: function fa_handleEvent(evt) {
+    let previousTarget = this.previousTarget;
+    let target = evt.target;
+
+    switch (evt.type) {
+      case "focus":
+        this.previousTarget = Services.fm.focusedElement;
+        break;
+
+      case "blur":
+        if (!target)
+          return;
+        this.previousTarget = null;
+
+        if (target instanceof HTMLSelectElement ||
+            (target instanceof HTMLOptionElement && target.parentNode instanceof HTMLSelectElement)) {
+
+          sendAsyncMessage("Forms:Input", { "type": "blur" });
+        }
+        break;
+
+      case 'resize':
+        if (!this.isKeyboardOpened)
+          return;
+
+        Services.fm.focusedElement.scrollIntoView(false);
+        break;
+
+      case "mousedown":
+        if (evt.target != target || this.isKeyboardOpened)
+          return;
+
+        if (!(evt.target instanceof HTMLInputElement  ||
+              evt.target instanceof HTMLTextAreaElement))
+          return;
+
+        this.isKeyboardOpened = this.tryShowIme(evt.target);
+        break;
+
+      case "keypress":
+        if (evt.keyCode != evt.DOM_VK_ESCAPE || !this.isKeyboardOpened)
+          return;
+
+        sendAsyncMessage("Forms:Input", { "type": "blur" });
+        this.isKeyboardOpened = false;
+
+        evt.preventDefault();
+        evt.stopPropagation();
+        break;
+
+      case "click":
+        content.setTimeout(function showIMEForSelect() {
+          if (evt.target instanceof HTMLSelectElement) { 
+            sendAsyncMessage("Forms:Input", getJSON(evt.target));
+          } else if (evt.target instanceof HTMLOptionElement &&
+                     evt.target.parentNode instanceof HTMLSelectElement) {
+            sendAsyncMessage("Forms:Input", getJSON(evt.target.parentNode));
+          }
+        });
+        break;
+    }
+  },
+
+  receiveMessage: function fa_receiveMessage(msg) {
+    let target = Services.fm.focusedElement;
+    if (!target)
+      return;
+
+    let json = msg.json;
+    switch (msg.name) {
+      case "Forms:Input:Value":
+        target.value = json.value;
+        break;
+
+      case "Forms:Select:Choice":
+        let options = target.options;
+        if ("index" in json) {
+          options.item(json.index).selected = true;
+        } else if ("indexes" in json) {
+          for (let i = 0; i < options.length; i++) {
+            options.item(i).selected = (json.indexes.indexOf(i) != -1);
+          }
+        }
+        break;
+    }
+  },
+
+  observe: function fa_observe(subject, topic, data) {
+    switch (topic) {
+      case "ime-enabled-state-changed":
+        let isOpen = this.isKeyboardOpened;
+        let shouldOpen = parseInt(data);
+        if (shouldOpen && !isOpen) {
+          let target = Services.fm.focusedElement;
+
+          if (!target || !this.tryShowIme(target)) {
+            this.previousTarget = null;
+            return;
+          } else {
+            this.previousTarget = target;
+          }
+        } else if (!shouldOpen && isOpen) {
+          sendAsyncMessage("Forms:Input", { "type": "blur" });
+        }
+        this.isKeyboardOpened = shouldOpen;
+        break;
+
+      case "xpcom-shutdown":
+        Services.obs.removeObserver(this, "ime-enabled-state-changed", false);
+        Services.obs.removeObserver(this, "xpcom-shutdown");
+        removeMessageListener("Forms:Select:Choice", this);
+        break;
+    }
+  },
+
+  tryShowIme: function(element) {
+    // FIXME/bug 729623: work around apparent bug in the IME manager
+    // in gecko.
+    let readonly = element.getAttribute("readonly");
+    if (readonly)
+      return false;
+
+    sendAsyncMessage("Forms:Input", getJSON(element));
+    return true;
+  }
+};
+
+FormAssistant.init();
+
+
+function getJSON(element) {
+  let type = element.type;
+  // FIXME/bug 344616 is input type="number"
+  // Until then, let's return 'number' even if the platform returns 'text'
+  let attributeType = element.getAttribute("type") || "";
+  if (attributeType && attributeType.toLowerCase() === "number")
+    type = "number";
+
+  return {
+    "type": type.toLowerCase(),
+    "choices": getListForElement(element)
+  };
+}
+
+function getListForElement(element) {
+  if (!(element instanceof HTMLSelectElement))
+    return null;
+
+  let optionIndex = 0;
+  let result = {
+    "multiple": element.multiple,
+    "choices": []
+  };
+
+  // Build up a flat JSON array of the choices.
+  // In HTML, it's possible for select element choices to be under a
+  // group header (but not recursively). We distinguish between headers
+  // and entries using the boolean "list.group".
+  let children = element.children;
+  for (let i = 0; i < children.length; i++) {
+    let child = children[i];
+
+    if (child instanceof HTMLOptGroupElement) {
+      result.choices.push({
+        "group": true,
+        "text": child.label || child.firstChild.data,
+        "disabled": child.disabled
+      });
+
+      let subchildren = child.children;
+      for (let j = 0; j < subchildren.length; j++) {
+        let subchild = subchildren[j];
+        result.choices.push({
+          "group": false,
+          "inGroup": true,
+          "text": subchild.text,
+          "disabled": child.disabled || subchild.disabled,
+          "selected": subchild.selected,
+          "optionIndex": optionIndex++
+        });
+      }
+    } else if (child instanceof HTMLOptionElement) {
+      result.choices.push({
+        "group": false,
+        "inGroup": false,
+        "text": child.text,
+        "disabled": child.disabled,
+        "selected": child.selected,
+        "optionIndex": optionIndex++
+      });
+    }
+  }
+
+  return result;
+};
+
new file mode 100644
--- /dev/null
+++ b/b2g/chrome/content/settings.js
@@ -0,0 +1,93 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* 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/. */
+
+"use strict;"
+
+// Once Bug 731746 - Allow chrome JS object to implement nsIDOMEventTarget
+// is resolved this helper could be removed.
+var SettingsListener = {
+  _callbacks: {},
+
+  init: function sl_init() {
+    if ('mozSettings' in navigator && navigator.mozSettings) {
+      navigator.mozSettings.onsettingchange = this.onchange.bind(this);
+    }
+  },
+
+  onchange: function sl_onchange(evt) {
+    var callback = this._callbacks[evt.settingName];
+    if (callback) {
+      callback(evt.settingValue);
+    }
+  },
+
+  observe: function sl_observe(name, defaultValue, callback) {
+    var settings = window.navigator.mozSettings;
+    if (!settings) {
+      window.setTimeout(function() { callback(defaultValue); });
+      return;
+    }
+
+    if (!callback || typeof callback !== 'function') {
+      throw new Error('Callback is not a function');
+    }
+
+    var req = settings.getLock().get(name);
+    req.addEventListener('success', (function onsuccess() {
+      callback(typeof(req.result[name]) != 'undefined' ?
+        req.result[name] : defaultValue);
+    }));
+
+    this._callbacks[name] = callback;
+  }
+};
+
+SettingsListener.init();
+
+
+// =================== Languages ====================
+SettingsListener.observe('language.current', 'en-US', function(value) {
+  Services.prefs.setCharPref('intl.accept_languages', value);
+});
+
+
+// =================== RIL ====================
+(function RILSettingsToPrefs() {
+  ['ril.data.enabled', 'ril.data.roaming.enabled'].forEach(function(key) {
+    SettingsListener.observe(key, false, function(value) {
+      Services.prefs.setBoolPref(key, value);
+    });
+  });
+
+  let strPrefs = ['ril.data.apn', 'ril.data.user', 'ril.data.passwd',
+                  'ril.data.mmsc', 'ril.data.mmsproxy'];
+  strPrefs.forEach(function(key) {
+    SettingsListener.observe(key, false, function(value) {
+      Services.prefs.setCharPref(key, value);
+    });
+  });
+
+  ['ril.data.mmsport'].forEach(function(key) {
+    SettingsListener.observe(key, false, function(value) {
+      Services.prefs.setIntPref(key, value);
+    });
+  });
+})();
+
+
+// =================== Debugger ====================
+SettingsListener.observe('devtools.debugger.enabled', false, function(enabled) {
+  Services.prefs.setBoolPref('devtools.debugger.enabled', value);
+});
+
+SettingsListener.observe('devtools.debugger.log', false, function(value) {
+  Services.prefs.setBoolPref('devtools.debugger.log', value);
+});
+
+SettingsListener.observe('devtools.debugger.port', 6000, function(value) {
+  Services.prefs.setIntPref('devtools.debugger.port', value);
+});
+
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -118,21 +118,21 @@ var shell = {
     let domains = "";
     try {
       domains = Services.prefs.getCharPref('b2g.privileged.domains');
     } catch(e) {}
 
     addPermissions(domains.split(","));
 
     // Load webapi.js as a frame script
-    let frameScriptUrl = 'chrome://browser/content/webapi.js';
+    let webapiUrl = 'chrome://browser/content/webapi.js';
     try {
-      messageManager.loadFrameScript(frameScriptUrl, true);
+      messageManager.loadFrameScript(webapiUrl, true);
     } catch (e) {
-      dump('Error loading ' + frameScriptUrl + ' as a frame script: ' + e + '\n');
+      dump('Error loading ' + webapiUrl + ' as a frame script: ' + e + '\n');
     }
 
     CustomEventManager.init();
 
     WebappsHelper.init();
 
     let browser = this.contentBrowser;
     browser.homePage = homeURL;
@@ -401,27 +401,30 @@ var CustomEventManager = {
   init: function custevt_init() {
     window.addEventListener("ContentStart", (function(evt) {
       content.addEventListener("mozContentEvent", this, false, true);
     }).bind(this), false);
   },
 
   handleEvent: function custevt_handleEvent(evt) {
     let detail = evt.detail;
-    dump("XXX FIXME : Got a mozContentEvent: " + detail.type);
+    dump('XXX FIXME : Got a mozContentEvent: ' + detail.type);
 
     switch(detail.type) {
-      case "desktop-notification-click":
-      case "desktop-notification-close":
+      case 'desktop-notification-click':
+      case 'desktop-notification-close':
         AlertsHelper.handleEvent(detail);
         break;
-      case "webapps-install-granted":
-      case "webapps-install-denied":
+      case 'webapps-install-granted':
+      case 'webapps-install-denied':
         WebappsHelper.handleEvent(detail);
         break;
+      case 'select-choicechange':
+        FormsHelper.handleEvent(detail);
+        break;
     }
   }
 }
 
 var AlertsHelper = {
   _listeners: {},
   _count: 0,
 
@@ -523,62 +526,16 @@ function startDebugger() {
 }
 
 window.addEventListener('ContentStart', function(evt) {
   if (Services.prefs.getBoolPref('devtools.debugger.enabled')) {
     startDebugger();
   }
 });
 
-
-// Once Bug 731746 - Allow chrome JS object to implement nsIDOMEventTarget
-// is resolved this helper could be removed.
-var SettingsListener = {
-  _callbacks: {},
-
-  init: function sl_init() {
-    if ('mozSettings' in navigator && navigator.mozSettings)
-      navigator.mozSettings.onsettingchange = this.onchange.bind(this);
-  },
-
-  onchange: function sl_onchange(evt) {
-    var callback = this._callbacks[evt.settingName];
-    if (callback) {
-      callback(evt.settingValue);
-    }
-  },
-
-  observe: function sl_observe(name, defaultValue, callback) {
-    var settings = window.navigator.mozSettings;
-    if (!settings) {
-      window.setTimeout(function() { callback(defaultValue); });
-      return;
-    }
-
-    if (!callback || typeof callback !== 'function') {
-      throw new Error('Callback is not a function');
-    }
-
-    var req = settings.getLock().get(name);
-    req.addEventListener('success', (function onsuccess() {
-      callback(typeof(req.result[name]) != 'undefined' ?
-        req.result[name] : defaultValue);
-    }));
-
-    this._callbacks[name] = callback;
-  }
-};
-
-SettingsListener.init();
-
-SettingsListener.observe('language.current', 'en-US', function(value) {
-  Services.prefs.setCharPref('intl.accept_languages', value);
-});
-
-
 (function PowerManager() {
   // This will eventually be moved to content, so use content API as
   // much as possible here. TODO: Bug 738530
   let power = navigator.mozPower;
   let idleHandler = function idleHandler(subject, topic, time) {
     if (topic !== 'idle')
       return;
 
@@ -639,31 +596,8 @@ SettingsListener.observe('language.curre
   });
 
   window.addEventListener('unload', function removeIdleObjects() {
     Services.idle.removeIdleObserver(idleHandler, idleTimeout);
     power.removeWakeLockListener(wakeLockHandler);
   });
 })();
 
-
-(function RILSettingsToPrefs() {
-  ['ril.data.enabled', 'ril.data.roaming.enabled'].forEach(function(key) {
-    SettingsListener.observe(key, false, function(value) {
-      Services.prefs.setBoolPref(key, value);
-    });
-  });
-
-  let strPrefs = ['ril.data.apn', 'ril.data.user', 'ril.data.passwd',
-                  'ril.data.mmsc', 'ril.data.mmsproxy'];
-  strPrefs.forEach(function(key) {
-    SettingsListener.observe(key, false, function(value) {
-      Services.prefs.setCharPref(key, value);
-    });
-  });
-
-  ['ril.data.mmsport'].forEach(function(key) {
-    SettingsListener.observe(key, false, function(value) {
-      Services.prefs.setIntPref(key, value);
-    });
-  });
-})();
-
--- a/b2g/chrome/content/shell.xul
+++ b/b2g/chrome/content/shell.xul
@@ -9,17 +9,19 @@
         windowtype="navigator:browser"
 #ifdef ANDROID
         sizemode="fullscreen"
 #endif
         style="background: black; overflow: hidden; width:480px; height:800px"
         onload="shell.start();"
         onunload="shell.stop();">
 
+  <script type="application/javascript" src="chrome://browser/content/settings.js"/>
   <script type="application/javascript" src="chrome://browser/content/shell.js"/>
+ 
 #ifndef ANDROID
   <!-- this script handles the screen argument for desktop builds -->
   <script type="application/javascript" src="chrome://browser/content/screen.js"/>
 #endif
   <browser id="homescreen"
            type="content-primary"
            flex="1"
            style="overflow: hidden;"
--- a/b2g/chrome/content/webapi.js
+++ b/b2g/chrome/content/webapi.js
@@ -1,105 +1,27 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 /* 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/. */
 
 'use strict';
 
-dump('======================= webapi+apps.js ======================= \n');
+dump('======================= webapi.js ======================= \n');
 
 let { classes: Cc, interfaces: Ci, utils: Cu }  = Components;
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/Geometry.jsm');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'fm',
                                    '@mozilla.org/focus-manager;1',
                                    'nsIFocusManager');
 
-// MozKeyboard
-(function VirtualKeyboardManager() {
-  let activeElement = null;
-  let isKeyboardOpened = false;
-  
-  function fireEvent(type, details) {
-    let event = content.document.createEvent('CustomEvent');
-    event.initCustomEvent(type, true, true, details ? details : {});
-    content.dispatchEvent(event);
-  }
-
-  function maybeShowIme(targetElement) {
-    // FIXME/bug 729623: work around apparent bug in the IME manager
-    // in gecko.
-    let readonly = targetElement.getAttribute('readonly');
-    if (readonly)
-      return false;
-
-    let type = targetElement.type;
-    // FIXME/bug 344616 is input type='number'
-    // Until then, let's return 'number' even if the platform returns 'text'
-    let attributeType = targetElement.getAttribute('type');
-    if (attributeType && attributeType.toLowerCase() === 'number')
-      type = 'number';
-
-    fireEvent('showime', { type: type });
-    return true;
-  }
-
-  let constructor = {
-    handleEvent: function vkm_handleEvent(evt) {
-      switch (evt.type) {
-        case 'resize':
-          if (!isKeyboardOpened)
-            return;
-
-          activeElement.scrollIntoView(false);
-          break;
-        case 'keypress':
-          if (evt.keyCode != evt.DOM_VK_ESCAPE || !isKeyboardOpened)
-            return;
-
-          fireEvent('hideime');
-          isKeyboardOpened = false;
-
-          evt.preventDefault();
-          evt.stopPropagation();
-          break;
-
-        case 'mousedown':
-          if (evt.target != activeElement || isKeyboardOpened)
-            return;
-
-          isKeyboardOpened = maybeShowIme(activeElement);
-          break;
-      }
-    },
-    observe: function vkm_observe(subject, topic, data) {
-      let shouldOpen = parseInt(data);
-      if (shouldOpen && !isKeyboardOpened) {
-        activeElement = Services.fm.focusedElement;
-        if (!activeElement || !maybeShowIme(activeElement)) {
-          activeElement = null;
-          return;
-        }
-      } else if (!shouldOpen && isKeyboardOpened) {
-        fireEvent('hideime');
-      }
-      isKeyboardOpened = shouldOpen;
-    }
-  };
-
-  Services.obs.addObserver(constructor, 'ime-enabled-state-changed', false);
-  ['keypress', 'mousedown', 'resize'].forEach(function vkm_events(type) {
-    addEventListener(type, constructor, true);
-  });
-})();
-
 const ContentPanning = {
   init: function cp_init() {
     ['mousedown', 'mouseup', 'mousemove'].forEach(function(type) {
       addEventListener(type, ContentPanning, true);
     });
   },
 
   handleEvent: function cp_handleEvent(evt) {
@@ -426,8 +348,9 @@ const KineticPanning = {
       }
 
       content.mozRequestAnimationFrame(callback);
     }).bind(this);
 
     content.mozRequestAnimationFrame(callback);
   }
 };
+
--- a/b2g/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -4,16 +4,18 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
 chrome.jar:
 % content branding %content/branding/
 % content browser %content/
 
   content/dbg-browser-actors.js         (content/dbg-browser-actors.js)
+  content/forms.js                      (content/forms.js)
+  content/settings.js                   (content/settings.js)
 * content/shell.xul                     (content/shell.xul)
 * content/shell.js                      (content/shell.js)
 #ifndef ANDROID
   content/screen.js                     (content/screen.js)
 #endif
   content/webapi.js                     (content/webapi.js)
   content/content.css                   (content/content.css)
   content/touchcontrols.css             (content/touchcontrols.css)
--- a/b2g/components/MozKeyboard.js
+++ b/b2g/components/MozKeyboard.js
@@ -1,52 +1,118 @@
 /* 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/. */
 
-'use strict';
+"use strict";
 
+const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
+const messageManager = Cc["@mozilla.org/globalmessagemanager;1"]
+                         .getService(Ci.nsIChromeFrameMessageManager);
+
+
 // -----------------------------------------------------------------------
 // MozKeyboard
 // -----------------------------------------------------------------------
 
 function MozKeyboard() { } 
 
 MozKeyboard.prototype = {
   classID: Components.ID("{397a7fdf-2254-47be-b74e-76625a1a66d5}"),
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIB2GKeyboard, Ci.nsIDOMGlobalPropertyInitializer, Ci.nsIObserver]),
-  classInfo: XPCOMUtils.generateCI({classID: Components.ID("{397a7fdf-2254-47be-b74e-76625a1a66d5}"),
-                                    contractID: "@mozilla.org/b2g-keyboard;1",
-                                    interfaces: [Ci.nsIB2GKeyboard],
-                                    flags: Ci.nsIClassInfo.DOM_OBJECT,
-                                    classDescription: "B2G Virtual Keyboard"}),
+
+  QueryInterface: XPCOMUtils.generateQI([
+    Ci.nsIB2GKeyboard, Ci.nsIDOMGlobalPropertyInitializer, Ci.nsIObserver
+  ]),
+
+  classInfo: XPCOMUtils.generateCI({
+    "classID": Components.ID("{397a7fdf-2254-47be-b74e-76625a1a66d5}"),
+    "contractID": "@mozilla.org/b2g-keyboard;1",
+    "interfaces": [Ci.nsIB2GKeyboard],
+    "flags": Ci.nsIClassInfo.DOM_OBJECT,
+    "classDescription": "B2G Virtual Keyboard"
+  }),
 
-  init: function(aWindow) {
-    this._utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+  init: function mozKeyboardInit(win) {
+    messageManager.loadFrameScript("chrome://browser/content/forms.js", true);
+    messageManager.addMessageListener("Forms:Input", this);
+
     Services.obs.addObserver(this, "inner-window-destroyed", false);
+
+    this._window = win;
+    this._utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
+                     .getInterface(Ci.nsIDOMWindowUtils);
     this.innerWindowID = this._utils.currentInnerWindowID;
+
+    this._focusHandler = null;
   },
 
-  observe: function(aSubject, aTopic, aData) {
-    if (aTopic == "inner-window-destroyed") {
-      let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
-      if (wId == this.innerWindowID) {
-        Services.obs.removeObserver(this, "inner-window-destroyed");
-        this._utils = null;
-      }
-    }
+  uninit: function mozKeyboardUninit() {
+    Services.obs.removeObserver(this, "inner-window-destroyed");
+    messageManager.removeMessageListener("Forms:Input", this);
+    this._window = null;
+    this._utils = null;
+    this._focusHandler = null;
   },
 
   sendKey: function mozKeyboardSendKey(keyCode, charCode) {
     charCode = (charCode == undefined) ? keyCode : charCode;
-    ['keydown', 'keypress', 'keyup'].forEach((function sendKey(type) {
+    ["keydown", "keypress", "keyup"].forEach((function sendKey(type) {
       this._utils.sendKeyEvent(type, keyCode, charCode, null);
     }).bind(this));
+  },
+
+  setSelectedOption: function mozKeyboardSetSelectedOption(index) {
+    messageManager.sendAsyncMessage("Forms:Select:Choice", {
+      "index": index
+    });
+  },
+
+  setValue: function mozKeyboardSetValue(value) {
+    messageManager.sendAsyncMessage("Forms:Input:Value", {
+      "value": value
+    });
+  },
+
+  setSelectedOptions: function mozKeyboardSetSelectedOptions(indexes) {
+    messageManager.sendAsyncMessage("Forms:Select:Choice", {
+      "indexes": indexes || []
+    });
+  },
+
+  set onfocuschange(val) {
+    this._focusHandler = val;
+  },
+
+  get onfocuschange() {
+    return this._focusHandler;
+  },
+
+  receiveMessage: function mozKeyboardReceiveMessage(msg) {
+    let handler = this._focusHandler;
+    if (!handler || !(handler instanceof Ci.nsIDOMEventListener))
+      return;
+
+    let detail = {
+      "detail": msg.json
+    };
+
+    let evt = new this._window.CustomEvent("focuschanged", detail);
+    handler.handleEvent(evt);
+  },
+
+  observe: function mozKeyboardObserve(subject, topic, data) {
+    if (topic == "inner-window-destroyed") {
+      let wId = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
+      if (wId == this.innerWindowID) {
+        this.uninit();
+      }
+    }
   }
 };
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([MozKeyboard]);
+
--- a/b2g/components/b2g.idl
+++ b/b2g/components/b2g.idl
@@ -2,17 +2,40 @@
  * 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 "domstubs.idl"
 
 [scriptable, uuid(3615a616-571d-4194-bf54-ccf546067b14)]
 interface nsIB2GCameraContent : nsISupports
 {
-    /* temporary solution, waiting for getUserMedia */
-    DOMString getCameraURI([optional] in jsval options);
+  /* temporary solution, waiting for getUserMedia */
+  DOMString getCameraURI([optional] in jsval options);
 };
 
-[scriptable, uuid(80ad05f8-e5f6-4a36-b25d-5d5a969b365d)]
+[scriptable, uuid(53990d7a-ab2a-11e1-8543-7767e4cbcbff)]
 interface nsIB2GKeyboard : nsISupports
 {
-    void sendKey(in long aKeyCode, in long aCharCode);
+  void sendKey(in long keyCode, in long charCode);
+
+  // Select the <select> option specified by index.
+  // If this method is called on a <select> that support multiple
+  // selection, then the option specified by index will be added to
+  // the selection.
+  // If this method is called for a select that does not support multiple
+  // selection the previous element will be unselected.
+  void setSelectedOption(in jsval index);
+
+  // Select the <select> options specified by indexes. All other options
+  // will be deselected.
+  // If this method is called for a <select> that does not support multiple
+  // selection, then the last index specified in indexes will be selected.
+  void setSelectedOptions(in jsval indexes);
+
+  // Set the value on the currently focused element. This has to be used
+  // for special situations where the value had to be chosen amongst a
+  // list (type=month) or a widget (type=date, time, etc.).
+  // If the value passed in parameter isn't valid (in the term of HTML5
+  // Forms Validation), the value will simply be ignored by the element. 
+  void setValue(in jsval value);
+
+  attribute nsIDOMEventListener onfocuschange;
 };
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -17,17 +17,17 @@
 #ifdef XP_MACOSX
 #include "MacQuirks.h"
 #endif
 
 #include <stdio.h>
 #include <stdarg.h>
 
 #include "nsCOMPtr.h"
-#include "nsILocalFile.h"
+#include "nsIFile.h"
 #include "nsStringGlue.h"
 
 #ifdef XP_WIN
 // we want a wmain entry point
 #include "nsWindowsWMain.cpp"
 #define snprintf _snprintf
 #define strcasecmp _stricmp
 #endif
@@ -101,17 +101,17 @@ static const nsDynamicFunctionLoad kXULF
 #endif
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
     { nsnull, nsnull }
 };
 
 static int do_main(int argc, char* argv[])
 {
-  nsCOMPtr<nsILocalFile> appini;
+  nsCOMPtr<nsIFile> appini;
   nsresult rv;
 
   // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
   // Note that -app must be the *first* argument.
   const char *appDataFile = getenv("XUL_APP_FILE");
   if (appDataFile && *appDataFile) {
     rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
     if (NS_FAILED(rv)) {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3472,20 +3472,17 @@ function OpenBrowserWindow()
   {
     win = window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no", defaultArgs);
   }
 
   return win;
 }
 
 var gCustomizeSheet = false;
-// Returns a reference to the window in which the toolbar
-// customization document is loaded.
-function BrowserCustomizeToolbar()
-{
+function BrowserCustomizeToolbar() {
   // Disable the toolbar context menu items
   var menubar = document.getElementById("main-menubar");
   for (var i = 0; i < menubar.childNodes.length; ++i)
     menubar.childNodes[i].setAttribute("disabled", true);
 
   var cmd = document.getElementById("cmd_CustomizeToolbars");
   cmd.setAttribute("disabled", "true");
 
@@ -3500,51 +3497,48 @@ function BrowserCustomizeToolbar()
   DownloadsButton.customizeStart();
 
   TabsInTitlebar.allowedBy("customizing-toolbars", false);
 
   var customizeURL = "chrome://global/content/customizeToolbar.xul";
   gCustomizeSheet = getBoolPref("toolbar.customization.usesheet", false);
 
   if (gCustomizeSheet) {
-    var sheetFrame = document.getElementById("customizeToolbarSheetIFrame");
-    var panel = document.getElementById("customizeToolbarSheetPopup");
-    sheetFrame.hidden = false;
+    let sheetFrame = document.createElement("iframe");
+    let panel = document.getElementById("customizeToolbarSheetPopup");
+    sheetFrame.id = "customizeToolbarSheetIFrame";
     sheetFrame.toolbox = gNavToolbox;
     sheetFrame.panel = panel;
-
-    // The document might not have been loaded yet, if this is the first time.
-    // If it is already loaded, reload it so that the onload initialization code
-    // re-runs.
-    if (sheetFrame.getAttribute("src") == customizeURL)
-      sheetFrame.contentWindow.location.reload()
-    else
-      sheetFrame.setAttribute("src", customizeURL);
+    sheetFrame.setAttribute("style", panel.getAttribute("sheetstyle"));
+    panel.appendChild(sheetFrame);
 
     // Open the panel, but make it invisible until the iframe has loaded so
     // that the user doesn't see a white flash.
     panel.style.visibility = "hidden";
     gNavToolbox.addEventListener("beforecustomization", function onBeforeCustomization() {
       gNavToolbox.removeEventListener("beforecustomization", onBeforeCustomization, false);
       panel.style.removeProperty("visibility");
     }, false);
+
+    sheetFrame.setAttribute("src", customizeURL);
+
     panel.openPopup(gNavToolbox, "after_start", 0, 0);
-    return sheetFrame.contentWindow;
   } else {
-    return window.openDialog(customizeURL,
-                             "CustomizeToolbar",
-                             "chrome,titlebar,toolbar,location,resizable,dependent",
-                             gNavToolbox);
+    window.openDialog(customizeURL,
+                      "CustomizeToolbar",
+                      "chrome,titlebar,toolbar,location,resizable,dependent",
+                      gNavToolbox);
   }
 }
 
 function BrowserToolboxCustomizeDone(aToolboxChanged) {
   if (gCustomizeSheet) {
-    document.getElementById("customizeToolbarSheetIFrame").hidden = true;
     document.getElementById("customizeToolbarSheetPopup").hidePopup();
+    let iframe = document.getElementById("customizeToolbarSheetIFrame");
+    iframe.parentNode.removeChild(iframe);
   }
 
   // Update global UI elements that may have been added or removed
   if (aToolboxChanged) {
     gURLBar = document.getElementById("urlbar");
 
     gProxyFavIcon = document.getElementById("page-proxy-favicon");
     gHomeButton.updateTooltip();
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -339,21 +339,18 @@
                        style="visibility:hidden"/>
       </stack>
     </panel>
 
     <!-- Bookmarks and history tooltip -->
     <tooltip id="bhTooltip"/>
 
     <panel id="customizeToolbarSheetPopup"
-           noautohide="true">
-      <iframe id="customizeToolbarSheetIFrame"
-              style="&dialog.dimensions;"
-              hidden="true"/>
-    </panel>
+           noautohide="true"
+           sheetstyle="&dialog.dimensions;"/>
 
     <tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/>
 
     <tooltip id="back-button-tooltip">
       <label class="tooltip-label" value="&backButton.tooltip;"/>
 #ifdef XP_MACOSX
       <label class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/>
 #else
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -148,16 +148,17 @@ endif
                  browser_bug655584.js \
                  browser_bug664672.js \
                  browser_bug710878.js \
                  browser_bug719271.js \
                  browser_bug735471.js \
                  browser_bug743421.js \
                  browser_bug749738.js \
                  browser_canonizeURL.js \
+                 browser_customize.js \
                  browser_findbarClose.js \
                  browser_homeDrop.js \
                  browser_keywordBookmarklets.js \
                  browser_contextSearchTabPosition.js \
                  browser_ctrlTab.js \
                  browser_customize_popupNotification.js \
                  browser_disablechrome.js \
                  browser_discovery.js \
@@ -255,17 +256,16 @@ endif
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
 else
 _BROWSER_FILES += \
 		browser_bug565667.js \
-		browser_customize.js \
 		$(NULL)
 
 # TODO: Activate after carbon test plugin lands, bug 628651
 # 		browser_maconly_carbon_mismatch_plugin.js \
 
 endif
 
 libs:: $(_TEST_FILES)
--- a/browser/base/content/test/browser_bug422590.js
+++ b/browser/base/content/test/browser_bug422590.js
@@ -5,68 +5,46 @@ function test() {
 }
 
 function testChromeless() {
   // test a chromeless window
   var newWin = openDialog(getBrowserURL(), "_blank",
                           "chrome,dialog=no,toolbar=no", "about:blank");
   ok(newWin, "got new window");
 
-  function runWindowTest() {
+  whenDelayedStartupFinished(newWin, function () {
     // Check that the search bar is hidden
     var searchBar = newWin.BrowserSearch.searchBar;
     ok(searchBar, "got search bar");
 
     var searchBarBO = searchBar.boxObject;
     is(searchBarBO.width, 0, "search bar hidden");
     is(searchBarBO.height, 0, "search bar hidden");
 
-    function finalize() {
-      newWin.removeEventListener("load", runWindowTest, false);
+    testCustomize(newWin, function () {
       newWin.close();
       finish();
-    }
-    testCustomize(newWin, finalize);
-  }
-
-  newWin.addEventListener("load", runWindowTest, false);
+    });
+  });
 }
 
 function testCustomize(aWindow, aCallback) {
   var fileMenu = aWindow.document.getElementById("file-menu");
   ok(fileMenu, "got file menu");
   is(fileMenu.disabled, false, "file menu initially enabled");
 
-  // Launch toolbar customization
-  // ctEl is either iframe that contains the customize sheet, or the dialog
-  var ctEl = aWindow.BrowserCustomizeToolbar();
-
-  is(fileMenu.disabled, true,
-     "file menu is disabled during toolbar customization");
-
-  aWindow.gNavToolbox.addEventListener("beforecustomization", function () {
-    aWindow.gNavToolbox.removeEventListener("beforecustomization", arguments.callee, false);
-    executeSoon(ctInit);
-  }, false);
-
-  function ctInit() {
-    // Close toolbar customization
-    closeToolbarCustomization(aWindow, ctEl);
-
+  openToolbarCustomizationUI(function () {
     // Can't use the property, since the binding may have since been removed
     // if the element is hidden (see bug 422590)
+    is(fileMenu.getAttribute("disabled"), "true",
+       "file menu is disabled during toolbar customization");
+
+    closeToolbarCustomizationUI(onClose, aWindow);
+  }, aWindow);
+
+  function onClose() {
     is(fileMenu.getAttribute("disabled"), "false",
        "file menu is enabled after toolbar customization");
 
     if (aCallback)
       aCallback();
   }
 }
-
-function closeToolbarCustomization(aWindow, aCTWindow) {
-  // Force the cleanup code to be run now instead of onunload.
-  // This also hides the sheet on Mac.
-  aCTWindow.finishToolbarCustomization();
-
-  // On windows and linux, need to explicitly close the window.
-  if (!gCustomizeSheet)
-    aCTWindow.close();
-}
--- a/browser/base/content/test/browser_bug495058.js
+++ b/browser/base/content/test/browser_bug495058.js
@@ -22,26 +22,22 @@ function next() {
       detach();
     }, true);
     browser.loadURI(uri);
   }
 
   function detach() {
     var win = gBrowser.replaceTabWithWindow(tab);
 
-    Services.obs.addObserver(function (subject, topic, data) {
-      if (subject != win)
-        return;
-      Services.obs.removeObserver(arguments.callee, topic);
-
+    whenDelayedStartupFinished(win, function () {
       is(win.gBrowser.currentURI.spec, uri, uri + ": uri loaded in detached tab");
       is(win.document.activeElement, win.gBrowser.selectedBrowser, uri + ": browser is focused");
       is(win.gURLBar.value, "", uri + ": urlbar is empty");
       ok(win.gURLBar.placeholder, uri + ": placeholder text is present");
 
       win.close();
       if (uris.length)
         next();
       else
         executeSoon(finish);
-    }, "browser-delayed-startup-finished", false);
+    });
   }
 }
--- a/browser/base/content/test/browser_bug599325.js
+++ b/browser/base/content/test/browser_bug599325.js
@@ -1,43 +1,21 @@
 function test() {
   waitForExplicitFinish();
-  testCustomize(window, finish);
-}
 
-function testCustomize(aWindow, aCallback) {
-  var addonBar = aWindow.document.getElementById("addon-bar");
+  let addonBar = document.getElementById("addon-bar");
   ok(addonBar, "got addon bar");
   ok(!isElementVisible(addonBar), "addon bar initially hidden");
 
-  // Launch toolbar customization
-  // ctEl is either iframe that contains the customize sheet, or the dialog
-  var ctEl = aWindow.BrowserCustomizeToolbar();
-
-  aWindow.gNavToolbox.addEventListener("beforecustomization", function () {
-    aWindow.gNavToolbox.removeEventListener("beforecustomization", arguments.callee, false);
-    executeSoon(ctInit);
-  }, false);
-
-  function ctInit() {
+  openToolbarCustomizationUI(function () {
     ok(isElementVisible(addonBar),
        "add-on bar is visible during toolbar customization");
 
-    // Close toolbar customization
-    closeToolbarCustomization(aWindow, ctEl);
+    closeToolbarCustomizationUI(onClose);
+  });
 
+  function onClose() {
     ok(!isElementVisible(addonBar),
        "addon bar is hidden after toolbar customization");
 
-    if (aCallback)
-      aCallback();
+    finish();
   }
 }
-
-function closeToolbarCustomization(aWindow, aCTWindow) {
-  // Force the cleanup code to be run now instead of onunload.
-  // This also hides the sheet on Mac.
-  aCTWindow.finishToolbarCustomization();
-
-  // On windows and linux, need to explicitly close the window.
-  if (!gCustomizeSheet)
-    aCTWindow.close();
-}
--- a/browser/base/content/test/browser_contentAreaClick.js
+++ b/browser/base/content/test/browser_contentAreaClick.js
@@ -178,33 +178,28 @@ let gInvokedMethods = [];
 
 // The test currently running.
 let gCurrentTest = null;
 
 function test() {
   waitForExplicitFinish();
 
   gTestWin = openDialog(location, "", "chrome,all,dialog=no", "about:blank");
-  Services.obs.addObserver(function(aSubject, aTopic, aData) {
-    if (aSubject != gTestWin)
-      return;
-
-    Services.obs.removeObserver(arguments.callee, "browser-delayed-startup-finished");
-
+  whenDelayedStartupFinished(gTestWin, function () {
     info("Browser window opened");
     waitForFocus(function() {
       info("Browser window focused");
       waitForFocus(function() {
         info("Setting up browser...");
         setupTestBrowserWindow();
         info("Running tests...");
         executeSoon(runNextTest);
       }, gTestWin.content, true);
     }, gTestWin);
-  }, "browser-delayed-startup-finished", false);
+  });
 }
 
 // Click handler used to steal click events.
 let gClickHandler = {
   handleEvent: function (event) {
     let linkId = event.target.id || event.target.localName;
     is(event.type, "click",
        gCurrentTest.desc + ":Handler received a click event on " + linkId);
--- a/browser/base/content/test/browser_customize.js
+++ b/browser/base/content/test/browser_customize.js
@@ -1,59 +1,24 @@
-function test()
-{
+function test() {
   waitForExplicitFinish();
-  var frame = document.getElementById("customizeToolbarSheetIFrame");
-  frame.addEventListener("load", testCustomizeFrameLoadedPre, true);
 
-  document.getElementById("cmd_CustomizeToolbars").doCommand();
-}
-
-function testCustomizeFrameLoadedPre(){
-  // This load listener can be called before
-  // customizeToolbarSheet.xul's, which would cause the test
-  // to fail. Use executeSoon to delay running the test until
-  // event dispatch is over (all load event listeners have run).
-  executeSoon(testCustomizeFrameLoaded);
+  openToolbarCustomizationUI(customizationWindowLoaded);
 }
 
-function testCustomizeFrameLoaded()
-{
-  var panel = document.getElementById("customizeToolbarSheetPopup");
-  panel.addEventListener("popuphidden", testCustomizePopupHidden, false);
-
-  var frame = document.getElementById("customizeToolbarSheetIFrame");
-  frame.removeEventListener("load", testCustomizeFrameLoadedPre, true);
+function customizationWindowLoaded(win) {
+  let x = win.screenX;
+  let iconModeList = win.document.getElementById("modelist");
 
-  if (navigator.platform.indexOf("Mac") == -1) {
-    var menu = document.getElementById("bookmarksMenuPopup");
-    ok("result" in menu, "menu has binding");
-  }
-
-  var framedoc = document.getElementById("customizeToolbarSheetIFrame").contentDocument;
+  iconModeList.addEventListener("popupshown", function popupshown() {
+    iconModeList.removeEventListener("popupshown", popupshown, false);
 
-  var panelX = panel.boxObject.screenX;
-  var iconModeList = framedoc.getElementById("modelist");
-  iconModeList.addEventListener("popupshown", function (e) {
-    iconModeList.removeEventListener("popupshown", arguments.callee, false);
-    SimpleTest.executeSoon(function () {
-      is(panel.boxObject.screenX, panelX, "toolbar customization panel shouldn't move when the iconmode menulist is opened");
+    executeSoon(function () {
+      is(win.screenX, x,
+         "toolbar customization window shouldn't move when the iconmode menulist is opened");
       iconModeList.open = false;
     
-      var b = framedoc.getElementById("donebutton");
-      b.focus();
-      b.doCommand();
+      closeToolbarCustomizationUI(finish);
     });
   }, false);
+
   iconModeList.open = true;
 }
-  
-function testCustomizePopupHidden(e)
-{
-  var panel = document.getElementById("customizeToolbarSheetPopup");
-  if (e.target != panel)
-    return;
-
-  panel.removeEventListener("popuphidden", testCustomizePopupHidden, false);
-  is(document.activeElement, document.documentElement, "focus after customize done");
-
-  finish();
-}
--- a/browser/base/content/test/head.js
+++ b/browser/base/content/test/head.js
@@ -1,8 +1,72 @@
+function whenDelayedStartupFinished(aWindow, aCallback) {
+  Services.obs.addObserver(function observer(aSubject, aTopic) {
+    if (aWindow == aSubject) {
+      Services.obs.removeObserver(observer, aTopic);
+      executeSoon(aCallback);
+    }
+  }, "browser-delayed-startup-finished", false);
+}
+
+function findChromeWindowByURI(aURI) {
+  let windows = Services.wm.getEnumerator(null);
+  while (windows.hasMoreElements()) {
+    let win = windows.getNext();
+    if (win.location.href == aURI)
+      return win;
+  }
+  return null;
+}
+
 function updateTabContextMenu(tab) {
   let menu = document.getElementById("tabContextMenu");
   if (!tab)
     tab = gBrowser.selectedTab;
   menu.openPopup(tab, "end_after", 0, 0, true, false, {target: tab});
   is(TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab");
   menu.hidePopup();
 }
+
+function findToolbarCustomizationWindow(aBrowserWin) {
+  if (!aBrowserWin)
+    aBrowserWin = window;
+
+  let iframe = aBrowserWin.document.getElementById("customizeToolbarSheetIFrame");
+  let win = iframe && iframe.contentWindow;
+  if (win)
+    return win;
+
+  win = findChromeWindowByURI("chrome://global/content/customizeToolbar.xul");
+  if (win && win.opener == aBrowserWin)
+    return win;
+
+  throw Error("Failed to find the customization window");
+}
+
+function openToolbarCustomizationUI(aCallback, aBrowserWin) {
+  if (!aBrowserWin)
+    aBrowserWin = window;
+
+  aBrowserWin.document.getElementById("cmd_CustomizeToolbars").doCommand();
+
+  aBrowserWin.gNavToolbox.addEventListener("beforecustomization", function UI_loaded() {
+    aBrowserWin.gNavToolbox.removeEventListener("beforecustomization", UI_loaded);
+
+    let win = findToolbarCustomizationWindow(aBrowserWin);
+    waitForFocus(function () {
+      aCallback(win);
+    }, win);
+  });
+}
+
+function closeToolbarCustomizationUI(aCallback, aBrowserWin) {
+  let win = findToolbarCustomizationWindow(aBrowserWin);
+
+  win.addEventListener("unload", function unloaded() {
+    win.removeEventListener("unload", unloaded);
+    executeSoon(aCallback);
+  });
+
+  let button = win.document.getElementById("donebutton");
+  button.focus();
+  button.doCommand();
+}
--- a/browser/components/dirprovider/DirectoryProvider.cpp
+++ b/browser/components/dirprovider/DirectoryProvider.cpp
@@ -49,17 +49,17 @@ DirectoryProvider::GetFile(const char *a
   if (!strcmp(aKey, NS_APP_BOOKMARKS_50_FILE)) {
     leafName = "bookmarks.html";
 
     nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
     if (prefs) {
       nsCString path;
       rv = prefs->GetCharPref("browser.bookmarks.file", getter_Copies(path));
       if (NS_SUCCEEDED(rv)) {
-        NS_NewNativeLocalFile(path, true, (nsILocalFile**)(nsIFile**) getter_AddRefs(file));
+        NS_NewNativeLocalFile(path, true, getter_AddRefs(file));
       }
     }
   }
   else if (!strcmp(aKey, NS_APP_EXISTING_PREF_OVERRIDE)) {
     rv = NS_GetSpecialDirectory(NS_APP_DEFAULTS_50_DIR,
                                 getter_AddRefs(file));
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/browser/components/sessionstore/content/aboutSessionRestore.xhtml
+++ b/browser/components/sessionstore/content/aboutSessionRestore.xhtml
@@ -66,28 +66,28 @@
             <treechildren flex="1"/>
           </tree>
         </div>
       </div>
 
       <!-- Buttons -->
       <hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="buttons">
 #ifdef XP_UNIX
-        <button id="errorCancel" label="&restorepage.cancelButton;"
-                accesskey="&restorepage.cancel.access;"
+        <button id="errorCancel" label="&restorepage.closeButton;"
+                accesskey="&restorepage.close.access;"
                 oncommand="startNewSession();"/>
         <button id="errorTryAgain" label="&restorepage.tryagainButton;"
                 accesskey="&restorepage.restore.access;"
                 oncommand="restoreSession();"/>
 #else
         <button id="errorTryAgain" label="&restorepage.tryagainButton;"
                 accesskey="&restorepage.restore.access;"
                 oncommand="restoreSession();"/>
-        <button id="errorCancel" label="&restorepage.cancelButton;"
-                accesskey="&restorepage.cancel.access;"
+        <button id="errorCancel" label="&restorepage.closeButton;"
+                accesskey="&restorepage.close.access;"
                 oncommand="startNewSession();"/>
 #endif
       </hbox>
       <!-- holds the session data for when the tab is closed -->
       <input type="text" id="sessionData" style="display: none;"/>
     </div>
 
   </body>
--- a/browser/components/shell/public/nsIShellService.idl
+++ b/browser/components/shell/public/nsIShellService.idl
@@ -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/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMElement;
-interface nsILocalFile;
+interface nsIFile;
 
 [scriptable, uuid(bb477da4-dddf-4106-a562-f06c85c7f9a8)]
 interface nsIShellService : nsISupports
 {
   /**
    * Determines whether or not Firefox is the "Default Browser."
    * This is simply whether or not Firefox is registered to handle 
    * http links. 
@@ -94,15 +94,15 @@ interface nsIShellService : nsISupports
 
   /**
    * Opens an application with a specific URI to load.
    * @param   application
    *          The application file (or bundle directory, on OS X)
    * @param   uri
    *          The uri to be loaded by the application
    */
-  void openApplicationWithURI(in nsILocalFile aApplication, in ACString aURI);
+  void openApplicationWithURI(in nsIFile aApplication, in ACString aURI);
 
   /**
    * The default system handler for web feeds
    */
-  readonly attribute nsILocalFile defaultFeedReader;
+  readonly attribute nsIFile defaultFeedReader;
 };
--- a/browser/components/shell/src/nsGNOMEShellService.cpp
+++ b/browser/components/shell/src/nsGNOMEShellService.cpp
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Util.h"
 
 #include "nsCOMPtr.h"
 #include "nsGNOMEShellService.h"
 #include "nsShellService.h"
 #include "nsIServiceManager.h"
-#include "nsILocalFile.h"
+#include "nsIFile.h"
 #include "nsIProperties.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsIPrefService.h"
 #include "prenv.h"
 #include "nsStringAPI.h"
 #include "nsIGConfService.h"
 #include "nsIGIOService.h"
 #include "nsIGSettingsService.h"
@@ -102,18 +102,18 @@ nsGNOMEShellService::Init()
 
   if (GetAppPathFromLauncher())
     return NS_OK;
 
   nsCOMPtr<nsIProperties> dirSvc
     (do_GetService("@mozilla.org/file/directory_service;1"));
   NS_ENSURE_TRUE(dirSvc, NS_ERROR_NOT_AVAILABLE);
 
-  nsCOMPtr<nsILocalFile> appPath;
-  rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsILocalFile),
+  nsCOMPtr<nsIFile> appPath;
+  rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile),
                    getter_AddRefs(appPath));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = appPath->AppendNative(NS_LITERAL_CSTRING(MOZ_APP_NAME));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return appPath->GetNativePath(mAppPath);
 }
@@ -636,17 +636,17 @@ nsGNOMEShellService::OpenApplication(PRI
 
   g_strfreev(argv);
   delete[] newArgv;
 
   return err ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-nsGNOMEShellService::OpenApplicationWithURI(nsILocalFile* aApplication, const nsACString& aURI)
+nsGNOMEShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI)
 {
   nsresult rv;
   nsCOMPtr<nsIProcess> process = 
     do_CreateInstance("@mozilla.org/process/util;1", &rv);
   if (NS_FAILED(rv))
     return rv;
   
   rv = process->Init(aApplication);
@@ -654,12 +654,12 @@ nsGNOMEShellService::OpenApplicationWith
     return rv;
 
   const nsCString spec(aURI);
   const char* specStr = spec.get();
   return process->Run(false, &specStr, 1);
 }
 
 NS_IMETHODIMP
-nsGNOMEShellService::GetDefaultFeedReader(nsILocalFile** _retval)
+nsGNOMEShellService::GetDefaultFeedReader(nsIFile** _retval)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
--- a/browser/components/shell/src/nsMacShellService.cpp
+++ b/browser/components/shell/src/nsMacShellService.cpp
@@ -162,17 +162,17 @@ nsMacShellService::SetDesktopBackground(
 
   nsCAutoString fileName;
   imageURL->GetFileName(fileName);
   nsCOMPtr<nsIProperties> fileLocator
     (do_GetService("@mozilla.org/file/directory_service;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get the current user's "Pictures" folder (That's ~/Pictures):
-  fileLocator->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsILocalFile),
+  fileLocator->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile),
                    getter_AddRefs(mBackgroundFile));
   if (!mBackgroundFile)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsAutoString fileNameUnicode;
   CopyUTF8toUTF16(fileName, fileNameUnicode);
 
   // and add the imgage file name itself:
@@ -324,29 +324,29 @@ nsMacShellService::OpenApplication(PRInt
     }
     break;
   case nsIMacShellService::APPLICATION_KEYCHAIN_ACCESS:
     err = ::LSGetApplicationForInfo('APPL', 'kcmr', NULL, kLSRolesAll, NULL,
                                     &appURL);
     break;
   case nsIMacShellService::APPLICATION_NETWORK:
     {
-      nsCOMPtr<nsILocalFile> lf;
+      nsCOMPtr<nsIFile> lf;
       rv = NS_NewNativeLocalFile(NETWORK_PREFPANE, true, getter_AddRefs(lf));
       NS_ENSURE_SUCCESS(rv, rv);
       bool exists;
       lf->Exists(&exists);
       if (!exists)
         return NS_ERROR_FILE_NOT_FOUND;
       return lf->Launch();
     }  
     break;
   case nsIMacShellService::APPLICATION_DESKTOP:
     {
-      nsCOMPtr<nsILocalFile> lf;
+      nsCOMPtr<nsIFile> lf;
       rv = NS_NewNativeLocalFile(DESKTOP_PREFPANE, true, getter_AddRefs(lf));
       NS_ENSURE_SUCCESS(rv, rv);
       bool exists;
       lf->Exists(&exists);
       if (!exists)
         return NS_ERROR_FILE_NOT_FOUND;
       return lf->Launch();
     }  
@@ -377,17 +377,17 @@ nsMacShellService::SetDesktopBackgroundC
 {
   // This method and |GetDesktopBackgroundColor| has no meaning on Mac OS X.
   // The mac desktop preferences UI uses pictures for the few solid colors it
   // supports.
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsMacShellService::OpenApplicationWithURI(nsILocalFile* aApplication, const nsACString& aURI)
+nsMacShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI)
 {
   nsCOMPtr<nsILocalFileMac> lfm(do_QueryInterface(aApplication));
   CFURLRef appURL;
   nsresult rv = lfm->GetCFURL(&appURL);
   if (NS_FAILED(rv))
     return rv;
   
   const nsCString spec(aURI);
@@ -414,17 +414,17 @@ nsMacShellService::OpenApplicationWithUR
   
   ::CFRelease(uris);
   ::CFRelease(uri);
   
   return err != noErr ? NS_ERROR_FAILURE : NS_OK;
 }
 
 NS_IMETHODIMP
-nsMacShellService::GetDefaultFeedReader(nsILocalFile** _retval)
+nsMacShellService::GetDefaultFeedReader(nsIFile** _retval)
 {
   nsresult rv = NS_ERROR_FAILURE;
   *_retval = nsnull;
 
   CFStringRef defaultHandlerID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("feed"));
   if (!defaultHandlerID) {
     defaultHandlerID = ::CFStringCreateWithCString(kCFAllocatorDefault,
                                                    SAFARI_BUNDLE_IDENTIFIER,
--- a/browser/components/shell/src/nsMacShellService.h
+++ b/browser/components/shell/src/nsMacShellService.h
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsmacshellservice_h____
 #define nsmacshellservice_h____
 
 #include "nsIMacShellService.h"
 #include "nsIWebProgressListener.h"
-#include "nsILocalFile.h"
+#include "nsIFile.h"
 #include "nsCOMPtr.h"
 
 class nsMacShellService : public nsIMacShellService,
                           public nsIWebProgressListener
 {
 public:
   nsMacShellService() : mCheckedThisSession(false) {};
   virtual ~nsMacShellService() {};
@@ -21,14 +21,14 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSISHELLSERVICE
   NS_DECL_NSIMACSHELLSERVICE
   NS_DECL_NSIWEBPROGRESSLISTENER
 
 protected:
 
 private:
-  nsCOMPtr<nsILocalFile> mBackgroundFile;
+  nsCOMPtr<nsIFile> mBackgroundFile;
 
   bool      mCheckedThisSession;
 };
 
 #endif // nsmacshellservice_h____
--- a/browser/components/shell/src/nsWindowsShellService.cpp
+++ b/browser/components/shell/src/nsWindowsShellService.cpp
@@ -208,19 +208,19 @@ static nsCOMPtr<nsIThread> sThread;
 nsresult
 GetHelperPath(nsAutoString& aPath)
 {
   nsresult rv;
   nsCOMPtr<nsIProperties> directoryService = 
     do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsILocalFile> appHelper;
+  nsCOMPtr<nsIFile> appHelper;
   rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
-                             NS_GET_IID(nsILocalFile),
+                             NS_GET_IID(nsIFile),
                              getter_AddRefs(appHelper));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = appHelper->AppendNative(NS_LITERAL_CSTRING("uninstall"));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = appHelper->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1037,17 +1037,17 @@ nsWindowsShellService::LaunchPrefetchCle
   if (sThread) {
     nsCOMPtr<nsIRunnable> prefetchEvent = new ClearPrefetchEvent();
     sThread->Dispatch(prefetchEvent, NS_DISPATCH_NORMAL);
   }
 }
 #endif
 
 NS_IMETHODIMP
-nsWindowsShellService::OpenApplicationWithURI(nsILocalFile* aApplication,
+nsWindowsShellService::OpenApplicationWithURI(nsIFile* aApplication,
                                               const nsACString& aURI)
 {
   nsresult rv;
   nsCOMPtr<nsIProcess> process = 
     do_CreateInstance("@mozilla.org/process/util;1", &rv);
   if (NS_FAILED(rv))
     return rv;
   
@@ -1056,17 +1056,17 @@ nsWindowsShellService::OpenApplicationWi
     return rv;
   
   const nsCString spec(aURI);
   const char* specStr = spec.get();
   return process->Run(false, &specStr, 1);
 }
 
 NS_IMETHODIMP
-nsWindowsShellService::GetDefaultFeedReader(nsILocalFile** _retval)
+nsWindowsShellService::GetDefaultFeedReader(nsIFile** _retval)
 {
   *_retval = nsnull;
 
   nsresult rv;
   nsCOMPtr<nsIWindowsRegKey> regKey =
     do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1085,17 +1085,17 @@ nsWindowsShellService::GetDefaultFeedRea
     // Everything inside the quotes
     path = Substring(path, 1, path.FindChar('"', 1) - 1);
   }
   else {
     // Everything up to the first space
     path = Substring(path, 0, path.FindChar(' '));
   }
 
-  nsCOMPtr<nsILocalFile> defaultReader =
+  nsCOMPtr<nsIFile> defaultReader =
     do_CreateInstance("@mozilla.org/file/local;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = defaultReader->InitWithPath(path);
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool exists;
   rv = defaultReader->Exists(&exists);
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -118,24 +118,33 @@ let DebuggerController = {
     }
 
     // If this debugger is connecting remotely to a server, we need to check
     // after a while if the connection actually succeeded.
     this._remoteConnectionTry = ++this._remoteConnectionTry || 1;
     this._remoteConnectionTimeout = window.setTimeout(function() {
       // If we couldn't connect to any server yet, try again...
       if (!DebuggerController.activeThread) {
+        DebuggerController._onRemoteConnectionTimeout();
         DebuggerController._connect();
       }
     }, Prefs.remoteTimeout);
 
     return true;
   },
 
   /**
+   * Called when a remote connection timeout occurs.
+   */
+  _onRemoteConnectionTimeout: function DC__onRemoteConnectionTimeout() {
+    Cu.reportError("Couldn't connect to " +
+      Prefs.remoteHost + ":" + Prefs.remotePort);
+  },
+
+  /**
    * Initializes a debugger client and connects it to the debugger server,
    * wiring event handlers as necessary.
    */
   _connect: function DC__connect() {
     if (this._isRemoteDebugger) {
       if (!this._prepareConnection()) {
         return;
       }
@@ -912,102 +921,150 @@ SourceScripts.prototype = {
         DebuggerView.editor.setMode(SourceEditor.MODES.JAVASCRIPT);
       } else {
         DebuggerView.editor.setMode(SourceEditor.MODES.HTML);
       }
       return;
     }
 
     // Use JS mode for files with .js and .jsm extensions.
-    if (/\.jsm?$/.test(this._trimUrlQuery(aUrl))) {
+    if (/\.jsm?$/.test(this.trimUrlQuery(aUrl))) {
       DebuggerView.editor.setMode(SourceEditor.MODES.JAVASCRIPT);
     } else {
       DebuggerView.editor.setMode(SourceEditor.MODES.HTML);
     }
   },
 
   /**
-   * Trims the id selector or query part of a url string, if necessary.
+   * Trims the query part or reference identifier of a url string, if necessary.
    *
    * @param string aUrl
    *        The script url.
    * @return string
+   *         The url with the trimmed query.
    */
-  _trimUrlQuery: function SS__trimUrlQuery(aUrl) {
-    let q = aUrl.indexOf('#');
-    if (q === -1) q = aUrl.indexOf('?');
-    if (q === -1) q = aUrl.indexOf('&');
+  trimUrlQuery: function SS_trimUrlQuery(aUrl) {
+    let length = aUrl.length;
+    let q1 = aUrl.indexOf('?');
+    let q2 = aUrl.indexOf('&');
+    let q3 = aUrl.indexOf('#');
+    let q = Math.min(q1 !== -1 ? q1 : length,
+                     q2 !== -1 ? q2 : length,
+                     q3 !== -1 ? q3 : length);
 
-    if (q > -1) {
-      return aUrl.slice(0, q);
-    }
-    return aUrl;
+    return aUrl.slice(0, q);
   },
 
   /**
-   * Gets the prePath for a script URL.
+   * Trims as much as possible from a URL, while keeping the result unique
+   * in the Debugger View scripts container.
    *
-   * @param string aUrl
-   *        The script url.
+   * @param string | nsIURL aUrl
+   *        The script URL.
+   * @param string aLabel [optional]
+   *        The resulting label at each step.
+   * @param number aSeq [optional]
+   *        The current iteration step.
    * @return string
-   *         The script prePath if the url is valid, null otherwise.
+   *         The resulting label at the final step.
    */
-  _getScriptPrePath: function SS__getScriptDomain(aUrl) {
-    try {
-      return Services.io.newURI(aUrl, null, null).prePath + "/";
-    } catch (e) {
+  _trimURL: function SS__trimURL(aUrl, aLabel, aSeq) {
+    if (!(aUrl instanceof Ci.nsIURL)) {
+      try {
+        // Use an nsIURL to parse all the url path parts.
+        aUrl = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
+      } catch (e) {
+        // This doesn't look like a url, or nsIURL can't handle it.
+        return aUrl;
+      }
+    }
+    if (!aSeq) {
+      let name = aUrl.fileName;
+      if (name) {
+        // This is a regular file url, get only the file name (contains the
+        // base name and extension if available).
+
+        // If this url contains an invalid query, unfortunately nsIURL thinks
+        // it's part of the file extension. It must be removed.
+        aLabel = aUrl.fileName.replace(/\&.*/, "");
+      } else {
+        // This is not a file url, hence there is no base name, nor extension.
+        // Proceed using other available information.
+        aLabel = "";
+      }
+      aSeq = 1;
+    }
+
+    // If we have a label and it doesn't start with a query...
+    if (aLabel && aLabel.indexOf("?") !== 0) {
+
+      if (DebuggerView.Scripts.containsIgnoringQuery(aUrl.spec)) {
+        // A page may contain multiple requests to the same url but with different
+        // queries. It would be redundant to show each one.
+        return aLabel;
+      }
+      if (!DebuggerView.Scripts.containsLabel(aLabel)) {
+        // We found the shortest unique label for the url.
+        return aLabel;
+      }
     }
-    return null;
+
+    // Append the url query.
+    if (aSeq === 1) {
+      let query = aUrl.query;
+      if (query) {
+        return this._trimURL(aUrl, aLabel + "?" + query, aSeq + 1);
+      }
+      aSeq++;
+    }
+    // Append the url reference.
+    if (aSeq === 2) {
+      let ref = aUrl.ref;
+      if (ref) {
+        return this._trimURL(aUrl, aLabel + "#" + aUrl.ref, aSeq + 1);
+      }
+      aSeq++;
+    }
+    // Prepend the url directory.
+    if (aSeq === 3) {
+      let dir = aUrl.directory;
+      if (dir) {
+        return this._trimURL(aUrl, dir.replace(/^\//, "") + aLabel, aSeq + 1);
+      }
+      aSeq++;
+    }
+    // Prepend the hostname and port number.
+    if (aSeq === 4) {
+      let host = aUrl.hostPort;
+      if (host) {
+        return this._trimURL(aUrl, host + "/" + aLabel, aSeq + 1);
+      }
+      aSeq++;
+    }
+    // Use the whole url spec but ignoring the reference.
+    if (aSeq === 5) {
+      return this._trimURL(aUrl, aUrl.specIgnoringRef, aSeq + 1);
+    }
+    // Give up.
+    return aUrl.spec;
   },
 
   /**
    * Gets a unique, simplified label from a script url.
-   * ex: a). ici://some.address.com/random/subrandom/
-   *     b). ni://another.address.org/random/subrandom/page.html
-   *     c). san://interesting.address.gro/random/script.js
-   *     d). si://interesting.address.moc/random/another/script.js
-   * =>
-   *     a). subrandom/
-   *     b). page.html
-   *     c). script.js
-   *     d). another/script.js
    *
    * @param string aUrl
    *        The script url.
    * @param string aHref
    *        The content location href to be used. If unspecified, it will
    *        default to the script url prepath.
    * @return string
    *         The simplified label.
    */
   _getScriptLabel: function SS__getScriptLabel(aUrl, aHref) {
-    let url = this._trimUrlQuery(aUrl);
-
-    if (this._labelsCache[url]) {
-      return this._labelsCache[url];
-    }
-
-    let content = window.parent.content;
-    let domain = content ? content.location.href : this._getScriptPrePath(aUrl);
-
-    let href = aHref || domain;
-    let pathElements = url.split("/");
-    let label = pathElements.pop() || (pathElements.pop() + "/");
-
-    // If the label as a leaf name is already present in the scripts list.
-    if (DebuggerView.Scripts.containsLabel(label)) {
-      label = url.replace(href.substring(0, href.lastIndexOf("/") + 1), "");
-
-      // If the path/to/script is exactly the same, we're in different domains.
-      if (DebuggerView.Scripts.containsLabel(label)) {
-        label = url;
-      }
-    }
-
-    return this._labelsCache[url] = label;
+    return this._labelsCache[aUrl] || (this._labelsCache[aUrl] = this._trimURL(aUrl));
   },
 
   /**
    * Clears the labels cache, populated by SS_getScriptLabel.
    * This should be done every time the content location changes.
    */
   _clearLabelsCache: function SS__clearLabelsCache() {
     this._labelsCache = {};
--- a/browser/devtools/debugger/debugger-view.js
+++ b/browser/devtools/debugger/debugger-view.js
@@ -154,16 +154,41 @@ ScriptsView.prototype = {
    */
   clearSearch: function DVS_clearSearch() {
     this._searchbox.value = "";
     this._onScriptsSearch({});
   },
 
   /**
    * Checks whether the script with the specified URL is among the scripts
+   * known to the debugger (ignoring the query & reference).
+   *
+   * @param string aUrl
+   *        The script URL.
+   * @return boolean
+   */
+  containsIgnoringQuery: function DVS_containsIgnoringQuery(aUrl) {
+    let sourceScripts = DebuggerController.SourceScripts;
+    aUrl = sourceScripts.trimUrlQuery(aUrl);
+
+    if (this._tmpScripts.some(function(element) {
+      return sourceScripts.trimUrlQuery(element.script.url) == aUrl;
+    })) {
+      return true;
+    }
+    if (this.scriptLocations.some(function(url) {
+      return sourceScripts.trimUrlQuery(url) == aUrl;
+    })) {
+      return true;
+    }
+    return false;
+  },
+
+  /**
+   * Checks whether the script with the specified URL is among the scripts
    * known to the debugger and shown in the list.
    *
    * @param string aUrl
    *        The script URL.
    * @return boolean
    */
   contains: function DVS_contains(aUrl) {
     if (this._tmpScripts.some(function(element) {
@@ -341,17 +366,17 @@ ScriptsView.prototype = {
    * @param boolean aSelectIfEmptyFlag
    *        True to set the newly created script as the currently selected item
    *        if there are no other existing scripts in the container.
    */
   _createScriptElement: function DVS__createScriptElement(
     aLabel, aScript, aIndex, aSelectIfEmptyFlag)
   {
     // Make sure we don't duplicate anything.
-    if (aLabel == "null" || this.containsLabel(aLabel)) {
+    if (aLabel == "null" || this.containsLabel(aLabel) || this.contains(aScript.url)) {
       return;
     }
 
     let scriptItem =
       aIndex == -1 ? this._scripts.appendItem(aLabel, aScript.url)
                    : this._scripts.insertItemAt(aIndex, aLabel, aScript.url);
 
     scriptItem.setAttribute("tooltiptext", aScript.url);
--- a/browser/devtools/debugger/test/browser_dbg_createRemote.js
+++ b/browser/devtools/debugger/test/browser_dbg_createRemote.js
@@ -2,26 +2,32 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Tests that a remote debugger can be created in a new window.
 
 var gWindow = null;
 var gTab = null;
+var gRemotePort = null;
 var gAutoConnect = null;
 
 const TEST_URL = EXAMPLE_URL + "browser_dbg_iframes.html";
 
 function test() {
   debug_remote(TEST_URL, function(aTab, aDebuggee, aWindow) {
     gTab = aTab;
     gWindow = aWindow;
     let gDebugger = gWindow.contentWindow;
 
+    info("Current remote port: " +
+      Services.prefs.getIntPref("devtools.debugger.remote-port"));
+    info("Current autoconnect flag: " +
+      Services.prefs.getBoolPref("devtools.debugger.remote-autoconnect"));
+
     is(gDebugger.document.getElementById("close").getAttribute("hidden"), "true",
       "The close button should be hidden in a remote debugger.");
 
     is(gDebugger.DebuggerController.activeThread.paused, false,
       "Should be running after debug_remote.");
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       Services.tm.currentThread.dispatch({ run: function() {
@@ -55,26 +61,51 @@ function test() {
   },
   function beforeTabAdded() {
     if (!DebuggerServer.initialized) {
       DebuggerServer.init(function() { return true; });
       DebuggerServer.addBrowserActors();
     }
     DebuggerServer.closeListener();
 
+    gRemotePort = Services.prefs.getIntPref("devtools.debugger.remote-port");
     gAutoConnect = Services.prefs.getBoolPref("devtools.debugger.remote-autoconnect");
-    Services.prefs.setBoolPref("devtools.debugger.remote-autoconnect", true);
 
     // Open the listener at some point in the future to test automatic reconnect.
-    window.setTimeout(function() {
-      DebuggerServer.openListener(
-        Services.prefs.getIntPref("devtools.debugger.remote-port"));
-    }, Math.random() * 1000);
+    openListener(gRemotePort + 1);
   });
 }
 
+let attempts = 0;
+
+function openListener(port) {
+  Services.prefs.setIntPref("devtools.debugger.remote-port", port);
+  Services.prefs.setBoolPref("devtools.debugger.remote-autoconnect", true);
+
+  info("Attempting to open a new listener on port " + port);
+  try {
+    info("Closing listener...");
+    DebuggerServer.closeListener();
+    info("Opening listener...");
+    DebuggerServer.openListener(port);
+  } catch (e) {
+    info(e);
+    info("Exception caught when opening listener on port " + port);
+    info("Retrying with port " + (++port));
+
+    if (++attempts < 100) {
+      DebuggerServer.closeListener();
+      openListener(port);
+    } else {
+      ok(false, "Timed out while opening a listener.");
+    }
+  }
+}
+
 registerCleanupFunction(function() {
+  Services.prefs.setIntPref("devtools.debugger.remote-port", gRemotePort);
   Services.prefs.setBoolPref("devtools.debugger.remote-autoconnect", gAutoConnect);
   removeTab(gTab);
   gWindow = null;
   gTab = null;
+  gRemotePort = null;
   gAutoConnect = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-01.js
@@ -32,66 +32,101 @@ function testSimpleCall() {
 
 function testScriptLabelShortening() {
   gDebugger.DebuggerController.activeThread.resume(function() {
     let vs = gDebugger.DebuggerView.Scripts;
     let ss = gDebugger.DebuggerController.SourceScripts;
     vs.empty();
     vs._scripts.removeEventListener("select", vs._onScriptsChange, false);
 
-    is(ss._trimUrlQuery("a/b/c.d?test=1&random=4"), "a/b/c.d",
+    is(ss.trimUrlQuery("a/b/c.d?test=1&random=4#reference"), "a/b/c.d",
       "Trimming the url query isn't done properly.");
 
     let urls = [
-      { href: "ichi://some.address.com/random/", leaf: "subrandom/" },
-      { href: "ni://another.address.org/random/subrandom/", leaf: "page.html" },
-      { href: "san://interesting.address.gro/random/", leaf: "script.js" },
-      { href: "shi://interesting.address.moc/random/", leaf: "script.js" },
-      { href: "shi://interesting.address.moc/random/", leaf: "x/script.js" },
-      { href: "shi://interesting.address.moc/random/", leaf: "x/y/script.js?a=1" },
-      { href: "shi://interesting.address.moc/random/x/", leaf: "y/script.js?a=1&b=2", dupe: true },
-      { href: "shi://interesting.address.moc/random/x/y/", leaf: "script.js?a=1&b=2&c=3", dupe: true },
-      { href: "go://random/", leaf: "script_t1.js&a=1&b=2&c=3" },
-      { href: "roku://random/", leaf: "script_t2.js#id" },
-      { href: "nana://random/", leaf: "script_t3.js#id?a=1&b=2" }
+      { href: "http://some.address.com/random/", leaf: "subrandom/" },
+      { href: "http://some.address.com/random/", leaf: "suprandom/?a=1" },
+      { href: "http://some.address.com/random/", leaf: "?a=1" },
+      { href: "https://another.address.org/random/subrandom/", leaf: "page.html" },
+
+      { href: "ftp://interesting.address.org/random/", leaf: "script.js" },
+      { href: "ftp://interesting.address.com/random/", leaf: "script.js" },
+      { href: "ftp://interesting.address.com/random/", leaf: "x/script.js" },
+      { href: "ftp://interesting.address.com/random/", leaf: "x/y/script.js?a=1" },
+      { href: "ftp://interesting.address.com/random/x/", leaf: "y/script.js?a=1&b=2", dupe: true },
+      { href: "ftp://interesting.address.com/random/x/y/", leaf: "script.js?a=1&b=2&c=3", dupe: true },
+      { href: "ftp://interesting.address.com/random/", leaf: "x/y/script.js?a=2", dupe: true },
+      { href: "ftp://interesting.address.com/random/x/", leaf: "y/script.js?a=2&b=3", dupe: true },
+      { href: "ftp://interesting.address.com/random/x/y/", leaf: "script.js?a=2&b=3&c=4", dupe: true },
+
+      { href: "file://random/", leaf: "script_t1.js&a=1&b=2&c=3" },
+      { href: "file://random/", leaf: "script_t2_1.js#id" },
+      { href: "file://random/", leaf: "script_t2_2.js?a" },
+      { href: "file://random/", leaf: "script_t2_3.js&b" },
+      { href: "resource://random/", leaf: "script_t3_1.js#id?a=1&b=2" },
+      { href: "resource://random/", leaf: "script_t3_2.js?a=1&b=2#id" },
+      { href: "resource://random/", leaf: "script_t3_3.js&a=1&b=2#id" }
     ];
 
     urls.forEach(function(url) {
       executeSoon(function() {
         let loc = url.href + url.leaf;
         vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc }, true);
       });
     });
 
     executeSoon(function() {
+      info("Script labels:");
+      info(vs.scriptLabels.toSource());
+
+      info("Script locations:");
+      info(vs.scriptLocations.toSource());
+
       urls.forEach(function(url) {
         let loc = url.href + url.leaf;
-        ok(url.dupe || vs.contains(loc), "Script url is incorrect: " + loc);
+        if (url.dupe) {
+          ok(!vs.contains(loc), "Shouldn't contain script: " + loc);
+        } else {
+          ok(vs.contains(loc), "Should contain script: " + loc);
+        }
       });
 
-      ok(gDebugger.DebuggerView.Scripts.containsLabel("subrandom/"),
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("random/subrandom/"),
         "Script (0) label is incorrect.");
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("random/suprandom/?a=1"),
+        "Script (1) label is incorrect.");
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("random/?a=1"),
+        "Script (2) label is incorrect.");
       ok(gDebugger.DebuggerView.Scripts.containsLabel("page.html"),
-        "Script (1) label is incorrect.");
+        "Script (3) label is incorrect.");
+
       ok(gDebugger.DebuggerView.Scripts.containsLabel("script.js"),
-        "Script (2) label is incorrect.");
-      ok(gDebugger.DebuggerView.Scripts.containsLabel("shi://interesting.address.moc/random/script.js"),
-        "Script (3) label is incorrect.");
-      ok(gDebugger.DebuggerView.Scripts.containsLabel("x/script.js"),
         "Script (4) label is incorrect.");
-      ok(gDebugger.DebuggerView.Scripts.containsLabel("x/y/script.js"),
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("random/script.js"),
         "Script (5) label is incorrect.");
-      ok(gDebugger.DebuggerView.Scripts.containsLabel("script_t1.js"),
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("random/x/script.js"),
         "Script (6) label is incorrect.");
-      ok(gDebugger.DebuggerView.Scripts.containsLabel("script_t2.js"),
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("script.js?a=1"),
         "Script (7) label is incorrect.");
-      ok(gDebugger.DebuggerView.Scripts.containsLabel("script_t3.js"),
+
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("script_t1.js"),
         "Script (8) label is incorrect.");
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("script_t2_1.js"),
+        "Script (9) label is incorrect.");
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("script_t2_2.js"),
+        "Script (10) label is incorrect.");
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("script_t2_3.js"),
+        "Script (11) label is incorrect.");
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("script_t3_1.js"),
+        "Script (12) label is incorrect.");
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("script_t3_2.js"),
+        "Script (13) label is incorrect.");
+      ok(gDebugger.DebuggerView.Scripts.containsLabel("script_t3_3.js"),
+        "Script (14) label is incorrect.");
 
-      is(vs._scripts.itemCount, 9,
+      is(vs._scripts.itemCount, urls.filter(function(url) !url.dupe).length,
         "Didn't get the correct number of scripts in the list.");
 
       closeDebuggerAndFinish();
     });
   });
 }
 
 registerCleanupFunction(function() {
--- a/browser/fuel/src/fuelApplication.js
+++ b/browser/fuel/src/fuelApplication.js
@@ -15,16 +15,22 @@ const APPLICATION_CONTRACTID = "@mozilla
 var Utilities = {
   get bookmarks() {
     let bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
                     getService(Ci.nsINavBookmarksService);
     this.__defineGetter__("bookmarks", function() bookmarks);
     return this.bookmarks;
   },
 
+  get bookmarksObserver() {
+    let bookmarksObserver = new BookmarksObserver();
+    this.__defineGetter__("bookmarksObserver", function() bookmarksObserver);
+    return this.bookmarksObserver;
+  },
+
   get livemarks() {
     let livemarks = Cc["@mozilla.org/browser/livemark-service;2"].
                     getService[Ci.mozIAsyncLivemarks].
                     QueryInterface(Ci.nsILivemarkService);
     this.__defineGetter__("livemarks", function() livemarks);
     return this.livemarks;
   },
 
@@ -44,114 +50,132 @@ var Utilities = {
 
   get windowMediator() {
     let windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
                          getService(Ci.nsIWindowMediator);
     this.__defineGetter__("windowMediator", function() windowMediator);
     return this.windowMediator;
   },
 
-  makeURI : function(aSpec) {
+  makeURI: function fuelutil_makeURI(aSpec) {
     if (!aSpec)
       return null;
     var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
     return ios.newURI(aSpec, null, null);
   },
 
-  free : function() {
+  free: function fuelutil_free() {
     delete this.bookmarks;
+    delete this.bookmarksObserver;
     delete this.livemarks
     delete this.annotations;
     delete this.history;
     delete this.windowMediator;
   }
 };
 
 
 //=================================================
 // Window implementation
+
+var fuelWindowMap = new WeakMap();
+function getWindow(aWindow) {
+  let fuelWindow = fuelWindowMap.get(aWindow);
+  if (!fuelWindow) {
+    fuelWindow = new Window(aWindow);
+    fuelWindowMap.set(aWindow, fuelWindow);
+  }
+  return fuelWindow;
+}
+
+// Don't call new Window() directly; use getWindow instead.
 function Window(aWindow) {
   this._window = aWindow;
-  this._tabbrowser = aWindow.getBrowser();
   this._events = new Events();
-  this._cleanup = {};
 
   this._watch("TabOpen");
   this._watch("TabMove");
   this._watch("TabClose");
   this._watch("TabSelect");
-
-  var self = this;
-  gShutdown.push(function() { self._shutdown(); });
 }
 
 Window.prototype = {
   get events() {
     return this._events;
   },
 
+  get _tabbrowser() {
+    return this._window.getBrowser();
+  },
+
   /*
    * Helper used to setup event handlers on the XBL element. Note that the events
    * are actually dispatched to tabs, so we capture them.
    */
-  _watch : function win_watch(aType) {
-    var self = this;
-    this._tabbrowser.tabContainer.addEventListener(aType,
-      this._cleanup[aType] = function(e){ self._event(e); },
-      true);
+  _watch: function win_watch(aType) {
+    this._tabbrowser.tabContainer.addEventListener(aType, this,
+                                                   /* useCapture = */ true);
   },
 
-  /*
-   * Helper event callback used to redirect events made on the XBL element
-   */
-  _event : function win_event(aEvent) {
-    this._events.dispatch(aEvent.type, new BrowserTab(this, aEvent.originalTarget.linkedBrowser));
+  handleEvent: function win_handleEvent(aEvent) {
+    this._events.dispatch(aEvent.type, getBrowserTab(this, aEvent.originalTarget.linkedBrowser));
   },
+
   get tabs() {
     var tabs = [];
     var browsers = this._tabbrowser.browsers;
     for (var i=0; i<browsers.length; i++)
-      tabs.push(new BrowserTab(this, browsers[i]));
+      tabs.push(getBrowserTab(this, browsers[i]));
     return tabs;
   },
+
   get activeTab() {
-    return new BrowserTab(this, this._tabbrowser.selectedBrowser);
-  },
-  open : function win_open(aURI) {
-    return new BrowserTab(this, this._tabbrowser.addTab(aURI.spec).linkedBrowser);
-  },
-  _shutdown : function win_shutdown() {
-    for (var type in this._cleanup)
-      this._tabbrowser.removeEventListener(type, this._cleanup[type], true);
-    this._cleanup = null;
-
-    this._window = null;
-    this._tabbrowser = null;
-    this._events = null;
+    return getBrowserTab(this, this._tabbrowser.selectedBrowser);
   },
 
-  QueryInterface : XPCOMUtils.generateQI([Ci.fuelIWindow])
+  open: function win_open(aURI) {
+    return getBrowserTab(this, this._tabbrowser.addTab(aURI.spec).linkedBrowser);
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.fuelIWindow])
 };
 
 //=================================================
 // BrowserTab implementation
+
+var fuelBrowserTabMap = new WeakMap();
+function getBrowserTab(aFUELWindow, aBrowser) {
+  let fuelBrowserTab = fuelBrowserTabMap.get(aBrowser);
+  if (!fuelBrowserTab) {
+    fuelBrowserTab = new BrowserTab(aFUELWindow, aBrowser);
+    fuelBrowserTabMap.set(aBrowser, fuelBrowserTab);
+  }
+  else {
+    // This tab may have moved to another window, so make sure its cached
+    // window is up-to-date.
+    fuelBrowserTab._window = aFUELWindow;
+  }
+
+  return fuelBrowserTab;
+}
+
+// Don't call new BrowserTab() directly; call getBrowserTab instead.
 function BrowserTab(aFUELWindow, aBrowser) {
   this._window = aFUELWindow;
-  this._tabbrowser = aFUELWindow._tabbrowser;
   this._browser = aBrowser;
   this._events = new Events();
-  this._cleanup = {};
 
   this._watch("load");
-
-  var self = this;
-  gShutdown.push(function() { self._shutdown(); });
 }
 
 BrowserTab.prototype = {
+  get _tabbrowser() {
+    return this._window._tabbrowser;
+  },
+
   get uri() {
     return this._browser.currentURI;
   },
 
   get index() {
     var tabs = this._tabbrowser.tabs;
     for (var i=0; i<tabs.length; i++) {
       if (tabs[i].linkedBrowser == this._browser)
@@ -170,138 +194,247 @@ BrowserTab.prototype = {
 
   get document() {
     return this._browser.contentDocument;
   },
 
   /*
    * Helper used to setup event handlers on the XBL element
    */
-  _watch : function bt_watch(aType) {
-    var self = this;
-    this._browser.addEventListener(aType,
-      this._cleanup[aType] = function(e){ self._event(e); },
-      true);
+  _watch: function bt_watch(aType) {
+    this._browser.addEventListener(aType, this,
+                                   /* useCapture = */ true);
   },
 
-  /*
-   * Helper event callback used to redirect events made on the XBL element
-   */
-  _event : function bt_event(aEvent) {
+  handleEvent: function bt_handleEvent(aEvent) {
     if (aEvent.type == "load") {
       if (!(aEvent.originalTarget instanceof Ci.nsIDOMDocument))
         return;
 
       if (aEvent.originalTarget.defaultView instanceof Ci.nsIDOMWindow &&
           aEvent.originalTarget.defaultView.frameElement)
         return;
     }
     this._events.dispatch(aEvent.type, this);
   },
   /*
    * Helper used to determine the index offset of the browsertab
    */
-  _getTab : function bt_gettab() {
+  _getTab: function bt_gettab() {
     var tabs = this._tabbrowser.tabs;
     return tabs[this.index] || null;
   },
 
-  load : function bt_load(aURI) {
+  load: function bt_load(aURI) {
     this._browser.loadURI(aURI.spec, null, null);
   },
 
-  focus : function bt_focus() {
+  focus: function bt_focus() {
     this._tabbrowser.selectedTab = this._getTab();
     this._tabbrowser.focus();
   },
 
-  close : function bt_close() {
+  close: function bt_close() {
     this._tabbrowser.removeTab(this._getTab());
   },
 
-  moveBefore : function bt_movebefore(aBefore) {
+  moveBefore: function bt_movebefore(aBefore) {
     this._tabbrowser.moveTabTo(this._getTab(), aBefore.index);
   },
 
-  moveToEnd : function bt_moveend() {
+  moveToEnd: function bt_moveend() {
     this._tabbrowser.moveTabTo(this._getTab(), this._tabbrowser.browsers.length);
   },
 
-  _shutdown : function bt_shutdown() {
-    for (var type in this._cleanup)
-      this._browser.removeEventListener(type, this._cleanup[type], true);
-    this._cleanup = null;
-
-    this._window = null;
-    this._tabbrowser = null;
-    this._browser = null;
-    this._events = null;
-  },
-
-  QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBrowserTab])
+  QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBrowserTab])
 };
 
 
 //=================================================
 // Annotations implementation
 function Annotations(aId) {
   this._id = aId;
 }
 
 Annotations.prototype = {
   get names() {
     return Utilities.annotations.getItemAnnotationNames(this._id);
   },
 
-  has : function ann_has(aName) {
+  has: function ann_has(aName) {
     return Utilities.annotations.itemHasAnnotation(this._id, aName);
   },
 
-  get : function(aName) {
+  get: function ann_get(aName) {
     if (this.has(aName))
       return Utilities.annotations.getItemAnnotation(this._id, aName);
     return null;
   },
 
-  set : function(aName, aValue, aExpiration) {
+  set: function ann_set(aName, aValue, aExpiration) {
     Utilities.annotations.setItemAnnotation(this._id, aName, aValue, 0, aExpiration);
   },
 
-  remove : function ann_remove(aName) {
+  remove: function ann_remove(aName) {
     if (aName)
       Utilities.annotations.removeItemAnnotation(this._id, aName);
   },
 
-  QueryInterface : XPCOMUtils.generateQI([Ci.fuelIAnnotations])
+  QueryInterface: XPCOMUtils.generateQI([Ci.fuelIAnnotations])
 };
 
 
 //=================================================
+// BookmarksObserver implementation (internal class)
+//
+// BookmarksObserver is a global singleton which watches the browser's
+// bookmarks and sends you events when things change.
+//
+// You can register three different kinds of event listeners on
+// BookmarksObserver, using addListener, addFolderListener, and
+// addRootlistener.
+//
+//  - addListener(aId, aEvent, aListener) lets you listen to a specific
+//    bookmark.  You can listen to the "change", "move", and "remove" events.
+//
+//  - addFolderListener(aId, aEvent, aListener) lets you listen to a specific
+//    bookmark folder.  You can listen to "addchild" and "removechild".
+//
+//  - addRootListener(aEvent, aListener) lets you listen to the root bookmark
+//    node.  This lets you hear "add", "remove", and "change" events on all
+//    bookmarks.
+//
+
+function BookmarksObserver() {
+  this._eventsDict = {};
+  this._folderEventsDict = {};
+  this._rootEvents = new Events();
+  Utilities.bookmarks.addObserver(this, /* ownsWeak = */ true);
+}
+
+BookmarksObserver.prototype = {
+  onBeginUpdateBatch: function () {},
+  onEndUpdateBatch: function () {},
+  onBeforeItemRemoved: function () {},
+  onItemVisited: function () {},
+
+  onItemAdded: function bo_onItemAdded(aId, aFolder, aIndex, aItemType, aURI) {
+    this._rootEvents.dispatch("add", aId);
+    this._dispatchToEvents("addchild", aId, this._folderEventsDict[aFolder]);
+  },
+
+  onItemRemoved: function bo_onItemRemoved(aId, aFolder, aIndex) {
+    this._rootEvents.dispatch("remove", aId);
+    this._dispatchToEvents("remove", aId, this._eventsDict[aId]);
+    this._dispatchToEvents("removechild", aId, this._folderEventsDict[aFolder]);
+  },
+
+  onItemChanged: function bo_onItemChanged(aId, aProperty, aIsAnnotationProperty, aValue) {
+    this._rootEvents.dispatch("change", aProperty);
+    this._dispatchToEvents("change", aProperty, this._eventsDict[aId]);
+  },
+
+  onItemMoved: function bo_onItemMoved(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
+    this._dispatchToEvents("move", aId, this._eventsDict[aId]);
+  },
+
+  _dispatchToEvents: function bo_dispatchToEvents(aEvent, aData, aEvents) {
+    if (aEvents) {
+      aEvents.dispatch(aEvent, aData);
+    }
+  },
+
+  _addListenerToDict: function bo_addListenerToDict(aId, aEvent, aListener, aDict) {
+    var events = aDict[aId];
+    if (!events) {
+      events = new Events();
+      aDict[aId] = events;
+    }
+    events.addListener(aEvent, aListener);
+  },
+
+  _removeListenerFromDict: function bo_removeListenerFromDict(aId, aEvent, aListener, aDict) {
+    var events = aDict[aId];
+    if (!events) {
+      return;
+    }
+    events.removeListener(aEvent, aListener);
+    if (events._listeners.length == 0) {
+      delete aDict[aId];
+    }
+  },
+
+  addListener: function bo_addListener(aId, aEvent, aListener) {
+    this._addListenerToDict(aId, aEvent, aListener, this._eventsDict);
+  },
+
+  removeListener: function bo_removeListener(aId, aEvent, aListener) {
+    this._removeListenerFromDict(aId, aEvent, aListener, this._eventsDict);
+  },
+
+  addFolderListener: function addFolderListener(aId, aEvent, aListener) {
+    this._addListenerToDict(aId, aEvent, aListener, this._folderEventsDict);
+  },
+
+  removeFolderListener: function removeFolderListener(aId, aEvent, aListener) {
+    this._removeListenerFromDict(aId, aEvent, aListener, this._folderEventsDict);
+  },
+
+  addRootListener: function addRootListener(aEvent, aListener) {
+    this._rootEvents.addListener(aEvent, aListener);
+  },
+
+  removeRootListener: function removeRootListener(aEvent, aListener) {
+    this._rootEvents.removeListener(aEvent, aListener);
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarksObserver,
+                                         Ci.nsISupportsWeakReference])
+};
+
+//=================================================
 // Bookmark implementation
+//
+// Bookmark event listeners are stored in BookmarksObserver, not in the
+// Bookmark objects themselves.  Thus, you don't have to hold on to a Bookmark
+// object in order for your event listener to stay valid, and Bookmark objects
+// not kept alive by the extension can be GC'ed.
+//
+// A consequence of this is that if you have two different Bookmark objects x
+// and y for the same bookmark (i.e., x != y but x.id == y.id), and you do
+//
+//   x.addListener("foo", fun);
+//   y.removeListener("foo", fun);
+//
+// the second line will in fact remove the listener added in the first line.
+//
+
 function Bookmark(aId, aParent, aType) {
   this._id = aId;
   this._parent = aParent;
   this._type = aType || "bookmark";
   this._annotations = new Annotations(this._id);
-  this._events = new Events();
 
-  Utilities.bookmarks.addObserver(this, false);
+  // Our _events object forwards to bookmarksObserver.
+  var self = this;
+  this._events = {
+    addListener: function bookmarkevents_al(aEvent, aListener) {
+      Utilities.bookmarksObserver.addListener(self._id, aEvent, aListener);
+    },
+    removeListener: function bookmarkevents_rl(aEvent, aListener) {
+      Utilities.bookmarksObserver.removeListener(self._id, aEvent, aListener);
+    },
+    QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents])
+  };
 
-  var self = this;
-  gShutdown.push(function() { self._shutdown(); });
+  // For our onItemMoved listener, which updates this._parent.
+  Utilities.bookmarks.addObserver(this, /* ownsWeak = */ true);
 }
 
 Bookmark.prototype = {
-  _shutdown : function bm_shutdown() {
-    this._annotations = null;
-    this._events = null;
-
-    Utilities.bookmarks.removeObserver(this);
-  },
-
   get id() {
     return this._id;
   },
 
   get title() {
     return Utilities.bookmarks.getItemTitle(this._id);
   },
 
@@ -353,76 +486,96 @@ Bookmark.prototype = {
   get events() {
     return this._events;
   },
 
   remove : function bm_remove() {
     Utilities.bookmarks.removeItem(this._id);
   },
 
-  // observer
-  onBeginUpdateBatch : function bm_obub() {
-  },
-
-  onEndUpdateBatch : function bm_oeub() {
-  },
-
-  onItemAdded : function bm_oia(aId, aFolder, aIndex, aItemType, aURI) {
-    // bookmark object doesn't exist at this point
-  },
-
-  onBeforeItemRemoved : function bm_obir(aId) {
-  },
+  onBeginUpdateBatch: function () {},
+  onEndUpdateBatch: function () {},
+  onItemAdded: function () {},
+  onBeforeItemRemoved: function () {},
+  onItemVisited: function () {},
+  onItemRemoved: function () {},
+  onItemChanged: function () {},
 
-  onItemRemoved : function bm_oir(aId, aFolder, aIndex) {
-    if (this._id == aId)
-      this._events.dispatch("remove", aId);
-  },
-
-  onItemChanged : function bm_oic(aId, aProperty, aIsAnnotationProperty, aValue) {
-    if (this._id == aId)
-      this._events.dispatch("change", aProperty);
-  },
-
-  onItemVisited: function bm_oiv(aId, aVisitID, aTime) {
-  },
-
-  onItemMoved: function bm_oim(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
-    if (this._id == aId) {
+  onItemMoved: function(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
+    if (aId == this._id) {
       this._parent = new BookmarkFolder(aNewParent, Utilities.bookmarks.getFolderIdForItem(aNewParent));
-      this._events.dispatch("move", aId);
     }
   },
 
-  QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmark, Ci.nsINavBookmarkObserver])
+  QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBookmark,
+                                         Ci.nsINavBookmarksObserver,
+                                         Ci.nsISupportsWeakReference])
 };
 
 
 //=================================================
 // BookmarkFolder implementation
+//
+// As with Bookmark, events on BookmarkFolder are handled by the
+// BookmarksObserver singleton.
+//
+
 function BookmarkFolder(aId, aParent) {
   this._id = aId;
   this._parent = aParent;
   this._annotations = new Annotations(this._id);
-  this._events = new Events();
 
-  Utilities.bookmarks.addObserver(this, false);
+  // Our event listeners are handled by the BookmarksObserver singleton.  This
+  // is a bit complicated because there are three different kinds of events we
+  // might want to listen to here:
+  //
+  //  - If this._parent is null, we're the root bookmark folder, and all our
+  //    listeners should be root listeners.
+  //
+  //  - Otherwise, events ending with "child" (addchild, removechild) are
+  //    handled by a folder listener.
+  //
+  //  - Other events are handled by a vanilla bookmark listener.
 
   var self = this;
-  gShutdown.push(function() { self._shutdown(); });
+  this._events = {
+    addListener: function bmfevents_al(aEvent, aListener) {
+      if (self._parent) {
+        if (/child$/.test(aEvent)) {
+          Utilities.bookmarksObserver.addFolderListener(self._id, aEvent, aListener);
+        }
+        else {
+          Utilities.bookmarksObserver.addListener(self._id, aEvent, aListener);
+        }
+      }
+      else {
+        Utilities.bookmarksObserver.addRootListener(aEvent, aListener);
+      }
+    },
+    removeListener: function bmfevents_rl(aEvent, aListener) {
+      if (self._parent) {
+        if (/child$/.test(aEvent)) {
+          Utilities.bookmarksObserver.removeFolderListener(self._id, aEvent, aListener);
+        }
+        else {
+          Utilities.bookmarksObserver.removeListener(self._id, aEvent, aListener);
+        }
+      }
+      else {
+        Utilities.bookmarksObserver.removeRootListener(aEvent, aListener);
+      }
+    },
+    QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents])
+  };
+
+  // For our onItemMoved listener, which updates this._parent.
+  Utilities.bookmarks.addObserver(this, /* ownsWeak = */ true);
 }
 
 BookmarkFolder.prototype = {
-  _shutdown : function bmf_shutdown() {
-    this._annotations = null;
-    this._events = null;
-
-    Utilities.bookmarks.removeObserver(this);
-  },
-
   get id() {
     return this._id;
   },
 
   get title() {
     return Utilities.bookmarks.getItemTitle(this._id);
   },
 
@@ -484,103 +637,63 @@ BookmarkFolder.prototype = {
         items.push(bookmark);
       }
     }
     rootNode.containerOpen = false;
 
     return items;
   },
 
-  addBookmark : function bmf_addbm(aTitle, aUri) {
+  addBookmark: function bmf_addbm(aTitle, aUri) {
     var newBookmarkID = Utilities.bookmarks.insertBookmark(this._id, aUri, Utilities.bookmarks.DEFAULT_INDEX, aTitle);
     var newBookmark = new Bookmark(newBookmarkID, this, "bookmark");
     return newBookmark;
   },
 
-  addSeparator : function bmf_addsep() {
+  addSeparator: function bmf_addsep() {
     var newBookmarkID = Utilities.bookmarks.insertSeparator(this._id, Utilities.bookmarks.DEFAULT_INDEX);
     var newBookmark = new Bookmark(newBookmarkID, this, "separator");
     return newBookmark;
   },
 
-  addFolder : function bmf_addfolder(aTitle) {
+  addFolder: function bmf_addfolder(aTitle) {
     var newFolderID = Utilities.bookmarks.createFolder(this._id, aTitle, Utilities.bookmarks.DEFAULT_INDEX);
     var newFolder = new BookmarkFolder(newFolderID, this);
     return newFolder;
   },
 
-  remove : function bmf_remove() {
+  remove: function bmf_remove() {
     Utilities.bookmarks.removeItem(this._id);
   },
 
   // observer
-  onBeginUpdateBatch : function bmf_obub() {
-  },
-
-  onEndUpdateBatch : function bmf_oeub() {
-  },
-
-  onItemAdded : function bmf_oia(aId, aFolder, aIndex, aItemType, aURI) {
-    // handle root folder events
-    if (!this._parent)
-      this._events.dispatch("add", aId);
-
-    // handle this folder events
-    if (this._id == aFolder)
-      this._events.dispatch("addchild", aId);
-  },
-
-  onBeforeItemRemoved : function bmf_oir(aId) {
-  },
+  onBeginUpdateBatch: function () {},
+  onEndUpdateBatch : function () {},
+  onItemAdded : function () {},
+  onBeforeItemRemoved : function () {},
+  onItemRemoved : function () {},
+  onItemChanged : function () {},
 
-  onItemRemoved : function bmf_oir(aId, aFolder, aIndex) {
-    // handle root folder events
-    if (!this._parent || this._id == aId)
-      this._events.dispatch("remove", aId);
-
-    // handle this folder events
-    if (this._id == aFolder)
-      this._events.dispatch("removechild", aId);
-  },
-
-  onItemChanged : function bmf_oic(aId, aProperty, aIsAnnotationProperty, aValue) {
-    // handle root folder and this folder events
-    if (!this._parent || this._id == aId)
-      this._events.dispatch("change", aProperty);
-  },
-
-  onItemVisited: function bmf_oiv(aId, aVisitID, aTime) {
-  },
-
-  onItemMoved: function bmf_oim(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
-    // handle this folder event, root folder cannot be moved
+  onItemMoved: function bf_onItemMoved(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
     if (this._id == aId) {
       this._parent = new BookmarkFolder(aNewParent, Utilities.bookmarks.getFolderIdForItem(aNewParent));
-      this._events.dispatch("move", aId);
     }
   },
 
-  QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmarkFolder, Ci.nsINavBookmarkObserver])
+  QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBookmarkFolder,
+                                         Ci.nsINavBookmarksObserver,
+                                         Ci.nsISupportsWeakReference])
 };
 
 //=================================================
 // BookmarkRoots implementation
 function BookmarkRoots() {
-  var self = this;
-  gShutdown.push(function() { self._shutdown(); });
 }
 
 BookmarkRoots.prototype = {
-  _shutdown : function bmr_shutdown() {
-    this._menu = null;
-    this._toolbar = null;
-    this._tags = null;
-    this._unfiled = null;
-  },
-
   get menu() {
     if (!this._menu)
       this._menu = new BookmarkFolder(Utilities.bookmarks.bookmarksMenuFolder, null);
 
     return this._menu;
   },
 
   get toolbar() {
@@ -599,17 +712,17 @@ BookmarkRoots.prototype = {
 
   get unfiled() {
     if (!this._unfiled)
       this._unfiled = new BookmarkFolder(Utilities.bookmarks.unfiledBookmarksFolder, null);
 
     return this._unfiled;
   },
 
-  QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmarkRoots])
+  QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBookmarkRoots])
 };
 
 
 //=================================================
 // Factory - Treat Application as a singleton
 // XXX This is required, because we're registered for the 'JavaScript global
 // privileged property' category, whose handler always calls createInstance.
 // See bug 386535.
@@ -627,69 +740,67 @@ var ApplicationFactory = {
   }
 };
 
 
 //=================================================
 // Application constructor
 function Application() {
   this.initToolkitHelpers();
-  this._bookmarks = null;
 }
 
 //=================================================
 // Application implementation
 Application.prototype = {
   // for nsIClassInfo + XPCOMUtils
-  classID:          APPLICATION_CID,
+  classID: APPLICATION_CID,
 
   // redefine the default factory for XPCOMUtils
   _xpcom_factory: ApplicationFactory,
 
   // for nsISupports
-  QueryInterface : XPCOMUtils.generateQI([Ci.fuelIApplication, Ci.extIApplication,
-                                          Ci.nsIObserver]),
+  QueryInterface: XPCOMUtils.generateQI([Ci.fuelIApplication, Ci.extIApplication,
+                                         Ci.nsIObserver, Ci.nsISupportsWeakReference]),
 
   // for nsIClassInfo
   classInfo: XPCOMUtils.generateCI({classID: APPLICATION_CID,
                                     contractID: APPLICATION_CONTRACTID,
                                     interfaces: [Ci.fuelIApplication,
                                                  Ci.extIApplication,
                                                  Ci.nsIObserver],
                                     flags: Ci.nsIClassInfo.SINGLETON}),
 
   // for nsIObserver
   observe: function app_observe(aSubject, aTopic, aData) {
     // Call the extApplication version of this function first
     this.__proto__.__proto__.observe.call(this, aSubject, aTopic, aData);
     if (aTopic == "xpcom-shutdown") {
       this._obs.removeObserver(this, "xpcom-shutdown");
-      this._bookmarks = null;
       Utilities.free();
     }
   },
 
   get bookmarks() {
     let bookmarks = new BookmarkRoots();
     this.__defineGetter__("bookmarks", function() bookmarks);
     return this.bookmarks;
   },
 
   get windows() {
     var win = [];
     var browserEnum = Utilities.windowMediator.getEnumerator("navigator:browser");
 
     while (browserEnum.hasMoreElements())
-      win.push(new Window(browserEnum.getNext()));
+      win.push(getWindow(browserEnum.getNext()));
 
     return win;
   },
 
   get activeWindow() {
-    return new Window(Utilities.windowMediator.getMostRecentWindow("navigator:browser"));
+    return getWindow(Utilities.windowMediator.getMostRecentWindow("navigator:browser"));
   }
 };
 
 #include ../../../toolkit/components/exthelper/extApplication.js
 
 // set the proto, defined in extApplication.js
 Application.prototype.__proto__ = extApplication.prototype;
 
--- a/browser/fuel/test/browser_ApplicationPrefs.js
+++ b/browser/fuel/test/browser_ApplicationPrefs.js
@@ -143,19 +143,16 @@ function test() {
     ok(false, "A locked preference could be modified.");
   } catch(e){
     ok(true, "A locked preference should not be able to be modified.");
   }
 
   pref.locked = false;
   ok(!pref.locked, "A single preference is unlocked.");
 
-  // Preference events tests disabled until bug 533290 is fixed
-  return;
-
   // check for change event when setting a value
   waitForExplicitFinish();
   Application.prefs.events.addListener("change", onPrefChange);
   Application.prefs.setValue("fuel.fuel-test", "change event");
 }
 
 function onPrefChange(evt) {
   is(evt.data, testdata.dummy, "Check 'Application.prefs.setValue' fired a change event");
@@ -172,9 +169,11 @@ function onPrefChange(evt) {
 
 function onPrefChange2(evt) {
   is(evt.data, testdata.dummy, "Check 'Application.prefs.setValue' fired a change event for a single preference");
   Application.prefs.events.removeListener("change", onPrefChange2);
 
   finish();
 }
 
-function onPrefChangeDummy(evt) { }
+function onPrefChangeDummy(evt) {
+  ok(false, "onPrefChangeDummy shouldn't be invoked!");
+}
--- a/browser/fuel/test/browser_Bookmarks.js
+++ b/browser/fuel/test/browser_Bookmarks.js
@@ -1,10 +1,11 @@
 var gLastFolderAction = "";
 var gLastBookmarkAction = "";
+var gLastRootAction = "";
 
 function url(spec) {
   return Services.io.newURI(spec, null, null);
 }
 
 function test() {
   // Some very basic tests on the tags root
   var tags = Application.bookmarks.tags;
@@ -182,16 +183,34 @@ function test() {
   is(testMove.parent.title, "folder-b", "Checking for new parent after moving bookmark");
   is(gLastBookmarkAction, "move", "Checking for event handler after moving bookmark");
 
   // test moving a folder
   testFolderA.events.addListener("move", onFolderMove);
   testFolderA.parent = testFolderB;
   is(testFolderA.parent.title, "folder-b", "Checking for new parent after moving folder");
   is(gLastFolderAction, "move", "Checking for event handler after moving folder");
+
+  // test events on the root
+  root.events.addListener("add", onRootAdd);
+  root.events.addListener("remove", onRootRemove);
+  root.events.addListener("change", onRootChange);
+  var testFolderC = root.addFolder("folder-c");
+  is(gLastRootAction, "add");
+
+  root.events.removeListener("add", onRootAdd);
+  gLastRootAction = "";
+  var testFolderD = root.addFolder("folder-d");
+  is(gLastRootAction, "");
+
+  testFolderC.remove();
+  is(gLastRootAction, "remove");
+
+  testFolderD.description = "Foo";
+  is(gLastRootAction, "bookmarkProperties/description");
 }
 
 function onFolderChange(evt) {
   gLastFolderAction = evt.data;
 }
 
 function onFolderRemove(evt) {
   gLastFolderAction = evt.type;
@@ -215,8 +234,20 @@ function onBookmarkChange(evt) {
 
 function onBookmarkRemove(evt) {
   gLastBookmarkAction = evt.type;
 }
 
 function onBookmarkMove(evt) {
   gLastBookmarkAction = evt.type;
 }
+
+function onRootAdd(evt) {
+  gLastRootAction = evt.type;
+}
+
+function onRootRemove(evt) {
+  gLastRootAction = evt.type;
+}
+
+function onRootChange(evt) {
+  gLastRootAction = evt.data;
+}
--- a/browser/locales/en-US/chrome/browser/aboutSessionRestore.dtd
+++ b/browser/locales/en-US/chrome/browser/aboutSessionRestore.dtd
@@ -9,15 +9,15 @@
 <!ENTITY restorepage.errorTitle     "Well, this is embarrassing.">
 <!ENTITY restorepage.problemDesc    "&brandShortName; is having trouble recovering your windows and tabs. This is usually caused by a recently opened web page.">
 <!ENTITY restorepage.tryThis        "You can try:">
 <!ENTITY restorepage.restoreSome    "Removing one or more tabs that you think may be causing the problem">
 <!ENTITY restorepage.startNew       "Starting an entirely new browsing session">
 
 <!ENTITY restorepage.tryagainButton "Restore">
 <!ENTITY restorepage.restore.access "R">
-<!ENTITY restorepage.cancelButton   "Start New Session">
-<!ENTITY restorepage.cancel.access  "S">
+<!ENTITY restorepage.closeButton    "Close">
+<!ENTITY restorepage.close.access   "C">
 
 <!ENTITY restorepage.restoreHeader  "Restore">
 <!ENTITY restorepage.listHeader     "Windows and Tabs">
 <!-- LOCALIZATION NOTE: &#37;S will be replaced with a number. -->
 <!ENTITY restorepage.windowLabel    "Window &#37;S">
--- a/browser/themes/gnomestripe/devtools/debugger.css
+++ b/browser/themes/gnomestripe/devtools/debugger.css
@@ -11,23 +11,26 @@
 /**
  * Debugger content
  */
 
 #dbg-content {
   padding: 0;
 }
 
+#scripts {
+  max-width: 350px;
+}
+
 /**
  * Lists and headers
  */
 
 .list-item {
   padding: 2px;
-  font: -moz-list;
 }
 
 .list-item.selected {
   background: Highlight;
   color: HighlightText;
 }
 
 .list-item.empty {
@@ -43,16 +46,17 @@
 }
 
 .dbg-stackframe {
   -moz-padding-start: 4px;
   -moz-padding-end: 4px;
 }
 
 .dbg-stackframe-name {
+  -moz-padding-end: 4px;
   font-weight: 600;
 }
 
 /**
  * Properties view
  */
 
 #variables {
@@ -60,27 +64,25 @@
 }
 
 /**
  * Property element details container
  */
 
 .details {
   -moz-margin-start: 10px;
-  font: -moz-list;
 }
 
 /**
  * Scope element
  */
 
 .scope > .title {
   text-shadow: 0 1px #222;
   color: #fff;
-  font: -moz-list;
 }
 
 .scope > .title > .arrow {
   margin-top: -2px;
 }
 
 .scope > .title > .name {
   padding-top: 2px;
--- a/browser/themes/pinstripe/devtools/debugger.css
+++ b/browser/themes/pinstripe/devtools/debugger.css
@@ -13,23 +13,26 @@
 /**
  * Debugger content
  */
 
 #dbg-content {
   padding: 0;
 }
 
+#scripts {
+  max-width: 350px;
+}
+
 /**
  * Lists and headers
  */
 
 .list-item {
   padding: 2px;
-  font: -moz-list;
 }
 
 .list-item.selected {
   background: Highlight;
   color: HighlightText;
 }
 
 .list-item.empty {
@@ -45,16 +48,17 @@
 }
 
 .dbg-stackframe {
   -moz-padding-start: 4px;
   -moz-padding-end: 4px;
 }
 
 .dbg-stackframe-name {
+  -moz-padding-end: 4px;
   font-weight: 600;
 }
 
 /**
  * Properties view
  */
 
 #variables {
@@ -62,27 +66,25 @@
 }
 
 /**
  * Property element details container
  */
 
 .details {
   -moz-margin-start: 10px;
-  font: -moz-list;
 }
 
 /**
  * Scope element
  */
 
 .scope > .title {
   text-shadow: 0 1px #222;
   color: #fff;
-  font: -moz-list;
 }
 
 .scope > .title > .arrow {
   margin-top: -2px;
 }
 
 .scope > .title > .name {
   padding-top: 2px;
--- a/browser/themes/winstripe/devtools/debugger.css
+++ b/browser/themes/winstripe/devtools/debugger.css
@@ -11,23 +11,26 @@
 /**
  * Debugger content
  */
 
 #dbg-content {
   padding: 0;
 }
 
+#scripts {
+  max-width: 350px;
+}
+
 /**
  * Lists and headers
  */
 
 .list-item {
   padding: 2px;
-  font: -moz-list;
 }
 
 .list-item.selected {
   background: Highlight;
   color: HighlightText;
 }
 
 .list-item.empty {
@@ -43,16 +46,17 @@
 }
 
 .dbg-stackframe {
   -moz-padding-start: 4px;
   -moz-padding-end: 4px;
 }
 
 .dbg-stackframe-name {
+  -moz-padding-end: 4px;
   font-weight: 600;
 }
 
 /**
  * Properties view
  */
 
 #variables {
@@ -60,27 +64,25 @@
 }
 
 /**
  * Property element details container
  */
 
 .details {
   -moz-margin-start: 10px;
-  font: -moz-list;
 }
 
 /**
  * Scope element
  */
 
 .scope > .title {
   text-shadow: 0 1px #222;
   color: #fff;
-  font: -moz-list;
 }
 
 .scope > .title > .arrow {
   margin-top: -2px;
 }
 
 .scope > .title > .name {
   padding-top: 2px;
--- a/build/mobile/b2gautomation.py
+++ b/build/mobile/b2gautomation.py
@@ -1,39 +1,60 @@
 # 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/.
 
 import automationutils
+import threading
 import os
+import Queue
 import re
 import socket
 import shutil
 import sys
 import tempfile
 import time
 
 from automation import Automation
 from devicemanager import DeviceManager, NetworkTools
+from mozprocess import ProcessHandlerMixin
+
+
+class LogcatProc(ProcessHandlerMixin):
+    """Process handler for logcat which puts all output in a Queue.
+    """
+
+    def __init__(self, cmd, queue, **kwargs):
+        self.queue = queue
+        kwargs.setdefault('processOutputLine', []).append(self.handle_output)
+        ProcessHandlerMixin.__init__(self, cmd, **kwargs)
+
+    def handle_output(self, line):
+        self.queue.put_nowait(line)
+
 
 class B2GRemoteAutomation(Automation):
     _devicemanager = None
 
     def __init__(self, deviceManager, appName='', remoteLog=None,
                  marionette=None):
         self._devicemanager = deviceManager
         self._appName = appName
         self._remoteProfile = None
         self._remoteLog = remoteLog
         self.marionette = marionette
+        self._is_emulator = False
 
         # Default our product to b2g
         self._product = "b2g"
         Automation.__init__(self)
 
+    def setEmulator(self, is_emulator):
+        self._is_emulator = is_emulator
+
     def setDeviceManager(self, deviceManager):
         self._devicemanager = deviceManager
 
     def setAppName(self, appName):
         self._appName = appName
 
     def setRemoteProfile(self, remoteProfile):
         self._remoteProfile = remoteProfile
@@ -46,16 +67,18 @@ class B2GRemoteAutomation(Automation):
 
     # Set up what we need for the remote environment
     def environment(self, env=None, xrePath=None, crashreporter=True):
         # Because we are running remote, we don't want to mimic the local env
         # so no copying of os.environ
         if env is None:
             env = {}
 
+        # We always hide the results table in B2G; it's much slower if we don't.
+        env['MOZ_HIDE_RESULTS_TABLE'] = '1'
         return env
 
     def checkForCrashes(self, directory, symbolsPath):
         # XXX: This will have to be updated after crash reporting on b2g
         # is in place.
         dumpDir = tempfile.mkdtemp()
         self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
         automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
@@ -114,16 +137,24 @@ class B2GRemoteAutomation(Automation):
             if result:
                 thisSerial = result.group(1)
                 if not serial or thisSerial == serial:
                     serial = thisSerial
                     status = result.group(2)
 
         return (serial, status)
 
+    def restartB2G(self):
+        self._devicemanager.checkCmd(['shell', 'stop', 'b2g'])
+        # Wait for a bit to make sure B2G has completely shut down.
+        time.sleep(5)
+        self._devicemanager.checkCmd(['shell', 'start', 'b2g'])
+        if self._is_emulator:
+            self.marionette.emulator.wait_for_port()
+
     def rebootDevice(self):
         # find device's current status and serial number
         serial, status = self.getDeviceStatus()
 
         # reboot!
         self._devicemanager.checkCmd(['reboot'])
 
         # wait for device to come back to previous status
@@ -148,28 +179,32 @@ class B2GRemoteAutomation(Automation):
         # seem to matter.
 
         instance = self.B2GInstance(self._devicemanager)
 
         # reboot device so it starts up with the mochitest profile
         # XXX:  We could potentially use 'stop b2g' + 'start b2g' to achieve
         # a similar effect; will see which is more stable while attempting
         # to bring up the continuous integration.
-        self.rebootDevice()
+        if self._is_emulator:
+            self.restartB2G()
+        else:
+            self.rebootDevice()
 
         # Infrequently, gecko comes up before networking does, so wait a little
         # bit to give the network time to become available.
         # XXX:  need a more robust mechanism for this
         time.sleep(20)
 
         # Set up port forwarding again for Marionette, since any that
         # existed previously got wiped out by the reboot.
-        self._devicemanager.checkCmd(['forward',
-                                      'tcp:%s' % self.marionette.port,
-                                      'tcp:%s' % self.marionette.port])
+        if not self._is_emulator:
+            self._devicemanager.checkCmd(['forward',
+                                          'tcp:%s' % self.marionette.port,
+                                          'tcp:%s' % self.marionette.port])
 
         # start a marionette session
         session = self.marionette.start_session()
         if 'b2g' not in session:
             raise Exception("bad session value %s returned by start_session" % session)
 
         # start the tests by navigating to the mochitest url
         self.marionette.execute_script("window.location.href='%s';" % self.testURL)
@@ -180,52 +215,53 @@ class B2GRemoteAutomation(Automation):
     class B2GInstance(object):
         """Represents a B2G instance running on a device, and exposes
            some process-like methods/properties that are expected by the
            automation.
         """
 
         def __init__(self, dm):
             self.dm = dm
-            self.lastloglines = []
+            self.logcat_proc = None
+            self.queue = Queue.Queue()
+
+            # Launch logcat in a separate thread, and dump all output lines
+            # into a queue.  The lines in this queue are
+            # retrieved and returned by accessing the stdout property of
+            # this class.
+            cmd = [self.dm.adbPath]
+            if self.dm.deviceSerial:
+                cmd.extend(['-s', self.dm.deviceSerial])
+            cmd.append('logcat')
+            proc = threading.Thread(target=self._save_logcat_proc, args=(cmd, self.queue))
+            proc.daemon = True
+            proc.start()
+
+        def _save_logcat_proc(self, cmd, queue):
+            self.logcat_proc = LogcatProc(cmd, queue)
+            self.logcat_proc.run()
+            self.logcat_proc.waitForFinish()
+            self.logcat_proc = None
 
         @property
         def pid(self):
             # a dummy value to make the automation happy
             return 0
 
         @property
         def stdout(self):
-            # Return any part of logcat output that wasn't returned
-            # previously.  This is done by fetching about the last 50
-            # lines of the log (logcat -t 50 generally fetches 50-58 lines),
-            # and comparing against the previous set to find new lines.
-            t = self.dm.runCmd(['logcat', '-t', '50']).stdout.read()
-            if t == None: return ''
-
-            t = t.strip('\n').strip()
-            loglines = t.split('\n')
-            line_index = 0
-
-            # If there are more than 50 lines, we skip the first 20; this
-            # is because the number of lines returned
-            # by logcat -t 50 varies (usually between 50 and 58).
-            log_index = 20 if len(loglines) > 50 else 0
-
-            for index, line in enumerate(loglines[log_index:]):
-                line_index = index + log_index + 1
+            # Return any lines in the queue used by the
+            # logcat process handler.
+            lines = []
+            while True:
                 try:
-                    self.lastloglines.index(line)
-                except ValueError:
+                    lines.append(self.queue.get_nowait())
+                except Queue.Empty:
                     break
-
-            newoutput = '\n'.join(loglines[line_index:])
-            self.lastloglines = loglines
-
-            return newoutput
+            return '\n'.join(lines)
 
         def wait(self, timeout = None):
             # this should never happen
             raise Exception("'wait' called on B2GInstance")
 
         def kill(self):
             # this should never happen
             raise Exception("'kill' called on B2GInstance")
--- a/build/mobile/sutagent/android/DoCommand.java
+++ b/build/mobile/sutagent/android/DoCommand.java
@@ -2375,106 +2375,92 @@ private void CancelNotification()
         {
         e.printStackTrace();
         }
         return(sRet);
     }
 
     public String KillProcess(String sProcName, OutputStream out)
         {
-        String sTmp = "";
-        String sCmd = "kill";
-
         String sRet = sErrorPrefix + "Unable to kill " + sProcName + "\n";
         ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE);
         List <ActivityManager.RunningAppProcessInfo> lProcesses = aMgr.getRunningAppProcesses();
         int lcv = 0;
-        String strProcName = "";
-        int    nPID = 0;
+        String sFoundProcName = "";
         int nProcs = 0;
-
-        if (lProcesses != null) 
+        boolean bFoundAppProcess = false;
+
+        if (lProcesses != null)
             nProcs = lProcesses.size();
 
         for (lcv = 0; lcv < nProcs; lcv++)
             {
             if (lProcesses.get(lcv).processName.contains(sProcName))
                 {
-                strProcName = lProcesses.get(lcv).processName;
-                nPID = lProcesses.get(lcv).pid;
-                sRet = sErrorPrefix + "Failed to kill " + nPID + " " + strProcName + "\n";
-
-                sCmd += " " + nPID;
+                sFoundProcName = lProcesses.get(lcv).processName;
+                bFoundAppProcess = true;
 
                 try
                     {
-                    pProc = Runtime.getRuntime().exec(this.getSuArgs(sCmd));
+                    pProc = Runtime.getRuntime().exec(this.getSuArgs("kill " + lProcesses.get(lcv).pid));
                     RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
                     outThrd.start();
                     outThrd.join(15000);
-                    sTmp = outThrd.strOutput;
+                    String sTmp = outThrd.strOutput;
                     Log.e("KILLPROCESS", sTmp);
-                    if (outThrd.nExitCode == 0) {
-                        sRet = "Successfully killed " + nPID + " " + strProcName + "\n";
-                        nPID = 0;
-                        break;
-                    } else {
-                        sRet = sErrorPrefix + "Failed to kill " + nPID + " " + strProcName + "\n";
-                    }
                     }
                 catch (IOException e)
                     {
                     sRet = e.getMessage();
                     e.printStackTrace();
                     }
                 catch (InterruptedException e)
                     {
                     e.printStackTrace();
                     }
-
-                // Give the messages a chance to be processed
-                try {
-                    Thread.sleep(2000);
-                    }
-                catch (InterruptedException e)
-                    {
-                    e.printStackTrace();
-                    }
-                break;
                 }
             }
 
-        if (nPID > 0)
+        if (bFoundAppProcess)
             {
-            sRet = "Successfully killed " + nPID + " " + strProcName + "\n";
+            // Give the messages a chance to be processed
+            try {
+                Thread.sleep(2000);
+                }
+            catch (InterruptedException e)
+                {
+                e.printStackTrace();
+                }
+
+            sRet = "Successfully killed " + sProcName + "\n";
             lProcesses = aMgr.getRunningAppProcesses();
             nProcs = 0;
-            if (lProcesses != null) 
+            if (lProcesses != null)
                 nProcs = lProcesses.size();
             for (lcv = 0; lcv < nProcs; lcv++)
                 {
                 if (lProcesses.get(lcv).processName.contains(sProcName))
                     {
-                    sRet = sErrorPrefix + "Unable to kill " + nPID + " " + strProcName + "\n";
+                    sRet = sErrorPrefix + "Unable to kill " + sProcName + " (couldn't kill " + sFoundProcName +")\n";
                     break;
                     }
                 }
             }
         else
             {
             // To kill processes other than Java applications - processes
             // like xpcshell - a different strategy is necessary: use ps
             // to find the process' PID.
             try
                 {
                 pProc = Runtime.getRuntime().exec("ps");
                 RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
                 outThrd.start();
                 outThrd.join(10000);
-                sTmp = outThrd.strOutput;
+                String sTmp = outThrd.strOutput;
                 StringTokenizer stokLines = new StringTokenizer(sTmp, "\n");
                 while(stokLines.hasMoreTokens())
                     {
                     String sLine = stokLines.nextToken();
                     StringTokenizer stokColumns = new StringTokenizer(sLine, " \t\n");
                     stokColumns.nextToken();
                     String sPid = stokColumns.nextToken();
                     stokColumns.nextToken();
@@ -2485,17 +2471,17 @@ private void CancelNotification()
                     stokColumns.nextToken();
                     String sName = null;
                     if (stokColumns.hasMoreTokens())
                         {
                         sName = stokColumns.nextToken();
                         if (sName.contains(sProcName))
                             {
                             NewKillProc(sPid, out);
-                            sRet = "Successfully killed " + sPid + " " + sName + "\n";
+                            sRet = "Successfully killed " + sName + "\n";
                             }
                         }
                     }
                 }
             catch (Exception e)
                 {
                 e.printStackTrace();
                 }
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -2437,19 +2437,19 @@ nsScriptSecurityManager::doGetObjectPrin
             if (result) {
                 break;
             }
         } else {
             nsISupports *priv;
             if (!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
                                      JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
                 priv = (nsISupports *) js::GetObjectPrivate(aObj);
-            } else if ((jsClass->flags & JSCLASS_IS_DOMJSCLASS) &&
+            } else if (IsDOMClass(jsClass) &&
                        DOMJSClass::FromJSClass(jsClass)->mDOMObjectIsISupports) {
-                priv = UnwrapDOMObject<nsISupports>(aObj, jsClass);
+                priv = UnwrapDOMObject<nsISupports>(aObj);
             } else {
                 priv = nsnull;
             }
 
 #ifdef DEBUG
             if (aAllowShortCircuit) {
                 nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
                     do_QueryInterface(priv);
--- a/chrome/src/nsChromeRegistryChrome.cpp
+++ b/chrome/src/nsChromeRegistryChrome.cpp
@@ -27,17 +27,17 @@
 #include "nsUnicharUtils.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsZipArchive.h"
 
 #include "mozilla/LookAndFeel.h"
 
 #include "nsICommandLine.h"
 #include "nsILocaleService.h"
-#include "nsILocalFile.h"
+#include "nsIFile.h"
 #include "nsIObserverService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsIResProtocolHandler.h"
 #include "nsIScriptError.h"
 #include "nsIVersionComparator.h"
 #include "nsIXPConnect.h"
 #include "nsIXULAppInfo.h"
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -75,16 +75,17 @@ MOZ_DEBUG_SYMBOLS = @MOZ_DEBUG_SYMBOLS@
 MOZ_DEBUG_ENABLE_DEFS		= @MOZ_DEBUG_ENABLE_DEFS@
 MOZ_DEBUG_DISABLE_DEFS	= @MOZ_DEBUG_DISABLE_DEFS@
 MOZ_DEBUG_FLAGS	= @MOZ_DEBUG_FLAGS@
 MOZ_DEBUG_LDFLAGS=@MOZ_DEBUG_LDFLAGS@
 MOZ_EXTENSIONS  = @MOZ_EXTENSIONS@
 MOZ_JSDEBUGGER  = @MOZ_JSDEBUGGER@
 MOZ_IPDL_TESTS 	= @MOZ_IPDL_TESTS@
 MOZ_MEMORY      = @MOZ_MEMORY@
+MOZ_JEMALLOC    = @MOZ_JEMALLOC@
 MOZ_PROFILING   = @MOZ_PROFILING@
 MOZ_ENABLE_PROFILER_SPS = @MOZ_ENABLE_PROFILER_SPS@
 MOZ_JPROF       = @MOZ_JPROF@
 MOZ_SHARK       = @MOZ_SHARK@
 MOZ_CALLGRIND   = @MOZ_CALLGRIND@
 MOZ_VALGRIND    = @MOZ_VALGRIND@
 MOZ_VTUNE       = @MOZ_VTUNE@
 MOZ_ETW         = @MOZ_ETW@
--- a/configure.in
+++ b/configure.in
@@ -3961,28 +3961,30 @@ LDFLAGS="$LDFLAGS $DSO_PIC_CFLAGS $DSO_L
 AC_CACHE_CHECK(for __thread keyword for TLS variables,
                ac_cv_thread_keyword,
                [AC_TRY_LINK([__thread bool tlsIsMainThread = false;],
                             [return tlsIsMainThread;],
                             ac_cv_thread_keyword=yes,
                             ac_cv_thread_keyword=no)])
 LDFLAGS=$_SAVE_LDFLAGS
 # The custom dynamic linker doesn't support TLS variables
+MOZ_TLS=
 if test "$ac_cv_thread_keyword" = yes -a "$MOZ_LINKER" != 1; then
   # mips builds fail with TLS variables because of a binutils bug.
   # See bug 528687
   case "${target}" in
     mips*-*)
       :
       ;;
     *-android*|*-linuxandroid*)
       :
       ;;
     *)
       AC_DEFINE(HAVE_THREAD_TLS_KEYWORD)
+      MOZ_TLS=1
       ;;
   esac
 fi
 
 dnl Using the custom linker on ARMv6 requires 16k alignment of ELF segments.
 if test -n "$MOZ_LINKER"; then
   if test "$CPU_ARCH" = arm; then
     dnl Determine the target ARM architecture (5 for ARMv5, v5T, v5E, etc.; 6 for ARMv6, v6K, etc.)
@@ -7272,16 +7274,19 @@ else
       ;;
     *)
       AC_MSG_ERROR([Unexpected pointer size])
       ;;
     esac
   fi
 
   AC_DEFINE(MOZ_MEMORY)
+  if test -n "$MOZ_JEMALLOC"; then
+    AC_DEFINE(MOZ_JEMALLOC)
+  fi
   if test "x$MOZ_DEBUG" = "x1"; then
     AC_DEFINE(MOZ_MEMORY_DEBUG)
   fi
   dnl The generic feature tests that determine how to compute ncpus are long and
   dnl complicated.  Therefore, simply define special cpp variables for the
   dnl platforms we have special knowledge of.
   case "${target}" in
   *-darwin*)
@@ -7327,16 +7332,17 @@ else
     export DLLFLAGS
     ;;
   *)
     AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
     ;;
   esac
 fi # MOZ_MEMORY
 AC_SUBST(MOZ_MEMORY)
+AC_SUBST(MOZ_JEMALLOC)
 AC_SUBST(MOZ_GLUE_LDFLAGS)
 AC_SUBST(MOZ_GLUE_PROGRAM_LDFLAGS)
 AC_SUBST(WIN32_CRT_LIBS)
 dnl Need to set this for make because NSS doesn't have configure
 AC_SUBST(DLLFLAGS)
 
 dnl We need to wrap dlopen and related functions on Android because we use
 dnl our own linker.
@@ -9116,16 +9122,52 @@ if test "$CAIRO_FEATURES_H"; then
   if cmp -s $CAIRO_FEATURES_H "$CAIRO_FEATURES_H".orig; then
     echo "$CAIRO_FEATURES_H is unchanged"
     mv -f "$CAIRO_FEATURES_H".orig "$CAIRO_FEATURES_H" 2> /dev/null
   else
     rm -f "$CAIRO_FEATURES_H".orig 2> /dev/null
   fi
 fi
 
+# Run jemalloc configure script
+
+if test "$MOZ_JEMALLOC" -a "$MOZ_MEMORY"; then
+  ac_configure_args="$_SUBDIR_CONFIG_ARGS --build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_"
+  if test "$OS_ARCH" = "Linux"; then
+    MANGLE="malloc calloc valloc free realloc memalign posix_memalign malloc_usable_size"
+    MANGLED=
+    JEMALLOC_WRAPPER=
+    if test -n "$_WRAP_MALLOC"; then
+      JEMALLOC_WRAPPER=__wrap_
+    fi
+    for mangle in ${MANGLE}; do
+      if test -n "$MANGLED"; then
+        MANGLED="$mangle:$JEMALLOC_WRAPPER$mangle,$MANGLED"
+      else
+        MANGLED="$mangle:$JEMALLOC_WRAPPER$mangle"
+      fi
+    done
+    ac_configure_args="$ac_configure_args --with-mangling=$MANGLED"
+  fi
+  unset CONFIG_FILES
+  if test -z "$MOZ_TLS"; then
+    ac_configure_args="$ac_configure_args --disable-tls"
+  fi
+  EXTRA_CFLAGS="$CFLAGS"
+  for var in AS CC CXX CPP LD AR RANLIB STRIP CPPFLAGS EXTRA_CFLAGS LDFLAGS; do
+    ac_configure_args="$ac_configure_args $var='`eval echo \\${${var}}`'"
+  done
+  ac_configure_args="$ac_configure_args je_cv_static_page_shift=12"
+  _save_cache_file="$cache_file"
+  cache_file=$_objdir/memory/jemalloc/src/config.cache
+  AC_OUTPUT_SUBDIRS(memory/jemalloc/src)
+  cache_file="$_save_cache_file"
+  ac_configure_args="$_SUBDIR_CONFIG_ARGS"
+fi
+
 dnl Build libunwind for Android profiling builds
 if test "$OS_TARGET" = "Android" -a "$MOZ_PROFILING"; then
   old_ac_configure_arg="$ac_configure_args"
   ac_configure_args="--build=${build} --host=${target_alias} --disable-shared --enable-block-signals=no"
   if test "$MOZ_DEBUG"; then
     ac_configure_args="$ac_configure_args --enable-debug"
   fi
   if test "$DSO_PIC_CFLAGS"; then
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -87,18 +87,18 @@ class Loader;
 
 namespace dom {
 class Link;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID \
-{ 0x7bac702d, 0xca67, 0x4ce1, \
- { 0x80, 0x3c, 0x35, 0xde, 0x81, 0x26, 0x04, 0x97 } }
+{ 0x077dcff0, 0x400d, 0x4d3c, \
+  { 0xbd, 0x4d, 0x5f, 0xd5, 0xe1, 0xa6, 0x63, 0x07 } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 // Enum for requesting a particular type of document when creating a doc
 enum DocumentFlavor {
   DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
   DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
@@ -497,19 +497,24 @@ public:
   virtual nsIDocument *GetSubDocumentFor(nsIContent *aContent) const = 0;
 
   /**
    * Find the content node for which aDocument is a sub document.
    */
   virtual Element* FindContentForSubDocument(nsIDocument* aDocument) const = 0;
 
   /**
+   * Return the doctype for this document.
+   */
+  nsIContent* GetDocumentType() const;
+
+  /**
    * Return the root element for this document.
    */
-  Element *GetRootElement() const;
+  Element* GetRootElement() const;
 
 protected:
   virtual Element *GetRootElementInternal() const = 0;
 
 public:
   // Get the root <html> element, or return null if there isn't one (e.g.
   // if the root isn't <html>)
   Element* GetHtmlElement();
--- a/content/base/src/FileIOObject.cpp
+++ b/content/base/src/FileIOObject.cpp
@@ -33,24 +33,26 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEve
 NS_IMPL_CYCLE_COLLECTION_CLASS(FileIOObject)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FileIOObject,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mProgressNotifier)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(abort)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(error)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(progress)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mError)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FileIOObject,
                                                 nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressNotifier)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(abort)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(error)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(progress)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mError)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 FileIOObject::FileIOObject()
   : mProgressEventWasDelayed(false),
     mTimerIsActive(false),
     mReadyState(0),
     mTotal(0), mTransferred(0)
 {}
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -29,16 +29,23 @@ EXPORTS		= \
 		nsRange.h \
 		nsScriptLoader.h \
 		nsStubDocumentObserver.h \
 		nsStubImageDecoderObserver.h \
 		nsStubMutationObserver.h \
 		nsTextFragment.h \
 		mozAutoDocUpdate.h \
 		nsFrameMessageManager.h \
+		nsAttrAndChildArray.h \
+		nsAttrValue.h \
+		nsCrossSiteListenerProxy.h \
+		nsDOMAttributeMap.h \
+		nsGenericElement.h \
+		nsMappedAttributeElement.h \
+		nsStyledElement.h \
 		$(NULL)
 
 EXPORTS_NAMESPACES = mozilla/dom
 
 EXPORTS_mozilla/dom = \
   Link.h \
   $(NULL)
 
--- a/content/base/src/nsContentAreaDragDrop.cpp
+++ b/content/base/src/nsContentAreaDragDrop.cpp
@@ -162,17 +162,17 @@ nsContentAreaDragDropDataProvider::SaveU
 // This is our nsIFlavorDataProvider callback. There are several
 // assumptions here that make this work:
 //
 // 1. Someone put a kFilePromiseURLMime flavor into the transferable
 //    with the source URI of the file to save (as a string). We did
 //    that in AddStringsToDataTransfer.
 //
 // 2. Someone put a kFilePromiseDirectoryMime flavor into the
-//    transferable with an nsILocalFile for the directory we are to
+//    transferable with an nsIFile for the directory we are to
 //    save in. That has to be done by platform-specific code (in
 //    widget), which gets the destination directory from
 //    OS-specific drag information.
 //
 NS_IMETHODIMP
 nsContentAreaDragDropDataProvider::GetFlavorData(nsITransferable *aTransferable,
                                                  const char *aFlavor,
                                                  nsISupports **aData,
@@ -213,28 +213,28 @@ nsContentAreaDragDropDataProvider::GetFl
       return NS_ERROR_FAILURE;
 
     // get the target directory from the kFilePromiseDirectoryMime
     // flavor
     nsCOMPtr<nsISupports> dirPrimitive;
     dataSize = 0;
     aTransferable->GetTransferData(kFilePromiseDirectoryMime,
                                    getter_AddRefs(dirPrimitive), &dataSize);
-    nsCOMPtr<nsILocalFile> destDirectory = do_QueryInterface(dirPrimitive);
+    nsCOMPtr<nsIFile> destDirectory = do_QueryInterface(dirPrimitive);
     if (!destDirectory)
       return NS_ERROR_FAILURE;
 
     nsCOMPtr<nsIFile> file;
     rv = destDirectory->Clone(getter_AddRefs(file));
     NS_ENSURE_SUCCESS(rv, rv);
 
     file->Append(targetFilename);
 
     rv = SaveURIToFile(sourceURLString, file);
-    // send back an nsILocalFile
+    // send back an nsIFile
     if (NS_SUCCEEDED(rv)) {
       CallQueryInterface(file, aData);
       *aDataLen = sizeof(nsIFile*);
     }
   }
 
   return rv;
 }
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -63,16 +63,17 @@
 #include "mozAutoDocUpdate.h"
 #include "nsIWebNavigation.h"
 #include "nsIDocumentLoader.h"
 #include "nsICachingChannel.h"
 #include "nsICacheEntryDescriptor.h"
 #include "nsGenericHTMLElement.h"
 #include "nsHTMLDNSPrefetch.h"
 #include "nsISupportsPrimitives.h"
+#include "nsIObserverService.h"
 #include "mozilla/Preferences.h"
 #include "nsParserConstants.h"
 
 using namespace mozilla;
 
 PRLogModuleInfo* gContentSinkLogModuleInfo;
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsContentSink)
--- a/content/base/src/nsDOMAttributeMap.h
+++ b/content/base/src/nsDOMAttributeMap.h
@@ -9,17 +9,16 @@
 
 #ifndef nsDOMAttributeMap_h___
 #define nsDOMAttributeMap_h___
 
 #include "nsIDOMNamedNodeMap.h"
 #include "nsString.h"
 #include "nsRefPtrHashtable.h"
 #include "nsCycleCollectionParticipant.h"
-#include "prbit.h"
 #include "nsIDOMNode.h"
 
 class nsIAtom;
 class nsIContent;
 class nsDOMAttribute;
 class nsINodeInfo;
 class nsIDocument;
 
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -594,22 +594,18 @@ nsDOMFileFile::Initialize(nsISupports* a
     JSString* str = JS_ValueToString(aCx, aArgv[0]);
     NS_ENSURE_TRUE(str, NS_ERROR_XPC_BAD_CONVERT_JS);
 
     nsDependentJSString xpcomStr;
     if (!xpcomStr.init(aCx, str)) {
       return NS_ERROR_XPC_BAD_CONVERT_JS;
     }
 
-    nsCOMPtr<nsILocalFile> localFile;
-    rv = NS_NewLocalFile(xpcomStr, false, getter_AddRefs(localFile));
+    rv = NS_NewLocalFile(xpcomStr, false, getter_AddRefs(file));
     NS_ENSURE_SUCCESS(rv, rv);
-
-    file = do_QueryInterface(localFile);
-    NS_ASSERTION(file, "This should never happen");
   }
 
   bool exists;
   rv = file->Exists(&exists);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(exists, NS_ERROR_FILE_NOT_FOUND);
 
   bool isDir;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -4290,32 +4290,35 @@ nsDocument::StyleRuleRemoved(nsIStyleShe
   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleRemoved,
                                (this, aStyleSheet, aStyleRule));
 }
 
 
 //
 // nsIDOMDocument interface
 //
+nsIContent*
+nsIDocument::GetDocumentType() const
+{
+  for (nsIContent* child = GetFirstChild();
+       child;
+       child = child->GetNextSibling()) {
+    if (child->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) {
+      return child;
+    }
+  }
+  return NULL;
+}
+
 NS_IMETHODIMP
 nsDocument::GetDoctype(nsIDOMDocumentType** aDoctype)
 {
-  NS_ENSURE_ARG_POINTER(aDoctype);
-
-  *aDoctype = nsnull;
-  PRInt32 i, count;
-  count = mChildren.ChildCount();
-  for (i = 0; i < count; i++) {
-    CallQueryInterface(mChildren.ChildAt(i), aDoctype);
-
-    if (*aDoctype) {
-      return NS_OK;
-    }
-  }
-
+  MOZ_ASSERT(aDoctype);
+  nsCOMPtr<nsIDOMDocumentType> doctype = do_QueryInterface(GetDocumentType());
+  doctype.forget(aDoctype);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::GetImplementation(nsIDOMDOMImplementation** aImplementation)
 {
   if (!mDOMImplementation) {
     nsCOMPtr<nsIURI> uri;
@@ -9650,17 +9653,17 @@ nsDocument::GetMozVisibilityState(nsAStr
   PR_STATIC_ASSERT(NS_ARRAY_LENGTH(states) == eVisibilityStateCount);
   aState.AssignASCII(states[mVisibilityState]);
   return NS_OK;
 }
 
 /* virtual */ void
 nsIDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
 {
-  aWindowSizes->mDOM +=
+  aWindowSizes->mDOMOther +=
     nsINode::SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
 
   if (mPresShell) {
     mPresShell->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf,
                                     &aWindowSizes->mLayoutArenas,
                                     &aWindowSizes->mLayoutStyleSets,
                                     &aWindowSizes->mLayoutTextRuns,
                                     &aWindowSizes->mLayoutPresContext);
@@ -9669,17 +9672,17 @@ nsIDocument::DocSizeOfExcludingThis(nsWi
   // Measurement of the following members may be added later if DMD finds it
   // is worthwhile:
   // - many!
 }
 
 void
 nsIDocument::DocSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
 {
-  aWindowSizes->mDOM += aWindowSizes->mMallocSizeOf(this);
+  aWindowSizes->mDOMOther += aWindowSizes->mMallocSizeOf(this);
   DocSizeOfExcludingThis(aWindowSizes);
 }
 
 static size_t
 SizeOfStyleSheetsElementIncludingThis(nsIStyleSheet* aStyleSheet,
                                       nsMallocSizeOfFun aMallocSizeOf,
                                       void* aData)
 {
@@ -9701,24 +9704,44 @@ void
 nsDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
 {
   nsIDocument::DocSizeOfExcludingThis(aWindowSizes);
 
   for (nsIContent* node = nsINode::GetFirstChild();
        node;
        node = node->GetNextNode(this))
   {
-    aWindowSizes->mDOM +=
-      node->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
+    size_t nodeSize = node->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
+    size_t* p;
+
+    switch (node->NodeType()) {
+    case nsIDOMNode::ELEMENT_NODE:
+      p = &aWindowSizes->mDOMElementNodes;
+      break;
+    case nsIDOMNode::TEXT_NODE:
+      p = &aWindowSizes->mDOMTextNodes;
+      break;
+    case nsIDOMNode::CDATA_SECTION_NODE:
+      p = &aWindowSizes->mDOMCDATANodes;
+      break;
+    case nsIDOMNode::COMMENT_NODE:
+      p = &aWindowSizes->mDOMCommentNodes;
+      break;
+    default:
+      p = &aWindowSizes->mDOMOther;
+      break;
+    }
+
+    *p += nodeSize;
   }
 
   aWindowSizes->mStyleSheets +=
     mStyleSheets.SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
                                      aWindowSizes->mMallocSizeOf); 
-  aWindowSizes->mDOM +=
+  aWindowSizes->mDOMOther +=
     mAttrStyleSheet ?
     mAttrStyleSheet->DOMSizeOfIncludingThis(aWindowSizes->mMallocSizeOf) :
     0;
 
   // Measurement of the following members may be added later if DMD finds it
   // is worthwhile:
   // - many!
 }
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -16,21 +16,24 @@
 #include "nsIJSContextStack.h"
 #include "nsIXULRuntime.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsIProtocolHandler.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIJSRuntimeService.h"
 #include "xpcpublic.h"
+#include "mozilla/Preferences.h"
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
 
+using namespace mozilla;
+
 static bool
 IsChromeProcess()
 {
   nsCOMPtr<nsIXULRuntime> rt = do_GetService("@mozilla.org/xre/runtime;1");
   if (!rt)
     return true;
 
   PRUint32 type;
@@ -154,17 +157,17 @@ nsFrameMessageManager::LoadFrameScript(c
 NS_IMETHODIMP
 nsFrameMessageManager::RemoveDelayedFrameScript(const nsAString& aURL)
 {
   mPendingScripts.RemoveElement(aURL);
   return NS_OK;
 }
 
 static JSBool
-JSONCreator(const jschar* aBuf, uint32 aLen, void* aData)
+JSONCreator(const jschar* aBuf, uint32_t aLen, void* aData)
 {
   nsAString* result = static_cast<nsAString*>(aData);
   result->Append(static_cast<const PRUnichar*>(aBuf),
                  static_cast<PRUint32>(aLen));
   return true;
 }
 
 void
@@ -774,17 +777,17 @@ nsFrameScriptExecutor::LoadFrameScriptIn
     {
       // Need to scope JSAutoRequest to happen after Push but before Pop,
       // at least for now. See bug 584673.
       JSAutoRequest ar(mCx);
       JSObject* global = nsnull;
       mGlobal->GetJSObject(&global);
       JSAutoEnterCompartment ac;
       if (global && ac.enter(mCx, global)) {
-        uint32 oldopts = JS_GetOptions(mCx);
+        uint32_t oldopts = JS_GetOptions(mCx);
         JS_SetOptions(mCx, oldopts | JSOPTION_NO_SCRIPT_RVAL);
 
         JSScript* script =
           JS_CompileUCScriptForPrincipals(mCx, nsnull,
                                           nsJSPrincipals::get(mPrincipal),
                                           static_cast<const jschar*>(dataString.get()),
                                           dataString.Length(),
                                           url.get(), 1);
@@ -826,19 +829,20 @@ nsFrameScriptExecutor::InitTabChildGloba
 
   JSContext* cx = JS_NewContext(rt, 8192);
   NS_ENSURE_TRUE(cx, false);
 
   mCx = cx;
 
   nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
 
+  bool allowXML = Preferences::GetBool("javascript.options.xml.chrome");
   JS_SetOptions(cx, JS_GetOptions(cx) |
                     JSOPTION_PRIVATE_IS_NSISUPPORTS |
-                    JSOPTION_ALLOW_XML);
+                    (allowXML ? JSOPTION_ALLOW_XML : 0));
   JS_SetVersion(cx, JSVERSION_LATEST);
   JS_SetErrorReporter(cx, ContentScriptErrorReporter);
 
   xpc_LocalizeContext(cx);
 
   JSAutoRequest ar(cx);
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -3955,78 +3955,71 @@ nsGenericElement::SaveSubtreeState()
 
 // Generic DOMNode implementations
 
 // When replacing, aRefChild is the content being replaced; when
 // inserting it's the content before which we're inserting.  In the
 // latter case it may be null.
 static
 bool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
-                        bool aIsReplace, nsINode* aRefChild)
-{
-  NS_PRECONDITION(aNewChild, "Must have new child");
-  NS_PRECONDITION(!aIsReplace || aRefChild,
-                  "Must have ref content for replace");
-  NS_PRECONDITION(aParent->IsNodeOfType(nsINode::eDOCUMENT) ||
-                  aParent->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT) ||
-                  aParent->IsElement(),
-                  "Nodes that are not documents, document fragments or "
-                  "elements can't be parents!");
+                      bool aIsReplace, nsINode* aRefChild)
+{
+  MOZ_ASSERT(aNewChild, "Must have new child");
+  MOZ_ASSERT_IF(aIsReplace, aRefChild);
+  MOZ_ASSERT(aParent);
+  MOZ_ASSERT(aParent->IsNodeOfType(nsINode::eDOCUMENT) ||
+             aParent->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT) ||
+             aParent->IsElement(),
+             "Nodes that are not documents, document fragments or elements "
+             "can't be parents!");
 
   // A common case is that aNewChild has no kids, in which case
   // aParent can't be a descendant of aNewChild unless they're
   // actually equal to each other.  Fast-path that case, since aParent
   // could be pretty deep in the DOM tree.
-  if (aParent &&
-      (aNewChild == aParent ||
-       (aNewChild->GetFirstChild() &&
-        nsContentUtils::ContentIsDescendantOf(aParent, aNewChild)))) {
+  if (aNewChild == aParent ||
+      (aNewChild->GetFirstChild() &&
+       nsContentUtils::ContentIsDescendantOf(aParent, aNewChild))) {
     return false;
   }
 
   // The allowed child nodes differ for documents and elements
   switch (aNewChild->NodeType()) {
   case nsIDOMNode::COMMENT_NODE :
   case nsIDOMNode::PROCESSING_INSTRUCTION_NODE :
     // OK in both cases
     return true;
   case nsIDOMNode::TEXT_NODE :
   case nsIDOMNode::CDATA_SECTION_NODE :
   case nsIDOMNode::ENTITY_REFERENCE_NODE :
-    // Only allowed under elements
-    return aParent != nsnull;
+    // Allowed under Elements and DocumentFragments
+    return aParent->NodeType() != nsIDOMNode::DOCUMENT_NODE;
   case nsIDOMNode::ELEMENT_NODE :
     {
       if (!aParent->IsNodeOfType(nsINode::eDOCUMENT)) {
         // Always ok to have elements under other elements or document fragments
         return true;
       }
 
-      Element* rootElement =
-        static_cast<nsIDocument*>(aParent)->GetRootElement();
+      nsIDocument* parentDocument = static_cast<nsIDocument*>(aParent);
+      Element* rootElement = parentDocument->GetRootElement();
       if (rootElement) {
         // Already have a documentElement, so this is only OK if we're
         // replacing it.
         return aIsReplace && rootElement == aRefChild;
       }
 
       // We don't have a documentElement yet.  Our one remaining constraint is
       // that the documentElement must come after the doctype.
       if (!aRefChild) {
         // Appending is just fine.
         return true;
       }
 
-      // Now grovel for a doctype
-      nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aParent);
-      NS_ASSERTION(doc, "Shouldn't happen");
-      nsCOMPtr<nsIDOMDocumentType> docType;
-      doc->GetDoctype(getter_AddRefs(docType));
-      nsCOMPtr<nsIContent> docTypeContent = do_QueryInterface(docType);
-      
+      nsIContent* docTypeContent = parentDocument->GetDocumentType();
       if (!docTypeContent) {
         // It's all good.
         return true;
       }
 
       PRInt32 doctypeIndex = aParent->IndexOf(docTypeContent);
       PRInt32 insertIndex = aParent->IndexOf(aRefChild);
 
@@ -4038,30 +4031,26 @@ bool IsAllowedAsChild(nsIContent* aNewCh
     }
   case nsIDOMNode::DOCUMENT_TYPE_NODE :
     {
       if (!aParent->IsNodeOfType(nsINode::eDOCUMENT)) {
         // doctypes only allowed under documents
         return false;
       }
 
-      nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aParent);
-      NS_ASSERTION(doc, "Shouldn't happen");
-      nsCOMPtr<nsIDOMDocumentType> docType;
-      doc->GetDoctype(getter_AddRefs(docType));
-      nsCOMPtr<nsIContent> docTypeContent = do_QueryInterface(docType);
+      nsIDocument* parentDocument = static_cast<nsIDocument*>(aParent);
+      nsIContent* docTypeContent = parentDocument->GetDocumentType();
       if (docTypeContent) {
         // Already have a doctype, so this is only OK if we're replacing it
         return aIsReplace && docTypeContent == aRefChild;
       }
 
       // We don't have a doctype yet.  Our one remaining constraint is
       // that the doctype must come before the documentElement.
-      Element* rootElement =
-        static_cast<nsIDocument*>(aParent)->GetRootElement();
+      Element* rootElement = parentDocument->GetRootElement();
       if (!rootElement) {
         // It's all good
         return true;
       }
 
       if (!aRefChild) {
         // Trying to append a doctype, but have a documentElement
         return false;
--- 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_bug761120.html \
 		test_XHR_onuploadprogress.html \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
 # This test fails on the Mac for some reason
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug761120.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=761120
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 761120</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=761120">Mozilla Bug 761120</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 761120 **/
+var doc = document.implementation.createHTMLDocument("title");
+try {
+  doc.appendChild(doc.createTextNode("text"));
+  ok(false, "Didn't throw");
+} catch (e) {
+  is(e.name, "HierarchyRequestError");
+}
+
+var el = document.createElement("div");
+var text = document.createTextNode("text");
+el.appendChild(text);
+is(el.firstChild, text);
+
+var df = document.createDocumentFragment();
+text = document.createTextNode("text");
+df.appendChild(text);
+is(df.firstChild, text);
+</script>
+</pre>
+</body>
+</html>
--- a/content/canvas/public/DocumentRendererChild.h
+++ b/content/canvas/public/DocumentRendererChild.h
@@ -1,17 +1,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 mozilla_dom_DocumentRendererChild
 #define mozilla_dom_DocumentRendererChild
 
 #include "mozilla/ipc/PDocumentRendererChild.h"
-#include "nsICanvasRenderingContextInternal.h"
 #include "nsString.h"
 #include "gfxContext.h"
 
 class nsIDOMWindow;
 
 namespace mozilla {
 namespace ipc {
 
--- a/content/canvas/public/DocumentRendererParent.h
+++ b/content/canvas/public/DocumentRendererParent.h
@@ -1,21 +1,22 @@
 /* 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_dom_DocumentRendererParent
 #define mozilla_dom_DocumentRendererParent
 
 #include "mozilla/ipc/PDocumentRendererParent.h"
-#include "nsICanvasRenderingContextInternal.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "gfxContext.h"
 
+class nsICanvasRenderingContextInternal;
+
 namespace mozilla {
 namespace ipc {
 
 class DocumentRendererParent : public PDocumentRendererParent
 {
 public:
     DocumentRendererParent();
     virtual ~DocumentRendererParent();
--- a/content/canvas/public/nsICanvasRenderingContextInternal.h
+++ b/content/canvas/public/nsICanvasRenderingContextInternal.h
@@ -4,24 +4,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsICanvasRenderingContextInternal_h___
 #define nsICanvasRenderingContextInternal_h___
 
 #include "nsISupports.h"
 #include "nsIInputStream.h"
 #include "nsIDocShell.h"
+#include "nsHTMLCanvasElement.h"
 #include "gfxPattern.h"
 #include "mozilla/RefPtr.h"
 
 #define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
-{ 0xffb42d3c, 0x8281, 0x44c8, \
-  { 0xac, 0xba, 0x73, 0x15, 0x31, 0xaa, 0xe5, 0x07 } }
+{ 0x8b8da863, 0xd151, 0x4014, \
+  { 0x8b, 0xdc, 0x62, 0xb5, 0x0d, 0xc0, 0x2b, 0x62 } }
 
-class nsHTMLCanvasElement;
 class gfxContext;
 class gfxASurface;
 class nsIPropertyBag;
 class nsDisplayListBuilder;
 
 namespace mozilla {
 namespace layers {
 class CanvasLayer;
@@ -41,19 +41,20 @@ public:
   typedef mozilla::layers::LayerManager LayerManager;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
 
   enum {
     RenderFlagPremultAlpha = 0x1
   };
 
-  // This method should NOT hold a ref to aParentCanvas; it will be called
-  // with nsnull when the element is going away.
-  NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas) = 0;
+  void SetCanvasElement(nsHTMLCanvasElement* aParentCanvas)
+  {
+    mCanvasElement = aParentCanvas;
+  }
 
   // Sets the dimensions of the canvas, in pixels.  Called
   // whenever the size of the element changes.
   NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height) = 0;
 
   NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height) = 0;
 
   // Render the canvas at the origin of the given gfxContext
@@ -114,14 +115,17 @@ public:
   // shmem support
   //
 
   // If this context can be set to use Mozilla's Shmem segments as its backing
   // store, this will set it to that state. Note that if you have drawn
   // anything into this canvas before changing the shmem state, it will be
   // lost.
   NS_IMETHOD SetIsIPC(bool isIPC) = 0;
+
+protected:
+  nsRefPtr<nsHTMLCanvasElement> mCanvasElement;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,
                               NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
 
 #endif /* nsICanvasRenderingContextInternal_h___ */
--- a/content/canvas/src/CanvasUtils.h
+++ b/content/canvas/src/CanvasUtils.h
@@ -123,17 +123,17 @@ JSValToDashArray(JSContext* cx, const js
             // Not an array-like thing
             return NS_ERROR_INVALID_ARG;
         } else if (length > MAX_NUM_DASHES) {
             // Too many dashes in the pattern
             return NS_ERROR_ILLEGAL_VALUE;
         }
 
         bool haveNonzeroElement = false;
-        for (uint32 i = 0; i < length; ++i) {
+        for (uint32_t i = 0; i < length; ++i) {
             jsval elt;
             double d;
             if (!JS_GetElement(cx, obj, i, &elt)) {
                 return NS_ERROR_FAILURE;
             }
             if (!(CoerceDouble(elt, &d) &&
                   FloatValidate(d) &&
                   d >= 0.0)) {
--- a/content/canvas/src/DocumentRendererChild.cpp
+++ b/content/canvas/src/DocumentRendererChild.cpp
@@ -6,16 +6,17 @@
 
 #include "base/basictypes.h"
 
 #include "gfxImageSurface.h"
 #include "gfxPattern.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMDocument.h"
+#include "nsIDocShell.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocument.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsComponentManagerUtils.h"
 #include "nsCSSParser.h"
 #include "nsPresContext.h"
 #include "nsCOMPtr.h"
@@ -31,17 +32,17 @@ DocumentRendererChild::DocumentRendererC
 
 DocumentRendererChild::~DocumentRendererChild()
 {}
 
 bool
 DocumentRendererChild::RenderDocument(nsIDOMWindow *window,
                                       const nsRect& documentRect,
                                       const gfxMatrix& transform,
-                                      const nsString& bgcolor,
+                                      const nsString& aBGColor,
                                       PRUint32 renderFlags,
                                       bool flushLayout, 
                                       const nsIntSize& renderSize,
                                       nsCString& data)
 {
     if (flushLayout)
         nsContentUtils::FlushLayoutForTree(window);
 
@@ -51,31 +52,35 @@ DocumentRendererChild::RenderDocument(ns
         nsIDocShell* docshell = win->GetDocShell();
         if (docshell) {
             docshell->GetPresContext(getter_AddRefs(presContext));
         }
     }
     if (!presContext)
         return false;
 
+    nsCSSParser parser;
+    nsCSSValue bgColorValue;
+    if (!parser.ParseColorString(aBGColor, nsnull, 0, bgColorValue)) {
+        return false;
+    }
+
     nscolor bgColor;
-    nsCSSParser parser;
-    nsresult rv = parser.ParseColorString(bgcolor, nsnull, 0, &bgColor);
-    if (NS_FAILED(rv))
+    if (!nsRuleNode::ComputeColor(bgColorValue, presContext, nsnull, bgColor)) {
         return false;
-
-    nsIPresShell* presShell = presContext->PresShell();
+    }
 
     // Draw directly into the output array.
     data.SetLength(renderSize.width * renderSize.height * 4);
 
     nsRefPtr<gfxImageSurface> surf =
         new gfxImageSurface(reinterpret_cast<uint8_t*>(data.BeginWriting()),
                             gfxIntSize(renderSize.width, renderSize.height),
                             4 * renderSize.width,
                             gfxASurface::ImageFormatARGB32);
     nsRefPtr<gfxContext> ctx = new gfxContext(surf);
     ctx->SetMatrix(transform);
 
-    presShell->RenderDocument(documentRect, renderFlags, bgColor, ctx);
+    presContext->PresShell()->
+      RenderDocument(documentRect, renderFlags, bgColor, ctx);
 
     return true;
 }
--- a/content/canvas/src/DocumentRendererParent.cpp
+++ b/content/canvas/src/DocumentRendererParent.cpp
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ipc/DocumentRendererParent.h"
 #include "gfxImageSurface.h"
 #include "gfxPattern.h"
+#include "nsICanvasRenderingContextInternal.h"
 
 using namespace mozilla::ipc;
 
 DocumentRendererParent::DocumentRendererParent()
 {}
 
 DocumentRendererParent::~DocumentRendererParent()
 {}
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -30,16 +30,17 @@
 
 #include "gfxCrashReporterUtils.h"
 
 #include "nsSVGEffects.h"
 
 #include "prenv.h"
 
 #include "mozilla/Preferences.h"
+#include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsIObserverService.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 using namespace mozilla::layers;
@@ -67,18 +68,17 @@ NS_NewCanvasRenderingContextWebGL(nsIDOM
     if (!ctx)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult = ctx);
     return NS_OK;
 }
 
 WebGLContext::WebGLContext()
-    : mCanvasElement(nsnull),
-      gl(nsnull)
+    : gl(nsnull)
 {
     SetIsDOMBinding();
     mEnabledExtensions.SetLength(WebGLExtensionID_Max);
 
     mGeneration = 0;
     mInvalidated = false;
     mResetLayer = true;
     mOptionsFrozen = false;
@@ -237,43 +237,35 @@ void
 WebGLContext::Invalidate()
 {
     if (mInvalidated)
         return;
 
     if (!mCanvasElement)
         return;
 
-    nsSVGEffects::InvalidateDirectRenderingObservers(HTMLCanvasElement());
+    nsSVGEffects::InvalidateDirectRenderingObservers(mCanvasElement);
 
     mInvalidated = true;
-    HTMLCanvasElement()->InvalidateCanvasContent(nsnull);
+    mCanvasElement->InvalidateCanvasContent(nsnull);
 }
 
 /* readonly attribute nsIDOMHTMLCanvasElement canvas; */
 NS_IMETHODIMP
 WebGLContext::GetCanvas(nsIDOMHTMLCanvasElement **canvas)
 {
     NS_IF_ADDREF(*canvas = mCanvasElement);
 
     return NS_OK;
 }
 
 //
 // nsICanvasRenderingContextInternal
 //
 
-NS_IMETHODIMP
-WebGLContext::SetCanvasElement(nsHTMLCanvasElement* aParentCanvas)
-{
-    mCanvasElement = aParentCanvas;
-
-    return NS_OK;
-}
-
 static bool
 GetBoolFromPropertyBag(nsIPropertyBag *bag, const char *propName, bool *boolResult)
 {
     nsCOMPtr<nsIVariant> vv;
     bool bv;
 
     nsresult rv = bag->GetProperty(NS_ConvertASCIItoUTF16(propName), getter_AddRefs(vv));
     if (NS_FAILED(rv) || !vv)
@@ -326,17 +318,17 @@ WebGLContext::SetContextOptions(nsIPrope
 }
 
 NS_IMETHODIMP
 WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
 {
     /*** early success return cases ***/
   
     if (mCanvasElement) {
-        HTMLCanvasElement()->InvalidateCanvas();
+        mCanvasElement->InvalidateCanvas();
     }
 
     if (gl && mWidth == width && mHeight == height)
         return NS_OK;
 
     // Zero-sized surfaces can cause problems.
     if (width == 0 || height == 0) {
         width = 1;
@@ -490,17 +482,17 @@ WebGLContext::SetDimensions(PRInt32 widt
         if (!gl || !InitAndValidateGL()) {
             GenerateWarning("Error during ANGLE OpenGL ES initialization");
             return NS_ERROR_FAILURE;
         }
     }
 #endif
 
     // try the default provider, whatever that is
-    if (!gl && useOpenGL) {
+    if (!gl && useOpenGL) {
         GLContext::ContextFlags flag = useMesaLlvmPipe 
                                        ? GLContext::ContextFlagsMesaLLVMPipe
                                        : GLContext::ContextFlagsNone;
         gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), 
                                                                format, flag);
         if (gl && !InitAndValidateGL()) {
             GenerateWarning("Error during %s initialization", 
                             useMesaLlvmPipe ? "Mesa LLVMpipe" : "OpenGL");
@@ -721,17 +713,17 @@ WebGLContext::GetCanvasLayer(nsDisplayLi
       // and if there is, flushing the invalidation state more often than
       // necessary is harmless).
 
       // The layer will be destroyed when we tear down the presentation
       // (at the latest), at which time this userData will be destroyed,
       // releasing the reference to the element.
       // The userData will receive DidTransactionCallbacks, which flush the
       // the invalidation state to indicate that the canvas is up to date.
-      userData = new WebGLContextUserData(HTMLCanvasElement());
+      userData = new WebGLContextUserData(mCanvasElement);
       canvasLayer->SetDidTransactionCallback(
               WebGLContextUserData::DidTransactionCallback, userData);
     }
     canvasLayer->SetUserData(&gWebGLLayerUserData, userData);
 
     CanvasLayer::Data data;
 
     // the gl context may either provide a native PBuffer, in which case we want to initialize
@@ -1060,28 +1052,28 @@ WebGLContext::DummyFramebufferOperation(
 // are met.
 // At a bare minimum, from context lost to context restores, it would take 3
 // full timer iterations: detection, webglcontextlost, webglcontextrestored.
 NS_IMETHODIMP
 WebGLContext::Notify(nsITimer* timer)
 {
     TerminateContextLossTimer();
 
-    if (!HTMLCanvasElement()) {
+    if (!mCanvasElement) {
         // the canvas is gone. That happens when the page was closed before we got
         // this timer event. In this case, there's nothing to do here, just don't crash.
         return NS_OK;
     }
 
     // If the context has been lost and we're waiting for it to be restored, do
     // that now.
     if (mContextStatus == ContextLostAwaitingEvent) {
         bool defaultAction;
-        nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
-                                             (nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
+        nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
+                                             static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
                                              NS_LITERAL_STRING("webglcontextlost"),
                                              true,
                                              true,
                                              &defaultAction);
 
         // If the script didn't handle the event, we don't allow restores.
         if (defaultAction)
             mAllowRestore = false;
@@ -1099,18 +1091,18 @@ WebGLContext::Notify(nsITimer* timer)
         }
     } else if (mContextStatus == ContextLostAwaitingRestore) {
         // Try to restore the context. If it fails, try again later.
         if (NS_FAILED(SetDimensions(mWidth, mHeight))) {
             SetupContextLossTimer();
             return NS_OK;
         }
         mContextStatus = ContextStable;
-        nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
-                                             (nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
+        nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
+                                             static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
                                              NS_LITERAL_STRING("webglcontextrestored"),
                                              true,
                                              true);
         // Set all flags back to the state they were in before the context was
         // lost.
         mContextLostErrorSet = false;
         mAllowRestore = true;
     }
@@ -1209,17 +1201,17 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebGLContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mEnabledExtensions)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebGLContext)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCanvasElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCanvasElement, nsINode)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mEnabledExtensions)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 DOMCI_DATA(WebGLRenderingContext, WebGLContext)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -478,32 +478,27 @@ public:
     virtual ~WebGLContext();
 
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(WebGLContext,
                                                            nsIDOMWebGLRenderingContext)
 
     nsINode* GetParentObject() {
-        return HTMLCanvasElement();
+        return mCanvasElement;
     }
 
     virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
                                  bool *triedToWrap);
 
     NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
 
     NS_DECL_NSITIMERCALLBACK
 
     // nsICanvasRenderingContextInternal
-    NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas);
-    nsHTMLCanvasElement* HTMLCanvasElement() const {
-        return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
-    }
-
     NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
     NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height)
         { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Reset()
         { /* (InitializeWithSurface) */ return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Render(gfxContext *ctx,
                       gfxPattern::GraphicsFilter f,
                       PRUint32 aFlags = RenderFlagPremultAlpha);
@@ -614,17 +609,17 @@ public:
         if (mContextLossTimerRunning) {
             mContextRestorer->Cancel();
             mContextLossTimerRunning = false;
         }
     }
 
     // WebIDL WebGLRenderingContext API
     nsHTMLCanvasElement* GetCanvas() const {
-        return HTMLCanvasElement();
+        return mCanvasElement;
     }
     WebGLsizei GetDrawingBufferWidth() const {
         if (!IsContextStable())
             return 0;
         return mWidth;
     }
     WebGLsizei GetDrawingBufferHeight() const {
         if (!IsContextStable())
@@ -1102,18 +1097,16 @@ protected:
                                       uint32_t pixelSize,
                                       uint32_t alignment);
 
     // Returns x rounded to the next highest multiple of y.
     static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y) {
         return ((x + y - 1) / y) * y;
     }
 
-    nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
-
     nsRefPtr<gl::GLContext> gl;
 
     CheckedUint32 mGeneration;
 
     WebGLContextOptions mOptions;
 
     bool mInvalidated;
     bool mResetLayer;
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -3836,17 +3836,17 @@ WebGLContext::ReadPixels(WebGLint x, Web
                          WebGLsizei height, WebGLenum format,
                          WebGLenum type, ArrayBufferView* pixels,
                          ErrorResult& rv)
 {
     if (!IsContextStable()) {
         return;
     }
 
-    if (HTMLCanvasElement()->IsWriteOnly() && !nsContentUtils::IsCallerTrustedForRead()) {
+    if (mCanvasElement->IsWriteOnly() && !nsContentUtils::IsCallerTrustedForRead()) {
         GenerateWarning("readPixels: Not allowed");
         return rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     }
 
     if (width < 0 || height < 0)
         return ErrorInvalidValue("readPixels: negative size passed");
 
     const WebGLRectangleObject *framebufferRect = FramebufferRectangleObject();
@@ -4338,17 +4338,17 @@ WebGLContext::SurfaceFromElementResultTo
     // To prevent a loophole where a Canvas2D would be used as a proxy to load
     // cross-domain textures, we also disallow loading textures from write-only
     // Canvas2D's.
 
     // part 1: check that the DOM element is same-origin, or has otherwise been
     // validated for cross-domain use.
     if (!res.mCORSUsed) {
         bool subsumes;
-        nsresult rv = HTMLCanvasElement()->NodePrincipal()->Subsumes(res.mPrincipal, &subsumes);
+        nsresult rv = mCanvasElement->NodePrincipal()->Subsumes(res.mPrincipal, &subsumes);
         if (NS_FAILED(rv) || !subsumes) {
             GenerateWarning("It is forbidden to load a WebGL texture from a cross-domain element that has not been validated with CORS. "
                                 "See https://developer.mozilla.org/en/WebGL/Cross-Domain_Textures");
             return NS_ERROR_DOM_SECURITY_ERR;
         }
     }
 
     // part 2: if the DOM element is write-only, it might contain
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -1,17 +1,18 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLContext.h"
 
+#include "mozilla/CheckedInt.h"
 #include "mozilla/Preferences.h"
-#include "mozilla/CheckedInt.h"
+#include "mozilla/Services.h"
 
 #include "jsfriendapi.h"
 
 #if defined(USE_ANGLE)
 #include "angle/ShaderLang.h"
 #endif
 
 #include <algorithm>
@@ -592,17 +593,17 @@ WebGLContext::InitAndValidateGL()
     if (!gl) return false;
 
     GLenum error = gl->fGetError();
     if (error != LOCAL_GL_NO_ERROR) {
         GenerateWarning("GL error 0x%x occurred during OpenGL context initialization, before WebGL initialization!", error);
         return false;
     }
 
-#ifdef ANDROID
+#ifdef MOZ_JAVA_COMPOSITOR
     // bug 736123, blacklist WebGL on Adreno
     bool forceEnabled = Preferences::GetBool("webgl.force-enabled", false);
     if (!forceEnabled) {
         int renderer = gl->Renderer();
         if (renderer == gl::GLContext::RendererAdreno200 ||
             renderer == gl::GLContext::RendererAdreno205)
         {
             GenerateWarning("WebGL blocked on this Adreno driver!");
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -82,16 +82,17 @@
 
 #include "mozilla/Assertions.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/ipc/DocumentRendererParent.h"
 #include "mozilla/ipc/PDocumentRendererParent.h"
+#include "mozilla/unused.h"
 
 // windows.h (included by chromium code) defines this, in its infinite wisdom
 #undef DrawText
 
 using namespace mozilla;
 using namespace mozilla::CanvasUtils;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
@@ -168,22 +169,26 @@ public:
 
     /* nsIDOMCanvasGradient */
     NS_IMETHOD AddColorStop (float offset,
                              const nsAString& colorstr)
     {
         if (!FloatValidate(offset) || offset < 0.0 || offset > 1.0)
             return NS_ERROR_DOM_INDEX_SIZE_ERR;
 
-        nscolor color;
+        nsCSSValue value;
         nsCSSParser parser;
-        nsresult rv = parser.ParseColorString(nsString(colorstr),
-                                              nsnull, 0, &color);
-        if (NS_FAILED(rv))
+        if (!parser.ParseColorString(colorstr, nsnull, 0, value)) {
             return NS_ERROR_DOM_SYNTAX_ERR;
+        }
+
+        nscolor color;
+        if (!nsRuleNode::ComputeColor(value, nsnull, nsnull, color)) {
+            return NS_ERROR_DOM_SYNTAX_ERR;
+        }
 
         mPattern->AddColorStop(offset, gfxRGBA(color));
 
         return NS_OK;
     }
 
     NS_DECL_ISUPPORTS
 
@@ -307,17 +312,16 @@ class nsCanvasRenderingContext2D :
 {
 public:
     nsCanvasRenderingContext2D();
     virtual ~nsCanvasRenderingContext2D();
 
     nsresult Redraw();
 
     // nsICanvasRenderingContextInternal
-    NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas);
     NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
     void Initialize(nsIDocShell *shell, PRInt32 width, PRInt32 height);
     NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height);
     bool EnsureSurface();
     NS_IMETHOD Render(gfxContext *ctx,
                       gfxPattern::GraphicsFilter aFilter,
                       PRUint32 aFlags = RenderFlagPremultAlpha);
     NS_IMETHOD GetInputStream(const char* aMimeType,
@@ -398,16 +402,19 @@ protected:
      * Lookup table used to speed up PutImageData().
      */
     static PRUint8 (*sPremultiplyTable)[256];
 
     // Some helpers.  Doesn't modify acolor on failure.
     nsresult SetStyleFromStringOrInterface(const nsAString& aStr, nsISupports *aInterface, Style aWhichStyle);
     nsresult GetStyleAsStringOrInterface(nsAString& aStr, nsISupports **aInterface, PRInt32 *aType, Style aWhichStyle);
 
+    // Returns whether a color was successfully parsed.
+    bool ParseColor(const nsAString& aString, nscolor* aColor);
+
     void StyleColorToString(const nscolor& aColor, nsAString& aStr);
 
     void DirtyAllStyles();
     /**
      * applies the given style as the current source. If the given style is
      * a solid color, aUseGlobalAlpha indicates whether to multiply the alpha
      * by global alpha, and is ignored otherwise.
      */
@@ -432,22 +439,16 @@ protected:
     // Member vars
     PRInt32 mWidth, mHeight;
     bool mValid;
     bool mZero;
     bool mOpaque;
     bool mResetLayer;
     bool mIPC;
 
-    // the canvas element we're a context of
-    nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
-    nsHTMLCanvasElement *HTMLCanvasElement() {
-        return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
-    }
-
     // Initialize the Thebes rendering context
     void CreateThebes();
 
     // If mCanvasElement is not provided, then a docshell is
     nsCOMPtr<nsIDocShell> mDocShell;
 
     // our drawing surfaces, contexts, and layers
     nsRefPtr<gfxContext> mThebes;
@@ -758,17 +759,17 @@ protected:
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCanvasRenderingContext2D)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCanvasRenderingContext2D)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCanvasRenderingContext2D)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCanvasRenderingContext2D)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCanvasRenderingContext2D)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCanvasElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCanvasElement, nsINode)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 DOMCI_DATA(CanvasRenderingContext2D, nsCanvasRenderingContext2D)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCanvasRenderingContext2D)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCanvasRenderingContext2D)
   NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMCanvasRenderingContext2D)
@@ -794,17 +795,16 @@ NS_NewCanvasRenderingContext2DThebes(nsI
 
     *aResult = ctx.forget().get();
     return NS_OK;
 }
 
 nsCanvasRenderingContext2D::nsCanvasRenderingContext2D()
     : mValid(false), mZero(false), mOpaque(false), mResetLayer(true)
     , mIPC(false)
-    , mCanvasElement(nsnull)
     , mSaveCount(0), mIsEntireFrameInvalid(false)
     , mPredictManyRedrawCalls(false), mHasPath(false), mInvalidateCount(0)
     , mLastStyle(STYLE_MAX), mStyleStack(20)
 {
     sNumLivingContexts++;
 }
 
 nsCanvasRenderingContext2D::~nsCanvasRenderingContext2D()
@@ -814,21 +814,51 @@ nsCanvasRenderingContext2D::~nsCanvasRen
     if (!sNumLivingContexts) {
         delete[] sUnpremultiplyTable;
         delete[] sPremultiplyTable;
         sUnpremultiplyTable = nsnull;
         sPremultiplyTable = nsnull;
     }
 }
 
+bool
+nsCanvasRenderingContext2D::ParseColor(const nsAString& aString,
+                                       nscolor* aColor)
+{
+    nsIDocument* document = mCanvasElement
+                            ? mCanvasElement->OwnerDoc()
+                            : nsnull;
+
+    // Pass the CSS Loader object to the parser, to allow parser error
+    // reports to include the outer window ID.
+    nsCSSParser parser(document ? document->CSSLoader() : nsnull);
+    nsCSSValue value;
+    if (!parser.ParseColorString(aString, nsnull, 0, value)) {
+        return false;
+    }
+
+    nsIPresShell* presShell = GetPresShell();
+    nsRefPtr<nsStyleContext> parentContext;
+    if (mCanvasElement && mCanvasElement->IsInDoc()) {
+        // Inherit from the canvas element.
+        parentContext = nsComputedDOMStyle::GetStyleContextForElement(
+            mCanvasElement, nsnull, presShell);
+    }
+
+    unused << nsRuleNode::ComputeColor(
+        value, presShell ? presShell->GetPresContext() : nsnull, parentContext,
+        *aColor);
+    return true;
+}
+
 nsresult
 nsCanvasRenderingContext2D::Reset()
 {
     if (mCanvasElement) {
-        HTMLCanvasElement()->InvalidateCanvas();
+        mCanvasElement->InvalidateCanvas();
     }
 
     // only do this for non-docshell created contexts,
     // since those are the ones that we created a surface for
     if (mValid && !mDocShell && mSurface)
         gCanvasMemoryUsed -= mWidth * mHeight * 4;
 
     mSurface = nsnull;
@@ -839,29 +869,19 @@ nsCanvasRenderingContext2D::Reset()
     return NS_OK;
 }
 
 nsresult
 nsCanvasRenderingContext2D::SetStyleFromStringOrInterface(const nsAString& aStr,
                                                           nsISupports *aInterface,
                                                           Style aWhichStyle)
 {
-    nsresult rv;
-    nscolor color;
-
     if (!aStr.IsVoid()) {
-        nsIDocument* document = mCanvasElement ?
-                                HTMLCanvasElement()->OwnerDoc() : nsnull;
-
-        // Pass the CSS Loader object to the parser, to allow parser error
-        // reports to include the outer window ID.
-        nsCSSParser parser(document ? document->CSSLoader() : nsnull);
-        rv = parser.ParseColorString(aStr, nsnull, 0, &color);
-        if (NS_FAILED(rv)) {
-            // Error reporting happens inside the CSS parser
+        nscolor color;
+        if (!ParseColor(aStr, &color)) {
             return NS_OK;
         }
 
         CurrentState().SetColorStyle(aWhichStyle, color);
 
         mDirtyStyle[aWhichStyle] = true;
         return NS_OK;
     }
@@ -880,17 +900,17 @@ nsCanvasRenderingContext2D::SetStyleFrom
             mDirtyStyle[aWhichStyle] = true;
             return NS_OK;
         }
     }
 
     nsContentUtils::ReportToConsole(
         nsIScriptError::warningFlag,
         "Canvas",
-        mCanvasElement ? HTMLCanvasElement()->OwnerDoc() : nsnull,
+        mCanvasElement ? mCanvasElement->OwnerDoc() : nsnull,
         nsContentUtils::eDOM_PROPERTIES,
         "UnexpectedCanvasVariantStyle");
 
     return NS_OK;
 }
 
 nsresult
 nsCanvasRenderingContext2D::GetStyleAsStringOrInterface(nsAString& aStr,
@@ -964,17 +984,17 @@ nsCanvasRenderingContext2D::ApplyStyle(S
     // if not using global alpha, don't optimize with dirty bit
     if (aUseGlobalAlpha)
         mDirtyStyle[aWhichStyle] = false;
     mLastStyle = aWhichStyle;
 
     nsCanvasPattern* pattern = CurrentState().patternStyles[aWhichStyle];
     if (pattern) {
         if (mCanvasElement)
-            CanvasUtils::DoDrawImageSecurityCheck(HTMLCanvasElement(),
+            CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
                                                   pattern->Principal(),
                                                   pattern->GetForceWriteOnly(),
                                                   pattern->GetCORSUsed());
 
         gfxPattern* gpat = pattern->GetPattern();
 
         if (CurrentState().imageSmoothingEnabled)
             gpat->SetFilter(gfxPattern::FILTER_GOOD);
@@ -1005,19 +1025,19 @@ nsCanvasRenderingContext2D::Redraw()
         return NS_OK;
     mIsEntireFrameInvalid = true;
 
     if (!mCanvasElement) {
         NS_ASSERTION(mDocShell, "Redraw with no canvas element or docshell!");
         return NS_OK;
     }
 
-    nsSVGEffects::InvalidateDirectRenderingObservers(HTMLCanvasElement());
-
-    HTMLCanvasElement()->InvalidateCanvasContent(nsnull);
+    nsSVGEffects::InvalidateDirectRenderingObservers(mCanvasElement);
+
+    mCanvasElement->InvalidateCanvasContent(nsnull);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::Redraw(const gfxRect& r)
 {
     ++mInvalidateCount;
@@ -1030,19 +1050,19 @@ nsCanvasRenderingContext2D::Redraw(const
         return Redraw();
     }
 
     if (!mCanvasElement) {
         NS_ASSERTION(mDocShell, "Redraw with no canvas element or docshell!");
         return NS_OK;
     }
 
-    nsSVGEffects::InvalidateDirectRenderingObservers(HTMLCanvasElement());
-
-    HTMLCanvasElement()->InvalidateCanvasContent(&r);
+    nsSVGEffects::InvalidateDirectRenderingObservers(mCanvasElement);
+
+    mCanvasElement->InvalidateCanvasContent(&r);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::RedrawUser(const gfxRect& r)
 {
     if (mIsEntireFrameInvalid) {
@@ -1345,24 +1365,16 @@ nsCanvasRenderingContext2D::GetImageForm
     return format;
 }
 
 //
 // nsCanvasRenderingContext2D impl
 //
 
 NS_IMETHODIMP
-nsCanvasRenderingContext2D::SetCanvasElement(nsHTMLCanvasElement* aCanvasElement)
-{
-    mCanvasElement = aCanvasElement;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 nsCanvasRenderingContext2D::GetCanvas(nsIDOMHTMLCanvasElement **canvas)
 {
     NS_IF_ADDREF(*canvas = mCanvasElement);
 
     return NS_OK;
 }
 
 //
@@ -1891,28 +1903,20 @@ nsCanvasRenderingContext2D::SetShadowBlu
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::GetShadowBlur(float *blur)
 {
     *blur = CurrentState().shadowBlur;
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsCanvasRenderingContext2D::SetShadowColor(const nsAString& colorstr)
+nsCanvasRenderingContext2D::SetShadowColor(const nsAString& aColor)
 {
-    nsIDocument* document = mCanvasElement ?
-                            HTMLCanvasElement()->OwnerDoc() : nsnull;
-
-    // Pass the CSS Loader object to the parser, to allow parser error reports
-    // to include the outer window ID.
-    nsCSSParser parser(document ? document->CSSLoader() : nsnull);
     nscolor color;
-    nsresult rv = parser.ParseColorString(colorstr, nsnull, 0, &color);
-    if (NS_FAILED(rv)) {
-        // Error reporting happens inside the CSS parser
+    if (!ParseColor(aColor, &color)) {
         return NS_OK;
     }
 
     CurrentState().SetColorStyle(STYLE_SHADOW, color);
 
     mDirtyStyle[STYLE_SHADOW] = true;
 
     return NS_OK;
@@ -2447,19 +2451,18 @@ nsCanvasRenderingContext2D::SetFont(cons
     /*
      * If font is defined with relative units (e.g. ems) and the parent
      * style context changes in between calls, setting the font to the
      * same value as previous could result in a different computed value,
      * so we cannot have the optimization where we check if the new font
      * string is equal to the old one.
      */
 
-    nsCOMPtr<nsIContent> content = do_QueryInterface(mCanvasElement);
-    if (!content && !mDocShell) {
-        NS_WARNING("Canvas element must be an nsIContent and non-null or a docshell must be provided");
+    if (!mCanvasElement && !mDocShell) {
+        NS_WARNING("Canvas element must be non-null or a docshell must be provided");
         return NS_ERROR_FAILURE;
     }
 
     nsIPresShell* presShell = GetPresShell();
     if (!presShell)
       return NS_ERROR_FAILURE;
     nsIDocument* document = presShell->GetDocument();
 
@@ -2489,20 +2492,20 @@ nsCanvasRenderingContext2D::SetFont(cons
     rules.AppendObject(rule);
 
     nsStyleSet* styleSet = presShell->StyleSet();
 
     // have to get a parent style context for inherit-like relative
     // values (2em, bolder, etc.)
     nsRefPtr<nsStyleContext> parentContext;
 
-    if (content && content->IsInDoc()) {
+    if (mCanvasElement && mCanvasElement->IsInDoc()) {
         // inherit from the canvas element
         parentContext = nsComputedDOMStyle::GetStyleContextForElement(
-                content->AsElement(),
+                mCanvasElement,
                 nsnull,
                 presShell);
     } else {
         // otherwise inherit from default
         nsRefPtr<css::StyleRule> parentRule;
         rv = CreateFontStyleRule(kDefaultFontStyle,
                                  document,
                                  getter_AddRefs(parentRule));
@@ -2827,39 +2830,38 @@ nsCanvasRenderingContext2D::DrawOrMeasur
 
     // spec isn't clear on what should happen if aMaxWidth <= 0, so
     // treat it as an invalid argument
     // technically, 0 should be an invalid value as well, but 0 is the default
     // arg, and there is no way to tell if the default was used
     if (aMaxWidth < 0)
         return NS_ERROR_INVALID_ARG;
 
-    nsCOMPtr<nsIContent> content = do_QueryInterface(mCanvasElement);
-    if (!content && !mDocShell) {
-        NS_WARNING("Canvas element must be an nsIContent and non-null or a docshell must be provided");
+    if (!mCanvasElement && !mDocShell) {
+        NS_WARNING("Canvas element must be non-null or a docshell must be provided");
         return NS_ERROR_FAILURE;
     }
 
     nsIPresShell* presShell = GetPresShell();
     if (!presShell)
         return NS_ERROR_FAILURE;
 
     nsIDocument* document = presShell->GetDocument();
 
     // replace all the whitespace characters with U+0020 SPACE
     nsAutoString textToDraw(aRawText);
     TextReplaceWhitespaceCharacters(textToDraw);
 
     // for now, default to ltr if not in doc
     bool isRTL = false;
 
-    if (content && content->IsInDoc()) {
+    if (mCanvasElement && mCanvasElement->IsInDoc()) {
         // try to find the closest context
         nsRefPtr<nsStyleContext> canvasStyle =
-            nsComputedDOMStyle::GetStyleContextForElement(content->AsElement(),
+            nsComputedDOMStyle::GetStyleContextForElement(mCanvasElement,
                                                           nsnull,
                                                           presShell);
         if (!canvasStyle)
             return NS_ERROR_FAILURE;
         isRTL = canvasStyle->GetStyleVisibility()->mDirection ==
             NS_STYLE_DIRECTION_RTL;
     } else {
       isRTL = GET_BIDI_OPTION_DIRECTION(document->GetBidiOptions()) == IBMBIDI_TEXTDIRECTION_RTL;
@@ -3372,17 +3374,17 @@ nsCanvasRenderingContext2D::DrawImage(ns
             return NS_ERROR_DOM_INVALID_STATE_ERR;
         }
     }
 
     gfxMatrix matrix;
     nsRefPtr<gfxPattern> pattern;
     gfxIntSize imgSize;
     nsRefPtr<gfxASurface> imgsurf =
-      CanvasImageCache::Lookup(imgElt, HTMLCanvasElement(), &imgSize);
+      CanvasImageCache::Lookup(imgElt, mCanvasElement, &imgSize);
 
     if (!imgsurf) {
         // The canvas spec says that drawImage should draw the first frame
         // of animated images
         PRUint32 sfeFlags = nsLayoutUtils::SFE_WANT_FIRST_FRAME;
         nsLayoutUtils::SurfaceFromElementResult res =
             nsLayoutUtils::SurfaceFromElement(content->AsElement(), sfeFlags);
         if (!res.mSurface) {
@@ -3399,24 +3401,24 @@ nsCanvasRenderingContext2D::DrawImage(ns
             if (!res.mSurface)
                 return NS_ERROR_NOT_AVAILABLE;
         }
 
         imgsurf = res.mSurface.forget();
         imgSize = res.mSize;
 
         if (mCanvasElement) {
-            CanvasUtils::DoDrawImageSecurityCheck(HTMLCanvasElement(),
+            CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
                                                   res.mPrincipal,
                                                   res.mIsWriteOnly,
                                                   res.mCORSUsed);
         }
 
         if (res.mImageRequest) {
-            CanvasImageCache::NotifyDrawImage(imgElt, HTMLCanvasElement(),
+            CanvasImageCache::NotifyDrawImage(imgElt, mCanvasElement,
                                               res.mImageRequest, imgsurf, imgSize);
         }
     }
 
     double sx,sy,sw,sh;
     double dx,dy,dw,dh;
     if (optional_argc == 0) {
         dx = a1;
@@ -3646,29 +3648,19 @@ nsCanvasRenderingContext2D::DrawWindow(n
         if (docshell) {
             docshell->GetPresContext(getter_AddRefs(presContext));
         }
     }
     if (!presContext)
         return NS_ERROR_FAILURE;
 
     nscolor bgColor;
-
-    nsIDocument* elementDoc = mCanvasElement ?
-                              HTMLCanvasElement()->OwnerDoc() : nsnull;
-
-    // Pass the CSS Loader object to the parser, to allow parser error reports
-    // to include the outer window ID.
-    nsCSSParser parser(elementDoc ? elementDoc->CSSLoader() : nsnull);
-    nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor),
-                                          nsnull, 0, &bgColor);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsIPresShell* presShell = presContext->PresShell();
-    NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
+    if (!ParseColor(aBGColor, &bgColor)) {
+        return NS_ERROR_FAILURE;
+    }
 
     nsRect r(nsPresContext::CSSPixelsToAppUnits(aX),
              nsPresContext::CSSPixelsToAppUnits(aY),
              nsPresContext::CSSPixelsToAppUnits(aW),
              nsPresContext::CSSPixelsToAppUnits(aH));
     PRUint32 renderDocFlags = (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
                                nsIPresShell::RENDER_DOCUMENT_RELATIVE);
     if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DRAW_CARET) {
@@ -3680,17 +3672,18 @@ nsCanvasRenderingContext2D::DrawWindow(n
     }
     if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_USE_WIDGET_LAYERS) {
         renderDocFlags |= nsIPresShell::RENDER_USE_WIDGET_LAYERS;
     }
     if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_ASYNC_DECODE_IMAGES) {
         renderDocFlags |= nsIPresShell::RENDER_ASYNC_DECODE_IMAGES;
     }
 
-    rv = presShell->RenderDocument(r, renderDocFlags, bgColor, mThebes);
+    nsresult rv = presContext->PresShell()->
+        RenderDocument(r, renderDocFlags, bgColor, mThebes);
 
     // get rid of the pattern surface ref, just in case
     mThebes->SetColor(gfxRGBA(1,1,1,1));
     DirtyAllStyles();
 
     // note that aX and aY are coordinates in the document that
     // we're drawing; aX and aY are drawn to 0,0 in current user
     // space.
@@ -3818,18 +3811,17 @@ nsCanvasRenderingContext2D::GetImageData
 {
     if (!mCanvasElement && !mDocShell) {
         NS_ERROR("No canvas element and no docshell in GetImageData!!!");
         return NS_ERROR_DOM_SECURITY_ERR;
     }
 
     // Check only if we have a canvas element; if we were created with a docshell,
     // then it's special internal use.
-    if (mCanvasElement &&
-        HTMLCanvasElement()->IsWriteOnly() &&
+    if (mCanvasElement && mCanvasElement->IsWriteOnly() &&
         !nsContentUtils::IsCallerTrustedForRead()) {
         // XXX ERRMSG we need to report an error to developers here! (bug 329026)
         return NS_ERROR_DOM_SECURITY_ERR;
     }
 
     if (!EnsureSurface()) {
         return NS_ERROR_FAILURE;
     }
@@ -4031,29 +4023,29 @@ nsCanvasRenderingContext2D::PutImageData
             NS_ENSURE_TRUE(dirtyWidth != INT_MIN, NS_ERROR_DOM_INDEX_SIZE_ERR);
 
             CheckedInt32 checkedDirtyX = CheckedInt32(dirtyX) + dirtyWidth;
 
             if (!checkedDirtyX.isValid())
                 return NS_ERROR_DOM_INDEX_SIZE_ERR;
 
             dirtyX = checkedDirtyX.value();
-            dirtyWidth = -(int32)dirtyWidth;
+            dirtyWidth = -dirtyWidth;
         }
 
         if (dirtyHeight < 0) {
             NS_ENSURE_TRUE(dirtyHeight != INT_MIN, NS_ERROR_DOM_INDEX_SIZE_ERR);
 
             CheckedInt32 checkedDirtyY = CheckedInt32(dirtyY) + dirtyHeight;
 
             if (!checkedDirtyY.isValid())
                 return NS_ERROR_DOM_INDEX_SIZE_ERR;
 
             dirtyY = checkedDirtyY.value();
-            dirtyHeight = -(int32)dirtyHeight;
+            dirtyHeight = -dirtyHeight;
         }
 
         // bound the dirty rect within the imageData rectangle
         dirtyRect = imageDataRect.Intersect(gfxRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight));
 
         if (dirtyRect.Width() <= 0 || dirtyRect.Height() <= 0)
             return NS_OK;
     } else {
@@ -4201,17 +4193,17 @@ nsCanvasRenderingContext2D::GetCanvasLay
       // and if there is, flushing the invalidation state more often than
       // necessary is harmless).
 
       // The layer will be destroyed when we tear down the presentation
       // (at the latest), at which time this userData will be destroyed,
       // releasing the reference to the element.
       // The userData will receive DidTransactionCallbacks, which flush the
       // the invalidation state to indicate that the canvas is up to date.
-      userData = new CanvasRenderingContext2DUserData(HTMLCanvasElement());
+      userData = new CanvasRenderingContext2DUserData(mCanvasElement);
       canvasLayer->SetDidTransactionCallback(
               CanvasRenderingContext2DUserData::DidTransactionCallback, userData);
     }
     canvasLayer->SetUserData(&g2DContextLayerUserData, userData);
 
     CanvasLayer::Data data;
 
     data.mSurface = mSurface.get();
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -83,16 +83,17 @@
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/ipc/DocumentRendererParent.h"
 #include "mozilla/ipc/PDocumentRendererParent.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/unused.h"
 
 #ifdef XP_WIN
 #include "gfxWindowsPlatform.h"
 #endif
 
 // windows.h (included by chromium code) defines this, in its infinite wisdom
 #undef DrawText
 
@@ -167,21 +168,24 @@ public:
   /* nsIDOMCanvasGradient */
   NS_IMETHOD AddColorStop (float offset,
                             const nsAString& colorstr)
   {
     if (!FloatValidate(offset) || offset < 0.0 || offset > 1.0) {
       return NS_ERROR_DOM_INDEX_SIZE_ERR;
     }
 
-    nscolor color;
+    nsCSSValue value;
     nsCSSParser parser;
-    nsresult rv = parser.ParseColorString(nsString(colorstr),
-                                          nsnull, 0, &color);
-    if (NS_FAILED(rv)) {
+    if (!parser.ParseColorString(colorstr, nsnull, 0, value)) {
+      return NS_ERROR_DOM_SYNTAX_ERR;
+    }
+
+    nscolor color;
+    if (!nsRuleNode::ComputeColor(value, nsnull, nsnull, color)) {
       return NS_ERROR_DOM_SYNTAX_ERR;
     }
 
     mStops = nsnull;
 
     GradientStop newStop;
 
     newStop.offset = offset;
@@ -364,17 +368,16 @@ class nsCanvasRenderingContext2DAzure :
 {
 public:
   nsCanvasRenderingContext2DAzure();
   virtual ~nsCanvasRenderingContext2DAzure();
 
   nsresult Redraw();
 
   // nsICanvasRenderingContextInternal
-  NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas);
   NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
   NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height)
   { return NS_ERROR_NOT_IMPLEMENTED; }
 
   NS_IMETHOD Render(gfxContext *ctx,
                     gfxPattern::GraphicsFilter aFilter,
                     PRUint32 aFlags = RenderFlagPremultAlpha);
   NS_IMETHOD GetInputStream(const char* aMimeType,
@@ -438,16 +441,19 @@ protected:
     * Lookup table used to speed up PutImageData().
     */
   static PRUint8 (*sPremultiplyTable)[256];
 
   // Some helpers.  Doesn't modify a color on failure.
   nsresult SetStyleFromStringOrInterface(const nsAString& aStr, nsISupports *aInterface, Style aWhichStyle);
   nsresult GetStyleAsStringOrInterface(nsAString& aStr, nsISupports **aInterface, PRInt32 *aType, Style aWhichStyle);
 
+  // Returns whether a color was successfully parsed.
+  bool ParseColor(const nsAString& aString, nscolor* aColor);
+
   void StyleColorToString(const nscolor& aColor, nsAString& aStr);
 
   /**
     * Creates the unpremultiply lookup table, if it doesn't exist.
     */
   void EnsureUnpremultiplyTable();
 
   /**
@@ -470,20 +476,16 @@ protected:
   void FillRuleChanged();
 
   /**
     * Returns the surface format this canvas should be allocated using. Takes
     * into account mOpaque, platform requirements, etc.
     */
   SurfaceFormat GetSurfaceFormat() const;
 
-  nsHTMLCanvasElement *HTMLCanvasElement() {
-    return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
-  }
-
   // Member vars
   PRInt32 mWidth, mHeight;
 
   // This is true when the canvas is valid, false otherwise, this occurs when
   // for some reason initialization of the drawtarget fails. If the canvas
   // is invalid certain behavior is expected.
   bool mValid;
   // This is true when the canvas is valid, but of zero size, this requires
@@ -493,19 +495,16 @@ protected:
   bool mOpaque;
 
   // This is true when the next time our layer is retrieved we need to
   // recreate it (i.e. our backing surface changed)
   bool mResetLayer;
   // This is needed for drawing in drawAsyncXULElement
   bool mIPC;
 
-  // the canvas element we're a context of
-  nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
-
   // If mCanvasElement is not provided, then a docshell is
   nsCOMPtr<nsIDocShell> mDocShell;
 
   // our drawing surfaces, contexts, and layers
   RefPtr<DrawTarget> mTarget;
 
   /**
     * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
@@ -772,17 +771,17 @@ protected:
         nsCanvasRadialGradientAzure *gradient =
           static_cast<nsCanvasRadialGradientAzure*>(state.gradientStyles[aStyle].get());
 
         mPattern = new (mRadialGradientPattern.addr())
           RadialGradientPattern(gradient->mCenter1, gradient->mCenter2, gradient->mRadius1,
                                 gradient->mRadius2, gradient->GetGradientStopsForTarget(aRT));
       } else if (state.patternStyles[aStyle]) {
         if (aCtx->mCanvasElement) {
-          CanvasUtils::DoDrawImageSecurityCheck(aCtx->HTMLCanvasElement(),
+          CanvasUtils::DoDrawImageSecurityCheck(aCtx->mCanvasElement,
                                                 state.patternStyles[aStyle]->mPrincipal,
                                                 state.patternStyles[aStyle]->mForceWriteOnly,
                                                 state.patternStyles[aStyle]->mCORSUsed);
         }
 
         ExtendMode mode;
         if (state.patternStyles[aStyle]->mRepeat == nsCanvasPatternAzure::NOREPEAT) {
           mode = EXTEND_CLAMP;
@@ -936,17 +935,17 @@ protected:
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCanvasRenderingContext2DAzure)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCanvasRenderingContext2DAzure)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCanvasRenderingContext2DAzure)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCanvasRenderingContext2DAzure)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCanvasRenderingContext2DAzure)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCanvasElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCanvasElement, nsINode)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 // XXX
 // DOMCI_DATA(CanvasRenderingContext2D, nsCanvasRenderingContext2DAzure)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCanvasRenderingContext2DAzure)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCanvasRenderingContext2D)
   NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
@@ -984,17 +983,16 @@ NS_NewCanvasRenderingContext2DAzure(nsID
 
   *aResult = ctx.forget().get();
   return NS_OK;
 }
 
 nsCanvasRenderingContext2DAzure::nsCanvasRenderingContext2DAzure()
   : mValid(false), mZero(false), mOpaque(false), mResetLayer(true)
   , mIPC(false)
-  , mCanvasElement(nsnull)
   , mIsEntireFrameInvalid(false)
   , mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false)
   , mInvalidateCount(0)
 {
   sNumLivingContexts++;
 }
 
 nsCanvasRenderingContext2DAzure::~nsCanvasRenderingContext2DAzure()
@@ -1004,21 +1002,51 @@ nsCanvasRenderingContext2DAzure::~nsCanv
   if (!sNumLivingContexts) {
     delete[] sUnpremultiplyTable;
     delete[] sPremultiplyTable;
     sUnpremultiplyTable = nsnull;
     sPremultiplyTable = nsnull;
   }
 }
 
+bool
+nsCanvasRenderingContext2DAzure::ParseColor(const nsAString& aString,
+                                            nscolor* aColor)
+{
+  nsIDocument* document = mCanvasElement
+                          ? mCanvasElement->OwnerDoc()
+                          : nsnull;
+
+  // Pass the CSS Loader object to the parser, to allow parser error
+  // reports to include the outer window ID.
+  nsCSSParser parser(document ? document->CSSLoader() : nsnull);
+  nsCSSValue value;
+  if (!parser.ParseColorString(aString, nsnull, 0, value)) {
+    return false;
+  }
+
+  nsIPresShell* presShell = GetPresShell();
+  nsRefPtr<nsStyleContext> parentContext;
+  if (mCanvasElement && mCanvasElement->IsInDoc()) {
+    // Inherit from the canvas element.
+    parentContext = nsComputedDOMStyle::GetStyleContextForElement(
+      mCanvasElement, nsnull, presShell);
+  }
+
+  unused << nsRuleNode::ComputeColor(
+    value, presShell ? presShell->GetPresContext() : nsnull, parentContext,
+    *aColor);
+  return true;
+}
+
 nsresult
 nsCanvasRenderingContext2DAzure::Reset()
 {
   if (mCanvasElement) {
-    HTMLCanvasElement()->InvalidateCanvas();
+    mCanvasElement->InvalidateCanvas();
   }
 
   // only do this for non-docshell created contexts,
   // since those are the ones that we created a surface for
   if (mValid && !mDocShell) {
     gCanvasAzureMemoryUsed -= mWidth * mHeight * 4;
   }
 
@@ -1034,29 +1062,19 @@ nsCanvasRenderingContext2DAzure::Reset()
   return NS_OK;
 }
 
 nsresult
 nsCanvasRenderingContext2DAzure::SetStyleFromStringOrInterface(const nsAString& aStr,
                                                                nsISupports *aInterface,
                                                                Style aWhichStyle)
 {
-  nsresult rv;
-  nscolor color;
-
   if (!aStr.IsVoid()) {
-    nsIDocument* document = mCanvasElement ?
-                            HTMLCanvasElement()->OwnerDoc() : nsnull;
-
-    // Pass the CSS Loader object to the parser, to allow parser error
-    // reports to include the outer window ID.
-    nsCSSParser parser(document ? document->CSSLoader() : nsnull);
-    rv = parser.ParseColorString(aStr, nsnull, 0, &color);
-    if (NS_FAILED(rv)) {
-      // Error reporting happens inside the CSS parser
+    nscolor color;
+    if (!ParseColor(aStr, &color)) {
       return NS_OK;
     }
 
     CurrentState().SetColorStyle(aWhichStyle, color);
     return NS_OK;
   }
 
   if (aInterface) {
@@ -1071,17 +1089,17 @@ nsCanvasRenderingContext2DAzure::SetStyl
       CurrentState().SetPatternStyle(aWhichStyle, pattern);
       return NS_OK;
     }
   }
 
   nsContentUtils::ReportToConsole(
     nsIScriptError::warningFlag,
     "Canvas",
-    mCanvasElement ? HTMLCanvasElement()->OwnerDoc() : nsnull,
+    mCanvasElement ? mCanvasElement->OwnerDoc() : nsnull,
     nsContentUtils::eDOM_PROPERTIES,
     "UnexpectedCanvasVariantStyle");
 
   return NS_OK;
 }
 
 nsresult
 nsCanvasRenderingContext2DAzure::GetStyleAsStringOrInterface(nsAString& aStr,
@@ -1144,19 +1162,19 @@ nsCanvasRenderingContext2DAzure::Redraw(
     return NS_OK;
   }
 
   if (!mThebesSurface)
     mThebesSurface =
       gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget);
   mThebesSurface->MarkDirty();
 
-  nsSVGEffects::InvalidateDirectRenderingObservers(HTMLCanvasElement());
-
-  HTMLCanvasElement()->InvalidateCanvasContent(nsnull);
+  nsSVGEffects::InvalidateDirectRenderingObservers(mCanvasElement);
+
+  mCanvasElement->InvalidateCanvasContent(nsnull);
 
   return NS_OK;
 }
 
 void
 nsCanvasRenderingContext2DAzure::Redraw(const mgfx::Rect &r)
 {
   ++mInvalidateCount;
@@ -1176,20 +1194,20 @@ nsCanvasRenderingContext2DAzure::Redraw(
     return;
   }
 
   if (!mThebesSurface)
     mThebesSurface =
       gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget);
   mThebesSurface->MarkDirty();
 
-  nsSVGEffects::InvalidateDirectRenderingObservers(HTMLCanvasElement());
+  nsSVGEffects::InvalidateDirectRenderingObservers(mCanvasElement);
 
   gfxRect tmpR = ThebesRect(r);
-  HTMLCanvasElement()->InvalidateCanvasContent(&tmpR);
+  mCanvasElement->InvalidateCanvasContent(&tmpR);
 
   return;
 }
 
 nsresult
 nsCanvasRenderingContext2DAzure::RedrawUser(const gfxRect& r)
 {
   if (mIsEntireFrameInvalid) {
@@ -1466,24 +1484,16 @@ nsCanvasRenderingContext2DAzure::GetSurf
   return mOpaque ? FORMAT_B8G8R8X8 : FORMAT_B8G8R8A8;
 }
 
 //
 // nsCanvasRenderingContext2DAzure impl
 //
 
 NS_IMETHODIMP
-nsCanvasRenderingContext2DAzure::SetCanvasElement(nsHTMLCanvasElement* aCanvasElement)
-{
-  mCanvasElement = aCanvasElement;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::GetCanvas(nsIDOMHTMLCanvasElement **canvas)
 {
   NS_IF_ADDREF(*canvas = mCanvasElement);
 
   return NS_OK;
 }
 
 //
@@ -2009,30 +2019,23 @@ nsCanvasRenderingContext2DAzure::SetShad
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::GetShadowBlur(float *blur)
 {
   *blur = CurrentState().shadowBlur;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsCanvasRenderingContext2DAzure::SetShadowColor(const nsAString& colorstr)
+nsCanvasRenderingContext2DAzure::SetShadowColor(const nsAString& aColor)
 {
-  nsIDocument* document = mCanvasElement ?
-                          HTMLCanvasElement()->OwnerDoc() : nsnull;
-
-  // Pass the CSS Loader object to the parser, to allow parser error reports
-  // to include the outer window ID.
-  nsCSSParser parser(document ? document->CSSLoader() : nsnull);
   nscolor color;
-  nsresult rv = parser.ParseColorString(colorstr, nsnull, 0, &color);
-  if (NS_FAILED(rv)) {
-    // Error reporting happens inside the CSS parser
+  if (!ParseColor(aColor, &color)) {
     return NS_OK;
   }
+
   CurrentState().shadowColor = color;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::GetShadowColor(nsAString& color)
 {
@@ -2655,19 +2658,18 @@ nsCanvasRenderingContext2DAzure::SetFont
   /*
     * If font is defined with relative units (e.g. ems) and the parent
     * style context changes in between calls, setting the font to the
     * same value as previous could result in a different computed value,
     * so we cannot have the optimization where we check if the new font
     * string is equal to the old one.
     */
 
-  nsCOMPtr<nsIContent> content = do_QueryInterface(mCanvasElement);
-  if (!content && !mDocShell) {
-      NS_WARNING("Canvas element must be an nsIContent and non-null or a docshell must be provided");
+  if (!mCanvasElement && !mDocShell) {
+      NS_WARNING("Canvas element must be non-null or a docshell must be provided");
       return NS_ERROR_FAILURE;
   }
 
   nsIPresShell* presShell = GetPresShell();
   if (!presShell) {
     return NS_ERROR_FAILURE;
   }
   nsIDocument* document = presShell->GetDocument();
@@ -2700,20 +2702,20 @@ nsCanvasRenderingContext2DAzure::SetFont
   rules.AppendObject(rule);
 
   nsStyleSet* styleSet = presShell->StyleSet();
 
   // have to get a parent style context for inherit-like relative
   // values (2em, bolder, etc.)
   nsRefPtr<nsStyleContext> parentContext;
 
-  if (content && content->IsInDoc()) {
+  if (mCanvasElement && mCanvasElement->IsInDoc()) {
       // inherit from the canvas element
       parentContext = nsComputedDOMStyle::GetStyleContextForElement(
-              content->AsElement(),
+              mCanvasElement,
               nsnull,
               presShell);
   } else {
     // otherwise inherit from default (10px sans-serif)
     nsRefPtr<css::StyleRule> parentRule;
     rv = CreateFontStyleRule(NS_LITERAL_STRING("10px sans-serif"),
                               document,
                               getter_AddRefs(parentRule));
@@ -3143,39 +3145,38 @@ nsCanvasRenderingContext2DAzure::DrawOrM
 
   // spec isn't clear on what should happen if aMaxWidth <= 0, so
   // treat it as an invalid argument
   // technically, 0 should be an invalid value as well, but 0 is the default
   // arg, and there is no way to tell if the default was used
   if (aMaxWidth < 0)
     return NS_ERROR_INVALID_ARG;
 
-  nsCOMPtr<nsIContent> content = do_QueryInterface(mCanvasElement);
-  if (!content && !mDocShell) {
-      NS_WARNING("Canvas element must be an nsIContent and non-null or a docshell must be provided");
+  if (!mCanvasElement && !mDocShell) {
+    NS_WARNING("Canvas element must be non-null or a docshell must be provided");
     return NS_ERROR_FAILURE;
   }
 
   nsIPresShell* presShell = GetPresShell();
   if (!presShell)
       return NS_ERROR_FAILURE;
 
   nsIDocument* document = presShell->GetDocument();
 
   // replace all the whitespace characters with U+0020 SPACE
   nsAutoString textToDraw(aRawText);
   TextReplaceWhitespaceCharacters(textToDraw);
 
   // for now, default to ltr if not in doc
   bool isRTL = false;
 
-  if (content && content->IsInDoc()) {
+  if (mCanvasElement && mCanvasElement->IsInDoc()) {
     // try to find the closest context
     nsRefPtr<nsStyleContext> canvasStyle =
-      nsComputedDOMStyle::GetStyleContextForElement(content->AsElement(),
+      nsComputedDOMStyle::GetStyleContextForElement(mCanvasElement,
                                                     nsnull,
                                                     presShell);
     if (!canvasStyle) {
       return NS_ERROR_FAILURE;
     }
 
     isRTL = canvasStyle->GetStyleVisibility()->mDirection ==
       NS_STYLE_DIRECTION_RTL;
@@ -3604,25 +3605,25 @@ nsCanvasRenderingContext2DAzure::DrawIma
       srcSurf = mTarget->Snapshot();
       imgSize = gfxIntSize(mWidth, mHeight);
     } else if (srcCanvas) {
       // This might not be an Azure canvas!
       srcSurf = srcCanvas->GetSurfaceSnapshot();
 
       if (srcSurf && mCanvasElement) {
         // Do security check here.
-        CanvasUtils::DoDrawImageSecurityCheck(HTMLCanvasElement(),
+        CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
                                               content->NodePrincipal(), canvas->IsWriteOnly(),
                                               false);
         imgSize = gfxIntSize(srcSurf->GetSize().width, srcSurf->GetSize().height);
       }
     }
   } else {
     gfxASurface* imgsurf =
-      CanvasImageCache::Lookup(imgElt, HTMLCanvasElement(), &imgSize);
+      CanvasImageCache::Lookup(imgElt, mCanvasElement, &imgSize);
     if (imgsurf) {
       srcSurf = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, imgsurf);
     }
   }
 
   if (!srcSurf) {
     // The canvas spec says that drawImage should draw the first frame
     // of animated images
@@ -3638,23 +3639,23 @@ nsCanvasRenderingContext2DAzure::DrawIma
     // Ignore cairo surfaces that are bad! See bug 666312.
     if (res.mSurface->CairoStatus()) {
       return NS_OK;
     }
 
     imgSize = res.mSize;
 
     if (mCanvasElement) {
-      CanvasUtils::DoDrawImageSecurityCheck(HTMLCanvasElement(),
+      CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
                                             res.mPrincipal, res.mIsWriteOnly,
                                             res.mCORSUsed);
     }
 
     if (res.mImageRequest) {
-      CanvasImageCache::NotifyDrawImage(imgElt, HTMLCanvasElement(),
+      CanvasImageCache::NotifyDrawImage(imgElt, mCanvasElement,
                                         res.mImageRequest, res.mSurface, imgSize);
     }
 
     srcSurf = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, res.mSurface);
   }
 
   if (optional_argc == 0) {
     dx = a1;
@@ -3783,17 +3784,17 @@ nsCanvasRenderingContext2DAzure::DrawWin
                                             const nsAString& aBGColor,
                                             PRUint32 flags)
 {
   NS_ENSURE_ARG(aWindow != nsnull);
 
   // protect against too-large surfaces that will cause allocation
   // or overflow issues
   if (!gfxASurface::CheckSurfaceSize(gfxIntSize(PRInt32(aW), PRInt32(aH)),
-                                      0xffff))
+                                     0xffff))
     return NS_ERROR_FAILURE;
 
   nsRefPtr<gfxASurface> drawSurf;
   GetThebesSurface(getter_AddRefs(drawSurf));
 
   nsRefPtr<gfxContext> thebes = new gfxContext(drawSurf);
 
   Matrix matrix = mTarget->GetTransform();
@@ -3823,29 +3824,19 @@ nsCanvasRenderingContext2DAzure::DrawWin
     if (docshell) {
       docshell->GetPresContext(getter_AddRefs(presContext));
     }
   }
   if (!presContext)
     return NS_ERROR_FAILURE;
 
   nscolor bgColor;
-
-  nsIDocument* elementDoc = mCanvasElement ?
-                            HTMLCanvasElement()->OwnerDoc() : nsnull;
-
-  // Pass the CSS Loader object to the parser, to allow parser error reports
-  // to include the outer window ID.
-  nsCSSParser parser(elementDoc ? elementDoc->CSSLoader() : nsnull);
-  nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor),
-                                        nsnull, 0, &bgColor);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsIPresShell* presShell = presContext->PresShell();
-  NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
+  if (!ParseColor(aBGColor, &bgColor)) {
+    return NS_ERROR_FAILURE;
+  }
 
   nsRect r(nsPresContext::CSSPixelsToAppUnits(aX),
            nsPresContext::CSSPixelsToAppUnits(aY),
            nsPresContext::CSSPixelsToAppUnits(aW),
            nsPresContext::CSSPixelsToAppUnits(aH));
   PRUint32 renderDocFlags = (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
                              nsIPresShell::RENDER_DOCUMENT_RELATIVE);
   if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DRAW_CARET) {
@@ -3857,17 +3848,18 @@ nsCanvasRenderingContext2DAzure::DrawWin
   }
   if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_USE_WIDGET_LAYERS) {
     renderDocFlags |= nsIPresShell::RENDER_USE_WIDGET_LAYERS;
   }
   if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_ASYNC_DECODE_IMAGES) {
     renderDocFlags |= nsIPresShell::RENDER_ASYNC_DECODE_IMAGES;
   }
 
-  rv = presShell->RenderDocument(r, renderDocFlags, bgColor, thebes);
+  unused << presContext->PresShell()->
+    RenderDocument(r, renderDocFlags, bgColor, thebes);
 
   // note that aX and aY are coordinates in the document that
   // we're drawing; aX and aY are drawn to 0,0 in current user
   // space.
   RedrawUser(gfxRect(0, 0, aW, aH));
 
   return NS_OK;
 }
@@ -3993,18 +3985,17 @@ nsCanvasRenderingContext2DAzure::GetImag
 
   if (!mCanvasElement && !mDocShell) {
     NS_ERROR("No canvas element and no docshell in GetImageData!!!");
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   // Check only if we have a canvas element; if we were created with a docshell,
   // then it's special internal use.
-  if (mCanvasElement &&
-      HTMLCanvasElement()->IsWriteOnly() &&
+  if (mCanvasElement && mCanvasElement->IsWriteOnly() &&
       !nsContentUtils::IsCallerTrustedForRead())
   {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   if (!NS_finite(aSx) || !NS_finite(aSy) ||
       !NS_finite(aSw) || !NS_finite(aSh)) {
@@ -4201,29 +4192,29 @@ nsCanvasRenderingContext2DAzure::PutImag
       NS_ENSURE_TRUE(dirtyWidth != INT_MIN, NS_ERROR_DOM_INDEX_SIZE_ERR);
 
       CheckedInt32 checkedDirtyX = CheckedInt32(dirtyX) + dirtyWidth;
 
       if (!checkedDirtyX.isValid())
           return NS_ERROR_DOM_INDEX_SIZE_ERR;
 
       dirtyX = checkedDirtyX.value();
-      dirtyWidth = -(int32)dirtyWidth;
+      dirtyWidth = -dirtyWidth;
     }
 
     if (dirtyHeight < 0) {
       NS_ENSURE_TRUE(dirtyHeight != INT_MIN, NS_ERROR_DOM_INDEX_SIZE_ERR);
 
       CheckedInt32 checkedDirtyY = CheckedInt32(dirtyY) + dirtyHeight;
 
       if (!checkedDirtyY.isValid())
           return NS_ERROR_DOM_INDEX_SIZE_ERR;
 
       dirtyY = checkedDirtyY.value();
-      dirtyHeight = -(int32)dirtyHeight;
+      dirtyHeight = -dirtyHeight;
     }
 
     // bound the dirty rect within the imageData rectangle
     dirtyRect = imageDataRect.Intersect(IntRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight));
 
     if (dirtyRect.Width() <= 0 || dirtyRect.Height() <= 0)
         return NS_OK;
   } else {
@@ -4391,17 +4382,17 @@ nsCanvasRenderingContext2DAzure::GetCanv
     // and if there is, flushing the invalidation state more often than
     // necessary is harmless).
 
     // The layer will be destroyed when we tear down the presentation
     // (at the latest), at which time this userData will be destroyed,
     // releasing the reference to the element.
     // The userData will receive DidTransactionCallbacks, which flush the
     // the invalidation state to indicate that the canvas is up to date.
-    userData = new CanvasRenderingContext2DUserData(HTMLCanvasElement());
+    userData = new CanvasRenderingContext2DUserData(mCanvasElement);
     canvasLayer->SetDidTransactionCallback(
             CanvasRenderingContext2DUserData::DidTransactionCallback, userData);
   }
   canvasLayer->SetUserData(&g2DContextLayerUserData, userData);
 
   CanvasLayer::Data data;
 
   data.mDrawTarget = mTarget;
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -4115,17 +4115,17 @@ function test_2d_fillStyle_parse_current
 
 var canvas = document.getElementById('c143');
 var ctx = canvas.getContext('2d');
 
 canvas.setAttribute('style', 'color: #0f0');
 ctx.fillStyle = '#f00';
 ctx.fillStyle = 'currentColor';
 ctx.fillRect(0, 0, 100, 50);
-todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
+isPixel(ctx, 50,25, 0,255,0,255, 0);
 
 
 }
 </script>
 
 <!-- [[[ test_2d.fillStyle.parse.current.changed.html ]]] -->
 
 <p>Canvas test: 2d.fillStyle.parse.current.changed</p>
@@ -4140,17 +4140,17 @@ function test_2d_fillStyle_parse_current
 var canvas = document.getElementById('c144');
 var ctx = canvas.getContext('2d');
 
 canvas.setAttribute('style', 'color: #0f0');
 ctx.fillStyle = '#f00';
 ctx.fillStyle = 'currentColor';
 canvas.setAttribute('style', 'color: #f00');
 ctx.fillRect(0, 0, 100, 50);
-todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
+isPixel(ctx, 50,25, 0,255,0,255, 0);
 
 
 }
 </script>
 
 <!-- [[[ test_2d.fillStyle.parse.current.removed.html ]]] -->
 
 <p>Canvas test: 2d.fillStyle.parse.current.removed</p>
@@ -4176,17 +4176,17 @@ var ctx2 = canvas2.getContext('2d');
 ctx2.fillStyle = '#f00';
 ctx2.fillStyle = 'currentColor';
 ctx2.fillRect(0, 0, 100, 50);
 ctx.drawImage(canvas2, 0, 0);
 
 document.body.parentNode.removeAttribute('style');
 document.body.removeAttribute('style');
 
-todo_isPixel(ctx, 50,25, 0,0,0,255, 0);
+isPixel(ctx, 50,25, 0,0,0,255, 0);
 
 
 }
 </script>
 
 <!-- [[[ test_2d.fillStyle.parse.hex3.html ]]] -->
 
 <p>Canvas test: 2d.fillStyle.parse.hex3</p>
--- a/content/events/public/nsEventStates.h
+++ b/content/events/public/nsEventStates.h
@@ -231,16 +231,22 @@ private:
 #define NS_EVENT_STATE_MOZ_UI_VALID NS_DEFINE_EVENT_STATE_MACRO(33)
 // Content is the full screen element, or a frame containing the
 // current full-screen element.
 #define NS_EVENT_STATE_FULL_SCREEN   NS_DEFINE_EVENT_STATE_MACRO(34)
 // Content is an ancestor of the DOM full-screen element.
 #define NS_EVENT_STATE_FULL_SCREEN_ANCESTOR   NS_DEFINE_EVENT_STATE_MACRO(35)
 // Handler for click to play plugin
 #define NS_EVENT_STATE_TYPE_CLICK_TO_PLAY NS_DEFINE_EVENT_STATE_MACRO(36)
+// Content is in the optimum region.
+#define NS_EVENT_STATE_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(37)
+// Content is in the suboptimal region.
+#define NS_EVENT_STATE_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(38)
+// Content is in the sub-suboptimal region.
+#define NS_EVENT_STATE_SUB_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(39)
 
 /**
  * NOTE: do not go over 63 without updating nsEventStates::InternalType!
  */
 
 #define ESM_MANAGED_STATES (NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS |     \
                             NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER |   \
                             NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \
--- a/content/events/src/nsDOMDataTransfer.h
+++ b/content/events/src/nsDOMDataTransfer.h
@@ -12,17 +12,16 @@
 #include "nsIPrincipal.h"
 #include "nsIDOMDataTransfer.h"
 #include "nsIDragService.h"
 #include "nsIDOMElement.h"
 #include "nsCycleCollectionParticipant.h"
 
 #include "nsAutoPtr.h"
 #include "nsIFile.h"
-#include "nsILocalFile.h"
 #include "nsDOMFile.h"
 
 class nsITransferable;
 
 /**
  * TransferItem is used to hold data for a particular format. Each piece of
  * data has a principal set from the caller which added it. This allows a
  * caller that wishes to retrieve the data to only be able to access the data
--- a/content/html/content/public/nsHTMLCanvasElement.h
+++ b/content/html/content/public/nsHTMLCanvasElement.h
@@ -11,24 +11,24 @@
 #include "nsGkAtoms.h"
 #include "nsSize.h"
 #include "nsIFrame.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsDOMError.h"
 #include "nsNodeInfoManager.h"
 
-#include "nsICanvasRenderingContextInternal.h"
 #include "nsICanvasElementExternal.h"
-#include "nsIDOMCanvasRenderingContext2D.h"
 #include "nsLayoutUtils.h"
 
 #include "Layers.h"
 
+class nsICanvasRenderingContextInternal;
 class nsIDOMFile;
+class nsIPropertyBag;
 
 class nsHTMLCanvasElement : public nsGenericHTMLElement,
                             public nsICanvasElementExternal,
                             public nsIDOMHTMLCanvasElement
 {
   typedef mozilla::layers::CanvasLayer CanvasLayer;
   typedef mozilla::layers::LayerManager LayerManager;
 
--- a/content/html/content/public/nsIFormControl.h
+++ b/content/html/content/public/nsIFormControl.h
@@ -21,16 +21,17 @@ class Element;
 
 enum FormControlsTypes {
   NS_FORM_FIELDSET = 1,
   NS_FORM_LABEL,
   NS_FORM_OUTPUT,
   NS_FORM_SELECT,
   NS_FORM_TEXTAREA,
   NS_FORM_OBJECT,
+  NS_FORM_METER,
   eFormControlsWithoutSubTypesMax,
   // After this, all types will have sub-types which introduce new enum lists.
   // eFormControlsWithoutSubTypesMax let us know if the previous types values
   // are not overlapping with sub-types/masks.
 
   // Elements with different types, the value is used as a mask.
   // Adding '_ELEMENT' because NS_FORM_INPUT is used for 'oninput' event.
   // When changing the order, adding or removing elements, be sure to update
@@ -238,23 +239,22 @@ nsIFormControl::IsSingleLineTextControl(
          aType == NS_FORM_INPUT_URL ||
          (!aExcludePassword && aType == NS_FORM_INPUT_PASSWORD);
 }
 
 bool
 nsIFormControl::IsLabelableControl() const
 {
   // TODO: keygen should be in that list, see bug 101019.
-  // TODO: meter should be added, see bug 555985.
   // TODO: NS_FORM_INPUT_HIDDEN should be removed, see bug 597650.
   PRUint32 type = GetType();
   return type & NS_FORM_INPUT_ELEMENT ||
          type & NS_FORM_BUTTON_ELEMENT ||
          // type == NS_FORM_KEYGEN ||
-         // type == NS_FORM_METER ||
+         type == NS_FORM_METER ||
          type == NS_FORM_OUTPUT ||
          type == NS_FORM_SELECT ||
          type == NS_FORM_TEXTAREA;
 }
 
 bool
 nsIFormControl::IsSubmittableControl() const
 {
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -12,18 +12,20 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkconhtmlcon_s
 LIBXUL_LIBRARY	= 1
 FAIL_ON_WARNINGS = 1
 
 
 EXPORTS		= \
+		nsGenericHTMLElement.h \
 		nsClientRect.h \
 		nsHTMLDNSPrefetch.h \
+		nsTimeRanges.h \
 		$(NULL)
 
 CPPSRCS		= \
 		HTMLPropertiesCollection.cpp \
 		nsClientRect.cpp \
 		nsHTMLDNSPrefetch.cpp \
 		nsGenericHTMLElement.cpp \
 		nsGenericHTMLFrameElement.cpp \
@@ -51,16 +53,17 @@ CPPSRCS		= \
 		nsHTMLLIElement.cpp \
 		nsHTMLLabelElement.cpp \
 		nsHTMLLegendElement.cpp \
 		nsHTMLLinkElement.cpp \
 		nsHTMLMapElement.cpp \
 		nsHTMLMenuElement.cpp \
 		nsHTMLMenuItemElement.cpp \
 		nsHTMLMetaElement.cpp \
+		nsHTMLMeterElement.cpp \
 		nsHTMLModElement.cpp \
 		nsHTMLObjectElement.cpp \
 		nsHTMLOListElement.cpp \
 		nsHTMLSharedObjectElement.cpp \
 		nsHTMLOptionElement.cpp \
 		nsHTMLOptGroupElement.cpp \
 		nsHTMLOutputElement.cpp \
 		nsHTMLParagraphElement.cpp \
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -88,22 +88,22 @@
 #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"
+#include "nsDOMSettableTokenList.h"
+#include "nsThreadUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
-#include "nsThreadUtils.h"
-
 class nsINodeInfo;
 class nsIDOMNodeList;
 class nsRuleWalker;
 
 // XXX todo: add in missing out-of-memory checks
 
 //----------------------------------------------------------------------
 
@@ -3461,17 +3461,18 @@ nsGenericHTMLFormElement::ForgetFieldSet
 bool
 nsGenericHTMLFormElement::CanBeDisabled() const
 {
   PRInt32 type = GetType();
   // It's easier to test the types that _cannot_ be disabled
   return
     type != NS_FORM_LABEL &&
     type != NS_FORM_OBJECT &&
-    type != NS_FORM_OUTPUT;
+    type != NS_FORM_OUTPUT &&
+    type != NS_FORM_METER;
 }
 
 bool
 nsGenericHTMLFormElement::IsHTMLFocusable(bool aWithMouse,
                                           bool* aIsFocusable,
                                           PRInt32* aTabIndex)
 {
   if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -5,21 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef nsGenericHTMLElement_h___
 #define nsGenericHTMLElement_h___
 
 #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;
@@ -31,16 +28,18 @@ class nsPresState;
 class nsILayoutHistoryState;
 class nsIEditor;
 struct nsRect;
 struct nsSize;
 class nsHTMLFormElement;
 class nsIDOMDOMStringMap;
 class nsIDOMHTMLMenuElement;
 class nsIDOMHTMLCollection;
+class nsDOMSettableTokenList;
+class nsIDOMHTMLPropertiesCollection;
 
 typedef nsMappedAttributeElement nsGenericHTMLElementBase;
 
 /**
  * A common superclass for HTML elements
  */
 class nsGenericHTMLElement : public nsGenericHTMLElementBase
 {
@@ -1157,41 +1156,16 @@ PR_STATIC_ASSERT(ELEMENT_TYPE_SPECIFIC_B
   }                                                                       \
   NS_IMETHODIMP                                                           \
   _class::Set##_method(const nsAString& aValue)                           \
   {                                                                       \
     return SetAttrHelper(nsGkAtoms::_atom, aValue);                       \
   }
 
 /**
- * A macro to implement the getter and setter for a given content
- * property that needs to set a positive integer. The method uses
- * the generic GetAttr and SetAttr methods. This macro is much like
- * the NS_IMPL_NON_NEGATIVE_INT_ATTR macro except the exception is
- * thrown also when the value is equal to 0.
- */
-#define NS_IMPL_POSITIVE_INT_ATTR(_class, _method, _atom)                 \
-  NS_IMPL_POSITIVE_INT_ATTR_DEFAULT_VALUE(_class, _method, _atom, 1)
-
-#define NS_IMPL_POSITIVE_INT_ATTR_DEFAULT_VALUE(_class, _method, _atom, _default)  \
-  NS_IMETHODIMP                                                           \
-  _class::Get##_method(PRInt32* aValue)                                   \
-  {                                                                       \
-    return GetIntAttr(nsGkAtoms::_atom, _default, aValue);                \
-  }                                                                       \
-  NS_IMETHODIMP                                                           \
-  _class::Set##_method(PRInt32 aValue)                                    \
-  {                                                                       \
-    if (aValue <= 0) {                                                    \
-      return NS_ERROR_DOM_INDEX_SIZE_ERR;                                 \
-    }                                                                     \
-    return SetIntAttr(nsGkAtoms::_atom, aValue);                          \
-  }
-
-/**
  * QueryInterface() implementation helper macros
  */
 
 #define NS_HTML_CONTENT_INTERFACE_TABLE_AMBIGUOUS_BEGIN(_class, _base)        \
   NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class)                            \
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMNode, _base)             \
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMElement, _base)          \
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMHTMLElement, _base)
@@ -1565,16 +1539,17 @@ NS_DECLARE_NS_NEW_HTML_ELEMENT(Input)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(LI)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Label)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Legend)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Link)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Map)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Menu)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(MenuItem)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Meta)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Meter)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Object)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(OptGroup)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Option)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Output)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Paragraph)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Pre)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Progress)
 NS_DECLARE_NS_NEW_HTML_ELEMENT(Script)
--- a/content/html/content/src/nsGenericHTMLFrameElement.h
+++ b/content/html/content/src/nsGenericHTMLFrameElement.h
@@ -1,20 +1,22 @@
 /* -*- 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 "nsGenericHTMLElement.h"
-#include "nsIDOMHTMLFrameElement.h"
+#include "nsIFrameLoader.h"
 #include "nsIMozBrowserFrame.h"
 #include "nsIDOMEventListener.h"
 
+#include "nsFrameLoader.h"
+
 /**
  * A helper class for frame elements
  */
 class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
                                   public nsIFrameLoaderOwner,
                                   public nsIMozBrowserFrame
 {
 public:
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -6,16 +6,18 @@
 #include "nsHTMLCanvasElement.h"
 
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "nsNetUtil.h"
 #include "prmem.h"
 #include "nsDOMFile.h"
 
+#include "nsICanvasRenderingContextInternal.h"
+#include "nsIDOMCanvasRenderingContext2D.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIXPConnect.h"
 #include "jsapi.h"
 #include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "nsMathUtils.h"
 #include "nsStreamUtils.h"
 #include "mozilla/Preferences.h"
@@ -448,25 +450,19 @@ nsHTMLCanvasElement::GetContextHelper(co
     return NS_ERROR_OUT_OF_MEMORY;
   }
   if (NS_FAILED(rv)) {
     *aContext = nsnull;
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     return NS_OK;
   }
 
-  rv = ctx->SetCanvasElement(this);
-  if (NS_FAILED(rv)) {
-    *aContext = nsnull;
-    return rv;
-  }
-
+  ctx->SetCanvasElement(this);
   ctx.forget(aContext);
-
-  return rv;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
                                 const JS::Value& aContextOptions,
                                 nsISupports **aContext)
 {
   nsresult rv;
--- a/content/html/content/src/nsHTMLFieldSetElement.cpp
+++ b/content/html/content/src/nsHTMLFieldSetElement.cpp
@@ -123,17 +123,18 @@ nsHTMLFieldSetElement::GetType(nsAString
 }
 
 /* static */
 bool
 nsHTMLFieldSetElement::MatchListedElements(nsIContent* aContent, PRInt32 aNamespaceID,
                                            nsIAtom* aAtom, void* aData)
 {
   nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(aContent);
-  return formControl && formControl->GetType() != NS_FORM_LABEL;
+  return formControl && formControl->GetType() != NS_FORM_LABEL &&
+                        formControl->GetType() != NS_FORM_METER;
 }
 
 NS_IMETHODIMP
 nsHTMLFieldSetElement::GetElements(nsIDOMHTMLCollection** aElements)
 {
   if (!mElements) {
     mElements = new nsContentList(this, MatchListedElements, nsnull, nsnull,
                                   true);
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -186,16 +186,17 @@ ShouldBeInElements(nsIFormControl* aForm
     return true;
   }
 
   // These form control types are not supposed to end up in the
   // form.elements array
   //
   // NS_FORM_INPUT_IMAGE
   // NS_FORM_LABEL
+  // NS_FORM_METER
 
   return false;
 }
 
 // nsHTMLFormElement implementation
 
 // construction, destruction
 nsGenericHTMLElement*
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -9,16 +9,17 @@
 
 #include "nsIDOMHTMLInputElement.h"
 #include "nsITextControlElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIRadioVisitor.h"
 #include "nsIPhonetic.h"
 
 #include "nsIControllers.h"
+#include "nsIStringBundle.h"
 #include "nsFocusManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsContentCID.h"
 #include "nsIComponentManager.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
@@ -61,22 +62,23 @@
 #include "nsEventListenerManager.h"
 
 #include "nsRuleData.h"
 
 // input type=radio
 #include "nsIRadioGroupContainer.h"
 
 // input type=file
-#include "nsILocalFile.h"
+#include "nsIFile.h"
 #include "nsNetUtil.h"
 #include "nsDOMFile.h"
 #include "nsIFilePicker.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsIContentPrefService.h"
+#include "nsIMIMEService.h"
 #include "nsIObserverService.h"
 #include "nsIPopupWindowManager.h"
 #include "nsGlobalWindow.h"
 
 // input type=image
 #include "nsImageLoadingContent.h"
 
 #include "mozAutoDocUpdate.h"
@@ -265,70 +267,55 @@ AsyncClickHandler::Run()
 
   nsresult rv = filePicker->Init(win, title,
                                  multi
                                   ? static_cast<PRInt16>(nsIFilePicker::modeOpenMultiple)
                                   : static_cast<PRInt16>(nsIFilePicker::modeOpen));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::accept)) {
-    PRInt32 filters = mInput->GetFilterFromAccept();
-
-    if (filters) {
-      // We add |filterAll| to be sure the user always has a sane fallback.
-      filePicker->AppendFilters(filters | nsIFilePicker::filterAll);
-
-      // If the accept attribute asked for a filter, we need to make it default.
-      // |filterAll| will always use index=0 so we need to set index=1 as the
-      // current filter.
-      filePicker->SetFilterIndex(1);
-    } else {
-      filePicker->AppendFilters(nsIFilePicker::filterAll);
-    }
+    mInput->SetFilePickerFiltersFromAccept(filePicker);
   } else {
     filePicker->AppendFilters(nsIFilePicker::filterAll);
   }
 
   // Set default directry and filename
   nsAutoString defaultName;
 
   const nsCOMArray<nsIDOMFile>& oldFiles = mInput->GetFiles();
 
   if (oldFiles.Count()) {
     nsString path;
 
     oldFiles[0]->GetMozFullPathInternal(path);
 
-    nsCOMPtr<nsILocalFile> localFile;
+    nsCOMPtr<nsIFile> localFile;
     rv = NS_NewLocalFile(path, false, getter_AddRefs(localFile));
 
     if (NS_SUCCEEDED(rv)) {
       nsCOMPtr<nsIFile> parentFile;
       rv = localFile->GetParent(getter_AddRefs(parentFile));
       if (NS_SUCCEEDED(rv)) {
-        nsCOMPtr<nsILocalFile> parentLocalFile = do_QueryInterface(parentFile, &rv);
-        if (parentLocalFile) {
-          filePicker->SetDisplayDirectory(parentLocalFile);
-        }
+        filePicker->SetDisplayDirectory(parentFile);
       }
     }
 
     // Unfortunately nsIFilePicker doesn't allow multiple files to be
     // default-selected, so only select something by default if exactly
     // one file was selected before.
     if (oldFiles.Count() == 1) {
       nsAutoString leafName;
       oldFiles[0]->GetName(leafName);
       if (!leafName.IsEmpty()) {
         filePicker->SetDefaultString(leafName);
       }
     }
   } else {
     // Attempt to retrieve the last used directory from the content pref service
-    nsCOMPtr<nsILocalFile> localFile;
+    nsCOMPtr<nsIFile> localFile;
     nsHTMLInputElement::gUploadLastDir->FetchLastUsedDirectory(doc->GetDocumentURI(),
                                                                getter_AddRefs(localFile));
     if (!localFile) {
       // Default to "desktop" directory for each platform
       nsCOMPtr<nsIFile> homeDir;
       NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(homeDir));
       localFile = do_QueryInterface(homeDir);
     }
@@ -353,17 +340,17 @@ AsyncClickHandler::Run()
     rv = filePicker->GetFiles(getter_AddRefs(iter));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsISupports> tmp;
     bool prefSaved = false;
     bool loop = true;
     while (NS_SUCCEEDED(iter->HasMoreElements(&loop)) && loop) {
       iter->GetNext(getter_AddRefs(tmp));
-      nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(tmp);
+      nsCOMPtr<nsIFile> localFile = do_QueryInterface(tmp);
       if (localFile) {
         nsString unicodePath;
         rv = localFile->GetPath(unicodePath);
         if (!unicodePath.IsEmpty()) {
           nsCOMPtr<nsIDOMFile> domFile =
             do_QueryObject(new nsDOMFileFile(localFile));
           newFiles.AppendObject(domFile);
         }
@@ -372,17 +359,17 @@ AsyncClickHandler::Run()
           nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(doc->GetDocumentURI(),
                                                                      localFile);
           prefSaved = true;
         }
       }
     }
   }
   else {
-    nsCOMPtr<nsILocalFile> localFile;
+    nsCOMPtr<nsIFile> localFile;
     rv = filePicker->GetFile(getter_AddRefs(localFile));
     if (localFile) {
       nsString unicodePath;
       rv = localFile->GetPath(unicodePath);
       if (!unicodePath.IsEmpty()) {
         nsCOMPtr<nsIDOMFile> domFile=
           do_QueryObject(new nsDOMFileFile(localFile));
         newFiles.AppendObject(domFile);
@@ -425,17 +412,17 @@ nsHTMLInputElement::InitUploadLastDir() 
 }
 
 void 
 nsHTMLInputElement::DestroyUploadLastDir() {
   NS_IF_RELEASE(gUploadLastDir);
 }
 
 nsresult
-UploadLastDir::FetchLastUsedDirectory(nsIURI* aURI, nsILocalFile** aFile)
+UploadLastDir::FetchLastUsedDirectory(nsIURI* aURI, nsIFile** aFile)
 {
   NS_PRECONDITION(aURI, "aURI is null");
   NS_PRECONDITION(aFile, "aFile is null");
   // Attempt to get the CPS, if it's not present we'll just return
   nsCOMPtr<nsIContentPrefService> contentPrefService =
     do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
   if (!contentPrefService)
     return NS_ERROR_NOT_AVAILABLE;
@@ -447,36 +434,35 @@ UploadLastDir::FetchLastUsedDirectory(ns
   // Get the last used directory, if it is stored
   bool hasPref;
   if (NS_SUCCEEDED(contentPrefService->HasPref(uri, CPS_PREF_NAME, &hasPref)) && hasPref) {
     nsCOMPtr<nsIVariant> pref;
     contentPrefService->GetPref(uri, CPS_PREF_NAME, nsnull, getter_AddRefs(pref));
     nsString prefStr;
     pref->GetAsAString(prefStr);
 
-    nsCOMPtr<nsILocalFile> localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
+    nsCOMPtr<nsIFile> localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
     if (!localFile)
       return NS_ERROR_OUT_OF_MEMORY;
     localFile->InitWithPath(prefStr);
     localFile.forget(aFile);
   }
   return NS_OK;
 }
 
 nsresult
-UploadLastDir::StoreLastUsedDirectory(nsIURI* aURI, nsILocalFile* aFile)
+UploadLastDir::StoreLastUsedDirectory(nsIURI* aURI, nsIFile* aFile)
 {
   NS_PRECONDITION(aURI, "aURI is null");
   NS_PRECONDITION(aFile, "aFile is null");
   nsCOMPtr<nsIFile> parentFile;
   aFile->GetParent(getter_AddRefs(parentFile));
   if (!parentFile) {
     return NS_OK;
   }
-  nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(parentFile);
 
   // Attempt to get the CPS, if it's not present we'll just return
   nsCOMPtr<nsIContentPrefService> contentPrefService =
     do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
   if (!contentPrefService)
     return NS_ERROR_NOT_AVAILABLE;
   nsCOMPtr<nsIWritableVariant> uri = do_CreateInstance(NS_VARIANT_CONTRACTID);
   if (!uri)
@@ -1060,20 +1046,18 @@ nsHTMLInputElement::MozSetFileNameArray(
       // Converts the URL string into the corresponding nsIFile if possible
       // A local file will be created if the URL string begins with file://
       NS_GetFileFromURLSpec(NS_ConvertUTF16toUTF8(aFileNames[i]),
                             getter_AddRefs(file));
     }
 
     if (!file) {
       // this is no "file://", try as local file
-      nsCOMPtr<nsILocalFile> localFile;
       NS_NewLocalFile(nsDependentString(aFileNames[i]),
-                      false, getter_AddRefs(localFile));
-      file = do_QueryInterface(localFile);
+                      false, getter_AddRefs(file));
     }
 
     if (file) {
       nsCOMPtr<nsIDOMFile> domFile = new nsDOMFileFile(file);
       files.AppendObject(domFile);
     } else {
       continue; // Not much we can do if the file doesn't exist
     }
@@ -4099,16 +4083,163 @@ void
 nsHTMLInputElement::FieldSetDisabledChanged(bool aNotify)
 {
   UpdateValueMissingValidityState();
   UpdateBarredFromConstraintValidation();
 
   nsGenericHTMLFormElement::FieldSetDisabledChanged(aNotify);
 }
 
+void
+nsHTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
+{
+  // We always add |filterAll|
+  filePicker->AppendFilters(nsIFilePicker::filterAll);
+
+  NS_ASSERTION(HasAttr(kNameSpaceID_None, nsGkAtoms::accept),
+               "You should not call SetFilePickerFiltersFromAccept if the"
+               " element has no accept attribute!");
+
+  // Services to retrieve image/*, audio/*, video/* filters
+  nsCOMPtr<nsIStringBundleService> stringService =
+    mozilla::services::GetStringBundleService();
+  if (!stringService) {
+    return;
+  }
+  nsCOMPtr<nsIStringBundle> filterBundle;
+  if (NS_FAILED(stringService->CreateBundle("chrome://global/content/filepicker.properties",
+                                            getter_AddRefs(filterBundle)))) {
+    return;
+  }
+
+  // Service to retrieve mime type information for mime types filters
+  nsCOMPtr<nsIMIMEService> mimeService = do_GetService("@mozilla.org/mime;1");
+  if (!mimeService) {
+    return;
+  }
+
+  nsAutoString accept;
+  GetAttr(kNameSpaceID_None, nsGkAtoms::accept, accept);
+
+  HTMLSplitOnSpacesTokenizer tokenizer(accept, ',');
+
+  nsTArray<nsFilePickerFilter> filters;
+  nsString allExtensionsList;
+
+  // Retrieve all filters
+  while (tokenizer.hasMoreTokens()) {
+    const nsDependentSubstring& token = tokenizer.nextToken();
+
+    if (token.IsEmpty()) {
+      continue;
+    }
+
+    PRInt32 filterMask = 0;
+    nsString filterName;
+    nsString extensionListStr;
+
+    // First, check for image/audio/video filters...
+    if (token.EqualsLiteral("image/*")) {
+      filterMask = nsIFilePicker::filterImages;
+      filterBundle->GetStringFromName(NS_LITERAL_STRING("imageFilter").get(),
+                                      getter_Copies(extensionListStr));
+    } else if (token.EqualsLiteral("audio/*")) {
+      filterMask = nsIFilePicker::filterAudio;
+      filterBundle->GetStringFromName(NS_LITERAL_STRING("audioFilter").get(),
+                                      getter_Copies(extensionListStr));
+    } else if (token.EqualsLiteral("video/*")) {
+      filterMask = nsIFilePicker::filterVideo;
+      filterBundle->GetStringFromName(NS_LITERAL_STRING("videoFilter").get(),
+                                      getter_Copies(extensionListStr));
+    } else {
+      //... if no image/audio/video filter is found, check mime types filters
+      nsCOMPtr<nsIMIMEInfo> mimeInfo;
+      if (NS_FAILED(mimeService->GetFromTypeAndExtension(
+                      NS_ConvertUTF16toUTF8(token),
+                      EmptyCString(), // No extension
+                      getter_AddRefs(mimeInfo))) ||
+          !mimeInfo) {
+        continue;
+      }
+
+      // Get mime type name
+      nsCString mimeTypeName;
+      mimeInfo->GetType(mimeTypeName);
+      CopyUTF8toUTF16(mimeTypeName, filterName);
+
+      // Get extension list
+      nsCOMPtr<nsIUTF8StringEnumerator> extensions;
+      mimeInfo->GetFileExtensions(getter_AddRefs(extensions));
+
+      bool hasMore;
+      while (NS_SUCCEEDED(extensions->HasMore(&hasMore)) && hasMore) {
+        nsCString extension;
+        if (NS_FAILED(extensions->GetNext(extension))) {
+          continue;
+        }
+        if (!extensionListStr.IsEmpty()) {
+          extensionListStr.AppendLiteral("; ");
+        }
+        extensionListStr += NS_LITERAL_STRING("*.") +
+                            NS_ConvertUTF8toUTF16(extension);
+      }
+    }
+
+    if (!filterMask && (extensionListStr.IsEmpty() || filterName.IsEmpty())) {
+      // No valid filter found
+      continue;
+    }
+
+    // If we arrived here, that means we have a valid filter: let's create it
+    // and add it to our list, if no similar filter is already present
+    nsFilePickerFilter filter;
+    if (filterMask) {
+      filter = nsFilePickerFilter(filterMask);
+    } else {
+      filter = nsFilePickerFilter(filterName, extensionListStr);
+    }
+
+    if (!filters.Contains(filter)) {
+      if (!allExtensionsList.IsEmpty()) {
+        allExtensionsList.AppendLiteral("; ");
+      }
+      allExtensionsList += extensionListStr;
+      filters.AppendElement(filter);
+    }
+  }
+
+  // Add "All Supported Types" filter
+  if (filters.Length() > 1) {
+    nsXPIDLString title;
+    nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
+                                       "AllSupportedTypes", title);
+    filePicker->AppendFilter(title, allExtensionsList);
+  }
+
+  // Add each filter, and check if all filters are trusted
+  bool allFilterAreTrusted = true;
+  for (PRUint32 i = 0; i < filters.Length(); ++i) {
+    const nsFilePickerFilter& filter = filters[i];
+    if (filter.mFilterMask) {
+      filePicker->AppendFilters(filter.mFilterMask);
+    } else {
+      filePicker->AppendFilter(filter.mTitle, filter.mFilter);
+    }
+    allFilterAreTrusted &= filter.mIsTrusted;
+  }
+
+  // If all filters are trusted, select the first filter as default;
+  // otherwise filterAll will remain the default filter
+  if (filters.Length() >= 1 && allFilterAreTrusted) {
+    // |filterAll| will always use index=0 so we need to set index=1 as the
+    // current filter.
+    filePicker->SetFilterIndex(1);
+  }
+}
+
 PRInt32
 nsHTMLInputElement::GetFilterFromAccept()
 {
   NS_ASSERTION(HasAttr(kNameSpaceID_None, nsGkAtoms::accept),
                "You should not call GetFileFiltersFromAccept if the element"
                " has no accept attribute!");
 
   PRInt32 filter = 0;
--- a/content/html/content/src/nsHTMLInputElement.h
+++ b/content/html/content/src/nsHTMLInputElement.h
@@ -15,42 +15,43 @@
 #include "nsTextEditorState.h"
 #include "nsCOMPtr.h"
 #include "nsIConstraintValidation.h"
 #include "nsDOMFile.h"
 #include "nsHTMLFormElement.h" // for ShouldShowInvalidUI()
 #include "nsIFile.h"
 
 class nsDOMFileList;
+class nsIFilePicker;
 class nsIRadioGroupContainer;
 class nsIRadioGroupVisitor;
 class nsIRadioVisitor;
 
 class UploadLastDir MOZ_FINAL : public nsIObserver, public nsSupportsWeakReference {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   /**
    * Fetch the last used directory for this location from the content
    * pref service, if it is available.
    *
    * @param aURI URI of the current page
    * @param aFile path to the last used directory
    */
-  nsresult FetchLastUsedDirectory(nsIURI* aURI, nsILocalFile** aFile);
+  nsresult FetchLastUsedDirectory(nsIURI* aURI, nsIFile** aFile);
 
   /**
    * Store the last used directory for this location using the
    * content pref service, if it is available
    * @param aURI URI of the current page
    * @param aFile file chosen by the user - the path to the parent of this
    *        file will be stored
    */
-  nsresult StoreLastUsedDirectory(nsIURI* aURI, nsILocalFile* aFile);
+  nsresult StoreLastUsedDirectory(nsIURI* aURI, nsIFile* aFile);
 };
 
 class nsHTMLInputElement : public nsGenericHTMLFormElement,
                            public nsImageLoadingContent,
                            public nsIDOMHTMLInputElement,
                            public nsITextControlElement,
                            public nsIPhonetic,
                            public nsIDOMNSEditableElement,
@@ -229,16 +230,33 @@ public:
    *
    * @param aIgnoreSelf Whether the required attribute and the checked state
    * of the current radio should be ignored.
    * @note This method shouldn't be called if the radio elemnet hasn't a group.
    */
   void     UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf);
 
   /**
+   * Set filters to the filePicker according to the accept attribute value.
+   *
+   * See:
+   * http://dev.w3.org/html5/spec/forms.html#attr-input-accept
+   *
+   * @note You should not call this function if the element has no @accept.
+   * @note "All Files" filter is always set, no matter if there is a valid
+   * filter specifed or not.
+   * @note If there is only one valid filter that is audio or video or image,
+   * it will be selected as the default filter. Otherwise "All files" remains
+   * the default filter.
+   * @note If more than one valid filter is found, the "All Supported Types"
+   * filter is added, which is the concatenation of all valid filters.
+   */
+  void SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker);
+
+  /**
    * Returns the filter which should be used for the file picker according to
    * the accept attribute value.
    *
    * See:
    * http://dev.w3.org/html5/spec/forms.html#attr-input-accept
    *
    * @return Filter to use on the file picker with AppendFilters, 0 if none.
    *
@@ -573,11 +591,56 @@ protected:
   bool                     mShouldInitChecked   : 1;
   bool                     mParserCreating      : 1;
   bool                     mInInternalActivate  : 1;
   bool                     mCheckedIsToggled    : 1;
   bool                     mIndeterminate       : 1;
   bool                     mInhibitRestoration  : 1;
   bool                     mCanShowValidUI      : 1;
   bool                     mCanShowInvalidUI    : 1;
+
+private:
+  struct nsFilePickerFilter {
+    nsFilePickerFilter()
+      : mFilterMask(0), mIsTrusted(false) {}
+
+    nsFilePickerFilter(PRInt32 aFilterMask)
+      : mFilterMask(aFilterMask), mIsTrusted(true) {}
+
+    nsFilePickerFilter(const nsString& aTitle,
+                       const nsString& aFilter,
+                       const bool aIsTrusted = false)
+      : mFilterMask(0), mTitle(aTitle), mFilter(aFilter), mIsTrusted(aIsTrusted) {}
+
+    nsFilePickerFilter(const nsFilePickerFilter& other) {
+      mFilterMask = other.mFilterMask;
+      mTitle = other.mTitle;
+      mFilter = other.mFilter;
+      mIsTrusted = other.mIsTrusted;
+    }
+
+    bool operator== (const nsFilePickerFilter& other) const {
+      if ((mFilter == other.mFilter) && (mFilterMask == other.mFilterMask)) {
+        NS_ASSERTION(mIsTrusted == other.mIsTrusted,
+                     "Filter with similar list of extensions and mask should"
+                     " have the same trusted flag value");
+        return true;
+      } else {
+        return false;
+      }
+    }
+    
+    // Filter mask, using values defined in nsIFilePicker
+    PRInt32 mFilterMask;
+    // If mFilterMask is defined, mTitle and mFilter are useless and should be
+    // ignored
+    nsString mTitle;
+    nsString mFilter;
+    // mIsTrusted is true if mime type comes from a "trusted" source (e.g. our
+    // hard-coded set).
+    // false means it may come from an "untrusted" source (e.g. OS mime types
+    // mapping, which can be different accross OS, user's personal configuration, ...)
+    // For now, only mask filters are considered to be "trusted".
+    bool mIsTrusted; 
+  };
 };
 
 #endif
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -1269,17 +1269,17 @@ NS_IMETHODIMP nsHTMLMediaElement::SetCur
   }
 
   mPlayingBeforeSeek = IsPotentiallyPlaying();
   // The media backend is responsible for dispatching the timeupdate
   // event if it changes the playback position as a result of the seek.
   LOG(PR_LOG_DEBUG, ("%p SetCurrentTime(%f) starting seek", this, aCurrentTime));
   nsresult rv = mDecoder->Seek(clampedTime);
   // Start a new range at position we seeked to.
-  mCurrentPlayRangeStart = clampedTime;
+  mCurrentPlayRangeStart = mDecoder->GetCurrentTime();
 
   // We changed whether we're seeking so we need to AddRemoveSelfReference.
   AddRemoveSelfReference();
 
   return rv;
 }
 
 /* readonly attribute double duration; */
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/nsHTMLMeterElement.cpp
@@ -0,0 +1,480 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mounir Lamouri <mounir.lamouri@mozilla.com> (original author)
+ *   Vincent Lamotte <Vincent.Lamotte@ensimag.imag.fr>
+ *   Laurent Dulary <Laurent.Dulary@ensimag.imag.fr>
+ *   Yoan Teboul <Yoan.Teboul@ensimag.imag.fr>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+ 
+#include "nsIDOMHTMLMeterElement.h"
+#include "nsGenericHTMLElement.h"
+#include "nsAttrValue.h"
+#include "nsEventStateManager.h"
+#include "nsAlgorithm.h"
+
+
+class nsHTMLMeterElement : public nsGenericHTMLFormElement,
+                           public nsIDOMHTMLMeterElement
+{
+public:
+  nsHTMLMeterElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual ~nsHTMLMeterElement();
+
+  /* nsISupports */
+  NS_DECL_ISUPPORTS_INHERITED
+
+  /* nsIDOMNode */
+  NS_FORWARD_NSIDOMNODE(nsGenericHTMLFormElement::)
+
+  /* nsIDOMElement */
+  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLFormElement::)
+
+  /* nsIDOMHTMLElement */
+  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLFormElement::)
+
+  /* nsIDOMHTMLMeterElement */
+  NS_DECL_NSIDOMHTMLMETERELEMENT
+
+  /* nsIFormControl */
+  NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_METER; }
+  NS_IMETHOD Reset();
+  NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
+
+  virtual nsEventStates IntrinsicState() const;
+
+  nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
+
+  bool ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute,
+                      const nsAString& aValue, nsAttrValue& aResult);
+
+  virtual nsXPCClassInfo* GetClassInfo();
+
+  virtual nsIDOMNode* AsDOMNode() { return this; }
+
+private:
+
+  static const double kDefaultValue;
+  static const double kDefaultMin;
+  static const double kDefaultMax;
+
+  /**
+   * Returns the optimum state of the element.
+   * NS_EVENT_STATE_OPTIMUM if the actual value is in the optimum region.
+   * NS_EVENT_STATE_SUB_OPTIMUM if the actual value is in the sub-optimal region.
+   * NS_EVENT_STATE_SUB_SUB_OPTIMUM if the actual value is in the sub-sub-optimal region.
+   *
+   * @return the optimum state of the element.
+   */
+  nsEventStates GetOptimumState() const;
+
+  /* @return the minimum value */
+  double GetMin() const;
+
+  /* @return the maximum value */
+  double GetMax() const;
+
+  /* @return the actual value */
+  double GetValue() const;
+
+  /* @return the low value */
+  double GetLow() const;
+
+  /* @return the high value */
+  double GetHigh() const;
+
+  /* @return the optimum value */
+  double GetOptimum() const;
+};
+
+const double nsHTMLMeterElement::kDefaultValue =  0.0;
+const double nsHTMLMeterElement::kDefaultMin   =  0.0;
+const double nsHTMLMeterElement::kDefaultMax   =  1.0;
+
+NS_IMPL_NS_NEW_HTML_ELEMENT(Meter)
+
+
+nsHTMLMeterElement::nsHTMLMeterElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+  : nsGenericHTMLFormElement(aNodeInfo)
+{
+}
+
+nsHTMLMeterElement::~nsHTMLMeterElement()
+{
+}
+
+NS_IMPL_ADDREF_INHERITED(nsHTMLMeterElement, nsGenericElement)
+NS_IMPL_RELEASE_INHERITED(nsHTMLMeterElement, nsGenericElement)
+
+DOMCI_NODE_DATA(HTMLMeterElement, nsHTMLMeterElement)
+
+NS_INTERFACE_TABLE_HEAD(nsHTMLMeterElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLMeterElement,
+                                   nsIDOMHTMLMeterElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLMeterElement,
+                                               nsGenericHTMLFormElement)
+NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMeterElement)
+
+NS_IMPL_ELEMENT_CLONE(nsHTMLMeterElement)
+
+
+NS_IMETHODIMP
+nsHTMLMeterElement::Reset()
+{
+  /* The meter element is not resettable. */
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
+{
+  /* The meter element is not submittable. */
+  return NS_OK;
+}
+
+nsEventStates
+nsHTMLMeterElement::IntrinsicState() const
+{
+  nsEventStates state = nsGenericHTMLFormElement::IntrinsicState();
+
+  state |= GetOptimumState();
+
+  return state;
+}
+
+bool
+nsHTMLMeterElement::ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute,
+                                 const nsAString& aValue, nsAttrValue& aResult)
+{
+  if (aNamespaceID == kNameSpaceID_None) {
+    if (aAttribute == nsGkAtoms::value || aAttribute == nsGkAtoms::max ||
+        aAttribute == nsGkAtoms::min   || aAttribute == nsGkAtoms::low ||
+        aAttribute == nsGkAtoms::high  || aAttribute == nsGkAtoms::optimum) {
+      return aResult.ParseDoubleValue(aValue);
+    }
+  }
+
+  return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
+                                                  aValue, aResult);
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::GetForm(nsIDOMHTMLFormElement** aForm)
+{
+  return nsGenericHTMLFormElement::GetForm(aForm);
+}
+
+/*
+ * Value getters :
+ * const getters used by XPCOM methods and by IntrinsicState
+ */
+
+double
+nsHTMLMeterElement::GetMin() const
+{
+  /**
+   * If the attribute min is defined, the minimum is this value.
+   * Otherwise, the minimum is the default value.
+   */
+  const nsAttrValue* attrMin = mAttrsAndChildren.GetAttr(nsGkAtoms::min);
+  if (attrMin && attrMin->Type() == nsAttrValue::eDoubleValue) {
+    return attrMin->GetDoubleValue();
+  }
+  return kDefaultMin;
+}
+
+double
+nsHTMLMeterElement::GetMax() const
+{
+  /**
+   * If the attribute max is defined, the maximum is this value.
+   * Otherwise, the maximum is the default value.
+   * If the maximum value is less than the minimum value,
+   * the maximum value is the same as the minimum value.
+   */
+  double max;
+
+  const nsAttrValue* attrMax = mAttrsAndChildren.GetAttr(nsGkAtoms::max);
+  if (attrMax && attrMax->Type() == nsAttrValue::eDoubleValue) {
+    max = attrMax->GetDoubleValue();
+  } else {
+    max = kDefaultMax;
+  }
+
+  return NS_MAX(max, GetMin());
+}
+
+double
+nsHTMLMeterElement::GetValue() const
+{
+  /**
+   * If the attribute value is defined, the actual value is this value.
+   * Otherwise, the actual value is the default value.
+   * If the actual value is less than the minimum value,
+   * the actual value is the same as the minimum value.
+   * If the actual value is greater than the maximum value,
+   * the actual value is the same as the maximum value.
+   */
+  double value;
+
+  const nsAttrValue* attrValue = mAttrsAndChildren.GetAttr(nsGkAtoms::value);
+  if (attrValue && attrValue->Type() == nsAttrValue::eDoubleValue) {
+    value = attrValue->GetDoubleValue();
+  } else {
+    value = kDefaultValue;
+  }
+
+  double min = GetMin();
+
+  if (value <= min) {
+    return min;
+  }
+
+  return NS_MIN(value, GetMax());
+}
+
+double
+nsHTMLMeterElement::GetLow() const
+{
+  /**
+   * If the low value is defined, the low value is this value.
+   * Otherwise, the low value is the minimum value.
+   * If the low value is less than the minimum value,
+   * the low value is the same as the minimum value.
+   * If the low value is greater than the maximum value,
+   * the low value is the same as the maximum value.
+   */
+
+  double min = GetMin();
+
+  const nsAttrValue* attrLow = mAttrsAndChildren.GetAttr(nsGkAtoms::low);
+  if (!attrLow || attrLow->Type() != nsAttrValue::eDoubleValue) {
+    return min;
+  }
+
+  double low = attrLow->GetDoubleValue();
+
+  if (low <= min) {
+    return min;
+  }
+
+  return NS_MIN(low, GetMax());
+}
+
+double
+nsHTMLMeterElement::GetHigh() const
+{
+  /**
+   * If the high value is defined, the high value is this value.
+   * Otherwise, the high value is the maximum value.
+   * If the high value is less than the low value,
+   * the high value is the same as the low value.
+   * If the high value is greater than the maximum value,
+   * the high value is the same as the maximum value.
+   */
+
+  double max = GetMax();
+
+  const nsAttrValue* attrHigh = mAttrsAndChildren.GetAttr(nsGkAtoms::high);
+  if (!attrHigh || attrHigh->Type() != nsAttrValue::eDoubleValue) {
+    return max;
+  }
+
+  double high = attrHigh->GetDoubleValue();
+
+  if (high >= max) {
+    return max;
+  }
+
+  return NS_MAX(high, GetLow());
+}
+
+double
+nsHTMLMeterElement::GetOptimum() const
+{
+  /**
+   * If the optimum value is defined, the optimum value is this value.
+   * Otherwise, the optimum value is the midpoint between
+   * the minimum value and the maximum value :
+   * min + (max - min)/2 = (min + max)/2
+   * If the optimum value is less than the minimum value,
+   * the optimum value is the same as the minimum value.
+   * If the optimum value is greater than the maximum value,
+   * the optimum value is the same as the maximum value.
+   */
+
+  double max = GetMax();
+
+  double min = GetMin();
+
+  const nsAttrValue* attrOptimum =
+              mAttrsAndChildren.GetAttr(nsGkAtoms::optimum);
+  if (!attrOptimum || attrOptimum->Type() != nsAttrValue::eDoubleValue) {
+    return (min + max) / 2.0;
+  }
+
+  double optimum = attrOptimum->GetDoubleValue();
+
+  if (optimum <= min) {
+    return min;
+  }
+
+  return NS_MIN(optimum, max);
+}
+
+/*
+ * XPCOM methods
+ */
+
+NS_IMETHODIMP
+nsHTMLMeterElement::GetMin(double* aValue)
+{
+  *aValue = GetMin();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::SetMin(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::min, aValue);
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::GetMax(double* aValue)
+{
+  *aValue = GetMax();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::SetMax(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::max, aValue);
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::GetValue(double* aValue)
+{
+  *aValue = GetValue();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::SetValue(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::value, aValue);
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::GetLow(double* aValue)
+{
+  *aValue = GetLow();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::SetLow(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::low, aValue);
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::GetHigh(double* aValue)
+{
+  *aValue = GetHigh();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::SetHigh(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::high, aValue);
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::GetOptimum(double* aValue)
+{
+  *aValue = GetOptimum();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLMeterElement::SetOptimum(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::optimum, aValue);
+}
+
+nsEventStates
+nsHTMLMeterElement::GetOptimumState() const
+{
+  /*
+   * If the optimum value is in [minimum, low[,
+   *     return if the value is in optimal, suboptimal or sub-suboptimal region
+   *
+   * If the optimum value is in [low, high],
+   *     return if the value is in optimal or suboptimal region
+   *
+   * If the optimum value is in ]high, maximum],
+   *     return if the value is in optimal, suboptimal or sub-suboptimal region
+   */
+  double value = GetValue();
+  double low = GetLow();
+  double high = GetHigh();
+  double optimum = GetOptimum();
+
+  if (optimum < low) {
+    if (value < low) {
+      return NS_EVENT_STATE_OPTIMUM;
+    }
+    if (value <= high) {
+      return NS_EVENT_STATE_SUB_OPTIMUM;
+    }
+    return NS_EVENT_STATE_SUB_SUB_OPTIMUM;
+  }
+  if (optimum > high) {
+    if (value > high) {
+      return NS_EVENT_STATE_OPTIMUM;
+    }
+    if (value >= low) {
+      return NS_EVENT_STATE_SUB_OPTIMUM;
+    }
+    return NS_EVENT_STATE_SUB_SUB_OPTIMUM;
+  }
+  // optimum in [low, high]
+  if (value >= low && value <= high) {
+    return NS_EVENT_STATE_OPTIMUM;
+  }
+  return NS_EVENT_STATE_SUB_OPTIMUM;
+}
+
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -1221,17 +1221,17 @@ nsHTMLSelectElement::SetValue(const nsAS
 }
 
 
 NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Autofocus, autofocus)
 NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Disabled, disabled)
 NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Multiple, multiple)
 NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Name, name)
 NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Required, required)
-NS_IMPL_NON_NEGATIVE_INT_ATTR_DEFAULT_VALUE(nsHTMLSelectElement, Size, size, 0)
+NS_IMPL_UINT_ATTR(nsHTMLSelectElement, Size, size)
 NS_IMPL_INT_ATTR(nsHTMLSelectElement, TabIndex, tabindex)
 
 bool
 nsHTMLSelectElement::IsHTMLFocusable(bool aWithMouse,
                                      bool *aIsFocusable, PRInt32 *aTabIndex)
 {
   if (nsGenericHTMLFormElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
     return true;
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -544,17 +544,17 @@ protected:
   /**
    * Is this a combobox?
    */
   bool IsCombobox() {
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
       return false;
     }
 
-    PRInt32 size = 1;
+    PRUint32 size = 1;
     GetSize(&size);
     return size <= 1;
   }
 
   /**
    * Helper method for dispatching ContentReset notifications to list
    * and combo box frames.
    */
--- a/content/html/content/src/nsTimeRanges.cpp
+++ b/content/html/content/src/nsTimeRanges.cpp
@@ -70,16 +70,20 @@ nsTimeRanges::Normalize()
   if (mRanges.Length() >= 2) {
     nsAutoTArray<TimeRange,4> normalized;
 
     mRanges.Sort(CompareTimeRanges());
 
     // This merges the intervals.
     TimeRange current(mRanges[0]);
     for (PRUint32 i = 1; i < mRanges.Length(); i++) {
+      if (current.mStart <= mRanges[i].mStart &&
+          current.mEnd >= mRanges[i].mEnd) {
+        continue;
+      }
       if (current.mEnd >= mRanges[i].mStart) {
         current.mEnd = mRanges[i].mEnd;
       } else {
         normalized.AppendElement(current);
         current = mRanges[i];
       }
     }
 
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -259,16 +259,19 @@ include $(topsrcdir)/config/rules.mk
 		test_li_attributes_reflection.html \
 		test_ol_attributes_reflection.html \
 		test_bug651956.html \
 		test_bug694503.html \
 		test_object_plugin_nav.html \
 		test_bug742030.html \
 		test_bug742549.html \
 		test_bug745685.html \
+		test_bug657938.html \
+		test_bug660238.html \
+		test_input_file_picker.html \
 		$(NULL)
 
 _BROWSER_TEST_FILES = \
 		browser_bug649778.js \
 		file_bug649778.html \
 		file_bug649778.html^headers^ \
 		$(NULL)
 
--- a/content/html/content/test/forms/test_form_attribute-1.html
+++ b/content/html/content/test/forms/test_form_attribute-1.html
@@ -395,22 +395,21 @@ var content = document.getElementById('c
 var forms = [
   document.createElement('form'),
   document.createElement('form'),
   document.createElement('form'),
 ];
 
 var elementNames = [
   'button', 'fieldset', 'input', 'label', 'object', 'output', 'select',
-  'textarea',
+  'textarea', 'meter'
 ];
 
 var todoElements = [
   ['keygen', 'Keygen'],
-  ['meter', 'Meter'],
 ];
 
 for each(var e in todoElements) {
   var node = document.createElement(e[0]);
   var nodeString = HTMLElement.prototype.toString.apply(node);
   nodeString = nodeString.replace(/Element[\] ].*/, "Element");
   todo_is(nodeString, "[object HTML" + e[1] + "Element",
           e[0] + " should not be implemented");
--- a/content/html/content/test/test_bug389797.html
+++ b/content/html/content/test/test_bug389797.html
@@ -173,16 +173,17 @@ HTML_TAG("legend", "Legend");
 HTML_TAG("li", "LI");
 HTML_TAG("link", "Link", [ "nsIDOMLinkStyle" ]);
 HTML_TAG("listing", "");
 HTML_TAG("map", "Map");
 HTML_TAG("mark", "");
 HTML_TAG("marquee", "Div");
 HTML_TAG("menu", "Menu");
 HTML_TAG("meta", "Meta");
+HTML_TAG("meter", "Meter");
 HTML_TAG("multicol", "Span");
 HTML_TAG("nav", "")
 HTML_TAG("nobr", "");
 HTML_TAG("noembed", "");
 HTML_TAG("noframes", "");
 HTML_TAG("noscript", "");
 HTML_TAG("object", "Object", [ "nsIDOMGetSVGDocument" ],
                              objectIfaces.concat([ "nsIImageLoadingContent" ]));
--- a/content/html/content/test/test_bug551846.html
+++ b/content/html/content/test/test_bug551846.html
@@ -98,23 +98,27 @@ function checkSetSizeException(element)
   caught = false;
   try {
     element.size = 0;
   } catch(e) {
     caught = true;
   }
   ok(!caught, "Setting a size to 0 from the IDL shouldn't throw an exception");
 
+  element.size = 1;
+
   caught = false;
   try {
     element.size = -1;
   } catch(e) {
     caught = true;
   }
-  ok(caught, "Setting an invalid size from the IDL should throw an exception");
+  ok(!caught, "Setting a negative size from the IDL shouldn't throw an exception");
+
+  is(element.size, 0, "The size should now be equal to the minimum non-negative value");
 
   caught = false;
   try {
     element.setAttribute('size', -10);
   } catch(e) {
     caught = true;
   }
   ok(!caught, "Setting an invalid size in the content attribute shouldn't throw an exception");
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug657938.html
@@ -0,0 +1,393 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=657938
+-->
+<head>
+  <title>Test for Bug 657938</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=657938">Mozilla Bug 657938</a>
+<p id="display"></p>
+<iframe name="submit_frame" style="visibility: hidden;"></iframe>
+<div id="content" style="visibility: hidden;">
+  <form id='f' method='get' target='submit_frame' action='foo'>
+    <meter id='m' value=0.5></meter>
+  </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 657938 **/
+
+function checkFormIDLAttribute(aElement)
+{
+  var form = document.forms[0];
+  var content = document.getElementById('content');
+  is(aElement.form, form, "The form IDL attribute should be the parent form");
+
+  content.removeChild(form);
+  content.appendChild(aElement);
+  is(aElement.form, null, "The form IDL attribute should be null");
+
+  // Cleaning-up.
+  content.appendChild(form);
+  form.appendChild(aElement);
+}
+
+function checkAttribute(aElement, aAttribute, aNewValue, aExpectedValueForIDL)
+{
+  var expectedValueForIDL = aNewValue;
+  var expectedValueForContent = aNewValue;
+
+  if (aExpectedValueForIDL !== undefined) {
+    expectedValueForIDL = aExpectedValueForIDL;
+  }
+
+  if (aNewValue != null) {
+    aElement.setAttribute(aAttribute, aNewValue);
+    is(aElement.getAttribute(aAttribute), expectedValueForContent,
+       aAttribute + " content attribute should be " + expectedValueForContent);
+    is(aElement[aAttribute], expectedValueForIDL,
+       aAttribute + " IDL attribute should be " + expectedValueForIDL);
+
+    if (parseFloat(aNewValue) == aNewValue) {
+      aElement[aAttribute] = aNewValue;
+      is(aElement.getAttribute(aAttribute), expectedValueForContent,
+         aAttribute + " content attribute should be " + expectedValueForContent);
+      is(aElement[aAttribute], parseFloat(expectedValueForIDL),
+         aAttribute + " IDL attribute should be " + parseFloat(expectedValueForIDL));
+    }
+  } else {
+    aElement.removeAttribute(aAttribute);
+    is(aElement.getAttribute(aAttribute), expectedValueForContent,
+       aAttribute + " content attribute should be " + expectedValueForContent);
+    is(aElement[aAttribute], expectedValueForIDL,
+       aAttribute + " IDL attribute should be " + expectedValueForIDL);
+  }
+}
+
+function checkValueAttribute()
+{
+  var tests = [
+    // value has to be a valid float, its default value is 0.0 otherwise.
+    [ null, 0.0 ],
+    [ 'foo', 0.0 ],
+    // If value < 0.0, 0.0 is used instead.
+    [ -1.0, 0.0 ],
+    // If value >= max, max is used instead (max default value is 1.0).
+    [  2.0, 1.0 ],
+    [  1.0, 0.5, 0.5 ],
+    [  10.0, 5.0, 5.0 ],
+    [ 13.37, 13.37, 42.0 ],
+    // If value <= min, min is used instead (min default value is 0.0).
+    [  0.5, 1.0, 10.0 ,1.0 ],
+    [  10.0, 13.37, 42.0 , 13.37],
+    // Regular reflection.
+    [  0.0 ],
+    [  0.5 ],
+    [  1.0 ],
+    // Check double-precision value.
+    [  0.234567898765432 ],
+  ];
+
+  var element = document.createElement('meter');
+
+  for each(var test in tests) {
+    if (test[2]) {
+      element.setAttribute('max', test[2]);
+    }
+
+    if (test[3]) {
+      element.setAttribute('min', test[3]);
+    }
+
+    checkAttribute(element, 'value', test[0], test[1]);
+
+    element.removeAttribute('max');
+    element.removeAttribute('min');
+  }
+}
+
+function checkMinAttribute()
+{
+  var tests = [
+    // min default value is 0.0.
+    [ null, 0.0 ],
+    [ 'foo', 0.0 ],
+    // Regular reflection.
+    [  0.5 ],
+    [  1.0 ],
+    [  2.0 ],
+    // Check double-precision value.
+    [  0.234567898765432 ],
+  ];
+
+  var element = document.createElement('meter');
+
+  for each(var test in tests) {
+    checkAttribute(element, 'min', test[0], test[1]);
+  }
+}
+
+function checkMaxAttribute()
+{
+  var tests = [
+    // max default value is 1.0.
+    [ null, 1.0 ],
+    [ 'foo', 1.0 ],
+    // If value <= min, min is used instead.
+    [ -1.0, 0.0 ],
+    [ 0.0, 0.5, 0.5 ],
+    [ 10.0, 15.0, 15.0 ],
+    [ 42, 42, 13.37 ],
+    // Regular reflection.
+    [  0.5 ],
+    [  1.0 ],
+    [  2.0 ],
+    // Check double-precision value.
+    [  0.234567898765432 ],
+  ];
+
+  var element = document.createElement('meter');
+
+  for each(var test in tests) {
+    if (test[2]) {
+      element.setAttribute('min', test[2]);
+    }
+
+    checkAttribute(element, 'max', test[0], test[1]);
+
+    element.removeAttribute('min');
+  }
+}
+
+function checkLowAttribute()
+{
+  var tests = [
+    // low default value is min (min default value is 0.0).
+    [ null, 0.0 ],
+    [ 'foo', 0.0 ],
+    [ 'foo', 1.0, 1.0],
+    // If low <= min, min is used instead.
+    [ -1.0, 0.0 ],
+    [ 0.0, 0.5, 0.5 ],
+    [ 10.0, 15.0, 15.0, 42.0 ],
+    [ 42.0, 42.0, 13.37, 100.0 ],
+    // If low >= max, max is used instead.
+    [ 2.0, 1.0 ],
+    [ 10.0, 5.0 , 0.5, 5.0 ],
+    [ 13.37, 13.37, 0.0, 42.0 ],
+    // Regular reflection.
+    [  0.0 ],
+    [  0.5 ],
+    [  1.0 ],
+    // Check double-precision value.
+    [  0.234567898765432 ],
+  ];
+
+  var element = document.createElement('meter');
+
+  for each(var test in tests) {
+    if (test[2]) {
+      element.setAttribute('min', test[2]);
+    }
+    if (test[3]) {
+      element.setAttribute('max', test[3]);
+    }
+
+    checkAttribute(element, 'low', test[0], test[1]);
+
+    element.removeAttribute('min');
+    element.removeAttribute('max');
+  }
+}
+
+function checkHighAttribute()
+{
+  var tests = [
+    // high default value is max (max default value is 1.0).
+    [ null, 1.0 ],
+    [ 'foo', 1.0 ],
+    [ 'foo', 42.0, 0.0, 42.0],
+    // If high <= min, min is used instead.
+    [ -1.0, 0.0 ],
+    [ 0.0, 0.5, 0.5 ],
+    [ 10.0, 15.0, 15.0, 42.0 ],
+    [ 42.0, 42.0, 13.37, 100.0 ],
+    // If high >= max, max is used instead.
+    [ 2.0, 1.0 ],
+    [ 10.0, 5.0 , 0.5, 5.0 ],
+    [ 13.37, 13.37, 0.0, 42.0 ],
+    // Regular reflection.
+    [  0.0 ],
+    [  0.5 ],
+    [  1.0 ],
+    // Check double-precision value.
+    [  0.234567898765432 ],
+  ];
+
+  var element = document.createElement('meter');
+
+  for each(var test in tests) {
+    if (test[2]) {
+      element.setAttribute('min', test[2]);
+    }
+    if (test[3]) {
+      element.setAttribute('max', test[3]);
+    }
+
+    checkAttribute(element, 'high', test[0], test[1]);
+
+    element.removeAttribute('min');
+    element.removeAttribute('max');
+  }
+}
+
+function checkOptimumAttribute()
+{
+  var tests = [
+    // opt default value is (max-min)/2 (thus default value is 0.5).
+    [ null, 0.5 ],
+    [ 'foo', 0.5 ],
+    [ 'foo', 2.0, 1.0, 3.0],
+    // If opt <= min, min is used instead.
+    [ -1.0, 0.0 ],
+    [ 0.0, 0.5, 0.5 ],
+    [ 10.0, 15.0, 15.0, 42.0 ],
+    [ 42.0, 42.0, 13.37, 100.0 ],
+    // If opt >= max, max is used instead.
+    [ 2.0, 1.0 ],
+    [ 10.0, 5.0 , 0.5, 5.0 ],
+    [ 13.37, 13.37, 0.0, 42.0 ],
+    // Regular reflection.
+    [  0.0 ],
+    [  0.5 ],
+    [  1.0 ],
+    // Check double-precision value.
+    [  0.234567898765432 ],
+  ];
+
+  var element = document.createElement('meter');
+
+  for each(var test in tests) {
+    if (test[2]) {
+      element.setAttribute('min', test[2]);
+    }
+    if (test[3]) {
+      element.setAttribute('max', test[3]);
+    }
+
+    checkAttribute(element, 'optimum', test[0], test[1]);
+
+    element.removeAttribute('min');
+    element.removeAttribute('max');
+  }
+}
+
+function checkFormListedElement(aElement)
+{
+  is(document.forms[0].elements.length, 0, "the form should have no element");
+}
+
+function checkLabelable(aElement)
+{
+  var content = document.getElementById('content');
+  var label = document.createElement('label');
+
+  content.appendChild(label);
+  label.appendChild(aElement);
+  is(label.control, aElement, "meter should be labelable");
+
+  // Cleaning-up.
+  content.removeChild(label);
+  content.appendChild(aElement);
+}
+
+function checkNotResetableAndFormSubmission(aElement)
+{
+  // Creating an input element to check the submission worked.
+  var form = document.forms[0];
+  var input = document.createElement('input');
+
+  input.name = 'a';
+  input.value = 'tulip';
+  form.appendChild(input);
+
+  // Setting values.
+  aElement.value = 42.0;
+  aElement.max = 100.0;
+
+  document.getElementsByName('submit_frame')[0].addEventListener("load", function() {
+    document.getElementsByName('submit_frame')[0].removeEventListener("load", arguments.callee, false);
+
+    /**
+     * All elements values have been set just before the submission.
+     * The input element value should be in the submit url but the meter
+     * element value should not appear.
+     */
+    is(frames['submit_frame'].location.href,
+      'http://mochi.test:8888/tests/content/html/content/test/foo?a=tulip',
+       "The meter element value should not be submitted");
+
+    checkNotResetable();
+  }, false);
+
+  form.submit();
+}
+
+function checkNotResetable()
+{
+  // Try to reset the form.
+  var form = document.forms[0];
+  var element = document.getElementById('m');
+
+  element.value = 3.0;
+  element.max = 42.0;
+
+  form.reset();
+
+  SimpleTest.executeSoon(function() {
+    is(element.value, 3.0, "meter.value should not have changed");
+    is(element.max, 42.0, "meter.max should not have changed");
+
+    SimpleTest.finish();
+  });
+}
+
+SimpleTest.waitForExplicitFinish();
+
+var m = document.getElementById('m');
+
+ok(m instanceof HTMLMeterElement,
+   "The meter element should be instance of HTMLMeterElement");
+is(m.constructor, HTMLMeterElement,
+   "The meter element constructor should be HTMLMeterElement");
+
+checkFormIDLAttribute(m);
+
+checkValueAttribute();
+
+checkMinAttribute();
+
+checkMaxAttribute();
+
+checkLowAttribute();
+
+checkHighAttribute();
+
+checkOptimumAttribute();
+
+checkFormListedElement(m);
+
+checkLabelable(m);
+
+checkNotResetableAndFormSubmission(m);
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug660238.html
@@ -0,0 +1,170 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=660238
+-->
+<head>
+  <title>Test for Bug 660238</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=770238">Mozilla Bug 660238</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 660238 **/
+
+function checkOptimum(aElement, aValue, aOptimum, expectedResult)
+{
+  var errorString = "value attribute should be in the optimum region";
+  if (!expectedResult) {
+    errorString = "value attribute should not be in the optimum region";
+  }
+  aElement.setAttribute('value', aValue);
+  aElement.setAttribute('optimum', aOptimum);
+  is(aElement.mozMatchesSelector(":-moz-meter-optimum"),
+    expectedResult, errorString);
+}
+
+function checkSubOptimum(aElement, aValue, aOptimum, expectedResult)
+{
+  var errorString = "value attribute should be in the suboptimal region";
+  if (!expectedResult) {
+    errorString = "value attribute should not be in the suboptimal region";
+  }
+  aElement.setAttribute('value', aValue);
+  aElement.setAttribute('optimum', aOptimum);
+  is(aElement.mozMatchesSelector(":-moz-meter-sub-optimum"),
+    expectedResult, errorString);
+}
+
+function checkSubSubOptimum(aElement, aValue, aOptimum, expectedResult)
+{
+  var errorString = "value attribute should be in the sub-suboptimal region";
+  if (!expectedResult) {
+    errorString = "value attribute should not be in the sub-suboptimal region";
+  }
+  aElement.setAttribute('value', aValue);
+  aElement.setAttribute('optimum', aOptimum);
+  is(aElement.mozMatchesSelector(":-moz-meter-sub-sub-optimum"),
+    expectedResult, errorString);
+}
+
+function checkMozMatchesSelector()
+{
+  var element = document.createElement('meter');
+  // all tests realised with default values for min and max (0 and 1)
+  // low = 0.3 and high = 0.7
+  element.setAttribute('low', 0.3);
+  element.setAttribute('high', 0.7);
+
+  var tests = [
+    /*
+     * optimum = 0.0 =>
+     *     optimum region        = [ 0.0, 0.3 [
+     *     suboptimal region     = [ 0.3, 0.7 ]
+     *     sub-suboptimal region = ] 0.7, 1.0 ]
+     */
+    [ 0.0, 0.0, true, false, false ],
+    [ 0.1, 0.0, true, false, false ],
+    [ 0.3, 0.0, false, true, false ],
+    [ 0.5, 0.0, false, true, false ],
+    [ 0.7, 0.0, false, true, false ],
+    [ 0.8, 0.0, false, false, true ],
+    [ 1.0, 0.0, false, false, true ],
+    /*
+     * optimum = 0.1 =>
+     *     optimum region        = [ 0.0, 0.3 [
+     *     suboptimal region     = [ 0.3, 0.7 ]
+     *     sub-suboptimal region = ] 0.7, 1.0 ]
+     */
+    [ 0.0, 0.1, true, false, false ],
+    [ 0.1, 0.1, true, false, false ],
+    [ 0.3, 0.1, false, true, false ],
+    [ 0.5, 0.1, false, true, false ],
+    [ 0.7, 0.1, false, true, false ],
+    [ 0.8, 0.1, false, false, true ],
+    [ 1.0, 0.1, false, false, true ],
+    /*
+     * optimum = 0.3 =>
+     *     suboptimal region     = [ 0.0, 0.3 [
+     *     optimum region        = [ 0.3, 0.7 ]
+     *     suboptimal region     = ] 0.7, 1.0 ]
+     */
+    [ 0.0, 0.3, false, true, false ],
+    [ 0.1, 0.3, false, true, false ],
+    [ 0.3, 0.3, true, false, false ],
+    [ 0.5, 0.3, true, false, false ],
+    [ 0.7, 0.3, true, false, false ],
+    [ 0.8, 0.3, false, true, false ],
+    [ 1.0, 0.3, false, true, false ],
+    /*
+     * optimum = 0.5 =>
+     *     suboptimal region     = [ 0.0, 0.3 [
+     *     optimum region        = [ 0.3, 0.7 ]
+     *     suboptimal region     = ] 0.7, 1.0 ]
+     */
+    [ 0.0, 0.5, false, true, false ],
+    [ 0.1, 0.5, false, true, false ],
+    [ 0.3, 0.5, true, false, false ],
+    [ 0.5, 0.5, true, false, false ],
+    [ 0.7, 0.5, true, false, false ],
+    [ 0.8, 0.5, false, true, false ],
+    [ 1.0, 0.5, false, true, false ],
+    /*
+     * optimum = 0.7 =>
+     *     suboptimal region     = [ 0.0, 0.3 [
+     *     optimum region        = [ 0.3, 0.7 ]
+     *     suboptimal region     = ] 0.7, 1.0 ]
+     */
+    [ 0.0, 0.7, false, true, false ],
+    [ 0.1, 0.7, false, true, false ],
+    [ 0.3, 0.7, true, false, false ],
+    [ 0.5, 0.7, true, false, false ],
+    [ 0.7, 0.7, true, false, false ],
+    [ 0.8, 0.7, false, true, false ],
+    [ 1.0, 0.7, false, true, false ],
+    /*
+     * optimum = 0.8 =>
+     *     sub-suboptimal region = [ 0.0, 0.3 [
+     *     suboptimal region     = [ 0.3, 0.7 ]
+     *     optimum region        = ] 0.7, 1.0 ]
+     */
+    [ 0.0, 0.8, false, false, true ],
+    [ 0.1, 0.8, false, false, true ],
+    [ 0.3, 0.8, false, true, false ],
+    [ 0.5, 0.8, false, true, false ],
+    [ 0.7, 0.8, false, true, false ],
+    [ 0.8, 0.8, true, false, false ],
+    [ 1.0, 0.8, true, false, false ],
+    /*
+     * optimum = 1.0 =>
+     *     sub-suboptimal region = [ 0.0, 0.3 [
+     *     suboptimal region     = [ 0.3, 0.7 ]
+     *     optimum region        = ] 0.7, 1.0 ]
+     */
+    [ 0.0, 1.0, false, false, true ],
+    [ 0.1, 1.0, false, false, true ],
+    [ 0.3, 1.0, false, true, false ],
+    [ 0.5, 1.0, false, true, false ],
+    [ 0.7, 1.0, false, true, false ],
+    [ 0.8, 1.0, true, false, false ],
+    [ 1.0, 1.0, true, false, false ],
+  ];
+  
+  for each(var test in tests) {
+    checkOptimum(element, test[0], test[1], test[2]);
+    checkSubOptimum(element, test[0], test[1], test[3]);
+    checkSubSubOptimum(element, test[0], test[1], test[4]);
+  }
+}
+
+checkMozMatchesSelector();
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_input_file_picker.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=377624
+https://bugzilla.mozilla.org/show_bug.cgi?id=565274
+-->
+<head>
+  <title>Test for Bug 377624</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=377624">Mozilla Bug 377624</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=565274">Mozilla Bug 565274</a>
+<p id="display"></p>
+<div id="content">
+  <input id='a' type='file' accept="image/*">
+  <input id='b' type='file' accept="audio/*">
+  <input id='c' type='file' accept="video/*">
+  <input id='d' type='file' accept="image/*, audio/* ">
+  <input id='e' type='file' accept=" image/*,video/*">
+  <input id='f' type='file' accept="audio/*,video/*">
+  <input id='g' type='file' accept="image/*, audio/* ,video/*">
+  <input id='h' type='file' accept="foo/baz,image/*,bogus/duh">
+  <input id='i' type='file' accept="mime/type;parameter,video/*">
+  <input id='j' type='file' accept="audio/*, audio/*, audio/*">
+  <input id='k' type="file" accept="image/gif,image/png" />
+  <input id='l' type="file" accept="image/*,image/gif,image/png" />
+  <input id='m' type="file" accept="image/gif,image/gif" />
+  <input id='n' type="file" accept="" />
+  <input id='z' type='file' accept="i/am,a,pathological,;,,,,test/case">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 377624 and Bug 565274 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init();
+
+// The following lists are from toolkit/content/filepicker.properties which is used by filePicker
+var imageExtensionList = "*.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw"
+var audioExtensionList = "*.aac; *.aif; *.flac; *.iff; *.m4a; *.m4b; *.mid; *.midi; *.mp3; *.mpa; *.mpc; *.oga; *.ogg; *.ra; *.ram; *.snd; *.wav; *.wma"
+var videoExtensionList = "*.avi; *.divx; *.flv; *.m4v; *.mkv; *.mov; *.mp4; *.mpeg; *.mpg; *.ogm; *.ogv; *.ogx; *.rm; *.rmvb; *.smil; *.webm; *.wmv; *.xvid"
+
+// [ element name | number of filters | extension list or filter mask | filter index ]
+var testData = [["a", 1, MockFilePicker.filterImages, 1],
+                ["b", 1, MockFilePicker.filterAudio, 1],
+                ["c", 1, MockFilePicker.filterVideo, 1],
+                ["d", 3, imageExtensionList + "; " + audioExtensionList, 1],
+                ["e", 3, imageExtensionList + "; " + videoExtensionList, 1],
+                ["f", 3, audioExtensionList + "; " + videoExtensionList, 1],
+                ["g", 4, imageExtensionList + "; " + audioExtensionList + "; " + videoExtensionList, 1],
+                ["h", 1, MockFilePicker.filterImages, 1],
+                ["i", 1, MockFilePicker.filterVideo, 1],
+                ["j", 1, MockFilePicker.filterAudio, 1],
+                ["k", 3, "*.gif; *.png", 0],
+                ["l", 4, imageExtensionList + "; " + "*.gif; *.png", 0],
+                ["m", 1, "*.gif", 0],
+                ["n", 0, undefined, 0],
+                ["z", 0, undefined, 0]];
+
+var currentTest = 0;
+var filterAllAdded;
+var filters;
+var filterIndex;
+
+// disable popups to make sure that the popup blocker does not interfere
+// with manually opened file pickers.
+SpecialPowers.pushPrefEnv({'set': [["dom.disable_open_during_load", false]]}, runTests);
+
+function launchNextTest() {
+  MockFilePicker.shown = false;
+  filterAllAdded = false;
+  filters = [];
+  filterIndex = 0;
+
+  document.getElementById(testData[currentTest][0]).click();
+}
+
+function runTests() {
+  MockFilePicker.appendFilterCallback = function(filepicker, title, val) {
+    filters.push(val);
+  };
+  MockFilePicker.appendFiltersCallback = function(filepicker, val) {
+    if (val === MockFilePicker.filterAll) {
+      filterAllAdded = true;
+    } else {
+      filters.push(val);
+    }
+  };
+  MockFilePicker.showCallback = function(filepicker) {
+    filterIndex = filepicker.filterIndex;
+    testName = testData[currentTest][0];
+    SimpleTest.executeSoon(function () {
+      ok(MockFilePicker.shown,
+         "File picker show method should have been called (" + testName + ")");
+      ok(filterAllAdded,
+         "filterAll is missing (" + testName + ")");
+      is(filters.length, testData[currentTest][1],
+         "appendFilters not called as often as expected (" + testName + ")");
+      is(filters[0], testData[currentTest][2],
+         "Correct filters should have been added (" + testName + ")");
+      is(filterIndex, testData[currentTest][3],
+         "File picker should show the correct filter index (" + testName + ")");
+
+      if (++currentTest == testData.length) {
+        MockFilePicker.cleanup();
+        SimpleTest.finish();
+      } else {
+        launchNextTest();
+      }
+    });
+  };
+
+  launchNextTest();
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2879,26 +2879,26 @@ static const struct MidasCommand gMidasC
   { "fontsize",      "cmd_fontSize",        "", false, false },
   { "increasefontsize", "cmd_increaseFont", "", false, false },
   { "decreasefontsize", "cmd_decreaseFont", "", false, false },
   { "inserthorizontalrule", "cmd_insertHR", "", true,  false },
   { "createlink",    "cmd_insertLinkNoUI",  "", false, false },
   { "insertimage",   "cmd_insertImageNoUI", "", false, false },
   { "inserthtml",    "cmd_insertHTML",      "", false, false },
   { "inserttext",    "cmd_insertText",      "", false, false },
-  { "insertparagraph", "cmd_insertText",  "\n", true,  false },
   { "gethtml",       "cmd_getContents",     "", false, false },
   { "justifyleft",   "cmd_align",       "left", true,  false },
   { "justifyright",  "cmd_align",      "right", true,  false },
   { "justifycenter", "cmd_align",     "center", true,  false },
   { "justifyfull",   "cmd_align",    "justify", true,  false },
   { "removeformat",  "cmd_removeStyles",    "", true,  false },
   { "unlink",        "cmd_removeLinks",     "", true,  false },
   { "insertorderedlist",   "cmd_ol",        "", true,  false },
   { "insertunorderedlist", "cmd_ul",        "", true,  false },
+  { "insertparagraph", "cmd_paragraphState", "p", true,  false },
   { "formatblock",   "cmd_paragraphState",  "", false, false },
   { "heading",       "cmd_paragraphState",  "", false, false },
   { "styleWithCSS",  "cmd_setDocumentUseCSS", "", false, true },
   { "contentReadOnly", "cmd_setDocumentReadOnly", "", false, true },
   { "insertBrOnReturn", "cmd_insertBrOnReturn", "", false, true },
   { "enableObjectResizing", "cmd_enableObjectResizing", "", false, true },
   { "enableInlineTableEditing", "cmd_enableInlineTableEditing", "", false, true },
 #if 0
--- a/content/media/Makefile.in
+++ b/content/media/Makefile.in
@@ -92,14 +92,9 @@ PARALLEL_DIRS += test
 endif
 
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
-INCLUDES += \
-  -I$(srcdir)/../base/src \
-  -I$(srcdir)/../html/content/src \
-  $(NULL)
-
 DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/media/gstreamer/nsGStreamerReader.cpp
+++ b/content/media/gstreamer/nsGStreamerReader.cpp
@@ -500,16 +500,20 @@ nsresult nsGStreamerReader::Seek(PRInt64
   LOG(PR_LOG_DEBUG, ("seek succeeded"));
 
   return DecodeToTarget(aTarget);
 }
 
 nsresult nsGStreamerReader::GetBuffered(nsTimeRanges* aBuffered,
                                         PRInt64 aStartTime)
 {
+  if (!mInfo.mHasVideo && !mInfo.mHasAudio) {
+    return NS_OK;
+  }
+
   GstFormat format = GST_FORMAT_TIME;
   MediaResource* resource = mDecoder->GetResource();
   gint64 resourceLength = resource->GetLength();
   nsTArray<MediaByteRange> ranges;
   resource->GetCachedRanges(ranges);
 
   if (mDecoder->OnStateMachineThread())
     /* Report the position from here while buffering as we can't report it from
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -25,20 +25,20 @@ using namespace mozilla::layers;
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gBuiltinDecoderLog;
 #define LOG(type, msg) PR_LOG(gBuiltinDecoderLog, type, msg)
 #else
 #define LOG(type, msg)
 #endif
 
-// Wait this number of milliseconds when buffering, then leave and play
+// Wait this number of seconds when buffering, then leave and play
 // as best as we can if the required amount of data hasn't been
 // retrieved.
-static const PRUint32 BUFFERING_WAIT = 30000;
+static const PRUint32 BUFFERING_WAIT_S = 30;
 
 // If audio queue has less than this many usecs of decoded audio, we won't risk
 // trying to decode the video, we'll skip decoding video up to the next
 // keyframe. We may increase this value for an individual decoder if we
 // encounter video frames which take a long time to decode.
 static const PRUint32 LOW_AUDIO_USECS = 300000;
 
 // If more than this many usecs of decoded audio is queued, we'll hold off
@@ -412,17 +412,17 @@ nsBuiltinDecoderStateMachine::nsBuiltinD
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
 
   StateMachineTracker::Instance().EnsureGlobalStateMachine();
 
   // only enable realtime mode when "media.realtime_decoder.enabled" is true.
   if (Preferences::GetBool("media.realtime_decoder.enabled", false) == false)
     mRealTime = false;
 
-  mBufferingWait = mRealTime ? 0 : BUFFERING_WAIT;
+  mBufferingWait = mRealTime ? 0 : BUFFERING_WAIT_S;
   mLowDataThresholdUsecs = mRealTime ? 0 : LOW_DATA_THRESHOLD_USECS;
 }
 
 nsBuiltinDecoderStateMachine::~nsBuiltinDecoderStateMachine()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   MOZ_COUNT_DTOR(nsBuiltinDecoderStateMachine);
   NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
--- a/content/media/nsBuiltinDecoderStateMachine.h
+++ b/content/media/nsBuiltinDecoderStateMachine.h
@@ -642,16 +642,18 @@ protected:
   // throttled to not-throttled we need to pump decoding.
   bool mDidThrottleAudioDecoding;
   bool mDidThrottleVideoDecoding;
 
   // True if we've requested a new decode thread, but it has not yet been
   // created. Synchronized by the decoder monitor.
   bool mRequestedNewDecodeThread;
   
+  // The maximum number of second we spend buffering when we are short on
+  // unbuffered data.
   PRUint32 mBufferingWait;
   PRInt64  mLowDataThresholdUsecs;
 
 private:
   // Manager for queuing and dispatching MozAudioAvailable events.  The
   // event manager is accessed from the state machine and audio threads,
   // and takes care of synchronizing access to its internal queue.
   nsAudioAvailableEventManager mEventManager;