Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Fri, 04 May 2012 14:25:04 -0700
changeset 95740 7b619c6838995a01a5cd9fcaa643b1aeff14e114
parent 95739 3b0110befbe1cbd3b0a182e9f992525b7485ff4a (current diff)
parent 95427 495e6cd1903dbfd4b6e643398e2c06fd259bf457 (diff)
child 95741 bc9a3a32b4358b9ed27266bc70515ab1b6f522c0
push id1439
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 20:19:22 +0000
treeherdermozilla-aurora@ea74834dccd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone15.0a1
Merge m-c to s-c.
accessible/src/atk/nsRootAccessibleWrap.cpp
accessible/src/atk/nsRootAccessibleWrap.h
accessible/src/base/nsRootAccessible.cpp
accessible/src/base/nsRootAccessible.h
accessible/src/mac/nsRootAccessibleWrap.h
accessible/src/mac/nsRootAccessibleWrap.mm
accessible/src/msaa/nsRootAccessibleWrap.cpp
accessible/src/msaa/nsRootAccessibleWrap.h
accessible/src/other/nsRootAccessibleWrap.cpp
accessible/src/other/nsRootAccessibleWrap.h
content/html/content/test/test_bug408231.html
content/html/document/test/test_bug404320.html
content/html/document/test/test_bug468353.html
content/html/document/test/test_bug742261.html
dom/bindings/Utils.cpp
dom/bindings/Utils.h
dom/bluetooth/BluetoothDevice.cpp
dom/bluetooth/BluetoothDevice.h
dom/bluetooth/nsIDOMBluetoothDevice.idl
hal/fallback/FallbackHal.cpp
hal/fallback/ScreenOrientationFallback.cpp
hal/linux/LinuxHal.cpp
hal/linux/Power.cpp
hal/windows/WindowsHal.cpp
js/src/jscell.h
js/src/jsgcmark.cpp
js/src/jsgcmark.h
layout/reftests/bugs/388980-1-ref.html
layout/reftests/bugs/388980-1.html
layout/reftests/editor/338427-1-ref.html
layout/reftests/editor/338427-1.html
layout/reftests/editor/338427-2-ref.html
layout/reftests/editor/338427-2.html
layout/reftests/editor/338427-3-ref.html
layout/reftests/editor/338427-3.html
layout/reftests/editor/462758-grabbers-resizers-ref.html
layout/reftests/editor/462758-grabbers-resizers.html
layout/reftests/editor/642800-iframe.html
layout/reftests/editor/642800-ref.html
layout/reftests/editor/642800.html
layout/reftests/editor/672709-ref.html
layout/reftests/editor/672709.html
layout/reftests/editor/674212-spellcheck-ref.html
layout/reftests/editor/674212-spellcheck.html
layout/reftests/editor/694880-1.html
layout/reftests/editor/694880-2.html
layout/reftests/editor/694880-3.html
layout/reftests/editor/694880-ref.html
layout/reftests/editor/caret_after_reframe-ref.html
layout/reftests/editor/caret_after_reframe.html
layout/reftests/editor/caret_on_focus-ref.html
layout/reftests/editor/caret_on_focus.html
layout/reftests/editor/caret_on_positioned-ref.html
layout/reftests/editor/caret_on_positioned.html
layout/reftests/editor/caret_on_presshell_reinit-2.html
layout/reftests/editor/caret_on_presshell_reinit-ref.html
layout/reftests/editor/caret_on_presshell_reinit.html
layout/reftests/editor/caret_on_textarea_lastline-ref.html
layout/reftests/editor/caret_on_textarea_lastline.html
layout/reftests/editor/dynamic-1.html
layout/reftests/editor/dynamic-overflow-change-ref.html
layout/reftests/editor/dynamic-overflow-change.html
layout/reftests/editor/dynamic-ref.html
layout/reftests/editor/dynamic-type-1.html
layout/reftests/editor/dynamic-type-2.html
layout/reftests/editor/dynamic-type-3.html
layout/reftests/editor/dynamic-type-4.html
layout/reftests/editor/emptypasswd-1.html
layout/reftests/editor/emptypasswd-2.html
layout/reftests/editor/emptypasswd-ref.html
layout/reftests/editor/input-text-notheme-onfocus-reframe-ref.html
layout/reftests/editor/input-text-notheme-onfocus-reframe.html
layout/reftests/editor/input-text-onfocus-reframe-ref.html
layout/reftests/editor/input-text-onfocus-reframe.html
layout/reftests/editor/newline-1.html
layout/reftests/editor/newline-2.html
layout/reftests/editor/newline-3.html
layout/reftests/editor/newline-4.html
layout/reftests/editor/newline-ref.html
layout/reftests/editor/nobogusnode-1.html
layout/reftests/editor/nobogusnode-2.html
layout/reftests/editor/nobogusnode-ref.html
layout/reftests/editor/passwd-1.html
layout/reftests/editor/passwd-2.html
layout/reftests/editor/passwd-3.html
layout/reftests/editor/passwd-4.html
layout/reftests/editor/passwd-ref.html
layout/reftests/editor/reftest.list
layout/reftests/editor/selection_visibility_after_reframe-2.html
layout/reftests/editor/selection_visibility_after_reframe-3.html
layout/reftests/editor/selection_visibility_after_reframe-ref.html
layout/reftests/editor/selection_visibility_after_reframe.html
layout/reftests/editor/spellcheck-comma-valid-ref.html
layout/reftests/editor/spellcheck-comma-valid.html
layout/reftests/editor/spellcheck-dotafterquote-valid-ref.html
layout/reftests/editor/spellcheck-dotafterquote-valid.html
layout/reftests/editor/spellcheck-hyphen-invalid-ref.html
layout/reftests/editor/spellcheck-hyphen-invalid.html
layout/reftests/editor/spellcheck-hyphen-multiple-invalid-ref.html
layout/reftests/editor/spellcheck-hyphen-multiple-invalid.html
layout/reftests/editor/spellcheck-hyphen-multiple-valid-ref.html
layout/reftests/editor/spellcheck-hyphen-multiple-valid.html
layout/reftests/editor/spellcheck-hyphen-valid-ref.html
layout/reftests/editor/spellcheck-hyphen-valid.html
layout/reftests/editor/spellcheck-input-attr-after.html
layout/reftests/editor/spellcheck-input-attr-before.html
layout/reftests/editor/spellcheck-input-attr-dynamic-inherit.html
layout/reftests/editor/spellcheck-input-attr-dynamic-override-inherit.html
layout/reftests/editor/spellcheck-input-attr-dynamic-override.html
layout/reftests/editor/spellcheck-input-attr-dynamic.html
layout/reftests/editor/spellcheck-input-attr-inherit.html
layout/reftests/editor/spellcheck-input-disabled.html
layout/reftests/editor/spellcheck-input-nofocus-ref.html
layout/reftests/editor/spellcheck-input-property-dynamic-inherit.html
layout/reftests/editor/spellcheck-input-property-dynamic-override-inherit.html
layout/reftests/editor/spellcheck-input-property-dynamic-override.html
layout/reftests/editor/spellcheck-input-property-dynamic.html
layout/reftests/editor/spellcheck-input-ref.html
layout/reftests/editor/spellcheck-period-valid-ref.html
layout/reftests/editor/spellcheck-period-valid.html
layout/reftests/editor/spellcheck-slash-valid-ref.html
layout/reftests/editor/spellcheck-slash-valid.html
layout/reftests/editor/spellcheck-space-valid-ref.html
layout/reftests/editor/spellcheck-space-valid.html
layout/reftests/editor/spellcheck-textarea-attr-dynamic-inherit.html
layout/reftests/editor/spellcheck-textarea-attr-dynamic-override-inherit.html
layout/reftests/editor/spellcheck-textarea-attr-dynamic-override.html
layout/reftests/editor/spellcheck-textarea-attr-dynamic.html
layout/reftests/editor/spellcheck-textarea-attr-inherit.html
layout/reftests/editor/spellcheck-textarea-attr.html
layout/reftests/editor/spellcheck-textarea-disabled.html
layout/reftests/editor/spellcheck-textarea-focused-notreadonly.html
layout/reftests/editor/spellcheck-textarea-focused-reframe.html
layout/reftests/editor/spellcheck-textarea-focused.html
layout/reftests/editor/spellcheck-textarea-nofocus-ref.html
layout/reftests/editor/spellcheck-textarea-nofocus.html
layout/reftests/editor/spellcheck-textarea-property-dynamic-inherit.html
layout/reftests/editor/spellcheck-textarea-property-dynamic-override-inherit.html
layout/reftests/editor/spellcheck-textarea-property-dynamic-override.html
layout/reftests/editor/spellcheck-textarea-property-dynamic.html
layout/reftests/editor/spellcheck-textarea-ref.html
layout/reftests/editor/unneeded_scroll-ref.html
layout/reftests/editor/unneeded_scroll.html
layout/reftests/editor/xul/autocomplete-1.xul
layout/reftests/editor/xul/autocomplete-ref.xul
layout/reftests/editor/xul/empty-1.xul
layout/reftests/editor/xul/empty-2.xul
layout/reftests/editor/xul/empty-ref.xul
layout/reftests/editor/xul/emptyautocomplete-1.xul
layout/reftests/editor/xul/emptyautocomplete-ref.xul
layout/reftests/editor/xul/emptymultiline-1.xul
layout/reftests/editor/xul/emptymultiline-2.xul
layout/reftests/editor/xul/emptymultiline-ref.xul
layout/reftests/editor/xul/emptytextbox-1.xul
layout/reftests/editor/xul/emptytextbox-2.xul
layout/reftests/editor/xul/emptytextbox-3.xul
layout/reftests/editor/xul/emptytextbox-4.xul
layout/reftests/editor/xul/emptytextbox-5.xul
layout/reftests/editor/xul/emptytextbox-ref.xul
layout/reftests/editor/xul/input.css
layout/reftests/editor/xul/number-1.xul
layout/reftests/editor/xul/number-2.xul
layout/reftests/editor/xul/number-3.xul
layout/reftests/editor/xul/number-4.xul
layout/reftests/editor/xul/number-5.xul
layout/reftests/editor/xul/number-ref.xul
layout/reftests/editor/xul/numberwithvalue-1.xul
layout/reftests/editor/xul/numberwithvalue-ref.xul
layout/reftests/editor/xul/passwd-1.xul
layout/reftests/editor/xul/passwd-2.xul
layout/reftests/editor/xul/passwd-3.xul
layout/reftests/editor/xul/passwd-ref.xul
layout/reftests/editor/xul/plain-1.xul
layout/reftests/editor/xul/plain-ref.xul
layout/reftests/editor/xul/platform.js
layout/reftests/editor/xul/reftest.list
layout/reftests/editor/xul/textbox-1.xul
layout/reftests/editor/xul/textbox-disabled.xul
layout/reftests/editor/xul/textbox-readonly.xul
layout/reftests/editor/xul/textbox-ref.xul
layout/reftests/svg/image/image-zoom-01-ref.svg
layout/reftests/svg/image/image-zoom-01a.svg
layout/reftests/svg/image/image-zoom-01b.svg
xpcom/ds/TimeStamp.cpp
new file mode 100644
--- /dev/null
+++ b/.gdbinit
@@ -0,0 +1,175 @@
+# .gdbinit file for debugging Mozilla
+
+# Don't stop for the SIG32/33/etc signals that Flash produces
+handle SIG32 noprint nostop pass
+handle SIG33 noprint nostop pass
+handle SIGPIPE noprint nostop pass
+
+# Show the concrete types behind nsIFoo
+set print object on
+
+# run when using the auto-solib-add trick
+def prun
+        tbreak main
+        run
+	set auto-solib-add 0
+        cont
+end
+
+# run -mail, when using the auto-solib-add trick
+def pmail
+        tbreak main
+        run -mail
+	set auto-solib-add 0
+        cont
+end
+
+# Define a "pu" command to display PRUnichar * strings (100 chars max)
+# Also allows an optional argument for how many chars to print as long as
+# it's less than 100.
+def pu
+  set $uni = $arg0
+  if $argc == 2
+    set $limit = $arg1
+    if $limit > 100
+      set $limit = 100
+    end
+  else
+    set $limit = 100
+  end
+  # scratch array with space for 100 chars plus null terminator.  Make
+  # sure to not use ' ' as the char so this copy/pastes well.
+  set $scratch = "____________________________________________________________________________________________________"
+  set $i = 0
+  set $scratch_idx = 0
+  while (*$uni && $i++ < $limit)
+    if (*$uni < 0x80)
+      set $scratch[$scratch_idx++] = *(char*)$uni++
+    else
+      if ($scratch_idx > 0)
+	set $scratch[$scratch_idx] = '\0'
+	print $scratch
+	set $scratch_idx = 0
+      end
+      print /x *(short*)$uni++
+    end
+  end
+  if ($scratch_idx > 0)
+    set $scratch[$scratch_idx] = '\0'
+    print $scratch
+  end
+end
+
+# Define a "ps" command to display subclasses of nsAC?String.  Note that
+# this assumes strings as of Gecko 1.9 (well, and probably a few
+# releases before that as well); going back far enough will get you
+# to string classes that this function doesn't work for.
+def ps
+  set $str = $arg0
+  if (sizeof(*$str.mData) == 1 && ($str.mFlags & 1) != 0)
+    print $str.mData
+  else
+    pu $str.mData $str.mLength
+  end
+end
+
+# Define a "pa" command to display the string value for an nsIAtom
+def pa
+  set $atom = $arg0
+  if (sizeof(*((&*$atom)->mString)) == 2)
+    pu (&*$atom)->mString
+  end
+end
+
+# define a "pxul" command to display the type of a XUL element from
+# an nsXULDocument* pointer.
+def pxul
+  set $p = $arg0
+  print $p->mNodeInfo.mRawPtr->mInner.mName->mStaticAtom->mString
+end
+
+# define a "prefcnt" command to display the refcount of an XPCOM obj
+def prefcnt
+  set $p = $arg0
+  print ((nsPurpleBufferEntry*)$p->mRefCnt.mTagged)->mRefCnt
+end
+
+# define a "ptag" command to display the tag name of a content node
+def ptag
+  set $p = $arg0
+  pa $p->mNodeInfo.mRawPtr->mInner.mName
+end
+
+##
+## nsTArray
+##
+define ptarray
+        if $argc == 0
+                help ptarray
+        else
+                set $size = $arg0.mHdr->mLength
+                set $capacity = $arg0.mHdr->mCapacity
+                set $size_max = $size - 1
+                set $elts = $arg0.Elements()
+        end
+        if $argc == 1
+                set $i = 0
+                while $i < $size
+                        printf "elem[%u]: ", $i
+                        p *($elts + $i)
+                        set $i++
+                end
+        end
+        if $argc == 2
+                set $idx = $arg1
+                if $idx < 0 || $idx > $size_max
+                        printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max
+                else
+                        printf "elem[%u]: ", $idx
+                        p *($elts + $idx)
+                end
+        end
+        if $argc == 3
+          set $start_idx = $arg1
+          set $stop_idx = $arg2
+          if $start_idx > $stop_idx
+            set $tmp_idx = $start_idx
+            set $start_idx = $stop_idx
+            set $stop_idx = $tmp_idx
+          end
+          if $start_idx < 0 || $stop_idx < 0 || $start_idx > $size_max || $stop_idx > $size_max
+            printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max
+          else
+            set $i = $start_idx
+                while $i <= $stop_idx
+                        printf "elem[%u]: ", $i
+                        p *($elts + $i)
+                        set $i++
+                end
+          end
+        end
+        if $argc > 0
+                printf "nsTArray length = %u\n", $size
+                printf "nsTArray capacity = %u\n", $capacity
+                printf "Element "
+                whatis *$elts
+        end
+end
+
+document ptarray
+        Prints nsTArray information.
+        Syntax: ptarray   
+        Note: idx, idx1 and idx2 must be in acceptable range [0...size()-1].
+        Examples:
+        ptarray a - Prints tarray content, size, capacity and T typedef
+        ptarray a 0 - Prints element[idx] from tarray
+        ptarray a 1 2 - Prints elements in range [idx1..idx2] from tarray
+end
+
+def js
+  call DumpJSStack()
+end
+
+def ft
+  call nsFrame::DumpFrameTree($arg0)
+end
--- a/.hgignore
+++ b/.hgignore
@@ -8,17 +8,17 @@
 (^|/)\.DS_Store$
 
 # Vim swap files.
 ^\.sw.$
 .[^/]*\.sw.$
 
 # User files that may appear at the root
 ^\.mozconfig
-^mozconfig$
+^mozconfig*
 ^configure$
 ^config\.cache$
 ^config\.log$
 
 # Empty marker file that's generated when we check out NSS
 ^security/manager/\.nss\.checkout$
 
 # Build directories
@@ -39,9 +39,8 @@
 
 # SVN directories
 \.svn/
 
 # Ignore the files and directory that Eclipse IDE creates
 \.project$
 \.cproject$
 \.settings/
-
--- a/Makefile.in
+++ b/Makefile.in
@@ -232,16 +232,20 @@ else
 maybe_clobber_profiledbuild:
 endif
 else
 maybe_clobber_profiledbuild:
 	$(RM) $(DIST)/bin/*.pgc
 	find $(DIST)/$(MOZ_APP_NAME) -name "*.pgc" -exec mv {} $(DIST)/bin \;
 endif
 
+# put in our default gdbinit so that the gdb debugging experience is happier.
+libs:: .gdbinit
+	$(INSTALL) $< $(DIST)/bin
+
 .PHONY: maybe_clobber_profiledbuild
 
 # Look for R_386_PC32 relocations in shared libs, these
 # break x86_64 builds and SELinux users.
 ifeq ($(OS_TARGET)_$(TARGET_XPCOM_ABI),Linux_x86-gcc3)
 scheck::
 	@relcount=`find $(DIST)/bin -name "*.so" | xargs objdump -R | grep R_386_PC32 | wc -l` && if test $$relcount -gt 0; then echo "FAILED: R_386_PC32 relocations detected in a shared library.  Did you use a system header without adding it to config/system-headers?"; exit 1; else echo "PASSED"; fi
 endif
--- a/accessible/accessible-docs.html
+++ b/accessible/accessible-docs.html
@@ -832,21 +832,21 @@ the <a
  href="http://lxr.mozilla.org/seamonkey/search?string=WM_GETOBJECT">WM_GETOBJECT</a>
 message in, nsWindow.cpp first generates an internal event called <a
  href="http://lxr.mozilla.org/seamonkey/search?string=NS_GETACCESSIBLE">NS_GETACCESSIBLE</a>,
 which is handled in <a
  href="http://lxr.mozilla.org/seamonkey/source/layout/html/base/src/nsPresShell.cpp#6345">PresShell::HandleEventInternal()</a>
 via the creation of an <a
  href="http://lxr.mozilla.org/seamonkey/find?string=msaa/nsDocAccessibleWrap">nsDocAccessibleWrap</a>
 for an inner window or <a
- href="http://lxr.mozilla.org/seamonkey/find?string=msaa/nsRootAccessibleWrap">nsRootAccessibleWrap</a>
+ href="http://lxr.mozilla.org/seamonkey/find?string=msaa/RootAccessibleWrap">RootAccessibleWrap</a>
 for a top level window. These classes implement both nsIAccessible, our
 cross platform API, as well as IAccessible, which is specific to
 Windows/MSAA/COM. The cross-platform nsDocAccessible and
-nsRootAccessible classes they inherit from are then told to start
+RootAccessible classes they inherit from are then told to start
 listening for DOM, page load and scroll events.&nbsp; These events cause
 MSAA-specific events, such as EVENT_OBJECT_FOCUS or
 EVENT_OBJECT_STATECHANGE, to fire on UI and document objects within the
 applicable window. We'll explain more about events later in this section.<br>
   </p>
   <p>Until the WM_GETOBJECT message is processed, the Gecko
 accessibility service is not used, and thus the accessibility.dll is not
 loaded, so there is almost zero overhead for accessibility API support
@@ -965,17 +965,17 @@ MSAA Events</h3>
 accessibility aids. Therefore we implement only the handful that matter.
 See the <a
  href="file:///c%7C/moz/mozdocs/mozilla-org/html/projects/ui/accessibility/accessible-architecture.html#events">Events</a>
 cheat sheet above for the list of events we implement. By far the most
 important one is EVENT_OBJECT_FOCUS.<br>
   </p>
   <p>When a potential accessibility-related event occurs within
 Mozilla, it is typically listened for by nsDocAccessible or
-nsRootAccessible. The event listeners on these classes call
+RootAccessible. The event listeners on these classes call
 FireToolkitEvent(), which is implemented for every accessible.
 Eventually, the event ends up at nsDocAccessibleWrap::FireToolkitEvent()
 which calls NotifyWinEvent from the Win32 API. NotifyWinEvent is passed
 arguments for the window the event occurred in, and the ID of the child
 within that window. Accessibility aids use the Win32 call
 SetWinEventHook() to register as a listener for these events. Creating
 a unique child ID for every object within a window can be difficult,
 see the problem and solution for <a
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -47,39 +47,38 @@ EXPORT_LIBRARY = ..
 LIBXUL_LIBRARY = 1
 
 
 CPPSRCS = \
   AtkSocketAccessible.cpp \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
   nsDocAccessibleWrap.cpp \
-  nsRootAccessibleWrap.cpp \
   ApplicationAccessibleWrap.cpp \
   nsMaiInterfaceComponent.cpp \
   nsMaiInterfaceAction.cpp \
   nsMaiInterfaceText.cpp \
   nsMaiInterfaceEditableText.cpp \
   nsMaiInterfaceSelection.cpp \
   nsMaiInterfaceValue.cpp \
   nsMaiHyperlink.cpp \
   nsMaiInterfaceHypertext.cpp \
   nsMaiInterfaceHyperlinkImpl.cpp \
   nsMaiInterfaceTable.cpp \
   nsMaiInterfaceDocument.cpp \
   nsMaiInterfaceImage.cpp \
+  RootAccessibleWrap.cpp \
   $(NULL)
 
 EXPORTS = \
   ARIAGridAccessibleWrap.h \
   AtkSocketAccessible.h \
   nsAccessNodeWrap.h \
   nsAccessibleWrap.h \
   nsDocAccessibleWrap.h \
-  nsRootAccessibleWrap.h \
   nsTextAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULListboxAccessibleWrap.h \
   nsXULTreeGridAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
   $(NULL)
rename from accessible/src/atk/nsRootAccessibleWrap.cpp
rename to accessible/src/atk/RootAccessibleWrap.cpp
--- a/accessible/src/atk/nsRootAccessibleWrap.cpp
+++ b/accessible/src/atk/RootAccessibleWrap.cpp
@@ -33,27 +33,30 @@
  * 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 "RootAccessibleWrap.h"
+
 #include "nsMai.h"
-#include "nsRootAccessibleWrap.h"
 
-nsNativeRootAccessibleWrap::nsNativeRootAccessibleWrap(AtkObject *aAccessible):
-    nsRootAccessible(nsnull, nsnull, nsnull)
+using namespace mozilla::a11y;
+
+NativeRootAccessibleWrap::NativeRootAccessibleWrap(AtkObject* aAccessible):
+  RootAccessible(nsnull, nsnull, nsnull)
 {
   // XXX: mark the object as defunct to ensure no single internal method is
   // running on it.
   mFlags |= eIsDefunct;
 
   g_object_ref(aAccessible);
   mAtkObject = aAccessible;
 }
 
-nsNativeRootAccessibleWrap::~nsNativeRootAccessibleWrap()
+NativeRootAccessibleWrap::~NativeRootAccessibleWrap()
 {
-    g_object_unref(mAtkObject);
-    mAtkObject = nsnull;
+  g_object_unref(mAtkObject);
+  mAtkObject = nsnull;
 }
rename from accessible/src/atk/nsRootAccessibleWrap.h
rename to accessible/src/atk/RootAccessibleWrap.h
--- a/accessible/src/atk/nsRootAccessibleWrap.h
+++ b/accessible/src/atk/RootAccessibleWrap.h
@@ -33,28 +33,35 @@
  * 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 ***** */
 
-#ifndef __NS_ROOT_ACCESSIBLE_WRAP_H__
-#define __NS_ROOT_ACCESSIBLE_WRAP_H__
+#ifndef mozilla_a11y_RootAccessibleWrap_h__
+#define mozilla_a11y_RootAccessibleWrap_h__
 
-#include "nsRootAccessible.h"
+#include "RootAccessible.h"
 
-typedef nsRootAccessible nsRootAccessibleWrap;
+namespace mozilla {
+namespace a11y {
 
-/* nsNativeRootAccessibleWrap is the accessible class for gtk+ native window.
- * The instance of nsNativeRootAccessibleWrap is a child of MaiAppRoot instance.
+typedef RootAccessible RootAccessibleWrap;
+
+/* NativeRootAccessibleWrap is the accessible class for gtk+ native window.
+ * The instance of NativeRootAccessibleWrap is a child of MaiAppRoot instance.
  * It is added into root when the toplevel window is created, and removed
  * from root when the toplevel window is destroyed.
  */
-class nsNativeRootAccessibleWrap: public nsRootAccessible
+class NativeRootAccessibleWrap : public RootAccessible
 {
 public:
-    nsNativeRootAccessibleWrap(AtkObject *aAccessible);
-    ~nsNativeRootAccessibleWrap();
+  NativeRootAccessibleWrap(AtkObject* aAccessible);
+  virtual ~NativeRootAccessibleWrap();
 };
 
-#endif   /* __NS_ROOT_ACCESSIBLE_WRAP_H__ */
+} // namespace a11y
+} // namespace mozilla
+
+#endif   /* mozilla_a11y_Root_Accessible_Wrap_h__ */
+
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -40,26 +40,26 @@
 
 #include "nsAccessibleWrap.h"
 
 #include "Accessible-inl.h"
 #include "ApplicationAccessibleWrap.h"
 #include "InterfaceInitFuncs.h"
 #include "nsAccUtils.h"
 #include "nsIAccessibleRelation.h"
-#include "nsRootAccessible.h"
-#include "nsDocAccessibleWrap.h"
+#include "RootAccessible.h"
 #include "nsIAccessibleValue.h"
 #include "nsMai.h"
 #include "nsMaiHyperlink.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "prprf.h"
 #include "nsStateMap.h"
 #include "Relation.h"
+#include "RootAccessible.h"
 #include "States.h"
 
 #include "mozilla/Util.h"
 #include "nsXPCOMStrings.h"
 #include "nsComponentManagerUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
@@ -724,18 +724,31 @@ getRoleCB(AtkObject *aAtkObj)
 #ifdef DEBUG_A11Y
   NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(accWrap),
       "Does not support nsIAccessibleText when it should");
 #endif
 
   if (aAtkObj->role != ATK_ROLE_INVALID)
     return aAtkObj->role;
 
-  return aAtkObj->role =
-    static_cast<AtkRole>(nsAccessibleWrap::AtkRoleFor(accWrap->Role()));
+#define ROLE(geckoRole, stringRole, atkRole, macRole, msaaRole, ia2Role) \
+  case roles::geckoRole: \
+    aAtkObj->role = atkRole; \
+    break;
+
+  switch (accWrap->Role()) {
+#include "RoleMap.h"
+    default:
+      MOZ_NOT_REACHED("Unknown role.");
+      aAtkObj->role = ATK_ROLE_UNKNOWN;
+  };
+
+#undef ROLE
+
+  return aAtkObj->role;
 }
 
 AtkAttributeSet*
 ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes)
 {
     if (!aAttributes)
         return nsnull;
 
@@ -1022,17 +1035,17 @@ nsAccessibleWrap::FirePlatformEvent(AccE
 
     case nsIAccessibleEvent::EVENT_TEXT_REMOVED:
     case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
         return FireAtkTextChangedEvent(aEvent, atkObj);
 
     case nsIAccessibleEvent::EVENT_FOCUS:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_FOCUS\n"));
-        nsRootAccessible* rootAccWrap = accWrap->RootAccessible();
+        a11y::RootAccessible* rootAccWrap = accWrap->RootAccessible();
         if (rootAccWrap && rootAccWrap->mActivated) {
             atk_focus_tracker_notify(atkObj);
             // Fire state change event for focus
             nsRefPtr<AccEvent> stateChangeEvent =
               new AccStateChangeEvent(accessible, states::FOCUSED, true);
             return FireAtkStateChangeEvent(stateChangeEvent, atkObj);
         }
       } break;
@@ -1215,32 +1228,28 @@ nsAccessibleWrap::FirePlatformEvent(AccE
 
     case nsIAccessibleEvent::EVENT_MENU_END:
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENU_END\n"));
         break;
 
     case nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_ACTIVATED\n"));
-        nsRootAccessible *rootAcc =
-          static_cast<nsRootAccessible *>(accessible);
-        rootAcc->mActivated = true;
+        accessible->AsRoot()->mActivated = true;
         guint id = g_signal_lookup ("activate", MAI_TYPE_ATK_OBJECT);
         g_signal_emit(atkObj, id, 0);
 
         // Always fire a current focus event after activation.
         FocusMgr()->ForceFocusEvent();
       } break;
 
     case nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_DEACTIVATED\n"));
-        nsRootAccessible *rootAcc =
-          static_cast<nsRootAccessible *>(accessible);
-        rootAcc->mActivated = false;
+        accessible->AsRoot()->mActivated = false;
         guint id = g_signal_lookup ("deactivate", MAI_TYPE_ATK_OBJECT);
         g_signal_emit(atkObj, id, 0);
       } break;
 
     case nsIAccessibleEvent::EVENT_WINDOW_MAXIMIZE:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_MAXIMIZE\n"));
         guint id = g_signal_lookup ("maximize", MAI_TYPE_ATK_OBJECT);
@@ -1385,25 +1394,8 @@ nsAccessibleWrap::FireAtkShowHideEvent(A
     bool isFromUserInput = aEvent->IsFromUserInput();
     char *signal_name = g_strconcat(aIsAdded ? "children_changed::add" :  "children_changed::remove",
                                     isFromUserInput ? "" : kNonUserInputEvent, NULL);
     g_signal_emit_by_name(parentObject, signal_name, indexInParent, aObject, NULL);
     g_free(signal_name);
 
     return NS_OK;
 }
-
-PRUint32
-nsAccessibleWrap::AtkRoleFor(role aRole)
-{
-#define ROLE(geckoRole, stringRole, atkRole, macRole, msaaRole, ia2Role) \
-  case roles::geckoRole: \
-    return atkRole;
-
-  switch (aRole) {
-#include "RoleMap.h"
-    default:
-      MOZ_NOT_REACHED("Unknown role.");
-      return ATK_ROLE_UNKNOWN;
-  }
-
-#undef ROLE
-}
--- a/accessible/src/atk/nsAccessibleWrap.h
+++ b/accessible/src/atk/nsAccessibleWrap.h
@@ -111,21 +111,16 @@ public:
     void SetMaiHyperlink(MaiHyperlink* aMaiHyperlink);
 
     static const char * ReturnString(nsAString &aString) {
       static nsCString returnedString;
       returnedString = NS_ConvertUTF16toUTF8(aString);
       return returnedString.get();
     }
 
-  /**
-   * Function mapping from cross platform roles to ATK roles.
-   */
-  static PRUint32 AtkRoleFor(mozilla::a11y::role aRole);
-
 protected:
     virtual nsresult FirePlatformEvent(AccEvent* aEvent);
 
     nsresult FireAtkStateChangeEvent(AccEvent* aEvent, AtkObject *aObject);
     nsresult FireAtkTextChangedEvent(AccEvent* aEvent, AtkObject *aObject);
     nsresult FireAtkShowHideEvent(AccEvent* aEvent, AtkObject *aObject,
                                   bool aIsAdded);
 
--- a/accessible/src/atk/nsMaiInterfaceText.cpp
+++ b/accessible/src/atk/nsMaiInterfaceText.cpp
@@ -40,27 +40,28 @@
 
 #include "InterfaceInitFuncs.h"
 
 #include "nsHyperTextAccessible.h"
 #include "nsMai.h"
 
 #include "nsIPersistentProperties2.h"
 
+using namespace mozilla::a11y;
+
 AtkAttributeSet* ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes);
 
 static void
 ConvertTexttoAsterisks(nsAccessibleWrap* accWrap, nsAString& aString)
 {
-    // convert each char to "*" when it's "password text" 
-    PRUint32 atkRole = nsAccessibleWrap::AtkRoleFor(accWrap->NativeRole());
-    if (atkRole == ATK_ROLE_PASSWORD_TEXT) {
-        for (PRUint32 i = 0; i < aString.Length(); i++)
-            aString.Replace(i, 1, NS_LITERAL_STRING("*"));
-    }
+  // convert each char to "*" when it's "password text" 
+  if (accWrap->NativeRole() == roles::PASSWORD_TEXT) {
+    for (PRUint32 i = 0; i < aString.Length(); i++)
+      aString.Replace(i, 1, NS_LITERAL_STRING("*"));
+  }
 }
 
 extern "C" {
 
 static gchar*
 getTextCB(AtkText *aText, gint aStartOffset, gint aEndOffset)
 {
     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
@@ -137,39 +138,39 @@ getTextAtOffsetCB(AtkText *aText, gint a
     NS_ENSURE_SUCCESS(rv, nsnull);
 
     ConvertTexttoAsterisks(accWrap, autoStr);
     NS_ConvertUTF16toUTF8 cautoStr(autoStr);
     return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nsnull;
 }
 
 static gunichar
-getCharacterAtOffsetCB(AtkText *aText, gint aOffset)
+getCharacterAtOffsetCB(AtkText* aText, gint aOffset)
 {
-    nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-    if (!accWrap)
-        return 0;
+  nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
+  if (!accWrap)
+    return 0;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, 0);
+  nsCOMPtr<nsIAccessibleText> accText;
+  accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
+                          getter_AddRefs(accText));
+  NS_ENSURE_TRUE(accText, 0);
 
-    /* PRUnichar is unsigned short in Mozilla */
-    /* gnuichar is guint32 in glib */
-    PRUnichar uniChar;
-    nsresult rv =
-        accText->GetCharacterAtOffset(aOffset, &uniChar);
+  // PRUnichar is unsigned short in Mozilla
+  // gnuichar is guint32 in glib
+  PRUnichar uniChar = 0;
+  nsresult rv = accText->GetCharacterAtOffset(aOffset, &uniChar);
+  if (NS_FAILED(rv))
+    return 0;
 
-    // convert char to "*" when it's "password text" 
-    PRUint32 atkRole = nsAccessibleWrap::AtkRoleFor(accWrap->NativeRole());
-    if (atkRole == ATK_ROLE_PASSWORD_TEXT)
-        uniChar = '*';
+  // Convert char to "*" when it's "password text".
+  if (accWrap->NativeRole() == roles::PASSWORD_TEXT)
+    uniChar = '*';
 
-    return (NS_FAILED(rv)) ? 0 : static_cast<gunichar>(uniChar);
+  return static_cast<gunichar>(uniChar);
 }
 
 static gchar*
 getTextBeforeOffsetCB(AtkText *aText, gint aOffset,
                       AtkTextBoundary aBoundaryType,
                       gint *aStartOffset, gint *aEndOffset)
 {
     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
--- a/accessible/src/base/FocusManager.cpp
+++ b/accessible/src/base/FocusManager.cpp
@@ -35,18 +35,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "FocusManager.h"
 
 #include "Accessible-inl.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
-#include "nsRootAccessible.h"
 #include "Role.h"
+#include "RootAccessible.h"
 
 #include "nsEventStateManager.h"
 #include "nsFocusManager.h"
 
 namespace dom = mozilla::dom;
 using namespace mozilla::a11y;
 
 FocusManager::FocusManager()
@@ -152,17 +152,17 @@ FocusManager::NotifyOfDOMFocus(nsISuppor
 
   nsCOMPtr<nsINode> targetNode(do_QueryInterface(aTarget));
   if (targetNode) {
     nsDocAccessible* document =
       GetAccService()->GetDocAccessible(targetNode->OwnerDoc());
     if (document) {
       // Set selection listener for focused element.
       if (targetNode->IsElement()) {
-        nsRootAccessible* root = document->RootAccessible();
+        RootAccessible* root = document->RootAccessible();
         nsCaretAccessible* caretAcc = root->GetCaretAccessible();
         caretAcc->SetControlSelectionListener(targetNode->AsElement());
       }
 
       document->HandleNotification<FocusManager, nsINode>
         (this, &FocusManager::ProcessDOMFocus, targetNode);
     }
   }
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -63,17 +63,16 @@ CPPSRCS = \
   nsCoreUtils.cpp \
   nsAccUtils.cpp \
   nsAccessibilityService.cpp \
   nsAccessible.cpp \
   nsAccessiblePivot.cpp \
   nsAccTreeWalker.cpp \
   nsBaseWidgetAccessible.cpp \
   nsEventShell.cpp \
-  nsRootAccessible.cpp \
   nsCaretAccessible.cpp \
   nsTextAccessible.cpp \
   nsTextEquivUtils.cpp \
   StyleInfo.cpp \
   TextAttrs.cpp \
   TextUpdater.cpp \
   $(NULL)
 
--- a/accessible/src/base/Role.h
+++ b/accessible/src/base/Role.h
@@ -809,17 +809,17 @@ enum Role {
   /**
    * Represent a term in a definition list (dt in HTML).
    */
   TERM = 127,
 
   /**
    * Represent a definition in a definition list (dd in HTML)
    */
-  DEFINITION = 128,
+  DEFINITION = 128
 };
 
 } // namespace role
 
 typedef enum mozilla::a11y::roles::Role role;
 
 } // namespace a11y
 } // namespace mozilla
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -37,17 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAccDocManager.h"
 
 #include "ApplicationAccessible.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsARIAMap.h"
-#include "nsRootAccessibleWrap.h"
+#include "RootAccessibleWrap.h"
 #include "States.h"
 
 #include "nsCURILoader.h"
 #include "nsDocShellLoadTypes.h"
 #include "nsIChannel.h"
 #include "nsIContentViewer.h"
 #include "nsIDOMDocument.h"
 #include "nsEventListenerManager.h"
@@ -351,17 +351,17 @@ nsAccDocManager::AddListeners(nsIDocumen
   if (aAddDOMContentLoadedListener) {
     elm->AddEventListenerByType(this, NS_LITERAL_STRING("DOMContentLoaded"),
                                 NS_EVENT_FLAG_CAPTURE);
     NS_LOG_ACCDOCCREATE_TEXT("  added 'DOMContentLoaded' listener")
   }
 }
 
 nsDocAccessible*
-nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
+nsAccDocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
 {
   // Ignore temporary, hiding, resource documents and documents without
   // docshell.
   if (aDocument->IsInitialDocument() || !aDocument->IsVisible() ||
       aDocument->IsResourceDoc() || !aDocument->IsActive())
     return nsnull;
 
   // Ignore documents without presshell and not having root frame.
@@ -386,17 +386,17 @@ nsAccDocManager::CreateDocOrRootAccessib
                  "Can't create an accessible for the document!");
     if (!parentDocAcc)
       return nsnull;
   }
 
   // We only create root accessibles for the true root, otherwise create a
   // doc accessible.
   nsRefPtr<nsDocAccessible> docAcc = isRootDoc ?
-    new nsRootAccessibleWrap(aDocument, rootElm, presShell) :
+    new RootAccessibleWrap(aDocument, rootElm, presShell) :
     new nsDocAccessibleWrap(aDocument, rootElm, presShell);
 
   // Cache the document accessible into document cache.
   if (!docAcc || !mDocAccessibleCache.Put(aDocument, docAcc))
     return nsnull;
 
   // Initialize the document accessible.
   if (!docAcc->Init()) {
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -37,33 +37,35 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAccessNode.h"
 
 #include "ApplicationAccessibleWrap.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
-#include "nsRootAccessible.h"
+#include "RootAccessible.h"
 
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDOMWindow.h"
 #include "nsIFrame.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIObserverService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsIStringBundle.h"
 #include "nsFocusManager.h"
 #include "nsPresContext.h"
 #include "mozilla/Services.h"
 
+using namespace mozilla::a11y;
+
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 nsIStringBundle *nsAccessNode::gStringBundle = 0;
 
 bool nsAccessNode::gIsFormFillEnabled = false;
 
@@ -87,19 +89,16 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DE
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNode construction/desctruction
 
 nsAccessNode::
   nsAccessNode(nsIContent* aContent, nsDocAccessible* aDoc) :
   mContent(aContent), mDoc(aDoc)
 {
-#ifdef DEBUG_A11Y
-  mIsInitialized = false;
-#endif
 }
 
 nsAccessNode::~nsAccessNode()
 {
   NS_ASSERTION(!mDoc, "LastRelease was never called!?!");
 }
 
 void nsAccessNode::LastRelease()
@@ -202,17 +201,17 @@ void nsAccessNode::ShutdownXPAccessibili
   if (gApplicationAccessible) {
     gApplicationAccessible->Shutdown();
     NS_RELEASE(gApplicationAccessible);
   }
 
   NotifyA11yInitOrShutdown(false);
 }
 
-nsRootAccessible*
+RootAccessible*
 nsAccessNode::RootAccessible() const
 {
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
     nsCoreUtils::GetDocShellTreeItemFor(mContent);
   NS_ASSERTION(docShellTreeItem, "No docshell tree item for mContent");
   if (!docShellTreeItem) {
     return nsnull;
   }
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -52,17 +52,22 @@
 #include "nsINameSpaceManager.h"
 #include "nsIStringBundle.h"
 #include "nsWeakReference.h"
 
 class ApplicationAccessible;
 class nsAccessNode;
 class nsDocAccessible;
 class nsIAccessibleDocument;
-class nsRootAccessible;
+
+namespace mozilla {
+namespace a11y {
+class RootAccessible;
+}
+}
 
 class nsIPresShell;
 class nsPresContext;
 class nsIFrame;
 class nsIDocShellTreeItem;
 
 #define ACCESSIBLE_BUNDLE_URL "chrome://global-platform/locale/accessible.properties"
 #define PLATFORM_KEYS_BUNDLE_URL "chrome://global-platform/locale/platformKeys.properties"
@@ -88,17 +93,17 @@ public:
   /**
    * Return the document accessible for this access node.
    */
   nsDocAccessible* Document() const { return mDoc; }
 
   /**
    * Return the root document accessible for this accessnode.
    */
-  nsRootAccessible* RootAccessible() const;
+  mozilla::a11y::RootAccessible* RootAccessible() const;
 
   /**
    * Initialize the access node object, add it to the cache.
    */
   virtual bool Init();
 
   /**
    * Shutdown the access node object.
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -52,21 +52,21 @@
 #include "nsIAccessibleProvider.h"
 #include "nsHTMLCanvasAccessible.h"
 #include "nsHTMLImageMapAccessible.h"
 #include "nsHTMLLinkAccessible.h"
 #include "nsHTMLSelectAccessible.h"
 #include "nsHTMLTableAccessibleWrap.h"
 #include "nsHTMLTextAccessible.h"
 #include "nsHyperTextAccessibleWrap.h"
-#include "nsRootAccessibleWrap.h"
 #include "nsXFormsFormControlsAccessible.h"
 #include "nsXFormsWidgetsAccessible.h"
 #include "OuterDocAccessible.h"
 #include "Role.h"
+#include "RootAccessibleWrap.h"
 #include "States.h"
 #include "Statistics.h"
 #ifdef XP_WIN
 #include "nsHTMLWin32ObjectAccessible.h"
 #endif
 
 #include "nsCURILoader.h"
 #include "nsEventStates.h"
@@ -652,17 +652,17 @@ nsAccessibilityService::PresShellDestroy
 
 void
 nsAccessibilityService::PresShellActivated(nsIPresShell* aPresShell)
 {
   nsIDocument* DOMDoc = aPresShell->GetDocument();
   if (DOMDoc) {
     nsDocAccessible* document = GetDocAccessibleFromCache(DOMDoc);
     if (document) {
-      nsRootAccessible* rootDocument = document->RootAccessible();
+      RootAccessible* rootDocument = document->RootAccessible();
       NS_ASSERTION(rootDocument, "Entirely broken tree: no root document!");
       if (rootDocument)
         rootDocument->DocumentActivated(document);
     }
   }
 }
 
 void
@@ -1723,34 +1723,34 @@ nsAccessibilityService::CreateHTMLAccess
   return nsnull;
  }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibilityService (DON'T put methods here)
 
 nsAccessible*
 nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible)
- {
+{
 #ifdef MOZ_ACCESSIBILITY_ATK
   ApplicationAccessible* applicationAcc =
     nsAccessNode::GetApplicationAccessible();
   if (!applicationAcc)
     return nsnull;
 
-  nsRefPtr<nsNativeRootAccessibleWrap> nativeRootAcc =
-     new nsNativeRootAccessibleWrap((AtkObject*)aAtkAccessible);
+  nsRefPtr<NativeRootAccessibleWrap> nativeRootAcc =
+    new NativeRootAccessibleWrap(static_cast<AtkObject*>(aAtkAccessible));
   if (!nativeRootAcc)
     return nsnull;
 
   if (applicationAcc->AppendChild(nativeRootAcc))
     return nativeRootAcc;
 #endif
 
   return nsnull;
- }
+}
 
 void
 nsAccessibilityService::RemoveNativeRootAccessible(nsAccessible* aAccessible)
 {
 #ifdef MOZ_ACCESSIBILITY_ATK
   ApplicationAccessible* applicationAcc =
     nsAccessNode::GetApplicationAccessible();
 
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -45,20 +45,20 @@
 #include "AccIterator.h"
 #include "nsAccUtils.h"
 #include "nsAccEvent.h"
 #include "nsAccessibleRelation.h"
 #include "nsAccessibilityService.h"
 #include "nsAccTreeWalker.h"
 #include "nsIAccessibleRelation.h"
 #include "nsEventShell.h"
-#include "nsRootAccessible.h"
 #include "nsTextEquivUtils.h"
 #include "Relation.h"
 #include "Role.h"
+#include "RootAccessible.h"
 #include "States.h"
 #include "StyleInfo.h"
 
 #include "nsIDOMCSSValue.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentXBL.h"
@@ -252,18 +252,17 @@ nsAccessible::GetDOMNode(nsIDOMNode **aD
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessible::GetRootDocument(nsIAccessibleDocument **aRootDocument)
 {
   NS_ENSURE_ARG_POINTER(aRootDocument);
 
-  nsRootAccessible* rootDocument = RootAccessible();
-  NS_IF_ADDREF(*aRootDocument = rootDocument);
+  NS_IF_ADDREF(*aRootDocument = RootAccessible());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessible::GetLanguage(nsAString& aLanguage)
 {
   Language(aLanguage);
   return NS_OK;
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -484,17 +484,17 @@ public:
 
   inline bool IsListControl() const { return mFlags & eListControlAccessible; }
 
   inline bool IsMenuButton() const { return mFlags & eMenuButtonAccessible; }
 
   inline bool IsMenuPopup() const { return mFlags & eMenuPopupAccessible; }
 
   inline bool IsRoot() const { return mFlags & eRootAccessible; }
-  nsRootAccessible* AsRoot();
+  mozilla::a11y::RootAccessible* AsRoot();
 
   virtual mozilla::a11y::TableAccessible* AsTable() { return nsnull; }
 
   inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
   nsTextAccessible* AsTextLeaf();
 
   //////////////////////////////////////////////////////////////////////////////
   // ActionAccessible
--- a/accessible/src/base/nsCaretAccessible.cpp
+++ b/accessible/src/base/nsCaretAccessible.cpp
@@ -36,45 +36,47 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsCaretAccessible.h"
 
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "nsIAccessibleEvent.h"
+#include "RootAccessible.h"
 
 #include "nsCaret.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMHTMLTextAreaElement.h"
 #include "nsIFrame.h"
 #include "nsIPresShell.h"
-#include "nsRootAccessible.h"
 #include "nsISelectionPrivate.h"
 #include "nsServiceManagerUtils.h"
 
 class nsIWidget;
 
+using namespace mozilla::a11y;
+
 NS_IMPL_ISUPPORTS1(nsCaretAccessible, nsISelectionListener)
   
-nsCaretAccessible::nsCaretAccessible( nsRootAccessible *aRootAccessible):
+nsCaretAccessible::nsCaretAccessible(RootAccessible* aRootAccessible) :
 mLastCaretOffset(-1), mRootAccessible(aRootAccessible)
 {
 }
 
 nsCaretAccessible::~nsCaretAccessible()
 {
 }
 
 void nsCaretAccessible::Shutdown()
 {
-  // The caret accessible isn't shut down until the nsRootAccessible owning it is shut down
-  // Each nsDocAccessible, including the nsRootAccessible, is responsible for clearing the
+  // The caret accessible isn't shut down until the RootAccessible owning it is shut down
+  // Each nsDocAccessible, including the RootAccessible, is responsible for clearing the
   // doc selection listeners they registered in this nsCaretAccessible
 
   ClearControlSelectionListener(); // Clear the selection listener for the currently focused control
   mLastTextAccessible = nsnull;
   mLastUsedSelection = nsnull;
   mRootAccessible = nsnull;
 }
 
--- a/accessible/src/base/nsCaretAccessible.h
+++ b/accessible/src/base/nsCaretAccessible.h
@@ -38,46 +38,44 @@
 #ifndef __nsCaretAccessible_h__
 #define __nsCaretAccessible_h__
 
 #include "NotificationController.h"
 #include "nsHyperTextAccessible.h"
 
 #include "nsISelectionListener.h"
 
-class nsRootAccessible;
-
 /*
  * This special accessibility class is for the caret, which is really the currently focused selection.
- * There is only 1 visible caret per top level window (nsRootAccessible),
+ * There is only 1 visible caret per top level window (RootAccessible),
  * However, there may be several visible selections.
  *
  * The important selections are the one owned by each document, and the one in the currently focused control.
  *
  * The caret accessible is no longer an accessible object in its own right.
  * On Windows it is used to move an invisible system caret that shadows the Mozilla caret. Windows will
  * also automatically map this to the MSAA caret accessible object (via OBJID_CARET).
  * (as opposed to the root accessible tree for a window which is retrieved with OBJID_CLIENT)
  * For ATK and Iaccessible2, the caret accessible is used to fire
  * caret move and selection change events.
  *
- * The caret accessible is owned by the nsRootAccessible for the top level window that it's in.
- * The nsRootAccessible needs to tell the nsCaretAccessible about focus changes via
+ * The caret accessible is owned by the RootAccessible for the top level window that it's in.
+ * The RootAccessible needs to tell the nsCaretAccessible about focus changes via
  * setControlSelectionListener().
  * Each nsDocAccessible needs to tell the nsCaretAccessible owned by the root to
  * listen for selection events via addDocSelectionListener() and then needs to remove the 
  * selection listener when the doc goes away via removeDocSelectionListener().
  */
 
 class nsCaretAccessible : public nsISelectionListener
 {
 public:
   NS_DECL_ISUPPORTS
 
-  nsCaretAccessible(nsRootAccessible *aRootAccessible);
+  nsCaretAccessible(mozilla::a11y::RootAccessible* aRootAccessible);
   virtual ~nsCaretAccessible();
   void Shutdown();
 
   /* ----- nsISelectionListener ---- */
   NS_DECL_NSISELECTIONLISTENER
 
   /**
    * Listen to selection events on the focused control.
@@ -150,12 +148,12 @@ private:
 
   // Info for the the last selection event.
   // If it was on a control, then its control's selection. Otherwise, it's for
   // a document where the selection changed.
   nsCOMPtr<nsIWeakReference> mLastUsedSelection; // Weak ref to nsISelection
   nsRefPtr<nsHyperTextAccessible> mLastTextAccessible;
   PRInt32 mLastCaretOffset;
 
-  nsRootAccessible *mRootAccessible;
+  mozilla::a11y::RootAccessible* mRootAccessible;
 };
 
 #endif
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -38,19 +38,19 @@
 
 #include "Accessible-inl.h"
 #include "AccIterator.h"
 #include "nsAccCache.h"
 #include "nsAccessibilityService.h"
 #include "nsAccessiblePivot.h"
 #include "nsAccTreeWalker.h"
 #include "nsAccUtils.h"
-#include "nsRootAccessible.h"
 #include "nsTextEquivUtils.h"
 #include "Role.h"
+#include "RootAccessible.h"
 #include "States.h"
 
 #include "nsIMutableArray.h"
 #include "nsICommandManager.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocument.h"
 #include "nsIDOMAttr.h"
@@ -759,17 +759,17 @@ nsresult nsDocAccessible::AddEventListen
     if (commandManager) {
       commandManager->AddCommandObserver(this, "obs_documentCreated");
     }
   }
 
   nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
   docShellTreeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
   if (rootTreeItem) {
-    nsRootAccessible* rootAccessible = RootAccessible();
+    a11y::RootAccessible* rootAccessible = RootAccessible();
     NS_ENSURE_TRUE(rootAccessible, NS_ERROR_FAILURE);
     nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible();
     if (caretAccessible) {
       caretAccessible->AddDocSelectionListener(mPresShell);
     }
   }
 
   // add document observer
@@ -806,17 +806,17 @@ nsresult nsDocAccessible::RemoveEventLis
   }
 
   if (mScrollWatchTimer) {
     mScrollWatchTimer->Cancel();
     mScrollWatchTimer = nsnull;
     NS_RELEASE_THIS(); // Kung fu death grip
   }
 
-  nsRootAccessible* rootAccessible = RootAccessible();
+  a11y::RootAccessible* rootAccessible = RootAccessible();
   if (rootAccessible) {
     nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible();
     if (caretAccessible)
       caretAccessible->RemoveDocSelectionListener(mPresShell);
   }
 
   return NS_OK;
 }
@@ -1762,21 +1762,16 @@ void
 nsDocAccessible::ProcessPendingEvent(AccEvent* aEvent)
 {
   PRUint32 eventType = aEvent->GetEventType();
   if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED) {
     nsHyperTextAccessible* hyperText = aEvent->GetAccessible()->AsHyperText();
     PRInt32 caretOffset;
     if (hyperText &&
         NS_SUCCEEDED(hyperText->GetCaretOffset(&caretOffset))) {
-#ifdef DEBUG_A11Y
-      PRUnichar chAtOffset;
-      hyperText->GetCharacterAtOffset(caretOffset, &chAtOffset);
-      printf("\nCaret moved to %d with char %c", caretOffset, chAtOffset);
-#endif
       nsRefPtr<AccEvent> caretMoveEvent =
         new AccCaretMoveEvent(hyperText, caretOffset);
       nsEventShell::FireEvent(caretMoveEvent);
 
       PRInt32 selectionCount;
       hyperText->GetSelectionCount(&selectionCount);
       if (selectionCount) {  // There's a selection so fire selection change as well
         nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED,
--- a/accessible/src/generic/Makefile.in
+++ b/accessible/src/generic/Makefile.in
@@ -14,21 +14,24 @@ LIBRARY_NAME = accessibility_generic_s
 LIBXUL_LIBRARY = 1
 
 
 CPPSRCS = \
   ApplicationAccessible.cpp \
   ARIAGridAccessible.cpp \
   FormControlAccessible.cpp \
   OuterDocAccessible.cpp \
+  RootAccessible.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
 
 LOCAL_INCLUDES = \
   -I$(srcdir)/../xpcom \
   -I$(srcdir)/../base \
+  -I$(srcdir)/../html \
+  -I$(srcdir)/../xul \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/xul/base/src \
   $(NULL)
rename from accessible/src/base/nsRootAccessible.cpp
rename to accessible/src/generic/RootAccessible.cpp
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/generic/RootAccessible.cpp
@@ -30,16 +30,18 @@
  * 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 "RootAccessible.h"
+
 #include "mozilla/Util.h"
 
 #define CreateEvent CreateEventA
 #include "nsIDOMDocument.h"
 
 #include "Accessible-inl.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
@@ -71,70 +73,70 @@
 #include "nsIFrame.h"
 #include "nsIHTMLDocument.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsISelectionPrivate.h"
 #include "nsIServiceManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsReadableUtils.h"
-#include "nsRootAccessible.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsFocusManager.h"
 
 #ifdef MOZ_XUL
 #include "nsXULTreeAccessible.h"
 #include "nsIXULDocument.h"
 #include "nsIXULWindow.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_ISUPPORTS_INHERITED1(nsRootAccessible, nsDocAccessible, nsIAccessibleDocument)
+NS_IMPL_ISUPPORTS_INHERITED1(RootAccessible, nsDocAccessible, nsIAccessibleDocument)
 
 ////////////////////////////////////////////////////////////////////////////////
-// Constructor/desctructor
+// Constructor/destructor
 
-nsRootAccessible::
-  nsRootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
-                   nsIPresShell* aPresShell) :
+RootAccessible::
+  RootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
+                 nsIPresShell* aPresShell) :
   nsDocAccessibleWrap(aDocument, aRootContent, aPresShell)
 {
   mFlags |= eRootAccessible;
 }
 
-nsRootAccessible::~nsRootAccessible()
+RootAccessible::~RootAccessible()
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible
 
 ENameValueFlag
-nsRootAccessible::Name(nsString& aName)
+RootAccessible::Name(nsString& aName)
 {
   aName.Truncate();
 
   if (mRoleMapEntry) {
     nsAccessible::Name(aName);
     if (!aName.IsEmpty())
       return eNameOK;
   }
 
   nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(mDocument);
+  NS_ENSURE_TRUE(document, eNameOK);
   document->GetTitle(aName);
   return eNameOK;
 }
 
 role
-nsRootAccessible::NativeRole()
+RootAccessible::NativeRole()
 {
   // If it's a <dialog> or <wizard>, use roles::DIALOG instead
   dom::Element *root = mDocument->GetRootElement();
   if (root) {
     nsCOMPtr<nsIDOMElement> rootElement(do_QueryInterface(root));
     if (rootElement) {
       nsAutoString name;
       rootElement->GetLocalName(name);
@@ -142,19 +144,20 @@ nsRootAccessible::NativeRole()
         return roles::DIALOG; // Always at the root
       }
     }
   }
 
   return nsDocAccessibleWrap::NativeRole();
 }
 
-// nsRootAccessible protected member
+// RootAccessible protected member
 #ifdef MOZ_XUL
-PRUint32 nsRootAccessible::GetChromeFlags()
+PRUint32
+RootAccessible::GetChromeFlags()
 {
   // Return the flag set for the top level window as defined 
   // by nsIWebBrowserChrome::CHROME_WINDOW_[FLAGNAME]
   // Not simple: nsIXULWindow is not just a QI from nsIDOMWindow
   nsCOMPtr<nsIDocShellTreeItem> treeItem =
     nsCoreUtils::GetDocShellTreeItemFor(mDocument);
   NS_ENSURE_TRUE(treeItem, 0);
   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
@@ -166,17 +169,17 @@ PRUint32 nsRootAccessible::GetChromeFlag
   }
   PRUint32 chromeFlags;
   xulWin->GetChromeFlags(&chromeFlags);
   return chromeFlags;
 }
 #endif
 
 PRUint64
-nsRootAccessible::NativeState()
+RootAccessible::NativeState()
 {
   PRUint64 states = nsDocAccessibleWrap::NativeState();
 
 #ifdef MOZ_XUL
   PRUint32 chromeFlags = GetChromeFlags();
   if (chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE)
     states |= states::SIZEABLE;
     // If it has a titlebar it's movable
@@ -226,17 +229,18 @@ const char* const docEvents[] = {
   "popuphiding",
   "DOMMenuInactive",
   "DOMMenuItemActive",
   "DOMMenuItemInactive",
   "DOMMenuBarActive",
   "DOMMenuBarInactive"
 };
 
-nsresult nsRootAccessible::AddEventListeners()
+nsresult
+RootAccessible::AddEventListeners()
 {
   // nsIDOMEventTarget interface allows to register event listeners to
   // receive untrusted events (synthetic events generated by untrusted code).
   // For example, XBL bindings implementations for elements that are hosted in
   // non chrome document fire untrusted events.
   nsCOMPtr<nsIDOMEventTarget> nstarget(do_QueryInterface(mDocument));
 
   if (nstarget) {
@@ -251,17 +255,18 @@ nsresult nsRootAccessible::AddEventListe
 
   if (!mCaretAccessible) {
     mCaretAccessible = new nsCaretAccessible(this);
   }
 
   return nsDocAccessible::AddEventListeners();
 }
 
-nsresult nsRootAccessible::RemoveEventListeners()
+nsresult
+RootAccessible::RemoveEventListeners()
 {
   nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDocument));
   if (target) { 
     for (const char* const* e = docEvents,
                    * const* e_end = ArrayEnd(docEvents);
          e < e_end; ++e) {
       nsresult rv = target->RemoveEventListener(NS_ConvertASCIItoUTF16(*e), this, true);
       NS_ENSURE_SUCCESS(rv, rv);
@@ -279,31 +284,31 @@ nsresult nsRootAccessible::RemoveEventLi
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // public
 
 nsCaretAccessible*
-nsRootAccessible::GetCaretAccessible()
+RootAccessible::GetCaretAccessible()
 {
   return mCaretAccessible;
 }
 
 void
-nsRootAccessible::DocumentActivated(nsDocAccessible* aDocument)
+RootAccessible::DocumentActivated(nsDocAccessible* aDocument)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIDOMEventListener
 
 NS_IMETHODIMP
-nsRootAccessible::HandleEvent(nsIDOMEvent* aDOMEvent)
+RootAccessible::HandleEvent(nsIDOMEvent* aDOMEvent)
 {
   nsCOMPtr<nsIDOMNSEvent> DOMNSEvent(do_QueryInterface(aDOMEvent));
   nsCOMPtr<nsIDOMEventTarget> DOMEventTarget;
   DOMNSEvent->GetOriginalTarget(getter_AddRefs(DOMEventTarget));
   nsCOMPtr<nsINode> origTargetNode(do_QueryInterface(DOMEventTarget));
   if (!origTargetNode)
     return NS_OK;
 
@@ -330,26 +335,26 @@ nsRootAccessible::HandleEvent(nsIDOMEven
              NS_ConvertUTF16toUTF8(tag).get(), id.get(),
              NS_ConvertUTF16toUTF8(eventType).get());
     }
 #endif
 
     // Root accessible exists longer than any of its descendant documents so
     // that we are guaranteed notification is processed before root accessible
     // is destroyed.
-    document->HandleNotification<nsRootAccessible, nsIDOMEvent>
-      (this, &nsRootAccessible::ProcessDOMEvent, aDOMEvent);
+    document->HandleNotification<RootAccessible, nsIDOMEvent>
+      (this, &RootAccessible::ProcessDOMEvent, aDOMEvent);
   }
 
   return NS_OK;
 }
 
-// nsRootAccessible protected
+// RootAccessible protected
 void
-nsRootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
+RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
 {
   nsCOMPtr<nsIDOMNSEvent> DOMNSEvent(do_QueryInterface(aDOMEvent));
   nsCOMPtr<nsIDOMEventTarget> DOMEventTarget;
   DOMNSEvent->GetOriginalTarget(getter_AddRefs(DOMEventTarget));
   nsCOMPtr<nsINode> origTargetNode(do_QueryInterface(DOMEventTarget));
 
   nsAutoString eventType;
   aDOMEvent->GetType(eventType);
@@ -529,28 +534,28 @@ nsRootAccessible::ProcessDOMEvent(nsIDOM
 #endif
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNode
 
 void
-nsRootAccessible::Shutdown()
+RootAccessible::Shutdown()
 {
   // Called manually or by nsAccessNode::LastRelease()
   if (!PresShell())
     return;  // Already shutdown
 
   nsDocAccessibleWrap::Shutdown();
 }
 
 // nsIAccessible method
 Relation
-nsRootAccessible::RelationByType(PRUint32 aType)
+RootAccessible::RelationByType(PRUint32 aType)
 {
   if (!mDocument || aType != nsIAccessibleRelation::RELATION_EMBEDS)
     return nsDocAccessibleWrap::RelationByType(aType);
 
   nsIDOMWindow* rootWindow = mDocument->GetWindow();
   if (rootWindow) {
     nsCOMPtr<nsIDOMWindow> contentWindow;
     rootWindow->GetContent(getter_AddRefs(contentWindow));
@@ -570,17 +575,17 @@ nsRootAccessible::RelationByType(PRUint3
 
   return Relation();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Protected members
 
 void
-nsRootAccessible::HandlePopupShownEvent(nsAccessible* aAccessible)
+RootAccessible::HandlePopupShownEvent(nsAccessible* aAccessible)
 {
   roles::Role role = aAccessible->Role();
 
   if (role == roles::MENUPOPUP) {
     // Don't fire menupopup events for combobox and autocomplete lists.
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
                             aAccessible);
     return;
@@ -608,17 +613,17 @@ nsRootAccessible::HandlePopupShownEvent(
         new AccStateChangeEvent(combobox, states::EXPANDED, true);
       if (event)
         nsEventShell::FireEvent(event);
     }
   }
 }
 
 void
-nsRootAccessible::HandlePopupHidingEvent(nsINode* aPopupNode)
+RootAccessible::HandlePopupHidingEvent(nsINode* aPopupNode)
 {
   // Get popup accessible. There are cases when popup element isn't accessible
   // but an underlying widget is and behaves like popup, an example is
   // autocomplete popups.
   nsDocAccessible* document = nsAccUtils::GetDocAccessibleFor(aPopupNode);
   if (!document)
     return;
 
@@ -713,18 +718,18 @@ nsRootAccessible::HandlePopupHidingEvent
     nsRefPtr<AccEvent> event =
       new AccStateChangeEvent(widget, states::EXPANDED, false);
     document->FireDelayedAccessibleEvent(event);
   }
 }
 
 #ifdef MOZ_XUL
 void
-nsRootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
-                                                 nsXULTreeAccessible* aAccessible)
+RootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
+                                               nsXULTreeAccessible* aAccessible)
 {
   nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));
   if (!dataEvent)
     return;
 
   nsCOMPtr<nsIVariant> indexVariant;
   dataEvent->GetData(NS_LITERAL_STRING("index"),
                      getter_AddRefs(indexVariant));
@@ -740,18 +745,18 @@ nsRootAccessible::HandleTreeRowCountChan
   PRInt32 index, count;
   indexVariant->GetAsInt32(&index);
   countVariant->GetAsInt32(&count);
 
   aAccessible->InvalidateCache(index, count);
 }
 
 void
-nsRootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
-                                             nsXULTreeAccessible* aAccessible)
+RootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
+                                           nsXULTreeAccessible* aAccessible)
 {
   nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));
   if (!dataEvent)
     return;
 
   PRInt32 startRow = 0, endRow = -1, startCol = 0, endCol = -1;
 
   nsCOMPtr<nsIVariant> startRowVariant;
rename from accessible/src/base/nsRootAccessible.h
rename to accessible/src/generic/RootAccessible.h
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/generic/RootAccessible.h
@@ -30,56 +30,57 @@
  * 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 ***** */
 
-#ifndef _nsRootAccessible_H_
-#define _nsRootAccessible_H_
+#ifndef mozilla_a11y_RootAccessible_h__
+#define mozilla_a11y_RootAccessible_h__
 
 #include "nsCaretAccessible.h"
 #include "nsDocAccessibleWrap.h"
 
 
 #include "nsHashtable.h"
 #include "nsCaretAccessible.h"
 #include "nsIDocument.h"
 #include "nsIDOMEventListener.h"
 
 class nsXULTreeAccessible;
 class Relation;
 
-const PRInt32 SCROLL_HASH_START_SIZE = 6;
+namespace mozilla {
+namespace a11y {
 
-class nsRootAccessible : public nsDocAccessibleWrap,
-                         public nsIDOMEventListener
+class RootAccessible : public nsDocAccessibleWrap,
+                       public nsIDOMEventListener
 {
   NS_DECL_ISUPPORTS_INHERITED
 
 public:
-  nsRootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
-                   nsIPresShell* aPresShell);
-  virtual ~nsRootAccessible();
+  RootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
+                 nsIPresShell* aPresShell);
+  virtual ~RootAccessible();
 
   // nsIDOMEventListener
   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
 
   // nsAccessNode
   virtual void Shutdown();
 
   // nsAccessible
   virtual mozilla::a11y::ENameValueFlag Name(nsString& aName);
   virtual Relation RelationByType(PRUint32 aType);
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
 
-  // nsRootAccessible
+  // RootAccessible
   nsCaretAccessible* GetCaretAccessible();
 
   /**
    * Notify that the sub document presshell was activated.
    */
   virtual void DocumentActivated(nsDocAccessible* aDocument);
 
 protected:
@@ -112,16 +113,19 @@ protected:
                                     nsXULTreeAccessible* aAccessible);
 
     PRUint32 GetChromeFlags();
 #endif
 
     nsRefPtr<nsCaretAccessible> mCaretAccessible;
 };
 
-inline nsRootAccessible*
+} // namespace a11y
+} // namespace mozilla
+
+inline mozilla::a11y::RootAccessible*
 nsAccessible::AsRoot()
 {
   return mFlags & eRootAccessible ?
-    static_cast<nsRootAccessible*>(this) : nsnull;
+    static_cast<mozilla::a11y::RootAccessible*>(this) : nsnull;
 }
 
 #endif
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -1292,20 +1292,18 @@ nsHTMLTableAccessible::Description(nsStr
     }
   }
 
 #ifdef SHOW_LAYOUT_HEURISTIC
   if (aDescription.IsEmpty()) {
     bool isProbablyForLayout = IsProbablyLayoutTable();
     aDescription = mLayoutHeuristic;
   }
-#ifdef DEBUG_A11Y
   printf("\nTABLE: %s\n", NS_ConvertUTF16toUTF8(mLayoutHeuristic).get());
 #endif
-#endif
 }
 
 bool
 nsHTMLTableAccessible::HasDescendant(const nsAString& aTagName,
                                      bool aAllowEmpty)
 {
   nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mContent));
   NS_ENSURE_TRUE(tableElt, false);
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -11,47 +11,49 @@ const Cr = Components.results;
 
 var EXPORTED_SYMBOLS = ['AccessFu'];
 
 Cu.import('resource://gre/modules/Services.jsm');
 
 Cu.import('resource://gre/modules/accessibility/Presenters.jsm');
 Cu.import('resource://gre/modules/accessibility/VirtualCursorController.jsm');
 
+const ACCESSFU_DISABLE = 0;
+const ACCESSFU_ENABLE = 1;
+const ACCESSFU_AUTO = 2;
+
 var AccessFu = {
   /**
    * Attach chrome-layer accessibility functionality to the given chrome window.
    * If accessibility is enabled on the platform (currently Android-only), then
    * a special accessibility mode is started (see startup()).
    * @param {ChromeWindow} aWindow Chrome window to attach to.
    * @param {boolean} aForceEnabled Skip platform accessibility check and enable
    *  AccessFu.
    */
   attach: function attach(aWindow) {
+    if (this.chromeWin)
+      // XXX: only supports attaching to one window now.
+      throw new Error('Only one window could be attached to AccessFu');
+
     dump('AccessFu attach!! ' + Services.appinfo.OS + '\n');
     this.chromeWin = aWindow;
     this.presenters = [];
 
-    function checkA11y() {
-      if (Services.appinfo.OS == 'Android') {
-        let msg = Cc['@mozilla.org/android/bridge;1'].
-          getService(Ci.nsIAndroidBridge).handleGeckoMessage(
-            JSON.stringify(
-                { gecko: {
-                    type: 'Accessibility:IsEnabled',
-                    eventType: 1,
-                    text: []
-                  }
-                }));
-        return JSON.parse(msg).enabled;
-      }
-      return false;
+    this.prefsBranch = Cc['@mozilla.org/preferences-service;1']
+      .getService(Ci.nsIPrefService).getBranch('accessibility.');
+    this.prefsBranch.addObserver('accessfu', this, false);
+
+    let accessPref = ACCESSFU_DISABLE;
+    try {
+      accessPref = this.prefsBranch.getIntPref('accessfu');
+    } catch (x) {
     }
 
-    if (checkA11y())
+    if (this.amINeeded(accessPref))
       this.enable();
   },
 
   /**
    * Start the special AccessFu mode, this primarily means controlling the virtual
    * cursor with arrow keys. Currently, on platforms other than Android this needs
    * to be called explicitly.
    */
@@ -89,16 +91,38 @@ var AccessFu = {
     this.chromeWin.removeEventListener('DOMActivate', this);
     this.chromeWin.removeEventListener('resize', this);
     this.chromeWin.removeEventListener('scroll', this);
     this.chromeWin.removeEventListener('TabOpen', this);
     this.chromeWin.removeEventListener('TabSelect', this);
     this.chromeWin.removeEventListener('TabClose', this);
   },
 
+  amINeeded: function(aPref) {
+    switch (aPref) {
+      case ACCESSFU_ENABLE:
+        return true;
+      case ACCESSFU_AUTO:
+        if (Services.appinfo.OS == 'Android') {
+          let msg = Cc['@mozilla.org/android/bridge;1'].
+            getService(Ci.nsIAndroidBridge).handleGeckoMessage(
+              JSON.stringify(
+                { gecko: {
+                    type: 'Accessibility:IsEnabled',
+                    eventType: 1,
+                    text: []
+                  }
+                }));
+          return JSON.parse(msg).enabled;
+        }
+      default:
+        return false;
+    }
+  },
+
   addPresenter: function addPresenter(presenter) {
     this.presenters.push(presenter);
     presenter.attach(this.chromeWin);
   },
 
   handleEvent: function handleEvent(aEvent) {
     switch (aEvent.type) {
       case 'TabSelect':
@@ -145,16 +169,24 @@ var AccessFu = {
       this._pendingDocuments[browserApp.selectedBrowser] = aCallback;
     } else {
       aCallback.apply(this, [docAcc]);
     }
   },
 
   observe: function observe(aSubject, aTopic, aData) {
     switch (aTopic) {
+      case 'nsPref:changed':
+        if (aData == 'accessfu') {
+          if (this.amINeeded(this.prefsBranch.getIntPref('accessfu')))
+            this.enable();
+          else
+            this.disable();
+        }
+        break;
       case 'accessible-event':
         let event;
         try {
           event = aSubject.QueryInterface(Ci.nsIAccessibleEvent);
           this.handleAccEvent(event);
         } catch (ex) {
           dump(ex);
           return;
@@ -199,16 +231,44 @@ var AccessFu = {
           let callback = this._pendingDocuments[node];
           if (callback && aEvent.accessible.childCount) {
             // We have a callback associated with a document.
             callback.apply(this, [aEvent.accessible.getChildAt(0)]);
             delete this._pendingDocuments[node];
           }
           break;
         }
+      case Ci.nsIAccessibleEvent.EVENT_TEXT_INSERTED:
+      case Ci.nsIAccessibleEvent.EVENT_TEXT_REMOVED:
+      {
+        if (aEvent.isFromUserInput) {
+          // XXX support live regions as well.
+          let event = aEvent.QueryInterface(Ci.nsIAccessibleTextChangeEvent);
+          let isInserted = event.isInserted();
+          let textIface = aEvent.accessible.QueryInterface(Ci.nsIAccessibleText);
+
+          let text = '';
+          try {
+            text = textIface.
+              getText(0, Ci.nsIAccessibleText.TEXT_OFFSET_END_OF_TEXT);
+          } catch (x) {
+            // XXX we might have gotten an exception with of a
+            // zero-length text. If we did, ignore it (bug #749810).
+            if (textIface.characterCount)
+              throw x;
+          }
+
+          this.presenters.forEach(
+            function(p) {
+              p.textChanged(isInserted, event.start, event.length, text, event.modifiedText);
+            }
+          );
+        }
+        break;
+      }
       default:
         break;
     }
   },
 
   getNewContext: function getNewContext(aOldObject, aNewObject) {
     let newLineage = [];
     let oldLineage = [];
--- a/accessible/src/jsat/Presenters.jsm
+++ b/accessible/src/jsat/Presenters.jsm
@@ -47,17 +47,17 @@ Presenter.prototype = {
    * @param {nsIAccessible} aObject the object that has been invoked.
    * @param {string} aActionName the name of the action.
    */
   actionInvoked: function actionInvoked(aObject, aActionName) {},
 
   /**
    * Text has changed, either by the user or by the system. TODO.
    */
-  textChanged: function textChanged() {},
+  textChanged: function textChanged(aIsInserted, aStartOffset, aLength, aText, aModifiedText) {},
 
   /**
    * Text selection has changed. TODO.
    */
   textSelectionChanged: function textSelectionChanged() {},
 
   /**
    * Selection has changed. TODO.
@@ -249,16 +249,37 @@ AndroidPresenter.prototype.tabSelected =
   let parent = vcDoc.virtualCursor.position || aObject;
   while ((parent = parent.parent))
     context.push(parent);
   context.reverse();
 
   this.pivotChanged(vcDoc.virtualCursor.position || aObject, context);
 };
 
+AndroidPresenter.prototype.textChanged = function(aIsInserted, aStart, aLength, aText, aModifiedText) {
+  let androidEvent = {
+    type: 'Accessibility:Event',
+    eventType: ANDROID_TYPE_VIEW_TEXT_CHANGED,
+    text: [aText],
+    fromIndex: aStart
+  };
+
+  if (aIsInserted) {
+    androidEvent.addedCount = aLength;
+    androidEvent.beforeText =
+      aText.substring(0, aStart) + aText.substring(aStart + aLength);
+  } else {
+    androidEvent.removedCount = aLength;
+    androidEvent.beforeText =
+      aText.substring(0, aStart) + aModifiedText + aText.substring(aStart);
+  }
+
+  this.sendMessageToJava({gecko: androidEvent});
+};
+
 AndroidPresenter.prototype.sendMessageToJava = function(aMessage) {
   return Cc['@mozilla.org/android/bridge;1'].
     getService(Ci.nsIAndroidBridge).
     handleGeckoMessage(JSON.stringify(aMessage));
 };
 
 /**
  * A dummy Android presenter for desktop testing
--- a/accessible/src/jsat/UtteranceGenerator.jsm
+++ b/accessible/src/jsat/UtteranceGenerator.jsm
@@ -45,17 +45,17 @@ var UtteranceGenerator = {
     let func = this.objectUtteranceFunctions[roleString] ||
       this.objectUtteranceFunctions.defaultFunc;
 
     let flags = this.verbosityRoleMap[roleString] || 0;
 
     if (aForceName)
       flags |= INCLUDE_NAME;
 
-    return func(aAccessible, roleString, flags);
+    return func.apply(this, [aAccessible, roleString, flags]);
   },
 
   genForAction: function(aObject, aActionName) {
     return [gStringBundle.GetStringFromName(this.gActionMap[aActionName])];
   },
 
   verbosityRoleMap: {
     'menubar': INCLUDE_ROLE,
@@ -108,18 +108,17 @@ var UtteranceGenerator = {
     'combobox option': INCLUDE_ROLE,
     'image map': INCLUDE_ROLE,
     'option': INCLUDE_ROLE,
     'listbox': INCLUDE_ROLE},
 
   objectUtteranceFunctions: {
     defaultFunc: function defaultFunc(aAccessible, aRoleStr, aFlags) {
       let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
-      let desc = (aFlags & INCLUDE_ROLE) ?
-        gStringBundle.GetStringFromName(aRoleStr) : '';
+      let desc = (aFlags & INCLUDE_ROLE) ? this._getLocalizedRole(aRoleStr) : '';
 
       if (!name && !desc)
         return [];
 
       let state = {};
       let extState = {};
       aAccessible.getState(state, extState);
 
@@ -144,19 +143,27 @@ var UtteranceGenerator = {
       aAccessible.groupPosition(level, {}, {});
       let desc = gStringBundle.formatStringFromName('headingLevel',
                                                    [level.value], 1);
       return [desc, name];
     },
 
     listitem: function(aAccessible, aRoleStr, aFlags) {
       let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
-      let localizedRole = gStringBundle.GetStringFromName(aRoleStr);
+      let localizedRole = this._getLocalizedRole(aRoleStr);
       let itemno = {};
       let itemof = {};
       aAccessible.groupPosition({}, itemof, itemno);
       let desc = gStringBundle.formatStringFromName(
           'objItemOf', [localizedRole, itemno.value, itemof.value], 3);
 
       return [desc, name];
     }
+  },
+
+  _getLocalizedRole: function _getLocalizedRole(aRoleStr) {
+    try {
+      return gStringBundle.GetStringFromName(aRoleStr.replace(' ', ''));
+    } catch (x) {
+      return '';
+    }
   }
 };
--- a/accessible/src/jsat/VirtualCursorController.jsm
+++ b/accessible/src/jsat/VirtualCursorController.jsm
@@ -117,27 +117,35 @@ var VirtualCursorController = {
       aRules.value = [];
       return 0;
     },
 
     preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
       Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
 
     match: function(aAccessible) {
-      let rv = Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
-      if (aAccessible.childCount == 0) {
-        // TODO: Find a better solution for ROLE_STATICTEXT.
-        // Right now it helps filter list bullets, but it is also used
-        // in CSS generated content.
-        let ignoreRoles = [Ci.nsIAccessibleRole.ROLE_WHITESPACE,
-                           Ci.nsIAccessibleRole.ROLE_STATICTEXT];
-        let state = {};
-        aAccessible.getState(state, {});
-        if ((state.value & Ci.nsIAccessibleStates.STATE_FOCUSABLE) ||
-          (aAccessible.name && ignoreRoles.indexOf(aAccessible.role) < 0))
-          rv = Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
-        }
-      return rv;
+      if (aAccessible.childCount)
+        // Non-leafs do not interest us.
+        return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
+
+      // XXX: Find a better solution for ROLE_STATICTEXT.
+      // It allows to filter list bullets but the same time it
+      // filters CSS generated content too as unwanted side effect.
+      let ignoreRoles = [Ci.nsIAccessibleRole.ROLE_WHITESPACE,
+                         Ci.nsIAccessibleRole.ROLE_STATICTEXT];
+
+      if (ignoreRoles.indexOf(aAccessible.role) < 0) {
+        let name = aAccessible.name;
+        if (name && name.trim())
+          return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+      }
+
+      let state = {};
+      aAccessible.getState(state, {});
+      if (state.value & Ci.nsIAccessibleStates.STATE_FOCUSABLE)
+        return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+
+      return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
     },
 
     QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
   }
 };
--- a/accessible/src/mac/Makefile.in
+++ b/accessible/src/mac/Makefile.in
@@ -45,34 +45,33 @@ MODULE = accessibility
 LIBRARY_NAME = accessibility_toolkit_s
 EXPORT_LIBRARY = ..
 LIBXUL_LIBRARY = 1
 
   
   
 CMMSRCS = nsAccessNodeWrap.mm \
           nsDocAccessibleWrap.mm \
-          nsRootAccessibleWrap.mm \
           nsAccessibleWrap.mm \
           mozAccessible.mm \
           mozDocAccessible.mm \
           mozActionElements.mm \
           mozTextAccessible.mm \
           mozHTMLAccessible.mm \
           MacUtils.mm \
+          RootAccessibleWrap.mm \
           $(NULL)
 
 
 EXPORTS = \
   ARIAGridAccessibleWrap.h \
   nsAccessNodeWrap.h \
   nsTextAccessibleWrap.h \
   nsAccessibleWrap.h \
   nsDocAccessibleWrap.h \
-  nsRootAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULListboxAccessibleWrap.h \
   nsXULTreeGridAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
   mozDocAccessible.h \
   mozAccessible.h \
rename from accessible/src/mac/nsRootAccessibleWrap.h
rename to accessible/src/mac/RootAccessibleWrap.h
--- a/accessible/src/mac/nsRootAccessibleWrap.h
+++ b/accessible/src/mac/RootAccessibleWrap.h
@@ -35,31 +35,36 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
-#ifndef _nsRootAccessibleWrap_H_
-#define _nsRootAccessibleWrap_H_
+#ifndef mozilla_a11y_RootAccessibleWrap_h__
+#define mozilla_a11y_RootAccessibleWrap_h__
 
-#include "nsRootAccessible.h"
+#include "RootAccessible.h"
+
+namespace mozilla {
+namespace a11y {
 
 struct objc_class;
 
-class nsRootAccessibleWrap : public nsRootAccessible
+class RootAccessibleWrap : public RootAccessible
 {
 public:
-  nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
-                       nsIPresShell* aPresShell);
-  virtual ~nsRootAccessibleWrap();
+  RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
+                     nsIPresShell* aPresShell);
+  virtual ~RootAccessibleWrap();
 
     Class GetNativeType ();
     
     // let's our native accessible get in touch with the
     // native cocoa view that is our accessible parent.
     void GetNativeWidget (void **aOutView);
 };
 
+} // namespace a11y
+} // namespace mozilla
 
 #endif
rename from accessible/src/mac/nsRootAccessibleWrap.mm
rename to accessible/src/mac/RootAccessibleWrap.mm
--- a/accessible/src/mac/nsRootAccessibleWrap.mm
+++ b/accessible/src/mac/RootAccessibleWrap.mm
@@ -31,48 +31,50 @@
  * 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 "nsRootAccessibleWrap.h"
+#include "RootAccessibleWrap.h"
 
 #include "mozDocAccessible.h"
 
 #include "nsCOMPtr.h"
 #include "nsObjCExceptions.h"
 #include "nsIWidget.h"
 #include "nsIViewManager.h"
 
-nsRootAccessibleWrap::
-  nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
-                       nsIPresShell* aPresShell) :
-  nsRootAccessible(aDocument, aRootContent, aPresShell)
+using namespace mozilla::a11y;
+
+RootAccessibleWrap::
+  RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
+                     nsIPresShell* aPresShell) :
+  RootAccessible(aDocument, aRootContent, aPresShell)
 {
 }
 
-nsRootAccessibleWrap::~nsRootAccessibleWrap()
+RootAccessibleWrap::~RootAccessibleWrap()
 {
 }
 
 Class
-nsRootAccessibleWrap::GetNativeType ()
+RootAccessibleWrap::GetNativeType()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
   return [mozRootAccessible class];
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 void
-nsRootAccessibleWrap::GetNativeWidget (void **aOutView)
+RootAccessibleWrap::GetNativeWidget(void** aOutView)
 {
   nsIFrame *frame = GetFrame();
   if (frame) {
     nsIView *view = frame->GetViewExternal();
     if (view) {
       nsIWidget *widget = view->GetWidget();
       if (widget) {
         *aOutView = (void**)widget->GetNativeData (NS_NATIVE_WIDGET);
--- a/accessible/src/mac/mozAccessible.mm
+++ b/accessible/src/mac/mozAccessible.mm
@@ -40,19 +40,19 @@
 
 #import "MacUtils.h"
 #import "mozView.h"
 
 #include "Accessible-inl.h"
 #include "nsIAccessibleRelation.h"
 #include "nsIAccessibleText.h"
 #include "nsIAccessibleEditableText.h"
-#include "nsRootAccessible.h"
 #include "Relation.h"
 #include "Role.h"
+#include "RootAccessible.h"
 
 #include "mozilla/Services.h"
 #include "nsRect.h"
 #include "nsCocoaUtils.h"
 #include "nsCoord.h"
 #include "nsObjCExceptions.h"
 
 using namespace mozilla;
@@ -348,17 +348,17 @@ GetNativeFromGeckoAccessible(nsIAccessib
       return GetClosestInterestingAccessible(nativeParent);
   }
   
   // GetUnignoredParent() returns null when there is no unignored accessible all the way up to
   // the root accessible. so we'll have to return whatever native accessible is above our root accessible 
   // (which might be the owning NSWindow in the application, for example).
   //
   // get the native root accessible, and tell it to return its first parent unignored accessible.
-  nsRootAccessible* root = mGeckoAccessible->RootAccessible();
+  RootAccessible* root = mGeckoAccessible->RootAccessible();
   id nativeParent = GetNativeFromGeckoAccessible(static_cast<nsIAccessible*>(root));
   NSAssert1 (nativeParent, @"!!! we can't find a parent for %@", self);
   
   return GetClosestInterestingAccessible(nativeParent);
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
--- a/accessible/src/mac/mozDocAccessible.h
+++ b/accessible/src/mac/mozDocAccessible.h
@@ -39,17 +39,17 @@
 #import <Cocoa/Cocoa.h>
 #import "mozAccessible.h"
 
 // our protocol that we implement (so cocoa widgets can talk to us)
 #import "mozAccessibleProtocol.h"
 
 /* 
   The root accessible. There is one per window.
-  Created by the nsRootAccessibleWrap.
+  Created by the RootAccessibleWrap.
 */
 @interface mozRootAccessible : mozAccessible
 {
   // the mozView that we're representing.
   // all outside communication goes through the mozView.
   // in reality, it's just piping all calls to us, and we're
   // doing its dirty work!
   //
--- a/accessible/src/mac/mozDocAccessible.mm
+++ b/accessible/src/mac/mozDocAccessible.mm
@@ -31,26 +31,30 @@
  * 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 "nsRootAccessibleWrap.h"
 #include "nsObjCExceptions.h"
+#include "RootAccessibleWrap.h"
 
 #import "mozDocAccessible.h"
 
 #import "mozView.h"
 
-static id <mozAccessible, mozView> getNativeViewFromRootAccessible (nsAccessible *accessible)
+using namespace mozilla::a11y;
+
+static id <mozAccessible, mozView> 
+getNativeViewFromRootAccessible(nsAccessible* aAccessible)
 {
-  nsRootAccessibleWrap *root = static_cast<nsRootAccessibleWrap*>(accessible);
+  RootAccessibleWrap* root =
+    static_cast<RootAccessibleWrap*>(aAccessible->AsRoot());
   id <mozAccessible, mozView> nativeView = nil;
   root->GetNativeWidget ((void**)&nativeView);
   return nativeView;
 }
 
 #pragma mark -
 
 @implementation mozRootAccessible
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -50,17 +50,16 @@ LIBXUL_LIBRARY = 1
 CPPSRCS = \
   ApplicationAccessibleWrap.cpp \
   ARIAGridAccessibleWrap.cpp \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
   nsTextAccessibleWrap.cpp \
   nsDocAccessibleWrap.cpp \
   nsHTMLWin32ObjectAccessible.cpp \
-  nsRootAccessibleWrap.cpp \
   nsXULMenuAccessibleWrap.cpp \
   nsXULListboxAccessibleWrap.cpp \
   nsXULTreeGridAccessibleWrap.cpp \
   nsHyperTextAccessibleWrap.cpp \
   nsHTMLImageAccessibleWrap.cpp \
   nsHTMLTableAccessibleWrap.cpp \
   nsWinUtils.cpp \
   ia2AccessibleAction.cpp \
@@ -70,25 +69,25 @@ CPPSRCS = \
   CAccessibleEditableText.cpp \
   CAccessibleHyperlink.cpp \
   ia2AccessibleHypertext.cpp \
   ia2AccessibleRelation.cpp \
   CAccessibleTable.cpp \
   CAccessibleTableCell.cpp \
   CAccessibleValue.cpp \
   Compatibility.cpp \
+  RootAccessibleWrap.cpp \
   $(NULL)
 
 EXPORTS = \
   ARIAGridAccessibleWrap.h \
   nsAccessNodeWrap.h \
   nsAccessibleWrap.h \
   nsTextAccessibleWrap.h \
   nsDocAccessibleWrap.h \
-  nsRootAccessibleWrap.h \
   nsHTMLWin32ObjectAccessible.h \
   nsXULMenuAccessibleWrap.h \
   nsXULListboxAccessibleWrap.h \
   nsXULTreeGridAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
   ia2AccessibleAction.h \
rename from accessible/src/msaa/nsRootAccessibleWrap.cpp
rename to accessible/src/msaa/RootAccessibleWrap.cpp
--- a/accessible/src/msaa/nsRootAccessibleWrap.cpp
+++ b/accessible/src/msaa/RootAccessibleWrap.cpp
@@ -31,45 +31,45 @@
  * 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 "nsRootAccessibleWrap.h"
+#include "RootAccessibleWrap.h"
 
 #include "Compatibility.h"
 #include "nsWinUtils.h"
 
 #include "nsIDOMEventTarget.h"
 #include "nsEventListenerManager.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor/desctructor
 
-nsRootAccessibleWrap::
-  nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
-                       nsIPresShell* aPresShell) :
-  nsRootAccessible(aDocument, aRootContent, aPresShell)
+RootAccessibleWrap::
+  RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
+                     nsIPresShell* aPresShell) :
+  RootAccessible(aDocument, aRootContent, aPresShell)
 {
 }
 
-nsRootAccessibleWrap::~nsRootAccessibleWrap()
+RootAccessibleWrap::~RootAccessibleWrap()
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsRootAccessible
+// RootAccessible
 
 void
-nsRootAccessibleWrap::DocumentActivated(nsDocAccessible* aDocument)
+RootAccessibleWrap::DocumentActivated(nsDocAccessible* aDocument)
 {
   if (Compatibility::IsDolphin() &&
       nsCoreUtils::IsTabDocument(aDocument->GetDocumentNode())) {
     PRUint32 count = mChildDocuments.Length();
     for (PRUint32 idx = 0; idx < count; idx++) {
       nsDocAccessible* childDoc = mChildDocuments[idx];
       HWND childDocHWND = static_cast<HWND>(childDoc->GetNativeWindow());
       if (childDoc != aDocument)
rename from accessible/src/msaa/nsRootAccessibleWrap.h
rename to accessible/src/msaa/RootAccessibleWrap.h
--- a/accessible/src/msaa/nsRootAccessibleWrap.h
+++ b/accessible/src/msaa/RootAccessibleWrap.h
@@ -32,25 +32,31 @@
  * 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 ***** */
 
-#ifndef _nsRootAccessibleWrap_H_
-#define _nsRootAccessibleWrap_H_
+#ifndef mozilla_a11y_RootAccessibleWrap_h__
+#define mozilla_a11y_RootAccessibleWrap_h__
+
+#include "RootAccessible.h"
 
-#include "nsRootAccessible.h"
+namespace mozilla {
+namespace a11y {
 
-class nsRootAccessibleWrap : public nsRootAccessible
+class RootAccessibleWrap : public RootAccessible
 {
 public:
-  nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
-                       nsIPresShell* aPresShell);
-  virtual ~nsRootAccessibleWrap();
+  RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
+                     nsIPresShell* aPresShell);
+  virtual ~RootAccessibleWrap();
 
-  // nsRootAccessible
+  // RootAccessible
   virtual void DocumentActivated(nsDocAccessible* aDocument);
 };
 
+} // namespace a11y
+} // namespace mozilla
+
 #endif
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -40,18 +40,18 @@
 
 #include "AccessibleApplication.h"
 #include "ApplicationAccessibleWrap.h"
 #include "ISimpleDOMNode_i.c"
 
 #include "Compatibility.h"
 #include "nsAccessibilityService.h"
 #include "nsCoreUtils.h"
-#include "nsRootAccessible.h"
 #include "nsWinUtils.h"
+#include "RootAccessible.h"
 #include "Statistics.h"
 
 #include "nsAttrName.h"
 #include "nsIDocument.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIFrame.h"
 #include "nsINameSpaceManager.h"
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -49,51 +49,38 @@
 #include "ia2AccessibleRelation.h"
 
 #include "nsIAccessibleEvent.h"
 #include "nsIAccessibleRelation.h"
 
 #include "Accessible2_i.c"
 #include "AccessibleRole.h"
 #include "AccessibleStates.h"
+#include "RootAccessible.h"
 
 #include "nsIMutableArray.h"
 #include "nsIDOMDocument.h"
 #include "nsIFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsINameSpaceManager.h"
 #include "nsINodeInfo.h"
-#include "nsRootAccessible.h"
 #include "nsIServiceManager.h"
 #include "nsTextFormatter.h"
 #include "nsIView.h"
 #include "nsIViewManager.h"
 #include "nsEventMap.h"
 #include "nsArrayUtils.h"
 
 #include "OLEACC.H"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 const PRUint32 USE_ROLE_STRING = 0;
 
-#ifndef ROLE_SYSTEM_SPLITBUTTON
-const PRUint32 ROLE_SYSTEM_SPLITBUTTON  = 0x3e; // Not defined in all oleacc.h versions
-#endif
-
-#ifndef ROLE_SYSTEM_IPADDRESS
-const PRUint32 ROLE_SYSTEM_IPADDRESS = 0x3f; // Not defined in all oleacc.h versions
-#endif
-
-#ifndef ROLE_SYSTEM_OUTLINEBUTTON
-const PRUint32 ROLE_SYSTEM_OUTLINEBUTTON = 0x40; // Not defined in all oleacc.h versions
-#endif
-
-
 /* For documentation of the accessibility architecture,
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 //#define DEBUG_LEAKS
 
 #ifdef DEBUG_LEAKS
 static gAccessibles = 0;
@@ -1888,17 +1875,17 @@ nsAccessibleWrap::GetXPAccessibleFor(con
 }
 
 void nsAccessibleWrap::UpdateSystemCaret()
 {
   // Move the system caret so that Windows Tablet Edition and tradional ATs with 
   // off-screen model can follow the caret
   ::DestroyCaret();
 
-  nsRootAccessible* rootAccessible = RootAccessible();
+  a11y::RootAccessible* rootAccessible = RootAccessible();
   if (!rootAccessible) {
     return;
   }
 
   nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible();
   if (!caretAccessible) {
     return;
   }
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -37,31 +37,32 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/dom/TabChild.h"
 
 #include "Compatibility.h"
 #include "nsDocAccessibleWrap.h"
 #include "ISimpleDOMDocument_i.c"
 #include "nsIAccessibilityService.h"
-#include "nsRootAccessible.h"
 #include "nsWinUtils.h"
 #include "Role.h"
+#include "RootAccessible.h"
 #include "Statistics.h"
 
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIFrame.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsISelectionController.h"
 #include "nsIServiceManager.h"
 #include "nsIURI.h"
 #include "nsIViewManager.h"
 #include "nsIWebNavigation.h"
 
+using namespace mozilla;
 using namespace mozilla::a11y;
 
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsDocAccessibleWrap
@@ -275,17 +276,17 @@ nsDocAccessibleWrap::DoInitialUpdate()
   nsDocAccessible::DoInitialUpdate();
 
   if (nsWinUtils::IsWindowEmulationStarted()) {
     // Create window for tab document.
     if (nsCoreUtils::IsTabDocument(mDocument)) {
       mozilla::dom::TabChild* tabChild =
         mozilla::dom::GetTabChildFrom(mDocument->GetShell());
 
-      nsRootAccessible* rootDocument = RootAccessible();
+      a11y::RootAccessible* rootDocument = RootAccessible();
 
       mozilla::WindowsHandle nativeData = nsnull;
       if (tabChild)
         tabChild->SendGetWidgetNativeData(&nativeData);
       else
         nativeData = reinterpret_cast<mozilla::WindowsHandle>(
           rootDocument->GetNativeWindow());
 
--- a/accessible/src/msaa/nsWinUtils.cpp
+++ b/accessible/src/msaa/nsWinUtils.cpp
@@ -36,18 +36,18 @@
  * 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 "nsWinUtils.h"
 
 #include "Compatibility.h"
-#include "nsIWinAccessNode.h"
-#include "nsRootAccessible.h"
+#include "nsDocAccessible.h"
+#include "nsCoreUtils.h"
 
 #include "mozilla/Preferences.h"
 #include "nsArrayUtils.h"
 #include "nsIDocShellTreeItem.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
--- a/accessible/src/other/Makefile.in
+++ b/accessible/src/other/Makefile.in
@@ -45,26 +45,24 @@ MODULE = accessibility
 LIBRARY_NAME = accessibility_toolkit_s
 EXPORT_LIBRARY = ..
 LIBXUL_LIBRARY = 1
 
 
 CPPSRCS = \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
-  nsRootAccessibleWrap.cpp \
   $(NULL)
 
 EXPORTS = \
   ARIAGridAccessibleWrap.h \
   nsAccessNodeWrap.h \
   nsTextAccessibleWrap.h \
   nsAccessibleWrap.h \
   nsDocAccessibleWrap.h \
-  nsRootAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULListboxAccessibleWrap.h \
   nsXULTreeGridAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
   $(NULL)
 
rename from accessible/src/other/nsRootAccessibleWrap.h
rename to accessible/src/other/RootAccessibleWrap.h
--- a/accessible/src/other/nsRootAccessibleWrap.h
+++ b/accessible/src/other/RootAccessibleWrap.h
@@ -35,23 +35,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
-#ifndef _nsRootAccessibleWrap_H_
-#define _nsRootAccessibleWrap_H_
+#ifndef mozilla_a11y_RootAccessibleWrap_h__
+#define mozilla_a11y_RootAccessibleWrap_h__
 
-#include "nsRootAccessible.h"
+#include "RootAccessible.h"
 
-class nsRootAccessibleWrap: public nsRootAccessible
-{
-public:
-  nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
-                       nsIPresShell* aPresShell);
-  virtual ~nsRootAccessibleWrap();
-};
+namespace mozilla {
+namespace a11y {
 
+typedef RootAccessible RootAccessibleWrap;
+
+} // namespace a11y
+} // namespace mozilla
 
 #endif
deleted file mode 100644
--- a/accessible/src/other/nsRootAccessibleWrap.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2003
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Original Author: Aaron Leventhal (aaronl@netscape.com)
- *
- * 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 "nsCOMPtr.h"
-#include "nsRootAccessibleWrap.h"
-#include "nsIServiceManager.h"
-#include "nsIAccessibilityService.h"
-
-////////////////////////////////////////////////////////////////////////////////
-// nsRootAccessibleWrap
-////////////////////////////////////////////////////////////////////////////////
-
-nsRootAccessibleWrap::
-  nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
-                       nsIPresShell* aPresShell) :
-  nsRootAccessible(aDocument, aRootContent, aPresShell)
-{
-}
-
-nsRootAccessibleWrap::~nsRootAccessibleWrap()
-{
-}
-
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -196,20 +196,24 @@ clean clobber repackage::
 	$(RM) -r $(dist_dest)
 
 ifdef LIBXUL_SDK
 APPFILES = Resources
 else
 APPFILES = MacOS
 endif
 
-libs repackage:: $(PROGRAM)
-	$(MKDIR) -p $(dist_dest)/Contents/MacOS
+libs-preqs = \
+  $(call mkdir_deps,$(dist_dest)/Contents/MacOS) \
+  $(call mkdir_deps,$(dist_dest)/Contents/Resources/$(AB).lproj) \
+  $(NULL)
+
+.PHONY: repackage
+libs repackage:: $(PROGRAM) $(libs-preqs)
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents $(dist_dest) --exclude English.lproj
-	$(MKDIR) -p $(dist_dest)/Contents/Resources/$(AB).lproj
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/Contents/Resources/$(AB).lproj
 	sed -e "s/%APP_VERSION%/$(MOZ_APP_VERSION)/" -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" -e "s/%LOWER_MAC_APP_NAME%/$(LOWER_MAC_APP_NAME)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
 	sed -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/Contents/Resources/$(AB).lproj/InfoPlist.strings
 	rsync -a $(DIST)/bin/ $(dist_dest)/Contents/$(APPFILES)
 ifdef LIBXUL_SDK
 	cp $(LIBXUL_DIST)/bin/$(XR_STUB_NAME) $(dist_dest)/Contents/MacOS/firefox
 else
 	$(RM) $(dist_dest)/Contents/MacOS/$(PROGRAM)
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1053,19 +1053,24 @@ pref("devtools.inspector.sidebarOpen", f
 pref("devtools.inspector.activeSidebar", "ruleview");
 
 // Enable the Layout View
 pref("devtools.layoutview.enabled", false);
 pref("devtools.layoutview.open", false);
 
 // Enable the Debugger
 pref("devtools.debugger.enabled", false);
+pref("devtools.debugger.remote-enabled", false);
+pref("devtools.debugger.remote-host", "localhost");
+pref("devtools.debugger.remote-port", 6000);
 
 // The default Debugger UI height
 pref("devtools.debugger.ui.height", 250);
+pref("devtools.debugger.ui.remote-win.width", 900);
+pref("devtools.debugger.ui.remote-win.height", 400);
 
 // Enable the style inspector
 pref("devtools.styleinspector.enabled", true);
 
 // Enable the Tilt inspector
 pref("devtools.tilt.enabled", true);
 pref("devtools.tilt.intro_transition", true);
 pref("devtools.tilt.outro_transition", true);
index c6907b2006fa30d7aec833e3cff99706014babac..79fc95d49ff1c848c71a2686885ecdf758a9a32d
GIT binary patch
literal 961
zc$@*j13vtTP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F8000AsNkl<Zc-qBR
zNl#N@6crb49HK#u8yC9rM`$7mijfkaprS2SELcjF7Vx#jGWE5EwscgXWmIOxg___-
zFit^46pTh)p`uF@O^n0@mFqo?MR8>xr7ljm+<VS>r{ClI%C~}u{wpL4cgqg%*q2-I
zgfWRap#f4dj%+%3T>nmQaT0(Uy@UnGQI%X5L_fJhy%C^BFChWaa#S*%$xg23ZVGl@
z0U|Yem@Q`jEd9!St?;VO+e(3s!G!>*(ZdX!WebpgP@PrE@4PYGN8Z)}ay50$Ih(rY
zP@{(#ILj75r4`2NJYn*+4Up(-oqI4bWxaL(p;Pp?eMb*7aF!*&Ub$*piODwaZtkJ_
za~H`M>bk-Gjf^dg=R0rnN)Tq?Fn4?01LUboYt8l`d0YCa#vS@L`RqknbaroSB9}k?
zypLZ6IN-)TfZAYrW(&0QyYDBfx8;*cXBtR9q#l;#6%HRStsJy^!e1~0hq+JV8emU$
z{u-T0{DJM}Y3YkRL=b&ssB)5_+7+qo!H!5caI{A8J8M?QCBUwI2a>Xt+HiFFfyPiT
z?||+_@Pzvo<|bQ!pn-Nt0d}V4CZ)+$!QzTKviaL#{!aiG8ff7mIlx}|QGa1sHPtkR
z_{i<S^8XXSg$7!9ND7derSz!v7OHkP<Gu1h(;E|@ffgR{iaCHnQ$f|PCY*Ns&U+*Q
zT6n-K<^Ux|k(}o*^5N3GB)|h+F$XwRS&zT&xBy-f0ywaQaRIzy4sg<J$MVGm@QOKr
z&Say8a~Bp+f3}nCfp#3jywBUn5$r$@K#d+|;Gnli%U%)!7)5G;5gx)15ZT<~2z(g2
zc_+v}XU^CIvld4%0@U1liy1iJLKD@)OVTcgemWSMMc>EAPoEojwv{1gsQ!W+GjPC#
zCb~+Jc7ax~!XUD&LY?RH=%Y!2`|B`E%~b5?|Nq=kF4qC{P=hlzF(p6)Ej-{AbAW=A
zW-{CSR95Ajy*oNy#l7{>nOs?XIa{fD`TKXxG<v83aG`+~9`KU#U2x(Tjxmz|oE4Q;
zjwm$cvnjH?wJ8~S8<d*zuSNRGk-zlG&_;dYdM~K3IQk0tjL%i+t}=#-3{`|)!Y(Gg
zgVz+rr)%d=@%{$5rnat21&O>HCR^;jaii5sz!{r&f_s}2dO4kbGm|0Ix?TaVXWnNf
j`gRPgV#om0Qhj~`RGd2H&5smU00000NkvXXu0mjf*O16)
index 01d340aaa9095a54d19071516cf9e0ca75b1f72e..3467cf4d4701c6623125a8ecf80a833c6a0afca3
GIT binary patch
literal 4025
zc$@*b4@U5bP)<h;3K|Lk000e1NJLTq004jh004jp0{{R3^x%>C0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUyIZ#YgMF0Q*ARr($H8n{|Nm*H0XJ==1
zb#;V<gprYvo}Qkns;aiOw!y){&CSi(+1cac<L>V6`1tt$|Nm_HVu%0$026dlPE!a7
z2nYxW2nYxW2nYxW2nYxW2yC4}O#lE6_en%SRCwCOTgi6YJhLpI=WYxX-~VCnBD`Ph
z#Fi;#@$YkTWTH`B6Of&c>6Jt~F!WI?ya~>PBv;n<&OS#pUd{$+3_fF$N7N}NOrY7u
z3^5CYQd+mhnbBhDY5<ZBlo|;zErUmO;iVGdV}P6lIFh7|0Uq7TP9S@DsR;Gaf?Rh{
z9GjJ8DOzjJ$Y{`Z^rJ;?Gv^T!W9szH3JMC~r2Wv9BO~3^$V#XwMX)l;hbf?#rE(@k
zOgJ3sR#c$uB*-ZU2$OmjK{H!i+J^@sgOF;lp`;x=L--WutyO}`;1ji5O(_pG&*?RI
z!}DCJDU@(V)1{9p>g`b36|r#~(kW^5Sxm!LCD7s3oAp{#vs9*<pBAWaX}q)f0U?LF
z^3;d-mTK6Nqw)v~?+-a~*6?~1X%emQ!CR3%$%PYQqg6jmX=)Y`;!%{-mNQ8qj2kiX
zfi20&Y=pC0#W;sMaU<5uL=v%Nc)F=oSb=<QH?`q1wx1rDF?X!70=dz4+SHI3&RnMv
z8d^3Q!z6PCW5L{OEGJGmBm*O=8Q95%=%kzx4(_Xn_92r%cDCs{$8p$<LL;dGwHTGo
z8X=;HVXOi3V%2E2b)2&hE=8>%4)hL|=wP*Q5tgBe>8JaImoy)t<coQoJ-iMX95H0a
z5in2Eq?M9W4jD6AO0uYPa4d-D2H>c><KDT<Jfnt?_2J^J9QJhF=QZv!O!51=wd=aA
z69cJTjj&cideu%C%aINm&BJ{a0!lSaT1NQDz;11pMd!)Iv^_@JgUe&=35*rtnnrC@
zQbUs<RPQYj6_ZAJx}uQ75D1sXAP9UB1X!J?A8n`vYMc_rOO%z;CJUKLHP7b7dw?@l
zRFrnvBziz|s@P~f4lZ_|>||lG;F+DnOk$kIbn0y4Lm=jIxIz@UXtq%fa>|NC7vbIf
zSmzv`CLShXag2-y;@A9#Z_`7AMx4$9B|2t_NgL4`?+OTKYuaUsx<rGs*j{rWfq>Yl
z&IdaZ*prOfShFocqtmUSkt_~P!?G%o+AyCA(K_;^`}akSbA*dmQ$iDJ4ZKm`U2qJc
z*qpg%;8+f+BvmEpIV@bca-93q1wXC}-jTJw2N=EpW{?P2&_p6xoK2fM*LDiG$==#S
zLVKTf2$5n>#p>>gDZ^7Jf(BNPlo=7iYc>TclZjEYFf84<84+{R5egL*$ykT%!32ls
zTuMC(QYqS_9+U{7khX=6sR6i-urU|OkTTEJS5NaOHG>ywmU)b$mZh>aLJ31xc0U$E
zx~#PX&DA=Phs+VaQhXR5M5d5Is?%nXI$GbMjGZt!B7_KwJd6j~ris0bR>FAbS^<!^
zb1@iUn`v&@v)TiYt%~&+nS$U*JS<_7e8jSIc;5!VNj4%QSUcygm5nyrtl4sKrdhAy
zjSxJht`?%KKFUuWtJdTJvaQKe-9sAcP!@<cjHuM9rG1c6W^WE(l9m!qiPd5$+}#Q4
zq1m|_gn4ksxz&nppo|#<gLhOJb|eXkS>PHOa;O!T96d)MSf<$+v^OMH!Fmg<Rs(~2
zK;%I}gi}^{W(z~wX)QuPsZ|;UZWKO;QW7#&_>V&}&Sld&gSTWGB3!3yv^Xqu1>}vv
z`}lv}9lUuBp88nx8hnK)<~u9!0}Hyn0>`xi36S|~1*`3W{XQ8I63B~WNHvKveDH2U
zODFO<<+GBQ5woPJu_-j9hei%CGLFX=lus|p7x0t5qMUY7&O{2@VizAAP<4dA%JG^s
zCUNP!z<~3Ni4ZjJHe<|oNJzHg%91(RMx@pp<1r1#Oo(}#1ATOYdoB=#NlLfg^6@j@
zK{u@!blMa}kV(-#6EcbgsU6(hT`A9SS@7LXmtN^%9SFn?8vX2>{>uQnFaRCRSM0;)
zI>!=I1)YFr9|JAP(HabK5@0>ckk(T|v7!V8Z(%7!Oo*JNV#ja>K@QCJP&aZLV*PO}
zp8;J7YU{+&eFISg)H6oZ^Z-g;TQ3wFG_)n369lskOo2u<ER7mN;Z22wd(70Xa+bT<
zG_!06<m1JBgB#zSm5;#S7cdY+ARov@S&&s`h8;Zu(3}FDHjf$I5$X+bv{JB)$Z5>C
z)XN{_W?tkbNDgG~)~zE1!$YHZ)QO@z#9N?c=3_i6QN_YI+r+t1Q6TbAe!|wcAfvlG
zSm3!ft%5VqT+Db4@eb@aX!W{i^)!69@aS52*;~k;3zx2iOI8DZlYD;n=R6~ya*<C3
zr+*;7dXe8f8w20MMf(jGLf^ubz|}$0W3scNrO}X>NcHd`G%`V-;mR+#Y7mEiB1?La
zr7{TJB5U4DAW(-WjtE$#rnu+NWQ{TzDZxG<?>aS|RyCEEoSOXQ)NB`a(2p$s`9=FA
zlWy7sbg76rcLTi(0E)8N=p_KS)Xj0J8@LYGt88LjY~r$Zo~_;ETDy77;a{x%+!@H1
zJ+9B9zuV|0#gvgWwMPx<y3a&|4GqTQJTp3_gk+}}5f6l9z_E@A16rR1)&S*02u@_9
zo9LX{kHGUue}_^Z7p2ysK)fac{zAnYGT<*%To)?t2EhJfcU6h*0iBP?!~2}pxvk<n
z8)nb=a`WCc6hE-bcCpLZqk+B{tXF9AJACrE2D|D3RI|s3J_~4vQ=yJoF+zD-jmc>`
zKnfA>&0NRPJtum&k5jte^s<_*@abX$U?#Zu$oZ&_^>I(~wI|8DwtIW}9ap7ai!H$i
z@V$bvJJx~OG?Q%f0=Lr-+z#z4+XJwfB2#+kRHxRtVo=-W+~7v!8wokb{Ll8F%l1%0
z#B<vve%mep|BM@Y;fAj-y!ms?CE`;YV3}qn+F;;8N=iW)8XI1@5v_L{-QvQn(4Lro
z8<{WV22Xz5x0sq2rdC8CUX45U6?a@q{6DKknpt3$#q3ClrA>EoAgT}2hHxyKV#0X*
zTH<QbAvezX**AX2Uc)tKlwz3Q$=;j5_-@i-B~cNH$Y!G{xDEJvoXkz8cyWrDON4Xo
zio%3wOrE46%;i{G0cmhOd#RLcuFz$9WGf9-M_Ol>AnLVPADP76XojP~)<fo2=sz7m
z&^!L-d0q4^Q$a6N$<MyuAD&ea^N$OjuLaNQ1M9_4&bDngbqb-e#=P^%aeeZd+bx^%
zb>vu&jd_#*e<wko@&E7a3cB=%!%yTN?)R(w^me@VfuG{yr$*`+ck)>e;X@<MOc$6F
z<m03n?Ys+EA5}+Osv{DB{$;#Hxz{S`ZpG29jgxuI10#)_BFs^BLdAQRFRAhmj3zEd
z)7K0TI3&W{ct&*bU(4*a;CrgwAH!Xmby+qo+c1p6Luc1f+fQ^j^bG|2XdKELCYN0%
zSBDD%fqzNv-XYU|SqzSJ_!4g!zP$|(13yfak!>}lMwv`-L1`vXkFu__oR?^7vdTi)
zgH>5mwF$7PP)B#bG^PtE+(YooQw?XG=}gpvo45jB{fo!-FGxJ-`7iu0K!n3RNnM5b
zaI{Dpr1;_&`t=LD#si?OhgozEiwM@3XmdiEB}p8W&ohyCnDo&*rmwK&z^*lyS2whr
zWpTLia5Y4v3d-u_ZtkiOO|Fy-WU;!ob7k#VbG;b*)D`>0sR_S}pWpa5wf*cJ^vZRX
z>pFu5@YXlP^$pkZ+iD~)H4=~V@k<R+L4dbz|8M^Ej>V0OKWV`bKLtEL$P<;*F6;NU
zJQ<hu>?;d$arGBHhX1s}J2c8Jt#IZh^c%k3v$^~O=Iw&{r*mo7To$V!-;uW;2I^T=
z<2!{jE`>8T1N_E4{utl>3{`)}w<&2`!Y#4zb-^ZBoo*F;{&4N0Gk~r_kM9dUdKG-A
zF#h*08GlW7=|J~8!Sn~Rdt2Y&BHNuy(Ee>1<{Qhf;#$`c(?I`p3D0=_5<28s4g)O_
z9~dsrNz)~5C==Xt!`PO3l6rE-VI#&`ni0#_cF)%vkRD<e!}f)R^-VwMZa?m0KS-~B
zkO5dv`bl~9liE28cq1kGsFLocBp(lQTn9<bJJvVdkh>)1V>e`9-H@M1N?zbr-T-+&
zHg>4nJF&4|?a#sc#Ei9^<85a6j>p<AR?{#Q{8KRagKGFP82q7$gG)8kC_r9UW1j}=
zrW*T%5c4-e6#P@m>jk^>a$zK06C<^_jnKXkTHVsu_boHIT4uq`5Z~K*^th49z1sYe
zX0|Rnky8SCvx4`X3Gohw(NzJg(*^W1a6K(nvZ#dEOU25%fD^U_`};)hR&er7BKI^n
zkt-1-ISKa0xqozJ?w<Qc8+rboyN2~5^!}+2??CULyfS}7KO^oGN1s?{??ldgS!bgV
zIDW1HkE;d@AM{rZ`Oltnxn@G=!6TjaFz&=G(uv5lQbonC8gfD#=;fsFb4TYLLAftO
zzE=v?jmF$F<L+k0{pF21nL5_L1t!NEfeGbx)0RLWH{H$exZgYYUDsdN=>YI*gYl2^
zc&Bra*Ln1ff`8Ssc_9vc<57mTtLH<ahB?$yCb|v{<(agsOYz;7+^gR5fG;th9??8c
zVBBaxKC5Ds$8tZ;rcu<!k)9E|VR&+ld}wPS(g&|GMZ}vl=Bt630As&6!GF%!?ZVNA
zUD2;y!N!F8Wp=$yOW%q9ahYwicLuu3JD>6Yi>$vb%j&Rdrha5k!ZaU{j6qOegO52O
z<a2E0H91wN=@j^T{^W1v^hVs^7s2gXiMahj>}!qk&hsR@G>T{s$iF2v;~gs1FQD_O
z2EFG=e|x|$JVp4A^XSESLal@UO_}*S?H9ZJ<~iMge`*znz1}K5;BB2a(nkz~yll>X
zE=%0ZxIYy+<g(V1azTFV%|2IqU-xF8_krT-1C=)ez4El~3%~Zqr*&WWwc~1}*pB(X
z?~=*Oq1zuW;;lD%pIt=!b`c+lFW!W{qF3*|$@{EV>(Z;Eg1|3SvcDRwA3Drmaw}Zi
z%CQ#aQ|>|+ci}uGzT{5t&`G;cevGpt{*8~s8+>GrOS=Y-1^Mee<Xyk>I(y4@_Nk-i
z>IokbqTHX_26ov7wu>;oMoYTTa>sc72IPkm`jXx53$4!sipSfE;MbylO%eQB)OIcE
fqLlx6o9_PrXME4{*=FyU00000NkvXXu0mjf=sUwq
--- a/browser/base/content/browser-appmenu.inc
+++ b/browser/base/content/browser-appmenu.inc
@@ -189,16 +189,24 @@
                     type="checkbox"
                     command="Tools:Inspect"
                     key="key_inspect"/>
           <menuitem id="appmenu_debugger"
                     hidden="true"
                     label="&debuggerMenu.label;"
                     key="key_debugger"
                     command="Tools:Debugger"/>
+          <menuitem id="appmenu_remoteDebugger"
+                    hidden="true"
+                    label="&remoteDebuggerMenu.label;"
+                    command="Tools:RemoteDebugger"/>
+          <menuitem id="appmenu_chromeDebugger"
+                    hidden="true"
+                    label="&chromeDebuggerMenu.label;"
+                    command="Tools:ChromeDebugger"/>
           <menuitem id="appmenu_scratchpad"
                     hidden="true"
                     label="&scratchpad.label;"
                     key="key_scratchpad"
                     command="Tools:Scratchpad"/>
           <menuitem id="appmenu_styleeditor"
                     hidden="true"
                     label="&styleeditor.label;"
--- a/browser/base/content/browser-fullZoom.js
+++ b/browser/base/content/browser-fullZoom.js
@@ -220,17 +220,17 @@ var FullZoom = {
    * @param aBrowser
    *        (optional) browser object displaying the document
    */
   onLocationChange: function FullZoom_onLocationChange(aURI, aIsTabSwitch, aBrowser) {
     if (!aURI || (aIsTabSwitch && !this.siteSpecific))
       return;
 
     // Avoid the cps roundtrip and apply the default/global pref.
-    if (isBlankPageURL(aURI.spec)) {
+    if (aURI.spec == "about:blank") {
       this._applyPrefToSetting(undefined, aBrowser);
       return;
     }
 
     let browser = aBrowser || gBrowser.selectedBrowser;
 
     // Media documents should always start at 1, and are not affected by prefs.
     if (!aIsTabSwitch && browser.contentDocument.mozSyntheticDocument) {
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -546,16 +546,24 @@
                             accesskey="&inspectMenu.accesskey;"
                             key="key_inspect"
                             command="Tools:Inspect"/>
                   <menuitem id="menu_debugger"
                             hidden="true"
                             label="&debuggerMenu.label;"
                             key="key_debugger"
                             command="Tools:Debugger"/>
+                  <menuitem id="menu_remoteDebugger"
+                            hidden="true"
+                            label="&remoteDebuggerMenu.label;"
+                            command="Tools:RemoteDebugger"/>
+                  <menuitem id="menu_chromeDebugger"
+                            hidden="true"
+                            label="&chromeDebuggerMenu.label;"
+                            command="Tools:ChromeDebugger"/>
                   <menuitem id="menu_scratchpad"
                             hidden="true"
                             label="&scratchpad.label;"
                             accesskey="&scratchpad.accesskey;"
                             key="key_scratchpad"
                             command="Tools:Scratchpad"/>
                   <menuitem id="menu_styleeditor"
                             hidden="true"
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -124,16 +124,18 @@
     <command id="cmd_fullZoomToggle"  oncommand="ZoomManager.toggleZoom();"/>
     <command id="Browser:OpenLocation" oncommand="openLocation();"/>
 
     <command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
     <command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
     <command id="Tools:WebConsole" oncommand="HUDConsoleUI.toggleHUD();"/>
     <command id="Tools:Inspect" oncommand="InspectorUI.toggleInspectorUI();" disabled="true"/>
     <command id="Tools:Debugger" oncommand="DebuggerUI.toggleDebugger();" disabled="true"/>
+    <command id="Tools:RemoteDebugger" oncommand="DebuggerUI.toggleRemoteDebugger();" disabled="true"/>
+    <command id="Tools:ChromeDebugger" oncommand="DebuggerUI.toggleChromeDebugger();" disabled="true"/>
     <command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true"/>
     <command id="Tools:StyleEditor" oncommand="StyleEditor.openChrome();" disabled="true"/>
     <command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
     <command id="Tools:Sanitize"
      oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
     <command id="Tools:PrivateBrowsing" oncommand="gPrivateBrowsingUI.toggleMode();"/>
     <command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
     <command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -425,30 +425,21 @@ window[chromehidden~="toolbar"] toolbar:
   -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image");
   margin: 0;
 }
 
 
 /* notification anchors should only be visible when their associated
    notifications are */
 .notification-anchor-icon {
-  display: none;
   -moz-user-focus: normal;
 }
 
-/* We use the iconBox as the notification anchor when a popup notification is
-   created with a null anchorID, so in that case use a default anchor icon. */
-#notification-popup-box[anchorid="notification-popup-box"] > #default-notification-icon,
-#notification-popup-box[anchorid="geo-notification-icon"] > #geo-notification-icon,
-#notification-popup-box[anchorid="indexedDB-notification-icon"] > #indexedDB-notification-icon,
-#notification-popup-box[anchorid="addons-notification-icon"] > #addons-notification-icon,
-#notification-popup-box[anchorid="password-notification-icon"] > #password-notification-icon,
-#notification-popup-box[anchorid="webapps-notification-icon"] > #webapps-notification-icon,
-#notification-popup-box[anchorid="plugins-notification-icon"] > #plugins-notification-icon {
-  display: -moz-box;
+.notification-anchor-icon:not([showing]) {
+  display: none;
 }
 
 #invalid-form-popup > description {
   max-width: 280px;
 }
 
 #geolocation-notification {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#geolocation-notification");
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1711,16 +1711,36 @@ function delayedStartup(isLoadingBlank, 
   if (enabled) {
     document.getElementById("menu_debugger").hidden = false;
     document.getElementById("Tools:Debugger").removeAttribute("disabled");
 #ifdef MENUBAR_CAN_AUTOHIDE
     document.getElementById("appmenu_debugger").hidden = false;
 #endif
   }
 
+  // Enable Remote Debugger?
+  let enabled = gPrefService.getBoolPref("devtools.debugger.remote-enabled");
+  if (enabled) {
+    document.getElementById("menu_remoteDebugger").hidden = false;
+    document.getElementById("Tools:RemoteDebugger").removeAttribute("disabled");
+#ifdef MENUBAR_CAN_AUTOHIDE
+    document.getElementById("appmenu_remoteDebugger").hidden = false;
+#endif
+  }
+
+  // Enable Chrome Debugger?
+  let enabled = gPrefService.getBoolPref("devtools.chrome.enabled");
+  if (enabled) {
+    document.getElementById("menu_chromeDebugger").hidden = false;
+    document.getElementById("Tools:ChromeDebugger").removeAttribute("disabled");
+#ifdef MENUBAR_CAN_AUTOHIDE
+    document.getElementById("appmenu_chromeDebugger").hidden = false;
+#endif
+  }
+
   // Enable Error Console?
   // XXX Temporarily always-enabled, see bug 601201
   let consoleEnabled = true || gPrefService.getBoolPref("devtools.errorconsole.enabled");
   if (consoleEnabled) {
     document.getElementById("javascriptConsole").hidden = false;
     document.getElementById("key_errorConsole").removeAttribute("disabled");
 #ifdef MENUBAR_CAN_AUTOHIDE
     document.getElementById("appmenu_errorConsole").hidden = false;
--- a/browser/base/content/test/browser_popupNotification.js
+++ b/browser/base/content/test/browser_popupNotification.js
@@ -637,16 +637,94 @@ var tests = [
       checkPopup(popup, this.notifyObj);
       dismissNotification(popup);
     },
     onHidden: function (popup) {
       ok(!this.notifyObj.dismissalCallbackTriggered, "dismissal callback wasn't triggered");
       ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
     }
   },
+  // Test multiple notification icons are shown
+  { // Test #21
+    run: function () {
+      this.notifyObj1 = new basicNotification();
+      this.notifyObj1.id += "_1";
+      this.notifyObj1.anchorID = "default-notification-icon";
+      this.notification1 = showNotification(this.notifyObj1);
+
+      this.notifyObj2 = new basicNotification();
+      this.notifyObj2.id += "_2";
+      this.notifyObj2.anchorID = "geo-notification-icon";
+      this.notification2 = showNotification(this.notifyObj2);
+    },
+    onShown: function (popup) {
+      checkPopup(popup, this.notifyObj2);
+
+      // check notifyObj1 anchor icon is showing
+      isnot(document.getElementById("default-notification-icon").boxObject.width, 0,
+            "default anchor should be visible");
+      // check notifyObj2 anchor icon is showing
+      isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
+            "geo anchor should be visible");
+
+      dismissNotification(popup);
+    },
+    onHidden: [
+      function (popup) {
+      },
+      function (popup) {
+        this.notification1.remove();
+        ok(this.notifyObj1.removedCallbackTriggered, "removed callback triggered");
+
+        this.notification2.remove();
+        ok(this.notifyObj2.removedCallbackTriggered, "removed callback triggered");
+      }
+    ],
+  },
+  // Test that multiple notification icons are removed when switching tabs
+  { // Test #22
+    run: function () {
+      // show the notification on old tab.
+      this.notifyObjOld = new basicNotification();
+      this.notifyObjOld.anchorID = "default-notification-icon";
+      this.notificationOld = showNotification(this.notifyObjOld);
+
+      // switch tab
+      this.oldSelectedTab = gBrowser.selectedTab;
+      gBrowser.selectedTab = gBrowser.addTab("about:blank");
+
+      // show the notification on new tab.
+      this.notifyObjNew = new basicNotification();
+      this.notifyObjNew.anchorID = "geo-notification-icon";
+      this.notificationNew = showNotification(this.notifyObjNew);
+    },
+    onShown: function (popup) {
+      checkPopup(popup, this.notifyObjNew);
+
+      // check notifyObjOld anchor icon is removed
+      is(document.getElementById("default-notification-icon").boxObject.width, 0,
+         "default anchor shouldn't be visible");
+      // check notifyObjNew anchor icon is showing
+      isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
+            "geo anchor should be visible");
+
+      dismissNotification(popup);
+    },
+    onHidden: [
+      function (popup) {
+      },
+      function (popup) {
+        this.notificationNew.remove();
+        gBrowser.removeTab(gBrowser.selectedTab);
+
+        gBrowser.selectedTab = this.oldSelectedTab;
+        this.notificationOld.remove();
+      }
+    ],
+  }
 ];
 
 function showNotification(notifyObj) {
   return PopupNotifications.show(notifyObj.browser,
                                  notifyObj.id,
                                  notifyObj.message,
                                  notifyObj.anchorID,
                                  notifyObj.mainAction,
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -236,26 +236,23 @@ var PlacesOrganizer = {
     // and update the back/forward buttons by setting location.
     if (this._content.place != placeURI || !resetSearchBox) {
       this._content.place = placeURI;
       PlacesSearchBox.hideSearchUI();
       this.location = node.uri;
     }
 
     // Update the selected folder title where it appears in the UI: the folder
-    // scope button, "Find in <current collection>" command, and the search box
-    // emptytext.  They must be updated even if the selection hasn't changed --
+    // scope button, and the search box emptytext.
+    // They must be updated even if the selection hasn't changed --
     // specifically when node's title changes.  In that case a selection event
     // is generated, this method is called, but the selection does not change.
     var folderButton = document.getElementById("scopeBarFolder");
     var folderTitle = node.title || folderButton.getAttribute("emptytitle");
     folderButton.setAttribute("label", folderTitle);
-    var cmd = document.getElementById("OrganizerCommand_find:current");
-    var label = PlacesUIUtils.getFormattedString("findInPrefix", [folderTitle]);
-    cmd.setAttribute("label", label);
     if (PlacesSearchBox.filterCollection == "collection")
       PlacesSearchBox.updateCollectionTitle(folderTitle);
 
     // When we invalidate a container we use suppressSelectionEvent, when it is
     // unset a select event is fired, in many cases the selection did not really
     // change, so we should check for it, and return early in such a case. Note
     // that we cannot return any earlier than this point, because when
     // !resetSearchBox, we need to update location and hide the UI as above,
@@ -920,44 +917,49 @@ var PlacesSearchBox = {
 
     PlacesSearchBox.showSearchUI();
 
     // Update the details panel
     PlacesOrganizer.onContentTreeSelect();
   },
 
   /**
-   * Finds across all bookmarks
+   * Finds across all history, downloads or all bookmarks.
    */
   findAll: function PSB_findAll() {
-    PlacesQueryBuilder.setScope("bookmarks");
-    this.focus();
-  },
-
-  /**
-   * Finds in the currently selected Place.
-   */
-  findCurrent: function PSB_findCurrent() {
-    PlacesQueryBuilder.setScope("collection");
+    switch (this.filterCollection) {
+      case "history":
+        PlacesQueryBuilder.setScope("history");
+        break;
+      case "downloads":
+        PlacesQueryBuilder.setScope("downloads");
+        break;
+      default:
+        PlacesQueryBuilder.setScope("bookmarks");
+        break;
+    }
     this.focus();
   },
 
   /**
    * Updates the display with the title of the current collection.
    * @param   aTitle
    *          The title of the current collection.
    */
   updateCollectionTitle: function PSB_updateCollectionTitle(aTitle) {
     let title = "";
+    // This is needed when a user performs a folder-specific search
+    // using the scope bar, removes the search-string, and unfocuses
+    // the search box, at least until the removal of the scope bar.
     if (aTitle) {
       title = PlacesUIUtils.getFormattedString("searchCurrentDefault",
                                                [aTitle]);
     }
     else {
-      switch(this.filterCollection) {
+      switch (this.filterCollection) {
         case "history":
           title = PlacesUIUtils.getString("searchHistory");
           break;
         case "downloads":
           title = PlacesUIUtils.getString("searchDownloads");
           break;
         default:
           title = PlacesUIUtils.getString("searchBookmarks");                                    
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -94,23 +94,17 @@
 #include ../../../base/content/browserMountPoints.inc
 #else
   <commandset id="editMenuCommands"/>
   <commandset id="placesCommands"/>
 #endif
 
   <commandset id="organizerCommandSet">
     <command id="OrganizerCommand_find:all"
-             label="&cmd.findInBookmarks.label;"
-             accesskey="&cmd.findInBookmarks.accesskey;"
              oncommand="PlacesSearchBox.findAll();"/>
-    <command id="OrganizerCommand_find:current"
-             label="&cmd.findCurrent.label;"
-             accesskey="&cmd.findCurrent.accesskey;"
-             oncommand="PlacesSearchBox.findCurrent();"/>
     <command id="OrganizerCommand_export"
              oncommand="PlacesOrganizer.exportBookmarks();"/>
     <command id="OrganizerCommand_import"
              oncommand="PlacesOrganizer.importFromFile();"/>
     <command id="OrganizerCommand_browserImport"
              oncommand="PlacesOrganizer.importFromBrowser();"/>
     <command id="OrganizerCommand_backup"
              oncommand="PlacesOrganizer.backupBookmarks();"/>
@@ -132,20 +126,16 @@
     <key id="placesKey_close" key="&cmd.close.key;" modifiers="accel" 
          oncommand="close();"/>
          
     <!-- Command Keys -->
     <key id="placesKey_find:all"
          command="OrganizerCommand_find:all" 
          key="&cmd.find.key;"
          modifiers="accel"/>
-    <key id="placesKey_find:current"
-         command="OrganizerCommand_find:current" 
-         key="&cmd.find.key;"
-         modifiers="accel,shift"/>
 
     <!-- Back/Forward Keys Support -->
 #ifndef XP_MACOSX
     <key id="placesKey_goBackKb"
          keycode="VK_LEFT"
          command="OrganizerCommand:Back"
          modifiers="alt"/>
     <key id="placesKey_goForwardKb"
--- a/browser/devtools/debugger/DebuggerUI.jsm
+++ b/browser/devtools/debugger/DebuggerUI.jsm
@@ -40,17 +40,23 @@
  *
  * ***** END LICENSE BLOCK ***** */
 "use strict";
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
+const DBG_XUL = "chrome://browser/content/debugger.xul";
+const REMOTE_PROFILE_NAME = "_remote-debug";
+
+Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 let EXPORTED_SYMBOLS = ["DebuggerUI"];
 
 /**
  * Provides a simple mechanism of managing debugger instances per tab.
  *
  * @param nsIDOMWindow aWindow
  *        The chrome window for which the DebuggerUI instance is created.
@@ -71,59 +77,101 @@ DebuggerUI.prototype = {
     if (tab._scriptDebugger) {
       tab._scriptDebugger.close();
       return null;
     }
     return new DebuggerPane(tab);
   },
 
   /**
+   * Starts a remote debugger in a new process, or stops it if already started.
+   * @see DebuggerProcess.constructor
+   * @return DebuggerProcess if the debugger is started, null if it's stopped.
+   */
+  toggleRemoteDebugger: function DUI_toggleRemoteDebugger(aOnClose, aOnRun) {
+    let win = this.chromeWindow;
+
+    if (win._remoteDebugger) {
+      win._remoteDebugger.close();
+      return null;
+    }
+    return new DebuggerProcess(win, aOnClose, aOnRun);
+  },
+
+  /**
+   * Starts a chrome debugger in a new process, or stops it if already started.
+   * @see DebuggerProcess.constructor
+   * @return DebuggerProcess if the debugger is started, null if it's stopped.
+   */
+  toggleChromeDebugger: function DUI_toggleChromeDebugger(aOnClose, aOnRun) {
+    let win = this.chromeWindow;
+
+    if (win._chromeDebugger) {
+      win._chromeDebugger.close();
+      return null;
+    }
+    return new DebuggerProcess(win, aOnClose, aOnRun, true);
+  },
+
+  /**
    * Get the debugger for a specified tab.
    * @return DebuggerPane if a debugger exists for the tab, null otherwise
    */
   getDebugger: function DUI_getDebugger(aTab) {
     return aTab._scriptDebugger;
   },
 
   /**
    * Get the preferences associated with the debugger frontend.
    * @return object
    */
   get preferences() {
-    return DebuggerUIPreferences;
+    return DebuggerPreferences;
   }
 };
 
 /**
  * Creates a pane that will host the debugger.
  *
  * @param XULElement aTab
  *        The tab in which to create the debugger.
  */
 function DebuggerPane(aTab) {
   this._tab = aTab;
+  
+  this._initServer();
   this._create();
 }
 
 DebuggerPane.prototype = {
 
   /**
+   * Initializes the debugger server.
+   */
+  _initServer: function DP__initServer() {
+    if (!DebuggerServer.initialized) {
+      DebuggerServer.init();
+      DebuggerServer.addBrowserActors();
+    }
+  },
+
+  /**
    * Creates and initializes the widgets containing the debugger UI.
    */
   _create: function DP__create() {
     this._tab._scriptDebugger = this;
 
     let gBrowser = this._tab.linkedBrowser.getTabBrowser();
     let ownerDocument = gBrowser.parentNode.ownerDocument;
 
     this._splitter = ownerDocument.createElement("splitter");
     this._splitter.setAttribute("class", "hud-splitter");
 
     this._frame = ownerDocument.createElement("iframe");
-    this._frame.height = DebuggerUIPreferences.height;
+    this._frame.height = DebuggerPreferences.height;
 
     this._nbox = gBrowser.getNotificationBox(this._tab.linkedBrowser);
     this._nbox.appendChild(this._splitter);
     this._nbox.appendChild(this._frame);
 
     this.close = this.close.bind(this);
     let self = this;
 
@@ -134,30 +182,30 @@ DebuggerPane.prototype = {
 
       // Bind shortcuts for accessing the breakpoint methods in the debugger.
       let bkp = self.debuggerWindow.DebuggerController.Breakpoints;
       self.addBreakpoint = bkp.addBreakpoint;
       self.removeBreakpoint = bkp.removeBreakpoint;
       self.getBreakpoint = bkp.getBreakpoint;
     }, true);
 
-    this._frame.setAttribute("src", "chrome://browser/content/debugger.xul");
+    this._frame.setAttribute("src", DBG_XUL);
   },
 
   /**
    * Closes the debugger, removing child nodes and event listeners.
    */
   close: function DP_close() {
     if (!this._tab) {
       return;
     }
-    this._tab._scriptDebugger = null;
+    delete this._tab._scriptDebugger;
     this._tab = null;
 
-    DebuggerUIPreferences.height = this._frame.height;
+    DebuggerPreferences.height = this._frame.height;
     this._frame.removeEventListener("Debugger:Close", this.close, true);
     this._frame.removeEventListener("unload", this.close, true);
 
     this._nbox.removeChild(this._splitter);
     this._nbox.removeChild(this._frame);
 
     this._splitter = null;
     this._frame = null;
@@ -181,19 +229,127 @@ DebuggerPane.prototype = {
     if (debuggerWindow) {
       return debuggerWindow.DebuggerController.Breakpoints.store;
     }
     return null;
   }
 };
 
 /**
- * Various debugger UI preferences (currently just the pane height).
+ * Creates a process that will hold the remote debugger.
+ *
+ * @param function aOnClose
+ *        Optional, a function called when the process exits.
+ * @param function aOnRun
+ *        Optional, a function called when the process starts running.
+ * @param boolean aInitServerFlag
+ *        True to initialize the server. This should happen only in the chrome
+ *        debugging case. This should also be true by default after bug #747429.
+ * @param nsIDOMWindow aWindow
+ *        The chrome window for which the remote debugger instance is created.
  */
-let DebuggerUIPreferences = {
+function DebuggerProcess(aWindow, aOnClose, aOnRun, aInitServerFlag) {
+  this._win = aWindow;
+  this._closeCallback = aOnClose;
+  this._runCallback = aOnRun;
+
+  aInitServerFlag && this._initServer();
+  this._initProfile();
+  this._create();
+}
+
+DebuggerProcess.prototype = {
+
+  /**
+   * Initializes the debugger server.
+   */
+  _initServer: function RDP__initServer() {
+    if (!DebuggerServer.initialized) {
+      DebuggerServer.init();
+      DebuggerServer.addBrowserActors();
+    }
+    DebuggerServer.closeListener();
+    DebuggerServer.openListener(DebuggerPreferences.remotePort, false);
+  },
+
+  /**
+   * Initializes a profile for the remote debugger process.
+   */
+  _initProfile: function RDP__initProfile() {
+    let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]
+      .createInstance(Ci.nsIToolkitProfileService);
+
+    let dbgProfileName;
+    try {
+      dbgProfileName = profileService.selectedProfile.name + REMOTE_PROFILE_NAME;
+    } catch(e) {
+      dbgProfileName = REMOTE_PROFILE_NAME;
+      Cu.reportError(e);
+    }
+
+    this._dbgProfile = profileService.createProfile(null, null, dbgProfileName);
+    profileService.flush();
+  },
+
+  /**
+   * Creates and initializes the profile & process for the remote debugger.
+   */
+  _create: function RDP__create() {
+    this._win._remoteDebugger = this;
+
+    let file = FileUtils.getFile("CurProcD",
+      [Services.appinfo.OS == "WINNT" ? "firefox.exe"
+                                      : "firefox-bin"]);
+
+    let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
+    process.init(file);
+
+    let args = [
+      "-no-remote", "-P", this._dbgProfile.name,
+      "-chrome", DBG_XUL,
+      "-width", DebuggerPreferences.remoteWinWidth,
+      "-height", DebuggerPreferences.remoteWinHeight];
+
+    process.runwAsync(args, args.length, { observe: this.close.bind(this) });
+    this._dbgProcess = process;
+
+    if (typeof this._runCallback === "function") {
+      this._runCallback.call({}, this);
+    }
+  },
+
+  /**
+   * Closes the remote debugger, removing the profile and killing the process.
+   */
+  close: function RDP_close() {
+    if (!this._win) {
+      return;
+    }
+    delete this._win._remoteDebugger;
+    this._win = null;
+
+    if (this._dbgProcess.isRunning) {
+      this._dbgProcess.kill();
+    }
+    if (this._dbgProfile) {
+      this._dbgProfile.remove(false);
+    }
+    if (typeof this._closeCallback === "function") {
+      this._closeCallback.call({}, this);
+    }
+
+    this._dbgProcess = null;
+    this._dbgProfile = null;
+  }
+};
+
+/**
+ * Various debugger preferences.
+ */
+let DebuggerPreferences = {
 
   /**
    * Gets the preferred height of the debugger pane.
    * @return number
    */
   get height() {
     if (this._height === undefined) {
       this._height = Services.prefs.getIntPref("devtools.debugger.ui.height");
@@ -205,8 +361,40 @@ let DebuggerUIPreferences = {
    * Sets the preferred height of the debugger pane.
    * @param number value
    */
   set height(value) {
     Services.prefs.setIntPref("devtools.debugger.ui.height", value);
     this._height = value;
   }
 };
+
+/**
+ * Gets the preferred width of the remote debugger window.
+ * @return number
+ */
+XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remoteWinWidth", function() {
+  return Services.prefs.getIntPref("devtools.debugger.ui.remote-win.width");
+});
+
+/**
+ * Gets the preferred height of the remote debugger window.
+ * @return number
+ */
+XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remoteWinHeight", function() {
+  return Services.prefs.getIntPref("devtools.debugger.ui.remote-win.height");
+});
+
+/**
+ * Gets the preferred default remote debugging host.
+ * @return string
+ */
+XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remoteHost", function() {
+  return Services.prefs.getCharPref("devtools.debugger.remote-host");
+});
+
+/**
+ * Gets the preferred default remote debugging port.
+ * @return number
+ */
+XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remotePort", function() {
+  return Services.prefs.getIntPref("devtools.debugger.remote-port");
+});
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -109,29 +109,28 @@ let DebuggerController = {
     DebuggerView.Properties.destroy();
 
     DebuggerController.SourceScripts.disconnect();
     DebuggerController.StackFrames.disconnect();
     DebuggerController.ThreadState.disconnect();
 
     this.dispatchEvent("Debugger:Unloaded");
     this._disconnect();
+    this._isRemote && this._quitApp();
   },
 
   /**
    * Initializes a debugger client and connects it to the debugger server,
    * wiring event handlers as necessary.
    */
   _connect: function DC__connect() {
-    if (!DebuggerServer.initialized) {
-      DebuggerServer.init();
-      DebuggerServer.addBrowserActors();
-    }
+    let transport =
+      this._isRemote ? debuggerSocketConnect(Prefs.remoteHost, Prefs.remotePort)
+                     : DebuggerServer.connectPipe();
 
-    let transport = DebuggerServer.connectPipe();
     let client = this.client = new DebuggerClient(transport);
 
     client.addListener("tabNavigated", this._onTabNavigated);
     client.addListener("tabDetached", this._onTabDetached);
 
     client.connect(function(aType, aTraits) {
       client.listTabs(function(aResponse) {
         let tab = aResponse.tabs[aResponse.selected];
@@ -216,16 +215,41 @@ let DebuggerController = {
           });
         });
 
       }.bind(this));
     }.bind(this));
   },
 
   /**
+   * Returns true if this is a remote debugger instance.
+   * @return boolean
+   */
+  get _isRemote() {
+    return !window.parent.content;
+  },
+
+  /**
+   * Attempts to quit the current process if allowed.
+   */
+  _quitApp: function DC__quitApp() {
+    let canceled = Cc["@mozilla.org/supports-PRBool;1"]
+      .createInstance(Ci.nsISupportsPRBool);
+
+    Services.obs.notifyObservers(canceled, "quit-application-requested", null);
+
+    // Somebody canceled our quit request.
+    if (canceled.data) {
+      return;
+    }
+
+    Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
+  },
+
+  /**
    * Convenience method, dispatching a custom event.
    *
    * @param string aType
    *        The name of the event.
    * @param string aDetail
    *        The data passed when initializing the event.
    */
   dispatchEvent: function DC_dispatchEvent(aType, aDetail) {
@@ -465,52 +489,71 @@ StackFrames.prototype = {
       let thisVar = localScope.addVar("this");
       thisVar.setGrip({
         type: frame.this.type,
         class: frame.this.class
       });
       this._addExpander(thisVar, frame.this);
     }
 
+    if (frame.environment) {
+      // Add nodes for every argument.
+      let variables = frame.environment.bindings.arguments;
+      for each (let variable in variables) {
+        let name = Object.getOwnPropertyNames(variable)[0];
+        let paramVar = localScope.addVar(name);
+        let paramVal = variable[name].value;
+        paramVar.setGrip(paramVal);
+        this._addExpander(paramVar, paramVal);
+      }
+
+      // Add nodes for every other variable in scope.
+      variables = frame.environment.bindings.variables;
+      for (let variable in variables) {
+        let paramVar = localScope.addVar(variable);
+        let paramVal = variables[variable].value;
+        paramVar.setGrip(paramVal);
+        this._addExpander(paramVar, paramVal);
+      }
+
+      // If we already found 'arguments', we are done here.
+      if ("arguments" in frame.environment.bindings.variables) {
+        // Signal that variables have been fetched.
+        DebuggerController.dispatchEvent("Debugger:FetchedVariables");
+        return;
+      }
+    }
+
+    // Sometimes in call frames with arguments we don't get 'arguments' in the
+    // environment (bug 746601) and we have to construct it manually. Note, that
+    // in this case arguments.callee will be absent, even in the cases where it
+    // shouldn't be.
     if (frame.arguments && frame.arguments.length > 0) {
       // Add "arguments".
       let argsVar = localScope.addVar("arguments");
       argsVar.setGrip({
         type: "object",
         class: "Arguments"
       });
       this._addExpander(argsVar, frame.arguments);
 
-      // Add variables for every argument.
-      let objClient = this.activeThread.pauseGrip(frame.callee);
-      objClient.getSignature(function SF_getSignature(aResponse) {
-        for (let i = 0, l = aResponse.parameters.length; i < l; i++) {
-          let param = aResponse.parameters[i];
-          let paramVar = localScope.addVar(param);
-          let paramVal = frame.arguments[i];
+      // Signal that variables have been fetched.
+      DebuggerController.dispatchEvent("Debugger:FetchedVariables");
+    }
 
-          paramVar.setGrip(paramVal);
-          this._addExpander(paramVar, paramVal);
-        }
-
-        // Signal that call parameters have been fetched.
-        DebuggerController.dispatchEvent("Debugger:FetchedParameters");
-
-      }.bind(this));
-    }
   },
 
   /**
-   * Adds a onexpand callback for a variable, lazily handling the addition of
+   * Adds an 'onexpand' callback for a variable, lazily handling the addition of
    * new properties.
    */
   _addExpander: function SF__addExpander(aVar, aObject) {
     // No need for expansion for null and undefined values, but we do need them
     // for frame.arguments which is a regular array.
-    if (!aObject || typeof aObject !== "object" ||
+    if (!aVar || !aObject || typeof aObject !== "object" ||
         (aObject.type !== "object" && !Array.isArray(aObject))) {
       return;
     }
 
     // Force the twisty to show up.
     aVar.forceShowArrow();
     aVar.onexpand = this._addVarProperties.bind(this, aVar, aObject);
   },
@@ -681,26 +724,27 @@ SourceScripts.prototype = {
     this.activeThread.removeListener("scriptsadded", this._onScriptsAdded);
     this.activeThread.removeListener("scriptscleared", this._onScriptsCleared);
   },
 
   /**
    * Handler for the debugger client's unsolicited newScript notification.
    */
   _onNewScript: function SS__onNewScript(aNotification, aPacket) {
-    this._addScript({ url: aPacket.url, startLine: aPacket.startLine });
+    this._addScript({ url: aPacket.url, startLine: aPacket.startLine }, true);
   },
 
   /**
    * Handler for the thread client's scriptsadded notification.
    */
   _onScriptsAdded: function SS__onScriptsAdded() {
     for each (let script in this.activeThread.cachedScripts) {
-      this._addScript(script);
+      this._addScript(script, false);
     }
+    DebuggerView.Scripts.commitScripts();
   },
 
   /**
    * Handler for the thread client's scriptscleared notification.
    */
   _onScriptsCleared: function SS__onScriptsCleared() {
     DebuggerView.Scripts.empty();
   },
@@ -743,51 +787,70 @@ SourceScripts.prototype = {
     let q = aUrl.indexOf('?');
     if (q > -1) {
       return aUrl.slice(0, q);
     }
     return aUrl;
   },
 
   /**
+   * Gets the prePath for a script URL.
+   *
+   * @param string aUrl
+   *        The script url.
+   * @return string
+   *         The script prePath if the url is valid, null otherwise.
+   */
+  _getScriptPrePath: function SS__getScriptDomain(aUrl) {
+    try {
+      return Services.io.newURI(aUrl, null, null).prePath + "/";
+    } catch (e) {
+    }
+    return null;
+  },
+
+  /**
    * 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
-   *        defalult to debugged panrent window location.
+   *        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 href = aHref || window.parent.content.location.href;
+    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 alreay present in the scripts list
+    // 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 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;
   },
 
@@ -795,25 +858,26 @@ SourceScripts.prototype = {
    * Clears the labels cache, populated by SS_getScriptLabel.
    * This should be done every time the content location changes.
    */
   _clearLabelsCache: function SS__clearLabelsCache() {
     this._labelsCache = {};
   },
 
   /**
-   * Add the specified script to the list and display it in the editor if the
-   * editor is empty.
+   * Add the specified script to the list.
+   *
+   * @param object aScript
+   *        The script object coming from the active thread.
+   * @param boolean aForceFlag
+   *        True to force the script to be immediately added.
    */
-  _addScript: function SS__addScript(aScript) {
-    DebuggerView.Scripts.addScript(this._getScriptLabel(aScript.url), aScript);
-
-    if (DebuggerView.editor.getCharCount() == 0) {
-      this.showScript(aScript);
-    }
+  _addScript: function SS__addScript(aScript, aForceFlag) {
+    DebuggerView.Scripts.addScript(
+      this._getScriptLabel(aScript.url), aScript, aForceFlag);
   },
 
   /**
    * Load the editor with the script text if available, otherwise fire an event
    * to load and display the script text.
    *
    * @param object aScript
    *        The script object coming from the active thread.
@@ -871,17 +935,17 @@ SourceScripts.prototype = {
       url: aScript.url
     });
   },
 
   /**
    * Handles notifications to load a source script from the cache or from a
    * local file.
    *
-   * XXX: Tt may be better to use nsITraceableChannel to get to the sources
+   * XXX: It may be better to use nsITraceableChannel to get to the sources
    * without relying on caching when we can (not for eval, etc.):
    * http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/
    */
   _onLoadSource: function SS__onLoadSource(aEvent) {
     let url = aEvent.detail.url;
     let options = aEvent.detail.options;
     let self = this;
 
@@ -962,17 +1026,17 @@ SourceScripts.prototype = {
    * Log an error message in the error console when a script fails to load.
    *
    * @param string aUrl
    *        The URL of the source script.
    * @param string aStatus
    *        The failure status code.
    */
   _logError: function SS__logError(aUrl, aStatus) {
-    Components.utils.reportError(L10N.getFormatStr("loadingError", [aUrl, aStatus]));
+    Cu.reportError(L10N.getFormatStr("loadingError", [aUrl, aStatus]));
   },
 };
 
 /**
  * Handles all the breakpoints in the current debugger.
  */
 function Breakpoints() {
   this._onEditorBreakpointChange = this._onEditorBreakpointChange.bind(this);
@@ -1254,16 +1318,37 @@ let L10N = {
   }
 };
 
 XPCOMUtils.defineLazyGetter(L10N, "stringBundle", function() {
   return Services.strings.createBundle(DBG_STRINGS_URI);
 });
 
 /**
+ * Shortcuts for accessing various debugger preferences.
+ */
+let Prefs = {};
+
+/**
+ * Gets the preferred default remote debugging host.
+ * @return string
+ */
+XPCOMUtils.defineLazyGetter(Prefs, "remoteHost", function() {
+  return Services.prefs.getCharPref("devtools.debugger.remote-host");
+});
+
+/**
+ * Gets the preferred default remote debugging port.
+ * @return number
+ */
+XPCOMUtils.defineLazyGetter(Prefs, "remotePort", function() {
+  return Services.prefs.getIntPref("devtools.debugger.remote-port");
+});
+
+/**
  * Preliminary setup for the DebuggerController object.
  */
 DebuggerController.init();
 DebuggerController.ThreadState = new ThreadState();
 DebuggerController.StackFrames = new StackFrames();
 DebuggerController.SourceScripts = new SourceScripts();
 DebuggerController.Breakpoints = new Breakpoints();
 
--- a/browser/devtools/debugger/debugger-view.js
+++ b/browser/devtools/debugger/debugger-view.js
@@ -85,53 +85,72 @@ let DebuggerView = {
   }
 };
 
 /**
  * Functions handling the scripts UI.
  */
 function ScriptsView() {
   this._onScriptsChange = this._onScriptsChange.bind(this);
+  this._onScriptsSearch = this._onScriptsSearch.bind(this);
 }
 
 ScriptsView.prototype = {
 
   /**
    * Removes all elements from the scripts container, leaving it empty.
    */
   empty: function DVS_empty() {
     while (this._scripts.firstChild) {
       this._scripts.removeChild(this._scripts.firstChild);
     }
   },
 
   /**
+   * Removes the input in the searchbox and unhides all the scripts.
+   */
+  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 and shown in the list.
    *
    * @param string aUrl
    *        The script URL.
    * @return boolean
    */
   contains: function DVS_contains(aUrl) {
+    if (this._tmpScripts.some(function(element) {
+      return element.script.url == aUrl;
+    })) {
+      return true;
+    }
     if (this._scripts.getElementsByAttribute("value", aUrl).length > 0) {
       return true;
     }
     return false;
   },
 
   /**
    * Checks whether the script with the specified label is among the scripts
    * known to the debugger and shown in the list.
    *
    * @param string aLabel
    *        The script label.
    * @return boolean
    */
   containsLabel: function DVS_containsLabel(aLabel) {
+    if (this._tmpScripts.some(function(element) {
+      return element.label == aLabel;
+    })) {
+      return true;
+    }
     if (this._scripts.getElementsByAttribute("label", aLabel).length > 0) {
       return true;
     }
     return false;
   },
 
   /**
    * Selects the script with the specified URL from the list.
@@ -167,80 +186,258 @@ ScriptsView.prototype = {
    * @return string | null
    */
   get selected() {
     return this._scripts.selectedItem ?
            this._scripts.selectedItem.value : null;
   },
 
   /**
+   * Returns the list of labels in the scripts container.
+   * @return array
+   */
+  get scriptLabels() {
+    let labels = [];
+    for (let i = 0, l = this._scripts.itemCount; i < l; i++) {
+      labels.push(this._scripts.getItemAtIndex(i).label);
+    }
+    return labels;
+  },
+
+  /**
    * Returns the list of URIs for scripts in the page.
    * @return array
    */
   get scriptLocations() {
     let locations = [];
     for (let i = 0, l = this._scripts.itemCount; i < l; i++) {
       locations.push(this._scripts.getItemAtIndex(i).value);
     }
     return locations;
   },
 
   /**
-   * Adds a script to the scripts container.
-   * If the script already exists (was previously added), null is returned.
-   * Otherwise, the newly created element is returned.
+   * Gets the number of visible (hidden=false) scripts in the container.
+   * @return number
+   */
+  get visibleItemsCount() {
+    let count = 0;
+    for (let i = 0, l = this._scripts.itemCount; i < l; i++) {
+      count += this._scripts.getItemAtIndex(i).hidden ? 0 : 1;
+    }
+    return count;
+  },
+
+  /**
+   * Prepares a script to be added to the scripts container. This allows
+   * for a large number of scripts to be batched up before being
+   * alphabetically sorted and added in the container.
+   * @see ScriptsView.commitScripts
+   *
+   * If aForceFlag is true, the script will be immediately inserted at the
+   * necessary position in the container so that all the scripts remain sorted.
+   * This can be much slower than batching up multiple scripts.
+   *
+   * @param string aLabel
+   *        The simplified script location to be shown.
+   * @param string aScript
+   *        The source script.
+   * @param boolean aForceFlag
+   *        True to force the script to be immediately added.
+   */
+  addScript: function DVS_addScript(aLabel, aScript, aForceFlag) {
+    // Batch the script to be added later.
+    if (!aForceFlag) {
+      this._tmpScripts.push({ label: aLabel, script: aScript });
+      return;
+    }
+
+    // Find the target position in the menulist and insert the script there.
+    for (let i = 0, l = this._scripts.itemCount; i < l; i++) {
+      if (this._scripts.getItemAtIndex(i).label > aLabel) {
+        this._createScriptElement(aLabel, aScript, i);
+        return;
+      }
+    }
+    // The script is alphabetically the last one.
+    this._createScriptElement(aLabel, aScript, -1, true);
+  },
+
+  /**
+   * Adds all the prepared scripts to the scripts container.
+   * If a script already exists (was previously added), nothing happens.
+   */
+  commitScripts: function DVS_commitScripts() {
+    let newScripts = this._tmpScripts;
+    this._tmpScripts = [];
+
+    if (!newScripts || !newScripts.length) {
+      return;
+    }
+    newScripts.sort(function(a, b) {
+      return a.label.toLowerCase() > b.label.toLowerCase();
+    });
+
+    for (let i = 0, l = newScripts.length; i < l; i++) {
+      let item = newScripts[i];
+      this._createScriptElement(item.label, item.script, -1, true);
+    }
+  },
+
+  /**
+   * Creates a custom script element and adds it to the scripts container.
+   * If the script with the specified label already exists, nothing happens.
    *
    * @param string aLabel
    *        The simplified script location to be shown.
    * @param string aScript
    *        The source script.
-   * @return object
-   *         The newly created html node representing the added script.
+   * @param number aIndex
+   *        The index where to insert to new script in the container.
+   *        Pass -1 to append the script at the end.
+   * @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.
    */
-  addScript: function DVS_addScript(aLabel, aScript) {
+  _createScriptElement: function DVS__createScriptElement(
+    aLabel, aScript, aIndex, aSelectIfEmptyFlag)
+  {
     // Make sure we don't duplicate anything.
-    if (this.containsLabel(aLabel)) {
-      return null;
+    if (aLabel == "null" || this.containsLabel(aLabel)) {
+      return;
     }
 
-    let script = this._scripts.appendItem(aLabel, aScript.url);
-    script.setAttribute("tooltiptext", aScript.url);
-    script.setUserData("sourceScript", aScript, null);
+    let scriptItem =
+      aIndex == -1 ? this._scripts.appendItem(aLabel, aScript.url)
+                   : this._scripts.insertItemAt(aIndex, aLabel, aScript.url);
 
-    this._scripts.selectedItem = script;
-    return script;
+    scriptItem.setAttribute("tooltiptext", aScript.url);
+    scriptItem.setUserData("sourceScript", aScript, null);
+
+    if (this._scripts.itemCount == 1 && aSelectIfEmptyFlag) {
+      this._scripts.selectedItem = scriptItem;
+    }
   },
 
   /**
-   * The cached click listener for the scripts container.
+   * The click listener for the scripts container.
    */
   _onScriptsChange: function DVS__onScriptsChange() {
     let script = this._scripts.selectedItem.getUserData("sourceScript");
+    this._preferredScript = script;
     DebuggerController.SourceScripts.showScript(script);
   },
 
   /**
-   * The cached scripts container.
+   * The search listener for the scripts search box.
+   */
+  _onScriptsSearch: function DVS__onScriptsSearch(e) {
+    let editor = DebuggerView.editor;
+    let scripts = this._scripts;
+    let rawValue = this._searchbox.value.toLowerCase();
+
+    let rawLength = rawValue.length;
+    let lastColon = rawValue.lastIndexOf(":");
+    let lastAt = rawValue.lastIndexOf("@");
+
+    let fileEnd = lastColon != -1 ? lastColon : lastAt != -1 ? lastAt : rawLength;
+    let lineEnd = lastAt != -1 ? lastAt : rawLength;
+
+    let file = rawValue.slice(0, fileEnd);
+    let line = window.parseInt(rawValue.slice(fileEnd + 1, lineEnd)) || -1;
+    let token = rawValue.slice(lineEnd + 1);
+
+    // Presume we won't find anything.
+    scripts.selectedItem = this._preferredScript;
+
+    // If we're not searching for a file anymore, unhide all the scripts.
+    if (!file) {
+      for (let i = 0, l = scripts.itemCount; i < l; i++) {
+        scripts.getItemAtIndex(i).hidden = false;
+      }
+    } else {
+      for (let i = 0, l = scripts.itemCount, found = false; i < l; i++) {
+        let item = scripts.getItemAtIndex(i);
+        let target = item.value.toLowerCase();
+
+        // Search is not case sensitive, and is tied to the url not the label.
+        if (target.match(file)) {
+          item.hidden = false;
+
+          if (!found) {
+            found = true;
+            scripts.selectedItem = item;
+          }
+        }
+        // Hide what doesn't match our search.
+        else {
+          item.hidden = true;
+        }
+      }
+    }
+    if (line > -1) {
+      editor.setCaretPosition(line - 1);
+    }
+    if (token) {
+      let offset = editor.find(token, { ignoreCase: true });
+      if (offset > -1) {
+        editor.setCaretPosition(0);
+        editor.setCaretOffset(offset);
+      }
+    }
+  },
+
+  /**
+   * The keyup listener for the scripts search box.
+   */
+  _onScriptsKeyUp: function DVS__onScriptsKeyUp(e) {
+    if (e.keyCode === e.DOM_VK_ESCAPE) {
+      DebuggerView.editor.focus();
+      return;
+    }
+
+    if (e.keyCode === e.DOM_VK_RETURN || e.keyCode === e.DOM_VK_ENTER) {
+      let editor = DebuggerView.editor;
+      let offset = editor.findNext(true);
+      if (offset > -1) {
+        editor.setCaretPosition(0);
+        editor.setCaretOffset(offset);
+      }
+    }
+  },
+
+  /**
+   * The cached scripts container and search box.
    */
   _scripts: null,
+  _searchbox: null,
 
   /**
    * Initialization function, called when the debugger is initialized.
    */
   initialize: function DVS_initialize() {
     this._scripts = document.getElementById("scripts");
+    this._searchbox = document.getElementById("scripts-search");
     this._scripts.addEventListener("select", this._onScriptsChange, false);
+    this._searchbox.addEventListener("select", this._onScriptsSearch, false);
+    this._searchbox.addEventListener("input", this._onScriptsSearch, false);
+    this._searchbox.addEventListener("keyup", this._onScriptsKeyUp, false);
+    this.commitScripts();
   },
 
   /**
    * Destruction function, called when the debugger is shut down.
    */
   destroy: function DVS_destroy() {
     this._scripts.removeEventListener("select", this._onScriptsChange, false);
+    this._searchbox.removeEventListener("select", this._onScriptsSearch, false);
+    this._searchbox.removeEventListener("input", this._onScriptsSearch, false);
+    this._searchbox.removeEventListener("keyup", this._onScriptsKeyUp, false);
     this._scripts = null;
+    this._searchbox = null;
   }
 };
 
 /**
  * Functions handling the html stackframes UI.
  */
 function StackFramesView() {
   this._onFramesScroll = this._onFramesScroll.bind(this);
@@ -272,16 +469,18 @@ StackFramesView.prototype = {
     else if (aState == "attached") {
       status.textContent = L10N.getStr("runningState");
       resume.label = L10N.getStr("pauseLabel");
     }
     // No valid state parameter.
     else {
       status.textContent = "";
     }
+
+    DebuggerView.Scripts.clearSearch();
   },
 
   /**
    * Removes all elements from the stackframes container, leaving it empty.
    */
   empty: function DVF_empty() {
     while (this._frames.firstChild) {
       this._frames.removeChild(this._frames.firstChild);
@@ -295,17 +494,17 @@ StackFramesView.prototype = {
   emptyText: function DVF_emptyText() {
     // Make sure the container is empty first.
     this.empty();
 
     let item = document.createElement("div");
 
     // The empty node should look grayed out to avoid confusion.
     item.className = "empty list-item";
-    item.appendChild(document.createTextNode(L10N.getStr("emptyText")));
+    item.appendChild(document.createTextNode(L10N.getStr("emptyStackText")));
 
     this._frames.appendChild(item);
   },
 
   /**
    * Adds a frame to the stackframes container.
    * If the frame already exists (was previously added), null is returned.
    * Otherwise, the newly created element is returned.
@@ -376,17 +575,17 @@ StackFramesView.prototype = {
 
   /**
    * Deselects a frame from the stackframe container.
    *
    * @param number aDepth
    *        The frame depth specified by the debugger.
    */
   unhighlightFrame: function DVF_unhighlightFrame(aDepth) {
-    this.highlightFrame(aDepth, true)
+    this.highlightFrame(aDepth, true);
   },
 
   /**
    * Gets the current dirty state.
    *
    * @return boolean value
    *         True if should load more frames.
    */
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -76,16 +76,18 @@
   <div id="body" class="vbox flex">
     <xul:toolbar id="dbg-toolbar">
       <xul:button id="close">&debuggerUI.closeButton;</xul:button>
       <xul:button id="resume"/>
       <xul:button id="step-over">&debuggerUI.stepOverButton;</xul:button>
       <xul:button id="step-in">&debuggerUI.stepInButton;</xul:button>
       <xul:button id="step-out">&debuggerUI.stepOutButton;</xul:button>
       <xul:menulist id="scripts"/>
+      <xul:textbox id="scripts-search" type="search"
+                   emptytext="&debuggerUI.emptyFilterText;"/>
     </xul:toolbar>
     <div id="dbg-content" class="hbox flex">
       <div id="stack" class="vbox">
         <div class="title unselectable">&debuggerUI.stackTitle;</div>
         <div id="stackframes" class="vbox flex"></div>
       </div>
       <div id="script" class="vbox flex">
         <div class="title unselectable">&debuggerUI.scriptTitle;</div>
--- a/browser/devtools/debugger/test/Makefile.in
+++ b/browser/devtools/debugger/test/Makefile.in
@@ -41,16 +41,17 @@ topsrcdir       = @top_srcdir@
 srcdir          = @srcdir@
 VPATH           = @srcdir@
 relativesrcdir  = browser/devtools/debugger/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
+	browser_dbg_createRemote.js \
 	browser_dbg_debuggerstatement.js \
 	browser_dbg_listtabs.js \
 	browser_dbg_tabactor-01.js \
 	browser_dbg_tabactor-02.js \
 	browser_dbg_contextactor-01.js \
 	browser_dbg_contextactor-02.js \
 	testactors.js \
 	browser_dbg_nav-01.js \
@@ -65,16 +66,19 @@ include $(topsrcdir)/config/rules.mk
 	browser_dbg_panesize.js \
 	browser_dbg_stack-01.js \
 	browser_dbg_stack-02.js \
 	browser_dbg_stack-03.js \
 	browser_dbg_stack-04.js \
 	browser_dbg_stack-05.js \
 	browser_dbg_location-changes.js \
 	browser_dbg_script-switching.js \
+	browser_dbg_scripts-sorting.js \
+	browser_dbg_scripts-searching-01.js \
+	browser_dbg_scripts-searching-02.js \
 	browser_dbg_pause-resume.js \
 	browser_dbg_update-editor-mode.js \
 	$(warning browser_dbg_select-line.js temporarily disabled due to oranges, see bug 726609) \
 	browser_dbg_clean-exit.js \
 	browser_dbg_bug723069_editor-breakpoints.js \
 	browser_dbg_bug731394_editor-contextmenu.js \
 	browser_dbg_displayName.js \
 	browser_dbg_iframes.js \
--- a/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js
@@ -18,47 +18,54 @@ let gBreakpoints = null;
 
 function test()
 {
   let tempScope = {};
   Cu.import("resource:///modules/source-editor.jsm", tempScope);
   let SourceEditor = tempScope.SourceEditor;
   let scriptShown = false;
   let framesAdded = false;
+  let resumed = false;
+  let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.debuggerWindow;
+    resumed = true;
+
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
-      runTest();
+      executeSoon(startTest);
     });
 
-    gDebuggee.firstCall();
+    executeSoon(function() {
+      gDebuggee.firstCall();
+    });
   });
 
-  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
-    let url = aEvent.detail.url;
-    if (url.indexOf("-02.js") != -1) {
-      scriptShown = true;
-      window.removeEventListener(aEvent.type, _onEvent);
-      runTest();
-    }
-  });
+  function onScriptShown(aEvent)
+  {
+    scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
+    executeSoon(startTest);
+  }
 
-  function runTest()
+  window.addEventListener("Debugger:ScriptShown", onScriptShown);
+
+  function startTest()
   {
-    if (scriptShown && framesAdded) {
-      Services.tm.currentThread.dispatch({ run: onScriptShown }, 0);
+    if (scriptShown && framesAdded && resumed && !testStarted) {
+      window.removeEventListener("Debugger:ScriptShown", onScriptShown);
+      testStarted = true;
+      Services.tm.currentThread.dispatch({ run: performTest }, 0);
     }
   }
 
-  function onScriptShown()
+  function performTest()
   {
     gScripts = gDebugger.DebuggerView.Scripts;
 
     is(gDebugger.DebuggerController.activeThread.state, "paused",
       "Should only be getting stack frames while paused.");
 
     is(gScripts._scripts.itemCount, 2, "Found the expected number of scripts.");
 
--- a/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js
@@ -16,47 +16,53 @@ function test()
 {
   let tempScope = {};
   Cu.import("resource:///modules/source-editor.jsm", tempScope);
   let SourceEditor = tempScope.SourceEditor;
 
   let contextMenu = null;
   let scriptShown = false;
   let framesAdded = false;
+  let resumed = false;
+  let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.debuggerWindow;
+    resumed = true;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
-      runTest();
+      executeSoon(startTest);
     });
-    gDebuggee.firstCall();
+
+    executeSoon(function() {
+      gDebuggee.firstCall();
+    });
   });
 
-  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
-    let url = aEvent.detail.url;
-    if (url.indexOf("-02.js") != -1) {
-      scriptShown = true;
-      window.removeEventListener(aEvent.type, _onEvent);
-      runTest();
-    }
-  });
+  function onScriptShown(aEvent) {
+    scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
+    executeSoon(startTest);
+  }
+
+  window.addEventListener("Debugger:ScriptShown", onScriptShown);
 
-  function runTest()
+  function startTest()
   {
-    if (scriptShown && framesAdded) {
-      Services.tm.currentThread.dispatch({ run: onScriptShown }, 0);
+    if (scriptShown && framesAdded && resumed && !testStarted) {
+      testStarted = true;
+      window.removeEventListener("Debugger:ScriptShown", onScriptShown);
+      Services.tm.currentThread.dispatch({ run: performTest }, 0);
     }
   }
 
-  function onScriptShown()
+  function performTest()
   {
     let scripts = gDebugger.DebuggerView.Scripts._scripts;
 
     is(gDebugger.DebuggerController.activeThread.state, "paused",
       "Should only be getting stack frames while paused.");
 
     is(scripts.itemCount, 2, "Found the expected number of scripts.");
 
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_createRemote.js
@@ -0,0 +1,86 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+var gProcess = null;
+var gTab = null;
+var gDebuggee = null;
+
+function test() {
+  remote_debug_tab_pane(STACK_URL, aOnClosing, function(aTab, aDebuggee, aProcess) {
+    gTab = aTab;
+    gDebuggee = aDebuggee;
+    gProcess = aProcess;
+
+    testSimpleCall();
+  });
+}
+
+function testSimpleCall() {
+  Services.tm.currentThread.dispatch({ run: function() {
+
+    ok(gProcess._dbgProcess,
+      "The remote debugger process wasn't created properly!");
+    ok(gProcess._dbgProcess.isRunning,
+      "The remote debugger process isn't running!");
+    is(typeof gProcess._dbgProcess.pid, "number",
+      "The remote debugger process doesn't have a pid (?!)");
+
+    info("process location: " + gProcess._dbgProcess.location);
+    info("process pid: " + gProcess._dbgProcess.pid);
+    info("process name: " + gProcess._dbgProcess.processName);
+    info("process sig: " + gProcess._dbgProcess.processSignature);
+
+    ok(gProcess._dbgProfile,
+      "The remote debugger profile wasn't created properly!");
+    ok(gProcess._dbgProfile.localDir,
+      "The remote debugger profile doesn't have a localDir...");
+    ok(gProcess._dbgProfile.rootDir,
+      "The remote debugger profile doesn't have a rootDir...");
+    ok(gProcess._dbgProfile.name,
+      "The remote debugger profile doesn't have a name...");
+
+    info("profile localDir: " + gProcess._dbgProfile.localDir);
+    info("profile rootDir: " + gProcess._dbgProfile.rootDir);
+    info("profile name: " + gProcess._dbgProfile.name);
+
+    let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]
+      .createInstance(Ci.nsIToolkitProfileService);
+
+    let profile = profileService.getProfileByName(gProcess._dbgProfile.name);
+
+    ok(profile,
+      "The remote debugger profile wasn't *actually* created properly!");
+    is(profile.localDir.path, gProcess._dbgProfile.localDir.path,
+      "The remote debugger profile doesn't have the correct localDir!");
+    is(profile.rootDir.path, gProcess._dbgProfile.rootDir.path,
+      "The remote debugger profile doesn't have the correct rootDir!");
+
+    DebuggerUI.toggleRemoteDebugger();
+  }}, 0);
+}
+
+function aOnClosing() {
+  ok(!gProcess._dbgProcess.isRunning,
+    "The remote debugger process isn't closed as it should be!");
+  is(gProcess._dbgProcess.exitValue, (Services.appinfo.OS == "WINNT" ? 0 : 256),
+    "The remote debugger process didn't die cleanly.");
+
+  info("process exit value: " + gProcess._dbgProcess.exitValue);
+
+  info("profile localDir: " + gProcess._dbgProfile.localDir.path);
+  info("profile rootDir: " + gProcess._dbgProfile.rootDir.path);
+  info("profile name: " + gProcess._dbgProfile.name);
+
+  executeSoon(function() {
+    finish();
+  });
+}
+
+registerCleanupFunction(function() {
+  removeTab(gTab);
+  gProcess = null;
+  gTab = null;
+  gDebuggee = null;
+});
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-01.js
@@ -80,38 +80,38 @@ function testSimpleCall() {
 
   gDebuggee.simpleCall();
 }
 
 function resumeAndFinish() {
   gDebugger.DebuggerController.activeThread.resume(function() {
     let vs = gDebugger.DebuggerView.Scripts;
     let ss = gDebugger.DebuggerController.SourceScripts;
-    ss._onScriptsCleared();
+    vs.empty();
+    vs._scripts.removeEventListener("select", vs._onScriptsChange, false);
 
     is(ss._trimUrlQuery("a/b/c.d?test=1&random=4"), "a/b/c.d",
       "Trimming the url query isn't done properly.");
 
     let urls = [
       { href: "ici://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: "si://interesting.address.moc/random/", leaf: "script.js" },
       { href: "si://interesting.address.moc/random/", leaf: "x/script.js" },
       { href: "si://interesting.address.moc/random/", leaf: "x/y/script.js?a=1" },
       { href: "si://interesting.address.moc/random/x/", leaf: "y/script.js?a=1&b=2" },
       { href: "si://interesting.address.moc/random/x/y/", leaf: "script.js?a=1&b=2&c=3" }
     ];
 
-    vs._scripts.removeEventListener("select", vs._onScriptsChange, false);
-
     urls.forEach(function(url) {
       executeSoon(function() {
         let loc = url.href + url.leaf;
         vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc });
+        vs.commitScripts();
       });
     });
 
     executeSoon(function() {
       for (let i = 0; i < vs._scripts.itemCount; i++) {
         let lab = vs._scripts.getItemAtIndex(i).getAttribute("label");
         let loc = urls[i].href + urls[i].leaf;
 
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-07.js
@@ -22,20 +22,20 @@ function test()
     testFrameParameters();
   });
 }
 
 function testFrameParameters()
 {
   dump("Started testFrameParameters!\n");
 
-  gDebugger.addEventListener("Debugger:FetchedParameters", function test() {
-    dump("Entered Debugger:FetchedParameters!\n");
+  gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
+    dump("Entered Debugger:FetchedVariables!\n");
 
-    gDebugger.removeEventListener("Debugger:FetchedParameters", test, false);
+    gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
       dump("After currentThread.dispatch!\n");
 
       var frames = gDebugger.DebuggerView.StackFrames._frames,
           childNodes = frames.childNodes,
           localScope = gDebugger.DebuggerView.Properties.localScope,
           localNodes = localScope.querySelector(".details").childNodes;
@@ -47,43 +47,52 @@ function testFrameParameters()
       dump("localNodes - " + localNodes.constructor + "\n");
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 3,
         "Should have three frames.");
 
-      is(localNodes.length, 8,
+      is(localNodes.length, 11,
         "The localScope should contain all the created variable elements.");
 
       is(localNodes[0].querySelector(".info").textContent, "[object Proxy]",
         "Should have the right property value for 'this'.");
 
-      is(localNodes[1].querySelector(".info").textContent, "[object Arguments]",
-        "Should have the right property value for 'arguments'.");
-
-      is(localNodes[2].querySelector(".info").textContent, "[object Object]",
+      is(localNodes[1].querySelector(".info").textContent, "[object Object]",
         "Should have the right property value for 'aArg'.");
 
-      is(localNodes[3].querySelector(".info").textContent, '"beta"',
+      is(localNodes[2].querySelector(".info").textContent, '"beta"',
         "Should have the right property value for 'bArg'.");
 
-      is(localNodes[4].querySelector(".info").textContent, "3",
+      is(localNodes[3].querySelector(".info").textContent, "3",
         "Should have the right property value for 'cArg'.");
 
-      is(localNodes[5].querySelector(".info").textContent, "false",
+      is(localNodes[4].querySelector(".info").textContent, "false",
         "Should have the right property value for 'dArg'.");
 
-      is(localNodes[6].querySelector(".info").textContent, "null",
+      is(localNodes[5].querySelector(".info").textContent, "null",
         "Should have the right property value for 'eArg'.");
 
-      is(localNodes[7].querySelector(".info").textContent, "undefined",
+      is(localNodes[6].querySelector(".info").textContent, "undefined",
         "Should have the right property value for 'fArg'.");
 
+      is(localNodes[7].querySelector(".info").textContent, "1",
+        "Should have the right property value for 'a'.");
+
+      is(localNodes[8].querySelector(".info").textContent, "[object Object]",
+        "Should have the right property value for 'b'.");
+
+      is(localNodes[9].querySelector(".info").textContent, "[object Object]",
+        "Should have the right property value for 'c'.");
+
+      is(localNodes[10].querySelector(".info").textContent, "[object Arguments]",
+        "Should have the right property value for 'arguments'.");
+
       resumeAndFinish();
     }}, 0);
   }, false);
 
   EventUtils.sendMouseEvent({ type: "click" },
     content.document.querySelector("button"),
     content.window);
 }
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-08.js
@@ -22,20 +22,20 @@ function test()
     testFrameParameters();
   });
 }
 
 function testFrameParameters()
 {
   dump("Started testFrameParameters!\n");
 
-  gDebugger.addEventListener("Debugger:FetchedParameters", function test() {
-    dump("Entered Debugger:FetchedParameters!\n");
+  gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
+    dump("Entered Debugger:FetchedVariables!\n");
 
-    gDebugger.removeEventListener("Debugger:FetchedParameters", test, false);
+    gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
       dump("After currentThread.dispatch!\n");
 
       var frames = gDebugger.DebuggerView.StackFrames._frames,
           localScope = gDebugger.DebuggerView.Properties.localScope,
           localNodes = localScope.querySelector(".details").childNodes;
 
@@ -45,82 +45,98 @@ function testFrameParameters()
       dump("localNodes - " + localNodes.constructor + "\n");
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 3,
         "Should have three frames.");
 
-      is(localNodes.length, 8,
+      is(localNodes.length, 11,
         "The localScope should contain all the created variable elements.");
 
       is(localNodes[0].querySelector(".info").textContent, "[object Proxy]",
         "Should have the right property value for 'this'.");
 
-      // Expand the __proto__ and arguments tree nodes. This causes their
-      // properties to be retrieved and displayed.
+      // Expand the '__proto__', 'arguments' and 'a' tree nodes. This causes
+      // their properties to be retrieved and displayed.
       localNodes[0].expand();
-      localNodes[1].expand();
+      localNodes[9].expand();
+      localNodes[10].expand();
 
       // Poll every few milliseconds until the properties are retrieved.
       // It's important to set the timer in the chrome window, because the
       // content window timers are disabled while the debuggee is paused.
       let count = 0;
       let intervalID = window.setInterval(function(){
         if (++count > 50) {
           ok(false, "Timed out while polling for the properties.");
           resumeAndFinish();
         }
-        if (!localNodes[0].fetched || !localNodes[1].fetched) {
+        if (!localNodes[0].fetched ||
+            !localNodes[9].fetched ||
+            !localNodes[10].fetched) {
           return;
         }
         window.clearInterval(intervalID);
         is(localNodes[0].querySelector(".property > .title > .key")
                         .textContent, "__proto__ ",
           "Should have the right property name for __proto__.");
 
         ok(localNodes[0].querySelector(".property > .title > .value")
                         .textContent.search(/object/) != -1,
           "__proto__ should be an object.");
 
-        is(localNodes[1].querySelector(".info").textContent, "[object Arguments]",
+        is(localNodes[9].querySelector(".info").textContent, "[object Object]",
+          "Should have the right property value for 'c'.");
+
+        is(localNodes[9].querySelectorAll(".property > .title > .key")[1]
+                        .textContent, "a",
+          "Should have the right property name for 'a'.");
+
+        is(localNodes[9].querySelectorAll(".property > .title > .value")[1]
+                        .textContent, 1,
+          "Should have the right value for 'c.a'.");
+
+        is(localNodes[10].querySelector(".info").textContent,
+          "[object Arguments]",
           "Should have the right property value for 'arguments'.");
 
-        is(localNodes[1].querySelector(".property > .title > .key")
+        is(localNodes[10].querySelector(".property > .title > .key")
                         .textContent, "length",
-          "Should have the right property name for length.");
+          "Should have the right property name for 'length'.");
 
-        is(localNodes[1].querySelector(".property > .title > .value")
+        is(localNodes[10].querySelector(".property > .title > .value")
                         .textContent, 5,
           "Should have the right argument length.");
 
         resumeAndFinish();
       }, 100);
     }}, 0);
   }, false);
 
   EventUtils.sendMouseEvent({ type: "click" },
     content.document.querySelector("button"),
     content.window);
 }
 
 function resumeAndFinish() {
-  gDebugger.DebuggerController.activeThread.addOneTimeListener("framescleared", function() {
+  let thread = gDebugger.DebuggerController.activeThread;
+  thread.addOneTimeListener("framescleared", function() {
     Services.tm.currentThread.dispatch({ run: function() {
       var frames = gDebugger.DebuggerView.StackFrames._frames;
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 0,
         "Should have no frames.");
 
       closeDebuggerAndFinish(gTab);
     }}, 0);
   });
 
-  gDebugger.DebuggerController.activeThread.resume();
+  thread.resume();
 }
 
 registerCleanupFunction(function() {
   removeTab(gTab);
   gPane = null;
   gTab = null;
   gDebugger = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_script-switching.js
+++ b/browser/devtools/debugger/test/browser_dbg_script-switching.js
@@ -3,57 +3,59 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Make sure that switching the displayed script in the UI works as advertised.
  */
 
 const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
 
-let tempScope = {};
-Cu.import("resource:///modules/source-editor.jsm", tempScope);
-let SourceEditor = tempScope.SourceEditor;
-
 var gPane = null;
 var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 var gScripts = null;
 
 function test()
 {
   let scriptShown = false;
   let framesAdded = false;
+  let resumed = false;
+  let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.debuggerWindow;
+    resumed = true;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
-      runTest();
+      executeSoon(startTest);
     });
 
-    gDebuggee.firstCall();
+    executeSoon(function() {
+      gDebuggee.firstCall();
+    });
   });
 
-  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
-    let url = aEvent.detail.url;
-    if (url.indexOf("-02.js") != -1) {
-      scriptShown = true;
-      window.removeEventListener(aEvent.type, _onEvent);
-      runTest();
-    }
-  });
+  function onScriptShown(aEvent)
+  {
+    scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
+    executeSoon(startTest);
+  }
 
-  function runTest()
+  window.addEventListener("Debugger:ScriptShown", onScriptShown);
+
+  function startTest()
   {
-    if (scriptShown && framesAdded) {
+    if (scriptShown && framesAdded && resumed && !testStarted) {
+      window.removeEventListener("Debugger:ScriptShown", onScriptShown);
+      testStarted = true;
       Services.tm.currentThread.dispatch({ run: testScriptsDisplay }, 0);
     }
   }
 }
 
 function testScriptsDisplay() {
   gScripts = gDebugger.DebuggerView.Scripts._scripts;
 
@@ -74,18 +76,16 @@ function testScriptsDisplay() {
   ok(gDebugger.DebuggerView.Scripts.contains(EXAMPLE_URL +
     label2), "Second script url is incorrect.");
 
   ok(gDebugger.DebuggerView.Scripts.containsLabel(
     label1), "First script label is incorrect.");
   ok(gDebugger.DebuggerView.Scripts.containsLabel(
     label2), "Second script label is incorrect.");
 
-  dump("Debugger editor text:\n" + gDebugger.editor.getText() + "\n");
-
   ok(gDebugger.editor.getText().search(/debugger/) != -1,
     "The correct script was loaded initially.");
 
   is(gDebugger.editor.getDebugLocation(), 5,
      "editor debugger location is correct.");
 
   window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
     let url = aEvent.detail.url;
@@ -95,18 +95,16 @@ function testScriptsDisplay() {
     }
   });
 
   gDebugger.DebuggerView.Scripts.selectScript(EXAMPLE_URL + label1);
 }
 
 function testSwitchPaused()
 {
-  dump("Debugger editor text:\n" + gDebugger.editor.getText() + "\n");
-
   ok(gDebugger.editor.getText().search(/debugger/) == -1,
     "The second script is no longer displayed.");
 
   ok(gDebugger.editor.getText().search(/firstCall/) != -1,
     "The first script is displayed.");
 
   is(gDebugger.editor.getDebugLocation(), -1,
      "editor debugger location has been cleared.");
@@ -122,16 +120,18 @@ function testSwitchPaused()
 
     gDebugger.DebuggerView.Scripts.selectScript(EXAMPLE_URL +
                                                 "test-script-switching-02.js");
   });
 }
 
 function testSwitchRunning()
 {
+  dump("Debugger editor text:\n" + gDebugger.editor.getText() + "\n");
+
   ok(gDebugger.editor.getText().search(/debugger/) != -1,
     "The second script is displayed again.");
 
   ok(gDebugger.editor.getText().search(/firstCall/) == -1,
     "The first script is no longer displayed.");
 
   is(gDebugger.editor.getDebugLocation(), -1,
      "editor debugger location is still -1.");
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-01.js
@@ -0,0 +1,188 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+var gPane = null;
+var gTab = null;
+var gDebuggee = null;
+var gDebugger = null;
+var gEditor = null;
+var gScripts = null;
+var gSearchBox = null;
+var gMenulist = null;
+
+function test()
+{
+  let scriptShown = false;
+  let framesAdded = false;
+
+  debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
+    gTab = aTab;
+    gDebuggee = aDebuggee;
+    gPane = aPane;
+    gDebugger = gPane.debuggerWindow;
+
+    gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
+      framesAdded = true;
+      runTest();
+    });
+
+    gDebuggee.simpleCall();
+  });
+
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    window.removeEventListener(aEvent.type, _onEvent);
+    scriptShown = true;
+    runTest();
+  });
+
+  function runTest()
+  {
+    if (scriptShown && framesAdded) {
+      Services.tm.currentThread.dispatch({ run: testScriptSearching }, 0);
+    }
+  }
+}
+
+function testScriptSearching() {
+  gDebugger.DebuggerController.activeThread.resume(function() {
+    gEditor = gDebugger.DebuggerView.editor;
+    gScripts = gDebugger.DebuggerView.Scripts;
+    gSearchBox = gScripts._searchbox;
+    gMenulist = gScripts._scripts;
+
+    write(":12");
+    ok(gEditor.getCaretPosition().line == 11 &&
+       gEditor.getCaretPosition().col == 0,
+      "The editor didn't jump to the correct line.");
+
+    write("@debugger");
+    ok(gEditor.getCaretPosition().line == 2 &&
+       gEditor.getCaretPosition().col == 44,
+      "The editor didn't jump to the correct token. (1)");
+
+    EventUtils.sendKey("RETURN");
+    ok(gEditor.getCaretPosition().line == 8 &&
+       gEditor.getCaretPosition().col == 2,
+      "The editor didn't jump to the correct token. (2)");
+
+    EventUtils.sendKey("ENTER");
+    ok(gEditor.getCaretPosition().line == 12 &&
+       gEditor.getCaretPosition().col == 8,
+      "The editor didn't jump to the correct token. (3)");
+
+    EventUtils.sendKey("ENTER");
+    ok(gEditor.getCaretPosition().line == 19 &&
+       gEditor.getCaretPosition().col == 4,
+      "The editor didn't jump to the correct token. (4)");
+
+    EventUtils.sendKey("RETURN");
+    ok(gEditor.getCaretPosition().line == 2 &&
+       gEditor.getCaretPosition().col == 44,
+      "The editor didn't jump to the correct token. (5)");
+
+
+    write(":bogus@debugger;");
+    ok(gEditor.getCaretPosition().line == 8 &&
+       gEditor.getCaretPosition().col == 2,
+      "The editor didn't jump to the correct token. (7)");
+
+    write(":13@debugger;");
+    ok(gEditor.getCaretPosition().line == 8 &&
+       gEditor.getCaretPosition().col == 2,
+      "The editor didn't jump to the correct token. (7)");
+
+    write(":@debugger;");
+    ok(gEditor.getCaretPosition().line == 8 &&
+       gEditor.getCaretPosition().col == 2,
+      "The editor didn't jump to the correct token. (8)");
+
+    write("::@debugger;");
+    ok(gEditor.getCaretPosition().line == 8 &&
+       gEditor.getCaretPosition().col == 2,
+      "The editor didn't jump to the correct token. (9)");
+
+    write(":::@debugger;");
+    ok(gEditor.getCaretPosition().line == 8 &&
+       gEditor.getCaretPosition().col == 2,
+      "The editor didn't jump to the correct token. (10)");
+
+
+    write(":i am not a number");
+    ok(gEditor.getCaretPosition().line == 8 &&
+       gEditor.getCaretPosition().col == 2,
+      "The editor didn't remain at the correct token. (11)");
+
+    write("@__i do not exist__");
+    ok(gEditor.getCaretPosition().line == 8 &&
+       gEditor.getCaretPosition().col == 2,
+      "The editor didn't remain at the correct token. (12)");
+
+
+    write(":1:2:3:a:b:c:::12");
+    ok(gEditor.getCaretPosition().line == 11 &&
+       gEditor.getCaretPosition().col == 0,
+      "The editor didn't jump to the correct line. (13)");
+
+    write("@don't@find@me@instead@find@debugger");
+    ok(gEditor.getCaretPosition().line == 2 &&
+       gEditor.getCaretPosition().col == 44,
+      "The editor didn't jump to the correct token. (14)");
+
+    EventUtils.sendKey("RETURN");
+    ok(gEditor.getCaretPosition().line == 8 &&
+       gEditor.getCaretPosition().col == 2,
+      "The editor didn't jump to the correct token. (15)");
+
+    EventUtils.sendKey("ENTER");
+    ok(gEditor.getCaretPosition().line == 12 &&
+       gEditor.getCaretPosition().col == 8,
+      "The editor didn't jump to the correct token. (16)");
+
+    EventUtils.sendKey("RETURN");
+    ok(gEditor.getCaretPosition().line == 19 &&
+       gEditor.getCaretPosition().col == 4,
+      "The editor didn't jump to the correct token. (17)");
+
+    EventUtils.sendKey("ENTER");
+    ok(gEditor.getCaretPosition().line == 2 &&
+       gEditor.getCaretPosition().col == 44,
+      "The editor didn't jump to the correct token. (18)");
+
+
+    clear();
+    ok(gEditor.getCaretPosition().line == 2 &&
+       gEditor.getCaretPosition().col == 44,
+      "The editor didn't remain at the correct token. (19)");
+    is(gScripts.visibleItemsCount, 1,
+      "Not all the scripts are shown after the search. (20)");
+
+    closeDebuggerAndFinish(gTab);
+  });
+}
+
+function clear() {
+  gSearchBox.focus();
+  gSearchBox.value = "";
+}
+
+function write(text) {
+  clear();
+
+  for (let i = 0; i < text.length; i++) {
+    EventUtils.sendChar(text[i]);
+  }
+  dump("editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
+}
+
+registerCleanupFunction(function() {
+  removeTab(gTab);
+  gPane = null;
+  gTab = null;
+  gDebuggee = null;
+  gDebugger = null;
+  gEditor = null;
+  gScripts = null;
+  gSearchBox = null;
+  gMenulist = null;
+});
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-02.js
@@ -0,0 +1,146 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
+
+var gPane = null;
+var gTab = null;
+var gDebuggee = null;
+var gDebugger = null;
+var gEditor = null;
+var gScripts = null;
+var gSearchBox = null;
+var gMenulist = null;
+
+function test()
+{
+  let scriptShown = false;
+  let framesAdded = false;
+
+  debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
+    gTab = aTab;
+    gDebuggee = aDebuggee;
+    gPane = aPane;
+    gDebugger = gPane.debuggerWindow;
+
+    gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
+      framesAdded = true;
+      runTest();
+    });
+
+    gDebuggee.firstCall();
+  });
+
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    let url = aEvent.detail.url;
+    if (url.indexOf("-02.js") != -1) {
+      scriptShown = true;
+      window.removeEventListener(aEvent.type, _onEvent);
+      runTest();
+    }
+  });
+
+  function runTest()
+  {
+    if (scriptShown && framesAdded) {
+      Services.tm.currentThread.dispatch({ run: testScriptSearching }, 0);
+    }
+  }
+}
+
+function testScriptSearching() {
+  gDebugger.DebuggerController.activeThread.resume(function() {
+    gEditor = gDebugger.DebuggerView.editor;
+    gScripts = gDebugger.DebuggerView.Scripts;
+    gSearchBox = gScripts._searchbox;
+    gMenulist = gScripts._scripts;
+
+    firstSearch();
+  });
+}
+
+function firstSearch() {
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    dump("Current script url:\n" + aEvent.detail.url + "\n");
+    dump("Debugger editor text:\n" + gEditor.getText() + "\n");
+
+    let url = aEvent.detail.url;
+    if (url.indexOf("-01.js") != -1) {
+      window.removeEventListener(aEvent.type, _onEvent);
+
+      executeSoon(function() {
+        dump("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
+        ok(gEditor.getCaretPosition().line == 4 &&
+           gEditor.getCaretPosition().col == 0,
+          "The editor didn't jump to the correct line. (1)");
+        is(gScripts.visibleItemsCount, 1,
+          "Not all the correct scripts are shown after the search. (1)");
+
+        secondSearch();
+      });
+    }
+  });
+  write(".*-01\.js:5");
+}
+
+function secondSearch() {
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    dump("Current script url:\n" + aEvent.detail.url + "\n");
+    dump("Debugger editor text:\n" + gEditor.getText() + "\n");
+
+    let url = aEvent.detail.url;
+    if (url.indexOf("-02.js") != -1) {
+      window.removeEventListener(aEvent.type, _onEvent);
+
+      executeSoon(function() {
+        dump("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
+        ok(gEditor.getCaretPosition().line == 5 &&
+           gEditor.getCaretPosition().col == 8,
+          "The editor didn't jump to the correct line. (2)");
+        is(gScripts.visibleItemsCount, 1,
+          "Not all the correct scripts are shown after the search. (2)");
+
+        finalCheck();
+      });
+    }
+  });
+  write(".*-02\.js@debugger;");
+}
+
+function finalCheck() {
+  clear();
+  ok(gEditor.getCaretPosition().line == 5 &&
+     gEditor.getCaretPosition().col == 8,
+    "The editor didn't remain at the correct token. (3)");
+  is(gScripts.visibleItemsCount, 2,
+    "Not all the scripts are shown after the search. (3)");
+
+  closeDebuggerAndFinish(gTab);
+}
+
+function clear() {
+  gSearchBox.focus();
+  gSearchBox.value = "";
+}
+
+function write(text) {
+  clear();
+
+  for (let i = 0; i < text.length; i++) {
+    EventUtils.sendChar(text[i]);
+  }
+  dump("editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
+}
+
+registerCleanupFunction(function() {
+  removeTab(gTab);
+  gPane = null;
+  gTab = null;
+  gDebuggee = null;
+  gDebugger = null;
+  gEditor = null;
+  gScripts = null;
+  gSearchBox = null;
+  gMenulist = null;
+});
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-sorting.js
@@ -0,0 +1,124 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+var gPane = null;
+var gTab = null;
+var gDebuggee = null;
+var gDebugger = null;
+
+function test() {
+  debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
+    gTab = aTab;
+    gDebuggee = aDebuggee;
+    gPane = aPane;
+    gDebugger = gPane.debuggerWindow;
+
+    testSimpleCall();
+  });
+}
+
+function testSimpleCall() {
+  gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
+    Services.tm.currentThread.dispatch({ run: function() {
+      resumeAndFinish();
+    }}, 0);
+  });
+
+  gDebuggee.simpleCall();
+}
+
+function resumeAndFinish() {
+  gDebugger.DebuggerController.activeThread.resume(function() {
+    checkScriptsOrder();
+    addScriptsAndCheckOrder(1, function() {
+      addScriptsAndCheckOrder(2, function() {
+        addScriptsAndCheckOrder(3, function() {
+          closeDebuggerAndFinish(gTab);
+        });
+      });
+    });
+  });
+}
+
+function addScriptsAndCheckOrder(method, callback) {
+  let vs = gDebugger.DebuggerView.Scripts;
+  let ss = gDebugger.DebuggerController.SourceScripts;
+  vs.empty();
+  vs._scripts.removeEventListener("select", vs._onScriptsChange, false);
+
+  let urls = [
+    { href: "ici://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: "si://interesting.address.moc/random/", leaf: "script.js" },
+    { href: "si://interesting.address.moc/random/", leaf: "x/script.js" },
+    { href: "si://interesting.address.moc/random/", leaf: "x/y/script.js?a=1" },
+    { href: "si://interesting.address.moc/random/x/", leaf: "y/script.js?a=1&b=2" },
+    { href: "si://interesting.address.moc/random/x/y/", leaf: "script.js?a=1&b=2&c=3" }
+  ];
+
+  urls.sort(function(a, b) {
+    return Math.random() - 0.5;
+  });
+
+  switch (method) {
+    case 1:
+      urls.forEach(function(url) {
+        let loc = url.href + url.leaf;
+        vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc });
+      });
+      vs.commitScripts();
+      break;
+
+    case 2:
+      urls.forEach(function(url) {
+        let loc = url.href + url.leaf;
+        vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc }, true);
+      });
+      break;
+
+    case 3:
+      let i = 0
+      for (; i < urls.length / 2; i++) {
+        let url = urls[i];
+        let loc = url.href + url.leaf;
+        vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc });
+      }
+      vs.commitScripts();
+
+      for (; i < urls.length; i++) {
+        let url = urls[i];
+        let loc = url.href + url.leaf;
+        vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc }, true);
+      }
+      break;
+  }
+
+  executeSoon(function() {
+    checkScriptsOrder(method);
+    callback();
+  });
+}
+
+function checkScriptsOrder(method) {
+  let labels = gDebugger.DebuggerView.Scripts.scriptLabels;
+  let sorted = labels.reduce(function(prev, curr, index, array) {
+    return array[index - 1] < array[index];
+  });
+
+  ok(sorted,
+    "Using method " + method + ", " +
+    "the scripts weren't in the correct order: " + labels.toSource());
+
+  return sorted;
+}
+
+registerCleanupFunction(function() {
+  removeTab(gTab);
+  gPane = null;
+  gTab = null;
+  gDebuggee = null;
+  gDebugger = null;
+});
--- a/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js
+++ b/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js
@@ -17,42 +17,48 @@ var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 var gScripts = null;
 
 function test()
 {
   let scriptShown = false;
   let framesAdded = false;
+  let testStarted = false;
+  let resumed = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.debuggerWindow;
+    resumed = true;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
-      runTest();
+      executeSoon(startTest);
     });
-    gDebuggee.firstCall();
+
+    executeSoon(function() {
+      gDebuggee.firstCall();
+    });
   });
 
-  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
-    let url = aEvent.detail.url;
-    if (url.indexOf("editor-mode") != -1) {
-      scriptShown = true;
-      window.removeEventListener(aEvent.type, _onEvent);
-      runTest();
-    }
-  });
+  function onScriptShown(aEvent) {
+    scriptShown = aEvent.detail.url.indexOf("test-editor-mode") != -1;
+    executeSoon(startTest);
+  }
 
-  function runTest()
+  window.addEventListener("Debugger:ScriptShown", onScriptShown);
+
+  function startTest()
   {
-    if (scriptShown && framesAdded) {
+    if (scriptShown && framesAdded && resumed && !testStarted) {
+      window.removeEventListener("Debugger:ScriptShown", onScriptShown);
+      testStarted = true;
       Services.tm.currentThread.dispatch({ run: testScriptsDisplay }, 0);
     }
   }
 }
 
 function testScriptsDisplay() {
   gScripts = gDebugger.DebuggerView.Scripts._scripts;
 
--- a/browser/devtools/debugger/test/head.js
+++ b/browser/devtools/debugger/test/head.js
@@ -87,22 +87,35 @@ function attach_thread_actor_for_url(aCl
     });
   });
 }
 
 function debug_tab_pane(aURL, aOnDebugging)
 {
   let tab = addTab(aURL, function() {
     gBrowser.selectedTab = gTab;
-
     let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
 
     let pane = DebuggerUI.toggleDebugger();
     pane._frame.addEventListener("Debugger:Connecting", function dbgConnected() {
       pane._frame.removeEventListener("Debugger:Connecting", dbgConnected, true);
 
       // Wait for the initial resume...
       pane.debuggerWindow.gClient.addOneTimeListener("resumed", function() {
         aOnDebugging(tab, debuggee, pane);
       });
     }, true);
   });
 }
+
+function remote_debug_tab_pane(aURL, aOnClosing, aOnDebugging)
+{
+  let tab = addTab(aURL, function() {
+    gBrowser.selectedTab = gTab;
+    let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
+
+    DebuggerUI.toggleRemoteDebugger(aOnClosing, function dbgRan(process) {
+
+      // Wait for the remote debugging process to start...
+      aOnDebugging(tab, debuggee, process);
+    });
+  });
+}
--- a/browser/devtools/highlighter/inspector.jsm
+++ b/browser/devtools/highlighter/inspector.jsm
@@ -288,59 +288,64 @@ InspectorUI.prototype = {
 
   /**
    * Add a tooltip to the Inspect and Markup buttons.
    * The tooltips include the related keyboard shortcut.
    */
   buildButtonsTooltip: function IUI_buildButtonsTooltip()
   {
     let keysbundle = Services.strings.createBundle("chrome://global-platform/locale/platformKeys.properties");
+    let separator = keysbundle.GetStringFromName("MODIFIER_SEPARATOR");
+
+    let button, tooltip;
 
     // Inspect Button - the shortcut string is built from the <key> element
 
     let key = this.chromeDoc.getElementById("key_inspect");
 
-    let modifiersAttr = key.getAttribute("modifiers");
+    if (key) {
+      let modifiersAttr = key.getAttribute("modifiers");
 
-    let combo = [];
+      let combo = [];
 
-    if (modifiersAttr.match("accel"))
+      if (modifiersAttr.match("accel"))
 #ifdef XP_MACOSX
-      combo.push(keysbundle.GetStringFromName("VK_META"));
+        combo.push(keysbundle.GetStringFromName("VK_META"));
 #else
-      combo.push(keysbundle.GetStringFromName("VK_CONTROL"));
+        combo.push(keysbundle.GetStringFromName("VK_CONTROL"));
 #endif
-    if (modifiersAttr.match("shift"))
-      combo.push(keysbundle.GetStringFromName("VK_SHIFT"));
-    if (modifiersAttr.match("alt"))
-      combo.push(keysbundle.GetStringFromName("VK_ALT"));
-    if (modifiersAttr.match("ctrl"))
-      combo.push(keysbundle.GetStringFromName("VK_CONTROL"));
-    if (modifiersAttr.match("meta"))
-      combo.push(keysbundle.GetStringFromName("VK_META"));
+      if (modifiersAttr.match("shift"))
+        combo.push(keysbundle.GetStringFromName("VK_SHIFT"));
+      if (modifiersAttr.match("alt"))
+        combo.push(keysbundle.GetStringFromName("VK_ALT"));
+      if (modifiersAttr.match("ctrl"))
+        combo.push(keysbundle.GetStringFromName("VK_CONTROL"));
+      if (modifiersAttr.match("meta"))
+        combo.push(keysbundle.GetStringFromName("VK_META"));
 
-    combo.push(key.getAttribute("key"));
-
-    let separator = keysbundle.GetStringFromName("MODIFIER_SEPARATOR");
+      combo.push(key.getAttribute("key"));
 
-    let tooltip = this.strings.formatStringFromName("inspectButton.tooltiptext",
-      [combo.join(separator)], 1);
-    let button = this.chromeDoc.getElementById("inspector-inspect-toolbutton");
+      tooltip = this.strings.formatStringFromName("inspectButtonWithShortcutKey.tooltip",
+        [combo.join(separator)], 1);
+    } else {
+      tooltip = this.strings.GetStringFromName("inspectButton.tooltip");
+    }
+
+    button = this.chromeDoc.getElementById("inspector-inspect-toolbutton");
     button.setAttribute("tooltiptext", tooltip);
 
     // Markup Button - the shortcut string is built from the accesskey attribute
 
     button = this.chromeDoc.getElementById("inspector-treepanel-toolbutton");
 #ifdef XP_MACOSX
     // On Mac, no accesskey
     tooltip = this.strings.GetStringFromName("markupButton.tooltip");
 #else
     let altString = keysbundle.GetStringFromName("VK_ALT");
     let accesskey = button.getAttribute("accesskey");
-    let separator = keysbundle.GetStringFromName("MODIFIER_SEPARATOR");
     let shortcut = altString + separator + accesskey;
     tooltip = this.strings.formatStringFromName("markupButton.tooltipWithAccesskey",
       [shortcut], 1);
 #endif
     button.setAttribute("tooltiptext", tooltip);
 
   },
 
--- a/browser/devtools/shared/Templater.jsm
+++ b/browser/devtools/shared/Templater.jsm
@@ -37,43 +37,64 @@
  * ***** END LICENSE BLOCK ***** */
 
 
 var EXPORTED_SYMBOLS = [ "Templater", "template" ];
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 const Node = Components.interfaces.nsIDOMNode;
 
+/**
+ * For full documentation, see:
+ * https://github.com/mozilla/domtemplate/blob/master/README.md
+ */
+
 // WARNING: do not 'use_strict' without reading the notes in _envEval();
 
 /**
  * Begin a new templating process.
  * @param node A DOM element or string referring to an element's id
  * @param data Data to use in filling out the template
  * @param options Options to customize the template processing. One of:
  * - allowEval: boolean (default false) Basic template interpolations are
- * either property paths (e.g. ${a.b.c.d}), however if allowEval=true then we
- * allow arbitrary JavaScript
+ *   either property paths (e.g. ${a.b.c.d}), or if allowEval=true then we
+ *   allow arbitrary JavaScript
+ * - stack: string or array of strings (default empty array) The template
+ *   engine maintains a stack of tasks to help debug where it is. This allows
+ *   this stack to be prefixed with a template name
+ * - blankNullUndefined: By default DOMTemplate exports null and undefined
+ *   values using the strings 'null' and 'undefined', which can be helpful for
+ *   debugging, but can introduce unnecessary extra logic in a template to
+ *   convert null/undefined to ''. By setting blankNullUndefined:true, this
+ *   conversion is handled by DOMTemplate
  */
 function template(node, data, options) {
   var template = new Templater(options || {});
   template.processNode(node, data);
   return template;
 }
 
 /**
  * Construct a Templater object. Use template() in preference to this ctor.
  * @deprecated Use template(node, data, options);
  */
 function Templater(options) {
   if (options == null) {
     options = { allowEval: true };
   }
   this.options = options;
-  this.stack = [];
+  if (options.stack && Array.isArray(options.stack)) {
+    this.stack = options.stack;
+  }
+  else if (typeof options.stack === 'string') {
+    this.stack = [ options.stack ];
+  }
+  else {
+    this.stack = [];
+  }
 }
 
 /**
  * Cached regex used to find ${...} sections in some text.
  * Performance note: This regex uses ( and ) to capture the 'script' for
  * further processing. Not all of the uses of this regex use this feature so
  * if use of the capturing group is a performance drain then we should split
  * this regex in two.
@@ -85,17 +106,17 @@ Templater.prototype._templateRegion = /\
  * See Templater._processTextNode() for details.
  */
 Templater.prototype._splitSpecial = /\uF001|\uF002/;
 
 /**
  * Cached regex used to detect if a script is capable of being interpreted
  * using Template._property() or if we need to use Template._envEval()
  */
-Templater.prototype._isPropertyScript = /^[a-zA-Z0-9.]*$/;
+Templater.prototype._isPropertyScript = /^[_a-zA-Z0-9.]*$/;
 
 /**
  * Recursive function to walk the tree processing the attributes as it goes.
  * @param node the node to process. If you pass a string in instead of a DOM
  * element, it is assumed to be an id for use with document.getElementById()
  * @param data the data to use for node processing.
  */
 Templater.prototype.processNode = function(node, data) {
@@ -148,17 +169,21 @@ Templater.prototype.processNode = functi
             var capture = node.hasAttribute('capture' + name.substring(2));
             node.addEventListener(name.substring(2), func, capture);
             if (capture) {
               node.removeAttribute('capture' + name.substring(2));
             }
           } else {
             // Replace references in all other attributes
             var newValue = value.replace(this._templateRegion, function(path) {
-              return this._envEval(path.slice(2, -1), data, value);
+              var insert = this._envEval(path.slice(2, -1), data, value);
+              if (this.options.blankNullUndefined && insert == null) {
+                insert = '';
+              }
+              return insert;
             }.bind(this));
             // Remove '_' prefix of attribute names so the DOM won't try
             // to use them before we've processed the template
             if (name.charAt(0) === '_') {
               node.removeAttribute(name);
               node.setAttribute(name.substring(1), newValue);
             } else if (value !== newValue) {
               attrs[i].value = newValue;
@@ -172,17 +197,17 @@ Templater.prototype.processNode = functi
 
     // Loop through our children calling processNode. First clone them, so the
     // set of nodes that we visit will be unaffected by additions or removals.
     var childNodes = Array.prototype.slice.call(node.childNodes);
     for (var j = 0; j < childNodes.length; j++) {
       this.processNode(childNodes[j], data);
     }
 
-    if (node.nodeType === Node.TEXT_NODE) {
+    if (node.nodeType === 3 /*Node.TEXT_NODE*/) {
       this._processTextNode(node, data);
     }
   } finally {
     delete data.__element;
     this.stack.pop();
   }
 };
 
@@ -342,40 +367,51 @@ Templater.prototype._processTextNode = f
     parts.forEach(function(part) {
       if (part === null || part === undefined || part === '') {
         return;
       }
       if (part.charAt(0) === '$') {
         part = this._envEval(part.slice(1), data, node.data);
       }
       this._handleAsync(part, node, function(reply, siblingNode) {
-        reply = this._toNode(reply, siblingNode.ownerDocument);
-        siblingNode.parentNode.insertBefore(reply, siblingNode);
+        var doc = siblingNode.ownerDocument;
+        if (reply == null) {
+          reply = this.options.blankNullUndefined ? '' : '' + reply;
+        }
+        if (typeof reply.cloneNode === 'function') {
+          // i.e. if (reply instanceof Element) { ...
+          reply = this._maybeImportNode(reply, doc);
+          siblingNode.parentNode.insertBefore(reply, siblingNode);
+        } else if (typeof reply.item === 'function' && reply.length) {
+          // if thing is a NodeList, then import the children
+          for (var i = 0; i < reply.length; i++) {
+            var child = this._maybeImportNode(reply.item(i), doc);
+            siblingNode.parentNode.insertBefore(child, siblingNode);
+          }
+        }
+        else {
+          // if thing isn't a DOM element then wrap its string value in one
+          reply = doc.createTextNode(reply.toString());
+          siblingNode.parentNode.insertBefore(reply, siblingNode);
+        }
+
       }.bind(this));
     }, this);
     node.parentNode.removeChild(node);
   }
 };
 
 /**
- * Helper to convert a 'thing' to a DOM Node.
- * This is (obviously) a no-op for DOM Elements (which are detected using
- * 'typeof thing.cloneNode !== "function"' (is there a better way that will
- * work in all environments, including a .jsm?)
- * Non DOM elements are converted to a string and wrapped in a TextNode.
+ * Return node or a import of node, if it's not in the given document
+ * @param node The node that we want to be properly owned
+ * @param doc The document that the given node should belong to
+ * @return A node that belongs to the given document
  */
-Templater.prototype._toNode = function(thing, document) {
-  if (thing == null) {
-    thing = '' + thing;
-  }
-  // if thing isn't a DOM element then wrap its string value in one
-  if (typeof thing.cloneNode !== 'function') {
-    thing = document.createTextNode(thing.toString());
-  }
-  return thing;
+Templater.prototype._maybeImportNode = function(node, doc) {
+  return node.ownerDocument === doc ? node : doc.importNode(node, true);
 };
 
 /**
  * A function to handle the fact that some nodes can be promises, so we check
  * and resolve if needed using a marker node to keep our place before calling
  * an inserter function.
  * @param thing The object which could be real data or a promise of real data
  * we use it directly if it's not a promise, or resolve it if it is.
@@ -424,38 +460,38 @@ Templater.prototype._stripBraces = funct
  * a string to be cut into an array using <tt>split('.')</tt>
  * @param data the data to use for node processing
  * @param newValue (optional) If defined, this value will replace the
  * original value for the data at the path specified.
  * @return The value pointed to by <tt>path</tt> before any
  * <tt>newValue</tt> is applied.
  */
 Templater.prototype._property = function(path, data, newValue) {
-  this.stack.push(path);
   try {
     if (typeof path === 'string') {
       path = path.split('.');
     }
     var value = data[path[0]];
     if (path.length === 1) {
       if (newValue !== undefined) {
         data[path[0]] = newValue;
       }
       if (typeof value === 'function') {
         return value.bind(data);
       }
       return value;
     }
     if (!value) {
-      this._handleError('Can\'t find path=' + path);
+      this._handleError('"' + path[0] + '" is undefined');
       return null;
     }
     return this._property(path.slice(1), value, newValue);
-  } finally {
-    this.stack.pop();
+  } catch (ex) {
+    this._handleError('Path error with \'' + path + '\'', ex);
+    return '${' + path + '}';
   }
 };
 
 /**
  * Like eval, but that creates a context of the variables in <tt>env</tt> in
  * which the script is evaluated.
  * WARNING: This script uses 'with' which is generally regarded to be evil.
  * The alternative is to create a Function at runtime that takes X parameters
@@ -464,47 +500,45 @@ Templater.prototype._property = function
  * @param script The string to be evaluated.
  * @param data The environment in which to eval the script.
  * @param frame Optional debugging string in case of failure.
  * @return The return value of the script, or the error message if the script
  * execution failed.
  */
 Templater.prototype._envEval = function(script, data, frame) {
   try {
-    this.stack.push(frame);
+    this.stack.push(frame.replace(/\s+/g, ' '));
     if (this._isPropertyScript.test(script)) {
       return this._property(script, data);
     } else {
       if (!this.options.allowEval) {
         this._handleError('allowEval is not set, however \'' + script + '\'' +
             ' can not be resolved using a simple property path.');
         return '${' + script + '}';
       }
       with (data) {
         return eval(script);
       }
     }
   } catch (ex) {
-    this._handleError('Template error evaluating \'' + script + '\'' +
-        ' environment=' + Object.keys(data).join(', '), ex);
+    this._handleError('Template error evaluating \'' + script + '\'', ex);
     return '${' + script + '}';
   } finally {
     this.stack.pop();
   }
 };
 
 /**
  * A generic way of reporting errors, for easy overloading in different
  * environments.
  * @param message the error message to report.
  * @param ex optional associated exception.
  */
 Templater.prototype._handleError = function(message, ex) {
-  this._logError(message);
-  this._logError('In: ' + this.stack.join(' > '));
+  this._logError(message + ' (In: ' + this.stack.join(' > ') + ')');
   if (ex) {
     this._logError(ex);
   }
 };
 
 
 /**
  * A generic way of reporting errors, for easy overloading in different
--- a/browser/devtools/shared/test/browser_templater_basic.js
+++ b/browser/devtools/shared/test/browser_templater_basic.js
@@ -1,18 +1,22 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the DOM Template engine works properly
 
-let tempScope = {};
-Cu.import("resource:///modules/devtools/Templater.jsm", tempScope);
-Cu.import("resource:///modules/devtools/Promise.jsm", tempScope);
-let template = tempScope.template;
-let Promise = tempScope.Promise;
+/*
+ * These tests run both in Mozilla/Mochitest and plain browsers (as does
+ * domtemplate)
+ * We should endevour to keep the source in sync.
+ */
+
+var imports = {};
+Cu.import("resource:///modules/devtools/Templater.jsm", imports);
+Cu.import("resource:///modules/devtools/Promise.jsm", imports);
 
 function test() {
   addTab("http://example.com/browser/browser/devtools/shared/test/browser_templater_basic.html", function() {
     info("Starting DOM Templater Tests");
     runTest(0);
   });
 }
 
@@ -20,17 +24,17 @@ function runTest(index) {
   var options = tests[index] = tests[index]();
   var holder = content.document.createElement('div');
   holder.id = options.name;
   var body = content.document.body;
   body.appendChild(holder);
   holder.innerHTML = options.template;
 
   info('Running ' + options.name);
-  template(holder, options.data, options.options);
+  imports.template(holder, options.data, options.options);
 
   if (typeof options.result == 'string') {
     is(holder.innerHTML, options.result, options.name);
   }
   else {
     ok(holder.innerHTML.match(options.result), options.name);
   }
 
@@ -233,18 +237,50 @@ var tests = [
     options: { allowEval: true },
     result: '<p>2</p>'
   };},
 
   function() { return {
     name: 'propertyFail',
     template: '<p>${Math.max(1, 2)}</p>',
     result: '<p>${Math.max(1, 2)}</p>'
+  };},
+
+  // Bug 723431: DOMTemplate should allow customisation of display of
+  // null/undefined values
+  function() { return {
+    name: 'propertyUndefAttrFull',
+    template: '<p>${nullvar}|${undefinedvar1}|${undefinedvar2}</p>',
+    data: { nullvar: null, undefinedvar1: undefined },
+    result: '<p>null|undefined|undefined</p>'
+  };},
+
+  function() { return {
+    name: 'propertyUndefAttrBlank',
+    template: '<p>${nullvar}|${undefinedvar1}|${undefinedvar2}</p>',
+    data: { nullvar: null, undefinedvar1: undefined },
+    options: { blankNullUndefined: true },
+    result: '<p>||</p>'
+  };},
+
+  function() { return {
+    name: 'propertyUndefAttrFull',
+    template: '<div><p value="${nullvar}"></p><p value="${undefinedvar1}"></p><p value="${undefinedvar2}"></p></div>',
+    data: { nullvar: null, undefinedvar1: undefined },
+    result: '<div><p value="null"></p><p value="undefined"></p><p value="undefined"></p></div>'
+  };},
+
+  function() { return {
+    name: 'propertyUndefAttrBlank',
+    template: '<div><p value="${nullvar}"></p><p value="${undefinedvar1}"></p><p value="${undefinedvar2}"></p></div>',
+    data: { nullvar: null, undefinedvar1: undefined },
+    options: { blankNullUndefined: true },
+    result: '<div><p value=""></p><p value=""></p><p value=""></p></div>'
   };}
 ];
 
 function delayReply(data) {
-  var p = new Promise();
+  var p = new imports.Promise();
   executeSoon(function() {
     p.resolve(data);
   });
   return p;
 }
--- a/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
@@ -6,16 +6,24 @@
   - You want to make that choice consistent across the developer tools.
   - A good criteria is the language in which you'd find the best
   - documentation on web development on the web. -->
 
 <!-- LOCALIZATION NOTE (debuggerMenu.label): This is the label for the
   -  application menu item that opens the debugger UI. -->
 <!ENTITY debuggerMenu.label          "Script Debugger">
 
+<!-- LOCALIZATION NOTE (remoteDebuggerMenu.label): This is the label for the
+  -  application menu item that opens the remote debugger UI. -->
+<!ENTITY remoteDebuggerMenu.label    "Remote Debugger">
+
+<!-- LOCALIZATION NOTE (chromeDebuggerMenu.label): This is the label for the
+  -  application menu item that opens the browser debugger UI. -->
+<!ENTITY chromeDebuggerMenu.label   "Browser Debugger">
+
 <!-- LOCALIZATION NOTE (debuggerMenu.commandkey): This is the command key that
   -  launches the debugger UI. Do not translate this one! -->
 <!ENTITY debuggerMenu.commandkey     "S">
 
 <!-- LOCALIZATION NOTE (debuggerUI.closeButton): This is the label for the
   -  button that closes the debugger UI. -->
 <!ENTITY debuggerUI.closeButton      "Close">
 
@@ -39,8 +47,12 @@
   -  widget that displays the source code for the script that is currently
   -  being inspected in the debugger. -->
 <!ENTITY debuggerUI.scriptTitle      "Script">
 
 <!-- LOCALIZATION NOTE (debuggerUI.propertiesTitle): This is the label for the
   -  widget that displays the variables in the various available scopes in the
   -  debugger. -->
 <!ENTITY debuggerUI.propertiesTitle  "Scope variables">
+
+<!-- LOCALIZATION NOTE (debuggerUI.emptyFilterText): This is the text that
+  -  appears in the filter text box when it is empty. -->
+<!ENTITY debuggerUI.emptyFilterText  "Filter scripts">
--- a/browser/locales/en-US/chrome/browser/devtools/debugger.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/debugger.properties
@@ -33,19 +33,19 @@ globalScope=Global
 # LOCALIZATION NOTE (withScope): The label that is displayed in the variables
 # pane as a header on the container for identifiers in a with block.
 withScope=With block
 
 # LOCALIZATION NOTE (closureScope): The label that is displayed in the variables
 # pane as a header on container for identifiers in a closure scope.
 closureScope=Closure
 
-# LOCALIZATION NOTE (emptyText): The text that is displayed in the stack frames
-# list when there are no frames to display.
-emptyText=Empty
+# LOCALIZATION NOTE (emptyStackText): The text that is displayed in the stack
+# frames list when there are no frames to display.
+emptyStackText=No stacks to display.
 
 # LOCALIZATION NOTE (loadingText): The text that is displayed in the script
 # editor when the laoding process has started but there is no file to display
 # yet.
 loadingText=Loading\u2026
 
 # LOCALIZATION NOTE (loadingError):
 # This is the error message that is displayed on failed attempts to load an
--- a/browser/locales/en-US/chrome/browser/devtools/inspector.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/inspector.properties
@@ -15,21 +15,26 @@ confirmNavigationAway.buttonLeave=Leave 
 confirmNavigationAway.buttonLeaveAccesskey=L
 confirmNavigationAway.buttonStay=Stay on Page
 confirmNavigationAway.buttonStayAccesskey=S
 
 breadcrumbs.siblings=Siblings
 # LOCALIZATION NOTE (htmlPanel): Used in the Inspector tool's openInspectorUI
 # method when registering the HTML panel.
 
-# LOCALIZATION NOTE (inspectButton.tooltiptext):
+# LOCALIZATION NOTE (inspectButtonWithShortcutKey.tooltip):
 # This button appears in the Inspector Toolbar. inspectButton is stateful,
 # if it's pressed users can select an element with the mouse.
 # %S is the keyboard shortcut.
-inspectButton.tooltiptext=Select element with mouse (%S)
+inspectButtonWithShortcutKey.tooltip=Select element with mouse (%S)
+
+# LOCALIZATION NOTE (inspectButton.tooltip):
+# Same as inspectButtonWithShortcutKey.tooltip but used when an add-on
+# overrides the shortcut key.
+inspectButton.tooltip=Select element with mouse
 
 # LOCALIZATION NOTE (markupButton.*):
 # This button is the button located at the beginning of the breadcrumbs
 # in the inspector toolbar. Its tooltip is built dynamically.
 # markupButton.tooltip is used on Mac.
 # On Windows and Linux, we use markupButton.tooltipWithAccesskey, where we append
 # the keyboard shortcut.
 markupButton.tooltip=Markup Panel
--- a/browser/locales/en-US/chrome/browser/places/places.dtd
+++ b/browser/locales/en-US/chrome/browser/places/places.dtd
@@ -18,21 +18,16 @@
 <!ENTITY view.sort.accesskey            "S">
 <!ENTITY view.unsorted.label            "Unsorted">
 <!ENTITY view.unsorted.accesskey        "U">
 <!ENTITY view.sortAscending.label       "A > Z Sort Order">
 <!ENTITY view.sortAscending.accesskey   "A">
 <!ENTITY view.sortDescending.label      "Z > A Sort Order">
 <!ENTITY view.sortDescending.accesskey  "Z">
 
-<!ENTITY cmd.findInBookmarks.label      "Find in Bookmarks…">
-<!ENTITY cmd.findInBookmarks.accesskey  "F">
-<!ENTITY cmd.findCurrent.label          "Find in Current Collection…">
-<!ENTITY cmd.findCurrent.accesskey      "i">
-
 <!ENTITY importBookmarksFromHTML.label     "Import Bookmarks from HTML…">
 <!ENTITY importBookmarksFromHTML.accesskey "I">
 <!ENTITY exportBookmarksToHTML.label       "Export Bookmarks to HTML…">
 <!ENTITY exportBookmarksToHTML.accesskey   "E">
 <!ENTITY importOtherBrowser.label          "Import Data from Another Browser…">
 <!ENTITY importOtherBrowser.accesskey      "A">
 
 <!ENTITY cmd.backup.label               "Backup…">
--- a/browser/locales/en-US/chrome/browser/places/places.properties
+++ b/browser/locales/en-US/chrome/browser/places/places.properties
@@ -39,17 +39,16 @@ view.sortBy.lastModified.label=Sort by L
 view.sortBy.lastModified.accesskey=M
 view.sortBy.tags.label=Sort by Tags
 view.sortBy.tags.accesskey=T
 
 searchBookmarks=Search Bookmarks
 searchHistory=Search History
 searchDownloads=Search Downloads
 searchCurrentDefault=Search in '%S'
-findInPrefix=Find in '%S'…
 
 tabs.openWarningTitle=Confirm open
 tabs.openWarningMultipleBranded=You are about to open %S tabs.  This might slow down %S while the pages are loading.  Are you sure you want to continue?
 tabs.openButtonMultiple=Open tabs
 tabs.openWarningPromptMeBranded=Warn me when opening multiple tabs might slow down %S
 
 SelectImport=Import Bookmarks File
 EnterExport=Export Bookmarks File
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1255,16 +1255,17 @@ toolbar[iconsize="small"] #feed-button {
 #notification-popup-box:-moz-locale-dir(rtl),
 .notification-anchor-icon:-moz-locale-dir(rtl) {
   -moz-transform: scaleX(-1);
 }
 
 .notification-anchor-icon {
   width: 16px;
   height: 16px;
+  margin: 0 2px;
 }
 
 .notification-anchor-icon:-moz-focusring {
   outline: 1px dotted -moz-DialogText;
 }
 
 #default-notification-icon {
   list-style-image: url(chrome://global/skin/icons/information-16.png);
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -2316,16 +2316,17 @@ toolbarbutton.bookmark-item[dragover="tr
 #notification-popup-box:-moz-locale-dir(rtl),
 .notification-anchor-icon:-moz-locale-dir(rtl) {
   -moz-transform: scaleX(-1);
 }
 
 .notification-anchor-icon {
   width: 16px;
   height: 16px;
+  margin: 0 2px;
 }
 
 .notification-anchor-icon:-moz-focusring {
   outline: 1px dotted -moz-DialogText;
   outline-offset: -3px;
 }
 
 #default-notification-icon {
--- a/build/autoconf/compiler-opts.m4
+++ b/build/autoconf/compiler-opts.m4
@@ -1,10 +1,58 @@
 dnl Add compiler specific options
 
+AC_DEFUN([MOZ_DEFAULT_COMPILER],
+[
+dnl Default to MSVC for win32 and gcc-4.2 for darwin
+dnl ==============================================================
+if test -z "$CROSS_COMPILE"; then
+case "$target" in
+*-mingw*)
+    if test -z "$CC"; then CC=cl; fi
+    if test -z "$CXX"; then CXX=cl; fi
+    if test -z "$CPP"; then CPP="cl -E -nologo"; fi
+    if test -z "$CXXCPP"; then CXXCPP="cl -TP -E -nologo"; ac_cv_prog_CXXCPP="$CXXCPP"; fi
+    if test -z "$LD"; then LD=link; fi
+    if test -z "$AS"; then
+        case "${target_cpu}" in
+        i*86)
+            AS=ml;
+            ;;
+        x86_64)
+            AS=ml64;
+            ;;
+        esac
+    fi
+    if test -z "$MIDL"; then MIDL=midl; fi
+
+    # need override this flag since we don't use $(LDFLAGS) for this.
+    if test -z "$HOST_LDFLAGS" ; then
+        HOST_LDFLAGS=" "
+    fi
+    ;;
+*-darwin*)
+    # we prefer gcc-4.2 over gcc on older darwin, so
+    # use that specific version if it's available.
+    # On newer versions of darwin, gcc is llvm-gcc while gcc-4.2 is the plain
+    # one, so we also try that first. If that fails, we fall back to clang
+    # as llvm-gcc is an unsupported dead end.
+    MOZ_PATH_PROGS(CC, $CC gcc-4.2 clang gcc)
+    MOZ_PATH_PROGS(CXX, $CXX g++-4.2 clang++ g++)
+    IS_LLVM_GCC=$($CC -v 2>&1 | grep llvm-gcc)
+    if test -n "$IS_LLVM_GCC"
+    then
+      echo llvm-gcc is known to be broken, please use gcc-4.2 or clang.
+      exit 1
+    fi
+    ;;
+esac
+fi
+])
+
 AC_DEFUN([MOZ_COMPILER_OPTS],
 [
 if test "$CLANG_CXX"; then
     ## We disable return-type-c-linkage because jsval is defined as a C++ type but is
     ## returned by C functions. This is possible because we use knowledge about the ABI
     ## to typedef it to a C type with the same layout when the headers are included
     ## from C.
     _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage"
--- a/build/mobile/robocop/FennecNativeDriver.java.in
+++ b/build/mobile/robocop/FennecNativeDriver.java.in
@@ -65,17 +65,17 @@ import android.opengl.GLSurfaceView;
 import android.view.View;
 import android.util.Log;
 
 import org.json.*;
 
 import com.jayway.android.robotium.solo.Solo;
 
 public class FennecNativeDriver implements Driver {
-    private static final int FRAME_TIME_THRESHOLD = 17;     // allow 17ms per frame (~60fps)
+    private static final int FRAME_TIME_THRESHOLD = 25;     // allow 25ms per frame (40fps)
 
     // Map of IDs to element names.
     private HashMap mLocators = null;
     private Activity mActivity;
     private Solo mSolo;
 
     private static String mLogFile = null;
     private static LogLevel mLogLevel = LogLevel.INFO;
@@ -226,30 +226,37 @@ public class FennecNativeDriver implemen
 
     public int stopFrameRecording() {
         Class [] parameters = new Class[1];
         parameters[0] = null;
 
         try {
             Object [] params = null;
             List<Long> frames = (List<Long>)_stopFrameRecording.invoke(null, params);
-            int numDelays = 0;
+            int badness = 0;
             for (int i = 1; i < frames.size(); i++) {
-                if (frames.get(i) - frames.get(i-1) > FRAME_TIME_THRESHOLD) {
-                    numDelays++;
+                long frameTime = frames.get(i) - frames.get(i - 1);
+                int delay = (int)(frameTime - FRAME_TIME_THRESHOLD);
+                // for each frame we miss, add the square of the delay. This
+                // makes large delays much worse than small delays.
+                if (delay > 0) {
+                    badness += delay * delay;
                 }
             }
-            return numDelays;
+            // Don't do any averaging of the numbers because really we want to
+            // know how bad the jank was at its worst
+            return badness;
         } catch (IllegalAccessException e) {
             log(LogLevel.ERROR, e);
         } catch (InvocationTargetException e) {
             log(LogLevel.ERROR, e);
         }
 
-        return 0;
+        // higher values are worse, and the test failing is the worst!
+        return Integer.MAX_VALUE;
     }
 
     public void startCheckerboardRecording() {
         try {
             Object [] params = null;
             _startCheckerboardRecording.invoke(null, params);
         } catch (IllegalAccessException e) {
             log(LogLevel.ERROR, e);
--- a/build/unix/build-toolchain/build-gcc.py
+++ b/build/unix/build-toolchain/build-gcc.py
@@ -87,17 +87,17 @@ def build_glibc_aux(stage_dir, inst_dir)
                    "--enable-kernel=%s" % linux_version,
                    "--libdir=%s/lib64" % inst_dir,
                    "--prefix=%s" % inst_dir])
 
 def build_linux_headers_aux(inst_dir):
     run_in(linux_source_dir, [old_make, "headers_check"])
     run_in(linux_source_dir, [old_make, "INSTALL_HDR_PATH=dest",
                                "headers_install"])
-    shutil.move(linux_source_dir + "/dest", inst_dir)
+    shutil.move(linux_source_dir + "/dest/include", inst_dir + '/include')
 
 def build_linux_headers(inst_dir):
     def f():
         build_linux_headers_aux(inst_dir)
     with_env({"PATH" : aux_inst_dir + "/bin:%s" % os.environ["PATH"]}, f)
 
 def build_gcc(stage_dir, is_stage_one):
     gcc_build_dir = stage_dir + '/gcc'
@@ -146,16 +146,20 @@ def build_one_stage_aux(stage_dir, is_st
                    "--with-gmp=%s" % lib_inst_dir])
     mpc_build_dir = stage_dir + '/mpc'
     build_package(mpc_source_dir, mpc_build_dir,
                   ["--prefix=%s" % lib_inst_dir, "--disable-shared",
                    "--with-gmp=%s" % lib_inst_dir,
                    "--with-mpfr=%s" % lib_inst_dir])
 
     tool_inst_dir = stage_dir + '/inst'
+    os.mkdir(tool_inst_dir)
+    os.mkdir(tool_inst_dir + '/lib64')
+    os.symlink('lib64', tool_inst_dir + '/lib')
+
     build_linux_headers(tool_inst_dir)
 
     binutils_build_dir = stage_dir + '/binutils'
     build_package(binutils_source_dir, binutils_build_dir,
                   ["--prefix=%s" % tool_inst_dir,
                    "--without-zlib"])
 
     # During stage one we have to build gcc first, this glibc doesn't even
new file mode 100644
--- /dev/null
+++ b/build/win32/mozconfig.vs2010-win64
@@ -0,0 +1,12 @@
+export INCLUDE=/c/tools/msvs10/vc/include:/c/tools/msvs10/vc/atlmfc/include:/c/tools/sdks/v7.0/include:/c/tools/sdks/v7.0/include/atl:/c/tools/sdks/dx10/include
+export LIBPATH=/c/tools/msvs10/vc/lib:/c/tools/msvs10/vc/atlmfc/lib
+export LIB=/c/tools/msvs10/vc/lib:/c/tools/msvs10/vc/atlmfc/lib:/c/tools/sdks/v7.0/lib:/c/tools/sdks/dx10/lib
+export PATH="/c/tools/msvs10/Common7/IDE:/c/tools/msvs10/VC/BIN:/c/tools/msvs10/Common7/Tools:/c/tools/msvs10/VC/VCPackages:${PATH}"
+export WIN32_REDIST_DIR=/c/tools/msvs10/VC/redist/x86/Microsoft.VC100.CRT
+
+
+mk_add_options "export LIB=$LIB"
+mk_add_options "export LIBPATH=$LIBPATH"
+mk_add_options "export PATH=$PATH"
+mk_add_options "export INCLUDE=$INCLUDE"
+mk_add_options "export WIN32_REDIST_DIR=$WIN32_REDIST_DIR"
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -89,17 +89,17 @@
 #include "nsAboutProtocolUtils.h"
 #include "nsIClassInfo.h"
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIChromeRegistry.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "mozilla/Preferences.h"
-#include "mozilla/dom/bindings/Utils.h"
+#include "mozilla/dom/BindingUtils.h"
 #include "mozilla/StandardInteger.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
 
 nsIIOService    *nsScriptSecurityManager::sIOService = nsnull;
@@ -2478,18 +2478,18 @@ nsScriptSecurityManager::doGetObjectPrin
                 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) &&
-                       bindings::DOMJSClass::FromJSClass(jsClass)->mDOMObjectIsISupports) {
-                priv = bindings::UnwrapDOMObject<nsISupports>(aObj, jsClass);
+                       DOMJSClass::FromJSClass(jsClass)->mDOMObjectIsISupports) {
+                priv = UnwrapDOMObject<nsISupports>(aObj, jsClass);
             } else {
                 priv = nsnull;
             }
 
 #ifdef DEBUG
             if (aAllowShortCircuit) {
                 nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
                     do_QueryInterface(priv);
--- a/config/makefiles/autotargets.mk
+++ b/config/makefiles/autotargets.mk
@@ -1,50 +1,53 @@
 # -*- makefile -*-
 # vim:set ts=8 sw=8 sts=8 noet:
 #
 # 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 INCLUDED_AUTOTARGETS_MK #{
+
+# Conditional does not wrap the entire file so multiple
+# includes will be able to accumulate dependencies.
+
 ###########################################################################
 #      AUTO_DEPS - A list of deps/targets drived from other macros.
-#         *_DEPS - Make dependencies derived from a given macro.
 ###########################################################################
 
 MKDIR ?= mkdir -p
 TOUCH ?= touch
 
 ###########################################################################
 # Threadsafe directory creation
 # GENERATED_DIRS - Automated creation of these directories.
 ###########################################################################
 mkdir_deps =$(foreach dir,$(getargv),$(dir)/.mkdir.done)
 
-ifneq (,$(GENERATED_DIRS))
-  tmpauto :=$(call mkdir_deps,GENERATED_DIRS)
-  GENERATED_DIRS_DEPS +=$(tmpauto)
-  GARBAGE_DIRS        +=$(tmpauto)
-endif
-
-## Only define rules once
-ifndef INCLUDED_AUTOTARGETS_MK
-
 %/.mkdir.done: # mkdir -p -p => mkdir -p
 	$(subst $(SPACE)-p,$(null),$(MKDIR)) -p $(dir $@)
 	@$(TOUCH) $@
 
 # A handful of makefiles are attempting "mkdir dot".  Likely not intended
 # or stale logic so add a stub target to handle the request and warn for now.
 .mkdir.done:
 	@echo "WARNING: $(MKDIR) -dot- requested by $(MAKE) -C $(CURDIR) $(MAKECMDGOALS)"
 	@$(TOUCH) $@
 
 INCLUDED_AUTOTARGETS_MK = 1
+endif #}
+
+
+## Accumulate deps and cleanup
+ifneq (,$(GENERATED_DIRS))
+  tmpauto :=$(call mkdir_deps,GENERATED_DIRS)
+  GENERATED_DIRS_DEPS +=$(tmpauto)
+  GARBAGE_DIRS        +=$(tmpauto)
 endif
 
 #################################################################
 # One ring/dep to rule them all:
 #   config/rules.mk::all target is available by default
 #   Add $(AUTO_DEPS) as an explicit target dependency when needed.
 #################################################################
 
--- a/configure.in
+++ b/configure.in
@@ -175,51 +175,17 @@ then
 	***
 	EOF
     exit 1
     break
   fi
 fi
 MOZ_BUILD_ROOT=`pwd`
 
-dnl Default to MSVC for win32 and gcc for darwin
-dnl ==============================================================
-if test -z "$CROSS_COMPILE"; then
-case "$target" in
-*-mingw*)
-    if test -z "$CC"; then CC=cl; fi
-    if test -z "$CXX"; then CXX=cl; fi
-    if test -z "$CPP"; then CPP="cl -E -nologo"; fi
-    if test -z "$CXXCPP"; then CXXCPP="cl -TP -E -nologo"; ac_cv_prog_CXXCPP="$CXXCPP"; fi
-    if test -z "$LD"; then LD=link; fi
-    if test -z "$AS"; then
-        case "${target_cpu}" in
-        i*86)
-            AS=ml;
-            ;;
-        x86_64)
-            AS=ml64;
-            ;;
-        esac
-    fi
-    if test -z "$MIDL"; then MIDL=midl; fi
-
-    # need override this flag since we don't use $(LDFLAGS) for this.
-    if test -z "$HOST_LDFLAGS" ; then
-        HOST_LDFLAGS=" "
-    fi
-    ;;
-*-darwin*)
-    # we prefer gcc-4.2 over gcc on older darwin, so
-    # use that specific version if it's available.
-    MOZ_PATH_PROGS(CC, $CC gcc-4.2 gcc)
-    MOZ_PATH_PROGS(CXX, $CXX g++-4.2 g++)
-    ;;
-esac
-fi
+MOZ_DEFAULT_COMPILER
 
 COMPILE_ENVIRONMENT=1
 MOZ_ARG_DISABLE_BOOL(compile-environment,
 [  --disable-compile-environment
                           Disable compiler/library checks.],
     COMPILE_ENVIRONMENT= )
 AC_SUBST(COMPILE_ENVIRONMENT)
 
@@ -2261,18 +2227,16 @@ case "$target" in
     MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
     MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
     MOZ_OPTIMIZE_FLAGS="-O3"
     _PEDANTIC=
     # Statically disable jemalloc on 10.5 and 32-bit 10.6.  See bug 702250.
     if test "$HAVE_64BIT_OS"; then
         MOZ_MEMORY=1
     fi
-    CFLAGS="$CFLAGS -fno-common"
-    CXXFLAGS="$CXXFLAGS -fno-common"
     DLL_SUFFIX=".dylib"
     DSO_LDOPTS=''
     STRIP="$STRIP -x -S"
     # Check whether we're targeting OS X or iOS
     AC_CACHE_CHECK(for iOS target,
                    ac_cv_ios_target,
                    [AC_TRY_COMPILE([#include <TargetConditionals.h>
 #if !(TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
@@ -7182,17 +7146,23 @@ elif test "${OS_TARGET}" = "WINNT" -o "$
   dnl On Windows, OSX and OS2, we want to link all our binaries against mozglue
   if test -z "$GNU_CC"; then
     MOZ_GLUE_LDFLAGS='$(call EXPAND_LIBNAME_PATH,mozglue,$(LIBXUL_DIST)/lib)'
   else
     MOZ_GLUE_LDFLAGS='-L$(LIBXUL_DIST)/lib $(call EXPAND_LIBNAME,mozglue)'
   fi
 else
   dnl On other Unix systems, we only want to link executables against mozglue
-  MOZ_GLUE_PROGRAM_LDFLAGS='$(MKSHLIB_FORCE_ALL) $(call EXPAND_LIBNAME_PATH,mozglue,$(LIBXUL_DIST)/lib) $(MKSHLIB_UNFORCE_ALL)'
+  MOZ_GLUE_PROGRAM_LDFLAGS='$(MKSHLIB_FORCE_ALL) $(call EXPAND_LIBNAME_PATH,mozglue,$(LIBXUL_DIST)/lib)'
+  dnl On other Unix systems, where mozglue is a static library, jemalloc is
+  dnl separated for the SDK, so we need to add it here.
+  if test "$MOZ_MEMORY" = 1; then
+    MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS "'$(call EXPAND_LIBNAME_PATH,memory,$(LIBXUL_DIST)/lib)'
+  fi
+  MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS "'$(MKSHLIB_UNFORCE_ALL)'
   if test -n "$GNU_CC"; then
     dnl And we need mozglue symbols to be exported.
     MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS -rdynamic"
   fi
   if test "$MOZ_LINKER" = 1; then
     MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS $ZLIB_LIBS"
   fi
 fi
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -6074,27 +6074,31 @@ public:
                                            const char *objName)
   {
   }
   NS_IMETHOD_(void) DescribeGCedNode(bool isMarked,
                                      size_t objSz,
                                      const char *objName)
   {
   }
+
   NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root)
   {
   }
-  NS_IMETHOD_(void) NoteRoot(PRUint32 langID, void* root,
-                             nsCycleCollectionParticipant* helper)
+  NS_IMETHOD_(void) NoteJSRoot(void* root)
+  {
+  }
+  NS_IMETHOD_(void) NoteNativeRoot(void* root,
+                                   nsCycleCollectionParticipant* helper)
   {
   }
-  NS_IMETHOD_(void) NoteScriptChild(PRUint32 langID, void* child)
+
+  NS_IMETHOD_(void) NoteJSChild(void* child)
   {
-    if (langID == nsIProgrammingLanguage::JAVASCRIPT &&
-        child == mWrapper) {
+    if (child == mWrapper) {
       mFound = true;
     }
   }
   NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child)
   {
   }
   NS_IMETHOD_(void) NoteNativeChild(void* child,
                                     nsCycleCollectionParticipant* helper)
@@ -6111,22 +6115,21 @@ public:
 
   bool mFound;
 
 private:
   void* mWrapper;
 };
 
 static void
-DebugWrapperTraceCallback(PRUint32 langID, void *p, const char *name,
-                          void *closure)
+DebugWrapperTraceCallback(void *p, const char *name, void *closure)
 {
   DebugWrapperTraversalCallback* callback =
     static_cast<DebugWrapperTraversalCallback*>(closure);
-  callback->NoteScriptChild(langID, p);
+  callback->NoteJSChild(p);
 }
 
 // static
 void
 nsContentUtils::CheckCCWrapperTraversal(nsISupports* aScriptObjectHolder,
                                         nsWrapperCache* aCache)
 {
   JSObject* wrapper = aCache->GetWrapper();
@@ -6634,18 +6637,17 @@ nsContentUtils::ReleaseWrapper(nsISuppor
 // static
 void
 nsContentUtils::TraceWrapper(nsWrapperCache* aCache, TraceCallback aCallback,
                              void *aClosure)
 {
   if (aCache->PreservingWrapper()) {
     JSObject *wrapper = aCache->GetWrapperPreserveColor();
     if (wrapper) {
-      aCallback(nsIProgrammingLanguage::JAVASCRIPT, wrapper,
-                "Preserved wrapper", aClosure);
+      aCallback(wrapper, "Preserved wrapper", aClosure);
     }
   }
 }
 
 nsresult
 nsContentUtils::JSArrayToAtomArray(JSContext* aCx, const JS::Value& aJSArray,
                                    nsCOMArray<nsIAtom>& aRetVal)
 {
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2778,18 +2778,23 @@ nsDocument::GetActiveElement(nsIDOMEleme
   nsCOMPtr<nsPIDOMWindow> window = GetWindow();
   if (window) {
     nsCOMPtr<nsPIDOMWindow> focusedWindow;
     nsIContent* focusedContent =
       nsFocusManager::GetFocusedDescendant(window, false,
                                            getter_AddRefs(focusedWindow));
     // be safe and make sure the element is from this document
     if (focusedContent && focusedContent->OwnerDoc() == this) {
-      CallQueryInterface(focusedContent, aElement);
-      return NS_OK;
+      if (focusedContent->IsInNativeAnonymousSubtree()) {
+        focusedContent = focusedContent->FindFirstNonNativeAnonymous();
+      }
+      if (focusedContent) {
+        CallQueryInterface(focusedContent, aElement);
+        return NS_OK;
+      }
     }
   }
 
   // No focused element anywhere in this document.  Try to get the BODY.
   nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryObject(this);
   if (htmlDoc) {
     nsCOMPtr<nsIDOMHTMLElement> bodyElement;
     htmlDoc->GetBody(getter_AddRefs(bodyElement));
@@ -6627,19 +6632,19 @@ nsDocument::RemoveFromRadioGroup(const n
   nsRadioGroupStruct* radioGroup = GetRadioGroup(aName);
   NS_ENSURE_TRUE(radioGroup, NS_OK);
 
   radioGroup->mRadioButtons.RemoveObject(aRadio);
 
   nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
   NS_ASSERTION(element, "radio controls have to be content elements");
   if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
+    NS_ASSERTION(radioGroup->mRequiredRadioCount != 0,
+                 "mRequiredRadioCount about to wrap below 0!");
     radioGroup->mRequiredRadioCount--;
-    NS_ASSERTION(radioGroup->mRequiredRadioCount >= 0,
-                 "mRequiredRadioCount shouldn't be negative!");
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::WalkRadioGroup(const nsAString& aName,
                            nsIRadioVisitor* aVisitor,
                            bool aFlushContent)
@@ -6680,19 +6685,19 @@ nsDocument::RadioRequiredChanged(const n
     return;
   }
 
   nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
   NS_ASSERTION(element, "radio controls have to be content elements");
   if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
     radioGroup->mRequiredRadioCount++;
   } else {
+    NS_ASSERTION(radioGroup->mRequiredRadioCount != 0,
+                 "mRequiredRadioCount about to wrap below 0!");
     radioGroup->mRequiredRadioCount--;
-    NS_ASSERTION(radioGroup->mRequiredRadioCount >= 0,
-                 "mRequiredRadioCount shouldn't be negative!");
   }
 }
 
 bool
 nsDocument::GetValueMissingState(const nsAString& aName) const
 {
   nsRadioGroupStruct* radioGroup = nsnull;
   // TODO: we should call GetRadioGroup here (and make it const) but for that
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1706,18 +1706,22 @@ GK_ATOM(onMozTapGesture, "onMozTapGestur
 GK_ATOM(onMozPressTapGesture, "onMozPressTapGesture")
 
 // Touch events
 GK_ATOM(onMozTouchDown, "onMozTouchDown")
 GK_ATOM(onMozTouchMove, "onMozTouchMove")
 GK_ATOM(onMozTouchUp, "onMozTouchUp")
 
 // orientation support
+GK_ATOM(ondevicemotion, "ondevicemotion")
 GK_ATOM(ondeviceorientation, "ondeviceorientation")
-GK_ATOM(ondevicemotion, "ondevicemotion")
+GK_ATOM(ondeviceproximity, "ondeviceproximity")
+
+// light sensor support
+GK_ATOM(ondevicelight, "ondevicelight")
 
 //---------------------------------------------------------------------------
 // Special atoms
 //---------------------------------------------------------------------------
 
 // Node types
 GK_ATOM(cdataTagName, "#cdata-section")
 GK_ATOM(commentTagName, "#comment")
@@ -1906,16 +1910,17 @@ GK_ATOM(x_symbol, "x-symbol")
 // referenced in all.js
 GK_ATOM(x_user_def, "x-user-def")
 
 // additional languages that have special case transformations
 GK_ATOM(az, "az")
 GK_ATOM(ba, "ba")
 GK_ATOM(crh, "crh")
 GK_ATOM(nl, "nl")
+GK_ATOM(el, "el")
 
 // Names for editor transactions
 GK_ATOM(TypingTxnName, "Typing")
 GK_ATOM(IMETxnName, "IME")
 GK_ATOM(DeleteTxnName, "Deleting")
 
 // IPC stuff
 GK_ATOM(Remote, "remote")
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -514,18 +514,22 @@ nsresult nsObjectLoadingContent::IsPlugi
     return rv;
   }
 
   if (!mShouldPlay) {
     nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
     MOZ_ASSERT(thisContent);
     nsIDocument* ownerDoc = thisContent->OwnerDoc();
 
+    nsCOMPtr<nsIDOMWindow> window = ownerDoc->GetWindow();
+    if (!window) {
+      return NS_ERROR_FAILURE;
+    }
     nsCOMPtr<nsIDOMWindow> topWindow;
-    rv = ownerDoc->GetWindow()->GetTop(getter_AddRefs(topWindow));
+    window->GetTop(getter_AddRefs(topWindow));
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDOMDocument> topDocument;
     rv = topWindow->GetDocument(getter_AddRefs(topDocument));
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDocument> topDoc = do_QueryInterface(topDocument);
     nsIURI* topUri = topDoc->GetDocumentURI();
 
     nsCOMPtr<nsIPermissionManager> permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -100,17 +100,17 @@
 #include "nsIContentSecurityPolicy.h"
 #include "nsAsyncRedirectVerifyHelper.h"
 #include "nsStringBuffer.h"
 #include "nsDOMFile.h"
 #include "nsIFileChannel.h"
 #include "mozilla/Telemetry.h"
 #include "jsfriendapi.h"
 #include "sampler.h"
-#include "mozilla/dom/bindings/XMLHttpRequestBinding.h"
+#include "mozilla/dom/XMLHttpRequestBinding.h"
 #include "nsIDOMFormData.h"
 
 #include "nsWrapperCacheInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define LOAD_STR "load"
@@ -1086,18 +1086,18 @@ NS_IMETHODIMP nsXMLHttpRequest::GetRespo
 }
 
 #ifdef DEBUG
 void
 nsXMLHttpRequest::StaticAssertions()
 {
 #define ASSERT_ENUM_EQUAL(_lc, _uc) \
   MOZ_STATIC_ASSERT(\
-    bindings::prototypes::XMLHttpRequestResponseType::_lc \
-      == bindings::prototypes::XMLHttpRequestResponseType::value(XML_HTTP_RESPONSE_TYPE_ ## _uc), \
+    XMLHttpRequestResponseTypeValues::_lc                \
+    == XMLHttpRequestResponseType(XML_HTTP_RESPONSE_TYPE_ ## _uc), \
     #_uc " should match")
 
   ASSERT_ENUM_EQUAL(_empty, DEFAULT);
   ASSERT_ENUM_EQUAL(arraybuffer, ARRAYBUFFER);
   ASSERT_ENUM_EQUAL(blob, BLOB);
   ASSERT_ENUM_EQUAL(document, DOCUMENT);
   ASSERT_ENUM_EQUAL(json, JSON);
   ASSERT_ENUM_EQUAL(text, TEXT);
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -64,18 +64,18 @@
 #include "nsIPrivateDOMEvent.h"
 #include "nsDOMProgressEvent.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsContentUtils.h"
 #include "nsDOMFile.h"
 #include "nsDOMBlobBuilder.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptObjectPrincipal.h"
-#include "mozilla/dom/bindings/XMLHttpRequestBinding.h"
-#include "mozilla/dom/bindings/XMLHttpRequestUploadBinding.h"
+#include "mozilla/dom/XMLHttpRequestBinding.h"
+#include "mozilla/dom/XMLHttpRequestUploadBinding.h"
 
 #include "mozilla/Assertions.h"
 
 class nsILoadGroup;
 class AsyncVerifyRedirectCallbackForwarder;
 class nsIUnicodeDecoder;
 class nsIDOMFormData;
 
@@ -90,17 +90,17 @@ class nsIDOMFormData;
                               mOn##_capitalized##Listener,              \
                               aCallback);                               \
   }
 
 class nsXHREventTarget : public nsDOMEventTargetHelper,
                          public nsIXMLHttpRequestEventTarget
 {
 public:
-  typedef mozilla::dom::bindings::prototypes::XMLHttpRequestResponseType::value
+  typedef mozilla::dom::XMLHttpRequestResponseType
           XMLHttpRequestResponseType;
 
   virtual ~nsXHREventTarget() {}
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXHREventTarget,
                                            nsDOMEventTargetHelper)
   NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
@@ -165,17 +165,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::)
   NS_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget::)
   NS_DECL_NSIXMLHTTPREQUESTUPLOAD
 
   virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
                                bool *triedToWrap)
   {
-    return mozilla::dom::bindings::prototypes::XMLHttpRequestUpload::Wrap(cx, scope, this, triedToWrap);
+    return mozilla::dom::XMLHttpRequestUploadBinding::Wrap(cx, scope, this, triedToWrap);
   }
   nsISupports* GetParentObject()
   {
     return GetOwner();
   }
 
   bool HasListeners()
   {
@@ -197,17 +197,17 @@ class nsXMLHttpRequest : public nsXHREve
   friend class nsXHRParseEndListener;
 public:
   nsXMLHttpRequest();
   virtual ~nsXMLHttpRequest();
 
   virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
                                bool *triedToWrap)
   {
-    return mozilla::dom::bindings::prototypes::XMLHttpRequest::Wrap(cx, scope, this, triedToWrap);
+    return mozilla::dom::XMLHttpRequestBinding::Wrap(cx, scope, this, triedToWrap);
   }
   nsISupports* GetParentObject()
   {
     return GetOwner();
   }
 
   // The WebIDL parser converts constructors into methods called _Constructor.
   static already_AddRefed<nsXMLHttpRequest>
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -2967,16 +2967,17 @@ nsCanvasRenderingContext2D::DrawOrMeasur
              (isRTL && CurrentState().textAlign == TEXT_ALIGN_END))
         anchorX = 0;
     else
         anchorX = 1;
 
     processor.mPt.x -= anchorX * totalWidth;
 
     // offset pt.y based on text baseline
+    processor.mFontgrp->UpdateFontList(); // ensure user font generation is current
     NS_ASSERTION(processor.mFontgrp->FontListLength()>0, "font group contains no fonts");
     const gfxFont::Metrics& fontMetrics = processor.mFontgrp->GetFontAt(0)->GetMetrics();
 
     gfxFloat anchorY;
 
     switch (CurrentState().textBaseline)
     {
     case TEXT_BASELINE_HANGING:
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -3277,16 +3277,17 @@ nsCanvasRenderingContext2DAzure::DrawOrM
     anchorX = 0;
   } else {
     anchorX = 1;
   }
 
   processor.mPt.x -= anchorX * totalWidth;
 
   // offset pt.y based on text baseline
+  processor.mFontgrp->UpdateFontList(); // ensure user font generation is current
   NS_ASSERTION(processor.mFontgrp->FontListLength()>0, "font group contains no fonts");
   const gfxFont::Metrics& fontMetrics = processor.mFontgrp->GetFontAt(0)->GetMetrics();
 
   gfxFloat anchorY;
 
   switch (state.textBaseline)
   {
   case TEXT_BASELINE_HANGING:
--- a/content/events/public/nsEventNameList.h
+++ b/content/events/public/nsEventNameList.h
@@ -450,16 +450,24 @@ WINDOW_EVENT(unload,
 WINDOW_ONLY_EVENT(devicemotion,
                   NS_DEVICE_MOTION,
                   EventNameType_None,
                   NS_EVENT)
 WINDOW_ONLY_EVENT(deviceorientation,
                   NS_DEVICE_ORIENTATION,
                   EventNameType_None,
                   NS_EVENT)
+WINDOW_ONLY_EVENT(deviceproximity,
+                  NS_DEVICE_PROXIMITY,
+                  EventNameType_None,
+                  NS_EVENT)
+WINDOW_ONLY_EVENT(devicelight,
+                  NS_DEVICE_LIGHT,
+                  EventNameType_None,
+                  NS_EVENT)
 
 TOUCH_EVENT(touchstart,
             NS_TOUCH_START,
             EventNameType_All,
             NS_TOUCH_EVENT)
 TOUCH_EVENT(touchend,
             NS_TOUCH_END,
             EventNameType_All,
--- a/content/events/public/nsIPrivateDOMEvent.h
+++ b/content/events/public/nsIPrivateDOMEvent.h
@@ -87,18 +87,22 @@ nsresult
 NS_NewDOMKeyboardEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsKeyEvent *aEvent);
 nsresult
 NS_NewDOMCompositionEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsCompositionEvent *aEvent);
 nsresult
 NS_NewDOMMutationEvent(nsIDOMEvent** aResult NS_OUTPARAM, nsPresContext* aPresContext, class nsMutationEvent* aEvent);
 nsresult
 NS_NewDOMPopupBlockedEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, nsEvent* aEvent);
 nsresult
+NS_NewDOMDeviceProximityEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent *aEvent);
+nsresult
 NS_NewDOMDeviceOrientationEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, nsEvent* aEvent);
 nsresult
+NS_NewDOMDeviceLightEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, nsEvent* aEvent);
+nsresult
 NS_NewDOMDeviceMotionEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, nsEvent* aEvent);
 nsresult
 NS_NewDOMTextEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsTextEvent* aEvent);
 nsresult
 NS_NewDOMBeforeUnloadEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, nsEvent* aEvent);
 nsresult
 NS_NewDOMPageTransitionEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, nsEvent* aEvent);
 nsresult
--- a/content/events/src/Makefile.in
+++ b/content/events/src/Makefile.in
@@ -46,30 +46,32 @@ MODULE		= content
 LIBRARY_NAME	= gkconevents_s
 LIBXUL_LIBRARY  = 1
 
 EXPORTS		= \
 		nsEventStateManager.h \
 		nsEventListenerManager.h \
 		nsDOMEventTargetHelper.h \
 		$(NULL)
-		
+
 CPPSRCS		= \
 		nsEventListenerManager.cpp \
 		nsEventStateManager.cpp \
 		nsDOMEvent.cpp \
 		nsDOMDataContainerEvent.cpp \
 		nsDOMUIEvent.cpp \
 		nsDOMKeyboardEvent.cpp \
 		nsDOMTextEvent.cpp \
 		nsDOMMouseEvent.cpp \
 		nsDOMMouseScrollEvent.cpp \
 		nsDOMDragEvent.cpp \
 		nsDOMMutationEvent.cpp \
 		nsDOMPopupBlockedEvent.cpp \
+		nsDOMDeviceProximityEvent.cpp \
+		nsDOMDeviceLightEvent.cpp \
 		nsDOMDeviceOrientationEvent.cpp \
 		nsDOMDeviceMotionEvent.cpp \
 		nsDOMBeforeUnloadEvent.cpp \
 		nsDOMPageTransitionEvent.cpp \
 		nsDOMXULCommandEvent.cpp \
 		nsDOMCommandEvent.cpp \
 		nsDOMMessageEvent.cpp \
 		nsPaintRequest.cpp \
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMDeviceLightEvent.cpp
@@ -0,0 +1,58 @@
+/* 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 "nsDOMDeviceLightEvent.h"
+#include "nsContentUtils.h"
+#include "DictionaryHelpers.h"
+
+NS_IMPL_ADDREF_INHERITED(nsDOMDeviceLightEvent, nsDOMEvent)
+NS_IMPL_RELEASE_INHERITED(nsDOMDeviceLightEvent, nsDOMEvent)
+
+DOMCI_DATA(DeviceLightEvent, nsDOMDeviceLightEvent)
+
+NS_INTERFACE_MAP_BEGIN(nsDOMDeviceLightEvent)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMDeviceLightEvent)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DeviceLightEvent)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
+
+NS_IMETHODIMP
+nsDOMDeviceLightEvent::InitDeviceLightEvent(const nsAString & aEventTypeArg,
+                                            bool aCanBubbleArg,
+                                            bool aCancelableArg,
+                                            double aValue)
+{
+  nsresult rv = nsDOMEvent::InitEvent(aEventTypeArg, aCanBubbleArg, aCancelableArg);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mValue = aValue;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDeviceLightEvent::GetValue(double *aValue)
+{
+  NS_ENSURE_ARG_POINTER(aValue);
+  *aValue = mValue;
+  return NS_OK;
+}
+
+nsresult
+nsDOMDeviceLightEvent::InitFromCtor(const nsAString& aType,
+                                    JSContext* aCx, jsval* aVal)
+{
+  mozilla::dom::DeviceLightEventInit d;
+  nsresult rv = d.Init(aCx, aVal);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return InitDeviceLightEvent(aType, d.bubbles, d.cancelable, d.value);
+}
+
+nsresult
+NS_NewDOMDeviceLightEvent(nsIDOMEvent** aInstancePtrResult,
+                          nsPresContext* aPresContext,
+                          nsEvent *aEvent) 
+{
+  NS_ENSURE_ARG_POINTER(aInstancePtrResult);
+  nsDOMDeviceLightEvent* it = new nsDOMDeviceLightEvent(aPresContext, aEvent);
+  return CallQueryInterface(it, aInstancePtrResult);
+}
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMDeviceLightEvent.h
@@ -0,0 +1,36 @@
+/* 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 nsDOMDeviceLightEvent_h__
+#define nsDOMDeviceLightEvent_h__
+
+#include "nsIDOMDeviceLightEvent.h"
+#include "nsDOMEvent.h"
+
+class nsDOMDeviceLightEvent
+ : public nsDOMEvent
+ , public nsIDOMDeviceLightEvent
+{
+public:
+
+  nsDOMDeviceLightEvent(nsPresContext* aPresContext, nsEvent* aEvent)
+  : nsDOMEvent(aPresContext, aEvent),
+    mValue(0) {}
+
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // Forward to nsDOMEvent
+  NS_FORWARD_TO_NSDOMEVENT
+
+  // nsIDOMDeviceLightEvent Interface
+  NS_DECL_NSIDOMDEVICELIGHTEVENT
+
+  virtual nsresult InitFromCtor(const nsAString& aType,
+                                JSContext* aCx,
+                                jsval* aVal);
+protected:
+  double mValue;
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMDeviceProximityEvent.cpp
@@ -0,0 +1,81 @@
+/* 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 "nsDOMDeviceProximityEvent.h"
+#include "nsContentUtils.h"
+#include "DictionaryHelpers.h"
+
+NS_IMPL_ADDREF_INHERITED(nsDOMDeviceProximityEvent, nsDOMEvent)
+NS_IMPL_RELEASE_INHERITED(nsDOMDeviceProximityEvent, nsDOMEvent)
+
+DOMCI_DATA(DeviceProximityEvent, nsDOMDeviceProximityEvent)
+
+NS_INTERFACE_MAP_BEGIN(nsDOMDeviceProximityEvent)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMDeviceProximityEvent)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DeviceProximityEvent)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
+
+NS_IMETHODIMP
+nsDOMDeviceProximityEvent::InitDeviceProximityEvent(const nsAString & aEventTypeArg,
+                                                    bool aCanBubbleArg,
+                                                    bool aCancelableArg,
+                                                    double aValue,
+                                                    double aMin,
+                                                    double aMax)
+{
+  nsresult rv = nsDOMEvent::InitEvent(aEventTypeArg, aCanBubbleArg, aCancelableArg);
+  NS_ENSURE_SUCCESS(rv, rv);
+    
+  mValue = aValue;
+  mMin = aMin;
+  mMax = aMax;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDeviceProximityEvent::GetValue(double *aValue)
+{
+  NS_ENSURE_ARG_POINTER(aValue);
+
+  *aValue = mValue;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDeviceProximityEvent::GetMin(double *aMin)
+{
+  NS_ENSURE_ARG_POINTER(aMin);
+
+  *aMin = mMin;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDeviceProximityEvent::GetMax(double *aMax)
+{
+  NS_ENSURE_ARG_POINTER(aMax);
+
+  *aMax = mMax;
+  return NS_OK;
+}
+
+nsresult
+nsDOMDeviceProximityEvent::InitFromCtor(const nsAString& aType,
+                                        JSContext* aCx, jsval* aVal)
+{
+  mozilla::dom::DeviceProximityEventInit d;
+  nsresult rv = d.Init(aCx, aVal);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return InitDeviceProximityEvent(aType, d.bubbles, d.cancelable, d.value, d.min, d.max);
+}
+
+nsresult
+NS_NewDOMDeviceProximityEvent(nsIDOMEvent** aInstancePtrResult,
+                              nsPresContext* aPresContext,
+                              nsEvent *aEvent)
+{
+  NS_ENSURE_ARG_POINTER(aInstancePtrResult);
+  nsDOMDeviceProximityEvent* it = new nsDOMDeviceProximityEvent(aPresContext, aEvent);
+  return CallQueryInterface(it, aInstancePtrResult);
+}
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMDeviceProximityEvent.h
@@ -0,0 +1,38 @@
+/* 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 nsDOMDeviceProximityEvent_h__
+#define nsDOMDeviceProximityEvent_h__
+
+#include "nsIDOMDeviceProximityEvent.h"
+#include "nsDOMEvent.h"
+
+class nsDOMDeviceProximityEvent
+ : public nsDOMEvent
+ , public nsIDOMDeviceProximityEvent
+{
+public:
+
+ nsDOMDeviceProximityEvent(nsPresContext* aPresContext, nsEvent* aEvent)
+  : nsDOMEvent(aPresContext, aEvent),
+    mValue(-1),
+    mMin(0),
+    mMax(0) {}
+
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // Forward to nsDOMEvent
+  NS_FORWARD_TO_NSDOMEVENT
+
+  // nsIDOMDeviceProximityEvent Interface
+  NS_DECL_NSIDOMDEVICEPROXIMITYEVENT
+
+  virtual nsresult InitFromCtor(const nsAString& aType,
+                                JSContext* aCx,
+                                jsval* aVal);
+protected:
+  double mValue, mMin, mMax;
+};
+
+#endif
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -121,17 +121,19 @@ static const char* const sEventNames[] =
   "touchenter",
   "touchleave",
   "MozScrolledAreaChanged",
   "transitionend",
   "animationstart",
   "animationend",
   "animationiteration",
   "devicemotion",
-  "deviceorientation"
+  "deviceorientation",
+  "deviceproximity",
+  "devicelight"
 };
 
 static char *sPopupAllowedEvents;
 
 
 nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
 {
   mPrivateDataDuplicated = false;
@@ -675,16 +677,17 @@ NS_METHOD nsDOMEvent::DuplicatePrivateDa
     case NS_KEY_EVENT:
     {
       nsKeyEvent* keyEvent = new nsKeyEvent(false, msg, nsnull);
       NS_ENSURE_TRUE(keyEvent, NS_ERROR_OUT_OF_MEMORY);
       nsKeyEvent* oldKeyEvent = static_cast<nsKeyEvent*>(mEvent);
       isInputEvent = true;
       keyEvent->keyCode = oldKeyEvent->keyCode;
       keyEvent->charCode = oldKeyEvent->charCode;
+      keyEvent->location = oldKeyEvent->location;
       keyEvent->isChar = oldKeyEvent->isChar;
       newEvent = keyEvent;
       break;
     }
     case NS_MOUSE_EVENT:
     {
       nsMouseEvent* oldMouseEvent = static_cast<nsMouseEvent*>(mEvent);
       nsMouseEvent* mouseEvent =
@@ -1547,16 +1550,20 @@ const char* nsDOMEvent::GetEventName(PRU
   case NS_ANIMATION_END:
     return sEventNames[eDOMEvents_animationend];
   case NS_ANIMATION_ITERATION:
     return sEventNames[eDOMEvents_animationiteration];
   case NS_DEVICE_MOTION:
     return sEventNames[eDOMEvents_devicemotion];
   case NS_DEVICE_ORIENTATION:
     return sEventNames[eDOMEvents_deviceorientation];
+  case NS_DEVICE_PROXIMITY:
+    return sEventNames[eDOMEvents_deviceproximity];
+  case NS_DEVICE_LIGHT:
+    return sEventNames[eDOMEvents_devicelight];
   case NS_FULLSCREENCHANGE:
     return sEventNames[eDOMEvents_mozfullscreenchange];
   case NS_FULLSCREENERROR:
     return sEventNames[eDOMEvents_mozfullscreenerror];
   default:
     break;
   }
   // XXXldb We can hit this case for nsEvent objects that we didn't
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -204,17 +204,19 @@ public:
     eDOMEvents_touchenter,
     eDOMEvents_touchleave,
     eDOMEvents_MozScrolledAreaChanged,
     eDOMEvents_transitionend,
     eDOMEvents_animationstart,
     eDOMEvents_animationend,
     eDOMEvents_animationiteration,
     eDOMEvents_devicemotion,
-    eDOMEvents_deviceorientation
+    eDOMEvents_deviceorientation,
+    eDOMEvents_deviceproximity,
+    eDOMEvents_devicelight
   };
 
   nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent);
   virtual ~nsDOMEvent();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMEvent, nsIDOMEvent)
 
--- a/content/events/src/nsDOMKeyboardEvent.cpp
+++ b/content/events/src/nsDOMKeyboardEvent.cpp
@@ -180,16 +180,25 @@ nsDOMKeyboardEvent::Which(PRUint32* aWhi
       *aWhich = 0;
       break;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMKeyboardEvent::GetLocation(PRUint32* aLocation)
+{
+  NS_ENSURE_ARG_POINTER(aLocation);
+
+  *aLocation = static_cast<nsKeyEvent*>(mEvent)->location;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMKeyboardEvent::InitKeyEvent(const nsAString& aType, bool aCanBubble, bool aCancelable,
                                  nsIDOMWindow* aView, bool aCtrlKey, bool aAltKey,
                                  bool aShiftKey, bool aMetaKey,
                                  PRUint32 aKeyCode, PRUint32 aCharCode)
 {
   nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, 0);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -285,16 +285,20 @@ nsEventListenerManager::AddEventListener
       // If aType is NS_MUTATION_SUBTREEMODIFIED, we need to listen all
       // mutations. nsContentUtils::HasMutationListeners relies on this.
       window->SetMutationListeners((aType == NS_MUTATION_SUBTREEMODIFIED) ?
                                    kAllMutationBits :
                                    MutationBitForEventType(aType));
     }
   } else if (aTypeAtom == nsGkAtoms::ondeviceorientation) {
     EnableDevice(NS_DEVICE_ORIENTATION);
+  } else if (aTypeAtom == nsGkAtoms::ondeviceproximity) {
+    EnableDevice(NS_DEVICE_PROXIMITY);
+  } else if (aTypeAtom == nsGkAtoms::ondevicelight) {
+    EnableDevice(NS_DEVICE_LIGHT);
   } else if (aTypeAtom == nsGkAtoms::ondevicemotion) {
     EnableDevice(NS_DEVICE_MOTION);
   } else if ((aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) ||
              (aTypeAtom == nsGkAtoms::ontouchstart ||
               aTypeAtom == nsGkAtoms::ontouchend ||
               aTypeAtom == nsGkAtoms::ontouchmove ||
               aTypeAtom == nsGkAtoms::ontouchenter ||
               aTypeAtom == nsGkAtoms::ontouchleave ||
@@ -341,16 +345,22 @@ nsEventListenerManager::EnableDevice(PRU
   }
 
   NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window");
 
   switch (aType) {
     case NS_DEVICE_ORIENTATION:
       window->EnableDeviceSensor(SENSOR_ORIENTATION);
       break;
+    case NS_DEVICE_PROXIMITY:
+      window->EnableDeviceSensor(SENSOR_PROXIMITY);
+      break;
+    case NS_DEVICE_LIGHT:
+      window->EnableDeviceSensor(SENSOR_LIGHT);
+      break;
     case NS_DEVICE_MOTION:
       window->EnableDeviceSensor(SENSOR_ACCELERATION);
       window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
       window->EnableDeviceSensor(SENSOR_GYROSCOPE);
       break;
     default:
       NS_WARNING("Enabling an unknown device sensor.");
       break;
@@ -371,16 +381,22 @@ nsEventListenerManager::DisableDevice(PR
     case NS_DEVICE_ORIENTATION:
       window->DisableDeviceSensor(SENSOR_ORIENTATION);
       break;
     case NS_DEVICE_MOTION:
       window->DisableDeviceSensor(SENSOR_ACCELERATION);
       window->DisableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
       window->DisableDeviceSensor(SENSOR_GYROSCOPE);
       break;
+    case NS_DEVICE_PROXIMITY:
+      window->DisableDeviceSensor(SENSOR_PROXIMITY);
+      break;
+    case NS_DEVICE_LIGHT:
+      window->DisableDeviceSensor(SENSOR_LIGHT);
+      break;
     default:
       NS_WARNING("Disabling an unknown device sensor.");
       break;
   }
 }
 
 void
 nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, 
@@ -542,17 +558,18 @@ nsEventListenerManager::AddScriptEventLi
   nsCOMPtr<nsIDocument> doc;
 
   nsCOMPtr<nsIScriptGlobalObject> global;
 
   if (node) {
     // Try to get context from doc
     // XXX sXBL/XBL2 issue -- do we really want the owner here?  What
     // if that's the XBL document?
-    global = node->OwnerDoc()->GetScriptGlobalObject();
+    doc = node->OwnerDoc();
+    global = doc->GetScriptGlobalObject();
   } else {
     nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(mTarget));
     if (win) {
       NS_ASSERTION(win->IsInnerWindow(),
                    "Event listener added to outer window!");
 
       nsCOMPtr<nsIDOMDocument> domdoc;
       win->GetDocument(getter_AddRefs(domdoc));
--- a/content/events/test/test_bug238987.html
+++ b/content/events/test/test_bug238987.html
@@ -56,16 +56,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       modifier = Components.interfaces.nsIDOMNSEvent.SHIFT_MASK;
     } else if (modifier) {
       var expected = backwardFocusArray.pop();
       ok(expected == e.target.id,
          "(focus) Backward tabbing, expected [" +
          expected + "], got [" + e.target.id + "]");
     } else {
       var expected = forwardFocusArray.shift();
+      is(e.target, document.activeElement, "Wrong activeElement!");
       ok(expected == e.target.id,
          "(focus) Forward tabbing, expected [" +
          expected + "], got [" + e.target.id + "]");
     }
   }
 
   function handleWindowFocus(e) {
     --expectedWindowFocusCount;
--- a/content/events/test/test_dom_keyboard_event.html
+++ b/content/events/test/test_dom_keyboard_event.html
@@ -1,13 +1,14 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for DOM KeyboardEvent</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>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
@@ -134,18 +135,174 @@ function testInitializingUntrustedEvent(
     }
     for (var k = 0; k < kInvalidModifierName.length; k++) {
       ok(!e.getModifierState(kInvalidModifierName[k]),
          description + "getModifierState(\"" + kInvalidModifierName[k] + "\") returns wrong value");
     }
   }
 }
 
+function testSynthesizedKeyLocation()
+{
+  const kTests = [
+    { key: "a", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
+    },
+    { key: "VK_SHIFT", isModifier: true,
+      event: { shiftKey: true, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_LEFT },
+    },
+    { key: "VK_SHIFT", isModifier: true,
+      event: { shiftKey: true, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_RIGHT },
+    },
+    { key: "VK_CONTROL", isModifier: true,
+      event: { shiftKey: false, ctrlKey: true, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_LEFT },
+    },
+    { key: "VK_CONTROL", isModifier: true,
+      event: { shiftKey: false, ctrlKey: true, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_RIGHT },
+    },
+/* XXX Alt key activates menubar even if we consume the key events.
+    { key: "VK_ALT", isModifier: true,
+      event: { shiftKey: false, ctrlKey: false, altKey: true, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_LEFT },
+    },
+    { key: "VK_ALT", isModifier: true,
+      event: { shiftKey: false, ctrlKey: false, altKey: true, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_RIGHT },
+    },
+*/
+    { key: "VK_META", isModifier: true,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: true,
+               location: KeyboardEvent.DOM_KEY_LOCATION_LEFT },
+    },
+    { key: "VK_META", isModifier: true,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: true,
+               location: KeyboardEvent.DOM_KEY_LOCATION_RIGHT },
+    },
+    { key: "VK_DOWN", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
+    },
+    { key: "VK_DOWN", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
+    },
+    { key: "VK_DOWN", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_JOYSTICK },
+    },
+    { key: "5", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
+    },
+    { key: "VK_NUMPAD5", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
+    },
+    { key: "5", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_MOBILE },
+    },
+    { key: "VK_NUMPAD5", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_MOBILE },
+    },
+    { key: "+", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
+    },
+    { key: "VK_ADD", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
+    },
+    { key: "VK_ENTER", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
+    },
+    { key: "VK_ENTER", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
+    },
+    { key: "VK_NUM_LOCK", isModifier: true,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
+    },
+    { key: "VK_INSERT", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
+    },
+    { key: "VK_INSERT", isModifier: false,
+      event: { shiftKey: false, ctrlKey: false, altKey: false, metaKey: false,
+               location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
+    },
+  ];
+
+  function getLocationName(aLocation)
+  {
+    switch (aLocation) {
+      case KeyboardEvent.DOM_KEY_LOCATION_STANDARD:
+        return "DOM_KEY_LOCATION_STANDARD";
+      case KeyboardEvent.DOM_KEY_LOCATION_LEFT:
+        return "DOM_KEY_LOCATION_LEFT";
+      case KeyboardEvent.DOM_KEY_LOCATION_RIGHT:
+        return "DOM_KEY_LOCATION_RIGHT";
+      case KeyboardEvent.DOM_KEY_LOCATION_MOBILE:
+        return "DOM_KEY_LOCATION_MOBILE";
+      case KeyboardEvent.DOM_KEY_LOCATION_NUMPAD:
+        return "DOM_KEY_LOCATION_NUMPAD";
+      case KeyboardEvent.DOM_KEY_LOCATION_JOYSTICK:
+        return "DOM_KEY_LOCATION_JOYSTICK";
+      default:
+        return "Invalid value (" + aLocation + ")";
+    }
+  }
+
+  var currentTest, description;
+  var events = { keydown: false, keypress: false, keyup: false };
+
+  function handler(aEvent)
+  {
+    is(aEvent.location, currentTest.event.location,
+       description + "location of " + aEvent.type + " was invalid");
+    events[aEvent.type] = true;
+    aEvent.preventDefault();
+  }
+
+  window.addEventListener("keydown", handler, true);
+  window.addEventListener("keypress", handler, true);
+  window.addEventListener("keyup", handler, true);
+
+  for (var i = 0; i < kTests.length; i++) {
+    currentTest = kTests[i];
+    events = { keydown: false, keypress: false, keyup: false };
+    description = "testSynthesizedKeyLocation, " + i + ", key: " +
+      currentTest.key + ", location: " +
+      getLocationName(currentTest.event.location) + ": ";
+    synthesizeKey(currentTest.key, currentTest.event);
+    ok(events.keydown, description + "keydown event wasn't fired");
+    if (currentTest.isModifier) {
+      todo(events.keypress, description + "keypress event was fired for modifier key");
+    } else {
+      ok(events.keypress, description + "keypress event wasn't fired");
+    }
+    ok(events.keyup, description + "keyup event wasn't fired");
+  }
+
+  window.removeEventListener("keydown", handler, true);
+  window.removeEventListener("keypress", handler, true);
+  window.removeEventListener("keyup", handler, true);
+}
+
 function runTests()
 {
   testInitializingUntrustedEvent();
+  testSynthesizedKeyLocation();
   SimpleTest.finish();
 }
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/events/test/test_eventctors.html
+++ b/content/events/test/test_eventctors.html
@@ -364,16 +364,35 @@ ok(e.cancelable, "Event should be cancel
 is(e.key, "key", "Wrong value");
 is(e.oldValue, "oldValue", "Wrong value");
 is(e.newValue, "newValue", "Wrong value");
 is(e.url, "url", "Wrong value");
 is(e.storageArea, localStorage, "Wrong value");
 document.dispatchEvent(e);
 is(receivedEvent, e, "Wrong event!");
 
+// DeviceProximityEvent
+e = new DeviceProximityEvent("hello", {min: 0, value: 1, max: 2});
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event should not be trusted");
+is(e.value, 1, "value should be 1");
+is(e.min, 0, "min should be 0");
+is(e.max, 2, "max should be 2");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+// DeviceLightEvent
+e = new DeviceLightEvent("hello", {value: 1} );
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event should not be trusted");
+is(e.value, 1, "value should be 1");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+
 // MouseEvent
 
 try {
   e = new MouseEvent();
 } catch(exp) {
   ex = true;
 }
 ok(ex, "First parameter is required!");
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -295,16 +295,18 @@ public:
   static bool IsRawEnabled();
 #endif
 
 #ifdef MOZ_OGG
   static bool IsOggEnabled();
   static bool IsOggType(const nsACString& aType);
   static const char gOggTypes[3][16];
   static char const *const gOggCodecs[3];
+  static bool IsOpusEnabled();
+  static char const *const gOggCodecsWithOpus[4];
 #endif
 
 #ifdef MOZ_WAVE
   static bool IsWaveEnabled();
   static bool IsWaveType(const nsACString& aType);
   static const char gWaveTypes[4][16];
   static char const *const gWaveCodecs[2];
 #endif
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -1958,16 +1958,33 @@ const char nsHTMLMediaElement::gOggTypes
 };
 
 char const *const nsHTMLMediaElement::gOggCodecs[3] = {
   "vorbis",
   "theora",
   nsnull
 };
 
+char const *const nsHTMLMediaElement::gOggCodecsWithOpus[4] = {
+  "vorbis",
+  "opus",
+  "theora",
+  nsnull
+};
+
+bool
+nsHTMLMediaElement::IsOpusEnabled()
+{
+#ifdef MOZ_OPUS
+  return Preferences::GetBool("media.opus.enabled");
+#else
+  return false;
+#endif
+}
+
 bool
 nsHTMLMediaElement::IsOggEnabled()
 {
   return Preferences::GetBool("media.ogg.enabled");
 }
 
 bool
 nsHTMLMediaElement::IsOggType(const nsACString& aType)
@@ -2108,17 +2125,17 @@ nsHTMLMediaElement::CanHandleMediaType(c
 #ifdef MOZ_RAW
   if (IsRawType(nsDependentCString(aMIMEType))) {
     *aCodecList = gRawCodecs;
     return CANPLAY_MAYBE;
   }
 #endif
 #ifdef MOZ_OGG
   if (IsOggType(nsDependentCString(aMIMEType))) {
-    *aCodecList = gOggCodecs;
+    *aCodecList = IsOpusEnabled() ? gOggCodecsWithOpus : gOggCodecs;
     return CANPLAY_MAYBE;
   }
 #endif
 #ifdef MOZ_WAVE
   if (IsWaveType(nsDependentCString(aMIMEType))) {
     *aCodecList = gWaveCodecs;
     return CANPLAY_MAYBE;
   }
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -132,17 +132,16 @@ include $(topsrcdir)/config/rules.mk
 		test_bug392567.html \
 		bug392567.jar       \
 		bug392567.jar^headers^ \
 		test_bug394700.html \
 		test_bug395107.html \
 		test_bug401160.xhtml \
 		test_bug405242.html \
 		test_bug406596.html \
-		test_bug408231.html \
 		test_bug417760.html \
 		file_bug417760.png \
 		test_formSubmission.html \
 		test_formSubmission2.html \
 		file_formSubmission_text.txt \
 		file_formSubmission_img.jpg \
 		test_bug421640.html \
 		test_bug424698.html \
--- a/content/html/content/test/test_bug430351.html
+++ b/content/html/content/test/test_bug430351.html
@@ -211,23 +211,18 @@ var nonFocusableElements = [
     "<input disabled>",
 
     "<input type=\"button\" tabindex=\"0\" disabled>",
     "<input type=\"button\" disabled>",
 
     "<input type=\"checkbox\" tabindex=\"0\" disabled>",
     "<input type=\"checkbox\" disabled>",
 
-    "<input type=\"file\">",
-    "<input type=\"file\" tabindex=\"-1\">",
-    "<input type=\"file\" tabindex=\"0\">",
     "<input type=\"file\" tabindex=\"0\" disabled>",
-    "<input type=\"file\" tabindex=\"1\">",
     "<input type=\"file\" disabled>",
-    "<input type=\"file\" contenteditable=\"true\">",
 
     "<input type=\"hidden\">",
     "<input type=\"hidden\" tabindex=\"-1\">",
     "<input type=\"hidden\" tabindex=\"0\">",
     "<input type=\"hidden\" tabindex=\"0\" disabled>",
     "<input type=\"hidden\" tabindex=\"1\">",
     "<input type=\"hidden\" disabled>",
     "<input type=\"hidden\" contenteditable=\"true\">",
@@ -321,16 +316,22 @@ var focusableInContentEditable = [
     "<input contenteditable=\"true\">",
 
     "<input type=\"button\">",
     "<input type=\"button\" tabindex=\"-1\">",
     "<input type=\"button\" tabindex=\"0\">",
     "<input type=\"button\" tabindex=\"1\">",
     "<input type=\"button\" contenteditable=\"true\">",
 
+    "<input type=\"file\">",
+    "<input type=\"file\" tabindex=\"-1\">",
+    "<input type=\"file\" tabindex=\"0\">",
+    "<input type=\"file\" tabindex=\"1\">",
+    "<input type=\"file\" contenteditable=\"true\">",
+
     "<input type=\"checkbox\">",
     "<input type=\"checkbox\" tabindex=\"-1\">",
     "<input type=\"checkbox\" tabindex=\"0\">",
     "<input type=\"checkbox\" tabindex=\"1\">",
     "<input type=\"checkbox\" contenteditable=\"true\">",
 
     "<input type=\"image\">",
     "<input type=\"image\" tabindex=\"-1\">",
@@ -451,16 +452,23 @@ function testElements(parent, tags, shou
         if (element.nodeName == "IFRAME" && element.hasAttribute("src"))
             var foo = element.contentDocument;
 
         element.focus();
 
         var errorPrefix = serializer.serializeToString(element) + " in " +
                           serializer.serializeToString(parent);
 
+        try {
+          // Make sure activeElement doesn't point to a
+          // native anonymous element.
+          parent.ownerDocument.activeElement.localName;
+        } catch (ex) {
+          ok(false, ex + errorPrefix + errorSuffix);
+        }
         if (focusable ? focusable.indexOf(tag) > -1 : shouldBeFocusable) {
             is(parent.ownerDocument.activeElement, element,
                errorPrefix + " should be focusable" + errorSuffix);
         }
         else {
             isnot(parent.ownerDocument.activeElement, element,
                   errorPrefix + " should not be focusable" + errorSuffix);
         }
--- a/content/html/document/test/Makefile.in
+++ b/content/html/document/test/Makefile.in
@@ -65,20 +65,18 @@ include $(topsrcdir)/config/rules.mk
 		test_bug359657.html \
 		test_bug369370.html \
 		bug369370-popup.png \
 		test_bug380383.html \
 		test_bug391777.html \
 		test_bug402680.html \
 		test_bug403868.html \
 		test_bug403868.xhtml \
-		test_bug404320.html \
 		$(warning test_bug435128.html disabled because it takes 60 seconds) \
 		test_bug463104.html \
-		test_bug468353.html \
 		test_form-parsing.html \
 		test_viewport.html \
 		test_documentAll.html \
 		test_document-element-inserted.html \
 		test_bug445004.html \
 		bug445004-inner.js \
 		bug445004-outer-rel.html \
 		bug445004-outer-abs.html \
@@ -101,17 +99,16 @@ include $(topsrcdir)/config/rules.mk
 		test_bug497242.xhtml \
 		test_bug499092.html \
 		bug499092.xml \
 		bug499092.html \
 		test_bug512367.html \
 		test_bug571981.html \
 		test_bug677495.html \
 		test_bug677495-1.html \
-		test_bug742261.html \
 		test_bug741266.html \
 		$(NULL)
 
 ifneq (mobile,$(MOZ_BUILD_APP))
 _BROWSER_TEST_FILES = \
 		browser_bug592641.js \
 		bug592641_img.jpg \
 		$(NULL)
--- a/content/media/ogg/nsOggCodecState.cpp
+++ b/content/media/ogg/nsOggCodecState.cpp
@@ -48,25 +48,53 @@
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gBuiltinDecoderLog;
 #define LOG(type, msg) PR_LOG(gBuiltinDecoderLog, type, msg)
 #else
 #define LOG(type, msg)
 #endif
 
+// Reads a little-endian encoded unsigned 32bit integer at p.
+static PRUint32 LEUint32(const unsigned char* p)
+{
+  return p[0] +
+        (p[1] << 8) +
+        (p[2] << 16) +
+        (p[3] << 24);
+}
+
+// Reads a little-endian encoded 64bit integer at p.
+static PRInt64 LEInt64(const unsigned char* p)
+{
+  PRUint32 lo = LEUint32(p);
+  PRUint32 hi = LEUint32(p + 4);
+  return static_cast<PRInt64>(lo) | (static_cast<PRInt64>(hi) << 32);
+}
+
+// Reads a little-endian encoded unsigned 16bit integer at p.
+static PRUint16 LEUint16(const unsigned char* p)
+{
+  return p[0] + (p[1] << 8);
+}
+
+/** Decoder base class for Ogg-encapsulated streams. */
 nsOggCodecState*
 nsOggCodecState::Create(ogg_page* aPage)
 {
   NS_ASSERTION(ogg_page_bos(aPage), "Only call on BOS page!");
   nsAutoPtr<nsOggCodecState> codecState;
   if (aPage->body_len > 6 && memcmp(aPage->body+1, "theora", 6) == 0) {
     codecState = new nsTheoraState(aPage);
   } else if (aPage->body_len > 6 && memcmp(aPage->body+1, "vorbis", 6) == 0) {
     codecState = new nsVorbisState(aPage);
+#ifdef MOZ_OPUS
+  } else if (aPage->body_len > 8 && memcmp(aPage->body, "OpusHead", 8) == 0) {
+    codecState = new nsOpusState(aPage);
+#endif
   } else if (aPage->body_len > 8 && memcmp(aPage->body, "fishead\0", 8) == 0) {
     codecState = new nsSkeletonState(aPage);
   } else {
     codecState = new nsOggCodecState(aPage, false);
   }
   return codecState->nsOggCodecState::Init() ? codecState.forget() : nsnull;
 }
 
@@ -745,22 +773,188 @@ nsresult nsVorbisState::ReconstructVorbi
 
   mPrevVorbisBlockSize = vorbis_packet_blocksize(&mInfo, last);
   mPrevVorbisBlockSize = NS_MAX(static_cast<long>(0), mPrevVorbisBlockSize);
   mGranulepos = last->granulepos;
 
   return NS_OK;
 }
 
+#ifdef MOZ_OPUS
+nsOpusState::nsOpusState(ogg_page* aBosPage) :
+  nsOggCodecState(aBosPage, true),
+  mRate(0),
+  mNominalRate(0),
+  mChannels(0),
+  mPreSkip(0),
+  mGain(0.0),
+  mChannelMapping(0),
+  mStreams(0),
+  mDecoder(NULL)
+{
+  MOZ_COUNT_CTOR(nsOpusState);
+}
 
-nsSkeletonState::nsSkeletonState(ogg_page* aBosPage)
-  : nsOggCodecState(aBosPage, true),
-    mVersion(0),
-    mPresentationTime(0),
-    mLength(0)
+nsOpusState::~nsOpusState() {
+  MOZ_COUNT_DTOR(nsOpusState);
+  Reset();
+
+  if (mDecoder) {
+    opus_decoder_destroy(mDecoder);
+    mDecoder = NULL;
+  }
+}
+
+nsresult nsOpusState::Reset()
+{
+  nsresult res = NS_OK;
+
+  if (mActive && mDecoder) {
+    // Reset the decoder.
+    opus_decoder_ctl(mDecoder, OPUS_RESET_STATE);
+  }
+
+  // Clear queued data.
+  if (NS_FAILED(nsOggCodecState::Reset())) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return res;
+}
+
+bool nsOpusState::Init(void)
+{
+  int error;
+
+  NS_ASSERTION(mDecoder == NULL, "leaking OpusDecoder");
+
+  mDecoder = opus_decoder_create(mRate, mChannels, &error);
+
+  return error == OPUS_OK;
+}
+
+bool nsOpusState::DecodeHeader(ogg_packet* aPacket)
+{
+  // Minimum length of any header is 16 bytes.
+  if (aPacket->bytes < 16) {
+    LOG(PR_LOG_DEBUG, ("Invalid Opus file: header too short"));
+    mActive = false;
+    return true;
+  }
+
+  // Try parsing as the metadata header.
+  if (!memcmp(aPacket->packet, "OpusTags", 8)) {
+    mDoneReadingHeaders = true; // This is the last Opus header.
+    mActive = true;
+    return true;
+  }
+
+  // Otherwise, parse as the id header.
+  if (aPacket->bytes < 19 || memcmp(aPacket->packet, "OpusHead\0", 9)) {
+    LOG(PR_LOG_DEBUG, ("Invalid Opus file: unrecognized header"));
+    mActive = false;
+    return true;
+  }
+
+  mRate = 48000; // The Opus decoder runs at 48 kHz regardless.
+
+  mChannels= aPacket->packet[9];
+  mPreSkip = LEUint16(aPacket->packet + 10);
+  mNominalRate = LEUint32(aPacket->packet + 12);
+  mGain = (float)LEUint16(aPacket->packet + 16) / 256.0;
+  mChannelMapping = aPacket->packet[18];
+
+  if (mChannelMapping == 0) {
+    mStreams = 1;
+  } else if (aPacket->bytes > 19) {
+    mStreams = aPacket->packet[19];
+  } else {
+    LOG(PR_LOG_DEBUG, ("Invalid Opus file: channel mapping %d,"
+                       " but no channel mapping table", mChannelMapping));
+    mActive = false;
+    return true;
+  }
+
+  return true;
+}
+
+/* Return the timestamp (in microseconds) equivalent to a granulepos. */
+PRInt64 nsOpusState::Time(PRInt64 granulepos)
+{
+  if (granulepos < 0)
+    return -1;
+
+  // Ogg Opus always runs at a granule rate of 48 kHz.
+  CheckedInt64 t = CheckedInt64(granulepos - mPreSkip) * USECS_PER_S;
+  return t.valid() ? t.value() / mRate : -1;
+}
+
+bool nsOpusState::IsHeader(ogg_packet* aPacket)
+{
+  return aPacket->bytes >= 16 &&
+         (!memcmp(aPacket->packet, "OpusHead\0", 9) ||
+          !memcmp(aPacket->packet, "OpusTags", 8));
+}
+
+nsresult nsOpusState::PageIn(ogg_page* aPage)
+{
+  if (!mActive)
+    return NS_OK;
+  NS_ASSERTION(static_cast<PRUint32>(ogg_page_serialno(aPage)) == mSerial,
+               "Page must be for this stream!");
+  if (ogg_stream_pagein(&mState, aPage) == -1)
+    return NS_ERROR_FAILURE;
+
+  bool haveGranulepos;
+  nsresult rv = PacketOutUntilGranulepos(haveGranulepos);
+  if (NS_FAILED(rv) || !haveGranulepos || !mDoneReadingHeaders)
+    return rv;
+  ReconstructGranulepos();
+  for (PRUint32 i = 0; i < mUnstamped.Length(); i++) {
+    ogg_packet* packet = mUnstamped[i];
+    NS_ASSERTION(!IsHeader(packet), "Don't try to play a header packet");
+    NS_ASSERTION(packet->granulepos != -1, "Packet should have a granulepos");
+    mPackets.Append(packet);
+  }
+  mUnstamped.Clear();
+  return NS_OK;
+}
+
+void nsOpusState::ReconstructGranulepos(void)
+{
+  NS_ASSERTION(mUnstamped.Length() > 0, "Must have unstamped packets");
+  ogg_packet* last = mUnstamped[mUnstamped.Length()-1];
+  NS_ASSERTION(last->e_o_s || last->granulepos > 0,
+      "Must know last granulepos!");
+
+  // Loop through the packets backwards, subtracting the next
+  // packet's duration from its granulepos to get the value
+  // for the current packet.
+  for (PRUint32 i = mUnstamped.Length() - 1; i > 0; i--) {
+    ogg_packet* next = mUnstamped[i];
+    int offset = opus_decoder_get_nb_samples(mDecoder,
+                                             next->packet,
+                                             next->bytes);
+    // Check for error (negative offset) and overflow.
+    if (offset >= 0 && offset <= next->granulepos) {
+      mUnstamped[i - 1]->granulepos = next->granulepos - offset;
+    } else {
+      if (offset > next->granulepos)
+        NS_WARNING("Clamping negative Opus granulepos to zero.");
+      mUnstamped[i - 1]->granulepos = 0;
+    }
+  }
+}
+#endif /* MOZ_OPUS */
+
+nsSkeletonState::nsSkeletonState(ogg_page* aBosPage) :
+  nsOggCodecState(aBosPage, true),
+  mVersion(0),
+  mPresentationTime(0),
+  mLength(0)
 {
   MOZ_COUNT_CTOR(nsSkeletonState);
 }
  
 nsSkeletonState::~nsSkeletonState()
 {
   MOZ_COUNT_DTOR(nsSkeletonState);
 }
@@ -805,39 +999,16 @@ static bool IsSkeletonBOS(ogg_packet* aP
 }
 
 static bool IsSkeletonIndex(ogg_packet* aPacket)
 {
   return aPacket->bytes >= SKELETON_4_0_MIN_INDEX_LEN &&
          memcmp(reinterpret_cast<char*>(aPacket->packet), "index", 5) == 0;
 }
 
-// Reads a little-endian encoded unsigned 32bit integer at p.
-static PRUint32 LEUint32(const unsigned char* p)
-{
-  return p[0] +
-        (p[1] << 8) + 
-        (p[2] << 16) +
-        (p[3] << 24);
-}
-
-// Reads a little-endian encoded 64bit integer at p.
-static PRInt64 LEInt64(const unsigned char* p)
-{
-  PRUint32 lo = LEUint32(p);
-  PRUint32 hi = LEUint32(p + 4);
-  return static_cast<PRInt64>(lo) | (static_cast<PRInt64>(hi) << 32);
-}
-
-// Reads a little-endian encoded unsigned 16bit integer at p.
-static PRUint16 LEUint16(const unsigned char* p)
-{
-  return p[0] + (p[1] << 8);  
-}
-
 // Reads a variable length encoded integer at p. Will not read
 // past aLimit. Returns pointer to character after end of integer.
 static const unsigned char* ReadVariableLengthInt(const unsigned char* p,
                                                   const unsigned char* aLimit,
                                                   PRInt64& n)
 {
   int shift = 0;
   PRInt64 byte = 0;
--- a/content/media/ogg/nsOggCodecState.h
+++ b/content/media/ogg/nsOggCodecState.h
@@ -41,16 +41,19 @@
 
 #include <ogg/ogg.h>
 #include <theora/theoradec.h>
 #ifdef MOZ_TREMOR
 #include <tremor/ivorbiscodec.h>
 #else
 #include <vorbis/codec.h>
 #endif
+#ifdef MOZ_OPUS
+#include <opus/opus.h>
+#endif
 #include <nsDeque.h>
 #include <nsTArray.h>
 #include <nsClassHashtable.h>
 #include "VideoUtils.h"
 
 #include "mozilla/StandardInteger.h"
 
 // Uncomment the following to validate that we're predicting the number
@@ -96,18 +99,19 @@ public:
 // Encapsulates the data required for decoding an ogg bitstream and for
 // converting granulepos to timestamps.
 class nsOggCodecState {
 public:
   // Ogg types we know about
   enum CodecType {
     TYPE_VORBIS=0,
     TYPE_THEORA=1,
-    TYPE_SKELETON=2,
-    TYPE_UNKNOWN=3
+    TYPE_OPUS=2,
+    TYPE_SKELETON=3,
+    TYPE_UNKNOWN=4
   };
 
   virtual ~nsOggCodecState();
   
   // Factory for creating nsCodecStates. Use instead of constructor.
   // aPage should be a beginning-of-stream page.
   static nsOggCodecState* Create(ogg_page* aPage);
   
@@ -314,16 +318,52 @@ private:
   // mUnstamped array. mUnstamped must be filled with consecutive packets from
   // the stream, with the last packet having a known granulepos. Using this
   // known granulepos, and the known frame numbers, we recover the granulepos
   // of all frames in the array. This enables us to determine their timestamps.
   void ReconstructTheoraGranulepos();
 
 };
 
+class nsOpusState : public nsOggCodecState {
+#ifdef MOZ_OPUS
+public:
+  nsOpusState(ogg_page* aBosPage);
+  virtual ~nsOpusState();
+
+  CodecType GetType() { return TYPE_OPUS; }
+  bool DecodeHeader(ogg_packet* aPacket);
+  PRInt64 Time(PRInt64 granulepos);
+  bool Init();
+  nsresult Reset();
+  bool IsHeader(ogg_packet* aPacket);
+  nsresult PageIn(ogg_page* aPage);
+
+  // Various fields from the Ogg Opus header.
+  int mRate;        // Sample rate the decoder uses (always 48 kHz).
+  int mNominalRate; // Original sample rate of the data (informational).
+  int mChannels;    // Number of channels the stream encodes.
+  int mPreSkip;     // Number of samples to strip after decoder reset.
+  float mGain;      // Gain (dB) to apply to decoder output.
+  int mChannelMapping; // Channel mapping family.
+  int mStreams;     // Number of packed streams in each packet.
+
+  OpusDecoder *mDecoder;
+
+private:
+
+  // Reconstructs the granulepos of Opus packets stored in the
+  // mUnstamped array. mUnstamped must be filled with consecutive packets from
+  // the stream, with the last packet having a known granulepos. Using this
+  // known granulepos, and the known frame numbers, we recover the granulepos
+  // of all frames in the array. This enables us to determine their timestamps.
+  void ReconstructGranulepos();
+#endif /* MOZ_OPUS */
+};
+
 // Constructs a 32bit version number out of two 16 bit major,minor
 // version numbers.
 #define SKELETON_VERSION(major, minor) (((major)<<16)|(minor))
 
 class nsSkeletonState : public nsOggCodecState {
 public:
   nsSkeletonState(ogg_page* aBosPage);
   ~nsSkeletonState();
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -37,16 +37,19 @@
  *
  * ***** END LICENSE BLOCK ***** */
 #include "nsError.h"
 #include "nsBuiltinDecoderStateMachine.h"
 #include "nsBuiltinDecoder.h"
 #include "nsOggReader.h"
 #include "VideoUtils.h"
 #include "theora/theoradec.h"
+#ifdef MOZ_OPUS
+#include "opus/opus.h"
+#endif
 #include "nsTimeRanges.h"
 #include "mozilla/TimeStamp.h"
 
 using namespace mozilla;
 
 // Un-comment to enable logging of seek bisections.
 //#define SEEK_LOGGING
 
@@ -100,16 +103,18 @@ public:
 private:
   ogg_packet* mPacket;
 };
 
 nsOggReader::nsOggReader(nsBuiltinDecoder* aDecoder)
   : nsBuiltinDecoderReader(aDecoder),
     mTheoraState(nsnull),
     mVorbisState(nsnull),
+    mOpusState(nsnull),
+    mOpusEnabled(nsHTMLMediaElement::IsOpusEnabled()),
     mSkeletonState(nsnull),
     mVorbisSerial(0),
     mTheoraSerial(0),
     mPageOffset(0)
 {
   MOZ_COUNT_CTOR(nsOggReader);
   memset(&mTheoraInfo, 0, sizeof(mTheoraInfo));
 }
@@ -140,16 +145,19 @@ nsresult nsOggReader::ResetDecode()
     res = NS_ERROR_FAILURE;
   }
 
   // Discard any previously buffered packets/pages.
   ogg_sync_reset(&mOggState);
   if (mVorbisState && NS_FAILED(mVorbisState->Reset())) {
     res = NS_ERROR_FAILURE;
   }
+  if (mOpusState && NS_FAILED(mOpusState->Reset())) {
+    res = NS_ERROR_FAILURE;
+  }
   if (mTheoraState && NS_FAILED(mTheoraState->Reset())) {
     res = NS_ERROR_FAILURE;
   }
 
   return res;
 }
 
 bool nsOggReader::ReadHeaders(nsOggCodecState* aState)
@@ -213,16 +221,27 @@ nsresult nsOggReader::ReadMetadata(nsVid
           codecState->GetType() == nsOggCodecState::TYPE_THEORA &&
           !mTheoraState)
       {
         // First Theora bitstream, we'll play this one. Subsequent Theora
         // bitstreams will be ignored.
         mTheoraState = static_cast<nsTheoraState*>(codecState);
       }
       if (codecState &&
+          codecState->GetType() == nsOggCodecState::TYPE_OPUS &&
+          !mOpusState)
+      {
+        if (mOpusEnabled) {
+          mOpusState = static_cast<nsOpusState*>(codecState);
+        } else {
+          NS_WARNING("Opus decoding disabled."
+                     " See media.opus.enabled in about:config");
+        }
+      }
+      if (codecState &&
           codecState->GetType() == nsOggCodecState::TYPE_SKELETON &&
           !mSkeletonState)
       {
         mSkeletonState = static_cast<nsSkeletonState*>(codecState);
       }
     }
 
     mCodecStates.Get(serial, &codecState);
@@ -235,17 +254,18 @@ nsresult nsOggReader::ReadMetadata(nsVid
 
   // We've read all BOS pages, so we know the streams contained in the media.
   // Now process all available header packets in the active Theora, Vorbis and
   // Skeleton streams.
 
   // Deactivate any non-primary bitstreams.
   for (PRUint32 i = 0; i < bitstreams.Length(); i++) {
     nsOggCodecState* s = bitstreams[i];
-    if (s != mVorbisState && s != mTheoraState && s != mSkeletonState) {
+    if (s != mVorbisState && s != mOpusState &&
+        s != mTheoraState && s != mSkeletonState) {
       s->Deactivate();
     }
   }
 
   if (mTheoraState && ReadHeaders(mTheoraState)) {
     nsIntRect picture = nsIntRect(mTheoraState->mInfo.pic_x,
                                   mTheoraState->mInfo.pic_y,
                                   mTheoraState->mInfo.pic_width,
@@ -285,17 +305,23 @@ nsresult nsOggReader::ReadMetadata(nsVid
     mInfo.mAudioChannels = mVorbisState->mInfo.channels;
     // Copy Vorbis info data for time computations on other threads.
     memcpy(&mVorbisInfo, &mVorbisState->mInfo, sizeof(mVorbisInfo));
     mVorbisInfo.codec_setup = NULL;
     mVorbisSerial = mVorbisState->mSerial;
   } else {
     memset(&mVorbisInfo, 0, sizeof(mVorbisInfo));
   }
-
+#ifdef MOZ_OPUS
+  if (mOpusState && ReadHeaders(mOpusState)) {
+    mInfo.mHasAudio = true;
+    mInfo.mAudioRate = mOpusState->mRate;
+    mInfo.mAudioChannels = mOpusState->mChannels;
+  }
+#endif
   if (mSkeletonState) {
     if (!HasAudio() && !HasVideo()) {
       // We have a skeleton track, but no audio or video, may as well disable
       // the skeleton, we can't do anything useful with this media.
       mSkeletonState->Deactivate();
     } else if (ReadHeaders(mSkeletonState) && mSkeletonState->HasIndex()) {
       // Extract the duration info out of the index, so we don't need to seek to
       // the end of resource to get it.
@@ -381,39 +407,110 @@ nsresult nsOggReader::DecodeVorbis(ogg_p
                                    channels));
     endFrame -= frames;
     if (vorbis_synthesis_read(&mVorbisState->mDsp, frames) != 0) {
       return NS_ERROR_FAILURE;
     }
   }
   return NS_OK;
 }
+#ifdef MOZ_OPUS
+nsresult nsOggReader::DecodeOpus(ogg_packet* aPacket) {
+  NS_ASSERTION(aPacket->granulepos != -1, "Must know opus granulepos!");
+
+  PRInt32 frames = opus_decoder_get_nb_samples(mOpusState->mDecoder,
+                                               aPacket->packet,
+                                               aPacket->bytes);
+  if (frames <= 0)
+    return NS_ERROR_FAILURE;
+  PRUint32 channels = mOpusState->mChannels;
+  nsAutoArrayPtr<AudioDataValue> buffer(new AudioDataValue[frames * channels]);
+
+  // Decode to the appropriate sample type.
+#ifdef MOZ_SAMPLE_TYPE_FLOAT32
+  int ret = opus_decode_float(mOpusState->mDecoder,
+                              aPacket->packet, aPacket->bytes,
+                              buffer, frames, false);
+#else
+  int ret = opus_decode(mOpusState->mDecoder,
+                        aPacket->packet, aPacket->bytes,
+                        buffer, frames, false);
+#endif
+  if (ret < 0)
+    return NS_ERROR_FAILURE;
+  NS_ASSERTION(ret == frames, "Opus decoded too few audio samples");
+
+  PRInt64 endFrame = aPacket->granulepos;
+  PRInt64 endTime = mOpusState->Time(endFrame);
+  PRInt64 startTime = mOpusState->Time(endFrame - frames);
+  PRInt64 duration = endTime - startTime;
+
+  // Trim the initial samples.
+  if (endTime < 0)
+    return NS_OK;
+  if (startTime < 0) {
+    PRInt32 skip = mOpusState->mPreSkip;
+    PRInt32 goodFrames = frames - skip;
+    NS_ASSERTION(goodFrames > 0, "endTime calculation was wrong");
+    nsAutoArrayPtr<AudioDataValue> goodBuffer(new AudioDataValue[goodFrames * channels]);
+    for (int i = 0; i < goodFrames*channels; i++)
+      goodBuffer[i] = buffer[skip*channels + i];
+
+    startTime = mOpusState->Time(endFrame - goodFrames);
+    duration = endTime - startTime;
+    frames = goodFrames;
+    buffer = goodBuffer;
+  }
+
+  mAudioQueue.Push(new AudioData(mPageOffset,
+                                 startTime,
+                                 duration,
+                                 frames,
+                                 buffer.forget(),
+                                 channels));
+  return NS_OK;
+}
+#endif /* MOZ_OPUS */
 
 bool nsOggReader::DecodeAudioData()
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
-  NS_ASSERTION(mVorbisState!=0, "Need Vorbis state to decode audio");
+  NS_ASSERTION(mVorbisState != nsnull || mOpusState != nsnull,
+    "Need audio codec state to decode audio");
 
   // Read the next data packet. Skip any non-data packets we encounter.
   ogg_packet* packet = 0;
+  nsOggCodecState* codecState;
+  if (mVorbisState)
+    codecState = static_cast<nsOggCodecState*>(mVorbisState);
+  else
+    codecState = static_cast<nsOggCodecState*>(mOpusState);
   do {
     if (packet) {
       nsOggCodecState::ReleasePacket(packet);
     }
-    packet = NextOggPacket(mVorbisState);
-  } while (packet && mVorbisState->IsHeader(packet));
+    packet = NextOggPacket(codecState);
+  } while (packet && codecState->IsHeader(packet));
+
   if (!packet) {
     mAudioQueue.Finish();
     return false;
   }
 
   NS_ASSERTION(packet && packet->granulepos != -1,
     "Must have packet with known granulepos");
   nsAutoReleasePacket autoRelease(packet);
-  DecodeVorbis(packet);
+  if (mVorbisState) {
+    DecodeVorbis(packet);
+#ifdef MOZ_OPUS
+  } else if (mOpusState) {
+    DecodeOpus(packet);
+#endif
+  }
+
   if (packet->e_o_s) {
     // We've encountered an end of bitstream packet, or we've hit the end of
     // file while trying to decode, so inform the audio queue that there'll
     // be no more samples.
     mAudioQueue.Finish();
     return false;
   }
 
@@ -1290,21 +1387,24 @@ nsresult nsOggReader::SeekBisection(PRIn
         mCodecStates.Get(serial, &codecState);
         if (codecState && codecState->mActive) {
           int ret = ogg_stream_pagein(&codecState->mState, &page);
           NS_ENSURE_TRUE(ret == 0, NS_ERROR_FAILURE);
         }
 
         ogg_int64_t granulepos = ogg_page_granulepos(&page);
 
-        if (HasAudio() &&
-            granulepos > 0 &&
-            serial == mVorbisState->mSerial &&
-            audioTime == -1) {
-          audioTime = mVorbisState->Time(granulepos);
+        if (HasAudio() && granulepos > 0 && audioTime == -1) {
+          if (mVorbisState && serial == mVorbisState->mSerial) {
+            audioTime = mVorbisState->Time(granulepos);
+#ifdef MOZ_OPUS
+          } else if (mOpusState && serial == mOpusState->mSerial) {
+            audioTime = mOpusState->Time(granulepos);
+#endif
+          }
         }
         
         if (HasVideo() &&
             granulepos > 0 &&
             serial == mTheoraState->mSerial &&
             videoTime == -1) {
           videoTime = mTheoraState->StartTime(granulepos);
         }
--- a/content/media/ogg/nsOggReader.h
+++ b/content/media/ogg/nsOggReader.h
@@ -67,17 +67,18 @@ public:
 
   // If the Theora granulepos has not been captured, it may read several packets
   // until one with a granulepos has been captured, to ensure that all packets
   // read have valid time info.  
   virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
                                   PRInt64 aTimeThreshold);
 
   virtual bool HasAudio() {
-    return mVorbisState != 0 && mVorbisState->mActive;
+    return (mVorbisState != 0 && mVorbisState->mActive) ||
+           (mOpusState != 0 && mOpusState->mActive);
   }
 
   virtual bool HasVideo() {
     return mTheoraState != 0 && mTheoraState->mActive;
   }
 
   virtual nsresult ReadMetadata(nsVideoInfo* aInfo);
   virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
@@ -211,16 +212,20 @@ private:
                             PRInt64 aEndTime,
                             bool aExact);
 private:
 
   // Decodes a packet of Vorbis data, and inserts its samples into the 
   // audio queue.
   nsresult DecodeVorbis(ogg_packet* aPacket);
 
+  // Decodes a packet of Opus data, and inserts its samples into the
+  // audio queue.
+  nsresult DecodeOpus(ogg_packet* aPacket);
+
   // Decodes a packet of Theora data, and inserts its frame into the
   // video queue. May return NS_ERROR_OUT_OF_MEMORY. Caller must have obtained
   // the reader's monitor. aTimeThreshold is the current playback position
   // in media time in microseconds. Frames with an end time before this will
   // not be enqueued.
   nsresult DecodeTheora(ogg_packet* aPacket, PRInt64 aTimeThreshold);
 
   // Read a page of data from the Ogg file. Returns the offset of the start
@@ -248,16 +253,24 @@ private:
   nsAutoTArray<PRUint32,4> mKnownStreams;
 
   // Decode state of the Theora bitstream we're decoding, if we have video.
   nsTheoraState* mTheoraState;
 
   // Decode state of the Vorbis bitstream we're decoding, if we have audio.
   nsVorbisState* mVorbisState;
 
+  // Decode state of the Opus bitstream we're decoding, if we have one.
+  nsOpusState *mOpusState;
+
+  // Represents the user pref media.opus.enabled at the time our
+  // contructor was called. We can't check it dynamically because
+  // we're not on the main thread;
+  bool mOpusEnabled;
+
   // Decode state of the Skeleton bitstream.
   nsSkeletonState* mSkeletonState;
 
   // Ogg decoding state.
   ogg_sync_state mOggState;
 
   // Vorbis/Theora data used to compute timestamps. This is written on the
   // decoder thread and read on the main thread. All reading on the main
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -227,16 +227,17 @@ endif
 		seek.webm \
 		seek.yuv \
 		short-video.ogv \
 		small-shot.ogg \
 		sound.ogg \
 		spacestorm-1000Hz-100ms.ogg \
 		video-overhang.ogg \
 		file_a4_tone.ogg \
+		detodos.opus \
 		$(NULL)
 
 # Wave sample files
 _TEST_FILES += \
 		big.wav \
 		bogus.wav \
 		r11025_msadpcm_c1.wav \
 		r11025_s16_c1.wav \
--- a/content/media/test/can_play_type_ogg.js
+++ b/content/media/test/can_play_type_ogg.js
@@ -10,13 +10,29 @@ function check_ogg(v, enabled) {
 
   // Supported Ogg codecs
   check("audio/ogg; codecs=vorbis", "probably");
   check("video/ogg; codecs=vorbis", "probably");
   check("video/ogg; codecs=vorbis,theora", "probably");
   check("video/ogg; codecs=\"vorbis, theora\"", "probably");
   check("video/ogg; codecs=theora", "probably");
 
+  // Verify Opus support
+  var OpusEnabled = undefined;
+  try {
+    OpusEnabled = SpecialPowers.getBoolPref("media.opus.enabled");
+  } catch (ex) {
+    // SpecialPowers failed, perhaps because Opus isn't compiled in
+    console.log("media.opus.enabled pref not found; skipping Opus validation");
+  }
+  if (OpusEnabled !== undefined) {
+    SpecialPowers.setBoolPref("media.opus.enabled", true);
+    check("audio/ogg; codecs=opus", "probably");
+    SpecialPowers.setBoolPref("media.opus.enabled", false);
+    check("audio/ogg; codecs=opus", "");
+    SpecialPowers.setBoolPref("media.opus.enabled", OpusEnabled);
+  }
+
   // Unsupported Ogg codecs
   check("video/ogg; codecs=xyz", "");
   check("video/ogg; codecs=xyz,vorbis", "");
   check("video/ogg; codecs=vorbis,xyz", "");
 }
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6c7ba88a668fed66f4cf5eecbe7bdc5abda02403
GIT binary patch
literal 6270
zc$`g_1yoc~x5s5bx)qSl0frn>T2e0Er6}Dgjnpu7hop3Or*ugR0@4UWN=S|f2*Mk`
z_pP_yUF)uW&pp4j_gVMub^iaOVPm872=wT`m+QAVp?@)IUoR5viH57EJ78sI`3Ow}
z4c7S|K;s|&=>OwrsQ4Ef+KguM57#xbai>DPakMjcK@Az8Jfb|J-2D99HWn7<!cY-&
z+<&#GQMZSkhohCGycL6oi=~S@4}+$eo7sP#Nm0{gZXR~-9+GM<@9i8N&3IhgZ2q_O
zf7kJ!(*IHkvqzcogISpw8EM#=`30Z?P;P!cK5i&0gp-3C%EZ9LM8`-^%Pzpl$<D#a
z$;Hab#7NJ|00uzO%fF*Pl!f=!tq65H@U*=MXWXPfh?<knR8d^N4;CaKI%NR3sGpt+
z7L<uPnQ;*+9Nq6^2C~aHP{x04U$e1yjaN;ie*W<;7~qc6Y#AC*Z<_AJUo0dla%Kn=
z!8*n53JS4Jvh*)MCwyxQ@G8pP%qi_jOtF7eLN?)jA|as6ko{o30YiQfTG{W)M*$E(
zDsO91b;^eHb}j{T_QiB>e^TyVPXUYTc*^NlfEUcee&HZe``F}9R(gda=*2~}Rbh>-
z*Q2&I05;J$71nKa@d+6t<FHcW`9><Zyk6r3sT}NuTUlj#G)2;E6+)N@gb;2pwjE-U
zt)|Y7@dj6hvfhEuCw+}*SiGdNHRTNWlG}lj{E!}@_Ac12a%WQxh9Q3I`4lzyPGb*8
zuLU2ubu}UBE<_RiXS8hPP2_IhTFwv{s1(@ypm)BbMk;Yf>*9><4-Wixgtyw&o$yi?
z(StY1Aa37^K&K|+m=!1?Az{&?VKW74=`-<4Vjc0KWixNUy5v4t-LeH8)B-WN+xEU?
zwb>u<<+3xhD@0XRkkqqR+^Rrjw;)gYpOpZNw~OU`S$|lnEd=F8wARztN;@bIwOaYe
zk;jCGy<?3YG(>deHbV>ieL&d;L}9dLi;Pb=1b;s%f($Bbj3FW(>5c!SDEn=4T7T#|
zI(e8i*^sWs+VZK1CQ!<L3;UvLf7(Msif4zIWnRW*P^=Nl#yKwDSI}1uOX1)bSezf2
zx!sGvh5>~T_S?b$z5c^bm)rG0CodEp=X5^z%3V-UdKo!sOp;~*2OiTz=bs#m-}$&3
zl^Q<<@*l{l>pnk&I~NK3`~pX(Qo9nlI21i83X)14n^%RH|8{wPoTU_ok6w|*wkaOu
z59F?wLGCWFlXl?&?H?}JH{_iJS(}7O?t{&rqc@UgUwUs)+RI=I`;N?LayMO^ZvipV
zQ?yB4b6Y0pJz1hZn89k(_&wIFj`z`e_-!HMUg(C`bPZBn_h&b^*^hzPsuvyGnOdtH
zI!AuS>=Ee2Dim`R3(%8Z);FXThXXoYYYk(ECP8G{7-8cC-O@nZo3W67>SFb1+MRZ7
zMVtY@+Nc5jtizbOBud-~Q&H<jM07{_K%DI}fiIjG1_{(ab<z{ay=G-x8vpOVY6o^?
z%kfwK(Gtm*mL~=~b3mMLqZo#RAJd2QHhstT%I~M8MLHS5%MR_vbg77e<@sRov!?Tb
zw`MRwAXa^c<|cuXRNc@M5z#O~w>Wq9@m-aM_9w2qSPGI`?TwK!-lZk&`#B&u3uy6G
z9O`wFiB23!YJZwiRcZ(L9KYVSKI{=JUjO>Iy4m4njZ`MtjjJ>e-1p0d{8hzq`mjvD
zjGO^-(-Om&nTBB@J~OFjVJAF)Gbb%}hvTqM3KlWmatZ)&qg-6bYa6{_xAc~Lf+VbO
zt1-Ore4R+%(_u4ev|6G*K+t>0Aviw$^9fHjL1F-=&s~m7rcPaN-AuzZEs?$q06qMY
zMEqMmF`AuB<8$mxx!m%j?AOPBWvY&{YJ$dhz&XIH0PcW)KvxQa?n7+zckhbS_U0_l
zI%8=3<yPo5dwpU5c9HwCq#$_(?BT08Yej}<3g#48_BoAP@k)d80PoAh_8l`bC#e2)
zOD*1vXOWaWo<#VCO8erflT&HOGk~XC^tB^pP2wFr$2!(Bf3!vFft39ZG`hk+ZCp+;
z0CrFt7XB8*7sC-42`Nm^*;>*sh?u(`Nxw>20^r#6<Bv;irlW_|9;&%*OFjE<G$6XO
zwsV5<*|>~<G25!Vq|tE}fH-M2k(W}VOTtn1M%;%l%L)ZwXbCsSY%gkXKO{wvdu)XO
zOS<=$EBZC1R6m*Sv@k7!1PfIrmituLp;TnhL1`h;xxI+G^Q(hrG+GSMaC@^LP8L|b
z!(M-#cOsB5;w3k};otC!iTmnQnOF9c*j$_3(t1$SDzBz(dYOImMB!$uHmg>0J&-W5
zVzmmVCa%Kjbify<8zfv-D##TZ7HUz)Yv*=;;P3eqy{4_$3?vM9H@Nw$>No$ggUe5T
z@6BnK-1G3i#`)Durkf{r?ji~Q+Pc2FG!H@*=hLTp*Ggwgy5ZPoB?w-BL6Z?YxvA6w
z$4uPRo~YaP9?9~J9+$N@MI}X=)jtaF)s&0K$HBeZeL^)nM#<RYF152^`s$2V`4K{}
zet2xWEM*o*82vfFNU?_|VLqUd-XJ}&--g@<22HzFBRcr`yptC(a}AX@X&j6?b<2VH
zce&b39Bl%-%gL2HH?>qTQ@ks#e5M6ooaIG_KRI#aA!hFKftcq3Y2esWsN|~2Dqf2~
zyRLkhTRq@AeQHV3xDi_tf9Z3#D~;;M*oC7m+JNiipzrfP#G;+jH0X)b<`330<UHis
zPiOj2-6jum;SWVdHkvPNKORRa3SV$fIgL7d*&FC=f2;08^^@>&HBIT;qMGN!-j9y=
z2taWq+X{#wuxXJ0uY7>}Z4@Z{pj_X&b+yZ4&8$#&$xG~<Zt-0v#WDu%5b4um1ku?f
zO4m5}$D~L_HAT$~#-F~Uh1+=_E!n7N<=!PAhx!=)Ww}g~rPD5GYRmtFtaBeQ8b9>Z
zX-wYJ`h9rZw%cJq<{|xGQ{s*Gf6f3M75TS)H27JVARG{Ges%~OHyZ~hl#>I(#)BI0
z(zEdL@^Q2AaPV?-a<I|UGSIU!F@V9WtPoViRFYX1kfa;>V&FGclaB4~%h%<Aa2~}y
zs~YYHv~$061i)=f^qA1aS7dp<xM{zs`4&<m^nw1a)bKFwIu%a}l${Sm4iwhr5TxKH
z!YMA7riN6-B2voO!q!|rQ@eenO8uQ^7pmtUQ`8~-4=f*8>^fFS>67&>;_jzrxMGIS
z;@3DA2TBNC`PE*KWGqurh;x1iA}9X>uLPxQ^q$uE2~Irq*-h-wi(k}|45ua%t-A52
z+~#}|Ti`5&0N^b$_-3E|XnnNX^(hPfY%^EB-5N<FreYlUE}YXWjDG}oR(j91K}cu@
zkp{|b#a1J9-(?<BWz$9_mH((2o+AEHfmpA~_ns9hYi2oBJ1Wg|VX-t@XJ9**5zuD<
zs^nP7af#VaCSIX=pt)Im&48qsdKGMXYec)&dz$CoPL}uC`>F*375=R1FJyw!zDj(J
zwey@>rJ;8*Q<~6L_(q*OZAi@tf@Hit#T%)w2Pz0_FI&Ba?VC3WEY~@|pR|m{8Q3p@
zg$(L)W<1Xk)kIdAgF7g1ve_6d{CeNX@hrC6S^i{+c1iI^FtyfI!|gz5on_Wv>2iZ}
zol(gEuXbM44lfP!-(c6${SX&yGfXCi6x{O~81a4ZELI;vE;=G)rBbM;U!Z)Kd>Q_O
zi+%CS)af-)--<JhxH2@J)LJQt^Q%)%<=r_2a(kfI&wU>OL_OhIDkhNOv)L%`#5-+3
z_app)Bo@-wG|@>dAbCW2C4A#|Y5DN#eM=vZ=)cY<NZ9I%&g1{f6hYGn{(_<6$yhdg
zuv??`w3{&`jlNwE$;m-_<7t`vh=m3SzEUIYh+exBevUrB{LSGveVUc`TXOPTl6U><
zI|BG#5ED9**3l2M&BZ_|NTn<;`TBZeZq#Dvne@W9ae->S%>vRWtd^V;?d85Wjm8pF
zXXNkCK#@r$BopkQdmSbBRJ0HAWPKph;HG4F>)k<(m$A?u^LQ?0-$|b}JCIE*P(y7F
z3iY-5fi_tGhE=5~bJ6{tt+xV`XjH!H41DDuK3?YmWPiR~Aza;5C0<gg2=89qIe41M
z)c%VuT4B;CWl~~}=73>F@SqLdZie5V$rvb%+2zM_*M)e`*AA9b+!tz=B_pRi7Jrb<
z%~LYx6&vrrt0pkmIROgc1HE+)3bM}U-^ZD)(a8&as<uYRht%hJ3<s)7^TZ+&ur=S|
z;$8rSf&0$~5;<@2dX6i47-Lm>=hZsTu6lBh-cNp_py~C-3lHlsLRmA_&?0=XwcXv0
z1C~O&DMJKdS-Y>Oq=h5whCCgUlJ+`Y$-STbQZGT20ZIe|g5l3cv`M;s_Bzpn*X*9U
z_(|lcKIg2p<|W6Ea0dZVISGYv+fk4zY4cmXi{B;*Y&NI2YVuR-pBmT$L~)-{v|<C%
zmt6X*{$@6y>f?abBF{7z@5~7E`@ia&?{Cw!FcyOTUh)PP*IO_&Ij+y1B?56hUA8T|
z2#poex87f^J)}nawBh6JNi0~}$mYUcPRKD%v;IDN5xrJrm-i=WAf7!JQ$PMNX6uwR
z|4QscrpF$q^0~QpriAD@3y}d!`xrf*U5R>@VsN75Vt9bFKT1uNV8b8AM31ao#D85H
zm-i@%sqeR(T`C+q;WCr`@e=e*b8f;TJrqnK_y#0Q_Ud$`Gx7M>qy#`6V>{*Sf26ub
zCsd0kJBP~z&eKniC==hKWOsPHFp1N-8qPyHCo#U{h0oO!#~}F&`;ltWy3wt1KtSBD
zN_cqBhGvSTwG4`Gr-yi$Ugal?yrEMGddXuGz9jtGl>Ye}QlrlR6J&wG_c%S>elHeP
zKDsGqC`Bq^eZE!vzJiJ3WXPqFweNZPiEYYn;e9pcozNg|HJ3CALNb{Q7z+PPRY>K&
zNxtap|BEN?E5eys4GFAoZFH(kt`-ZLu8QS<_0MD0Fng+WhFV3Bm_{7gZXhdt9rJ;X
zMFzv1!yQ(y2{#(ZQJQ9jk~Tg+MB>cS?+lf<^66HNz_%g(E`+=zt#K#)nLz=Qi{ZP#
z*k~m)+6J9$T4K;U?KcnxAnx`3eqTq3VpOd8dJ4fQAKETdB69c7W48kRb9M@@6``A*
z@C%d|>{9z__FFFgVI~IB(g9i+q`vVhnW7Qaz&Q%P=>z!VXEo%gW@yiKBVnPu5+C_A
z>}TE#N=<J(UU38XupbE4K6Ssb>y^(z7XKX0mlo1G>tEq<-X{D;kOu{L(XQq}A3L~S
zE5DkgdGF(gz#qik3bC5PV)tgSg#z3yW#-jYDc5RpSU?+IibO@QW&<TFK_H1)*y<=@
z#?zv{&i+Q!iPi1T^+Or@AD}Dk<GI{frw5Ee!mFFL-N??X`!fQq7$wUrwX3~OAP$jE
zDktPX#IlL_H9OOhO=sf?(#5A7C6b|hWZnX8*7jN<Zw=d^YM<m(GBLJ0J5!f3gHwO9
zH^}PNqoClydM+OIA2lNH+pzV2keh?YjZ?3Oz1+)s6pc5fT`o&u|KyeloFYGjezV(n
z&wWL)#2mofRdCi?Eu;Bh<~bLJu$`4)M^SbuwI6YqLnmdLp*O-W%*Q*MsJ*N9KE#8y
zL7}bL!Io;Y>L@A$K23PhM7NPwVs_9X`h(g;lgetyiw0Y(Jun0eyzU(?lIJ&E`Hx}1
zfH8yq&oE%1Vi_Tbg@=ii8O+Sg%gceX2T(yCRysO<9v%pog@uQenUR;9o0W%~i<6y$
z6~aYJOGl5Y7&+uPNqy1|F(cjXGLY@Bx^C7jWHr;)Hy2u`@%j7D289a!lzkGNJpi#z
zJ~~SawQ}CYnZrW9lr(LMu!yj3#iNhWL{YF2lkEAg$gS#>YZ0SY@m>AKDmg1w>N%A;
zY%APE4gWqAY$C4}M?J>WXkqvUH1QR5!!%rJjj>P~rr(nCq_=h5O9cg4GvhVr;7;KF
zQQ+jl>O5MaIvO<XFnU)WzuAIWTnIJ<V3*+BH>NLlB)i28f7hjLtz9_=EwFkMiF9!N
zo%^dB<{k;a4a&B%7eOW(CX@xDbzoR}Oi0wrY_3zjz4_$iSq*`m$QDOS(52q^c35>b
z1JD@R73Ec?SbteBqnKWp%d}sp*|*>lP|Ti-o0s%CEyGyp)R!r&^dnB>s$UNXXqX6l
z6<QjqH~#HOqk@hzS{~?02RGqLK@U}b;`ao;LJsIRxSM%M?;6m^p4YO?QvE*I-IXSZ
zIAJa!<j#?jAo&G+WpVU*jpN0E4d?#IsE_FMY<>REKA>4-SS{ab+qYyPYh3sQT(*Km
z(iV1wEB2MaWAp>EDXGWFm~1T%*=r|_nBJyB^<KzKR=7;(kMTVpT?anw!7(>|^ej4q
zaw>&!ug}7<-+dGh+#gJrlgLcjrlo<hHocF9#5dE*OvWkx70ayt`0v3!<P|aIr8(qe
z8Eql*LJo>|WcLQiZqOIiO)#KjBj@K-xJ6wJ4c?%yM6veR0F{`xj_)hNLnZcW^yJHN
z==b`%lfJV|IU0M>b!>YZ%=bW1sBL^PORs*L3O|iiM$o#XIxfK&Pb0s9mv#%%O=GQB
zy-_1-&U3PRCBgC*h*5_+ER-8k$a*e>|FO<!_?ue%8J5^Bmt@wMSpuee5P~M`lLLHE
zEIN5i6@02oD95A}B&WmGRq^Kgwz98-%$_02<tx%*y?I%?d#e^7UUni<;6T}}dGpR2
zr&KFN8t5)-I$b4E=c<BxeAK9WBN>&pwBFhwTPocxg(<IzMqq02k{OoLSR;e`2+Hj^
zP6GoH>({E6J=~8baMvE1HaTgp)f_4?M(PHLjctWVUj%Ll3G!gtiHgI6x&M;$12ITG
zSqwMtU$(7jny%`jF#<RaWHXJI;VZa><nkdo&*U4K*QqiI0=_6baY3nd7t-S)gW&B?
zt(9a0Ee-<ueRv@A$8EZppx@LS<mQCgzJe=b{!s!zbf4_4{f4~?SH3n+_xv`UnzOkB
zVNgi6!;S@U^~yMnPl;6`5S529l}DjfVl+LR>K6eNjR|g6BAdssEi4@G=1Srs{Z&kX
z;1_%WgTG|04F<av!4iU|AmVq;<L_^kDG59Jo=q1!q7gg;qKTaCXQsb7hiJ8v17b}9
zi<6;Zx13sS%cH}p_(TOA7CF7Om1q5Jk&>^75kRoyS0z^~c}k)YNDd=6%<NRhGE*EE
z%I0(|#@odxGWDx8{>T(15yJT^fw!L;zd)nv16*tR^ReTFiHkD;->6@-OE0j;C;t6b
zEKu4|5m@g5qz!&$ZufVXZ}VPeXz;=DhCf@85Qt{*+}NEL@e&n(^EM|P4YU*!c#pHn
zky)+!GA0RWazNqOnwcJLknk;yk?)5z5L*+}K|dh5k<?q7y)Mqfxxg~0VIfMg?F8W+
z$>dg?pw(lH)EwE&vAbMD013~>D)bQM@uvN`AGade9~H6~c{34+{YFI7>(Zyd-o81_
zntf*ZR*J`BiUx?UOw2$WiWGhCdQpS-8TzQ=iUF8EpEXF_*Xx>8I6Aq95c$J^_$E^}
zx4QZZ()!tlO}MjbDh-hc^t9Y!@(I!0crmL}<2>;#=ll1%OX5;!(m;ZASl-~>;heCn
z35U4DCd@G1;%>lUN!c8^;G;yv{_)ax%=+;YyOe}3-C~q+=uwRdo<?{pUqH#{KEC?o
z*3Z#VH3$&Ay?G$w$vefTE?A5^d4KC3fieSMgcHB*!r6sCtE>>VSatG^A(jMxI{c-&
z7nWmtjJcz1fVlW8fDC_$T7%@muAT4W31#CNW%G>rBxiXTiDk1}aP$uso23D__1?@h
z;U|^#K!Rx0w4G!-b|S*t8Oli%S;G;>Y$3MM<(+k3B6SIOJ)ccP*L3)l#0Vrn8d6*v
z#dVi13#g&_S_VebuI6dAUy%E}vV6CWykNPN=WPfeK6{t2g&vew-lY-#EZCz9lxH$@
zJ;i(6_hmDIsggbKA>r)%Oo~@N5Rb9f1&6{rI#=Lh{Gw8UY(lv%=BgBigFZZqM_av$
zczwY>LUZU{Nd-_qB%>LP-zcP$wO9H{#iu+^Km7ztjBA-!i^w@`RIg!w9}V7ACnpGc
zr(jKEr>g4o#e0_d_Lp_x9cuD%a(8mM{wn6pdJfLWho4E!@a^(?_<hbXf9t>VeHi;k
dw4e_z?Rggyk1cLjDoE2Kisr9uTjRNg{s#z~#IFDV
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -4,16 +4,17 @@
 
 // These are small test files, good for just seeing if something loads. We
 // really only need one test file per backend here.
 var gSmallTests = [
   { name:"small-shot.ogg", type:"audio/ogg", duration:0.276 },
   { name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
   { name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.233 },
   { name:"seek.webm", type:"video/webm", duration:3.966 },
+  { name:"detodos.opus", type:"audio/ogg; codecs=opus", duration:2.9135 },
   { name:"bogus.duh", type:"bogus/duh" }
 ];
 
 // Used by test_progress to ensure we get the correct progress information
 // during resource download.
 var gProgressTests = [
   { name:"r11025_u8_c1.wav", type:"audio/x-wav", duration:1.0, size:11069 },
   { name:"big.wav", type:"audio/x-wav", duration:9.278981, size:102444 },
@@ -138,16 +139,20 @@ var gPlayTests = [
   // Test playback of a raw file
   { name:"seek.yuv", type:"video/x-raw-yuv", duration:1.833 },
   
   // A really short, low sample rate, single channel file. This tests whether
   // we can handle playing files when only push very little audio data to the
   // hardware.
   { name:"spacestorm-1000Hz-100ms.ogg", type:"audio/ogg", duration:0.099 },
 
+  // Opus data in an ogg container
+  { name:"detodos.opus", type:"audio/ogg; codecs=opus", duration:2.9135 },
+
+  // Invalid file
   { name:"bogus.duh", type:"bogus/duh", duration:Number.NaN }
 ];
 
 // Converts a path/filename to a file:// URI which we can load from disk.
 // Optionally checks whether the file actually exists on disk at the location
 // we've specified.
 function fileUriToSrc(path, mustExist) {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
@@ -248,16 +253,17 @@ var gErrorTests = [
 var gSeekTests = [
   { name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
   { name:"audio.wav", type:"audio/x-wav", duration:0.031247 },
   { name:"seek.ogv", type:"video/ogg", duration:3.966 },
   { name:"320x240.ogv", type:"video/ogg", duration:0.233 },
   { name:"seek.webm", type:"video/webm", duration:3.966 },
   { name:"bug516323.indexed.ogv", type:"video/ogg", duration:4.208 },
   { name:"split.webm", type:"video/webm", duration:1.967 },
+  { name:"detodos.opus", type:"audio/ogg; codecs=opus", duration:2.9135 },
   { name:"bogus.duh", type:"bogus/duh", duration:123 }
 ];
 
 // These are files suitable for using with a "new Audio" constructor.
 var gAudioTests = [
   { name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
   { name:"sound.ogg", type:"audio/ogg" },
   { name:"bogus.duh", type:"bogus/duh", duration:123 }
@@ -463,21 +469,28 @@ function mediaTestCleanup() {
 (function() {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   // Ensure that preload preferences are comsistent
   var prefService = Components.classes["@mozilla.org/preferences-service;1"]
                                .getService(Components.interfaces.nsIPrefService);
   var branch = prefService.getBranch("media.");
   var oldDefault = 2;
   var oldAuto = 3;
+  var oldOpus = undefined;
   try {
     oldDefault = branch.getIntPref("preload.default");
     oldAuto    = branch.getIntPref("preload.auto");
+    oldOpus    = branch.getBoolPref("opus.enabled");
   } catch(ex) { }
   branch.setIntPref("preload.default", 2); // preload_metadata
   branch.setIntPref("preload.auto", 3); // preload_enough
+  // test opus playback iff the pref exists
+  if (oldOpus !== undefined)
+    branch.setBoolPref("opus.enabled", true);
 
   window.addEventListener("unload", function() {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     branch.setIntPref("preload.default", oldDefault);
     branch.setIntPref("preload.auto", oldAuto);
+    if (oldOpus !== undefined)
+      branch.setBoolPref("opus.enabled", oldOpus);
   }, false);
  })();
--- a/content/media/test/test_played.html
+++ b/content/media/test/test_played.html
@@ -157,24 +157,23 @@ var tests = [
     }, false);
   }
 },
 // Seek repeatedly without playing. No range should appear.
 {
   setup : function(element) {
     let index = 1;
 
-    element.addEventListener('ended', function() {
-      is(element.played.length, 0, "element.played.length should be 0");
-      finish_test(element);
-    }, false);
-
     element.addEventListener('seeked', function() {
       index++;
       element.currentTime = index * element.duration / 5;
+      is(element.played.length, 0, "element.played.length should be 0");
+      if (index == 5) {
+        finish_test(element);
+      }
     }, false);
 
     element.addEventListener('loadedmetadata', function() {
       element.currentTime = element.duration / 5;
     }, false);
   }
 }
 ];
--- a/content/media/test/test_streams_element_capture_reset.html
+++ b/content/media/test/test_streams_element_capture_reset.html
@@ -13,16 +13,30 @@
 <script class="testbody" type="text/javascript">
 SimpleTest.waitForExplicitFinish();
 
 var v = document.getElementById('v');
 var vout = document.getElementById('vout');
 var stream = v.mozCaptureStream();
 vout.src = stream;
 
+function dumpEvent(event) {
+  var detail;
+  if (event.type == "timeupdate") {
+    detail = " currentTime=" + event.target.currentTime;
+  } else {
+    detail = "";
+  }
+  dump("GOT EVENT " + event.type + detail + "\n");
+}
+var events = ["timeupdate", "seeking", "seeked", "ended", "playing", "pause"];
+for (var i = 0; i < events.length; ++i) {
+  v.addEventListener(events[i], dumpEvent, false);
+}
+
 function startTest(test) {
   var seekTime = test.duration/2;
 
   function ended() {
     ok(true, "Final ended after changing src");
     SimpleTest.finish();
   };
   function timeupdateAfterSeek() {
--- a/content/svg/content/src/SVGTransformListParser.cpp
+++ b/content/svg/content/src/SVGTransformListParser.cpp
@@ -115,17 +115,17 @@ SVGTransformListParser::GetTransformToke
   const char* delimiters = "\x20\x9\xD\xA,(";
   char* delimiterStart = PL_strnpbrk(mTokenPos, delimiters, 11);
   if (delimiterStart != 0) {
     /* save this character and null it out */
     char holdingChar = *delimiterStart;
     *delimiterStart = '\0';
 
     PRUint32 len;
-    if ((len = nsCRT::strlen(mTokenPos)) > 0) {
+    if ((len = strlen(mTokenPos)) > 0) {
       *aKeyAtom = NS_NewAtom(Substring(mTokenPos, mTokenPos + len));
 
       if (aAdvancePos) {
          mInputPos = mTokenPos + len;
          mTokenPos = mInputPos;
       }
     } else {
       rv = NS_ERROR_FAILURE;
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/crashtests/751515-1.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+
+<svg xmlns="http://www.w3.org/2000/svg">
+<script>
+
+document.documentElement.createSVGAngle().convertToSpecifiedUnits(2);
+
+</script>
+</svg>
--- a/content/svg/content/src/crashtests/crashtests.list
+++ b/content/svg/content/src/crashtests/crashtests.list
@@ -54,8 +54,9 @@ load 579356-2.svg
 load 595608-1.svg
 load 601251-1.html
 load 601406-1.svg
 load 603145-1.svg
 load 613899-1.svg
 load 613899-2.svg
 load zero-size-image.svg
 load 723441-1.html
+load 751515-1.svg
--- a/content/svg/content/src/nsSVGAngle.cpp
+++ b/content/svg/content/src/nsSVGAngle.cpp
@@ -67,17 +67,17 @@ public:
   NS_IMETHOD GetUnitType(PRUint16* aResult)
     { *aResult = mVal.mBaseValUnit; return NS_OK; }
 
   NS_IMETHOD GetValue(float* aResult)
     { *aResult = mVal.GetBaseValue(); return NS_OK; }
   NS_IMETHOD SetValue(float aValue)
     {
       NS_ENSURE_FINITE(aValue, NS_ERROR_ILLEGAL_VALUE);
-      mVal.SetBaseValue(aValue, nsnull, true);
+      mVal.SetBaseValue(aValue, nsnull, false);
       return NS_OK;
     }
 
   NS_IMETHOD GetValueInSpecifiedUnits(float* aResult)
     { *aResult = mVal.mBaseVal; return NS_OK; }
   NS_IMETHOD SetValueInSpecifiedUnits(float aValue)
     {
       NS_ENSURE_FINITE(aValue, NS_ERROR_ILLEGAL_VALUE);
@@ -278,25 +278,30 @@ nsSVGAngle::ConvertToSpecifiedUnits(PRUi
                                     nsSVGElement *aSVGElement)
 {
   if (!IsValidUnitType(unitType))
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 
   if (mBaseValUnit == PRUint8(unitType))
     return NS_OK;
 
-  nsAttrValue emptyOrOldValue = aSVGElement->WillChangeAngle(mAttrEnum);
+  nsAttrValue emptyOrOldValue;
+  if (aSVGElement) {
+    emptyOrOldValue = aSVGElement->WillChangeAngle(mAttrEnum);
+  }
 
   float valueInUserUnits = mBaseVal * GetDegreesPerUnit(mBaseValUnit);
   mBaseValUnit = PRUint8(unitType);
   // Setting aDoSetAttr to false here will ensure we don't call
   // Will/DidChangeAngle a second time (and dispatch duplicate notifications).
   SetBaseValue(valueInUserUnits, aSVGElement, false);
 
-  aSVGElement->DidChangeAngle(mAttrEnum, emptyOrOldValue);
+  if (aSVGElement) {
+    aSVGElement->DidChangeAngle(mAttrEnum, emptyOrOldValue);
+  }
 
   return NS_OK;
 }
 
 nsresult
 nsSVGAngle::NewValueSpecifiedUnits(PRUint16 unitType,
                                    float valueInSpecifiedUnits,
                                    nsSVGElement *aSVGElement)
--- a/content/svg/content/src/nsSVGMarkerElement.cpp
+++ b/content/svg/content/src/nsSVGMarkerElement.cpp
@@ -365,17 +365,17 @@ nsSVGMarkerElement::GetMarkerTransform(f
   return gfxMatrix(cos(angle) * scale,   sin(angle) * scale,
                    -sin(angle) * scale,  cos(angle) * scale,
                    aX,                    aY);
 }
 
 nsSVGViewBoxRect
 nsSVGMarkerElement::GetViewBoxRect()
 {
-  if (mViewBox.IsValid()) {
+  if (mViewBox.IsExplicitlySet()) {
     return mViewBox.GetAnimValue();
   }
   return nsSVGViewBoxRect(
            0, 0,
            mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx),
            mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx));
 }
 
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -971,17 +971,17 @@ nsSVGSVGElement::GetViewBoxTransform() c
     viewportHeight = mViewportHeight;
   }
 
   if (viewportWidth <= 0.0f || viewportHeight <= 0.0f) {
     return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // singular
   }
 
   nsSVGViewBoxRect viewBox;
-  if (mViewBox.IsValid()) {
+  if (HasViewBox()) {
     viewBox = mViewBox.GetAnimValue();
   } else {
     viewBox.x = viewBox.y = 0.0f;
     if (ShouldSynthesizeViewBox()) {
       // Special case -- fake a viewBox, using height & width attrs.
       // (Use |this| as context, since if we get here, we're outermost <svg>.)
       viewBox.width =
         ComputeSynthesizedViewBoxDimension(mLengthAttributes[WIDTH],
@@ -1102,17 +1102,18 @@ nsSVGSVGElement::WillBeOutermostSVG(nsIC
 void
 nsSVGSVGElement::InvalidateTransformNotifyFrame()
 {
   nsIFrame* frame = GetPrimaryFrame();
   if (frame) {
     nsISVGSVGFrame* svgframe = do_QueryFrame(frame);
     // might fail this check if we've failed conditional processing
     if (svgframe) {
-      svgframe->NotifyViewportChange();
+      svgframe->NotifyViewportOrTransformChanged(
+                  nsISVGChildFrame::TRANSFORM_CHANGED);
     }
   }
 }
 
 bool
 nsSVGSVGElement::HasPreserveAspectRatio()
 {
   return HasAttr(kNameSpaceID_None, nsGkAtoms::preserveAspectRatio) ||
@@ -1122,17 +1123,17 @@ nsSVGSVGElement::HasPreserveAspectRatio(
 //----------------------------------------------------------------------
 // nsSVGSVGElement
 
 float
 nsSVGSVGElement::GetLength(PRUint8 aCtxType)
 {
   float h, w;
 
-  if (mViewBox.IsValid()) {
+  if (HasViewBox()) {
     const nsSVGViewBoxRect& viewbox = mViewBox.GetAnimValue();
     w = viewbox.width;
     h = viewbox.height;
   } else if (IsInner()) {
     nsSVGSVGElement *ctx = GetCtx();
     w = mLengthAttributes[WIDTH].GetAnimValue(ctx);
     h = mLengthAttributes[HEIGHT].GetAnimValue(ctx);
   } else if (ShouldSynthesizeViewBox()) {
@@ -1243,17 +1244,17 @@ SVGAnimatedPreserveAspectRatio *
 nsSVGSVGElement::GetPreserveAspectRatio()
 {
   return &mPreserveAspectRatio;
 }
 
 bool
 nsSVGSVGElement::ShouldSynthesizeViewBox() const
 {
-  NS_ABORT_IF_FALSE(!HasValidViewbox(),
+  NS_ABORT_IF_FALSE(!HasViewBox(),
                     "Should only be called if we lack a viewBox");
 
   nsIDocument* doc = GetCurrentDoc();
   return doc &&
     doc->IsBeingUsedAsImage() &&
     !mIsPaintingSVGImageElement &&
     !GetParent();
 }
@@ -1275,25 +1276,25 @@ void
 nsSVGSVGElement::
   SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR)
 {
 #ifdef DEBUG
   NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(),
                     "should only override preserveAspectRatio in images");
 #endif
 
-  if (!HasValidViewbox() && ShouldSynthesizeViewBox()) {
+  if (!HasViewBox() && ShouldSynthesizeViewBox()) {
     // My non-<svg:image> clients will have been painting me with a synthesized
     // viewBox, but my <svg:image> client that's about to paint me now does NOT
     // want that.  Need to tell ourselves to flush our transform.
     mImageNeedsTransformInvalidation = true;
   }
   mIsPaintingSVGImageElement = true;
 
-  if (!mViewBox.IsValid()) {
+  if (!HasViewBox()) {
     return; // preserveAspectRatio irrelevant (only matters if we have viewBox)
   }
 
   if (aPAR.GetDefer() && HasPreserveAspectRatio()) {
     return; // Referring element defers to my own preserveAspectRatio value.
   }
 
   SVGPreserveAspectRatio* pAROverridePtr = new SVGPreserveAspectRatio(aPAR);
@@ -1315,17 +1316,17 @@ void
 nsSVGSVGElement::ClearImageOverridePreserveAspectRatio()
 {
 #ifdef DEBUG
   NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(),
                     "should only override preserveAspectRatio in images");
 #endif
 
   mIsPaintingSVGImageElement = false;
-  if (!HasValidViewbox() && ShouldSynthesizeViewBox()) {
+  if (!HasViewBox() && ShouldSynthesizeViewBox()) {
     // My non-<svg:image> clients will want to paint me with a synthesized
     // viewBox, but my <svg:image> client that just painted me did NOT
     // use that.  Need to tell ourselves to flush our transform.
     mImageNeedsTransformInvalidation = true;
   }
 
   void* valPtr = UnsetProperty(nsGkAtoms::overridePreserveAspectRatio);
   if (valPtr) {
--- a/content/svg/content/src/nsSVGSVGElement.h
+++ b/content/svg/content/src/nsSVGSVGElement.h
@@ -191,18 +191,41 @@ public:
   virtual bool HasValidDimensions() const;
  
   // nsSVGSVGElement methods:
   float GetLength(PRUint8 mCtxType);
   // Copy our width or height to the target
   void SyncWidthOrHeight(nsIAtom* aName, nsSVGElement *aTarget) const;
 
   // public helpers:
+
+  /**
+   * Returns true if this element has a base/anim value for its "viewBox"
+   * attribute that defines a viewBox rectangle with finite values.
+   *
+   * Note that this does not check whether we need to synthesize a viewBox,
+   * so you must call ShouldSynthesizeViewBox() if you need to check that too.
+   *
+   * Note also that this method does not pay attention to whether the width or
+   * height values of the viewBox rect are positive!
+   */
+  bool HasViewBox() const {
+    return mViewBox.IsExplicitlySet();
+  }
+
+  /**
+   * Returns true if we should synthesize a viewBox for ourselves (that is, if
+   * we're the root element in an image document, and we're not currently being
+   * painted for an <svg:image> element).
+   *
+   * Only call this method if HasViewBox() returns false.
+   */
+  bool ShouldSynthesizeViewBox() const;
+
   gfxMatrix GetViewBoxTransform() const;
-  bool      HasValidViewbox() const { return mViewBox.IsValid(); }
 
   // This services any pending notifications for the transform on on this root
   // <svg> node needing to be recalculated.  (Only applicable in
   // SVG-as-an-image documents.)
   virtual void FlushImageTransformInvalidation();
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
@@ -222,22 +245,16 @@ public:
 private:
   // Methods for <image> elements to override my "PreserveAspectRatio" value.
   // These are private so that only our friends (nsSVGImageFrame in
   // particular) have access.
   void SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR);
   void ClearImageOverridePreserveAspectRatio();
   const SVGPreserveAspectRatio* GetImageOverridePreserveAspectRatio() const;
 
-  // Returns true if we should synthesize a viewBox for ourselves (that is,
-  // if we're the outermost <svg> in an image document, and we're not currently
-  // being painted by an <svg:image> element). This method also assumes that we
-  // lack a valid viewBox attribute.
-  bool ShouldSynthesizeViewBox() const;
-
 protected:
   // nsSVGElement overrides
   bool IsEventName(nsIAtom* aName);
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
   virtual void UnbindFromTree(bool aDeep, bool aNullParent);
--- a/content/svg/content/src/nsSVGViewBox.h
+++ b/content/svg/content/src/nsSVGViewBox.h
@@ -66,18 +66,27 @@ struct nsSVGViewBoxRect
 
 class nsSVGViewBox
 {
 
 public:
 
   void Init();
 
-  // Used by element to tell if viewBox is defined
-  bool IsValid() const
+  /**
+   * Returns true if the corresponding "viewBox" attribute defined a rectangle
+   * with finite values. Returns false if the viewBox was set to an invalid
+   * string, or if any of the four rect values were too big to store in a
+   * float.
+   *
+   * This method does not check whether the width or height values are
+   * positive, so callers must check whether the viewBox rect is valid where
+   * necessary!
+   */
+  bool IsExplicitlySet() const
     { return (mHasBaseVal || mAnimVal); }
 
   const nsSVGViewBoxRect& GetBaseValue() const
     { return mBaseVal; }
   void SetBaseValue(float aX, float aY, float aWidth, float aHeight,
                     nsSVGElement *aSVGElement);
 
   const nsSVGViewBoxRect& GetAnimValue() const
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -54,22 +54,22 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsContentUtils.h"
 #include "nsDOMJSUtils.h"
 #include "mozilla/Services.h"
 #include "xpcpublic.h"
 #include "mozilla/scache/StartupCache.h"
 #include "mozilla/scache/StartupCacheUtils.h"
 #include "nsCCUncollectableMarker.h"
-#include "mozilla/dom/bindings/Utils.h"
+#include "mozilla/dom/BindingUtils.h"
 
 using namespace mozilla::scache;
 using namespace mozilla;
 
-using mozilla::dom::bindings::DestroyProtoOrIfaceCache;
+using mozilla::dom::DestroyProtoOrIfaceCache;
 
 static const char kXBLCachePrefix[] = "xblcache";