Merge last PGO-green changeset from mozilla-inbound to mozilla-central
authorEd Morley <bmo@edmorley.co.uk>
Wed, 11 Jan 2012 02:39:31 +0000
changeset 85379 e79ef0ffcb0998cb134fdfd416549327e4600e64
parent 85343 e0ca89e88831cb0332e885fad039bc5424df6913 (current diff)
parent 85378 460ffa419de5dfa993841b6ef6fcf9a8c56017d2 (diff)
child 85380 545fc4728614f090b8630428d46d1476c040b3a8
child 85885 682eb90df44ba691e840347dee5931f9a1de11fd
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone12.0a1
Merge last PGO-green changeset from mozilla-inbound to mozilla-central
content/base/public/nsIRange.h
dom/interfaces/range/nsIDOMNSRange.idl
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -41,40 +41,37 @@
 #include "nsIAccessibleTypes.h"
 
 #include "nsAccessNode.h"
 
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
-#include "nsIDOMRange.h"
+#include "nsRange.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDocShell.h"
 #include "nsIContentViewer.h"
 #include "nsEventListenerManager.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIScrollableFrame.h"
 #include "nsEventStateManager.h"
 #include "nsISelectionPrivate.h"
 #include "nsISelectionController.h"
 #include "nsPIDOMWindow.h"
 #include "nsGUIEvent.h"
 #include "nsIView.h"
 #include "nsLayoutUtils.h"
 
-#include "nsContentCID.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "mozilla/dom/Element.h"
 
-static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsCoreUtils
 ////////////////////////////////////////////////////////////////////////////////
 
 bool
 nsCoreUtils::HasClickListener(nsIContent *aContent)
 {
   NS_ENSURE_TRUE(aContent, false);
@@ -312,19 +309,17 @@ nsCoreUtils::ScrollSubstringTo(nsIFrame 
                                nsIDOMNode *aEndNode, PRInt32 aEndIndex,
                                PRInt16 aVPercent, PRInt16 aHPercent)
 {
   if (!aFrame || !aStartNode || !aEndNode)
     return NS_ERROR_FAILURE;
 
   nsPresContext *presContext = aFrame->PresContext();
 
-  nsCOMPtr<nsIDOMRange> scrollToRange = do_CreateInstance(kRangeCID);
-  NS_ENSURE_TRUE(scrollToRange, NS_ERROR_FAILURE);
-
+  nsRefPtr<nsIDOMRange> scrollToRange = new nsRange();
   nsCOMPtr<nsISelectionController> selCon;
   aFrame->GetSelectionController(presContext, getter_AddRefs(selCon));
   NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
 
   scrollToRange->SetStart(aStartNode, aStartIndex);
   scrollToRange->SetEnd(aEndNode, aEndIndex);
 
   nsCOMPtr<nsISelection> selection;
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1273,23 +1273,28 @@ nsDocAccessible::HandleAccEvent(AccEvent
 
 ////////////////////////////////////////////////////////////////////////////////
 // Public members
 
 void*
 nsDocAccessible::GetNativeWindow() const
 {
   nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
+  if (!shell)
+    return nsnull;
+
   nsIViewManager* vm = shell->GetViewManager();
-  if (vm) {
-    nsCOMPtr<nsIWidget> widget;
-    vm->GetRootWidget(getter_AddRefs(widget));
-    if (widget)
-      return widget->GetNativeData(NS_NATIVE_WINDOW);
-  }
+  if (!vm)
+    return nsnull;
+
+  nsCOMPtr<nsIWidget> widget;
+  vm->GetRootWidget(getter_AddRefs(widget));
+  if (widget)
+    return widget->GetNativeData(NS_NATIVE_WINDOW);
+
   return nsnull;
 }
 
 nsAccessible*
 nsDocAccessible::GetAccessibleByUniqueIDInSubtree(void* aUniqueID)
 {
   nsAccessible* child = GetAccessibleByUniqueID(aUniqueID);
   if (child)
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -40,40 +40,36 @@
 #include "nsHyperTextAccessible.h"
 
 #include "States.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsTextAttrs.h"
 
 #include "nsIClipboard.h"
-#include "nsContentCID.h"
 #include "nsFocusManager.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMRange.h"
-#include "nsIDOMNSRange.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIEditingSession.h"
 #include "nsIEditor.h"
 #include "nsIFrame.h"
 #include "nsFrameSelection.h"
 #include "nsILineIterator.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIPlaintextEditor.h"
 #include "nsIScrollableFrame.h"
 #include "nsISelectionPrivate.h"
 #include "nsIServiceManager.h"
 #include "nsTextFragment.h"
 #include "gfxSkipChars.h"
 
 using namespace mozilla::a11y;
 
-static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsHyperTextAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHyperTextAccessible::
   nsHyperTextAccessible(nsIContent *aNode, nsIWeakReference *aShell) :
   nsAccessibleWrap(aNode, aShell)
 {
@@ -1734,17 +1730,17 @@ already_AddRefed<nsFrameSelection>
 nsHyperTextAccessible::FrameSelection()
 {
   nsIFrame* frame = GetFrame();
   return frame ? frame->GetFrameSelection() : nsnull;
 }
 
 void
 nsHyperTextAccessible::GetSelectionDOMRanges(PRInt16 aType,
-                                             nsCOMArray<nsIDOMRange>* aRanges)
+                                             nsTArray<nsRange*>* aRanges)
 {
   nsRefPtr<nsFrameSelection> frameSelection = FrameSelection();
   if (!frameSelection)
     return;
 
   nsISelection* domSel = frameSelection->GetSelection(aType);
   if (!domSel)
     return;
@@ -1758,72 +1754,70 @@ nsHyperTextAccessible::GetSelectionDOMRa
     editor->GetRootElement(getter_AddRefs(editorRoot));
     startNode = do_QueryInterface(editorRoot);
   }
 
   if (!startNode)
     return;
 
   PRUint32 childCount = startNode->GetChildCount();
-  nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(startNode));
   nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(domSel));
   nsresult rv = privSel->
-    GetRangesForIntervalCOMArray(startDOMNode, 0, startDOMNode, childCount,
-                                 true, aRanges);
+    GetRangesForIntervalArray(startNode, 0, startNode, childCount, true, aRanges);
   NS_ENSURE_SUCCESS(rv,);
 
   // Remove collapsed ranges
-  PRInt32 numRanges = aRanges->Count();
-  for (PRInt32 count = 0; count < numRanges; count ++) {
+  PRUint32 numRanges = aRanges->Length();
+  for (PRUint32 count = 0; count < numRanges; count ++) {
     bool isCollapsed = false;
     (*aRanges)[count]->GetCollapsed(&isCollapsed);
     if (isCollapsed) {
-      aRanges->RemoveObjectAt(count);
+      aRanges->RemoveElementAt(count);
       --numRanges;
       --count;
     }
   }
 }
 
 /*
  * Gets the number of selected regions.
  */
 NS_IMETHODIMP
 nsHyperTextAccessible::GetSelectionCount(PRInt32* aSelectionCount)
 {
   NS_ENSURE_ARG_POINTER(aSelectionCount);
   *aSelectionCount = 0;
 
-  nsCOMArray<nsIDOMRange> ranges;
+  nsTArray<nsRange*> ranges;
   GetSelectionDOMRanges(nsISelectionController::SELECTION_NORMAL, &ranges);
-  *aSelectionCount = ranges.Count();
+  *aSelectionCount = PRInt32(ranges.Length());
 
   return NS_OK;
 }
 
 /*
  * Gets the start and end offset of the specified selection.
  */
 NS_IMETHODIMP
 nsHyperTextAccessible::GetSelectionBounds(PRInt32 aSelectionNum,
                                           PRInt32* aStartOffset,
                                           PRInt32* aEndOffset)
 {
   NS_ENSURE_ARG_POINTER(aStartOffset);
   NS_ENSURE_ARG_POINTER(aEndOffset);
   *aStartOffset = *aEndOffset = 0;
 
-  nsCOMArray<nsIDOMRange> ranges;
+  nsTArray<nsRange*> ranges;
   GetSelectionDOMRanges(nsISelectionController::SELECTION_NORMAL, &ranges);
 
-  PRInt32 rangeCount = ranges.Count();
+  PRUint32 rangeCount = ranges.Length();
   if (aSelectionNum < 0 || aSelectionNum >= rangeCount)
     return NS_ERROR_INVALID_ARG;
 
-  nsCOMPtr<nsIDOMRange> range = ranges[aSelectionNum];
+  nsRange* range = ranges[aSelectionNum];
 
   // Get start point
   nsCOMPtr<nsIDOMNode> startDOMNode;
   range->GetStartContainer(getter_AddRefs(startDOMNode));
   nsCOMPtr<nsINode> startNode(do_QueryInterface(startDOMNode));
   PRInt32 startOffset = 0;
   range->GetStartOffset(&startOffset);
 
@@ -1875,18 +1869,17 @@ nsHyperTextAccessible::SetSelectionBound
 
   // Caret is a collapsed selection
   bool isOnlyCaret = (aStartOffset == aEndOffset);
 
   PRInt32 rangeCount = 0;
   domSel->GetRangeCount(&rangeCount);
   nsCOMPtr<nsIDOMRange> range;
   if (aSelectionNum == rangeCount) { // Add a range
-    range = do_CreateInstance(kRangeCID);
-    NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
+    range = new nsRange();
   }
   else if (aSelectionNum < 0 || aSelectionNum > rangeCount) {
     return NS_ERROR_INVALID_ARG;
   }
   else {
     domSel->GetRangeAt(aSelectionNum, getter_AddRefs(range));
     NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
   }
@@ -2300,20 +2293,20 @@ nsHyperTextAccessible::GetDOMPointByFram
   }
 
   NS_IF_ADDREF(*aNode = node);
   return NS_OK;
 }
 
 // nsHyperTextAccessible
 nsresult
-nsHyperTextAccessible::DOMRangeBoundToHypertextOffset(nsIDOMRange *aRange,
-                                                      bool aIsStartBound,
-                                                      bool aIsStartHTOffset,
-                                                      PRInt32 *aHTOffset)
+nsHyperTextAccessible::RangeBoundToHypertextOffset(nsRange *aRange,
+                                                   bool aIsStartBound,
+                                                   bool aIsStartHTOffset,
+                                                   PRInt32 *aHTOffset)
 {
   nsCOMPtr<nsIDOMNode> DOMNode;
   PRInt32 nodeOffset = 0;
 
   nsresult rv;
   if (aIsStartBound) {
     rv = aRange->GetStartContainer(getter_AddRefs(DOMNode));
     NS_ENSURE_SUCCESS(rv, rv);
@@ -2341,30 +2334,28 @@ nsHyperTextAccessible::DOMRangeBoundToHy
 // nsHyperTextAccessible
 nsresult
 nsHyperTextAccessible::GetSpellTextAttribute(nsIDOMNode *aNode,
                                              PRInt32 aNodeOffset,
                                              PRInt32 *aHTStartOffset,
                                              PRInt32 *aHTEndOffset,
                                              nsIPersistentProperties *aAttributes)
 {
-  nsCOMArray<nsIDOMRange> ranges;
+  nsTArray<nsRange*> ranges;
   GetSelectionDOMRanges(nsISelectionController::SELECTION_SPELLCHECK, &ranges);
 
-  PRInt32 rangeCount = ranges.Count();
+  PRUint32 rangeCount = ranges.Length();
   if (!rangeCount)
     return NS_OK;
 
-  for (PRInt32 index = 0; index < rangeCount; index++) {
-    nsCOMPtr<nsIDOMRange> range = ranges[index];
-    nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
-    NS_ENSURE_STATE(nsrange);
+  for (PRUint32 index = 0; index < rangeCount; index++) {
+    nsRange* range = ranges[index];
 
     PRInt16 result;
-    nsresult rv = nsrange->ComparePoint(aNode, aNodeOffset, &result);
+    nsresult rv = range->ComparePoint(aNode, aNodeOffset, &result);
     NS_ENSURE_SUCCESS(rv, rv);
     // ComparePoint checks boundary points, but we need to check that
     // text at aNodeOffset is inside the range.
     // See also bug 460690.
     if (result == 0) {
       nsCOMPtr<nsIDOMNode> end;
       rv = range->GetEndContainer(getter_AddRefs(end));
       NS_ENSURE_SUCCESS(rv, rv);
@@ -2373,41 +2364,41 @@ nsHyperTextAccessible::GetSpellTextAttri
       NS_ENSURE_SUCCESS(rv, rv);
       if (aNode == end && aNodeOffset == endOffset) {
         result = 1;
       }
     }
 
     if (result == 1) { // range is before point
       PRInt32 startHTOffset = 0;
-      nsresult rv = DOMRangeBoundToHypertextOffset(range, false, true,
-                                                   &startHTOffset);
+      nsresult rv = RangeBoundToHypertextOffset(range, false, true,
+                                                &startHTOffset);
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (startHTOffset > *aHTStartOffset)
         *aHTStartOffset = startHTOffset;
 
     } else if (result == -1) { // range is after point
       PRInt32 endHTOffset = 0;
-      nsresult rv = DOMRangeBoundToHypertextOffset(range, true, false,
-                                                   &endHTOffset);
+      nsresult rv = RangeBoundToHypertextOffset(range, true, false,
+                                                &endHTOffset);
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (endHTOffset < *aHTEndOffset)
         *aHTEndOffset = endHTOffset;
 
     } else { // point is in range
       PRInt32 startHTOffset = 0;
-      nsresult rv = DOMRangeBoundToHypertextOffset(range, true, true,
-                                                   &startHTOffset);
+      nsresult rv = RangeBoundToHypertextOffset(range, true, true,
+                                                &startHTOffset);
       NS_ENSURE_SUCCESS(rv, rv);
 
       PRInt32 endHTOffset = 0;
-      rv = DOMRangeBoundToHypertextOffset(range, false, false,
-                                          &endHTOffset);
+      rv = RangeBoundToHypertextOffset(range, false, false,
+                                       &endHTOffset);
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (startHTOffset > *aHTStartOffset)
         *aHTStartOffset = startHTOffset;
       if (endHTOffset < *aHTEndOffset)
         *aHTEndOffset = endHTOffset;
 
       if (aAttributes) {
--- a/accessible/src/html/nsHyperTextAccessible.h
+++ b/accessible/src/html/nsHyperTextAccessible.h
@@ -355,17 +355,17 @@ protected:
   /**
    * Return frame selection object for the accessible.
    */
   virtual already_AddRefed<nsFrameSelection> FrameSelection();
 
   /**
    * Return selection ranges within the accessible subtree.
    */
-  void GetSelectionDOMRanges(PRInt16 aType, nsCOMArray<nsIDOMRange>* aRanges);
+  void GetSelectionDOMRanges(PRInt16 aType, nsTArray<nsRange*>* aRanges);
 
   nsresult SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos);
 
   /**
    * Provide the line number for the caret, relative to the
    * current DOM node.
    * @return 1-based index for the line number with the caret
    */
@@ -385,20 +385,20 @@ protected:
    *
    * @param aRange          [in] the given range
    * @param aIsStartBound   [in] specifies whether the required range bound is
    *                        start bound
    * @param aIsStartOffset  [in] the offset type, used when the range bound is
    *                        outside of hyper text
    * @param aHTOffset       [out] the result offset
    */
-  nsresult DOMRangeBoundToHypertextOffset(nsIDOMRange *aRange,
-                                          bool aIsStartBound,
-                                          bool aIsStartOffset,
-                                          PRInt32 *aHTOffset);
+  nsresult RangeBoundToHypertextOffset(nsRange *aRange,
+                                       bool aIsStartBound,
+                                       bool aIsStartOffset,
+                                       PRInt32 *aHTOffset);
 
   /**
    * Set 'misspelled' text attribute and return range offsets where the
    * attibute is stretched. If the text is not misspelled at the given offset
    * then we expose only range offsets where text is not misspelled. The method
    * is used by GetTextAttributes() method.
    *
    * @param aIncludeDefAttrs  [in] points whether text attributes having default
--- a/browser/base/content/syncUtils.js
+++ b/browser/base/content/syncUtils.js
@@ -192,17 +192,17 @@ let gSyncUtils = {
       filepicker.init(window, dialogTitle, Ci.nsIFilePicker.modeSave);
       filepicker.appendFilters(Ci.nsIFilePicker.filterHTML);
       filepicker.defaultString = defaultSaveName;
       let rv = filepicker.show();
       if (rv == Ci.nsIFilePicker.returnOK
           || rv == Ci.nsIFilePicker.returnReplace) {
         let stream = Cc["@mozilla.org/network/file-output-stream;1"]
                        .createInstance(Ci.nsIFileOutputStream);
-        stream.init(filepicker.file, -1, -1, 0);
+        stream.init(filepicker.file, -1, 0600, 0);
 
         let serializer = new XMLSerializer();
         let output = serializer.serializeToString(iframe.contentDocument);
         output = output.replace(/<!DOCTYPE (.|\n)*?]>/,
           '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' +
           '"DTD/xhtml1-strict.dtd">');
         output = Weave.Utils.encodeUTF8(output);
         stream.write(output, output.length);
--- a/build/autoconf/libstdcxx.py
+++ b/build/autoconf/libstdcxx.py
@@ -7,16 +7,17 @@
 
 # We find out both the host and target versions. Since the output
 # will be used from shell, we just print the two assignments and evaluate
 # them from shell.
 
 import os
 import subprocess
 import re
+import sys
 
 re_for_ld = re.compile('.*\((.*)\).*')
 
 def parse_readelf_line(x):
     """Return the version from a readelf line that looks like:
     0x00ec: Rev: 1  Flags: none  Index: 8  Cnt: 2  Name: GLIBCXX_3.4.6
     """
     return x.split(':')[-1].split('_')[-1].strip()
@@ -62,12 +63,24 @@ def find_version(e):
 
     p = subprocess.Popen(['readelf', '-V', libstdcxx], stdout=subprocess.PIPE)
     versions = [parse_readelf_line(x)
                 for x in p.stdout.readlines() if 'Name: GLIBCXX' in x]
     last_version = sorted(versions, cmp = cmp_ver)[-1]
     return encode_ver(last_version)
 
 if __name__ == '__main__':
-    cxx_env = os.environ['CXX']
-    print 'MOZ_LIBSTDCXX_TARGET_VERSION=%s' % find_version(cxx_env)
-    host_cxx_env = os.environ.get('HOST_CXX', cxx_env)
-    print 'MOZ_LIBSTDCXX_HOST_VERSION=%s' % find_version(host_cxx_env)
+    if os.uname()[0] == 'Darwin':
+        sdk_dir = os.environ['MACOS_SDK_DIR']
+        if 'MacOSX10.5.sdk' in sdk_dir:
+            target_ver = 0
+            host_ver = 0
+        else:
+            target_ver = encode_ver('3.4.9')
+            host_ver = encode_ver('3.4.9')
+    else:
+        cxx_env = os.environ['CXX']
+        target_ver = find_version(cxx_env)
+        host_cxx_env = os.environ.get('HOST_CXX', cxx_env)
+        host_ver = find_version(host_cxx_env)
+
+    print 'MOZ_LIBSTDCXX_TARGET_VERSION=%s' % target_ver
+    print 'MOZ_LIBSTDCXX_HOST_VERSION=%s' % host_ver
--- a/build/macosx/common
+++ b/build/macosx/common
@@ -1,2 +1,4 @@
 CC=/usr/bin/gcc-4.2
 CXX=/usr/bin/g++-4.2
+
+ac_add_options --enable-stdcxx-compat
--- a/build/mobile/robocop/FennecNativeDriver.java.in
+++ b/build/mobile/robocop/FennecNativeDriver.java.in
@@ -260,29 +260,34 @@ public class FennecNativeDriver implemen
     }
 
   }
 
   //Takes a filename, loads the file, 
   //  and returns a string version of the entire file.
   public static String getFile(String filename)
   {
-    File file = new File(filename);
     StringBuilder text = new StringBuilder();
 
+    BufferedReader br = null;
     try {
-      BufferedReader br = new BufferedReader(new FileReader(file));
+      br = new BufferedReader(new FileReader(filename));
       String line;
 
       while ((line = br.readLine()) != null) {
         text.append(line);
         text.append('\n');
       }
     } catch(IOException e) {
       e.printStackTrace();
+    } finally {
+      try {
+        br.close();
+      } catch (IOException e) {
+      }
     }
     return text.toString();  
   }
 
   // Takes a string of "key=value" pairs split by \n and creates a hash table.
   public static HashMap convertTextToTable(String data)
   {
     HashMap retVal = new HashMap();
--- a/build/mobile/robocop/FennecNativeElement.java.in
+++ b/build/mobile/robocop/FennecNativeElement.java.in
@@ -72,17 +72,19 @@ public class FennecNativeElement impleme
 
   public void click() {
     final SynchronousQueue syncQueue = new SynchronousQueue();
     mActivity.runOnUiThread(
         new Runnable() {
           public void run() {
             View view = (View)mActivity.findViewById(id);
             if(view != null) {
-              view.performClick();
+              if (!view.performClick()) {
+                Log.w("Robocop", "Robocop called click on an element with no listener");
+              }
             } else {
               throw new RoboCopException("click: unable to find view "+id); 
             }
             syncQueue.offer(new Object());
           }
         });
     try {
       syncQueue.take();
--- a/build/stdc++compat.cpp
+++ b/build/stdc++compat.cpp
@@ -52,16 +52,19 @@
 #define GLIBCXX_VERSION(a, b, c) (((a) << 16) | ((b) << 8) | (c))
 
 namespace std {
 #if MOZ_LIBSTDCXX_VERSION >= GLIBCXX_VERSION(3, 4, 9)
     /* Instantiate these templates to avoid GLIBCXX_3.4.9 symbol versions */
     template ostream& ostream::_M_insert(double);
     template ostream& ostream::_M_insert(long);
     template ostream& ostream::_M_insert(unsigned long);
+#ifdef DEBUG
+    template ostream& ostream::_M_insert(const void*);
+#endif
     template ostream& __ostream_insert(ostream&, const char*, streamsize);
     template istream& istream::_M_extract(double&);
 #endif
 #if MOZ_LIBSTDCXX_VERSION >= GLIBCXX_VERSION(3, 4, 14)
     /* Instantiate these templates to avoid GLIBCXX_3.4.14 symbol versions
      * depending on optimization level */
     template char *string::_S_construct_aux_2(size_type, char, allocator<char> const&);
 #ifdef _GLIBCXX_USE_WCHAR_T
--- a/config/Preprocessor.py
+++ b/config/Preprocessor.py
@@ -423,17 +423,17 @@ class Preprocessor:
     if isName:
       try:
         args = str(args)
         if not os.path.isabs(args):
           args = os.path.join(self.context['DIRECTORY'], args)
         args = open(args, 'rU')
       except:
         raise Preprocessor.Error(self, 'FILE_NOT_FOUND', str(args))
-    self.checkLineNumbers = bool(re.search('\.js(?:\.in)?$', args.name))
+    self.checkLineNumbers = bool(re.search('\.(js|java)(?:\.in)?$', args.name))
     oldFile = self.context['FILE']
     oldLine = self.context['LINE']
     oldDir = self.context['DIRECTORY']
     if args.isatty():
       # we're stdin, use '-' and '' for file and dir
       self.context['FILE'] = '-'
       self.context['DIRECTORY'] = ''
     else:
--- a/configure.in
+++ b/configure.in
@@ -7461,17 +7461,17 @@ dnl ====================================
 STDCXX_COMPAT=
 MOZ_ARG_ENABLE_BOOL(stdcxx-compat,
 [  --enable-stdcxx-compat  Enable compatibility with older libstdc++],
     STDCXX_COMPAT=stdc++compat.cpp)
 
 AC_SUBST(STDCXX_COMPAT)
 
 if test -n "$STDCXX_COMPAT"; then
-   eval $(CXX="$CXX" $PYTHON $_topsrcdir/build/autoconf/libstdcxx.py)
+   eval $(CXX="$CXX" MACOS_SDK_DIR="$MACOS_SDK_DIR" $PYTHON $_topsrcdir/build/autoconf/libstdcxx.py)
    AC_SUBST(MOZ_LIBSTDCXX_TARGET_VERSION)
    AC_SUBST(MOZ_LIBSTDCXX_HOST_VERSION)
 fi
 
 dnl ========================================================
 dnl =
 dnl = Profiling and Instrumenting
 dnl =
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -57,17 +57,16 @@ nsIDocument.h \
 nsDeprecatedOperationList.h \
 nsIDocumentObserver.h \
 nsIMutationObserver.h \
 nsIMutationObserver2.h \
 nsINameSpaceManager.h \
 nsINode.h \
 nsINodeInfo.h \
 nsINodeList.h \
-nsIRange.h \
 nsIRangeUtils.h \
 nsIScriptElement.h \
 nsIStyleSheetLinkingElement.h \
 nsIContentSerializer.h \
 nsIHTMLToTextSink.h \
 nsIXPathEvaluatorInternal.h \
 mozISanitizingSerializer.h \
 nsCaseTreatment.h \
--- a/content/base/public/nsContentCID.h
+++ b/content/base/public/nsContentCID.h
@@ -92,20 +92,16 @@
  {0xb1, 0x58, 0x26, 0xbb, 0x5e, 0x9c, 0x65, 0xe9}}
 #endif
 
 #define NS_NAMESPACEMANAGER_CID                   \
 { /* d9783472-8fe9-11d2-9d3c-0060088f9ff7 */      \
  0xd9783472, 0x8fe9, 0x11d2,                      \
  {0x9d, 0x3c, 0x00, 0x60, 0x08, 0x8f, 0x9f, 0xf7}}
 
-#define NS_RANGE_CID \
-{/* {56AD2981-8A87-11d2-918C-0080C8E44DB5}*/ \
- 0x56ad2981, 0x8a87, 0x11d2, { 0x91, 0x8c, 0x0, 0x80, 0xc8, 0xe4, 0x4d, 0xb5 } }
-
 #define NS_CONTENTITERATOR_CID \
 {/* {a6cf90e3-15b3-11d2-932e-00805f8add32}*/ \
  0xa6cf90e3, 0x15b3, 0x11d2, {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 } }
 
 #define NS_PRECONTENTITERATOR_CID \
 {/* {80D7E247-D4B8-45d7-BB59-6F1DD56F384C} */ \
  0x80d7e247, 0xd4b8, 0x45d7, { 0xbb, 0x59, 0x6f, 0x1d, 0xd5, 0x6f, 0x38, 0x4c } }
 
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1831,16 +1831,28 @@ public:
    * NOTE: the caller has to make sure autocomplete makes sense for the
    * element's type.
    *
    * @param aInput the input element to check. NOTE: aInput can't be null.
    * @return whether the input element has autocomplete enabled.
    */
   static bool IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput);
 
+  /**
+   * If the URI is chrome, return true unconditionarlly.
+   *
+   * Otherwise, get the contents of the given pref, and treat it as a
+   * comma-separated list of URIs.  Return true if the given URI's prepath is
+   * in the list, and false otherwise.
+   *
+   * Comparisons are case-insensitive, and whitespace between elements of the
+   * comma-separated list is ignored.
+   */
+  static bool URIIsChromeOrInPref(nsIURI *aURI, const char *aPref);
+
 private:
   static bool InitializeEventTable();
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
 
   static nsresult HoldScriptObject(PRUint32 aLangID, void* aObject);
--- a/content/base/public/nsIContentIterator.h
+++ b/content/base/public/nsIContentIterator.h
@@ -37,18 +37,16 @@
 
 #ifndef __nsIContentIterator_h___
 #define __nsIContentIterator_h___
 
 #include "nsISupports.h"
 
 class nsINode;
 class nsIDOMRange;
-class nsIRange;
-class nsRange;
 
 #define NS_ICONTENTITERATOR_IID \
 { 0x2550078e, 0xae87, 0x4914, \
  { 0xb3, 0x04, 0xe4, 0xd1, 0x46, 0x19, 0x3d, 0x5f } }
 
 class nsIContentIterator : public nsISupports
 {
 public:
@@ -57,17 +55,16 @@ public:
   /* Initializes an iterator for the subtree rooted by the node aRoot
    */
   virtual nsresult Init(nsINode* aRoot) = 0;
 
   /* Initializes an iterator for the subtree defined by the range aRange
      Subclasses should make sure they implement both of these!
    */
   virtual nsresult Init(nsIDOMRange* aRange) = 0;
-  virtual nsresult Init(nsIRange* aRange) = 0;
 
   /** First will reset the list.
    */
   virtual void First() = 0;
 
   /** Last will reset the list to the end.
    */
   virtual void Last() = 0;
deleted file mode 100644
--- a/content/base/public/nsIRange.h
+++ /dev/null
@@ -1,181 +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 Mozilla.com.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *         Boris Zbarsky <bzbarsky@mit.edu> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either 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 ***** */
-
-#ifndef nsIRange_h___
-#define nsIRange_h___
-
-#include "nsISupports.h"
-#include "nsCOMPtr.h"
-#include "nsHashKeys.h"
-#include "nsINode.h"
-#include "nsIDOMRange.h"
-#include "nsTHashtable.h"
-
-// IID for the nsIRange interface
-#define NS_IRANGE_IID \
-{ 0x09dec26b, 0x1ab7, 0x4ff0, \
- { 0xa1, 0x67, 0x7f, 0x22, 0x9c, 0xaa, 0xc3, 0x04 } }
-
-class nsIDOMFontFaceList;
-
-class nsIRange : public nsIDOMRange {
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IRANGE_IID)
-
-  nsIRange()
-    : mRoot(nsnull),
-      mStartOffset(0),
-      mEndOffset(0),
-      mIsPositioned(false),
-      mIsDetached(false),
-      mMaySpanAnonymousSubtrees(false),
-      mInSelection(false)
-  {
-  }
-
-  nsINode* GetRoot() const
-  {
-    return mRoot;
-  }
-
-  nsINode* GetStartParent() const
-  {
-    return mStartParent;
-  }
-
-  nsINode* GetEndParent() const
-  {
-    return mEndParent;
-  }
-
-  PRInt32 StartOffset() const
-  {
-    return mStartOffset;
-  }
-
-  PRInt32 EndOffset() const
-  {
-    return mEndOffset;
-  }
-  
-  bool IsPositioned() const
-  {
-    return mIsPositioned;
-  }
-
-  bool IsDetached() const
-  {
-    return mIsDetached;
-  }
-  
-  bool Collapsed() const
-  {
-    return mIsPositioned && mStartParent == mEndParent &&
-           mStartOffset == mEndOffset;
-  }
-
-  void SetMaySpanAnonymousSubtrees(bool aMaySpanAnonymousSubtrees)
-  {
-    mMaySpanAnonymousSubtrees = aMaySpanAnonymousSubtrees;
-  }
-
-  /**
-   * Return true iff this range is part of at least one Selection object
-   * and isn't detached.
-   */
-  bool IsInSelection() const
-  {
-    return mInSelection;
-  }
-
-  /**
-   * Called when the range is added/removed from a Selection.
-   */
-  void SetInSelection(bool aInSelection)
-  {
-    if (mInSelection == aInSelection || mIsDetached) {
-      return;
-    }
-    mInSelection = aInSelection;
-    nsINode* commonAncestor = GetCommonAncestor();
-    NS_ASSERTION(commonAncestor, "unexpected disconnected nodes");
-    if (mInSelection) {
-      RegisterCommonAncestor(commonAncestor);
-    } else {
-      UnregisterCommonAncestor(commonAncestor);
-    }
-  }
-
-  virtual nsINode* GetCommonAncestor() const = 0;
-
-  virtual void Reset() = 0;
-
-  // XXXbz we could make these non-virtual if a bunch of nsRange stuff
-  // became nsIRange stuff... and if no one outside layout needs them.
-  virtual nsresult SetStart(nsINode* aParent, PRInt32 aOffset) = 0;
-  virtual nsresult SetEnd(nsINode* aParent, PRInt32 aOffset) = 0;
-  virtual nsresult CloneRange(nsIRange** aNewRange) const = 0;
-
-  // Work around hiding warnings
-  NS_IMETHOD SetStart(nsIDOMNode* aParent, PRInt32 aOffset) = 0;
-  NS_IMETHOD SetEnd(nsIDOMNode* aParent, PRInt32 aOffset) = 0;
-  NS_IMETHOD CloneRange(nsIDOMRange** aNewRange) = 0;
-
-  // To support the font inspector API
-  NS_IMETHOD GetUsedFontFaces(nsIDOMFontFaceList** aResult) = 0;
-
-  typedef nsTHashtable<nsPtrHashKey<nsIRange> > RangeHashTable;
-protected:
-  void RegisterCommonAncestor(nsINode* aNode);
-  void UnregisterCommonAncestor(nsINode* aNode);
-  nsINode* IsValidBoundary(nsINode* aNode);
-
-  nsCOMPtr<nsINode> mRoot;
-  nsCOMPtr<nsINode> mStartParent;
-  nsCOMPtr<nsINode> mEndParent;
-  PRInt32 mStartOffset;
-  PRInt32 mEndOffset;
-
-  bool mIsPositioned;
-  bool mIsDetached;
-  bool mMaySpanAnonymousSubtrees;
-  bool mInSelection;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIRange, NS_IRANGE_IID)
-
-#endif /* nsIRange_h___ */
--- a/content/base/public/nsIRangeUtils.h
+++ b/content/base/public/nsIRangeUtils.h
@@ -40,33 +40,33 @@
 /* A class for range utilities. */
 
 #ifndef nsIRangeUtils_h___
 #define nsIRangeUtils_h___
 
 #include "nsISupports.h"
 
 // Forward declarations
-class nsIDOMRange;
+class nsRange;
 class nsIDOMNode;
 class nsIContent;
 
 // IID for the nsIRangeUtils interface
 #define NS_IRANGEUTILS_IID       \
 { 0xa6cf9127, 0x15b3, 0x11d2, {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
 
 class nsIRangeUtils : public nsISupports {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IRANGEUTILS_IID)
 
   NS_IMETHOD_(PRInt32) ComparePoints(nsIDOMNode* aParent1, PRInt32 aOffset1,
                                      nsIDOMNode* aParent2, PRInt32 aOffset2) = 0;
                                
   NS_IMETHOD CompareNodeToRange(nsIContent* aNode, 
-                                nsIDOMRange* aRange,
+                                nsRange* aRange,
                                 bool *outNodeBefore,
                                 bool *outNodeAfter) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIRangeUtils, NS_IRANGEUTILS_IID)
 
 #endif /* nsIRangeUtils_h___ */
 
--- a/content/base/public/nsISelectionPrivate.idl
+++ b/content/base/public/nsISelectionPrivate.idl
@@ -35,35 +35,36 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 #include "nsISelectionListener.idl"
 #include "nsIEnumerator.idl"
 #include "nsISelection.idl"
 
-interface nsIDOMRange;
+interface nsRange;
 interface nsIDOMNode;
 interface nsISelectionListener;
 interface nsIContent;
+interface nsINode;
 
 %{C++
 class nsFrameSelection;
 class nsIFrame;
 class nsIPresShell;
 struct nsTextRangeStyle;
 struct nsPoint;
 #include "nsIFrame.h"
-#include "nsCOMArray.h"
+#include "nsTArray.h"
 %}
 
 [ptr] native nsFrameSelection(nsFrameSelection);
 [ptr] native nsIFrame(nsIFrame);
 [ptr] native nsIPresShell(nsIPresShell);
-[ptr] native RangeArray(nsCOMArray<nsIDOMRange>);
+[ptr] native RangeArray(nsTArray<nsRange*>);
 [ref] native constTextRangeStyleRef(const nsTextRangeStyle);
 [ref] native nsPointRef(nsPoint);
 native nsDirection(nsDirection);
 
 [scriptable, uuid(1820a940-6203-4e27-bc94-fa81131722a4)]
 interface nsISelectionPrivate : nsISelection
  {
     const short ENDOFPRECEDINGLINE=0;
@@ -152,19 +153,19 @@ interface nsISelectionPrivate : nsISelec
      */
     void GetRangesForInterval(
         in nsIDOMNode beginNode, in PRInt32 beginOffset,
         in nsIDOMNode endNode, in PRInt32 endOffset,
         in boolean allowAdjacent,
         out PRUint32 resultCount,
         [retval, array, size_is(resultCount)] out nsIDOMRange results);
 
-    [noscript] void GetRangesForIntervalCOMArray(
-        in nsIDOMNode beginNode, in PRInt32 beginOffset,
-        in nsIDOMNode endNode, in PRInt32 endOffset,
+    [noscript] void GetRangesForIntervalArray(
+        in nsINode beginNode, in PRInt32 beginOffset,
+        in nsINode endNode, in PRInt32 endOffset,
         in boolean allowAdjacent,
         in RangeArray results);
 
     /**
      * Scrolls a region of the selection, so that it is visible in
      * the scrolled view.
      *
      * @param aRegion - the region inside the selection to scroll into view
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -53,16 +53,17 @@ EXPORTS		= \
 		nsAttrName.h \
 		nsContentList.h \
 		nsContentSink.h \
 		nsGkAtomList.h \
 		nsGkAtoms.h \
 		nsNodeInfoManager.h \
 		nsNodeUtils.h \
 		nsPropertyTable.h \
+		nsRange.h \
 		nsScriptLoader.h \
 		nsStubDocumentObserver.h \
 		nsStubImageDecoderObserver.h \
 		nsStubMutationObserver.h \
 		nsTextFragment.h \
 		mozAutoDocUpdate.h \
 		nsFrameMessageManager.h \
 		$(NULL)
--- a/content/base/src/nsContentIterator.cpp
+++ b/content/base/src/nsContentIterator.cpp
@@ -124,17 +124,16 @@ public:
   explicit nsContentIterator(bool aPre);
   virtual ~nsContentIterator();
 
   // nsIContentIterator interface methods ------------------------------
 
   virtual nsresult Init(nsINode* aRoot);
 
   virtual nsresult Init(nsIDOMRange* aRange);
-  virtual nsresult Init(nsIRange* aRange);
 
   virtual void First();
 
   virtual void Last();
   
   virtual void Next();
 
   virtual void Prev();
@@ -298,44 +297,36 @@ nsContentIterator::Init(nsINode* aRoot)
   }
 
   mCommonParent = aRoot;
   mCurNode = mFirst;
   RebuildIndexStack();
   return NS_OK;
 }
 
-
 nsresult
-nsContentIterator::Init(nsIDOMRange* aRange)
+nsContentIterator::Init(nsIDOMRange* aDOMRange)
 {
-  nsCOMPtr<nsIRange> range = do_QueryInterface(aRange);
-  return Init(range);
-
-}
-
-nsresult
-nsContentIterator::Init(nsIRange* aRange)
-{
-  NS_ENSURE_ARG_POINTER(aRange);
+  NS_ENSURE_ARG_POINTER(aDOMRange);
+  nsRange* range = static_cast<nsRange*>(aDOMRange);
 
   mIsDone = false;
 
   // get common content parent
-  mCommonParent = aRange->GetCommonAncestor();
+  mCommonParent = range->GetCommonAncestor();
   NS_ENSURE_TRUE(mCommonParent, NS_ERROR_FAILURE);
 
   // get the start node and offset
-  PRInt32 startIndx = aRange->StartOffset();
-  nsINode* startNode = aRange->GetStartParent();
+  PRInt32 startIndx = range->StartOffset();
+  nsINode* startNode = range->GetStartParent();
   NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
 
   // get the end node and offset
-  PRInt32 endIndx = aRange->EndOffset();
-  nsINode* endNode = aRange->GetEndParent();
+  PRInt32 endIndx = range->EndOffset();
+  nsINode* endNode = range->GetEndParent();
   NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE);
 
   bool startIsData = startNode->IsNodeOfType(nsINode::eDATA_NODE);
 
   // short circuit when start node == end node
   if (startNode == endNode)
   {
     // Check to see if we have a collapsed range, if so,
@@ -1174,17 +1165,16 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsContentSubtreeIterator, nsContentIterator)
 
   // nsContentIterator overrides ------------------------------
 
   virtual nsresult Init(nsINode* aRoot);
 
   virtual nsresult Init(nsIDOMRange* aRange);
-  virtual nsresult Init(nsIRange* aRange);
 
   virtual void Next();
 
   virtual void Prev();
 
   virtual nsresult PositionAt(nsINode* aCurNode);
 
   // Must override these because we don't do PositionAt
@@ -1197,17 +1187,17 @@ protected:
 
   nsresult GetTopAncestorInRange(nsINode *aNode,
                                  nsCOMPtr<nsINode> *outAnestor);
 
   // no copy's or assigns  FIX ME
   nsContentSubtreeIterator(const nsContentSubtreeIterator&);
   nsContentSubtreeIterator& operator=(const nsContentSubtreeIterator&);
 
-  nsCOMPtr<nsIDOMRange> mRange;
+  nsRefPtr<nsRange> mRange;
   // these arrays all typically are used and have elements
 #if 0
   nsAutoTArray<nsIContent*, 8> mStartNodes;
   nsAutoTArray<PRInt32, 8>     mStartOffsets;
 #endif
 
   nsAutoTArray<nsIContent*, 8> mEndNodes;
   nsAutoTArray<PRInt32, 8>     mEndOffsets;
@@ -1216,17 +1206,17 @@ protected:
 NS_IMPL_ADDREF_INHERITED(nsContentSubtreeIterator, nsContentIterator)
 NS_IMPL_RELEASE_INHERITED(nsContentSubtreeIterator, nsContentIterator)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsContentSubtreeIterator)
 NS_INTERFACE_MAP_END_INHERITING(nsContentIterator)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsContentSubtreeIterator)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsContentSubtreeIterator, nsContentIterator)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRange)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mRange, nsIDOMRange)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsContentSubtreeIterator, nsContentIterator)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRange)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 nsresult NS_NewContentSubtreeIterator(nsIContentIterator** aInstancePtrResult);
 
 
@@ -1263,17 +1253,17 @@ nsresult nsContentSubtreeIterator::Init(
 
 nsresult nsContentSubtreeIterator::Init(nsIDOMRange* aRange)
 {
   if (!aRange) 
     return NS_ERROR_NULL_POINTER; 
 
   mIsDone = false;
 
-  mRange = aRange;
+  mRange = static_cast<nsRange*>(aRange);
   
   // get the start node and offset, convert to nsINode
   nsCOMPtr<nsIDOMNode> commonParent;
   nsCOMPtr<nsIDOMNode> startParent;
   nsCOMPtr<nsIDOMNode> endParent;
   nsCOMPtr<nsINode> nStartP;
   nsCOMPtr<nsINode> nEndP;
   nsCOMPtr<nsINode> n;
@@ -1361,17 +1351,17 @@ nsresult nsContentSubtreeIterator::Init(
   
   firstCandidate = GetDeepFirstChild(firstCandidate, nsnull);
   
   // confirm that this first possible contained node
   // is indeed contained.  Else we have a range that
   // does not fully contain any node.
   
   bool nodeBefore, nodeAfter;
-  if (NS_FAILED(nsRange::CompareNodeToRange(firstCandidate, aRange,
+  if (NS_FAILED(nsRange::CompareNodeToRange(firstCandidate, mRange,
                                             &nodeBefore, &nodeAfter)))
     return NS_ERROR_FAILURE;
 
   if (nodeBefore || nodeAfter)
   {
     MakeEmpty();
     return NS_OK;
   }
@@ -1412,17 +1402,17 @@ nsresult nsContentSubtreeIterator::Init(
   }
   
   lastCandidate = GetDeepLastChild(lastCandidate, nsnull);
   
   // confirm that this last possible contained node
   // is indeed contained.  Else we have a range that
   // does not fully contain any node.
   
-  if (NS_FAILED(nsRange::CompareNodeToRange(lastCandidate, aRange, &nodeBefore,
+  if (NS_FAILED(nsRange::CompareNodeToRange(lastCandidate, mRange, &nodeBefore,
                                             &nodeAfter)))
     return NS_ERROR_FAILURE;
 
   if (nodeBefore || nodeAfter)
   {
     MakeEmpty();
     return NS_OK;
   }
@@ -1433,22 +1423,16 @@ nsresult nsContentSubtreeIterator::Init(
   if (NS_FAILED(GetTopAncestorInRange(lastCandidate, address_of(mLast))))
     return NS_ERROR_FAILURE;
   
   mCurNode = mFirst;
 
   return NS_OK;
 }
 
-nsresult nsContentSubtreeIterator::Init(nsIRange* aRange)
-{
-  nsCOMPtr<nsIDOMRange> range = do_QueryInterface(aRange);
-  return Init(range);
-}
-
 /****************************************************************
  * nsContentSubtreeIterator overrides of ContentIterator routines
  ****************************************************************/
 
 // we can't call PositionAt in a subtree iterator...
 void
 nsContentSubtreeIterator::First()
 {
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -206,16 +206,18 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsIScriptElement.h"
 #include "nsIContentViewer.h"
 #include "nsIObjectLoadingContent.h"
 
 #include "mozilla/Base64.h"
 #include "mozilla/Preferences.h"
 
 #include "nsWrapperCacheInlines.h"
+#include "nsCharSeparatedTokenizer.h"
+#include "nsUnicharUtils.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 using namespace mozilla;
 
 const char kLoadAsData[] = "loadAsData";
 
@@ -669,16 +671,50 @@ nsContentUtils::IsAutocompleteEnabled(ns
     }
 
     form->GetAutocomplete(autocomplete);
   }
 
   return autocomplete.EqualsLiteral("on");
 }
 
+bool
+nsContentUtils::URIIsChromeOrInPref(nsIURI *aURI, const char *aPref)
+{
+  if (!aURI) {
+    return false;
+  }
+
+  nsCAutoString scheme;
+  aURI->GetScheme(scheme);
+  if (scheme.EqualsLiteral("chrome")) {
+    return true;
+  }
+
+  nsCAutoString prePathUTF8;
+  aURI->GetPrePath(prePathUTF8);
+  NS_ConvertUTF8toUTF16 prePath(prePathUTF8);
+
+  const nsAdoptingString& whitelist = Preferences::GetString(aPref);
+
+  // This tokenizer also strips off whitespace around tokens, as desired.
+  nsCharSeparatedTokenizer tokenizer(whitelist, ',',
+    nsCharSeparatedTokenizerTemplate<>::SEPARATOR_OPTIONAL);
+
+  while (tokenizer.hasMoreTokens()) {
+    const nsSubstring& whitelistItem = tokenizer.nextToken();
+
+    if (whitelistItem.Equals(prePath, nsCaseInsensitiveStringComparator())) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 /**
  * Access a cached parser service. Don't addref. We need only one
  * reference to it and this class has that one.
  */
 /* static */
 nsIParserService*
 nsContentUtils::GetParserService()
 {
--- a/content/base/src/nsCopySupport.cpp
+++ b/content/base/src/nsCopySupport.cpp
@@ -306,21 +306,19 @@ nsresult
 nsCopySupport::GetTransferableForNode(nsINode* aNode,
                                       nsIDocument* aDoc,
                                       nsITransferable** aTransferable)
 {
   nsCOMPtr<nsISelection> selection;
   // Make a temporary selection with aNode in a single range.
   nsresult rv = NS_NewDomSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(rv, rv);
-  nsCOMPtr<nsIDOMRange> range;
-  rv = NS_NewRange(getter_AddRefs(range));
-  NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
+  nsRefPtr<nsRange> range = new nsRange();
   rv = range->SelectNode(node);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = selection->AddRange(range);
   NS_ENSURE_SUCCESS(rv, rv);
   // It's not the primary selection - so don't skip invisible content.
   PRUint32 flags = 0;
   return SelectionCopyHelper(selection, aDoc, false, 0, flags,
                              aTransferable);
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -57,17 +57,17 @@
 #include "nsIOutputStream.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMText.h"
 #include "nsIDOMCDATASection.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMProcessingInstruction.h"
 #include "nsIDOMDocumentType.h"
 #include "nsIDOMNodeList.h"
-#include "nsIRange.h"
+#include "nsRange.h"
 #include "nsIDOMRange.h"
 #include "nsIDOMDocument.h"
 #include "nsICharsetConverterManager.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "nsIEnumerator.h"
 #include "nsIParserService.h"
 #include "nsIScriptContext.h"
@@ -108,19 +108,19 @@ protected:
                               nsINode* aOriginalNode = nsnull);
   nsresult SerializeToStringRecursive(nsINode* aNode,
                                       nsAString& aStr,
                                       bool aDontSerializeRoot);
   nsresult SerializeNodeEnd(nsINode* aNode, nsAString& aStr);
   // This serializes the content of aNode.
   nsresult SerializeToStringIterative(nsINode* aNode,
                                       nsAString& aStr);
-  nsresult SerializeRangeToString(nsIRange *aRange,
+  nsresult SerializeRangeToString(nsRange *aRange,
                                   nsAString& aOutputString);
-  nsresult SerializeRangeNodes(nsIRange* aRange, 
+  nsresult SerializeRangeNodes(nsRange* aRange, 
                                nsINode* aNode, 
                                nsAString& aString,
                                PRInt32 aDepth);
   nsresult SerializeRangeContextStart(const nsTArray<nsINode*>& aAncestorArray,
                                       nsAString& aString);
   nsresult SerializeRangeContextEnd(const nsTArray<nsINode*>& aAncestorArray,
                                     nsAString& aString);
 
@@ -150,17 +150,17 @@ protected:
   }
 
   static bool IsTag(nsIContent* aContent, nsIAtom* aAtom);
   
   virtual bool IncludeInContext(nsINode *aNode);
 
   nsCOMPtr<nsIDocument>          mDocument;
   nsCOMPtr<nsISelection>         mSelection;
-  nsCOMPtr<nsIRange>             mRange;
+  nsRefPtr<nsRange>              mRange;
   nsCOMPtr<nsINode>              mNode;
   nsCOMPtr<nsIOutputStream>      mStream;
   nsCOMPtr<nsIContentSerializer> mSerializer;
   nsCOMPtr<nsIUnicodeEncoder>    mUnicodeEncoder;
   nsCOMPtr<nsINode>              mCommonParent;
   nsCOMPtr<nsIDocumentEncoderNodeFixup> mNodeFixup;
   nsCOMPtr<nsICharsetConverterManager> mCharsetConverterManager;
 
@@ -199,17 +199,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRange)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCommonParent)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocumentEncoder)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSelection)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRange)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mRange, nsIDOMRange)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNode)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCommonParent)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 nsDocumentEncoder::nsDocumentEncoder() : mCachedBuffer(nsnull)
 {
   Initialize();
   mMimeType.AssignLiteral("text/plain");
@@ -284,17 +284,17 @@ nsDocumentEncoder::SetSelection(nsISelec
 {
   mSelection = aSelection;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocumentEncoder::SetRange(nsIDOMRange* aRange)
 {
-  mRange = do_QueryInterface(aRange);
+  mRange = static_cast<nsRange*>(aRange);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocumentEncoder::SetNode(nsIDOMNode* aNode)
 {
   mNodeIsContainer = false;
   mNode = do_QueryInterface(aNode);
@@ -761,17 +761,17 @@ static nsresult GetLengthOfDOMNode(nsIDO
         nodeList->GetLength(&aCount);
       }
     }
   }
   return result;
 }
 
 nsresult
-nsDocumentEncoder::SerializeRangeNodes(nsIRange* aRange,
+nsDocumentEncoder::SerializeRangeNodes(nsRange* aRange,
                                        nsINode* aNode,
                                        nsAString& aString,
                                        PRInt32 aDepth)
 {
   nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
   NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
 
   if (!IsVisibleNode(aNode))
@@ -932,17 +932,17 @@ nsDocumentEncoder::SerializeRangeContext
         break;
     }
   }
 
   return rv;
 }
 
 nsresult
-nsDocumentEncoder::SerializeRangeToString(nsIRange *aRange,
+nsDocumentEncoder::SerializeRangeToString(nsRange *aRange,
                                           nsAString& aOutputString)
 {
   if (!aRange || aRange->Collapsed())
     return NS_OK;
 
   mCommonParent = aRange->GetCommonAncestor();
 
   if (!mCommonParent)
@@ -1074,17 +1074,17 @@ nsDocumentEncoder::EncodeToString(nsAStr
         if (content && content->Tag() == nsGkAtoms::tr) {
           nsCOMPtr<nsINode> n = do_QueryInterface(node);
           rv = SerializeNodeStart(n, 0, -1, output);
           NS_ENSURE_SUCCESS(rv, rv);
           prevNode = node;
         }
       }
 
-      nsCOMPtr<nsIRange> r = do_QueryInterface(range);
+      nsRange* r = static_cast<nsRange*>(range.get());
       rv = SerializeRangeToString(r, output);
       NS_ENSURE_SUCCESS(rv, rv);
     }
     if (prevNode) {
       nsCOMPtr<nsINode> p = do_QueryInterface(prevNode);
       rv = SerializeNodeEnd(p, output);
       NS_ENSURE_SUCCESS(rv, rv);
     }
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -87,17 +87,17 @@
 #include "nsNodeUtils.h"
 #include "nsDocument.h"
 #ifdef MOZ_XUL
 #include "nsXULElement.h"
 #endif /* MOZ_XUL */
 #include "nsFrameManager.h"
 #include "nsFrameSelection.h"
 #ifdef DEBUG
-#include "nsIRange.h"
+#include "nsRange.h"
 #endif
 
 #include "nsBindingManager.h"
 #include "nsXBLBinding.h"
 #include "nsIXBLService.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIBoxObject.h"
 #include "nsClientRect.h"
@@ -4969,18 +4969,18 @@ nsGenericElement::List(FILE* out, PRInt3
 
   fprintf(out, "@%p", (void *)this);
 
   ListAttributes(out);
 
   fprintf(out, " state=[%llx]", State().GetInternalValue());
   fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
   if (IsCommonAncestorForRangeInSelection()) {
-    nsIRange::RangeHashTable* ranges =
-      static_cast<nsIRange::RangeHashTable*>(GetProperty(nsGkAtoms::range));
+    nsRange::RangeHashTable* ranges =
+      static_cast<nsRange::RangeHashTable*>(GetProperty(nsGkAtoms::range));
     fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
   }
   fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
   fprintf(out, " refcount=%d<", mRefCnt.get());
 
   nsIContent* child = GetFirstChild();
   if (child) {
     fputs("\n", out);
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -163,16 +163,17 @@ GK_ATOM(bottompadding, "bottompadding")
 GK_ATOM(bottomright, "bottomright")
 GK_ATOM(box, "box")
 GK_ATOM(br, "br")
 GK_ATOM(braille, "braille")
 GK_ATOM(broadcast, "broadcast")
 GK_ATOM(broadcaster, "broadcaster")
 GK_ATOM(broadcasterset, "broadcasterset")
 GK_ATOM(browser, "browser")
+GK_ATOM(mozbrowser, "mozbrowser")
 GK_ATOM(bulletinboard, "bulletinboard")
 GK_ATOM(button, "button")
 GK_ATOM(callTemplate, "call-template")
 GK_ATOM(cancel, "cancel")
 GK_ATOM(canvas, "canvas")
 GK_ATOM(caption, "caption")
 GK_ATOM(capture, "capture")
 GK_ATOM(caseOrder, "case-order")
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -114,29 +114,17 @@ static void InvalidateAllFrames(nsINode*
 // If outNodeBefore is returned true, then the node starts before the range does.
 // If outNodeAfter is returned true, then the node ends after the range does.
 // Note that both of the above might be true.
 // If neither are true, the node is contained inside of the range.
 // XXX - callers responsibility to ensure node in same doc as range! 
 
 // static
 nsresult
-nsRange::CompareNodeToRange(nsINode* aNode, nsIDOMRange* aRange,
-                            bool *outNodeBefore, bool *outNodeAfter)
-{
-  nsresult rv;
-  nsCOMPtr<nsIRange> range = do_QueryInterface(aRange, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return CompareNodeToRange(aNode, range, outNodeBefore, outNodeAfter);
-}
-
-// static
-nsresult
-nsRange::CompareNodeToRange(nsINode* aNode, nsIRange* aRange,
+nsRange::CompareNodeToRange(nsINode* aNode, nsRange* aRange,
                             bool *outNodeBefore, bool *outNodeAfter)
 {
   NS_ENSURE_STATE(aNode);
   // create a pair of dom points that expresses location of node:
   //     NODE(start), NODE(end)
   // Let incoming range be:
   //    {RANGE(start), RANGE(end)}
   // if (RANGE(start) <= NODE(start))  and (RANGE(end) => NODE(end))
@@ -181,25 +169,25 @@ nsRange::CompareNodeToRange(nsINode* aNo
                                                 &disconnected) < 0;
   NS_ENSURE_TRUE(!disconnected, NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
   return NS_OK;
 }
 
 struct FindSelectedRangeData
 {
   nsINode*  mNode;
-  nsIRange* mResult;
+  nsRange* mResult;
   PRUint32  mStartOffset;
   PRUint32  mEndOffset;
 };
 
 static PLDHashOperator
-FindSelectedRange(nsPtrHashKey<nsIRange>* aEntry, void* userArg)
+FindSelectedRange(nsPtrHashKey<nsRange>* aEntry, void* userArg)
 {
-  nsIRange* range = aEntry->GetKey();
+  nsRange* range = aEntry->GetKey();
   if (range->IsInSelection() && !range->Collapsed()) {
     FindSelectedRangeData* data = static_cast<FindSelectedRangeData*>(userArg);
     PRInt32 cmp = nsContentUtils::ComparePoints(data->mNode, data->mEndOffset,
                                                 range->GetStartParent(),
                                                 range->StartOffset());
     if (cmp == 1) {
       cmp = nsContentUtils::ComparePoints(data->mNode, data->mStartOffset,
                                           range->GetEndParent(),
@@ -280,41 +268,24 @@ nsRangeUtils::ComparePoints(nsIDOMNode* 
   nsCOMPtr<nsINode> parent2 = do_QueryInterface(aParent2);
 
   NS_ENSURE_TRUE(parent1 && parent2, -1);
 
   return nsContentUtils::ComparePoints(parent1, aOffset1, parent2, aOffset2);
 }
 
 NS_IMETHODIMP
-nsRangeUtils::CompareNodeToRange(nsIContent* aNode, nsIDOMRange* aRange,
+nsRangeUtils::CompareNodeToRange(nsIContent* aNode, nsRange* aRange,
                                  bool *outNodeBefore, bool *outNodeAfter)
 {
   return nsRange::CompareNodeToRange(aNode, aRange, outNodeBefore,
                                      outNodeAfter);
 }
 
 /******************************************************
- * non members
- ******************************************************/
-
-nsresult
-NS_NewRange(nsIDOMRange** aResult)
-{
-  NS_ENSURE_ARG_POINTER(aResult);
-
-  nsRange * range = new nsRange();
-  if (!range) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  return CallQueryInterface(range, aResult);
-}
-
-/******************************************************
  * constructor/destructor
  ******************************************************/
 
 nsRange::~nsRange() 
 {
   NS_ASSERTION(!IsInSelection(), "deleting nsRange that is in use");
 
   // we want the side effects (releases and list removals)
@@ -330,20 +301,18 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsRange)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsRange)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsRange)
 
 DOMCI_DATA(Range, nsRange)
 
 // QueryInterface implementation for nsRange
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsRange)
   NS_INTERFACE_MAP_ENTRY(nsIDOMRange)
-  NS_INTERFACE_MAP_ENTRY(nsIRange)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMNSRange)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRange)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMRange)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Range)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsRange)
   tmp->Reset();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsRange)
@@ -351,18 +320,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEndParent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 static void
 RangeHashTableDtor(void* aObject, nsIAtom* aPropertyName, void* aPropertyValue,
                    void* aData)
 {
-  nsIRange::RangeHashTable* ranges =
-    static_cast<nsIRange::RangeHashTable*>(aPropertyValue);
+  nsRange::RangeHashTable* ranges =
+    static_cast<nsRange::RangeHashTable*>(aPropertyValue);
   delete ranges;
 }
 
 static void MarkDescendants(nsINode* aNode)
 {
   // Set NodeIsDescendantOfCommonAncestorForRangeInSelection on aNode's
   // descendants unless aNode is already marked as a range common ancestor
   // or a descendant of one, in which case all of our descendants have the
@@ -399,17 +368,17 @@ static void UnmarkDescendants(nsINode* a
         // We found an ancestor of an overlapping range, skip its descendants.
         node = node->GetNextNonChildNode(aNode);
       }
     }
   }
 }
 
 void
-nsIRange::RegisterCommonAncestor(nsINode* aNode)
+nsRange::RegisterCommonAncestor(nsINode* aNode)
 {
   NS_PRECONDITION(aNode, "bad arg");
   NS_ASSERTION(IsInSelection(), "registering range not in selection");
 
   MarkDescendants(aNode);
 
   RangeHashTable* ranges =
     static_cast<RangeHashTable*>(aNode->GetProperty(nsGkAtoms::range));
@@ -418,17 +387,17 @@ nsIRange::RegisterCommonAncestor(nsINode
     ranges->Init();
     aNode->SetProperty(nsGkAtoms::range, ranges, RangeHashTableDtor, true);
   }
   ranges->PutEntry(this);
   aNode->SetCommonAncestorForRangeInSelection();
 }
 
 void
-nsIRange::UnregisterCommonAncestor(nsINode* aNode)
+nsRange::UnregisterCommonAncestor(nsINode* aNode)
 {
   NS_PRECONDITION(aNode, "bad arg");
   NS_ASSERTION(aNode->IsCommonAncestorForRangeInSelection(), "wrong node");
   RangeHashTable* ranges =
     static_cast<RangeHashTable*>(aNode->GetProperty(nsGkAtoms::range));
   NS_ASSERTION(ranges->GetEntry(this), "unknown range");
 
   if (ranges->Count() == 1) {
@@ -660,19 +629,19 @@ nsRange::ParentChainChanged(nsIContent *
   NS_ASSERTION(newRoot, "No valid boundary or root found!");
   NS_ASSERTION(newRoot == IsValidBoundary(mEndParent),
                "Start parent and end parent give different root!");
   // This is safe without holding a strong ref to self as long as the change
   // of mRoot is the last thing in DoSetRange.
   DoSetRange(mStartParent, mStartOffset, mEndParent, mEndOffset, newRoot);
 }
 
-/********************************************************
- * Utilities for comparing points: API from nsIDOMNSRange
- ********************************************************/
+/******************************************************
+ * Utilities for comparing points: API from nsIDOMRange
+ ******************************************************/
 NS_IMETHODIMP
 nsRange::IsPointInRange(nsIDOMNode* aParent, PRInt32 aOffset, bool* aResult)
 {
   PRInt16 compareResult = 0;
   nsresult rv = ComparePoint(aParent, aOffset, &compareResult);
   // If the node isn't in the range's document, it clearly isn't in the range.
   if (rv == NS_ERROR_DOM_WRONG_DOCUMENT_ERR) {
     *aResult = false;
@@ -815,29 +784,25 @@ IndexOf(nsIDOMNode* aChildNode)
   }
 
   nsINode *parent = child->GetNodeParent();
 
   // finally we get the index
   return parent ? parent->IndexOf(child) : -1;
 }
 
-/******************************************************
- * nsIRange implementation
- ******************************************************/
-
-/* virtual */ nsINode*
+nsINode*
 nsRange::GetCommonAncestor() const
 {
   return mIsPositioned ?
     nsContentUtils::GetCommonAncestor(mStartParent, mEndParent) :
     nsnull;
 }
 
-/* virtual */ void
+void
 nsRange::Reset()
 {
   DoSetRange(nsnull, 0, nsnull, 0, nsnull);
 }
 
 /******************************************************
  * public functionality
  ******************************************************/
@@ -907,17 +872,18 @@ nsRange::GetCommonAncestorContainer(nsID
   nsINode* container = nsContentUtils::GetCommonAncestor(mStartParent, mEndParent);
   if (container) {
     return CallQueryInterface(container, aCommonParent);
   }
 
   return NS_ERROR_NOT_INITIALIZED;
 }
 
-nsINode* nsIRange::IsValidBoundary(nsINode* aNode)
+nsINode*
+nsRange::IsValidBoundary(nsINode* aNode)
 {
   if (!aNode) {
     return nsnull;
   }
 
   if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
     nsIContent* content = static_cast<nsIContent*>(aNode);
     if (content->Tag() == nsGkAtoms::documentTypeNodeName) {
@@ -1795,17 +1761,17 @@ nsRange::ExtractContents(nsIDOMDocumentF
   NS_ENSURE_ARG_POINTER(aReturn);
   return CutContents(aReturn);
 }
 
 NS_IMETHODIMP
 nsRange::CompareBoundaryPoints(PRUint16 aHow, nsIDOMRange* aOtherRange,
                                PRInt16* aCmpRet)
 {
-  nsCOMPtr<nsIRange> otherRange = do_QueryInterface(aOtherRange);
+  nsRange* otherRange = static_cast<nsRange*>(aOtherRange);
   NS_ENSURE_TRUE(otherRange, NS_ERROR_NULL_POINTER);
 
   if(mIsDetached || otherRange->IsDetached())
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   if (!mIsPositioned || !otherRange->IsPositioned())
     return NS_ERROR_NOT_INITIALIZED;
 
   nsINode *ourNode, *otherNode;
@@ -2091,52 +2057,45 @@ nsRange::CloneContents(nsIDOMDocumentFra
   }
 
   *aReturn = clonedFrag;
   NS_IF_ADDREF(*aReturn);
 
   return NS_OK;
 }
 
-nsresult nsRange::DoCloneRange(nsIRange** aReturn) const
+nsresult
+nsRange::CloneRange(nsRange** aReturn) const
 {
   if(mIsDetached)
     return NS_ERROR_DOM_INVALID_STATE_ERR;
 
   if (aReturn == 0)
     return NS_ERROR_NULL_POINTER;
 
   nsRefPtr<nsRange> range = new nsRange();
-  NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
 
   range->SetMaySpanAnonymousSubtrees(mMaySpanAnonymousSubtrees);
 
   range->DoSetRange(mStartParent, mStartOffset, mEndParent, mEndOffset, mRoot);
 
-  *aReturn = range.forget().get();
+  range.forget(aReturn);
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsRange::CloneRange(nsIDOMRange** aReturn)
+NS_IMETHODIMP
+nsRange::CloneRange(nsIDOMRange** aReturn)
 {
-  nsIRange* clone;
-  nsresult rv = DoCloneRange(&clone);
-  if (NS_SUCCEEDED(rv)) {
-    *aReturn = clone;
-  }
+  nsRefPtr<nsRange> range;
+  nsresult rv = CloneRange(getter_AddRefs(range));
+  range.forget(aReturn);
   return rv;
 }
 
-/* virtual */ nsresult
-nsRange::CloneRange(nsIRange** aReturn) const
-{
-  return DoCloneRange(aReturn);
-}
-
 NS_IMETHODIMP
 nsRange::InsertNode(nsIDOMNode* aN)
 {
   VALIDATE_ACCESS(aN);
   
   nsresult res;
   PRInt32 tStartOffset;
   this->GetStartOffset(&tStartOffset);
@@ -2307,17 +2266,17 @@ nsRange::ToString(nsAString& aReturn)
   
   /* complex case: mStartParent != mEndParent, or mStartParent not a text node
      revisit - there are potential optimizations here and also tradeoffs.
   */
 
   nsCOMPtr<nsIContentIterator> iter;
   nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = iter->Init(static_cast<nsIRange*>(this));
+  rv = iter->Init(this);
   NS_ENSURE_SUCCESS(rv, rv);
   
   nsString tempString;
  
   // loop through the content iterator, which returns nodes in the range in 
   // close tag order, and grab the text from any text node
   while (!iter->IsDone())
   {
@@ -2372,17 +2331,16 @@ nsRange::Detach()
 
   mIsDetached = true;
 
   DoSetRange(nsnull, 0, nsnull, 0, nsnull);
   
   return NS_OK;
 }
 
-// nsIDOMNSRange interface
 NS_IMETHODIMP    
 nsRange::CreateContextualFragment(const nsAString& aFragment,
                                   nsIDOMDocumentFragment** aReturn)
 {
   if (mIsPositioned) {
     return nsContentUtils::CreateContextualFragment(mStartParent, aFragment,
                                                     false, aReturn);
   }
--- a/content/base/src/nsRange.h
+++ b/content/base/src/nsRange.h
@@ -37,69 +37,124 @@
 
 /*
  * Implementation of the DOM nsIDOMRange object.
  */
 
 #ifndef nsRange_h___
 #define nsRange_h___
 
-#include "nsIRange.h"
 #include "nsIDOMRange.h"
 #include "nsIRangeUtils.h"
-#include "nsIDOMNSRange.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIContent.h"
 #include "nsIDOMNode.h"
 #include "prmon.h"
 #include "nsStubMutationObserver.h"
 
-// -------------------------------------------------------------------------------
-
-class nsRangeUtils : public nsIRangeUtils
-{
-public:
-  NS_DECL_ISUPPORTS
-
-  // nsIRangeUtils interface
-  NS_IMETHOD_(PRInt32) ComparePoints(nsIDOMNode* aParent1, PRInt32 aOffset1,
-                                     nsIDOMNode* aParent2, PRInt32 aOffset2);
-                               
-  NS_IMETHOD CompareNodeToRange(nsIContent* aNode, 
-                                nsIDOMRange* aRange,
-                                bool *outNodeBefore,
-                                bool *outNodeAfter);
-};
-
-// -------------------------------------------------------------------------------
-
-class nsRange : public nsIRange,
-                public nsIDOMNSRange,
+class nsRange : public nsIDOMRange,
                 public nsStubMutationObserver
 {
 public:
-  nsRange(){}
+  nsRange()
+    : mRoot(nsnull)
+    , mStartOffset(0)
+    , mEndOffset(0)
+    , mIsPositioned(false)
+    , mIsDetached(false)
+    , mMaySpanAnonymousSubtrees(false)
+    , mInSelection(false)
+  {}
   virtual ~nsRange();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsRange, nsIRange)
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsRange, nsIDOMRange)
 
   // nsIDOMRange interface
   NS_DECL_NSIDOMRANGE
+  
+  nsINode* GetRoot() const
+  {
+    return mRoot;
+  }
 
-  // nsIDOMNSRange interface
-  NS_DECL_NSIDOMNSRANGE
+  nsINode* GetStartParent() const
+  {
+    return mStartParent;
+  }
+
+  nsINode* GetEndParent() const
+  {
+    return mEndParent;
+  }
+
+  PRInt32 StartOffset() const
+  {
+    return mStartOffset;
+  }
+
+  PRInt32 EndOffset() const
+  {
+    return mEndOffset;
+  }
+  
+  bool IsPositioned() const
+  {
+    return mIsPositioned;
+  }
+
+  bool IsDetached() const
+  {
+    return mIsDetached;
+  }
   
-  // nsIRange interface
-  virtual nsINode* GetCommonAncestor() const;
-  virtual void Reset();
-  virtual nsresult SetStart(nsINode* aParent, PRInt32 aOffset);
-  virtual nsresult SetEnd(nsINode* aParent, PRInt32 aOffset);
-  virtual nsresult CloneRange(nsIRange** aNewRange) const;
+  bool Collapsed() const
+  {
+    return mIsPositioned && mStartParent == mEndParent &&
+           mStartOffset == mEndOffset;
+  }
+
+  void SetMaySpanAnonymousSubtrees(bool aMaySpanAnonymousSubtrees)
+  {
+    mMaySpanAnonymousSubtrees = aMaySpanAnonymousSubtrees;
+  }
+  
+  /**
+   * Return true iff this range is part of at least one Selection object
+   * and isn't detached.
+   */
+  bool IsInSelection() const
+  {
+    return mInSelection;
+  }
+
+  /**
+   * Called when the range is added/removed from a Selection.
+   */
+  void SetInSelection(bool aInSelection)
+  {
+    if (mInSelection == aInSelection || mIsDetached) {
+      return;
+    }
+    mInSelection = aInSelection;
+    nsINode* commonAncestor = GetCommonAncestor();
+    NS_ASSERTION(commonAncestor, "unexpected disconnected nodes");
+    if (mInSelection) {
+      RegisterCommonAncestor(commonAncestor);
+    } else {
+      UnregisterCommonAncestor(commonAncestor);
+    }
+  }
+
+  nsINode* GetCommonAncestor() const;
+  void Reset();
+  nsresult SetStart(nsINode* aParent, PRInt32 aOffset);
+  nsresult SetEnd(nsINode* aParent, PRInt32 aOffset);
+  nsresult CloneRange(nsRange** aNewRange) const;
 
   nsresult Set(nsINode* aStartParent, PRInt32 aStartOffset,
                nsINode* aEndParent, PRInt32 aEndOffset)
   {
     // If this starts being hot, we may be able to optimize this a bit,
     // but for now just set start and end separately.
     nsresult rv = SetStart(aStartParent, aStartOffset);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -124,45 +179,42 @@ private:
   /**
    * Cut or delete the range's contents.
    *
    * @param aFragment nsIDOMDocumentFragment containing the nodes.
    *                  May be null to indicate the caller doesn't want a fragment.
    */
   nsresult CutContents(nsIDOMDocumentFragment** frag);
 
-  /**
-   * Guts of cloning a range.  Addrefs the new range.
-   */
-  nsresult DoCloneRange(nsIRange** aNewRange) const;
-
   static nsresult CloneParentsBetween(nsIDOMNode *aAncestor,
                                       nsIDOMNode *aNode,
                                       nsIDOMNode **aClosestAncestor,
                                       nsIDOMNode **aFarthestAncestor);
 
 public:
 /******************************************************************************
  *  Utility routine to detect if a content node starts before a range and/or 
  *  ends after a range.  If neither it is contained inside the range.
  *  
  *  XXX - callers responsibility to ensure node in same doc as range!
  *
  *****************************************************************************/
-  static nsresult CompareNodeToRange(nsINode* aNode, nsIDOMRange* aRange,
-                                     bool *outNodeBefore,
-                                     bool *outNodeAfter);
-  static nsresult CompareNodeToRange(nsINode* aNode, nsIRange* aRange,
+  static nsresult CompareNodeToRange(nsINode* aNode, nsRange* aRange,
                                      bool *outNodeBefore,
                                      bool *outNodeAfter);
 
   static bool IsNodeSelected(nsINode* aNode, PRUint32 aStartOffset,
                              PRUint32 aEndOffset);
 
+  typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
 protected:
+  void RegisterCommonAncestor(nsINode* aNode);
+  void UnregisterCommonAncestor(nsINode* aNode);
+  nsINode* IsValidBoundary(nsINode* aNode);
+
   // CharacterDataChanged set aNotInsertedYet to true to disable an assertion
   // and suppress re-registering a range common ancestor node since
   // the new text node of a splitText hasn't been inserted yet.
   // CharacterDataChanged does the re-registering when needed.
   void DoSetRange(nsINode* aStartN, PRInt32 aStartOffset,
                   nsINode* aEndN, PRInt32 aEndOffset,
                   nsINode* aRoot, bool aNotInsertedYet = false);
 
@@ -194,17 +246,40 @@ protected:
     nsRange* mRange;
     nsRefPtr<nsINode> mCommonAncestor;
 #ifdef DEBUG
     bool mWasInSelection;
 #endif
     static bool mIsNested;
   };
   
+  nsCOMPtr<nsINode> mRoot;
+  nsCOMPtr<nsINode> mStartParent;
+  nsCOMPtr<nsINode> mEndParent;
+  PRInt32 mStartOffset;
+  PRInt32 mEndOffset;
+
+  bool mIsPositioned;
+  bool mIsDetached;
+  bool mMaySpanAnonymousSubtrees;
+  bool mInSelection;
 };
 
-// Make a new nsIDOMRange object
-nsresult NS_NewRange(nsIDOMRange** aInstancePtrResult);
+
+class nsRangeUtils : public nsIRangeUtils
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  // nsIRangeUtils interface
+  NS_IMETHOD_(PRInt32) ComparePoints(nsIDOMNode* aParent1, PRInt32 aOffset1,
+                                     nsIDOMNode* aParent2, PRInt32 aOffset2);
+                               
+  NS_IMETHOD CompareNodeToRange(nsIContent* aNode, 
+                                nsRange* aRange,
+                                bool *outNodeBefore,
+                                bool *outNodeAfter);
+};
 
 // Make a new nsIRangeUtils object
 nsresult NS_NewRangeUtils(nsIRangeUtils** aInstancePtrResult);
 
 #endif /* nsRange_h___ */
--- a/content/base/src/nsTextNode.cpp
+++ b/content/base/src/nsTextNode.cpp
@@ -42,17 +42,17 @@
 #include "nsTextNode.h"
 #include "nsContentUtils.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsIAttribute.h"
 #include "nsIDocument.h"
 #include "nsThreadUtils.h"
 #ifdef DEBUG
-#include "nsIRange.h"
+#include "nsRange.h"
 #endif
 
 using namespace mozilla::dom;
 
 /**
  * class used to implement attr() generated content
  */
 class nsAttributeTextNode : public nsTextNode,
@@ -223,17 +223,17 @@ void
 nsTextNode::List(FILE* out, PRInt32 aIndent) const
 {
   PRInt32 index;
   for (index = aIndent; --index >= 0; ) fputs("  ", out);
 
   fprintf(out, "Text@%p", static_cast<const void*>(this));
   fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
   if (IsCommonAncestorForRangeInSelection()) {
-    typedef nsTHashtable<nsPtrHashKey<nsIRange> > RangeHashTable;
+    typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
     RangeHashTable* ranges =
       static_cast<RangeHashTable*>(GetProperty(nsGkAtoms::range));
     fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
   }
   fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
   fprintf(out, " refcount=%d<", mRefCnt.get());
 
   nsAutoString tmp;
--- a/content/base/test/test_bug451376.html
+++ b/content/base/test/test_bug451376.html
@@ -25,18 +25,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
     function testRange(aRangeID,
                        aStartNode, aStartOffset,
                        aEndNode, aEndOffset,
                        aBeforeRangeNode, aBeforeRangeOffset,
                        aInRangeNode, aInRangeOffset,
                        aAfterRangeNode, aAfterRangeOffset)
     {
-      var range = document.createRange().
-        QueryInterface(Components.interfaces.nsIDOMNSRange);
+      var range = document.createRange();
 
       range.setStart(aStartNode, aStartOffset);
       range.setEnd(aEndNode, aEndOffset);
 
       if (aBeforeRangeNode)
         is(range.comparePoint(aBeforeRangeNode, aBeforeRangeOffset), -1,
            "Wrong result for the point before the range '" + aRangeID + "'");
       if (aInRangeNode)
--- a/content/events/src/nsContentEventHandler.cpp
+++ b/content/events/src/nsContentEventHandler.cpp
@@ -93,18 +93,17 @@ nsContentEventHandler::InitCommon()
   nsCopySupport::GetSelectionForCopy(mPresShell->GetDocument(),
                                      getter_AddRefs(mSelection));
 
   nsCOMPtr<nsIDOMRange> firstRange;
   nsresult rv = mSelection->GetRangeAt(0, getter_AddRefs(firstRange));
   // This shell doesn't support selection.
   if (NS_FAILED(rv))
     return NS_ERROR_NOT_AVAILABLE;
-  mFirstSelectedRange = do_QueryInterface(firstRange);
-  NS_ENSURE_TRUE(mFirstSelectedRange, NS_ERROR_FAILURE);
+  mFirstSelectedRange = static_cast<nsRange*>(firstRange.get());
 
   nsINode* startNode = mFirstSelectedRange->GetStartParent();
   NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
   nsINode* endNode = mFirstSelectedRange->GetEndParent();
   NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE);
 
   // See bug 537041 comment 5, the range could have removed node.
   NS_ENSURE_TRUE(startNode->GetCurrentDoc() == mPresShell->GetDocument(),
@@ -275,26 +274,24 @@ static PRUint32 ConvertToXPOffset(nsICon
   // offset minus the number of newlines encountered in the string.
   return aNativeOffset - CountNewlinesIn(aContent, aNativeOffset);
 #else
   // On other platforms, the native and XP newlines are the same.
   return aNativeOffset;
 #endif
 }
 
-static nsresult GenerateFlatTextContent(nsIRange* aRange,
+static nsresult GenerateFlatTextContent(nsRange* aRange,
                                         nsAFlatString& aString)
 {
   nsCOMPtr<nsIContentIterator> iter;
   nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ASSERTION(iter, "NS_NewContentIterator succeeded, but the result is null");
-  nsCOMPtr<nsIDOMRange> domRange(do_QueryInterface(aRange));
-  NS_ASSERTION(domRange, "aRange doesn't have nsIDOMRange!");
-  iter->Init(domRange);
+  iter->Init(aRange);
 
   NS_ASSERTION(aString.IsEmpty(), "aString must be empty string");
 
   nsINode* startNode = aRange->GetStartParent();
   NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
   nsINode* endNode = aRange->GetEndParent();
   NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE);
 
@@ -369,29 +366,27 @@ nsContentEventHandler::ExpandToClusterBo
   newOffsetInFrame += aForward ? -1 : 1;
   textFrame->PeekOffsetCharacter(aForward, &newOffsetInFrame);
   *aXPOffset = startOffset + newOffsetInFrame;
   return NS_OK;
 }
 
 nsresult
 nsContentEventHandler::SetRangeFromFlatTextOffset(
-                              nsIRange* aRange,
+                              nsRange* aRange,
                               PRUint32 aNativeOffset,
                               PRUint32 aNativeLength,
                               bool aExpandToClusterBoundaries)
 {
   nsCOMPtr<nsIContentIterator> iter;
   nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ASSERTION(iter, "NS_NewContentIterator succeeded, but the result is null");
   rv = iter->Init(mRootContent);
   NS_ENSURE_SUCCESS(rv, rv);
-  nsCOMPtr<nsIDOMRange> domRange(do_QueryInterface(aRange));
-  NS_ASSERTION(domRange, "aRange doesn't have nsIDOMRange!");
 
   PRUint32 nativeOffset = 0;
   PRUint32 nativeEndOffset = aNativeOffset + aNativeLength;
   nsCOMPtr<nsIContent> content;
   for (; !iter->IsDone(); iter->Next()) {
     nsINode* node = iter->GetCurrentNode();
     if (!node || !node->IsNodeOfType(nsINode::eCONTENT))
       continue;
@@ -411,21 +406,21 @@ nsContentEventHandler::SetRangeFromFlatT
         content->IsNodeOfType(nsINode::eTEXT) ?
           ConvertToXPOffset(content, aNativeOffset - nativeOffset) : 0;
 
       if (aExpandToClusterBoundaries) {
         rv = ExpandToClusterBoundary(content, false, &xpOffset);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
-      rv = domRange->SetStart(domNode, PRInt32(xpOffset));
+      rv = aRange->SetStart(domNode, PRInt32(xpOffset));
       NS_ENSURE_SUCCESS(rv, rv);
       if (aNativeLength == 0) {
         // Ensure that the end offset and the start offset are same.
-        rv = domRange->SetEnd(domNode, PRInt32(xpOffset));
+        rv = aRange->SetEnd(domNode, PRInt32(xpOffset));
         NS_ENSURE_SUCCESS(rv, rv);
         return NS_OK;
       }
     }
     if (nativeEndOffset <= nativeOffset + nativeTextLength) {
       nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(content));
       NS_ASSERTION(domNode, "aContent doesn't have nsIDOMNode!");
 
@@ -441,34 +436,34 @@ nsContentEventHandler::SetRangeFromFlatT
         // by ContentIterator when the offset is zero.
         xpOffset = 0;
         iter->Next();
         if (iter->IsDone())
           break;
         domNode = do_QueryInterface(iter->GetCurrentNode());
       }
 
-      rv = domRange->SetEnd(domNode, PRInt32(xpOffset));
+      rv = aRange->SetEnd(domNode, PRInt32(xpOffset));
       NS_ENSURE_SUCCESS(rv, rv);
       return NS_OK;
     }
 
     nativeOffset += nativeTextLength;
   }
 
   if (nativeOffset < aNativeOffset)
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mRootContent));
   NS_ASSERTION(domNode, "lastContent doesn't have nsIDOMNode!");
   if (!content) {
-    rv = domRange->SetStart(domNode, 0);
+    rv = aRange->SetStart(domNode, 0);
     NS_ENSURE_SUCCESS(rv, rv);
   }
-  rv = domRange->SetEnd(domNode, PRInt32(mRootContent->GetChildCount()));
+  rv = aRange->SetEnd(domNode, PRInt32(mRootContent->GetChildCount()));
   NS_ASSERTION(NS_SUCCEEDED(rv), "nsIDOMRange::SetEnd failed");
   return rv;
 }
 
 nsresult
 nsContentEventHandler::OnQuerySelectedText(nsQueryContentEvent* aEvent)
 {
   nsresult rv = Init(aEvent);
@@ -498,18 +493,17 @@ nsContentEventHandler::OnQuerySelectedTe
   nsCOMPtr<nsINode> focusNode(do_QueryInterface(focusDomNode));
   NS_ENSURE_TRUE(anchorNode && focusNode, NS_ERROR_UNEXPECTED);
 
   PRInt16 compare = nsContentUtils::ComparePoints(anchorNode, anchorOffset,
                                                   focusNode, focusOffset);
   aEvent->mReply.mReversed = compare > 0;
 
   if (compare) {
-    nsCOMPtr<nsIRange> range = mFirstSelectedRange;
-    rv = GenerateFlatTextContent(range, aEvent->mReply.mString);
+    rv = GenerateFlatTextContent(mFirstSelectedRange, aEvent->mReply.mString);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   aEvent->mSucceeded = true;
   return NS_OK;
 }
 
 nsresult
@@ -517,18 +511,17 @@ nsContentEventHandler::OnQueryTextConten
 {
   nsresult rv = Init(aEvent);
   if (NS_FAILED(rv))
     return rv;
 
   NS_ASSERTION(aEvent->mReply.mString.IsEmpty(),
                "The reply string must be empty");
 
-  nsCOMPtr<nsIRange> range = new nsRange();
-  NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
+  nsRefPtr<nsRange> range = new nsRange();
   rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset,
                                   aEvent->mInput.mLength, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = GenerateFlatTextContent(range, aEvent->mReply.mString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   aEvent->mSucceeded = true;
@@ -575,20 +568,17 @@ static nsresult GetFrameForTextRect(nsIN
 
 nsresult
 nsContentEventHandler::OnQueryTextRect(nsQueryContentEvent* aEvent)
 {
   nsresult rv = Init(aEvent);
   if (NS_FAILED(rv))
     return rv;
 
-  nsCOMPtr<nsIRange> range = new nsRange();
-  if (!range) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
+  nsRefPtr<nsRange> range = new nsRange();
   rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset,
                                   aEvent->mInput.mLength, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // used to iterate over all contents and their frames
   nsCOMPtr<nsIContentIterator> iter;
   rv = NS_NewContentIterator(getter_AddRefs(iter));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -723,18 +713,17 @@ nsContentEventHandler::OnQueryCaretRect(
       aEvent->mReply.mRect =
         rect.ToOutsidePixels(caretFrame->PresContext()->AppUnitsPerDevPixel());
       aEvent->mSucceeded = true;
       return NS_OK;
     }
   }
 
   // Otherwise, we should set the guessed caret rect.
-  nsCOMPtr<nsIRange> range = new nsRange();
-  NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
+  nsRefPtr<nsRange> range = new nsRange();
   rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 0, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt32 offsetInFrame;
   nsIFrame* frame;
   rv = GetStartFrameAndOffset(range, &frame, &offsetInFrame);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -911,32 +900,29 @@ nsContentEventHandler::OnQueryDOMWidgetH
 nsresult
 nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
                                                 nsINode* aNode,
                                                 PRInt32 aNodeOffset,
                                                 PRUint32* aNativeOffset)
 {
   NS_ASSERTION(aNativeOffset, "param is invalid");
 
-  nsCOMPtr<nsIRange> prev = new nsRange();
-  NS_ENSURE_TRUE(prev, NS_ERROR_OUT_OF_MEMORY);
-  nsCOMPtr<nsIDOMRange> domPrev(do_QueryInterface(prev));
-  NS_ASSERTION(domPrev, "nsRange doesn't have nsIDOMRange??");
+  nsRefPtr<nsRange> prev = new nsRange();
   nsCOMPtr<nsIDOMNode> rootDOMNode(do_QueryInterface(aRootContent));
-  domPrev->SetStart(rootDOMNode, 0);
+  prev->SetStart(rootDOMNode, 0);
 
   nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(aNode));
   NS_ASSERTION(startDOMNode, "startNode doesn't have nsIDOMNode");
-  domPrev->SetEnd(startDOMNode, aNodeOffset);
+  prev->SetEnd(startDOMNode, aNodeOffset);
 
   nsCOMPtr<nsIContentIterator> iter;
   nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ASSERTION(iter, "NS_NewContentIterator succeeded, but the result is null");
-  iter->Init(domPrev);
+  iter->Init(prev);
 
   nsCOMPtr<nsINode> startNode = do_QueryInterface(startDOMNode);
   nsINode* endNode = aNode;
 
   *aNativeOffset = 0;
   for (; !iter->IsDone(); iter->Next()) {
     nsINode* node = iter->GetCurrentNode();
     if (!node || !node->IsNodeOfType(nsINode::eCONTENT))
@@ -959,28 +945,28 @@ nsContentEventHandler::GetFlatTextOffset
 #endif
     }
   }
   return NS_OK;
 }
 
 nsresult
 nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
-                                                nsIRange* aRange,
+                                                nsRange* aRange,
                                                 PRUint32* aNativeOffset)
 {
   nsINode* startNode = aRange->GetStartParent();
   NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
   PRInt32 startOffset = aRange->StartOffset();
   return GetFlatTextOffsetOfRange(aRootContent, startNode, startOffset,
                                   aNativeOffset);
 }
 
 nsresult
-nsContentEventHandler::GetStartFrameAndOffset(nsIRange* aRange,
+nsContentEventHandler::GetStartFrameAndOffset(nsRange* aRange,
                                               nsIFrame** aFrame,
                                               PRInt32* aOffsetInFrame)
 {
   NS_ASSERTION(aRange && aFrame && aOffsetInFrame, "params are invalid");
 
   nsIContent* content = nsnull;
   nsINode* node = aRange->GetStartParent();
   if (node && node->IsNodeOfType(nsINode::eCONTENT))
--- a/content/events/src/nsContentEventHandler.h
+++ b/content/events/src/nsContentEventHandler.h
@@ -39,17 +39,17 @@
 
 #ifndef nsContentEventHandler_h__
 #define nsContentEventHandler_h__
 
 #include "nscore.h"
 #include "nsCOMPtr.h"
 
 #include "nsISelection.h"
-#include "nsIRange.h"
+#include "nsRange.h"
 #include "nsIContent.h"
 #include "nsIDOMTreeWalker.h"
 
 class nsPresContext;
 class nsIPresShell;
 class nsQueryContentEvent;
 class nsSelectionEvent;
 class nsCaret;
@@ -88,17 +88,17 @@ public:
 
   // NS_SELECTION_* event
   nsresult OnSelectionEvent(nsSelectionEvent* aEvent);
 
 protected:
   nsPresContext* mPresContext;
   nsCOMPtr<nsIPresShell> mPresShell;
   nsCOMPtr<nsISelection> mSelection;
-  nsCOMPtr<nsIRange> mFirstSelectedRange;
+  nsRefPtr<nsRange> mFirstSelectedRange;
   nsCOMPtr<nsIContent> mRootContent;
 
   nsresult Init(nsQueryContentEvent* aEvent);
   nsresult Init(nsSelectionEvent* aEvent);
 
   // InitCommon() is called from each Init().
   nsresult InitCommon();
 
@@ -107,29 +107,29 @@ public:
   // are replaced to native linefeeds. Other elements are ignored.
 
   // Get the offset in FlatText of the range. (also used by nsIMEStateManager)
   static nsresult GetFlatTextOffsetOfRange(nsIContent* aRootContent,
                                            nsINode* aNode,
                                            PRInt32 aNodeOffset,
                                            PRUint32* aOffset);
   static nsresult GetFlatTextOffsetOfRange(nsIContent* aRootContent,
-                                           nsIRange* aRange,
+                                           nsRange* aRange,
                                            PRUint32* aOffset);
 protected:
   // Make the DOM range from the offset of FlatText and the text length.
   // If aExpandToClusterBoundaries is true, the start offset and the end one are
   // expanded to nearest cluster boundaries.
-  nsresult SetRangeFromFlatTextOffset(nsIRange* aRange,
+  nsresult SetRangeFromFlatTextOffset(nsRange* aRange,
                                       PRUint32 aNativeOffset,
                                       PRUint32 aNativeLength,
                                       bool aExpandToClusterBoundaries);
   // Find the first textframe for the range, and get the start offset in
   // the frame.
-  nsresult GetStartFrameAndOffset(nsIRange* aRange,
+  nsresult GetStartFrameAndOffset(nsRange* aRange,
                                   nsIFrame** aFrame,
                                   PRInt32* aOffsetInFrame);
   // Convert the frame relative offset to the root view relative offset.
   nsresult ConvertToRootViewRelativeOffset(nsIFrame* aFrame,
                                            nsRect& aRect);
   // Expand aXPOffset to the nearest offset in cluster boundary. aForward is
   // true, it is expanded to forward.
   nsresult ExpandToClusterBoundary(nsIContent* aContent, bool aForward,
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -487,17 +487,17 @@ nsTextStateManager::Init(nsIWidget* aWid
   nsresult rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
                                      getter_AddRefs(sel));
   NS_ENSURE_TRUE(sel, NS_ERROR_UNEXPECTED);
 
   nsCOMPtr<nsIDOMRange> selDomRange;
   rv = sel->GetRangeAt(0, getter_AddRefs(selDomRange));
 
   if (NS_SUCCEEDED(rv)) {
-    nsCOMPtr<nsIRange> selRange(do_QueryInterface(selDomRange));
+    nsRange* selRange = static_cast<nsRange*>(selDomRange.get());
     NS_ENSURE_TRUE(selRange && selRange->GetStartParent(),
                    NS_ERROR_UNEXPECTED);
 
     mRootContent = selRange->GetStartParent()->
                      GetSelectionRootContent(presShell);
   } else {
     mRootContent = aNode->GetSelectionRootContent(presShell);
   }
--- a/content/events/test/test_eventctors.xul
+++ b/content/events/test/test_eventctors.xul
@@ -38,14 +38,12 @@ https://bugzilla.mozilla.org/show_bug.cg
   
   e = new Event("hello");
   ok(e.type, "hello", "Wrong event type!");
   ok(e.isTrusted, "Event should be trusted!");
   ok(!e.bubbles, "Event shouldn't bubble!");
   ok(!e.cancelable, "Event shouldn't be cancelable!");
   document.dispatchEvent(e);
   is(receivedEvent, e, "Wrong event!");
-  
-  SimpleTest.finish();
 
   ]]>
   </script>
 </window>
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -2554,16 +2554,17 @@ nsGenericHTMLElement::GetContextMenu(nsI
   }
 
   return NS_OK;
 }
 
 //----------------------------------------------------------------------
 
 NS_IMPL_INT_ATTR(nsGenericHTMLFrameElement, TabIndex, tabindex)
+NS_IMPL_BOOL_ATTR(nsGenericHTMLFrameElement, MozBrowser, mozbrowser)
 
 nsGenericHTMLFormElement::nsGenericHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
   , mForm(nsnull)
   , mFieldSet(nsnull)
 {
   // We should add the NS_EVENT_STATE_ENABLED bit here as needed, but
   // that depends on our type, which is not initialized yet.  So we
@@ -3222,18 +3223,19 @@ nsGenericHTMLFrameElement::~nsGenericHTM
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mFrameLoader, nsIFrameLoader)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_TABLE_HEAD(nsGenericHTMLFrameElement)
-  NS_INTERFACE_TABLE_INHERITED1(nsGenericHTMLFrameElement,
-                                nsIFrameLoaderOwner)
+  NS_INTERFACE_TABLE_INHERITED2(nsGenericHTMLFrameElement,
+                                nsIFrameLoaderOwner,
+                                nsIDOMMozBrowserFrameElement)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsGenericHTMLFrameElement)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
 
 nsresult
 nsGenericHTMLFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
 {
   NS_PRECONDITION(aContentDocument, "Null out param");
   *aContentDocument = nsnull;
@@ -3430,16 +3432,118 @@ nsGenericHTMLFrameElement::SizeOf() cons
 {
   PRInt64 size = MemoryReporter::GetBasicSize<nsGenericHTMLFrameElement,
                                               nsGenericHTMLElement>(this);
   // TODO: need to implement SizeOf() in nsFrameLoader, bug 672539.
   size += mFrameLoader ? sizeof(*mFrameLoader.get()) : 0;
   return size;
 }
 
+namespace {
+
+// GetContentStateCallbackRunnable is used by MozGetContentState to fire its callback
+// asynchronously.
+class GetContentStateCallbackRunnable : public nsRunnable
+{
+public:
+  GetContentStateCallbackRunnable(nsIDOMMozGetContentStateCallback *aCallback,
+                             nsIDOMEventTarget *aEventTarget,
+                             const nsAString &aResult)
+    : mCallback(aCallback)
+    , mEventTarget(aEventTarget)
+    , mResult(aResult)
+  {
+  }
+
+  NS_IMETHOD Run()
+  {
+    FireCallback();
+
+    // Break cycles.
+    mCallback = NULL;
+    mEventTarget = NULL;
+    return NS_OK;
+  }
+
+private:
+  void FireCallback()
+  {
+    nsCxPusher pusher;
+    if (!pusher.Push(mEventTarget)) {
+      return;
+    }
+
+    mCallback->Callback(mResult);
+  }
+
+  nsCOMPtr<nsIDOMMozGetContentStateCallback> mCallback;
+  nsCOMPtr<nsIDOMEventTarget> mEventTarget;
+  const nsString mResult;
+};
+
+} // anonymous namespace
+
+nsresult
+nsGenericHTMLFrameElement::BrowserFrameSecurityCheck()
+{
+  if (!Preferences::GetBool("dom.mozBrowserFramesEnabled")) {
+    return NS_ERROR_FAILURE;
+  }
+
+  bool browser;
+  GetMozBrowser(&browser);
+  if (!browser) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsIPrincipal *principal = NodePrincipal();
+  nsCOMPtr<nsIURI> principalURI;
+  principal->GetURI(getter_AddRefs(principalURI));
+  if (!nsContentUtils::URIIsChromeOrInPref(principalURI,
+                                           "dom.mozBrowserFramesWhitelist")) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGenericHTMLFrameElement::MozGetContentState(const nsAString &aProperty,
+                                              nsIDOMMozGetContentStateCallback *aCallback)
+{
+  nsresult rv = BrowserFrameSecurityCheck();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (!aProperty.EqualsLiteral("location")) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIDOMWindow> contentWindow;
+  GetContentWindow(getter_AddRefs(contentWindow));
+  NS_ENSURE_TRUE(contentWindow, NS_ERROR_FAILURE);
+
+  nsCOMPtr<nsIDOMLocation> location;
+  rv = contentWindow->GetLocation(getter_AddRefs(location));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoString href;
+  rv = location->ToString(href);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIDOMEventTarget> eventTarget =
+    do_QueryInterface(nsContentUtils::GetWindowFromCaller());
+  NS_ENSURE_TRUE(eventTarget, NS_ERROR_FAILURE);
+
+  // Asynchronously fire the callback.
+  nsRefPtr<GetContentStateCallbackRunnable> runnable =
+    new GetContentStateCallbackRunnable(aCallback, eventTarget, href);
+  NS_DispatchToMainThread(runnable);
+  return NS_OK;
+}
+
 //----------------------------------------------------------------------
 
 nsresult
 nsGenericHTMLElement::Blur()
 {
   if (!ShouldBlur(this)) {
     return NS_OK;
   }
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -42,16 +42,17 @@
 #include "nsIDOMHTMLElement.h"
 #include "nsINameSpaceManager.h"  // for kNameSpaceID_None
 #include "nsIFormControl.h"
 #include "nsIDOMHTMLFrameElement.h"
 #include "nsFrameLoader.h"
 #include "nsGkAtoms.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsDOMMemoryReporter.h"
+#include "nsIDOMMozBrowserFrameElement.h"
 
 class nsIDOMAttr;
 class nsIDOMEventListener;
 class nsIDOMNodeList;
 class nsIFrame;
 class nsIStyleRule;
 class nsChildContentList;
 class nsDOMCSSDeclaration;
@@ -1014,17 +1015,18 @@ PR_STATIC_ASSERT(ELEMENT_TYPE_SPECIFIC_B
 
 //----------------------------------------------------------------------
 
 /**
  * A helper class for frame elements
  */
 
 class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
-                                  public nsIFrameLoaderOwner
+                                  public nsIFrameLoaderOwner,
+                                  public nsIDOMMozBrowserFrameElement
 {
 public:
   nsGenericHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                             mozilla::dom::FromParser aFromParser)
     : nsGenericHTMLElement(aNodeInfo)
   {
     mNetworkCreated = aFromParser == mozilla::dom::FROM_PARSER_NETWORK;
   }
@@ -1059,24 +1061,29 @@ public:
 
   // nsIDOMHTMLElement 
   NS_IMETHOD GetTabIndex(PRInt32 *aTabIndex);
   NS_IMETHOD SetTabIndex(PRInt32 aTabIndex);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsGenericHTMLFrameElement,
                                                      nsGenericHTMLElement)
 
+  // nsIDOMMozBrowserFrameElement
+  NS_DECL_NSIDOMMOZBROWSERFRAMEELEMENT
+
 protected:
   // This doesn't really ensure a frame loade in all cases, only when
   // it makes sense.
   nsresult EnsureFrameLoader();
   nsresult LoadSrc();
   nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
   nsresult GetContentWindow(nsIDOMWindow** aContentWindow);
 
+  nsresult BrowserFrameSecurityCheck();
+
   nsRefPtr<nsFrameLoader> mFrameLoader;
   // True when the element is created by the parser
   // using NS_FROM_PARSER_NETWORK flag.
   // If the element is modified, it may lose the flag.
   bool                    mNetworkCreated;
 };
 
 //----------------------------------------------------------------------
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -2659,17 +2659,17 @@ nsIContent* nsHTMLMediaElement::GetNextS
 {
   nsCOMPtr<nsIDOMNode> thisDomNode = do_QueryObject(this);
 
   mSourceLoadCandidate = nsnull;
 
   nsresult rv = NS_OK;
   if (!mSourcePointer) {
     // First time this has been run, create a selection to cover children.
-    mSourcePointer = do_CreateInstance("@mozilla.org/content/range;1");
+    mSourcePointer = new nsRange();
 
     rv = mSourcePointer->SelectNodeContents(thisDomNode);
     if (NS_FAILED(rv)) return nsnull;
 
     rv = mSourcePointer->Collapse(true);
     if (NS_FAILED(rv)) return nsnull;
   }
 
--- a/content/html/content/test/test_bug389797.html
+++ b/content/html/content/test/test_bug389797.html
@@ -138,31 +138,31 @@ HTML_TAG("dt", "");
 HTML_TAG("em", "");
 HTML_TAG("embed", "Embed", [ "nsIDOMGetSVGDocument" ], objectIfaces);
 HTML_TAG("fieldset", "FieldSet");
 HTML_TAG("figcaption", "")
 HTML_TAG("figure", "")
 HTML_TAG("font", "Font");
 HTML_TAG("footer", "")
 HTML_TAG("form", "Form", [], [ "nsIWebProgressListener" ]);
-HTML_TAG("frame", "Frame", [], [ "nsIFrameLoaderOwner" ]);
+HTML_TAG("frame", "Frame", [ "nsIDOMMozBrowserFrameElement" ], [ "nsIFrameLoaderOwner" ]);
 HTML_TAG("frameset", "FrameSet");
 HTML_TAG("h1", "Heading");
 HTML_TAG("h2", "Heading");
 HTML_TAG("h3", "Heading");
 HTML_TAG("h4", "Heading");
 HTML_TAG("h5", "Heading");
 HTML_TAG("h6", "Heading");
 HTML_TAG("head", "Head");
 HTML_TAG("header", "")
 HTML_TAG("hgroup", "")
 HTML_TAG("hr", "HR");
 HTML_TAG("html", "Html");
 HTML_TAG("i", "");
-HTML_TAG("iframe", "IFrame", [ "nsIDOMGetSVGDocument" ],
+HTML_TAG("iframe", "IFrame", [ "nsIDOMGetSVGDocument", "nsIDOMMozBrowserFrameElement" ],
                              [ "nsIFrameLoaderOwner" ]);
 HTML_TAG("image", "Span");
 HTML_TAG("img", "Image", [], [ "imgIDecoderObserver",
                                "nsIImageLoadingContent" ]);
 HTML_TAG("input", "Input", [], [ "imgIDecoderObserver",
                                  "nsIImageLoadingContent",
                                  "nsIDOMNSEditableElement" ]);
 HTML_TAG("ins", "Mod");
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2521,20 +2521,17 @@ nsHTMLDocument::DeferredContentEditableC
 
       nsCOMPtr<nsIEditorDocShell> editorDocShell =
         do_QueryInterface(docshell, &rv);
       NS_ENSURE_SUCCESS(rv, );
 
       nsCOMPtr<nsIEditor> editor;
       editorDocShell->GetEditor(getter_AddRefs(editor));
       if (editor) {
-        nsCOMPtr<nsIDOMRange> range;
-        rv = NS_NewRange(getter_AddRefs(range));
-        NS_ENSURE_SUCCESS(rv, );
-
+        nsRefPtr<nsRange> range = new nsRange();
         rv = range->SelectNode(node);
         if (NS_FAILED(rv)) {
           // The node might be detached from the document at this point,
           // which would cause this call to fail.  In this case, we can
           // safely ignore the contenteditable count change.
           return;
         }
 
--- a/content/test/unit/test_range.js
+++ b/content/test/unit/test_range.js
@@ -498,17 +498,16 @@ function run_miscellaneous_tests() {
 
   baseRange.setEnd(externalRange.endContainer, 0);
   do_check_eq(baseRange.startContainer, externalRange.endContainer);
   do_check_eq(baseRange.startOffset, 0);
   do_check_true(baseRange.collapsed);
 
   /*
   // XXX ajvincent if rv == WRONG_DOCUMENT_ERR, return false?
-  do_check_true(baseRange instanceof C_i.nsIDOMNSRange);
   do_check_false(baseRange.isPointInRange(startContainer, startOffset));
   do_check_false(baseRange.isPointInRange(startContainer, startOffset + 1));
   do_check_false(baseRange.isPointInRange(endContainer, endOffset));
   */
 
   // Requested by smaug:  A range involving a comment as a document child.
   doc = parser.parseFromString("<!-- foo --><foo/>", "application/xml");
   do_check_true(doc instanceof C_i.nsIDOMDocument);
--- a/content/xbl/test/test_bug296375.xul
+++ b/content/xbl/test/test_bug296375.xul
@@ -28,14 +28,14 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 /** Test for Bug 296375 **/
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function () {
   document.addBinding(document.getElementById("b"),
                       "chrome://global/content/bindings/checkbox.xml#checkbox");
   ok(true, "addBinding didn't cause a crash");
+  SimpleTest.finish();
 });
-addLoadEvent(SimpleTest.finish);
 ]]>
 </script>
 
 </window>
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -135,16 +135,17 @@
 #include "nsDOMError.h"
 #include "nsIDOMDOMException.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMNamedNodeMap.h"
 #include "nsIDOMDOMStringList.h"
 #include "nsIDOMDOMTokenList.h"
 #include "nsIDOMDOMSettableTokenList.h"
+#include "nsIDOMMozBrowserFrameElement.h"
 
 #include "nsDOMStringMap.h"
 
 // HTMLFormElement helper includes
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMHTMLCollection.h"
@@ -324,17 +325,16 @@
 #include "nsIDOMMozCSSKeyframesRule.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsIDOMCSSStyleRule.h"
 #include "nsIDOMCSSStyleSheet.h"
 #include "nsDOMCSSValueList.h"
 #include "nsIDOMDeviceOrientationEvent.h"
 #include "nsIDOMDeviceMotionEvent.h"
 #include "nsIDOMRange.h"
-#include "nsIDOMNSRange.h"
 #include "nsIDOMRangeException.h"
 #include "nsIDOMNodeIterator.h"
 #include "nsIDOMTreeWalker.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIDOMCrypto.h"
 #include "nsIDOMCRMFObject.h"
@@ -2667,16 +2667,17 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN(HTMLFormElement, nsIDOMHTMLFormElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLFormElement)
     DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(HTMLFrameElement, nsIDOMHTMLFrameElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLFrameElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozBrowserFrameElement)
     DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(HTMLFrameSetElement, nsIDOMHTMLFrameSetElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLFrameSetElement)
     DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
@@ -2698,16 +2699,17 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(HTMLHtmlElement, nsIDOMHTMLHtmlElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLHtmlElement)
     DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(HTMLIFrameElement, nsIDOMHTMLIFrameElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLIFrameElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMGetSVGDocument)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozBrowserFrameElement)
     DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(HTMLImageElement, nsIDOMHTMLImageElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLImageElement)
     DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
@@ -2950,17 +2952,16 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(CSSRGBColor, nsIDOMRGBColor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMRGBColor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSRGBAColor)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(Range, nsIDOMRange)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMRange)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSRange)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(NodeIterator, nsIDOMNodeIterator)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeIterator)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(TreeWalker, nsIDOMTreeWalker)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMTreeWalker)
--- a/dom/interfaces/html/Makefile.in
+++ b/dom/interfaces/html/Makefile.in
@@ -111,16 +111,17 @@ SDK_XPIDLSRCS =					\
 	nsIDOMTimeRanges.idl		\
 	nsIDOMHTMLByteRanges.idl		\
 	nsIDOMHTMLMediaElement.idl		\
 	nsIDOMHTMLSourceElement.idl		\
 	nsIDOMHTMLVideoElement.idl		\
 	nsIDOMHTMLAudioElement.idl		\
 	nsIDOMValidityState.idl		\
 	nsIDOMDOMStringMap.idl		\
+	nsIDOMMozBrowserFrameElement.idl	\
 	$(NULL)
 
 XPIDLSRCS = 					\
 	nsIDOMHTMLCanvasElement.idl		\
 	nsIDOMHTMLUnknownElement.idl \
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMMozBrowserFrameElement.idl
@@ -0,0 +1,68 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Justin Lebar <justin.lebar@gmail.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 "nsISupports.idl"
+
+[scriptable, function, uuid(37687881-1801-489f-ad03-7af651a93448)]
+interface nsIDOMMozGetContentStateCallback : nsISupports
+{
+  void callback(in DOMString value);
+};
+
+[scriptable, uuid(2ff0f421-64e4-4186-b0dd-619629f46048)]
+interface nsIDOMMozBrowserFrameElement : nsISupports
+{
+  /**
+   * If true, a privileged page can call mozGetContentState on this element.
+   * If false, mozGetContentState will fail.
+   */
+  attribute boolean mozBrowser;
+
+  /**
+   * Get a piece of state from this element's content window, returning its
+   * value via |callback|.
+   *
+   * At the moment, the only valid property is "location", which returns the
+   * content window's location.  Passing any other property causes an error.
+   *
+   * If the iframe's mozBrowser is false, or if the calling window is not
+   * privileged, this function fails.
+   */
+  void mozGetContentState(in DOMString property,
+                          in nsIDOMMozGetContentStateCallback callback);
+};
--- a/dom/interfaces/range/Makefile.in
+++ b/dom/interfaces/range/Makefile.in
@@ -41,18 +41,17 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= dom
 XPIDL_MODULE	= dom_range
 GRE_MODULE	= 1
 
-SDK_XPIDLSRCS = 				\
-	nsIDOMRange.idl				\
+SDK_XPIDLSRCS =		\
+	nsIDOMRange.idl	\
 	$(NULL)
 
-XPIDLSRCS =					\
-	nsIDOMNSRange.idl			\
+XPIDLSRCS =						\
 	nsIDOMRangeException.idl	\
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/dom/interfaces/range/nsIDOMNSRange.idl
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: IDL; 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) 2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Vidur Apparao <vidur@netscape.com> (original author)
- *   Johnny Stenback <jst@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 "domstubs.idl"
-
-[scriptable, uuid(fed93d11-f24d-41d8-ae55-4197927999bb)]
-interface nsIDOMNSRange : nsISupports
-{
-  nsIDOMDocumentFragment    createContextualFragment(in DOMString fragment);
-
-  // This returns true if parent+offset equals either
-  // of the boundary points or is between them.
-  boolean                   isPointInRange(in nsIDOMNode parent,
-                                           in long offset);
-
-  // comparePoint returns
-  //   -1 if point is before the start boundary point,
-  //    0 if point is either of the boundary points or between them,
-  //    1 if point is after the end boundary point.
-  // Sort of a strcmp for ranges.
-  short                     comparePoint(in nsIDOMNode parent, in long offset);
-
-  nsIDOMClientRectList getClientRects();
-  nsIDOMClientRect getBoundingClientRect();
-};
--- a/dom/interfaces/range/nsIDOMRange.idl
+++ b/dom/interfaces/range/nsIDOMRange.idl
@@ -41,17 +41,17 @@
 
 /**
  * The nsIDOMRange interface is an interface to a DOM range object.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Traversal-Range/
  */
 
-[scriptable, uuid(a6cf90ce-15b3-11d2-932e-00805f8add32)]
+[scriptable, builtinclass, uuid(a059eea8-fece-4c14-93d3-7f50a944ae43)]
 interface nsIDOMRange : nsISupports
 {
   readonly attribute nsIDOMNode       startContainer;
                                         // raises(DOMException) on retrieval
 
   readonly attribute long             startOffset;
                                         // raises(DOMException) on retrieval
 
@@ -105,9 +105,30 @@ interface nsIDOMRange : nsISupports
                                         raises(DOMException, RangeException);
   void               surroundContents(in nsIDOMNode newParent)
                                         raises(DOMException, RangeException);
   nsIDOMRange        cloneRange()
                                         raises(DOMException);
   DOMString          toString()
                                         raises(DOMException);
   void               detach();
+  
+  // This method comes from
+  // http://html5.org/specs/dom-parsing.html#extensions-to-the-range-interface
+  nsIDOMDocumentFragment    createContextualFragment(in DOMString fragment);
+
+  // This returns true if parent+offset equals either
+  // of the boundary points or is between them.
+  boolean                   isPointInRange(in nsIDOMNode parent,
+                                           in long offset);
+
+  // comparePoint returns
+  //   -1 if point is before the start boundary point,
+  //    0 if point is either of the boundary points or between them,
+  //    1 if point is after the end boundary point.
+  // Sort of a strcmp for ranges.
+  short                     comparePoint(in nsIDOMNode parent, in long offset);
+
+  // These methods come from 
+  // http://dev.w3.org/csswg/cssom-view/#extensions-to-the-range-interface
+  nsIDOMClientRectList getClientRects();
+  nsIDOMClientRect getBoundingClientRect();
 };
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -87,16 +87,17 @@
 
 #include "nsIObserverService.h"
 #include <prinrval.h>
 
 #ifdef MOZ_WIDGET_COCOA
 #include <Carbon/Carbon.h>
 #include <ApplicationServices/ApplicationServices.h>
 #include <OpenGL/OpenGL.h>
+#include "nsCocoaFeatures.h"
 #endif
 
 // needed for nppdf plugin
 #ifdef MOZ_WIDGET_GTK2
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 #include "gtk2xtbin.h"
 #endif
@@ -2252,23 +2253,23 @@ NPError NP_CALLBACK
 
   case NPNVsupportsCoreGraphicsBool: {
     *(NPBool*)result = true;
     
     return NPERR_NO_ERROR;
   }
 
    case NPNVsupportsCoreAnimationBool: {
-     *(NPBool*)result = true;
+     *(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
 
      return NPERR_NO_ERROR;
    }
 
    case NPNVsupportsInvalidatingCoreAnimationBool: {
-     *(NPBool*)result = true;
+     *(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
 
      return NPERR_NO_ERROR;
    }
 
 
 #ifndef NP_NO_CARBON
   case NPNVsupportsCarbonBool: {
     *(NPBool*)result = true;
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -91,18 +91,16 @@ using mozilla::DefaultXDisplay;
 #include "nsIDOMHTMLAppletElement.h"
 #include "nsAttrName.h"
 #include "nsIFocusManager.h"
 #include "nsFocusManager.h"
 #include "nsIDOMDragEvent.h"
 #include "nsIScrollableFrame.h"
 
 #include "nsContentCID.h"
-static NS_DEFINE_CID(kRangeCID, NS_RANGE_CID);
-
 #include "nsWidgetsCID.h"
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #ifdef XP_WIN
 #include <wtypes.h>
 #include <winuser.h>
 #endif
 
@@ -828,20 +826,17 @@ NS_IMETHODIMP nsPluginInstanceOwner::Get
 
     nsCOMPtr<nsIDocumentEncoder> docEncoder(do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "text/html", &rv));
     if (NS_FAILED(rv))
       return rv;
     rv = docEncoder->Init(domDoc, NS_LITERAL_STRING("text/html"), nsIDocumentEncoder::OutputEncodeBasicEntities);
     if (NS_FAILED(rv))
       return rv;
 
-    nsCOMPtr<nsIDOMRange> range(do_CreateInstance(kRangeCID,&rv));
-    if (NS_FAILED(rv))
-      return rv;
-
+    nsRefPtr<nsRange> range = new nsRange();
     rv = range->SelectNode(node);
     if (NS_FAILED(rv))
       return rv;
 
     docEncoder->SetRange(range);
     nsString elementHTML;
     rv = docEncoder->EncodeToString(elementHTML);
     if (NS_FAILED(rv))
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -113,16 +113,17 @@ using mozilla::gfx::SharedDIB;
 // from Chromium's web plugin delegate src. See 'flash msg throttling
 // helpers' section for details.
 const int kFlashWMUSERMessageThrottleDelayMs = 5;
 
 static const TCHAR kPluginIgnoreSubclassProperty[] = TEXT("PluginIgnoreSubclassProperty");
 
 #elif defined(XP_MACOSX)
 #include <ApplicationServices/ApplicationServices.h>
+#include "nsCocoaFeatures.h"
 #include "PluginUtilsOSX.h"
 #endif // defined(XP_MACOSX)
 
 template<>
 struct RunnableMethodTraits<PluginInstanceChild>
 {
     static void RetainCallee(PluginInstanceChild* obj) { }
     static void ReleaseCallee(PluginInstanceChild* obj) { }
@@ -415,22 +416,22 @@ PluginInstanceChild::NPN_GetValue(NPNVar
 
 #ifdef XP_MACOSX
    case NPNVsupportsCoreGraphicsBool: {
         *((NPBool*)aValue) = true;
         return NPERR_NO_ERROR;
     }
 
     case NPNVsupportsCoreAnimationBool: {
-        *((NPBool*)aValue) = true;
+        *((NPBool*)aValue) = nsCocoaFeatures::SupportCoreAnimationPlugins();
         return NPERR_NO_ERROR;
     }
 
     case NPNVsupportsInvalidatingCoreAnimationBool: {
-        *((NPBool*)aValue) = true;
+        *((NPBool*)aValue) = nsCocoaFeatures::SupportCoreAnimationPlugins();
         return NPERR_NO_ERROR;
     }
 
     case NPNVsupportsCocoaBool: {
         *((NPBool*)aValue) = true;
         return NPERR_NO_ERROR;
     }
 
--- a/dom/src/storage/nsDOMStoragePersistentDB.cpp
+++ b/dom/src/storage/nsDOMStoragePersistentDB.cpp
@@ -193,22 +193,22 @@ nsDOMStoragePersistentDB::Init(const nsS
   NS_ENSURE_SUCCESS(rv, rv);
   rv = storageFile->Append(aDatabaseName);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<mozIStorageService> service;
 
   service = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = service->OpenDatabase(storageFile, getter_AddRefs(mConnection));
+  rv = service->OpenUnsharedDatabase(storageFile, getter_AddRefs(mConnection));
   if (rv == NS_ERROR_FILE_CORRUPTED) {
     // delete the db and try opening again
     rv = storageFile->Remove(false);
     NS_ENSURE_SUCCESS(rv, rv);
-    rv = service->OpenDatabase(storageFile, getter_AddRefs(mConnection));
+    rv = service->OpenUnsharedDatabase(storageFile, getter_AddRefs(mConnection));
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA temp_store = MEMORY"));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mozStorageTransaction transaction(mConnection, false);
--- a/dom/tests/mochitest/general/Makefile.in
+++ b/dom/tests/mochitest/general/Makefile.in
@@ -69,16 +69,17 @@ include $(topsrcdir)/config/rules.mk
 		test_nodesFromRect.html \
 		test_frameElementWrapping.html \
 		file_frameElementWrapping.html \
 		test_framedhistoryframes.html \
 		test_windowedhistoryframes.html \
 		test_focusrings.xul \
 		file_moving_xhr.html \
 		test_vibrator.html \
+		test_getContentState.html \
 		$(NULL)
 
 _CHROME_FILES = \
 		test_innerScreen.xul \
 		test_offsets.xul \
 		test_offsets.js \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/test_getContentState.html
@@ -0,0 +1,144 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=708963
+-->
+<head>
+  <title>Test for Bug 708963</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=708963">Mozilla Bug 708963</a>
+
+<script type="application/javascript;version=1.7">
+"use strict";
+
+function getEnabledPref() {
+  try {
+    return SpecialPowers.getBoolPref('dom.mozBrowserFramesEnabled');
+  }
+  catch(e) {
+    return undefined;
+  }
+}
+
+function getWhitelistPref() {
+  try {
+    return SpecialPowers.getCharPref('dom.mozBrowserFramesWhitelist');
+  }
+  catch(e) {
+    return undefined;
+  }
+}
+
+function setPrefs(enabled, whitelist) {
+  if (enabled !== undefined) {
+    SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', enabled);
+  }
+  else {
+    SpecialPowers.clearUserPref('dom.mozBrowserFramesEnabled');
+  }
+
+  if (whitelist !== undefined) {
+    SpecialPowers.setCharPref('dom.mozBrowserFramesWhitelist', whitelist);
+  }
+  else {
+    SpecialPowers.clearUserPref('dom.mozBrowserFramesWhitelist');
+  }
+}
+
+function getPrePath() {
+  return 'http://' + window.location.host;
+}
+
+function checkCannotQueryIframe(id) {
+  let iframe = document.getElementById(id);
+  try {
+    iframe.mozGetContentState('location', function() {
+      ok(false, 'Got callback, but should have failed.');
+    });
+    ok(false, 'Should have thrown exception.');
+  }
+  catch(e) {
+    ok(true, 'Got expected exception.');
+  }
+}
+
+function checkCannotQuery() {
+  checkCannotQueryIframe('queryable');
+  checkCannotQueryIframe('not-queryable');
+}
+
+let numCallbacksExpected = 0;
+let numCallbacksSeen = 0;
+function checkCanQuery() {
+  checkCannotQueryIframe('not-queryable');
+
+  let iframe = document.getElementById('queryable');
+  iframe.mozGetContentState('location', function(href) {
+    ok(true, 'Got callback, as expected.');
+    is(href, 'http://example.com/', "Callback value.");
+    numCallbacksSeen++;
+  });
+  numCallbacksExpected++;
+}
+
+const oldEnabled = getEnabledPref();
+const oldWhitelist = getWhitelistPref();
+
+function runTest() {
+  setPrefs(false, getPrePath());
+  checkCannotQuery();
+
+  setPrefs(true, '');
+  checkCannotQuery();
+
+  setPrefs(true, getPrePath());
+  checkCanQuery();
+
+  setPrefs(true, 'http://example.com  , ' +
+                 getPrePath().toUpperCase() + ',  ');
+  checkCanQuery();
+
+  // Spin if we haven't seen all the expected callbacks.
+  waitForAllExpectedCallbacks();
+}
+
+function waitForAllExpectedCallbacks() {
+  if (numCallbacksSeen < numCallbacksExpected) {
+    SimpleTest.executeSoon(waitForAllExpectedCallbacks);
+    return;
+  }
+
+  // Spin the event loop a few times to let any remaining pending callbacks
+  // fire.  (If we get any callbacks here, the test should fail.)
+  SimpleTest.executeSoon(function() {
+    SimpleTest.executeSoon(function() {
+      SimpleTest.executeSoon(function() {
+        setPrefs(oldEnabled, oldWhitelist);
+        SimpleTest.finish();
+      });
+    });
+  });
+}
+
+SimpleTest.waitForExplicitFinish();
+
+var numLoaded = 0;
+function iframeLoaded() {
+  numLoaded++;
+  if (numLoaded == 2) {
+    runTest();
+  }
+}
+
+</script>
+
+<iframe onload='iframeLoaded()' id='not-queryable' src='http://example.net'></iframe>
+<iframe onload='iframeLoaded()' mozbrowser id='queryable' src='http://example.com'></iframe>
+
+</body>
+</html>
+
+
--- a/editor/libeditor/base/IMETextTxn.cpp
+++ b/editor/libeditor/base/IMETextTxn.cpp
@@ -33,17 +33,17 @@
  * 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 "IMETextTxn.h"
 #include "nsIDOMCharacterData.h"
-#include "nsIDOMRange.h"
+#include "nsRange.h"
 #include "nsIPrivateTextRange.h"
 #include "nsISelection.h"
 #include "nsISelectionPrivate.h"
 #include "nsISelectionController.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIEditor.h"
 
 // #define DEBUG_IMETXN
@@ -333,22 +333,17 @@ NS_IMETHODIMP IMETextTxn::CollapseTextSe
                 continue;
 
              result= selCon->GetSelection(TextRangeToSelection(textRangeType),
                      getter_AddRefs(imeSel));
              NS_ASSERTION(NS_SUCCEEDED(result), "Cannot get selction");
              if(NS_FAILED(result))
                 break;
 
-             nsCOMPtr<nsIDOMRange> newRange = do_CreateInstance(
-                                      "@mozilla.org/content/range;1", &result);
-             NS_ASSERTION(NS_SUCCEEDED(result), "Cannot create new nsIDOMRange");
-             if(NS_FAILED(result))
-                break;
-
+             nsRefPtr<nsRange> newRange = new nsRange();
              result = newRange->SetStart(mElement,mOffset+selectionStart);
              NS_ASSERTION(NS_SUCCEEDED(result), "Cannot SetStart");
              if(NS_FAILED(result))
                 break;
 
              result = newRange->SetEnd(mElement,mOffset+selectionEnd);
              NS_ASSERTION(NS_SUCCEEDED(result), "Cannot SetEnd");
              if(NS_FAILED(result))
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -4975,23 +4975,19 @@ nsEditor::CreateTxnForDeleteInsertionPoi
   return result;
 }
 
 nsresult 
 nsEditor::CreateRange(nsIDOMNode *aStartParent, PRInt32 aStartOffset,
                       nsIDOMNode *aEndParent, PRInt32 aEndOffset,
                       nsIDOMRange **aRange)
 {
-  nsresult result;
-  result = CallCreateInstance("@mozilla.org/content/range;1", aRange);
-  NS_ENSURE_SUCCESS(result, result);
-
-  NS_ENSURE_TRUE(*aRange, NS_ERROR_NULL_POINTER);
-
-  result = (*aRange)->SetStart(aStartParent, aStartOffset);
+  NS_ADDREF(*aRange = new nsRange());
+
+  nsresult result = (*aRange)->SetStart(aStartParent, aStartOffset);
 
   if (NS_SUCCEEDED(result))
     result = (*aRange)->SetEnd(aEndParent, aEndOffset);
 
   if (NS_FAILED(result))
   {
     NS_RELEASE((*aRange));
     *aRange = 0;
--- a/editor/libeditor/base/nsEditorEventListener.cpp
+++ b/editor/libeditor/base/nsEditorEventListener.cpp
@@ -60,17 +60,17 @@
 
 // Drag & Drop, Clipboard
 #include "nsIServiceManager.h"
 #include "nsIClipboard.h"
 #include "nsIDragService.h"
 #include "nsIDragSession.h"
 #include "nsIContent.h"
 #include "nsISupportsPrimitives.h"
-#include "nsIDOMNSRange.h"
+#include "nsIDOMRange.h"
 #include "nsEditorUtils.h"
 #include "nsISelectionPrivate.h"
 #include "nsIDOMDragEvent.h"
 #include "nsIFocusManager.h"
 #include "nsIDOMWindow.h"
 #include "nsContentUtils.h"
 #include "nsIBidiKeyboard.h"
 
@@ -881,22 +881,21 @@ nsEditorEventListener::CanDrop(nsIDOMDra
       PRInt32 rangeCount;
       rv = selection->GetRangeCount(&rangeCount);
       NS_ENSURE_SUCCESS(rv, false);
 
       for (PRInt32 i = 0; i < rangeCount; i++)
       {
         nsCOMPtr<nsIDOMRange> range;
         rv = selection->GetRangeAt(i, getter_AddRefs(range));
-        nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
-        if (NS_FAILED(rv) || !nsrange) 
+        if (NS_FAILED(rv) || !range) 
           continue; //don't bail yet, iterate through them all
 
         bool inRange = true;
-        (void)nsrange->IsPointInRange(parent, offset, &inRange);
+        (void)range->IsPointInRange(parent, offset, &inRange);
         if (inRange)
           return false;  //okay, now you can bail, we are over the orginal selection
       }
     }
   }
   
   return true;
 }
--- a/editor/libeditor/base/nsSelectionState.cpp
+++ b/editor/libeditor/base/nsSelectionState.cpp
@@ -33,17 +33,17 @@
  * 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 "nsSelectionState.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMNode.h"
-#include "nsIDOMRange.h"
+#include "nsRange.h"
 #include "nsISelection.h"
 #include "nsEditor.h"
 #include "nsEditorUtils.h"
 
 
 /***************************************************************************
  * class for recording selection info.  stores selection as collection of
  * { {startnode, startoffset} , {endnode, endoffset} } tuples.  Can't store
@@ -117,52 +117,52 @@ nsSelectionState::RestoreSelection(nsISe
   PRUint32 i, arrayCount = mArray.Length();
 
   // clear out selection
   aSel->RemoveAllRanges();
   
   // set the selection ranges anew
   for (i=0; i<arrayCount; i++)
   {
-    nsCOMPtr<nsIDOMRange> range;
-    mArray[i].GetRange(address_of(range));
+    nsRefPtr<nsRange> range;
+    mArray[i].GetRange(getter_AddRefs(range));
     NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED);
    
     res = aSel->AddRange(range);
     if(NS_FAILED(res)) return res;
 
   }
   return NS_OK;
 }
 
 bool
 nsSelectionState::IsCollapsed()
 {
   if (1 != mArray.Length()) return false;
-  nsCOMPtr<nsIDOMRange> range;
-  mArray[0].GetRange(address_of(range));
+  nsRefPtr<nsRange> range;
+  mArray[0].GetRange(getter_AddRefs(range));
   NS_ENSURE_TRUE(range, false);
   bool bIsCollapsed = false;
   range->GetCollapsed(&bIsCollapsed);
   return bIsCollapsed;
 }
 
 bool
 nsSelectionState::IsEqual(nsSelectionState *aSelState)
 {
   NS_ENSURE_TRUE(aSelState, false);
   PRUint32 i, myCount = mArray.Length(), itsCount = aSelState->mArray.Length();
   if (myCount != itsCount) return false;
   if (myCount < 1) return false;
 
   for (i=0; i<myCount; i++)
   {
-    nsCOMPtr<nsIDOMRange> myRange, itsRange;
-    mArray[i].GetRange(address_of(myRange));
-    aSelState->mArray[i].GetRange(address_of(itsRange));
+    nsRefPtr<nsRange> myRange, itsRange;
+    mArray[i].GetRange(getter_AddRefs(myRange));
+    aSelState->mArray[i].GetRange(getter_AddRefs(itsRange));
     NS_ENSURE_TRUE(myRange && itsRange, false);
   
     PRInt16 compResult;
     nsresult rv;
     rv = myRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START, itsRange, &compResult);
     if (NS_FAILED(rv) || compResult) return false;
     rv = myRange->CompareBoundaryPoints(nsIDOMRange::END_TO_END, itsRange, &compResult);
     if (NS_FAILED(rv) || compResult) return false;
@@ -695,21 +695,20 @@ nsresult nsRangeStore::StoreRange(nsIDOM
   NS_ENSURE_TRUE(aRange, NS_ERROR_NULL_POINTER);
   aRange->GetStartContainer(getter_AddRefs(startNode));
   aRange->GetEndContainer(getter_AddRefs(endNode));
   aRange->GetStartOffset(&startOffset);
   aRange->GetEndOffset(&endOffset);
   return NS_OK;
 }
 
-nsresult nsRangeStore::GetRange(nsCOMPtr<nsIDOMRange> *outRange)
+nsresult nsRangeStore::GetRange(nsRange** outRange)
 {
   NS_ENSURE_TRUE(outRange, NS_ERROR_NULL_POINTER);
-  nsresult res;
-  *outRange = do_CreateInstance("@mozilla.org/content/range;1", &res);
-  if(NS_FAILED(res)) return res;
+  *outRange = new nsRange();
+  NS_ADDREF((*outRange));
 
-  res = (*outRange)->SetStart(startNode, startOffset);
+  nsresult res = (*outRange)->SetStart(startNode, startOffset);
   if(NS_FAILED(res)) return res;
 
   res = (*outRange)->SetEnd(endNode, endOffset);
   return res;
 }
--- a/editor/libeditor/base/nsSelectionState.h
+++ b/editor/libeditor/base/nsSelectionState.h
@@ -41,30 +41,31 @@
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMRange.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsIDOMCharacterData;
 class nsISelection;
+class nsRange;
 
 /***************************************************************************
  * class for recording selection info.  stores selection as collection of
  * { {startnode, startoffset} , {endnode, endoffset} } tuples.  Can't store
  * ranges since dom gravity will possibly change the ranges.
  */
 
 // first a helper struct for saving/setting ranges
 struct nsRangeStore 
 {
   nsRangeStore();
   ~nsRangeStore();
   nsresult StoreRange(nsIDOMRange *aRange);
-  nsresult GetRange(nsCOMPtr<nsIDOMRange> *outRange);
+  nsresult GetRange(nsRange** outRange);
         
   nsCOMPtr<nsIDOMNode> startNode;
   PRInt32              startOffset;
   nsCOMPtr<nsIDOMNode> endNode;
   PRInt32              endOffset;
   // DEBUG:   static PRInt32 n;
 };
 
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/crashtests/716456-1.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+<script>
+
+function boom()
+{
+  var div = document.querySelector("div");
+  div.contentEditable = "true";
+  div.focus();
+
+  var r = document.documentElement;
+  document["removeChild"](r);
+  document["appendChild"](r);
+
+  setTimeout(function() {
+    document.execCommand("inserthtml", false, "a");
+    setTimeout(function() {
+      document.documentElement.removeAttribute("class");
+    }, 0);
+  }, 0);
+}
+
+</script>
+</head>
+
+<body onload="boom();"><div></div></body>
+</html>
--- a/editor/libeditor/html/crashtests/crashtests.list
+++ b/editor/libeditor/html/crashtests/crashtests.list
@@ -19,8 +19,9 @@ load 513375-1.xhtml
 load 535632-1.xhtml
 load 574558-1.xhtml
 load 582138-1.xhtml
 load 612565-1.html
 asserts(0-6) load 615015-1.html # Bug 439258
 load 615450-1.html
 load 643786-1.html
 load 682650-1.html
+load 716456-1.html
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -59,17 +59,16 @@
 
 #include "nsIDocumentObserver.h"
 #include "nsIDocumentStateListener.h"
 
 #include "nsIEnumerator.h"
 #include "nsIContent.h"
 #include "nsIContentIterator.h"
 #include "nsIDOMRange.h"
-#include "nsIDOMNSRange.h"
 #include "nsCOMArray.h"
 #include "nsIFile.h"
 #include "nsIURL.h"
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIPresShell.h"
@@ -207,23 +206,21 @@ NS_IMETHODIMP nsHTMLEditor::LoadHTML(con
       NS_ENSURE_SUCCESS(res, res);
     }
 
     // Get the first range in the selection, for context:
     nsCOMPtr<nsIDOMRange> range;
     res = selection->GetRangeAt(0, getter_AddRefs(range));
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
-    nsCOMPtr<nsIDOMNSRange> nsrange (do_QueryInterface(range));
-    NS_ENSURE_TRUE(nsrange, NS_ERROR_NO_INTERFACE);
 
     // create fragment for pasted html
     nsCOMPtr<nsIDOMDocumentFragment> docfrag;
     {
-      res = nsrange->CreateContextualFragment(aInputString, getter_AddRefs(docfrag));
+      res = range->CreateContextualFragment(aInputString, getter_AddRefs(docfrag));
       NS_ENSURE_SUCCESS(res, res);
     }
     // put the fragment into the document
     nsCOMPtr<nsIDOMNode> parent, junk;
     res = range->GetStartContainer(getter_AddRefs(parent));
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
     PRInt32 childOffset;
@@ -1559,21 +1556,17 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDr
         for (PRInt32 j = 0; j < rangeCount; j++)
         {
           nsCOMPtr<nsIDOMRange> range;
 
           rv = selection->GetRangeAt(j, getter_AddRefs(range));
           if (NS_FAILED(rv) || !range) 
             continue;//don't bail yet, iterate through them all
 
-          nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
-          if (NS_FAILED(rv) || !nsrange) 
-            continue;//don't bail yet, iterate through them all
-
-          rv = nsrange->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);
+          rv = range->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);
           if(cursorIsInSelection)
             break;
         }
         if (cursorIsInSelection)
         {
           // Dragging within same doc can't drop on itself -- leave!
           // (We shouldn't get here - drag event shouldn't have started if over selection)
           if (srcdomdoc == destdomdoc)
@@ -2658,20 +2651,17 @@ nsresult nsHTMLEditor::CreateListOfNodes
     NS_ENSURE_SUCCESS(res, res);
 
     aStartNode = aFragmentAsNode;
     aStartOffset = 0;
     aEndNode = aFragmentAsNode;
     aEndOffset = fragLen;
   }
 
-  nsCOMPtr<nsIDOMRange> docFragRange =
-                          do_CreateInstance("@mozilla.org/content/range;1");
-  NS_ENSURE_TRUE(docFragRange, NS_ERROR_OUT_OF_MEMORY);
-
+  nsRefPtr<nsRange> docFragRange = new nsRange();
   res = docFragRange->SetStart(aStartNode, aStartOffset);
   NS_ENSURE_SUCCESS(res, res);
   res = docFragRange->SetEnd(aEndNode, aEndOffset);
   NS_ENSURE_SUCCESS(res, res);
 
   // now use a subtree iterator over the range to create a list of nodes
   nsTrivialFunctor functor;
   nsDOMSubtreeIterator iter;
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -55,22 +55,21 @@
 #include "nsIDOMNode.h"
 #include "nsIDOMText.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMNodeList.h"
 #include "nsISelection.h"
 #include "nsISelectionPrivate.h"
 #include "nsISelectionController.h"
 #include "nsIDOMRange.h"
-#include "nsIDOMNSRange.h"
 #include "nsIRangeUtils.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIEnumerator.h"
 #include "nsIDOMNamedNodeMap.h"
-#include "nsIRange.h"
+#include "nsRange.h"
 
 #include "nsEditorUtils.h"
 #include "nsWSRunObject.h"
 
 #include "InsertTextTxn.h"
 #include "DeleteTextTxn.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
@@ -248,29 +247,27 @@ nsHTMLEditRules::Init(nsPlaintextEditor 
   nsAdoptingCString returnInEmptyLIKillsList =
     Preferences::GetCString(kPrefName);
 
   // only when "false", becomes FALSE.  Otherwise (including empty), TRUE.
   // XXX Why was this pref designed as a string and not bool?
   mReturnInEmptyLIKillsList = !returnInEmptyLIKillsList.EqualsLiteral("false");
 
   // make a utility range for use by the listenter
-  mUtilRange = do_CreateInstance("@mozilla.org/content/range;1");
-  NS_ENSURE_TRUE(mUtilRange, NS_ERROR_NULL_POINTER);
+  mUtilRange = new nsRange();
    
   // set up mDocChangeRange to be whole doc
   nsCOMPtr<nsIDOMElement> rootElem = do_QueryInterface(mHTMLEditor->GetRoot());
   if (rootElem)
   {
     // temporarily turn off rules sniffing
     nsAutoLockRulesSniffing lockIt((nsTextEditRules*)this);
     if (!mDocChangeRange)
     {
-      mDocChangeRange = do_CreateInstance("@mozilla.org/content/range;1");
-      NS_ENSURE_TRUE(mDocChangeRange, NS_ERROR_NULL_POINTER);
+      mDocChangeRange = new nsRange();
     }
     mDocChangeRange->SelectNode(rootElem);
     res = AdjustSpecialBreaks();
     NS_ENSURE_SUCCESS(res, res);
   }
 
   // add ourselves as a listener to edit actions
   res = mHTMLEditor->AddEditActionListener(this);
@@ -296,17 +293,17 @@ nsHTMLEditRules::BeforeEdit(PRInt32 acti
   if (!mActionNesting++)
   {
     // clear our flag about if just deleted a range
     mDidRangedDelete = false;
     
     // remember where our selection was before edit action took place:
     
     // get selection
-    nsCOMPtr<nsISelection>selection;
+    nsCOMPtr<nsISelection> selection;
     nsresult res = mHTMLEditor->GetSelection(getter_AddRefs(selection));
     NS_ENSURE_SUCCESS(res, res);
   
     // get the selection start location
     nsCOMPtr<nsIDOMNode> selStartNode, selEndNode;
     PRInt32 selOffset;
     res = mHTMLEditor->GetStartNodeAndOffset(selection, getter_AddRefs(selStartNode), &selOffset);
     NS_ENSURE_SUCCESS(res, res);
@@ -324,24 +321,22 @@ nsHTMLEditRules::BeforeEdit(PRInt32 acti
 
     // clear deletion state bool
     mDidDeleteSelection = false;
     
     // clear out mDocChangeRange and mUtilRange
     if(mDocChangeRange)
     {
       // clear out our accounting of what changed
-      nsCOMPtr<nsIRange> range = do_QueryInterface(mDocChangeRange);
-      range->Reset(); 
+      mDocChangeRange->Reset(); 
     }
     if(mUtilRange)
     {
       // ditto for mUtilRange.
-      nsCOMPtr<nsIRange> range = do_QueryInterface(mUtilRange);
-      range->Reset(); 
+      mUtilRange->Reset(); 
     }
 
     // remember current inline styles for deletion and normal insertion operations
     if ((action == nsEditor::kOpInsertText)      || 
         (action == nsEditor::kOpInsertIMEText)   ||
         (action == nsEditor::kOpDeleteSelection) ||
         (action == nsEditor::kOpInsertBreak))
     {
@@ -590,17 +585,17 @@ nsHTMLEditRules::WillDoAction(nsISelecti
   {
     if (!mHTMLEditor->IsModifiableNode(selEndNode))
     {
       *aCancel = true;
 
       return NS_OK;
     }
 
-    nsCOMPtr<nsIRange> range = do_QueryInterface(domRange);
+    nsRange* range = static_cast<nsRange*>(domRange.get());
     nsCOMPtr<nsIDOMNode> ancestor =
       do_QueryInterface(range->GetCommonAncestor());
     if (!mHTMLEditor->IsModifiableNode(ancestor))
     {
       *aCancel = true;
 
       return NS_OK;
     }
@@ -1484,18 +1479,17 @@ nsHTMLEditRules::WillInsertText(PRInt32 
     nsCOMPtr<nsISelection> selection(aSelection);
     nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
     selPriv->SetInterlinePosition(false);
     if (curNode) aSelection->Collapse(curNode, curOffset);
     // manually update the doc changed range so that AfterEdit will clean up
     // the correct portion of the document.
     if (!mDocChangeRange)
     {
-      mDocChangeRange = do_CreateInstance("@mozilla.org/content/range;1");
-      NS_ENSURE_TRUE(mDocChangeRange, NS_ERROR_NULL_POINTER);
+      mDocChangeRange = new nsRange();
     }
     res = mDocChangeRange->SetStart(selNode, selOffset);
     NS_ENSURE_SUCCESS(res, res);
     if (curNode)
       res = mDocChangeRange->SetEnd(curNode, curOffset);
     else
       res = mDocChangeRange->SetEnd(selNode, selOffset);
     NS_ENSURE_SUCCESS(res, res);
@@ -5251,18 +5245,17 @@ nsHTMLEditRules::ExpandSelectionForDelet
   {
     // find block node containing br
     nsCOMPtr<nsIDOMNode> brBlock = firstBRParent;
     if (!IsBlockNode(brBlock))
       brBlock = nsHTMLEditor::GetBlockNodeParent(brBlock);
     bool nodeBefore=false, nodeAfter=false;
     
     // create a range that represents expanded selection
-    nsCOMPtr<nsIDOMRange> range = do_CreateInstance("@mozilla.org/content/range;1");
-    NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
+    nsRefPtr<nsRange> range = new nsRange();
     res = range->SetStart(selStartNode, selStartOffset);
     NS_ENSURE_SUCCESS(res, res);
     res = range->SetEnd(selEndNode, selEndOffset);
     NS_ENSURE_SUCCESS(res, res);
     
     // check if block is entirely inside range
     nsCOMPtr<nsIContent> brContentBlock = do_QueryInterface(brBlock);
     res = mHTMLEditor->sRangeHelper->CompareNodeToRange(brContentBlock, range, &nodeBefore, &nodeAfter);
@@ -5892,17 +5885,19 @@ nsHTMLEditRules::GetNodesForOperation(ns
     {
       res = BustUpInlinesAtRangeEndpoints(rangeItemArray[i]);
     } 
     // then unregister the ranges
     for (i = 0; i < rangeCount; i++)
     {
       nsRangeStore *item = rangeItemArray.Elements() + i;
       mHTMLEditor->mRangeUpdater.DropRangeItem(item);
-      nsresult res2 = item->GetRange(address_of(opRange));
+      nsRefPtr<nsRange> range;
+      nsresult res2 = item->GetRange(getter_AddRefs(range));
+      opRange = range;
       if (NS_FAILED(res2) && NS_SUCCEEDED(res)) {
         // Remember the failure, but keep going so we make sure to unregister
         // all our range items.
         res = res2;
       }
       inArrayOfRanges.AppendObject(opRange);
     }
     NS_ENSURE_SUCCESS(res, res);
@@ -6410,17 +6405,17 @@ nsHTMLEditRules::GetNodesFromPoint(DOMPo
   nsresult res;
 
   // get our point
   nsCOMPtr<nsIDOMNode> node;
   PRInt32 offset;
   point.GetPoint(node, offset);
   
   // use it to make a range
-  nsCOMPtr<nsIDOMRange> range = do_CreateInstance("@mozilla.org/content/range;1");
+  nsRefPtr<nsRange> range = new nsRange();
   res = range->SetStart(node, offset);
   NS_ENSURE_SUCCESS(res, res);
   /* SetStart() will also set the end for this new range
   res = range->SetEnd(node, offset);
   NS_ENSURE_SUCCESS(res, res); */
   
   // expand the range to include adjacent inlines
   res = PromoteRange(range, operation);
@@ -7630,17 +7625,17 @@ nsHTMLEditRules::PinSelectionToNewBlock(
   // get the (collapsed) selection location
   nsCOMPtr<nsIDOMNode> selNode, temp;
   PRInt32 selOffset;
   res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(selNode), &selOffset);
   NS_ENSURE_SUCCESS(res, res);
   temp = selNode;
   
   // use ranges and sRangeHelper to compare sel point to new block
-  nsCOMPtr<nsIDOMRange> range = do_CreateInstance("@mozilla.org/content/range;1");
+  nsRefPtr<nsRange> range = new nsRange();
   res = range->SetStart(selNode, selOffset);
   NS_ENSURE_SUCCESS(res, res);
   res = range->SetEnd(selNode, selOffset);
   NS_ENSURE_SUCCESS(res, res);
   nsCOMPtr<nsIContent> block (do_QueryInterface(mNewBlock));
   NS_ENSURE_TRUE(block, NS_ERROR_NO_INTERFACE);
   bool nodeBefore, nodeAfter;
   res = mHTMLEditor->sRangeHelper->CompareNodeToRange(block, range, &nodeBefore, &nodeAfter);
@@ -8425,19 +8420,20 @@ nsHTMLEditRules::UpdateDocChangeRange(ns
   if (!mHTMLEditor->IsDescendantOfBody(startNode))
   {
     // just return - we don't need to adjust mDocChangeRange in this case
     return NS_OK;
   }
   
   if (!mDocChangeRange)
   {
-    // clone aRange.  
-    res = aRange->CloneRange(getter_AddRefs(mDocChangeRange));
-    return res;
+    // clone aRange.
+    nsCOMPtr<nsIDOMRange> range;
+    res = aRange->CloneRange(getter_AddRefs(range));
+    mDocChangeRange = static_cast<nsRange*>(range.get());
   }
   else
   {
     PRInt16 result;
     
     // compare starts of ranges
     res = mDocChangeRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START, aRange, &result);
     if (res == NS_ERROR_NOT_INITIALIZED) {
--- a/editor/libeditor/html/nsHTMLEditRules.h
+++ b/editor/libeditor/html/nsHTMLEditRules.h
@@ -45,16 +45,17 @@
 #include "nsIEditActionListener.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsEditorUtils.h"
 #include "TypeInState.h"
 #include "nsReadableUtils.h"
 #include "nsTArray.h"
+#include "nsRange.h"
 
 class nsIDOMElement;
 class nsIEditor;
 class nsHTMLEditor;
 
 struct StyleCache : public PropItem
 {
   bool mPresent;
@@ -298,23 +299,23 @@ protected:
   nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode, bool aStarts);
   nsresult AlignBlock(nsIDOMElement * aElement, const nsAString * aAlignType, bool aContentsOnly);
   nsresult RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, PRInt8 aRelativeChange);
   void DocumentModifiedWorker();
 
 // data members
 protected:
   nsHTMLEditor           *mHTMLEditor;
-  nsCOMPtr<nsIDOMRange>   mDocChangeRange;
+  nsRefPtr<nsRange>       mDocChangeRange;
   bool                    mListenerEnabled;
   bool                    mReturnInEmptyLIKillsList;
   bool                    mDidDeleteSelection;
   bool                    mDidRangedDelete;
   bool                    mRestoreContentEditableCount;
-  nsCOMPtr<nsIDOMRange>   mUtilRange;
+  nsRefPtr<nsRange>       mUtilRange;
   PRUint32                mJoinOffset;  // need to remember an int across willJoin/didJoin...
   nsCOMPtr<nsIDOMNode>    mNewBlock;
   nsRangeStore            mRangeItem;
   StyleCache              mCachedStyles[SIZE_STYLE_TABLE];
 };
 
 #endif //nsHTMLEditRules_h__
 
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -67,17 +67,16 @@
 #include "mozilla/css/Loader.h"
 #include "nsCSSStyleSheet.h"
 #include "nsIDOMStyleSheet.h"
 
 #include "nsIEnumerator.h"
 #include "nsIContent.h"
 #include "nsIContentIterator.h"
 #include "nsIDOMRange.h"
-#include "nsIDOMNSRange.h"
 #include "nsIRangeUtils.h"
 #include "nsISupportsArray.h"
 #include "nsContentUtils.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "SetDocTitleTxn.h"
@@ -1598,21 +1597,19 @@ nsHTMLEditor::ReplaceHeadContentsWithHTM
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
   // Get the first range in the selection, for context:
   nsCOMPtr<nsIDOMRange> range;
   res = selection->GetRangeAt(0, getter_AddRefs(range));
   NS_ENSURE_SUCCESS(res, res);
 
-  nsCOMPtr<nsIDOMNSRange> nsrange (do_QueryInterface(range));
-  NS_ENSURE_TRUE(nsrange, NS_ERROR_NO_INTERFACE);
   nsCOMPtr<nsIDOMDocumentFragment> docfrag;
-  res = nsrange->CreateContextualFragment(inputString,
-                                          getter_AddRefs(docfrag));
+  res = range->CreateContextualFragment(inputString,
+                                        getter_AddRefs(docfrag));
 
   //XXXX BUG 50965: This is not returning the text between <title> ... </title>
   // Special code is needed in JS to handle title anyway, so it really doesn't matter!
 
   if (NS_FAILED(res))
   {
 #ifdef DEBUG
     printf("Couldn't create contextual fragment: error was %d\n", res);
@@ -1764,21 +1761,18 @@ nsHTMLEditor::RebuildDocumentFromSource(
   nsAutoString bodyTag;
   bodyTag.AssignLiteral("<div ");
   bodyTag.Append(Substring(endbody, endclosebody));
 
   nsCOMPtr<nsIDOMRange> range;
   res = selection->GetRangeAt(0, getter_AddRefs(range));
   NS_ENSURE_SUCCESS(res, res);
 
-  nsCOMPtr<nsIDOMNSRange> nsrange (do_QueryInterface(range));
-  NS_ENSURE_TRUE(nsrange, NS_ERROR_NO_INTERFACE);
-
   nsCOMPtr<nsIDOMDocumentFragment> docfrag;
-  res = nsrange->CreateContextualFragment(bodyTag, getter_AddRefs(docfrag));
+  res = range->CreateContextualFragment(bodyTag, getter_AddRefs(docfrag));
   NS_ENSURE_SUCCESS(res, res);
 
   nsCOMPtr<nsIDOMNode> fragmentAsNode (do_QueryInterface(docfrag));
   NS_ENSURE_TRUE(fragmentAsNode, NS_ERROR_NULL_POINTER);
   
   nsCOMPtr<nsIDOMNode> child;
   res = fragmentAsNode->GetFirstChild(getter_AddRefs(child));
   NS_ENSURE_SUCCESS(res, res);
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -69,17 +69,16 @@
 #include "nsIDocumentObserver.h"
 
 #include "nsPoint.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 
 class nsIDOMKeyEvent;
 class nsITransferable;
-class nsIDOMNSRange;
 class nsIDocumentEncoder;
 class nsIClipboard;
 class TypeInState;
 class nsIContentFilter;
 class nsIURL;
 class nsIRangeUtils;
 class nsILinkHandler;
 struct PropItem;
--- a/editor/libeditor/html/nsHTMLEditorEventListener.cpp
+++ b/editor/libeditor/html/nsHTMLEditorEventListener.cpp
@@ -42,17 +42,16 @@
 #include "nsString.h"
 
 #include "nsIDOMEvent.h"
 #include "nsIDOMNSEvent.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsISelection.h"
 #include "nsIDOMRange.h"
-#include "nsIDOMNSRange.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMHTMLTableElement.h"
 #include "nsIDOMHTMLTableCellElement.h"
 #include "nsIContent.h"
 
 #include "nsIHTMLObjectResizer.h"
 #include "nsEditProperty.h"
 #include "nsTextEditUtils.h"
@@ -173,21 +172,17 @@ nsHTMLEditorEventListener::MouseDown(nsI
         for (PRInt32 i = 0; i < rangeCount; i++)
         {
           nsCOMPtr<nsIDOMRange> range;
 
           res = selection->GetRangeAt(i, getter_AddRefs(range));
           if (NS_FAILED(res) || !range) 
             continue;//don't bail yet, iterate through them all
 
-          nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
-          if (NS_FAILED(res) || !nsrange) 
-            continue;//don't bail yet, iterate through them all
-
-          res = nsrange->IsPointInRange(parent, offset, &nodeIsInSelection);
+          res = range->IsPointInRange(parent, offset, &nodeIsInSelection);
 
           // Done when we find a range that we are in
           if (nodeIsInSelection)
             break;
         }
       }
     }
     nsCOMPtr<nsIDOMNode> node = do_QueryInterface(target);
--- a/editor/libeditor/html/nsWSRunObject.cpp
+++ b/editor/libeditor/html/nsWSRunObject.cpp
@@ -39,16 +39,17 @@
 #include "nsWSRunObject.h"
 #include "nsIDOMNode.h"
 #include "nsHTMLEditor.h"
 #include "nsTextEditUtils.h"
 #include "nsIContent.h"
 #include "nsIDOMCharacterData.h"
 #include "nsCRT.h"
 #include "nsIRangeUtils.h"
+#include "nsRange.h"
 
 const PRUnichar nbsp = 160;
 
 static bool IsBlockNode(nsIDOMNode* node)
 {
   bool isBlock (false);
   nsHTMLEditor::NodeIsBlockStatic(node, &isBlock);
   return isBlock;
@@ -1545,17 +1546,17 @@ nsWSRunObject::DeleteChars(nsIDOMNode *a
     return NS_OK;  // nothing to delete
   
   nsresult res = NS_OK;
   PRInt32 idx = mNodeArray.IndexOf(aStartNode);
   if (idx==-1) idx = 0; // if our strarting point wasn't one of our ws text nodes,
                         // then just go through them from the beginning.
   nsCOMPtr<nsIDOMNode> node;
   nsCOMPtr<nsIDOMCharacterData> textnode;
-  nsCOMPtr<nsIDOMRange> range;
+  nsRefPtr<nsRange> range;
 
   if (aStartNode == aEndNode)
   {
     textnode = do_QueryInterface(aStartNode);
     if (textnode)
     {
       return mHTMLEditor->DeleteText(textnode, (PRUint32)aStartOffset, 
                                      (PRUint32)(aEndOffset-aStartOffset));
@@ -1588,18 +1589,17 @@ nsWSRunObject::DeleteChars(nsIDOMNode *a
         NS_ENSURE_SUCCESS(res, res);
       }
       break;
     }
     else
     {
       if (!range)
       {
-        range = do_CreateInstance("@mozilla.org/content/range;1");
-        NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
+        range = new nsRange();
         res = range->SetStart(aStartNode, aStartOffset);
         NS_ENSURE_SUCCESS(res, res);
         res = range->SetEnd(aEndNode, aEndOffset);
         NS_ENSURE_SUCCESS(res, res);
       }
       bool nodeBefore, nodeAfter;
       nsCOMPtr<nsIContent> content (do_QueryInterface(node));
       res = mHTMLEditor->sRangeHelper->CompareNodeToRange(content, range, &nodeBefore, &nodeAfter);
--- a/editor/libeditor/text/nsPlaintextDataTransfer.cpp
+++ b/editor/libeditor/text/nsPlaintextDataTransfer.cpp
@@ -47,17 +47,16 @@
 #include "nsIDOMNSEvent.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsIDOMDragEvent.h"
 #include "nsISelection.h"
 #include "nsCRT.h"
 #include "nsServiceManagerUtils.h"
 
 #include "nsIDOMRange.h"
-#include "nsIDOMNSRange.h"
 #include "nsIDocumentEncoder.h"
 #include "nsISupportsPrimitives.h"
 
 // Drag & Drop, Clipboard
 #include "nsIClipboard.h"
 #include "nsITransferable.h"
 #include "nsIDragService.h"
 #include "nsIDOMUIEvent.h"
@@ -228,21 +227,20 @@ NS_IMETHODIMP nsPlaintextEditor::InsertF
     PRInt32 rangeCount;
     rv = selection->GetRangeCount(&rangeCount);
     NS_ENSURE_SUCCESS(rv, rv);
 
     for (PRInt32 j = 0; j < rangeCount; j++)
     {
       nsCOMPtr<nsIDOMRange> range;
       rv = selection->GetRangeAt(j, getter_AddRefs(range));
-      nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
-      if (NS_FAILED(rv) || !nsrange) 
+      if (NS_FAILED(rv) || !range) 
         continue;  // don't bail yet, iterate through them all
 
-      rv = nsrange->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);
+      rv = range->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);
       if (cursorIsInSelection)
         break;
     }
 
     // Source doc is null if source is *not* the current editor document
     // Current doc is destination (set earlier)
     nsCOMPtr<nsIDOMDocument> srcdomdoc;
     rv = dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc));
--- a/editor/libeditor/text/nsTextEditRules.cpp
+++ b/editor/libeditor/text/nsTextEditRules.cpp
@@ -46,17 +46,16 @@
 #include "nsIDOMNode.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMText.h"
 #include "nsIDOMNodeList.h"
 #include "nsISelection.h"
 #include "nsISelectionPrivate.h"
 #include "nsISelectionController.h"
 #include "nsIDOMRange.h"
-#include "nsIDOMNSRange.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIContent.h"
 #include "nsIContentIterator.h"
 #include "nsEditorUtils.h"
 #include "EditTxn.h"
 #include "nsEditProperty.h"
 #include "nsUnicharUtils.h"
 #include "DeleteTextTxn.h"
--- a/editor/txtsvc/src/nsFilteredContentIterator.cpp
+++ b/editor/txtsvc/src/nsFilteredContentIterator.cpp
@@ -40,18 +40,16 @@
 #include "nsComponentManagerUtils.h"
 #include "nsIContent.h"
 #include "nsString.h"
 #include "nsIEnumerator.h"
 
 #include "nsTextServicesDocument.h"
 
 #include "nsIDOMNode.h"
-#include "nsIDOMRange.h"
-#include "nsIRange.h"
 
 //------------------------------------------------------------
 nsFilteredContentIterator::nsFilteredContentIterator(nsITextServicesFilter* aFilter) :
   mFilter(aFilter),
   mDidSkip(false),
   mIsOutOfRange(false),
   mDirection(eDirNotSet)
 {
@@ -86,28 +84,25 @@ nsresult
 nsFilteredContentIterator::Init(nsINode* aRoot)
 {
   NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
   NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
   mIsOutOfRange    = false;
   mDirection       = eForward;
   mCurrentIterator = mPreIterator;
 
-  nsresult rv;
-  mRange = do_CreateInstance("@mozilla.org/content/range;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-  nsCOMPtr<nsIDOMRange> domRange(do_QueryInterface(mRange));
+  mRange = new nsRange();
   nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(aRoot));
-  if (domRange && domNode) {
-    domRange->SelectNode(domNode);
+  if (domNode) {
+    mRange->SelectNode(domNode);
   }
 
-  rv = mPreIterator->Init(domRange);
+  nsresult rv = mPreIterator->Init(mRange);
   NS_ENSURE_SUCCESS(rv, rv);
-  return mIterator->Init(domRange);
+  return mIterator->Init(mRange);
 }
 
 //------------------------------------------------------------
 nsresult
 nsFilteredContentIterator::Init(nsIDOMRange* aRange)
 {
   NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
   NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
@@ -121,23 +116,16 @@ nsFilteredContentIterator::Init(nsIDOMRa
   NS_ENSURE_SUCCESS(rv, rv);
   mRange = do_QueryInterface(domRange);
 
   rv = mPreIterator->Init(domRange);
   NS_ENSURE_SUCCESS(rv, rv);
   return mIterator->Init(domRange);
 }
 
-nsresult
-nsFilteredContentIterator::Init(nsIRange* aRange)
-{
-  nsCOMPtr<nsIDOMRange> domRange = do_QueryInterface(aRange);
-  return Init(domRange);
-}
-
 //------------------------------------------------------------
 nsresult 
 nsFilteredContentIterator::SwitchDirections(bool aChangeToForward)
 {
   nsINode *node = mCurrentIterator->GetCurrentNode();
 
   if (aChangeToForward) {
     mCurrentIterator = mPreIterator;
@@ -273,32 +261,29 @@ ContentIsInTraversalRange(nsIContent *aC
 
   rv = nsTextServicesDocument::ComparePoints(aEndNode,   aEndOffset,   parentNode, indx,  &endRes);
   NS_ENSURE_SUCCESS(rv, false);
 
   return (startRes <= 0) && (endRes >= 0);
 }
 
 static bool
-ContentIsInTraversalRange(nsIDOMNSRange *aRange, nsIDOMNode* aNextNode, bool aIsPreMode)
+ContentIsInTraversalRange(nsIDOMRange *aRange, nsIDOMNode* aNextNode, bool aIsPreMode)
 {
-  nsCOMPtr<nsIContent>  content(do_QueryInterface(aNextNode));
-  nsCOMPtr<nsIDOMRange> range(do_QueryInterface(aRange));
-  NS_ENSURE_TRUE(content && range, false);
-
-
+  nsCOMPtr<nsIContent> content(do_QueryInterface(aNextNode));
+  NS_ENSURE_TRUE(content && aRange, false);
 
   nsCOMPtr<nsIDOMNode> sNode;
   nsCOMPtr<nsIDOMNode> eNode;
   PRInt32 sOffset;
   PRInt32 eOffset;
-  range->GetStartContainer(getter_AddRefs(sNode));
-  range->GetStartOffset(&sOffset);
-  range->GetEndContainer(getter_AddRefs(eNode));
-  range->GetEndOffset(&eOffset);
+  aRange->GetStartContainer(getter_AddRefs(sNode));
+  aRange->GetStartOffset(&sOffset);
+  aRange->GetEndContainer(getter_AddRefs(eNode));
+  aRange->GetEndOffset(&eOffset);
   return ContentIsInTraversalRange(content, aIsPreMode, sNode, sOffset, eNode, eOffset);
 }
 
 //------------------------------------------------------------
 // Helper function to advance to the next or previous node
 nsresult 
 nsFilteredContentIterator::AdvanceNode(nsIDOMNode* aNode, nsIDOMNode*& aNewNode, eDirectionType aDir)
 {
--- a/editor/txtsvc/src/nsFilteredContentIterator.h
+++ b/editor/txtsvc/src/nsFilteredContentIterator.h
@@ -37,17 +37,17 @@
 
 #ifndef nsFilteredContentIterator_h__
 #define nsFilteredContentIterator_h__
 
 #include "nsIContentIterator.h"
 #include "nsCOMPtr.h"
 #include "nsIAtom.h"
 #include "nsITextServicesFilter.h"
-#include "nsIDOMNSRange.h"
+#include "nsRange.h"
 #include "nsIRangeUtils.h"
 #include "nsCycleCollectionParticipant.h"
 
 /**
  * 
  */
 class nsFilteredContentIterator : public nsIContentIterator
 {
@@ -59,17 +59,16 @@ public:
 
   nsFilteredContentIterator(nsITextServicesFilter* aFilter);
 
   virtual ~nsFilteredContentIterator();
 
   /* nsIContentIterator */
   virtual nsresult Init(nsINode* aRoot);
   virtual nsresult Init(nsIDOMRange* aRange);
-  virtual nsresult Init(nsIRange* aRange);
   virtual void First();
   virtual void Last();
   virtual void Next();
   virtual void Prev();
   virtual nsINode *GetCurrentNode();
   virtual bool IsDone();
   virtual nsresult PositionAt(nsINode* aCurNode);
 
@@ -92,15 +91,15 @@ protected:
 
   nsCOMPtr<nsIAtom> mBlockQuoteAtom;
   nsCOMPtr<nsIAtom> mScriptAtom;
   nsCOMPtr<nsIAtom> mTextAreaAtom;
   nsCOMPtr<nsIAtom> mSelectAreaAtom;
   nsCOMPtr<nsIAtom> mMapAtom;
 
   nsCOMPtr<nsITextServicesFilter> mFilter;
-  nsCOMPtr<nsIDOMNSRange>         mRange;
+  nsCOMPtr<nsIDOMRange>           mRange;
   bool                            mDidSkip;
   bool                            mIsOutOfRange;
   eDirectionType                  mDirection;
 };
 
 #endif
--- a/editor/txtsvc/src/nsTextServicesDocument.cpp
+++ b/editor/txtsvc/src/nsTextServicesDocument.cpp
@@ -2117,20 +2117,18 @@ nsTextServicesDocument::CreateDocumentCo
   nsCOMPtr<nsIDOMNode>node;
 
   result = GetDocumentContentRootNode(getter_AddRefs(node));
 
   NS_ENSURE_SUCCESS(result, result);
 
   NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
 
-  result = CallCreateInstance("@mozilla.org/content/range;1", aRange);
-  NS_ENSURE_SUCCESS(result, result);
-
-  NS_ENSURE_TRUE(*aRange, NS_ERROR_NULL_POINTER);
+  *aRange = new nsRange();
+  NS_ADDREF(*aRange);
 
   result = (*aRange)->SelectNodeContents(node);
 
   if (NS_FAILED(result))
   {
     NS_RELEASE((*aRange));
     *aRange = 0;
     return result;
@@ -2197,18 +2195,18 @@ nsTextServicesDocument::CreateDocumentCo
       result = nodeList->GetLength(&nodeListLength);
 
       NS_ENSURE_SUCCESS(result, NS_ERROR_FAILURE);
 
       endOffset = (PRInt32)nodeListLength;
     }
   }
 
-  result = CallCreateInstance("@mozilla.org/content/range;1", aRange);
-  NS_ENSURE_SUCCESS(result, result);
+  *aRange = new nsRange();
+  NS_ADDREF((*aRange));
 
   NS_ENSURE_TRUE(*aRange, NS_ERROR_NULL_POINTER);
 
   result = (*aRange)->SetStart(startNode, startOffset);
 
   if (NS_SUCCEEDED(result))
     result = (*aRange)->SetEnd(endNode, endOffset);
 
@@ -3309,24 +3307,19 @@ nsTextServicesDocument::GetRangeEndPoint
 }
 
 
 nsresult
 nsTextServicesDocument::CreateRange(nsIDOMNode *aStartParent, PRInt32 aStartOffset,
                                     nsIDOMNode *aEndParent, PRInt32 aEndOffset,
                                     nsIDOMRange **aRange)
 {
-  nsresult result;
-
-  result = CallCreateInstance("@mozilla.org/content/range;1", aRange);
-  NS_ENSURE_SUCCESS(result, result);
-
-  NS_ENSURE_TRUE(*aRange, NS_ERROR_NULL_POINTER);
-
-  result = (*aRange)->SetStart(aStartParent, aStartOffset);
+  NS_ADDREF(*aRange = new nsRange());
+
+  nsresult result = (*aRange)->SetStart(aStartParent, aStartOffset);
 
   if (NS_SUCCEEDED(result))
     result = (*aRange)->SetEnd(aEndParent, aEndOffset);
 
   if (NS_FAILED(result))
   {
     NS_RELEASE((*aRange));
     *aRange = 0;
--- a/embedding/components/find/src/nsFind.cpp
+++ b/embedding/components/find/src/nsFind.cpp
@@ -56,24 +56,23 @@
 #include "nsString.h"
 #include "nsIAtom.h"
 #include "nsParserCIID.h"
 #include "nsServiceManagerUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsIDOMElement.h"
 #include "nsIWordBreaker.h"
 #include "nsCRT.h"
-#include "nsIRange.h"
+#include "nsRange.h"
 
 // Yikes!  Casting a char to unichar can fill with ones!
 #define CHAR_TO_UNICHAR(c) ((PRUnichar)(const unsigned char)c)
 
 static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
 static NS_DEFINE_CID(kCPreContentIteratorCID, NS_PRECONTENTITERATOR_CID);
-static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
 
 #define CH_SHY ((PRUnichar) 0xAD)
 
 // nsFind::Find casts CH_SHY to char before calling StripChars
 // This works correctly if and only if CH_SHY <= 255
 PR_STATIC_ASSERT(CH_SHY <= 255);
 
 // -----------------------------------------------------------------------
@@ -128,21 +127,16 @@ public:
     NS_NOTREACHED("internal error");
     return NS_ERROR_NOT_IMPLEMENTED;
   }
   virtual nsresult Init(nsIDOMRange* aRange)
   {
     NS_NOTREACHED("internal error");
     return NS_ERROR_NOT_IMPLEMENTED;
   }
-  virtual nsresult Init(nsIRange* aRange)
-  {
-    NS_NOTREACHED("internal error");
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
   // Not a range because one of the endpoints may be anonymous.
   nsresult Init(nsIDOMNode* aStartNode, PRInt32 aStartOffset,
                 nsIDOMNode* aEndNode, PRInt32 aEndOffset);
   virtual void First();
   virtual void Last();
   virtual void Next();
   virtual void Prev();
   virtual nsINode* GetCurrentNode();
@@ -1315,19 +1309,12 @@ nsFind::Find(const PRUnichar *aPatText, 
   ResetAll();
   return NS_OK;
 }
 
 /* static */
 already_AddRefed<nsIDOMRange>
 nsFind::CreateRange()
 {
-  nsCOMPtr<nsIRange> range = do_CreateInstance(kRangeCID);
-  if (!range) {
-    return nsnull;
-  }
-
+  nsRefPtr<nsRange> range = new nsRange();
   range->SetMaySpanAnonymousSubtrees(true);
-
-  nsIDOMRange* result;
-  CallQueryInterface(range.get(), &result);
-  return result;
+  return range.forget();
 }
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -73,18 +73,17 @@
 #include "nsIDOMNode.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
-#include "nsIDOMNSRange.h"
-#include "nsIDOMRange.h"
+#include "nsRange.h"
 #include "nsIPlaintextEditor.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsIRunnable.h"
 #include "nsISelection.h"
 #include "nsISelectionPrivate.h"
 #include "nsISelectionController.h"
 #include "nsIServiceManager.h"
@@ -164,20 +163,18 @@ mozInlineSpellStatus::InitForEditorChang
   }
 
   mOp = eOpChange;
 
   // range to check
   mRange = new nsRange();
 
   // ...we need to put the start and end in the correct order
-  nsCOMPtr<nsIDOMNSRange> nsrange = do_QueryInterface(mAnchorRange, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
   PRInt16 cmpResult;
-  rv = nsrange->ComparePoint(aPreviousNode, aPreviousOffset, &cmpResult);
+  rv = mAnchorRange->ComparePoint(aPreviousNode, aPreviousOffset, &cmpResult);
   NS_ENSURE_SUCCESS(rv, rv);
   if (cmpResult < 0) {
     // previous anchor node is before the current anchor
     rv = mRange->SetStart(aPreviousNode, aPreviousOffset);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = mRange->SetEnd(aAnchorNode, aAnchorOffset);
   } else {
     // previous anchor node is after (or the same as) the current anchor
@@ -189,27 +186,24 @@ mozInlineSpellStatus::InitForEditorChang
 
   // On insert save this range: DoSpellCheck optimizes things in this range.
   // Otherwise, just leave this NULL.
   if (aAction == mozInlineSpellChecker::kOpInsertText)
     mCreatedRange = mRange;
 
   // if we were given a range, we need to expand our range to encompass it
   if (aStartNode && aEndNode) {
-    nsrange = do_QueryInterface(mRange, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = nsrange->ComparePoint(aStartNode, aStartOffset, &cmpResult);
+    rv = mRange->ComparePoint(aStartNode, aStartOffset, &cmpResult);
     NS_ENSURE_SUCCESS(rv, rv);
     if (cmpResult < 0) { // given range starts before
       rv = mRange->SetStart(aStartNode, aStartOffset);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
-    rv = nsrange->ComparePoint(aEndNode, aEndOffset, &cmpResult);
+    rv = mRange->ComparePoint(aEndNode, aEndOffset, &cmpResult);
     NS_ENSURE_SUCCESS(rv, rv);
     if (cmpResult > 0) { // given range ends after
       rv = mRange->SetEnd(aEndNode, aEndOffset);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   return NS_OK;
@@ -280,17 +274,17 @@ mozInlineSpellStatus::InitForSelection()
 }
 
 // mozInlineSpellStatus::InitForRange
 //
 //    Called to cause the spellcheck of the given range. This will look like
 //    a change operation over the given range.
 
 nsresult
-mozInlineSpellStatus::InitForRange(nsIRange* aRange)
+mozInlineSpellStatus::InitForRange(nsRange* aRange)
 {
   mOp = eOpChange;
   mRange = aRange;
   return NS_OK;
 }
 
 // mozInlineSpellStatus::FinishInitOnEvent
 //
@@ -370,41 +364,38 @@ mozInlineSpellStatus::FinishNavigationEv
   nsresult rv = mOldNavigationAnchorRange->GetStartContainer(
       getter_AddRefs(oldAnchorNode));
   NS_ENSURE_SUCCESS(rv, rv);
   rv = mOldNavigationAnchorRange->GetStartOffset(&oldAnchorOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // find the word on the old caret position, this is the one that we MAY need
   // to check
-  nsCOMPtr<nsIRange> oldWord;
+  nsRefPtr<nsRange> oldWord;
   rv = aWordUtil.GetRangeForWord(oldAnchorNode, oldAnchorOffset,
                                  getter_AddRefs(oldWord));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // aWordUtil.GetRangeForWord flushes pending notifications, check editor again.
   editor = do_QueryReferent(mSpellChecker->mEditor);
   if (! editor)
     return NS_ERROR_FAILURE; // editor is gone
 
-  nsCOMPtr<nsIDOMNSRange> oldWordNS = do_QueryInterface(oldWord, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   // get the DOM position of the new caret, the range should be collapsed
   rv = mAnchorRange->GetStartContainer(getter_AddRefs(newAnchorNode));
   NS_ENSURE_SUCCESS(rv, rv);
   rv = mAnchorRange->GetStartOffset(&newAnchorOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // see if the new cursor position is in the word of the old cursor position
   bool isInRange = false;
   if (! mForceNavigationWordCheck) {
-    rv = oldWordNS->IsPointInRange(newAnchorNode,
-                                   newAnchorOffset + mNewNavigationPositionOffset,
-                                   &isInRange);
+    rv = oldWord->IsPointInRange(newAnchorNode,
+                                 newAnchorOffset + mNewNavigationPositionOffset,
+                                 &isInRange);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (isInRange) {
     // caller should give up
     mRange = nsnull;
   } else {
     // check the old word
@@ -793,17 +784,17 @@ mozInlineSpellChecker::SpellCheckAfterEd
 //    Supply a NULL range and this will check the entire editor.
 
 nsresult
 mozInlineSpellChecker::SpellCheckRange(nsIDOMRange* aRange)
 {
   NS_ENSURE_TRUE(mSpellCheck, NS_ERROR_NOT_INITIALIZED);
 
   mozInlineSpellStatus status(this);
-  nsCOMPtr<nsIRange> range = do_QueryInterface(aRange);
+  nsRange* range = static_cast<nsRange*>(aRange);
   nsresult rv = status.InitForRange(range);
   NS_ENSURE_SUCCESS(rv, rv);
   return ScheduleSpellCheck(status);
 }
 
 // mozInlineSpellChecker::GetMisspelledWord
 
 NS_IMETHODIMP
@@ -876,18 +867,17 @@ mozInlineSpellChecker::RemoveWordFromDic
 {
   NS_ENSURE_TRUE(mSpellCheck, NS_ERROR_NOT_INITIALIZED);
 
   nsAutoString wordstr(word);
   nsresult rv = mSpellCheck->RemoveWordFromDictionary(wordstr.get());
   NS_ENSURE_SUCCESS(rv, rv); 
   
   mozInlineSpellStatus status(this);
-  nsCOMPtr<nsIRange> range = do_QueryInterface(NULL); // Check everything
-  rv = status.InitForRange(range);
+  rv = status.InitForRange(nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
   return ScheduleSpellCheck(status);
 }
 
 // mozInlineSpellChecker::IgnoreWord
 
 NS_IMETHODIMP
 mozInlineSpellChecker::IgnoreWord(const nsAString &word)
@@ -1018,17 +1008,17 @@ NS_IMETHODIMP mozInlineSpellChecker::Did
 //
 //    If the resulting range would be empty, NULL is put into *aRange and the
 //    function succeeds.
 
 nsresult
 mozInlineSpellChecker::MakeSpellCheckRange(
     nsIDOMNode* aStartNode, PRInt32 aStartOffset,
     nsIDOMNode* aEndNode, PRInt32 aEndOffset,
-    nsIRange** aRange)
+    nsRange** aRange)
 {
   nsresult rv;
   *aRange = nsnull;
 
   nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
   NS_ENSURE_TRUE(editor, NS_ERROR_NULL_POINTER);
 
   nsCOMPtr<nsIDOMDocument> doc;
@@ -1073,27 +1063,27 @@ mozInlineSpellChecker::MakeSpellCheckRan
   rv = range->SetStart(aStartNode, aStartOffset);
   NS_ENSURE_SUCCESS(rv, rv);
   if (aEndOffset)
     rv = range->SetEnd(aEndNode, aEndOffset);
   else
     rv = range->SetEndAfter(aEndNode);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  CallQueryInterface(range, aRange);
+  *aRange = static_cast<nsRange*>(range.forget().get());
   return NS_OK;
 }
 
 nsresult
 mozInlineSpellChecker::SpellCheckBetweenNodes(nsIDOMNode *aStartNode,
                                               PRInt32 aStartOffset,
                                               nsIDOMNode *aEndNode,
                                               PRInt32 aEndOffset)
 {
-  nsCOMPtr<nsIRange> range;
+  nsRefPtr<nsRange> range;
   nsresult rv = MakeSpellCheckRange(aStartNode, aStartOffset,
                                     aEndNode, aEndOffset,
                                     getter_AddRefs(range));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (! range)
     return NS_OK; // range is empty: nothing to do
 
@@ -1248,17 +1238,17 @@ mozInlineSpellChecker::DoSpellCheckSelec
   bool doneChecking;
   for (idx = 0; idx < count; idx ++) {
     checkRange = ranges[idx];
     if (checkRange) {
       // We can consider this word as "added" since we know it has no spell
       // check range over it that needs to be deleted. All the old ranges
       // were cleared above. We also need to clear the word count so that we
       // check all words instead of stopping early.
-      status.mRange = do_QueryInterface(checkRange);
+      status.mRange = static_cast<nsRange*>(checkRange.get());
       rv = DoSpellCheck(aWordUtil, aSpellCheckSelection, &status,
                         &doneChecking);
       NS_ENSURE_SUCCESS(rv, rv);
       NS_ASSERTION(doneChecking, "We gave the spellchecker one word, but it didn't finish checking?!?!");
 
       status.mWordCount = 0;
     }
   }
@@ -1346,29 +1336,22 @@ nsresult mozInlineSpellChecker::DoSpellC
     aWordUtil.SetEnd(endNode, endOffset);
     aWordUtil.SetPosition(beginNode, beginOffset);
   }
 
   // aWordUtil.SetPosition flushes pending notifications, check editor again.
   editor = do_QueryReferent(mEditor);
   if (! editor)
     return NS_ERROR_FAILURE;
-  
-  // we need to use IsPointInRange which is on a more specific interface
-  nsCOMPtr<nsIDOMNSRange> noCheckRange, createdRange;
-  if (aStatus->mNoCheckRange)
-    noCheckRange = do_QueryInterface(aStatus->mNoCheckRange);
-  if (aStatus->mCreatedRange)
-    createdRange = do_QueryInterface(aStatus->mCreatedRange);
 
   PRInt32 wordsSinceTimeCheck = 0;
   PRTime beginTime = PR_Now();
 
   nsAutoString wordText;
-  nsCOMPtr<nsIRange> wordRange;
+  nsRefPtr<nsRange> wordRange;
   bool dontCheckWord;
   while (NS_SUCCEEDED(aWordUtil.GetNextWord(wordText,
                                             getter_AddRefs(wordRange),
                                             &dontCheckWord)) &&
          wordRange) {
     wordsSinceTimeCheck ++;
 
     // get the range for the current word.
@@ -1389,25 +1372,27 @@ nsresult mozInlineSpellChecker::DoSpellC
 #endif
 
     // see if there is a spellcheck range that already intersects the word
     // and remove it. We only need to remove old ranges, so don't bother if
     // there were no ranges when we started out.
     if (originalRangeCount > 0) {
       // likewise, if this word is inside new text, we won't bother testing
       bool inCreatedRange = false;
-      if (createdRange)
-        createdRange->IsPointInRange(beginNode, beginOffset, &inCreatedRange);
+      if (aStatus->mCreatedRange)
+        aStatus->mCreatedRange->IsPointInRange(beginNode, beginOffset, &inCreatedRange);
       if (! inCreatedRange) {
-        nsCOMArray<nsIDOMRange> ranges;
-        rv = privSel->GetRangesForIntervalCOMArray(beginNode, beginOffset,
-                                                   endNode, endOffset,
-                                                   true, &ranges);
+        nsTArray<nsRange*> ranges;
+        nsCOMPtr<nsINode> firstNode = do_QueryInterface(beginNode);
+        nsCOMPtr<nsINode> lastNode = do_QueryInterface(endNode);
+        rv = privSel->GetRangesForIntervalArray(firstNode, beginOffset,
+                                                lastNode, endOffset,
+                                                true, &ranges);
         NS_ENSURE_SUCCESS(rv, rv);
-        for (PRInt32 i = 0; i < ranges.Count(); i ++)
+        for (PRUint32 i = 0; i < ranges.Length(); i++)
           RemoveRange(aSpellCheckSelection, ranges[i]);
       }
     }
 
     // some words are special and don't need checking
     if (dontCheckWord)
       continue;
 
@@ -1420,19 +1405,20 @@ nsresult mozInlineSpellChecker::DoSpellC
 
     // Don't check spelling if we're inside the noCheckRange. This needs to
     // be done after we clear any old selection because the excluded word
     // might have been previously marked.
     //
     // We do a simple check to see if the beginning of our word is in the
     // exclusion range. Because the exclusion range is a multiple of a word,
     // this is sufficient.
-    if (noCheckRange) {
+    if (aStatus->mNoCheckRange) {
       bool inExclusion = false;
-      noCheckRange->IsPointInRange(beginNode, beginOffset, &inExclusion);
+      aStatus->mNoCheckRange->IsPointInRange(beginNode, beginOffset,
+                                             &inExclusion);
       if (inExclusion)
         continue;
     }
 
     // check spelling and add to selection if misspelled
     bool isMisspelled;
     aWordUtil.NormalizeWord(wordText);
     rv = mSpellCheck->CheckCurrentWordNoSuggest(wordText.get(), &isMisspelled);
@@ -1555,22 +1541,23 @@ mozInlineSpellChecker::IsPointInSelectio
                                           nsIDOMNode *aNode,
                                           PRInt32 aOffset,
                                           nsIDOMRange **aRange)
 {
   *aRange = nsnull;
 
   nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(aSelection));
 
-  nsCOMArray<nsIDOMRange> ranges;
-  nsresult rv = privSel->GetRangesForIntervalCOMArray(aNode, aOffset, aNode, aOffset,
-                                                      true, &ranges);
+  nsTArray<nsRange*> ranges;
+  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+  nsresult rv = privSel->GetRangesForIntervalArray(node, aOffset, node, aOffset,
+                                                   true, &ranges);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (ranges.Count() == 0)
+  if (ranges.Length() == 0)
     return NS_OK; // no matches
 
   // there may be more than one range returned, and we don't know what do
   // do with that, so just get the first one
   NS_ADDREF(*aRange = ranges[0]);
   return NS_OK;
 }
 
--- a/extensions/spellcheck/src/mozInlineSpellChecker.h
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.h
@@ -35,17 +35,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __mozinlinespellchecker_h__
 #define __mozinlinespellchecker_h__
 
 #include "nsAutoPtr.h"
-#include "nsIRange.h"
+#include "nsRange.h"
 #include "nsIEditorSpellCheck.h"
 #include "nsIEditActionListener.h"
 #include "nsIInlineSpellChecker.h"
 #include "nsITextServicesDocument.h"
 #include "nsIDOMTreeWalker.h"
 #include "nsWeakReference.h"
 #include "nsIEditor.h"
 #include "nsIDOMEventListener.h"
@@ -73,17 +73,17 @@ public:
                                nsIDOMNode* aPreviousNode, PRInt32 aPreviousOffset,
                                nsIDOMNode* aStartNode, PRInt32 aStartOffset,
                                nsIDOMNode* aEndNode, PRInt32 aEndOffset);
   nsresult InitForNavigation(bool aForceCheck, PRInt32 aNewPositionOffset,
                              nsIDOMNode* aOldAnchorNode, PRInt32 aOldAnchorOffset,
                              nsIDOMNode* aNewAnchorNode, PRInt32 aNewAnchorOffset,
                              bool* aContinue);
   nsresult InitForSelection();
-  nsresult InitForRange(nsIRange* aRange);
+  nsresult InitForRange(nsRange* aRange);
 
   nsresult FinishInitOnEvent(mozInlineSpellWordUtil& aWordUtil);
 
   // Return true if we plan to spell-check everything
   bool IsFullSpellCheck() const {
     return mOp == eOpChange && !mRange;
   }
 
@@ -99,24 +99,24 @@ public:
                    eOpChangeDelete, // for SpellCheckAfterChange kOpDeleteSelection
                    eOpNavigation,   // for HandleNavigationEvent
                    eOpSelection,    // re-check all misspelled words
                    eOpResume };     // for resuming a previously started check
   Operation mOp;
 
   // Used for events where we have already computed the range to use. It can
   // also be NULL in these cases where we need to check the entire range.
-  nsCOMPtr<nsIRange> mRange;
+  nsRefPtr<nsRange> mRange;
 
   // If we happen to know something was inserted, this is that range.
   // Can be NULL (this only allows an optimization, so not setting doesn't hurt)
   nsCOMPtr<nsIDOMRange> mCreatedRange;
 
   // Contains the range computed for the current word. Can be NULL.
-  nsCOMPtr<nsIRange> mNoCheckRange;
+  nsRefPtr<nsRange> mNoCheckRange;
 
   // Indicates the position of the cursor for the event (so we can compute
   // mNoCheckRange). It can be NULL if we don't care about the cursor position
   // (such as for the intial check of everything).
   //
   // For mOp == eOpNavigation, this is the NEW position of the cursor
   nsCOMPtr<nsIDOMRange> mAnchorRange;
 
@@ -287,17 +287,17 @@ public:
   nsresult CleanupRangesInSelection(nsISelection *aSelection);
 
   nsresult RemoveRange(nsISelection *aSpellCheckSelection, nsIDOMRange * aRange);
   nsresult AddRange(nsISelection *aSpellCheckSelection, nsIDOMRange * aRange);
   bool     SpellCheckSelectionIsFull() { return mNumWordsInSpellSelection >= mMaxNumWordsInSpellSelection; }
 
   nsresult MakeSpellCheckRange(nsIDOMNode* aStartNode, PRInt32 aStartOffset,
                                nsIDOMNode* aEndNode, PRInt32 aEndOffset,
-                               nsIRange** aRange);
+                               nsRange** aRange);
 
   // DOM and editor event registration helper routines
   nsresult RegisterEventListeners();
   nsresult UnregisterEventListeners();
   nsresult HandleNavigationEvent(bool aForceWordSpellCheck, PRInt32 aNewPositionOffset = 0);
 
   nsresult GetSpellCheckSelection(nsISelection ** aSpellCheckSelection);
   nsresult SaveCurrentSelectionPosition();
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
@@ -38,28 +38,28 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozInlineSpellWordUtil.h"
 #include "nsDebug.h"
 #include "nsIAtom.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMElement.h"
-#include "nsIDOMNSRange.h"
 #include "nsIDOMRange.h"
 #include "nsIEditor.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMHTMLBRElement.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIContent.h"
 #include "nsTextFragment.h"
 #include "mozilla/dom/Element.h"
 #include "nsIFrame.h"
 #include "nsRange.h"
+#include "nsContentUtils.h"
 
 using namespace mozilla;
 
 // IsIgnorableCharacter
 //
 //    These characters are ones that we should ignore in input.
 
 inline bool IsIgnorableCharacter(PRUnichar ch)
@@ -252,29 +252,29 @@ mozInlineSpellWordUtil::EnsureWords()
   if (mSoftTextValid)
     return;
   BuildSoftText();
   BuildRealWords();
   mSoftTextValid = true;
 }
 
 nsresult
-mozInlineSpellWordUtil::MakeRangeForWord(const RealWord& aWord, nsIRange** aRange)
+mozInlineSpellWordUtil::MakeRangeForWord(const RealWord& aWord, nsRange** aRange)
 {
   NodeOffset begin = MapSoftTextOffsetToDOMPosition(aWord.mSoftTextOffset, HINT_BEGIN);
   NodeOffset end = MapSoftTextOffsetToDOMPosition(aWord.EndOffset(), HINT_END);
   return MakeRange(begin, end, aRange);
 }
 
 // mozInlineSpellWordUtil::GetRangeForWord
 
 nsresult
 mozInlineSpellWordUtil::GetRangeForWord(nsIDOMNode* aWordNode,
                                         PRInt32 aWordOffset,
-                                        nsIRange** aRange)
+                                        nsRange** aRange)
 {
   // Set our soft end and start
   nsCOMPtr<nsINode> wordNode = do_QueryInterface(aWordNode);
   NodeOffset pt = NodeOffset(wordNode, aWordOffset);
   
   InvalidateWords();
   mSoftBegin = mSoftEnd = pt;
   EnsureWords();
@@ -311,17 +311,17 @@ NormalizeWord(const nsSubstring& aInput,
 
 // mozInlineSpellWordUtil::GetNextWord
 //
 //    FIXME-optimization: we shouldn't have to generate a range every single
 //    time. It would be better if the inline spellchecker didn't require a
 //    range unless the word was misspelled. This may or may not be possible.
 
 nsresult
-mozInlineSpellWordUtil::GetNextWord(nsAString& aText, nsIRange** aRange,
+mozInlineSpellWordUtil::GetNextWord(nsAString& aText, nsRange** aRange,
                                     bool* aSkipChecking)
 {
 #ifdef DEBUG_SPELLCHECK
   printf("GetNextWord called; mNextWordIndex=%d\n", mNextWordIndex);
 #endif
 
   if (mNextWordIndex < 0 ||
       mNextWordIndex >= PRInt32(mRealWords.Length())) {
@@ -347,17 +347,17 @@ mozInlineSpellWordUtil::GetNextWord(nsAS
 }
 
 // mozInlineSpellWordUtil::MakeRange
 //
 //    Convenience function for creating a range over the current document.
 
 nsresult
 mozInlineSpellWordUtil::MakeRange(NodeOffset aBegin, NodeOffset aEnd,
-                                  nsIRange** aRange)
+                                  nsRange** aRange)
 {
   if (!mDOMDocument)
     return NS_ERROR_NOT_INITIALIZED;
 
   nsRefPtr<nsRange> range = new nsRange();
   nsresult rv = range->Set(aBegin.mNode, aBegin.mOffset,
                            aEnd.mNode, aEnd.mOffset);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -523,16 +523,20 @@ mozInlineSpellWordUtil::BuildSoftText()
     }
     checkBeforeOffset = PR_INT32_MAX;
     if (IsBreakElement(node)) {
       // Since GetPreviousContent follows tree *preorder*, we're about to traverse
       // up out of 'node'. Since node induces breaks (e.g., it's a block),
       // don't bother trying to look outside it, just stop now.
       break;
     }
+    // GetPreviousContent below expects mRootNode to be an ancestor of node.
+    if (!nsContentUtils::ContentIsDescendantOf(node, mRootNode)) {
+      break;
+    }
     node = node->GetPreviousContent(mRootNode);
   }
 
   // Now build up the string moving forward through the DOM until we reach
   // the soft end and *then* see a DOM word separator, a non-inline-element
   // boundary, or the hard end node.
   mSoftText.Truncate();
   mSoftTextDOMMapping.Clear();
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.h
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.h
@@ -39,17 +39,17 @@
 #include "nsIDOMDocument.h"
 #include "nsIDocument.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsIUGenCategory.h"
 
 //#define DEBUG_SPELLCHECK
 
-class nsIRange;
+class nsRange;
 class nsINode;
 
 /**
  *    This class extracts text from the DOM and builds it into a single string.
  *    The string includes whitespace breaks whereever non-inline elements begin
  *    and end. This string is broken into "real words", following somewhat
  *    complex rules; for example substrings that look like URLs or
  *    email addresses are treated as single words, but otherwise many kinds of
@@ -96,23 +96,23 @@ public:
   // position will be at the end of the word. This will find the previous
   // word if the current position is space, so if you care that the point is
   // inside the word, you should check the range.
   //
   // THIS CHANGES THE CURRENT POSITION AND RANGE. It is designed to be called
   // before you actually generate the range you are interested in and iterate
   // the words in it.
   nsresult GetRangeForWord(nsIDOMNode* aWordNode, PRInt32 aWordOffset,
-                           nsIRange** aRange);
+                           nsRange** aRange);
 
   // Moves to the the next word in the range, and retrieves it's text and range.
   // An empty word and a NULL range are returned when we are done checking.
   // aSkipChecking will be set if the word is "special" and shouldn't be
   // checked (e.g., an email address).
-  nsresult GetNextWord(nsAString& aText, nsIRange** aRange,
+  nsresult GetNextWord(nsAString& aText, nsRange** aRange,
                        bool* aSkipChecking);
 
   // Call to normalize some punctuation. This function takes an autostring
   // so we can access characters directly.
   static void NormalizeWord(nsSubstring& aWord);
 
   nsIDOMDocument* GetDOMDocument() const { return mDOMDocument; }
   nsIDocument* GetDocument() const { return mDocument; }
@@ -186,11 +186,11 @@ private:
   // build mSoftText and mSoftTextDOMMapping
   void BuildSoftText();
   // Build mRealWords array
   void BuildRealWords();
 
   void SplitDOMWord(PRInt32 aStart, PRInt32 aEnd);
 
   // Convenience functions, object must be initialized
-  nsresult MakeRange(NodeOffset aBegin, NodeOffset aEnd, nsIRange** aRange);
-  nsresult MakeRangeForWord(const RealWord& aWord, nsIRange** aRange);
+  nsresult MakeRange(NodeOffset aBegin, NodeOffset aEnd, nsRange** aRange);
+  nsresult MakeRangeForWord(const RealWord& aWord, nsRange** aRange);
 };
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -3232,23 +3232,35 @@ gfxFontGroup::InitScriptRun(gfxContext *
 
 already_AddRefed<gfxFont>
 gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
                               PRInt32 aRunScript, gfxFont *aPrevMatchedFont,
                               PRUint8 *aMatchType)
 {
     nsRefPtr<gfxFont>    selectedFont;
 
-    // if this character is a join-control or the previous is a join-causer,
-    // use the same font as the previous range if we can
-    if (gfxFontUtils::IsJoinControl(aCh) || gfxFontUtils::IsJoinCauser(aPrevCh)) {
-        if (aPrevMatchedFont && aPrevMatchedFont->HasCharacter(aCh)) {
+    if (aPrevMatchedFont) {
+        // Don't switch fonts for control characters, regardless of
+        // whether they are present in the current font, as they won't
+        // actually be rendered (see bug 716229)
+        PRUint8 category = gfxUnicodeProperties::GetGeneralCategory(aCh);
+        if (category == HB_CATEGORY_CONTROL) {
             selectedFont = aPrevMatchedFont;
             return selectedFont.forget();
         }
+
+        // if this character is a join-control or the previous is a join-causer,
+        // use the same font as the previous range if we can
+        if (gfxFontUtils::IsJoinControl(aCh) ||
+            gfxFontUtils::IsJoinCauser(aPrevCh)) {
+            if (aPrevMatchedFont->HasCharacter(aCh)) {
+                selectedFont = aPrevMatchedFont;
+                return selectedFont.forget();
+            }
+        }
     }
 
     // if this character is a variation selector,
     // use the previous font regardless of whether it supports VS or not.
     // otherwise the text run will be divided.
     if (gfxFontUtils::IsVarSelector(aCh)) {
         if (aPrevMatchedFont) {
             selectedFont = aPrevMatchedFont;
--- a/gfx/thebes/gfxPangoFonts.cpp
+++ b/gfx/thebes/gfxPangoFonts.cpp
@@ -2043,22 +2043,33 @@ gfxPangoFontGroup::GetFontSet(PangoLangu
 }
 
 already_AddRefed<gfxFont>
 gfxPangoFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
                                    PRInt32 aRunScript,
                                    gfxFont *aPrevMatchedFont,
                                    PRUint8 *aMatchType)
 {
-    // if this character is a join-control or the previous is a join-causer,
-    // use the same font as the previous range if we can
-    if (gfxFontUtils::IsJoinControl(aCh) || gfxFontUtils::IsJoinCauser(aPrevCh)) {
-        if (aPrevMatchedFont && aPrevMatchedFont->HasCharacter(aCh)) {
+    if (aPrevMatchedFont) {
+        // Don't switch fonts for control characters, regardless of
+        // whether they are present in the current font, as they won't
+        // actually be rendered (see bug 716229)
+        PRUint8 category = gfxUnicodeProperties::GetGeneralCategory(aCh);
+        if (category == HB_CATEGORY_CONTROL) {
             return nsRefPtr<gfxFont>(aPrevMatchedFont).forget();
         }
+
+        // if this character is a join-control or the previous is a join-causer,
+        // use the same font as the previous range if we can
+        if (gfxFontUtils::IsJoinControl(aCh) ||
+            gfxFontUtils::IsJoinCauser(aPrevCh)) {
+            if (aPrevMatchedFont->HasCharacter(aCh)) {
+                return nsRefPtr<gfxFont>(aPrevMatchedFont).forget();
+            }
+        }
     }
 
     // if this character is a variation selector,
     // use the previous font regardless of whether it supports VS or not.
     // otherwise the text run will be divided.
     if (gfxFontUtils::IsVarSelector(aCh)) {
         if (aPrevMatchedFont) {
             return nsRefPtr<gfxFont>(aPrevMatchedFont).forget();
--- a/gfx/thebes/nsCoreAnimationSupport.mm
+++ b/gfx/thebes/nsCoreAnimationSupport.mm
@@ -775,34 +775,36 @@ nsresult nsCARenderer::DrawSurfaceToCGCo
                                               nsIOSurface *surf, 
                                               CGColorSpaceRef aColorSpace,
                                               int aX, int aY,
                                               size_t aWidth, size_t aHeight) {
   surf->Lock();
   size_t bytesPerRow = surf->GetBytesPerRow();
   size_t ioWidth = surf->GetWidth();
   size_t ioHeight = surf->GetHeight();
-  void* ioData = surf->GetBaseAddress();
-  CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(ioData,
-                                      ioData, ioHeight*(bytesPerRow)*4, 
-                                      NULL); //No release callback 
-  if (!dataProvider) {
-    surf->Unlock();
-    return NS_ERROR_FAILURE;
-  }
 
   // We get rendering glitches if we use a width/height that falls
   // outside of the IOSurface.
   if (aWidth + aX > ioWidth) 
     aWidth = ioWidth - aX;
   if (aHeight + aY > ioHeight) 
     aHeight = ioHeight - aY;
 
   if (aX < 0 || aX >= ioWidth ||
       aY < 0 || aY >= ioHeight) {
+    surf->Unlock();
+    return NS_ERROR_FAILURE;
+  }
+
+  void* ioData = surf->GetBaseAddress();
+  CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(ioData,
+                                      ioData, ioHeight*(bytesPerRow)*4, 
+                                      NULL); //No release callback 
+  if (!dataProvider) {
+    surf->Unlock();
     return NS_ERROR_FAILURE;
   }
 
   CGImageRef cgImage = ::CGImageCreate(ioWidth, ioHeight, 8, 32, bytesPerRow,
               aColorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
               dataProvider, NULL, true, kCGRenderingIntentDefault);
   ::CGDataProviderRelease(dataProvider);
   if (!cgImage) {
@@ -854,43 +856,48 @@ void nsCARenderer::SaveToDisk(nsIOSurfac
   CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(ioData,
                                       ioData, ioHeight*(bytesPerRow)*4, 
                                       NULL); //No release callback 
   if (!dataProvider) {
     surf->Unlock();
     return;
   }
 
+  CGColorSpaceRef colorSpace = CreateSystemColorSpace();
   CGImageRef cgImage = ::CGImageCreate(ioWidth, ioHeight, 8, 32, bytesPerRow,
-              CreateSystemColorSpace(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+              colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
               dataProvider, NULL, true, kCGRenderingIntentDefault);
   ::CGDataProviderRelease(dataProvider);
+  ::CGColorSpaceRelease(colorSpace);
   if (!cgImage) {
     surf->Unlock();
     return;
   }
 
   char cstr[1000];
 
   sprintf(cstr, "file:///Users/benoitgirard/debug/iosurface_%i.png", ++sSaveToDiskSequence);
 
   CFStringRef cfStr = ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, kCFStringEncodingMacRoman);
 
   printf("Exporting: %s\n", cstr);
   CFURLRef url = ::CFURLCreateWithString( NULL, cfStr, NULL);
+  ::CFRelease(cfStr);
 
   CFStringRef type = kUTTypePNG;
   size_t count = 1;
   CFDictionaryRef options = NULL;
   CGImageDestinationRef dest = ::CGImageDestinationCreateWithURL(url, type, count, options);
+  ::CFRelease(url);
 
   ::CGImageDestinationAddImage(dest, cgImage, NULL);
 
   ::CGImageDestinationFinalize(dest);
   ::CFRelease(dest);
+  ::CGImageRelease(cgImage);
 
   surf->Unlock();
 
   return;
 
 }
 
 #endif
--- a/js/src/config/Preprocessor.py
+++ b/js/src/config/Preprocessor.py
@@ -423,17 +423,17 @@ class Preprocessor:
     if isName:
       try:
         args = str(args)
         if not os.path.isabs(args):
           args = os.path.join(self.context['DIRECTORY'], args)
         args = open(args, 'rU')
       except:
         raise Preprocessor.Error(self, 'FILE_NOT_FOUND', str(args))
-    self.checkLineNumbers = bool(re.search('\.js(?:\.in)?$', args.name))
+    self.checkLineNumbers = bool(re.search('\.(js|java)(?:\.in)?$', args.name))
     oldFile = self.context['FILE']
     oldLine = self.context['LINE']
     oldDir = self.context['DIRECTORY']
     if args.isatty():
       # we're stdin, use '-' and '' for file and dir
       self.context['FILE'] = '-'
       self.context['DIRECTORY'] = ''
     else:
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -760,32 +760,31 @@ struct TraversalTracer : public JSTracer
     {
     }
     nsCycleCollectionTraversalCallback &cb;
 };
 
 static void
 NoteJSChild(JSTracer *trc, void *thing, JSGCTraceKind kind)
 {
+    TraversalTracer *tracer = static_cast<TraversalTracer*>(trc);
+
+    // Don't traverse non-gray objects, unless we want all traces.
+    if (!xpc_IsGrayGCThing(thing) && !tracer->cb.WantAllTraces())
+        return;
+
     /*
      * This function needs to be careful to avoid stack overflow. Normally, when
      * AddToCCKind is true, the recursion terminates immediately as we just add
      * |thing| to the CC graph. So overflow is only possible when there are long
      * chains of non-AddToCCKind GC things. Currently, this only can happen via
      * shape parent pointers. The special JSTRACE_SHAPE case below handles
      * parent pointers iteratively, rather than recursively, to avoid overflow.
      */
     if (AddToCCKind(kind)) {
-        TraversalTracer *tracer = static_cast<TraversalTracer*>(trc);
-
-        // There's no point in further traversing a non-gray object here unless
-        // we explicitly want to see all traces.
-        if (!xpc_IsGrayGCThing(thing) && !tracer->cb.WantAllTraces())
-            return;
-
 #if defined(DEBUG)
         if (NS_UNLIKELY(tracer->cb.WantDebugInfo())) {
             // based on DumpNotify in jsapi.c
             if (tracer->debugPrinter) {
                 char buffer[200];
                 tracer->debugPrinter(trc, buffer, sizeof(buffer));
                 tracer->cb.NoteNextEdgeName(buffer);
             } else if (tracer->debugPrintIndex != (size_t)-1) {
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -195,16 +195,19 @@
 #include "nsPlaceholderFrame.h"
 #include "nsCanvasFrame.h"
 
 // Content viewer interfaces
 #include "nsIContentViewer.h"
 #include "imgIEncoder.h"
 #include "gfxPlatform.h"
 
+/* for NS_MEMORY_REPORTER_IMPLEMENT */
+#include "nsIMemoryReporter.h"
+
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "sampler.h"
 
 #include "Layers.h"
 #include "nsAsyncDOMEvent.h"
 
@@ -219,22 +222,16 @@
      "%s (line %d) (document: %s)", MOZ_FUNCTION_NAME, \
      __LINE__, docURL__.get())
 #else
 #define NS_TIME_FUNCTION_WITH_DOCURL do{} while(0)
 #endif
 
 #define ANCHOR_SCROLL_FLAGS (SCROLL_OVERFLOW_HIDDEN | SCROLL_NO_PARENT_FRAMES)
 
-#include "nsContentCID.h"
-static NS_DEFINE_IID(kRangeCID,     NS_RANGE_CID);
-
-/* for NS_MEMORY_REPORTER_IMPLEMENT */
-#include "nsIMemoryReporter.h"
-
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 
 CapturingContentInfo nsIPresShell::gCaptureInfo =
   { false /* mAllowed */,     false /* mRetargetToElement */,
     false /* mPreventDrag */, nsnull /* mContent */ };
 nsIContent* nsIPresShell::gKeyDownTarget;
@@ -252,24 +249,24 @@ ChangeFlag(PRUint32 aFlags, bool aOnOff,
 }
 
 // convert a color value to a string, in the CSS format #RRGGBB
 // *  - initially created for bugs 31816, 20760, 22963
 static void ColorToString(nscolor aColor, nsAutoString &aString);
 
 // RangePaintInfo is used to paint ranges to offscreen buffers
 struct RangePaintInfo {
-  nsCOMPtr<nsIRange> mRange;
+  nsRefPtr<nsRange> mRange;
   nsDisplayListBuilder mBuilder;
   nsDisplayList mList;
 
   // offset of builder's reference frame to the root frame
   nsPoint mRootOffset;
 
-  RangePaintInfo(nsIRange* aRange, nsIFrame* aFrame)
+  RangePaintInfo(nsRange* aRange, nsIFrame* aFrame)
     : mRange(aRange), mBuilder(aFrame, nsDisplayListBuilder::PAINTING, false)
   {
     MOZ_COUNT_CTOR(RangePaintInfo);
   }
 
   ~RangePaintInfo()
   {
     mList.DeleteAll();
@@ -3151,47 +3148,44 @@ PresShell::GoToAnchor(const nsAString& a
 
     // Should we select the target? This action is controlled by a
     // preference: the default is to not select.
     bool selectAnchor = Preferences::GetBool("layout.selectanchor");
 
     // Even if select anchor pref is false, we must still move the
     // caret there. That way tabbing will start from the new
     // location
-    nsCOMPtr<nsIDOMRange> jumpToRange = do_CreateInstance(kRangeCID);
-    if (jumpToRange) {
-      while (content && content->GetChildCount() > 0) {
-        content = content->GetChildAt(0);
+    nsRefPtr<nsIDOMRange> jumpToRange = new nsRange();
+    while (content && content->GetChildCount() > 0) {
+      content = content->GetChildAt(0);
+    }
+    nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content));
+    NS_ASSERTION(node, "No nsIDOMNode for descendant of anchor");
+    jumpToRange->SelectNodeContents(node);
+    // Select the anchor
+    nsISelection* sel = mSelection->
+      GetSelection(nsISelectionController::SELECTION_NORMAL);
+    if (sel) {
+      sel->RemoveAllRanges();
+      sel->AddRange(jumpToRange);
+      if (!selectAnchor) {
+        // Use a caret (collapsed selection) at the start of the anchor
+        sel->CollapseToStart();
       }
-      nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content));
-      NS_ASSERTION(node, "No nsIDOMNode for descendant of anchor");
-      jumpToRange->SelectNodeContents(node);
-    }
-    if (jumpToRange) {
-      // Select the anchor
-      nsISelection* sel = mSelection->
-        GetSelection(nsISelectionController::SELECTION_NORMAL);
-      if (sel) {
-        sel->RemoveAllRanges();
-        sel->AddRange(jumpToRange);
-        if (!selectAnchor) {
-          // Use a caret (collapsed selection) at the start of the anchor
-          sel->CollapseToStart();
-        }
-      }
-      // Selection is at anchor.
-      // Now focus the document itself if focus is on an element within it.
-      nsPIDOMWindow *win = mDocument->GetWindow();
-
-      nsIFocusManager* fm = nsFocusManager::GetFocusManager();
-      if (fm && win) {
-        nsCOMPtr<nsIDOMWindow> focusedWindow;
-        fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
-        if (SameCOMIdentity(win, focusedWindow))
-          fm->ClearFocus(focusedWindow);
+    }
+    // Selection is at anchor.
+    // Now focus the document itself if focus is on an element within it.
+    nsPIDOMWindow *win = mDocument->GetWindow();
+
+    nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+    if (fm && win) {
+      nsCOMPtr<nsIDOMWindow> focusedWindow;
+      fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
+      if (SameCOMIdentity(win, focusedWindow)) {
+        fm->ClearFocus(focusedWindow);
       }
     }
   } else {
     rv = NS_ERROR_FAILURE;
     NS_NAMED_LITERAL_STRING(top, "top");
     if (nsContentUtils::EqualsIgnoreASCIICase(aAnchorName, top)) {
       // Scroll to the top/left if aAnchorName is "top" and there is no element
       // with such a name or id.
@@ -4626,17 +4620,17 @@ PresShell::RenderDocument(const nsRect& 
 
 /*
  * Clip the display list aList to a range. Returns the clipped
  * rectangle surrounding the range.
  */
 nsRect
 PresShell::ClipListToRange(nsDisplayListBuilder *aBuilder,
                            nsDisplayList* aList,
-                           nsIRange* aRange)
+                           nsRange* aRange)
 {
   NS_TIME_FUNCTION_WITH_DOCURL;
 
   // iterate though the display items and add up the bounding boxes of each.
   // This will allow the total area of the frames within the range to be
   // determined. To do this, remove an item from the bottom of the list, check
   // whether it should be part of the range, and if so, append it to the top
   // of the temporary list tmpList. If the item is a text frame at the end of
@@ -4738,19 +4732,17 @@ RangePaintInfo*
 PresShell::CreateRangePaintInfo(nsIDOMRange* aRange,
                                 nsRect& aSurfaceRect,
                                 bool aForPrimarySelection)
 {
   NS_TIME_FUNCTION_WITH_DOCURL;
 
   RangePaintInfo* info = nsnull;
 
-  nsCOMPtr<nsIRange> range = do_QueryInterface(aRange);
-  if (!range)
-    return nsnull;
+  nsRange* range = static_cast<nsRange*>(aRange);
 
   nsIFrame* ancestorFrame;
   nsIFrame* rootFrame = GetRootFrame();
 
   // If the start or end of the range is the document, just use the root
   // frame, otherwise get the common ancestor of the two endpoints of the
   // range.
   nsINode* startParent = range->GetStartParent();
@@ -4957,18 +4949,17 @@ PresShell::RenderNode(nsIDOMNode* aNode,
   nsRect area;
   nsTArray<nsAutoPtr<RangePaintInfo> > rangeItems;
 
   // nothing to draw if the node isn't in a document
   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
   if (!node->IsInDoc())
     return nsnull;
   
-  nsCOMPtr<nsIDOMRange> range;
-  NS_NewRange(getter_AddRefs(range));
+  nsRefPtr<nsRange> range = new nsRange();
   if (NS_FAILED(range->SelectNode(aNode)))
     return nsnull;
 
   RangePaintInfo* info = CreateRangePaintInfo(range, area, false);
   if (info && !rangeItems.AppendElement(info)) {
     delete info;
     return nsnull;
   }
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -69,17 +69,17 @@
 #include "nsIWidget.h"
 #include "nsStyleSet.h"
 #include "nsPresArena.h"
 #include "nsFrameSelection.h"
 #include "nsGUIEvent.h"
 #include "nsContentUtils.h"
 #include "nsRefreshDriver.h"
 
-class nsIRange;
+class nsRange;
 class nsIDragService;
 class nsCSSStyleSheet;
 
 struct RangePaintInfo;
 struct nsCallbackEventRequest;
 #ifdef MOZ_REFLOW_PERF
 class ReflowCountMgr;
 #endif
@@ -543,17 +543,17 @@ protected:
   nsresult SetPrefNoFramesRule(void);
 
   // methods for painting a range to an offscreen buffer
 
   // given a display list, clip the items within the list to
   // the range
   nsRect ClipListToRange(nsDisplayListBuilder *aBuilder,
                          nsDisplayList* aList,
-                         nsIRange* aRange);
+                         nsRange* aRange);
 
   // create a RangePaintInfo for the range aRange containing the
   // display list needed to paint the range to a surface
   RangePaintInfo* CreateRangePaintInfo(nsIDOMRange* aRange,
                                        nsRect& aSurfaceRect,
                                        bool aForPrimarySelection);
 
   /*
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -52,17 +52,16 @@
 #include "nsGenericHTMLElement.h"
 #include "nsIComponentManager.h"
 #include "nsIContentIterator.h"
 #include "nsIContentSerializer.h"
 #include "nsIContentViewer.h"
 #include "nsIController.h"
 #include "nsIControllers.h"
 #include "nsIDOMDOMImplementation.h"
-#include "nsIDOMRange.h"
 #include "nsIDocument.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIFactory.h"
 #include "nsIFrameUtil.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsIHTMLToTextSink.h"
 #include "nsILayoutDebugger.h"
 #include "nsINameSpaceManager.h"
@@ -419,17 +418,16 @@ nsresult NS_NewTreeBoxObject(nsIBoxObjec
 nsresult NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult);
 nsresult NS_NewCanvasRenderingContext2DThebes(nsIDOMCanvasRenderingContext2D** aResult);
 nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult);
 
 nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult);
 
 nsresult NS_NewDomSelection(nsISelection** aResult);
 nsresult NS_NewContentViewer(nsIContentViewer** aResult);
-nsresult NS_NewRange(nsIDOMRange** aResult);
 nsresult NS_NewRangeUtils(nsIRangeUtils** aResult);
 nsresult NS_NewContentIterator(nsIContentIterator** aResult);
 nsresult NS_NewPreContentIterator(nsIContentIterator** aResult);
 nsresult NS_NewGenRegularIterator(nsIContentIterator** aResult);
 nsresult NS_NewContentSubtreeIterator(nsIContentIterator** aResult);
 nsresult NS_NewGenSubtreeIterator(nsIContentIterator** aInstancePtrResult);
 nsresult NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult);
 nsresult NS_NewHTMLCopyTextEncoder(nsIDocumentEncoder** aResult);
@@ -488,17 +486,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(inDOMUtil
 
 MAKE_CTOR(CreateNameSpaceManager,         nsINameSpaceManager,         NS_GetNameSpaceManager)
 MAKE_CTOR(CreateContentViewer,            nsIContentViewer,            NS_NewContentViewer)
 MAKE_CTOR(CreateHTMLDocument,             nsIDocument,                 NS_NewHTMLDocument)
 MAKE_CTOR(CreateXMLDocument,              nsIDocument,                 NS_NewXMLDocument)
 MAKE_CTOR(CreateSVGDocument,              nsIDocument,                 NS_NewSVGDocument)
 MAKE_CTOR(CreateImageDocument,            nsIDocument,                 NS_NewImageDocument)
 MAKE_CTOR(CreateDOMSelection,             nsISelection,                NS_NewDomSelection)
-MAKE_CTOR(CreateRange,                    nsIDOMRange,                 NS_NewRange)
 MAKE_CTOR(CreateRangeUtils,               nsIRangeUtils,               NS_NewRangeUtils)
 MAKE_CTOR(CreateContentIterator,          nsIContentIterator,          NS_NewContentIterator)
 MAKE_CTOR(CreatePreContentIterator,       nsIContentIterator,          NS_NewPreContentIterator)
 MAKE_CTOR(CreateSubtreeIterator,          nsIContentIterator,          NS_NewContentSubtreeIterator)
 // CreateHTMLImgElement, see below
 // CreateHTMLOptionElement, see below
 // CreateHTMLAudioElement, see below
 MAKE_CTOR(CreateTextEncoder,              nsIDocumentEncoder,          NS_NewTextEncoder)
@@ -682,17 +679,16 @@ NS_DEFINE_NAMED_CID(IN_CSSVALUESEARCH_CI
 NS_DEFINE_NAMED_CID(IN_DOMUTILS_CID);
 NS_DEFINE_NAMED_CID(NS_NAMESPACEMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_CONTENT_VIEWER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLDOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_XMLDOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_SVGDOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_IMAGEDOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_DOMSELECTION_CID);
-NS_DEFINE_NAMED_CID(NS_RANGE_CID);
 NS_DEFINE_NAMED_CID(NS_RANGEUTILS_CID);
 NS_DEFINE_NAMED_CID(NS_CONTENTITERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_PRECONTENTITERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_SUBTREEITERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLIMAGEELEMENT_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLOPTIONELEMENT_CID);
 #ifdef MOZ_MEDIA
 NS_DEFINE_NAMED_CID(NS_HTMLAUDIOELEMENT_CID);
@@ -954,17 +950,16 @@ static const mozilla::Module::CIDEntry k
   { &kIN_DOMUTILS_CID, false, NULL, inDOMUtilsConstructor },
   { &kNS_NAMESPACEMANAGER_CID, false, NULL, CreateNameSpaceManager },
   { &kNS_CONTENT_VIEWER_CID, false, NULL, CreateContentViewer },
   { &kNS_HTMLDOCUMENT_CID, false, NULL, CreateHTMLDocument },
   { &kNS_XMLDOCUMENT_CID, false, NULL, CreateXMLDocument },
   { &kNS_SVGDOCUMENT_CID, false, NULL, CreateSVGDocument },
   { &kNS_IMAGEDOCUMENT_CID, false, NULL, CreateImageDocument },
   { &kNS_DOMSELECTION_CID, false, NULL, CreateDOMSelection },
-  { &kNS_RANGE_CID, false, NULL, CreateRange },
   { &kNS_RANGEUTILS_CID, false, NULL, CreateRangeUtils },
   { &kNS_CONTENTITERATOR_CID, false, NULL, CreateContentIterator },
   { &kNS_PRECONTENTITERATOR_CID, false, NULL, CreatePreContentIterator },
   { &kNS_SUBTREEITERATOR_CID, false, NULL, CreateSubtreeIterator },
   { &kNS_HTMLIMAGEELEMENT_CID, false, NULL, CreateHTMLImgElement },
   { &kNS_HTMLOPTIONELEMENT_CID, false, NULL, CreateHTMLOptionElement },
 #ifdef MOZ_MEDIA
   { &kNS_HTMLAUDIOELEMENT_CID, false, NULL, CreateHTMLAudioElement },
@@ -1089,17 +1084,16 @@ static const mozilla::Module::ContractID
   { "@mozilla.org/inspector/deep-tree-walker;1", &kIN_DEEPTREEWALKER_CID },
   { "@mozilla.org/inspector/flasher;1", &kIN_FLASHER_CID },
   { "@mozilla.org/inspector/search;1?type=cssvalue", &kIN_CSSVALUESEARCH_CID },
   { "@mozilla.org/inspector/dom-utils;1", &kIN_DOMUTILS_CID },
   { NS_NAMESPACEMANAGER_CONTRACTID, &kNS_NAMESPACEMANAGER_CID },
   { "@mozilla.org/xml/xml-document;1", &kNS_XMLDOCUMENT_CID },
   { "@mozilla.org/svg/svg-document;1", &kNS_SVGDOCUMENT_CID },
   { "@mozilla.org/content/dom-selection;1", &kNS_DOMSELECTION_CID },
-  { "@mozilla.org/content/range;1", &kNS_RANGE_CID },
   { "@mozilla.org/content/range-utils;1", &kNS_RANGEUTILS_CID },
   { "@mozilla.org/content/post-content-iterator;1", &kNS_CONTENTITERATOR_CID },
   { "@mozilla.org/content/pre-content-iterator;1", &kNS_PRECONTENTITERATOR_CID },
   { "@mozilla.org/content/subtree-content-iterator;1", &kNS_SUBTREEITERATOR_CID },
   { NS_HTMLIMGELEMENT_CONTRACTID, &kNS_HTMLIMAGEELEMENT_CID },
   { NS_HTMLOPTIONELEMENT_CONTRACTID, &kNS_HTMLOPTIONELEMENT_CID },
 #ifdef MOZ_MEDIA
   { NS_HTMLAUDIOELEMENT_CONTRACTID, &kNS_HTMLAUDIOELEMENT_CID },
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -109,19 +109,16 @@
 #include "nsFocusManager.h"
 #include "nsTextEditRules.h"
 #include "nsPresState.h"
 
 #include "mozilla/FunctionTimer.h"
 
 #define DEFAULT_COLUMN_WIDTH 20
 
-#include "nsContentCID.h"
-static NS_DEFINE_IID(kRangeCID,     NS_RANGE_CID);
-
 nsIFrame*
 NS_NewTextControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsTextControlFrame(aPresShell, aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsTextControlFrame)
 
@@ -850,19 +847,17 @@ nsTextControlFrame::SetSelectionInternal
                                          nsIDOMNode *aEndNode,
                                          PRInt32 aEndOffset,
                                          nsITextControlFrame::SelectionDirection aDirection)
 {
   // Create a new range to represent the new selection.
   // Note that we use a new range to avoid having to do
   // isIncreasing checks to avoid possible errors.
 
-  nsCOMPtr<nsIDOMRange> range = do_CreateInstance(kRangeCID);
-  NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
-
+  nsRefPtr<nsRange> range = new nsRange();
   nsresult rv = range->SetStart(aStartNode, aStartOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = range->SetEnd(aEndNode, aEndOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get the selection, clear it and add the new range to it!
   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
--- a/layout/generic/nsFrameSelection.h
+++ b/layout/generic/nsFrameSelection.h
@@ -42,17 +42,17 @@
 
 #include "nsIFrame.h"
 #include "nsIContent.h"
 #include "nsISelectionController.h"
 #include "nsITableLayout.h"
 #include "nsITableCellLayout.h"
 #include "nsIDOMElement.h"
 #include "nsGUIEvent.h"
-#include "nsIRange.h"
+#include "nsRange.h"
 
 // IID for the nsFrameSelection interface
 // 3c6ae2d0-4cf1-44a1-9e9d-2411867f19c6
 #define NS_FRAME_SELECTION_IID      \
 { 0x3c6ae2d0, 0x4cf1, 0x44a1, \
   { 0x9e, 0x9d, 0x24, 0x11, 0x86, 0x7f, 0x19, 0xc6 } }
 
 #ifdef IBMBIDI // Constant for Set/Get CaretBidiLevel
@@ -679,39 +679,39 @@ private:
                          PRInt32 aEndRowIndex, PRInt32 aEndColumnIndex,
                          bool aRemoveOutsideOfCellRange);
 
   nsresult GetCellIndexes(nsIContent *aCell, PRInt32 &aRowIndex, PRInt32 &aColIndex);
 
   // Get our first range, if its first selected node is a cell.  If this does
   // not return null, then the first node in the returned range is a cell
   // (according to GetFirstCellNodeInRange).
-  nsIRange* GetFirstCellRange();
+  nsRange* GetFirstCellRange();
   // Get our next range, if its first selected node is a cell.  If this does
   // not return null, then the first node in the returned range is a cell
   // (according to GetFirstCellNodeInRange).
-  nsIRange* GetNextCellRange();
-  nsIContent* GetFirstCellNodeInRange(nsIRange *aRange) const;
+  nsRange* GetNextCellRange();
+  nsIContent* GetFirstCellNodeInRange(nsRange *aRange) const;
   // Returns non-null table if in same table, null otherwise
   nsIContent* IsInSameTable(nsIContent *aContent1, nsIContent *aContent2) const;
   // Might return null
   nsIContent* GetParentTable(nsIContent *aCellNode) const;
   nsresult CreateAndAddRange(nsINode *aParentNode, PRInt32 aOffset);
   nsresult ClearNormalSelection();
 
   nsCOMPtr<nsINode> mCellParent; //used to snap to table selection
   nsCOMPtr<nsIContent> mStartSelectedCell;
   nsCOMPtr<nsIContent> mEndSelectedCell;
   nsCOMPtr<nsIContent> mAppendStartSelectedCell;
   nsCOMPtr<nsIContent> mUnselectCellOnMouseUp;
   PRInt32  mSelectingTableCellMode;
   PRInt32  mSelectedCellIndex;
 
   // maintain selection
-  nsCOMPtr<nsIRange> mMaintainRange;
+  nsRefPtr<nsRange> mMaintainRange;
   nsSelectionAmount mMaintainedAmount;
 
   //batching
   PRInt32 mBatching;
     
   nsIContent *mLimiter;     //limit selection navigation to a child of this node.
   nsIContent *mAncestorLimiter; // Limit selection navigation to a descendant of
                                 // this node.
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -129,17 +129,17 @@ class nsAutoScrollTimer;
 static bool IsValidSelectionPoint(nsFrameSelection *aFrameSel, nsINode *aNode);
 
 static nsIAtom *GetTag(nsINode *aNode);
 // returns the parent
 static nsINode* ParentOffset(nsINode *aNode, PRInt32 *aChildOffset);
 static nsINode* GetCellParent(nsINode *aDomNode);
 
 #ifdef PRINT_RANGE
-static void printRange(nsIRange *aDomRange);
+static void printRange(nsRange *aDomRange);
 #define DEBUG_OUT_RANGE(x)  printRange(x)
 #else
 #define DEBUG_OUT_RANGE(x)  
 #endif //MOZ_DEBUG
 
 
 
 //#define DEBUG_SELECTION // uncomment for printf describing every collapse and extend.
@@ -159,20 +159,21 @@ struct CachedOffsetForFrame {
   nsPoint      mCachedFrameOffset;      // cached frame offset
   nsIFrame*    mLastCaretFrame;         // store the frame the caret was last drawn in.
   PRInt32      mLastContentOffset;      // store last content offset
   bool mCanCacheFrameOffset;    // cached frame offset is valid?
 };
 
 struct RangeData
 {
-  RangeData(nsIRange* aRange) :
-    mRange(aRange) {}
-
-  nsCOMPtr<nsIRange> mRange;
+  RangeData(nsRange* aRange)
+    : mRange(aRange)
+  {}
+
+  nsRefPtr<nsRange> mRange;
   nsTextRangeStyle mTextRangeStyle;
 };
 
 static RangeData sEmptyData(nsnull);
 
 // Note, the ownership of nsTypedSelection depends on which way the object is
 // created. When nsFrameSelection has created nsTypedSelection,
 // addreffing/releasing nsTypedSelection object is aggregated to
@@ -214,49 +215,43 @@ public:
     SCROLL_DO_FLUSH = 1<<3
   };
   // aDoFlush only matters if aIsSynchronous is true.  If not, we'll just flush
   // when the scroll event fires so we make sure to scroll to the right place.
   nsresult      ScrollIntoView(SelectionRegion aRegion,
                                PRInt16 aVPercent = NS_PRESSHELL_SCROLL_ANYWHERE,
                                PRInt16 aHPercent = NS_PRESSHELL_SCROLL_ANYWHERE,
                                PRInt32 aFlags = 0);
-  nsresult      SubtractRange(RangeData* aRange, nsIRange* aSubtract,
+  nsresult      SubtractRange(RangeData* aRange, nsRange* aSubtract,
                               nsTArray<RangeData>* aOutput);
-  nsresult      AddItem(nsIRange *aRange, PRInt32* aOutIndex = nsnull);
-  nsresult      RemoveItem(nsIRange *aRange);
+  nsresult      AddItem(nsRange *aRange, PRInt32* aOutIndex = nsnull);
+  nsresult      RemoveItem(nsRange *aRange);
   nsresult      RemoveCollapsedRanges();
   nsresult      Clear(nsPresContext* aPresContext);
   nsresult      Collapse(nsINode* aParentNode, PRInt32 aOffset);
   nsresult      Extend(nsINode* aParentNode, PRInt32 aOffset);
-  nsresult      AddRange(nsIRange* aRange);
-  // The nsIRange version of RemoveRange assumes the caller is holding
-  // a strong reference to aRange.
-  nsresult      RemoveRange(nsIRange* aRange);
-  nsIRange*     GetRangeAt(PRInt32 aIndex);
-  nsresult      GetTableSelectionType(nsIRange* aRange,
-                                      PRInt32* aTableSelectionType);
+  nsRange*      GetRangeAt(PRInt32 aIndex);
 
   // methods for convenience. Note, these don't addref
   nsINode*     GetAnchorNode();
   PRInt32      GetAnchorOffset();
 
   nsINode*     GetFocusNode();
   PRInt32      GetFocusOffset();
 
   // Get the anchor-to-focus range if we don't care which end is
   // anchor and which end is focus.
-  const nsIRange* GetAnchorFocusRange() const {
+  const nsRange* GetAnchorFocusRange() const {
     return mAnchorFocusRange;
   }
 
   nsDirection  GetDirection(){return mDirection;}
   void         SetDirection(nsDirection aDir){mDirection = aDir;}
-  nsresult     CopyRangeToAnchorFocus(nsIRange *aRange);
-  void         ReplaceAnchorFocusRange(nsIRange *aRange);
+  nsresult     CopyRangeToAnchorFocus(nsRange *aRange);
+  void         ReplaceAnchorFocusRange(nsRange *aRange);
 
   //  NS_IMETHOD   GetPrimaryFrameForRangeEndpoint(nsIDOMNode *aNode, PRInt32 aOffset, bool aIsEndNode, nsIFrame **aResultFrame);
   NS_IMETHOD   GetPrimaryFrameForAnchorNode(nsIFrame **aResultFrame);
   NS_IMETHOD   GetPrimaryFrameForFocusNode(nsIFrame **aResultFrame, PRInt32 *aOffset, bool aVisual);
   NS_IMETHOD   LookUpSelection(nsIContent *aContent, PRInt32 aContentOffset, PRInt32 aContentLength,
                              SelectionDetails **aReturnDetails, SelectionType aType, bool aSlowCheck);
   NS_IMETHOD   Repaint(nsPresContext* aPresContext);
 
@@ -304,32 +299,28 @@ private:
   };
 
   void setAnchorFocusRange(PRInt32 aIndex); // pass in index into mRanges;
                                             // negative value clears
                                             // mAnchorFocusRange
   nsresult     SelectAllFramesForContent(nsIContentIterator *aInnerIter,
                                nsIContent *aContent,
                                bool aSelected);
-  nsresult     selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bool aSelect);
-  nsresult     getTableCellLocationFromRange(nsIRange *aRange, PRInt32 *aSelectionType, PRInt32 *aRow, PRInt32 *aCol);
-  nsresult     addTableCellRange(nsIRange *aRange, bool *aDidAddRange, PRInt32 *aOutIndex);
+  nsresult     selectFrames(nsPresContext* aPresContext, nsRange *aRange, bool aSelect);
+  nsresult     getTableCellLocationFromRange(nsRange *aRange, PRInt32 *aSelectionType, PRInt32 *aRow, PRInt32 *aCol);
+  nsresult     addTableCellRange(nsRange *aRange, bool *aDidAddRange, PRInt32 *aOutIndex);
 
   nsresult FindInsertionPoint(
       nsTArray<RangeData>* aElementArray,
       nsINode* aPointNode, PRInt32 aPointOffset,
-      nsresult (*aComparator)(nsINode*,PRInt32,nsIRange*,PRInt32*),
+      nsresult (*aComparator)(nsINode*,PRInt32,nsRange*,PRInt32*),
       PRInt32* aPoint);
   bool EqualsRangeAtPoint(nsINode* aBeginNode, PRInt32 aBeginOffset,
                             nsINode* aEndNode, PRInt32 aEndOffset,
                             PRInt32 aRangeIndex);
-  nsresult GetRangesForIntervalCOMArray(nsINode* aBeginNode, PRInt32 aBeginOffset,
-                                        nsINode* aEndNode, PRInt32 aEndOffset,
-                                        bool aAllowAdjacent,
-                                        nsCOMArray<nsIRange>* aRanges);
   void GetIndicesForInterval(nsINode* aBeginNode, PRInt32 aBeginOffset,
                              nsINode* aEndNode, PRInt32 aEndOffset,
                              bool aAllowAdjacent,
                              PRInt32 *aStartIndex, PRInt32 *aEndIndex);
   RangeData* FindRangeData(nsIDOMRange* aRange);
 
   // These are the ranges inside this selection. They are kept sorted in order
   // of DOM start position.
@@ -341,17 +332,17 @@ private:
   //
   // Inserting a new range requires finding the overlapping interval, requiring
   // two binary searches plus up to an additional 6 DOM comparisons. If this
   // proves to be a performance concern, then an interval tree may be a
   // possible solution, allowing the calculation of the overlap interval in
   // O(log n) time, though this would require rebalancing and other overhead.
   nsTArray<RangeData> mRanges;
 
-  nsCOMPtr<nsIRange> mAnchorFocusRange;
+  nsRefPtr<nsRange> mAnchorFocusRange;
   nsRefPtr<nsFrameSelection> mFrameSelection;
   nsWeakPtr mPresShellWeak;
   nsRefPtr<nsAutoScrollTimer> mAutoScrollTimer;
   nsCOMArray<nsISelectionListener> mSelectionListeners;
   nsRevocableEventPtr<ScrollSelectionIntoViewEvent> mScrollEvent;
   CachedOffsetForFrame *mCachedOffsetForFrame;
   nsDirection mDirection;
   SelectionType mType;
@@ -382,17 +373,17 @@ see the nsIEnumerator for more details*/
   NS_DECL_ISUPPORTS
 
   NS_DECL_NSIENUMERATOR
 
   NS_DECL_NSIBIDIRECTIONALENUMERATOR
 
 /*END nsIEnumerator interfaces*/
 /*BEGIN Helper Methods*/
-  nsIRange* CurrentItem();
+  nsRange* CurrentItem();
 /*END Helper Methods*/
 private:
   friend class nsTypedSelection;
 
   //lame lame lame if delete from document goes away then get rid of this unless its debug
   friend class nsFrameSelection;
 
   nsSelectionIterator(nsTypedSelection *);
@@ -660,26 +651,26 @@ nsSelectionIterator::Last()
   return NS_OK;
 }
 
 
 
 NS_IMETHODIMP 
 nsSelectionIterator::CurrentItem(nsISupports **aItem)
 {
-  *aItem = CurrentItem();
+  *aItem = static_cast<nsIDOMRange*>(CurrentItem());
   if (!*aItem) {
     return NS_ERROR_FAILURE;
   }
 
   NS_ADDREF(*aItem);
   return NS_OK;
 }
 
-nsIRange*
+nsRange*
 nsSelectionIterator::CurrentItem()
 {
   return mDomSelection->mRanges.SafeElementAt(mIndex, sEmptyData).mRange;
 }
 
 
 
 NS_IMETHODIMP
@@ -772,17 +763,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
                                                          nsISelection)
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCellParent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStartSelectedCell)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEndSelectedCell)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAppendStartSelectedCell)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mUnselectCellOnMouseUp)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMaintainRange)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mMaintainRange, nsIDOMRange)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameSelection)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameSelection)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameSelection)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
@@ -1001,17 +992,17 @@ void
 nsFrameSelection::UndefineCaretBidiLevel()
 {
   mCaretBidiLevel |= BIDI_LEVEL_UNDEFINED;
 }
 #endif
 
 
 #ifdef PRINT_RANGE
-void printRange(nsIRange *aDomRange)
+void printRange(nsRange *aDomRange)
 {
   if (!aDomRange)
   {
     printf("NULL nsIDOMRange\n");
   }
   nsINode* startNode = aDomRange->GetStartParent();
   nsINode* endNode = aDomRange->GetEndParent();
   PRInt32 startOffset = aDomRange->StartOffset();
@@ -1149,31 +1140,31 @@ nsFrameSelection::MoveCaret(PRUint32    
   }
 #endif
 
   if (!isCollapsed && !aContinueSelection && caretStyle == 2) {
     switch (aKeycode){
       case nsIDOMKeyEvent::DOM_VK_LEFT  :
       case nsIDOMKeyEvent::DOM_VK_UP    :
         {
-          const nsIRange* anchorFocusRange = sel->GetAnchorFocusRange();
+          const nsRange* anchorFocusRange = sel->GetAnchorFocusRange();
           if (anchorFocusRange) {
             sel->Collapse(anchorFocusRange->GetStartParent(),
                           anchorFocusRange->StartOffset());
           }
           mHint = HINTRIGHT;
           sel->ScrollIntoView(nsISelectionController::SELECTION_FOCUS_REGION,
                               false, false);
           return NS_OK;
         }
 
       case nsIDOMKeyEvent::DOM_VK_RIGHT :
       case nsIDOMKeyEvent::DOM_VK_DOWN  :
         {
-          const nsIRange* anchorFocusRange = sel->GetAnchorFocusRange();
+          const nsRange* anchorFocusRange = sel->GetAnchorFocusRange();
           if (anchorFocusRange) {
             sel->Collapse(anchorFocusRange->GetEndParent(),
                           anchorFocusRange->EndOffset());
           }
           mHint = HINTLEFT;
           sel->ScrollIntoView(nsISelectionController::SELECTION_FOCUS_REGION,
                               false, false);
           return NS_OK;
@@ -1515,17 +1506,17 @@ nsresult
 nsFrameSelection::MaintainSelection(nsSelectionAmount aAmount)
 {
   PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
   if (!mDomSelections[index])
     return NS_ERROR_NULL_POINTER;
 
   mMaintainedAmount = aAmount;
 
-  const nsIRange* anchorFocusRange =
+  const nsRange* anchorFocusRange =
     mDomSelections[index]->GetAnchorFocusRange();
   if (anchorFocusRange) {
     return anchorFocusRange->CloneRange(getter_AddRefs(mMaintainRange));
   }
 
   mMaintainRange = nsnull;
   return NS_OK;
 }
@@ -1820,17 +1811,17 @@ nsFrameSelection::TakeFocus(nsIContent *
     bool changes = mChangesDuringBatching;
     mBatching = 1;
 
     if (aMultipleSelection) {
       // Remove existing collapsed ranges as there's no point in having 
       // non-anchor/focus collapsed ranges.
       mDomSelections[index]->RemoveCollapsedRanges();
 
-      nsCOMPtr<nsIRange> newRange = new nsRange();
+      nsRefPtr<nsRange> newRange = new nsRange();
 
       newRange->SetStart(aNewFocus, aContentOffset);
       newRange->SetEnd(aNewFocus, aContentOffset);
       mDomSelections[index]->AddRange(newRange);
       mBatching = batching;
       mChangesDuringBatching = changes;
     }
     else
@@ -2322,17 +2313,17 @@ nsFrameSelection::ClearNormalSelection()
   PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
   if (!mDomSelections[index])
     return NS_ERROR_NULL_POINTER;
 
   return mDomSelections[index]->RemoveAllRanges();
 }
 
 static nsIContent*
-GetFirstSelectedContent(nsIRange* aRange)
+GetFirstSelectedContent(nsRange* aRange)
 {
   if (!aRange) {
     return nsnull;
   }
 
   NS_PRECONDITION(aRange->GetStartParent(), "Must have start parent!");
   NS_PRECONDITION(aRange->GetStartParent()->IsElement(),
                   "Unexpected parent");
@@ -2604,17 +2595,17 @@ printf("HandleTableSelection: Ending cel
         nsINode* previousCellParent = nsnull;
 #ifdef DEBUG_TABLE_SELECTION
 printf("HandleTableSelection: Unselecting mUnselectCellOnMouseUp; rangeCount=%d\n", rangeCount);
 #endif
         for( PRInt32 i = 0; i < rangeCount; i++)
         {
           // Strong reference, because sometimes we want to remove
           // this range, and then we might be the only owner.
-          nsCOMPtr<nsIRange> range = mDomSelections[index]->GetRangeAt(i);
+          nsRefPtr<nsRange> range = mDomSelections[index]->GetRangeAt(i);
           if (!range) return NS_ERROR_NULL_POINTER;
 
           nsINode* parent = range->GetStartParent();
           if (!parent) return NS_ERROR_NULL_POINTER;
 
           PRInt32 offset = range->StartOffset();
           // Be sure previous selection is a table cell
           nsIContent* child = parent->GetChildAt(offset);
@@ -2715,17 +2706,17 @@ nsFrameSelection::UnselectCells(nsIConte
     return NS_ERROR_FAILURE;
 
   PRInt32 minRowIndex = NS_MIN(aStartRowIndex, aEndRowIndex);
   PRInt32 maxRowIndex = NS_MAX(aStartRowIndex, aEndRowIndex);
   PRInt32 minColIndex = NS_MIN(aStartColumnIndex, aEndColumnIndex);
   PRInt32 maxColIndex = NS_MAX(aStartColumnIndex, aEndColumnIndex);
 
   // Strong reference because we sometimes remove the range
-  nsCOMPtr<nsIRange> range = GetFirstCellRange();
+  nsRefPtr<nsRange> range = GetFirstCellRange();
   nsIContent* cellNode = GetFirstSelectedContent(range);
   NS_PRECONDITION(!range || cellNode, "Must have cellNode if had a range");
 
   PRInt32 curRowIndex, curColIndex;
   while (cellNode)
   {
     nsresult result = GetCellIndexes(cellNode, curRowIndex, curColIndex);
     if (NS_FAILED(result))
@@ -2978,17 +2969,17 @@ nsFrameSelection::SelectRowOrColumn(nsIC
   }
   while (cellElement);
 #endif
 
   return NS_OK;
 }
 
 nsIContent*
-nsFrameSelection::GetFirstCellNodeInRange(nsIRange *aRange) const
+nsFrameSelection::GetFirstCellNodeInRange(nsRange *aRange) const
 {
   if (!aRange) return nsnull;
 
   nsINode* startParent = aRange->GetStartParent();
   if (!startParent)
     return nsnull;
 
   PRInt32 offset = aRange->StartOffset();
@@ -2998,42 +2989,42 @@ nsFrameSelection::GetFirstCellNodeInRang
     return nsnull;
   // Don't return node if not a cell
   if (!IsCell(childContent))
     return nsnull;
 
   return childContent;
 }
 
-nsIRange*
+nsRange*
 nsFrameSelection::GetFirstCellRange()
 {
   PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
   if (!mDomSelections[index])
     return nsnull;
 
-  nsIRange* firstRange = mDomSelections[index]->GetRangeAt(0);
+  nsRange* firstRange = mDomSelections[index]->GetRangeAt(0);
   if (!GetFirstCellNodeInRange(firstRange)) {
     return nsnull;
   }
 
   // Setup for next cell
   mSelectedCellIndex = 1;
 
   return firstRange;
 }
 
-nsIRange*
+nsRange*
 nsFrameSelection::GetNextCellRange()
 {
   PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
   if (!mDomSelections[index])
     return nsnull;
 
-  nsIRange* range = mDomSelections[index]->GetRangeAt(mSelectedCellIndex);
+  nsRange* range = mDomSelections[index]->GetRangeAt(mSelectedCellIndex);
 
   // Get first node in next range of selection - test if it's a cell
   if (!GetFirstCellNodeInRange(range)) {
     return nsnull;
   }
 
   // Setup for next cell
   mSelectedCellIndex++;
@@ -3095,17 +3086,17 @@ nsFrameSelection::SelectCellElement(nsIC
 
   // Get child offset
   PRInt32 offset = parent->IndexOf(aCellElement);
 
   return CreateAndAddRange(parent, offset);
 }
 
 nsresult
-nsTypedSelection::getTableCellLocationFromRange(nsIRange *aRange, PRInt32 *aSelectionType, PRInt32 *aRow, PRInt32 *aCol)
+nsTypedSelection::getTableCellLocationFromRange(nsRange *aRange, PRInt32 *aSelectionType, PRInt32 *aRow, PRInt32 *aCol)
 {
   if (!aRange || !aSelectionType || !aRow || !aCol)
     return NS_ERROR_NULL_POINTER;
 
   *aSelectionType = nsISelectionPrivate::TABLESELECTION_NONE;
   *aRow = 0;
   *aCol = 0;
 
@@ -3137,17 +3128,17 @@ nsTypedSelection::getTableCellLocationFr
     return result;
   if (!cellLayout)
     return NS_ERROR_FAILURE;
 
   return cellLayout->GetCellIndexes(*aRow, *aCol);
 }
 
 nsresult
-nsTypedSelection::addTableCellRange(nsIRange *aRange, bool *aDidAddRange,
+nsTypedSelection::addTableCellRange(nsRange *aRange, bool *aDidAddRange,
                                     PRInt32 *aOutIndex)
 {  
   if (!aDidAddRange || !aOutIndex)
     return NS_ERROR_NULL_POINTER;
 
   *aDidAddRange = false;
   *aOutIndex = -1;
 
@@ -3177,47 +3168,40 @@ nsTypedSelection::addTableCellRange(nsIR
   if (mFrameSelection->mSelectingTableCellMode == TABLESELECTION_NONE)
     mFrameSelection->mSelectingTableCellMode = tableMode;
 
   *aDidAddRange = true;
   return AddItem(aRange, aOutIndex);
 }
 
 //TODO: Figure out TABLESELECTION_COLUMN and TABLESELECTION_ALLCELLS
-NS_IMETHODIMP
-nsTypedSelection::GetTableSelectionType(nsIDOMRange* aRange,
+nsresult
+nsTypedSelection::GetTableSelectionType(nsIDOMRange* aDOMRange,
                                         PRInt32* aTableSelectionType)
 {
-  nsCOMPtr<nsIRange> range = do_QueryInterface(aRange);
-  return GetTableSelectionType(range, aTableSelectionType);
-}
-
-nsresult
-nsTypedSelection::GetTableSelectionType(nsIRange* aRange,
-                                        PRInt32* aTableSelectionType)
-{
-  if (!aRange || !aTableSelectionType)
+  if (!aDOMRange || !aTableSelectionType)
     return NS_ERROR_NULL_POINTER;
+  nsRange* range = static_cast<nsRange*>(aDOMRange);
   
   *aTableSelectionType = nsISelectionPrivate::TABLESELECTION_NONE;
  
   // Must have access to frame selection to get cell info
   if(!mFrameSelection) return NS_OK;
 
-  nsINode* startNode = aRange->GetStartParent();
+  nsINode* startNode = range->GetStartParent();
   if (!startNode) return NS_ERROR_FAILURE;
   
-  nsINode* endNode = aRange->GetEndParent();
+  nsINode* endNode = range->GetEndParent();
   if (!endNode) return NS_ERROR_FAILURE;
 
   // Not a single selected node
   if (startNode != endNode) return NS_OK;
 
-  PRInt32 startOffset = aRange->StartOffset();
-  PRInt32 endOffset = aRange->EndOffset();
+  PRInt32 startOffset = range->StartOffset();
+  PRInt32 endOffset = range->EndOffset();
 
   // Not a single selected node
   if ((endOffset - startOffset) != 1)
     return NS_OK;
 
   nsIContent* startContent = static_cast<nsIContent*>(startNode);
   if (!(startNode->IsElement() && startContent->IsHTML())) {
     // Implies a check for being an element; if we ever make this work
@@ -3248,17 +3232,17 @@ nsTypedSelection::GetTableSelectionType(
   return NS_OK;
 }
 
 nsresult
 nsFrameSelection::CreateAndAddRange(nsINode *aParentNode, PRInt32 aOffset)
 {
   if (!aParentNode) return NS_ERROR_NULL_POINTER;
 
-  nsCOMPtr<nsIRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange();
 
   // Set range around child at given offset
   nsresult result = range->SetStart(aParentNode, aOffset);
   if (NS_FAILED(result)) return result;
   result = range->SetEnd(aParentNode, aOffset+1);
   if (NS_FAILED(result)) return result;
   
   PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
@@ -3329,17 +3313,17 @@ nsFrameSelection::DeleteFromDocument()
   // Get an iterator
   nsSelectionIterator iter(mDomSelections[index]);
   res = iter.First();
   if (NS_FAILED(res))
     return res;
 
   while (iter.IsDone())
   {
-    nsCOMPtr<nsIRange> range = iter.CurrentItem();
+    nsRefPtr<nsRange> range = iter.CurrentItem();
     res = range->DeleteContents();
     if (NS_FAILED(res))
       return res;
     iter.Next();
   }
 
   // Collapse to the new location.
   // If we deleted one character, then we move back one element.
@@ -3446,20 +3430,20 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mSelectionListeners)
   tmp->RemoveAllRanges();
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFrameSelection)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsTypedSelection)
   {
     PRUint32 i, count = tmp->mRanges.Length();
     for (i = 0; i < count; ++i) {
-      NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRanges[i].mRange)
+      NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mRanges[i].mRange, nsIDOMRange)
     }
   }
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAnchorFocusRange)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mAnchorFocusRange, nsIDOMRange)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFrameSelection)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mSelectionListeners)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 DOMCI_DATA(Selection, nsTypedSelection)
 
 // QueryInterface implementation for nsTypedSelection
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTypedSelection)
@@ -3582,17 +3566,17 @@ nsTypedSelection::GetFocusOffset()
     return mAnchorFocusRange->EndOffset();
   }
 
   return mAnchorFocusRange->StartOffset();
 }
 
 static nsresult
 CompareToRangeStart(nsINode* aCompareNode, PRInt32 aCompareOffset,
-                    nsIRange* aRange, PRInt32* aCmp)
+                    nsRange* aRange, PRInt32* aCmp)
 {
   nsINode* start = aRange->GetStartParent();
   NS_ENSURE_STATE(aCompareNode && start);
   // If the nodes that we're comparing are not in the same document,
   // assume that aCompareNode will fall at the end of the ranges.
   if (aCompareNode->GetCurrentDoc() != start->GetCurrentDoc() ||
       !start->GetCurrentDoc()) {
     *aCmp = 1;
@@ -3600,17 +3584,17 @@ CompareToRangeStart(nsINode* aCompareNod
     *aCmp = nsContentUtils::ComparePoints(aCompareNode, aCompareOffset,
                                           start, aRange->StartOffset());
   }
   return NS_OK;
 }
 
 static nsresult
 CompareToRangeEnd(nsINode* aCompareNode, PRInt32 aCompareOffset,
-                  nsIRange* aRange, PRInt32* aCmp)
+                  nsRange* aRange, PRInt32* aCmp)
 {
   nsINode* end = aRange->GetEndParent();
   NS_ENSURE_STATE(aCompareNode && end);
   // If the nodes that we're comparing are not in the same document,
   // assume that aCompareNode will fall at the end of the ranges.
   if (aCompareNode->GetCurrentDoc() != end->GetCurrentDoc() ||
       !end->GetCurrentDoc()) {
     *aCmp = 1;
@@ -3629,26 +3613,26 @@ CompareToRangeEnd(nsINode* aCompareNode,
 //
 //    If there is an item in the array equal to the input point, we will return
 //    the index of this item.
 
 nsresult
 nsTypedSelection::FindInsertionPoint(
     nsTArray<RangeData>* aElementArray,
     nsINode* aPointNode, PRInt32 aPointOffset,
-    nsresult (*aComparator)(nsINode*,PRInt32,nsIRange*,PRInt32*),
+    nsresult (*aComparator)(nsINode*,PRInt32,nsRange*,PRInt32*),
     PRInt32* aPoint)
 {
   *aPoint = 0;
   PRInt32 beginSearch = 0;
   PRInt32 endSearch = aElementArray->Length(); // one beyond what to check
   while (endSearch - beginSearch > 0) {
     PRInt32 center = (endSearch - beginSearch) / 2 + beginSearch;
 
-    nsIRange* range = (*aElementArray)[center].mRange;
+    nsRange* range = (*aElementArray)[center].mRange;
 
     PRInt32 cmp;
     nsresult rv = aComparator(aPointNode, aPointOffset, range, &cmp);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (cmp < 0) {        // point < cur
       endSearch = center;
     } else if (cmp > 0) { // point > cur
@@ -3665,20 +3649,20 @@ nsTypedSelection::FindInsertionPoint(
 // nsTypedSelection::SubtractRange
 //
 //    A helper function that subtracts aSubtract from aRange, and adds
 //    1 or 2 RangeData objects representing the remaining non-overlapping
 //    difference to aOutput. It is assumed that the caller has checked that
 //    aRange and aSubtract do indeed overlap
 
 nsresult
-nsTypedSelection::SubtractRange(RangeData* aRange, nsIRange* aSubtract,
+nsTypedSelection::SubtractRange(RangeData* aRange, nsRange* aSubtract,
                                 nsTArray<RangeData>* aOutput)
 {
-  nsIRange* range = aRange->mRange;
+  nsRange* range = aRange->mRange;
 
   // First we want to compare to the range start
   PRInt32 cmp;
   nsresult rv = CompareToRangeStart(range->GetStartParent(),
                                     range->StartOffset(),
                                     aSubtract, &cmp);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -3692,17 +3676,17 @@ nsTypedSelection::SubtractRange(RangeDat
   // If the existing range left overlaps the new range (aSubtract) then
   // cmp < 0, and cmp2 < 0
   // If it right overlaps the new range then cmp > 0 and cmp2 > 0
   // If it fully contains the new range, then cmp < 0 and cmp2 > 0
 
   if (cmp2 > 0) {
     // We need to add a new RangeData to the output, running from
     // the end of aSubtract to the end of range
-    nsIRange* postOverlap = new nsRange();
+    nsRange* postOverlap = new nsRange();
 
     rv =
       postOverlap->SetStart(aSubtract->GetEndParent(), aSubtract->EndOffset());
     NS_ENSURE_SUCCESS(rv, rv);
     rv =
      postOverlap->SetEnd(range->GetEndParent(), range->EndOffset());
     NS_ENSURE_SUCCESS(rv, rv);
     if (!postOverlap->Collapsed()) {
@@ -3710,17 +3694,17 @@ nsTypedSelection::SubtractRange(RangeDat
         return NS_ERROR_OUT_OF_MEMORY;
       (*aOutput)[0].mTextRangeStyle = aRange->mTextRangeStyle;
     }
   }
 
   if (cmp < 0) {
     // We need to add a new RangeData to the output, running from
     // the start of the range to the start of aSubtract
-    nsIRange* preOverlap = new nsRange();
+    nsRange* preOverlap = new nsRange();
 
     nsresult rv =
      preOverlap->SetStart(range->GetStartParent(), range->StartOffset());
     NS_ENSURE_SUCCESS(rv, rv);
     rv =
      preOverlap->SetEnd(aSubtract->GetStartParent(), aSubtract->StartOffset());
     NS_ENSURE_SUCCESS(rv, rv);
     
@@ -3730,17 +3714,17 @@ nsTypedSelection::SubtractRange(RangeDat
       (*aOutput)[0].mTextRangeStyle = aRange->mTextRangeStyle;
     }
   }
 
   return NS_OK;
 }
 
 nsresult
-nsTypedSelection::AddItem(nsIRange *aItem, PRInt32 *aOutIndex)
+nsTypedSelection::AddItem(nsRange *aItem, PRInt32 *aOutIndex)
 {
   if (!aItem)
     return NS_ERROR_NULL_POINTER;
   if (!aItem->IsPositioned())
     return NS_ERROR_UNEXPECTED;
   if (aOutIndex)
     *aOutIndex = -1;
 
@@ -3839,17 +3823,17 @@ nsTypedSelection::AddItem(nsIRange *aIte
     temp[i].mRange->SetInSelection(true);
   }
 
   *aOutIndex = startIndex + insertionPoint;
   return NS_OK;
 }
 
 nsresult
-nsTypedSelection::RemoveItem(nsIRange *aItem)
+nsTypedSelection::RemoveItem(nsRange *aItem)
 {
   if (!aItem)
     return NS_ERROR_NULL_POINTER;
 
   // Find the range's index & remove it. We could use FindInsertionPoint to
   // get O(log n) time, but that requires many expensive DOM comparisons.
   // For even several thousand items, this is probably faster because the
   // comparisons are so fast.
@@ -3918,114 +3902,88 @@ nsTypedSelection::GetType(PRInt16 *aType
 }
 
 // RangeMatches*Point
 //
 //    Compares the range beginning or ending point, and returns true if it
 //    exactly matches the given DOM point.
 
 static inline bool
-RangeMatchesBeginPoint(nsIRange* aRange, nsINode* aNode, PRInt32 aOffset)
+RangeMatchesBeginPoint(nsRange* aRange, nsINode* aNode, PRInt32 aOffset)
 {
   return aRange->GetStartParent() == aNode && aRange->StartOffset() == aOffset;
 }
 
 static inline bool
-RangeMatchesEndPoint(nsIRange* aRange, nsINode* aNode, PRInt32 aOffset)
+RangeMatchesEndPoint(nsRange* aRange, nsINode* aNode, PRInt32 aOffset)
 {
   return aRange->GetEndParent() == aNode && aRange->EndOffset() == aOffset;
 }
 
 // nsTypedSelection::EqualsRangeAtPoint
 //
 //    Utility method for checking equivalence of two ranges.
 
 bool
 nsTypedSelection::EqualsRangeAtPoint(
     nsINode* aBeginNode, PRInt32 aBeginOffset,
     nsINode* aEndNode, PRInt32 aEndOffset,
     PRInt32 aRangeIndex)
 {
   if (aRangeIndex >=0 && aRangeIndex < (PRInt32) mRanges.Length()) {
-    nsIRange* range = mRanges[aRangeIndex].mRange;
+    nsRange* range = mRanges[aRangeIndex].mRange;
     if (RangeMatchesBeginPoint(range, aBeginNode, aBeginOffset) &&
         RangeMatchesEndPoint(range, aEndNode, aEndOffset))
       return true;
   }
   return false;
 }
 
 // nsTypedSelection::GetRangesForInterval
 //
-//    XPCOM wrapper for the COMArray version
+//    XPCOM wrapper for the nsTArray version
 
 NS_IMETHODIMP
 nsTypedSelection::GetRangesForInterval(nsIDOMNode* aBeginNode, PRInt32 aBeginOffset,
                                        nsIDOMNode* aEndNode, PRInt32 aEndOffset,
                                        bool aAllowAdjacent,
                                        PRUint32 *aResultCount,
                                        nsIDOMRange ***aResults)
 {
   if (!aBeginNode || ! aEndNode || ! aResultCount || ! aResults)
     return NS_ERROR_NULL_POINTER;
 
   *aResultCount = 0;
   *aResults = nsnull;
-
-  nsCOMArray<nsIDOMRange> results;
-  nsresult rv = GetRangesForIntervalCOMArray(aBeginNode, aBeginOffset,
-                                             aEndNode, aEndOffset,
-                                             aAllowAdjacent,
-                                             &results);
+  
+  nsCOMPtr<nsINode> beginNode = do_QueryInterface(aBeginNode);
+  nsCOMPtr<nsINode> endNode = do_QueryInterface(aEndNode);
+
+  nsTArray<nsRange*> results;
+  nsresult rv = GetRangesForIntervalArray(beginNode, aBeginOffset,
+                                          endNode, aEndOffset,
+                                          aAllowAdjacent, &results);
   NS_ENSURE_SUCCESS(rv, rv);
-  if (results.Count() == 0)
+  *aResultCount = results.Length();
+  if (*aResultCount == 0) {
     return NS_OK;
+  }
 
   *aResults = static_cast<nsIDOMRange**>
-                         (nsMemory::Alloc(sizeof(nsIDOMRange*) * results.Count()));
+                         (nsMemory::Alloc(sizeof(nsIDOMRange*) * *aResultCount));
   NS_ENSURE_TRUE(*aResults, NS_ERROR_OUT_OF_MEMORY);
 
-  *aResultCount = results.Count();
-  for (PRInt32 i = 0; i < results.Count(); i ++)
+  for (PRUint32 i = 0; i < *aResultCount; i++)
     NS_ADDREF((*aResults)[i] = results[i]);
   return NS_OK;
 }
 
-// nsTypedSelection::GetRangesForIntervalCOMArray
+// nsTypedSelection::GetRangesForIntervalArray
 //
-//    Fills a COM array with the ranges overlapping the range specified by
-//    the given endpoints. Ranges in the selection exactly adjacent to the
-//    input range are not returned unless aAllowAdjacent is set.
-
-NS_IMETHODIMP
-nsTypedSelection::GetRangesForIntervalCOMArray(nsIDOMNode* aBeginNode, PRInt32 aBeginOffset,
-                                               nsIDOMNode* aEndNode, PRInt32 aEndOffset,
-                                               bool aAllowAdjacent,
-                                               nsCOMArray<nsIDOMRange>* aRanges)
-{
-  nsCOMPtr<nsINode> begin = do_QueryInterface(aBeginNode);
-  nsCOMPtr<nsINode> end = do_QueryInterface(aEndNode);
-  nsCOMArray<nsIRange> ranges;
-  nsresult rv = GetRangesForIntervalCOMArray(begin, aBeginOffset,
-                                             end, aEndOffset,
-                                             aAllowAdjacent, &ranges);
-  NS_ENSURE_SUCCESS(rv, rv);
-  for (PRInt32 i = 0; i < ranges.Count(); ++i) {
-    nsCOMPtr<nsIDOMRange> r = do_QueryInterface(ranges[i]);
-    if (!aRanges->AppendObject(r)) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  return NS_OK;
-}
-
-// nsTypedSelection::GetRangesForIntervalCOMArray
-//
-//    Fills a COM array with the ranges overlapping the range specified by
+//    Fills a nsTArray with the ranges overlapping the range specified by
 //    the given endpoints. Ranges in the selection exactly adjacent to the
 //    input range are not returned unless aAllowAdjacent is set.
 //
 //    For example, if the following ranges were in the selection
 //    (assume everything is within the same node)
 //
 //    Start Offset: 0 2 7 9
 //      End Offset: 2 5 9 10
@@ -4034,39 +3992,39 @@ nsTypedSelection::GetRangesForIntervalCO
 //    aAllowAdjacent set, all the ranges should be returned. If
 //    aAllowAdjacent was false, the ranges [2, 5] and [7, 9] only
 //    should be returned
 //
 //    Now that overlapping ranges are disallowed, there can be a maximum of
 //    2 adjacent ranges
 
 nsresult
-nsTypedSelection::GetRangesForIntervalCOMArray(nsINode* aBeginNode, PRInt32 aBeginOffset,
-                                               nsINode* aEndNode, PRInt32 aEndOffset,
-                                               bool aAllowAdjacent,
-                                               nsCOMArray<nsIRange>* aRanges)
+nsTypedSelection::GetRangesForIntervalArray(nsINode* aBeginNode, PRInt32 aBeginOffset,
+                                            nsINode* aEndNode, PRInt32 aEndOffset,
+                                            bool aAllowAdjacent,
+                                            nsTArray<nsRange*>* aRanges)
 {
   aRanges->Clear();
   PRInt32 startIndex, endIndex;
   GetIndicesForInterval(aBeginNode, aBeginOffset, aEndNode, aEndOffset,
                         aAllowAdjacent, &startIndex, &endIndex);
   if (startIndex == -1 || endIndex == -1)
     return NS_OK;
 
   for (PRInt32 i = startIndex; i < endIndex; i++) {
-    if (!aRanges->AppendObject(mRanges[i].mRange))
+    if (!aRanges->AppendElement(mRanges[i].mRange))
       return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return NS_OK;
 }
 
 // nsTypedSelection::GetIndicesForInterval
 //
-//    Works on the same principle as GetRangesForIntervalCOMArray above, however
+//    Works on the same principle as GetRangesForIntervalArray above, however
 //    instead this returns the indices into mRanges between which the
 //    overlapping ranges lie.
 
 void
 nsTypedSelection::GetIndicesForInterval(nsINode* aBeginNode,
                                         PRInt32 aBeginOffset,
                                         nsINode* aEndNode, PRInt32 aEndOffset,
                                         bool aAllowAdjacent,
@@ -4095,17 +4053,17 @@ nsTypedSelection::GetIndicesForInterval(
   PRInt32 endsBeforeIndex;
   if (NS_FAILED(FindInsertionPoint(&mRanges, aEndNode, aEndOffset,
                                    &CompareToRangeStart,
                                    &endsBeforeIndex))) {
     return;
   }
 
   if (endsBeforeIndex == 0) {
-    nsIRange* endRange = mRanges[endsBeforeIndex].mRange;
+    nsRange* endRange = mRanges[endsBeforeIndex].mRange;
 
     // If the interval is strictly before the range at index 0, we can optimize
     // by returning now - all ranges start after the given interval
     if (!RangeMatchesBeginPoint(endRange, aEndNode, aEndOffset))
       return;
 
     // We now know that the start point of mRanges[0].mRange equals the end of
     // the interval. Thus, when aAllowadjacent is true, the caller is always
@@ -4133,56 +4091,56 @@ nsTypedSelection::GetIndicesForInterval(
     //     given interval's start point
     //   endsBeforeIndex points to a range whose start point equals the given
     //     interval's start point
     // In the final case, there can be two such ranges, a collapsed range, and
     // an adjacent range (they will appear in mRanges in that order). For this
     // final case, we need to increment endsBeforeIndex, until one of the
     // first two possibilites hold
     while (endsBeforeIndex < (PRInt32) mRanges.Length()) {
-      nsIRange* endRange = mRanges[endsBeforeIndex].mRange;
+      nsRange* endRange = mRanges[endsBeforeIndex].mRange;
       if (!RangeMatchesBeginPoint(endRange, aEndNode, aEndOffset))
         break;
       endsBeforeIndex++;
     }
 
     // Likewise, one of the following holds:
     //   beginsAfterIndex == 0,
     //   beginsAfterIndex points to a range whose end point does not equal
     //     the given interval's end point
     //   beginsOnOrAfter points to a range whose end point equals the given
     //     interval's end point
     // In the final case, there can be two such ranges, an adjacent range, and
     // a collapsed range (they will appear in mRanges in that order). For this
     // final case, we only need to take action if both those ranges exist, and
     // we are pointing to the collapsed range - we need to point to the
     // adjacent range
-    nsIRange* beginRange = mRanges[beginsAfterIndex].mRange;
+    nsRange* beginRange = mRanges[beginsAfterIndex].mRange;
     if (beginsAfterIndex > 0 && beginRange->Collapsed() &&
         RangeMatchesEndPoint(beginRange, aBeginNode, aBeginOffset)) {
       beginRange = mRanges[beginsAfterIndex - 1].mRange;
       if (RangeMatchesEndPoint(beginRange, aBeginNode, aBeginOffset))
         beginsAfterIndex--;
     }
   } else {
     // See above for the possibilities at this point. The only case where we
     // need to take action is when the range at beginsAfterIndex ends on
     // the given interval's start point, but that range isn't collapsed (a
     // collapsed range should be included in the returned results).
-    nsIRange* beginRange = mRanges[beginsAfterIndex].mRange;
+    nsRange* beginRange = mRanges[beginsAfterIndex].mRange;
     if (RangeMatchesEndPoint(beginRange, aBeginNode, aBeginOffset) &&
         !beginRange->Collapsed())
       beginsAfterIndex++;
 
     // Again, see above for the meaning of endsBeforeIndex at this point.
     // In particular, endsBeforeIndex may point to a collaped range which
     // represents the point at the end of the interval - this range should be
     // included
     if (endsBeforeIndex < (PRInt32) mRanges.Length()) {
-      nsIRange* endRange = mRanges[endsBeforeIndex].mRange;
+      nsRange* endRange = mRanges[endsBeforeIndex].mRange;
       if (RangeMatchesBeginPoint(endRange, aEndNode, aEndOffset) &&
           endRange->Collapsed())
         endsBeforeIndex++;
      }
   }
 
   *aStartIndex = beginsAfterIndex;
   *aEndIndex = endsBeforeIndex;
@@ -4335,17 +4293,17 @@ nsTypedSelection::SelectAllFramesForCont
     return NS_OK;
   }
 
   return NS_ERROR_FAILURE;
 }
 
 //the idea of this helper method is to select, deselect "top to bottom" traversing through the frames
 nsresult
-nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bool aFlags)
+nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsRange* aRange, bool aFlags)
 {
   if (!mFrameSelection || !aPresContext || !aPresContext->GetPresShell()) {
     return NS_OK; // nothing to do
   }
   if (!aRange) {
     return NS_ERROR_NULL_POINTER;
   }
 
@@ -4464,27 +4422,27 @@ nsTypedSelection::LookUpSelection(nsICon
   nsresult rv;
   if (!aContent || ! aReturnDetails)
     return NS_ERROR_NULL_POINTER;
 
   // it is common to have no ranges, to optimize that
   if (mRanges.Length() == 0)
     return NS_OK;
 
-  nsCOMArray<nsIRange> overlappingRanges;
-  rv = GetRangesForIntervalCOMArray(aContent, aContentOffset,
-                                    aContent, aContentOffset + aContentLength,
-                                    false,
-                                    &overlappingRanges);
+  nsTArray<nsRange*> overlappingRanges;
+  rv = GetRangesForIntervalArray(aContent, aContentOffset,
+                                 aContent, aContentOffset + aContentLength,
+                                 false,
+                                 &overlappingRanges);
   NS_ENSURE_SUCCESS(rv, rv);
-  if (overlappingRanges.Count() == 0)
+  if (overlappingRanges.Length() == 0)
     return NS_OK;
 
-  for (PRInt32 i = 0; i < overlappingRanges.Count(); i ++) {
-    nsIRange* range = overlappingRanges[i];
+  for (PRUint32 i = 0; i < overlappingRanges.Length(); i++) {
+    nsRange* range = overlappingRanges[i];
     nsINode* startNode = range->GetStartParent();
     nsINode* endNode = range->GetEndParent();
     PRInt32 startOffset = range->StartOffset();
     PRInt32 endOffset = range->EndOffset();
 
     PRInt32 start = -1, end = -1;
     if (startNode == aContent && endNode == aContent) {
       if (startOffset < (aContentOffset + aContentLength)  &&
@@ -4763,50 +4721,46 @@ nsTypedSelection::RemoveAllRanges()
   // Also need to notify the frames!
   // PresShell::CharacterDataChanged should do that on DocumentChanged
 }
 
 /** AddRange adds the specified range to the selection
  *  @param aRange is the range to be added
  */
 NS_IMETHODIMP
-nsTypedSelection::AddRange(nsIDOMRange* aRange)
-{
-  nsCOMPtr<nsIRange> range = do_QueryInterface(aRange);
-  return AddRange(range);
-}
-
-nsresult
-nsTypedSelection::AddRange(nsIRange* aRange)
-{
-  if (!aRange) return NS_ERROR_NULL_POINTER;
+nsTypedSelection::AddRange(nsIDOMRange* aDOMRange)
+{
+  if (!aDOMRange) {
+    return NS_ERROR_NULL_POINTER;
+  }
+  nsRange* range = static_cast<nsRange*>(aDOMRange);
 
   // This inserts a table cell range in proper document order
   // and returns NS_OK if range doesn't contain just one table cell
   bool didAddRange;
   PRInt32 rangeIndex;
-  nsresult result = addTableCellRange(aRange, &didAddRange, &rangeIndex);
+  nsresult result = addTableCellRange(range, &didAddRange, &rangeIndex);
   if (NS_FAILED(result)) return result;
 
   if (!didAddRange)
   {
-    result = AddItem(aRange, &rangeIndex);
+    result = AddItem(range, &rangeIndex);
     if (NS_FAILED(result)) return result;
   }
 
   NS_ASSERTION(rangeIndex >= 0, "Range index not returned");
   setAnchorFocusRange(rangeIndex);
   
   // Make sure the caret appears on the next line, if at a newline
   if (mType == nsISelectionController::SELECTION_NORMAL)
     SetInterlinePosition(true);
 
   nsRefPtr<nsPresContext>  presContext;
   GetPresContext(getter_AddRefs(presContext));
-  selectFrames(presContext, aRange, true);
+  selectFrames(presContext, range, true);
 
   if (!mFrameSelection)
     return NS_OK;//nothing to do
 
   return mFrameSelection->NotifySelectionListeners(GetType());
 }
 
 // nsTypedSelection::RemoveRange
@@ -4816,71 +4770,67 @@ nsTypedSelection::AddRange(nsIRange* aRa
 //    not. There could be several selection ranges on the frame, and clearing
 //    the bit would cause the selection to not be drawn, even when there is
 //    another range on the frame (bug 346185).
 //
 //    We therefore find any ranges that intersect the same nodes as the range
 //    being removed, and cause them to set the selected bits back on their
 //    selected frames after we've cleared the bit from ours.
 
-NS_IMETHODIMP
-nsTypedSelection::RemoveRange(nsIDOMRange* aRange)
-{
-  nsCOMPtr<nsIRange> range = do_QueryInterface(aRange);
-  return RemoveRange(range);
-}
-
 nsresult
-nsTypedSelection::RemoveRange(nsIRange* aRange)
-{
-  if (!aRange)
+nsTypedSelection::RemoveRange(nsIDOMRange* aDOMRange)
+{
+  if (!aDOMRange) {
     return NS_ERROR_INVALID_ARG;
-  nsresult rv = RemoveItem(aRange);
+  }
+  nsRefPtr<nsRange> range = static_cast<nsRange*>(aDOMRange);
+  
+  nsresult rv = RemoveItem(range);
   if (NS_FAILED(rv))
     return rv;
 
-  nsINode* beginNode = aRange->GetStartParent();
-  nsINode* endNode = aRange->GetEndParent();
+  nsINode* beginNode = range->GetStartParent();
+  nsINode* endNode = range->GetEndParent();
 
   if (!beginNode || !endNode) {
     // Detached range; nothing else to do here.
     return NS_OK;
   }
   
   // find out the length of the end node, so we can select all of it
   PRInt32 beginOffset, endOffset;
   if (endNode->IsNodeOfType(nsINode::eTEXT)) {
     // Get the length of the text. We can't just use the offset because
     // another range could be touching this text node but not intersect our
     // range.
     beginOffset = 0;
     endOffset = static_cast<nsIContent*>(endNode)->TextLength();
   } else {
     // For non-text nodes, the given offsets should be sufficient.
-    beginOffset = aRange->StartOffset();
-    endOffset = aRange->EndOffset();
+    beginOffset = range->StartOffset();
+    endOffset = range->EndOffset();
   }
 
   // clear the selected bit from the removed range's frames
   nsRefPtr<nsPresContext>  presContext;
   GetPresContext(getter_AddRefs(presContext));
-  selectFrames(presContext, aRange, false);
+  selectFrames(presContext, range, false);
 
   // add back the selected bit for each range touching our nodes
-  nsCOMArray<nsIRange> affectedRanges;
-  rv = GetRangesForIntervalCOMArray(beginNode, beginOffset,
-                                    endNode, endOffset,
-                                    true, &affectedRanges);
+  nsTArray<nsRange*> affectedRanges;
+  rv = GetRangesForIntervalArray(beginNode, beginOffset,
+                                 endNode, endOffset,
+                                 true, &affectedRanges);
   NS_ENSURE_SUCCESS(rv, rv);
-  for (PRInt32 i = 0; i < affectedRanges.Count(); i ++) {
+  for (PRUint32 i = 0; i < affectedRanges.Length(); i++) {
     selectFrames(presContext, affectedRanges[i], true);
   }
 
   PRInt32 cnt = mRanges.Length();
-  if (aRange == mAnchorFocusRange) {
+  if (range == mAnchorFocusRange) {
     // Reset anchor to LAST range or clear it if there are no ranges.
     setAnchorFocusRange(cnt - 1);
 
     // When the selection is user-created it makes sense to scroll the range
     // into view. The spell-check selection, however, is created and destroyed
     // in the background. We don't want to scroll in this case or the view
     // might appear to be moving randomly (bug 337871).
     if (mType != nsISelectionController::SELECTION_SPELLCHECK && cnt > 0)
@@ -4922,17 +4872,17 @@ nsTypedSelection::Collapse(nsINode* aPar
   // Delete all of the current ranges
   nsRefPtr<nsPresContext>  presContext;
   GetPresContext(getter_AddRefs(presContext));
   Clear(presContext);
 
   // Turn off signal for table selection
   mFrameSelection->ClearTableCellSelection();
 
-  nsCOMPtr<nsIRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange();
   result = range->SetEnd(aParentNode, aOffset);
   if (NS_FAILED(result))
     return result;
   result = range->SetStart(aParentNode, aOffset);
   if (NS_FAILED(result))
     return result;
 
 #ifdef DEBUG_SELECTION
@@ -4962,17 +4912,17 @@ NS_IMETHODIMP
 nsTypedSelection::CollapseToStart()
 {
   PRInt32 cnt;
   nsresult rv = GetRangeCount(&cnt);
   if (NS_FAILED(rv) || cnt <= 0)
     return NS_ERROR_DOM_INVALID_STATE_ERR;
 
   // Get the first range
-  nsIRange* firstRange = mRanges[0].mRange;
+  nsRange* firstRange = mRanges[0].mRange;
   if (!firstRange)
     return NS_ERROR_FAILURE;
 
   return Collapse(firstRange->GetStartParent(), firstRange->StartOffset());
 }
 
 /*
  * Sets the whole selection to be one point
@@ -4982,17 +4932,17 @@ NS_IMETHODIMP
 nsTypedSelection::CollapseToEnd()
 {
   PRInt32 cnt;
   nsresult rv = GetRangeCount(&cnt);
   if (NS_FAILED(rv) || cnt <= 0)
     return NS_ERROR_DOM_INVALID_STATE_ERR;
 
   // Get the last range
-  nsIRange* lastRange = mRanges[cnt-1].mRange;
+  nsRange* lastRange = mRanges[cnt - 1].mRange;
   if (!lastRange)
     return NS_ERROR_FAILURE;
 
   return Collapse(lastRange->GetEndParent(), lastRange->EndOffset());
 }
 
 /*
  * IsCollapsed -- is the whole selection just one point, or unset?
@@ -5036,27 +4986,27 @@ nsTypedSelection::GetRangeAt(PRInt32 aIn
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
 
   NS_ADDREF(*aReturn);
 
   return NS_OK;
 }
 
-nsIRange*
+nsRange*
 nsTypedSelection::GetRangeAt(PRInt32 aIndex)
 {
   return mRanges.SafeElementAt(aIndex, sEmptyData).mRange;
 }
 
 /*
 utility function
 */
 nsresult
-nsTypedSelection::CopyRangeToAnchorFocus(nsIRange *aRange)
+nsTypedSelection::CopyRangeToAnchorFocus(nsRange *aRange)
 {
   // XXXbz could we just clone into mAnchorFocusRange, or do consumers
   // expect that pointer to not change across this call?
   NS_ENSURE_STATE(mAnchorFocusRange);
   
   nsINode* startNode = aRange->GetStartParent();
   nsINode* endNode = aRange->GetEndParent();
   PRInt32 startOffset = aRange->StartOffset();
@@ -5070,17 +5020,17 @@ nsTypedSelection::CopyRangeToAnchorFocus
       return NS_ERROR_FAILURE;//???
   }
   else if (NS_FAILED(mAnchorFocusRange->SetEnd(endNode,endOffset)))
     return NS_ERROR_FAILURE;//???
   return NS_OK;
 }
 
 void
-nsTypedSelection::ReplaceAnchorFocusRange(nsIRange *aRange)
+nsTypedSelection::ReplaceAnchorFocusRange(nsRange *aRange)
 {
   nsRefPtr<nsPresContext> presContext;
   GetPresContext(getter_AddRefs(presContext));
   if (presContext) {
     selectFrames(presContext, mAnchorFocusRange, false);
     CopyRangeToAnchorFocus(aRange);
     selectFrames(presContext, mAnchorFocusRange, true);
   }
@@ -5135,27 +5085,26 @@ nsTypedSelection::Extend(nsINode* aParen
   if (!mFrameSelection)
     return NS_ERROR_NOT_INITIALIZED; // Can't do selection
 
   nsresult res;
   if (!IsValidSelectionPoint(mFrameSelection, aParentNode))
     return NS_ERROR_FAILURE;
 
   //mFrameSelection->InvalidateDesiredX();
-  nsCOMPtr<nsIRange> difRange = new nsRange();
-  nsCOMPtr<nsIRange> range;
 
   nsINode* anchorNode = GetAnchorNode();
   nsINode* focusNode = GetFocusNode();
   PRInt32 anchorOffset = GetAnchorOffset();
   PRInt32 focusOffset = GetFocusOffset();
 
   if (focusNode == aParentNode && focusOffset == aOffset)
     return NS_OK; //same node nothing to do!
 
+  nsRefPtr<nsRange> range;
   res = mAnchorFocusRange->CloneRange(getter_AddRefs(range));
   if (NS_FAILED(res))
     return res;
   //range = mAnchorFocusRange;
 
   nsINode* startNode = range->GetStartParent();
   nsINode* endNode = range->GetEndParent();
   PRInt32 startOffset = range->StartOffset();
@@ -5183,16 +5132,17 @@ nsTypedSelection::Extend(nsINode* aParen
                                                   aParentNode, aOffset,
                                                   &disconnected);
 
   if (result2 == 0) //not selecting anywhere
     return NS_OK;
 
   nsRefPtr<nsPresContext>  presContext;
   GetPresContext(getter_AddRefs(presContext));
+  nsRefPtr<nsRange> difRange = new nsRange();
   if ((result1 == 0 && result3 < 0) || (result1 <= 0 && result2 < 0)){//a1,2  a,1,2
     //select from 1 to 2 unless they are collapsed
     res = range->SetEnd(aParentNode, aOffset);
     if (NS_FAILED(res))
       return res;
     dir = eDirNext;
     res = difRange->SetEnd(range->GetEndParent(), range->EndOffset());
     res |= difRange->SetStart(focusNode, focusOffset);
@@ -5406,38 +5356,38 @@ nsTypedSelection::ContainsNode(nsIDOMNod
   PRUint32 nodeLength;
   bool isData = node->IsNodeOfType(nsINode::eDATA_NODE);
   if (isData) {
     nodeLength = static_cast<nsIContent*>(node.get())->TextLength();
   } else {
     nodeLength = node->GetChildCount();
   }
 
-  nsCOMArray<nsIRange> overlappingRanges;
-  rv = GetRangesForIntervalCOMArray(node, 0, node, nodeLength,
-                                    false, &overlappingRanges);
+  nsTArray<nsRange*> overlappingRanges;
+  rv = GetRangesForIntervalArray(node, 0, node, nodeLength,
+                                 false, &overlappingRanges);
   NS_ENSURE_SUCCESS(rv, rv);
-  if (overlappingRanges.Count() == 0)
+  if (overlappingRanges.Length() == 0)
     return NS_OK; // no ranges overlap
   
   // if the caller said partial intersections are OK, we're done
   if (aAllowPartial) {
     *aYes = true;
     return NS_OK;
   }
 
   // text nodes always count as inside
   if (isData) {
     *aYes = true;
     return NS_OK;
   }
 
   // The caller wants to know if the node is entirely within the given range,
   // so we have to check all intersecting ranges.
-  for (PRInt32 i = 0; i < overlappingRanges.Count(); i ++) {
+  for (PRUint32 i = 0; i < overlappingRanges.Length(); i++) {
     bool nodeStartsBeforeRange, nodeEndsAfterRange;
     if (NS_SUCCEEDED(nsRange::CompareNodeToRange(node, overlappingRanges[i],
                                                  &nodeStartsBeforeRange,
                                                  &nodeEndsAfterRange))) {
       if (!nodeStartsBeforeRange && !nodeEndsAfterRange) {
         *aYes = true;
         return NS_OK;
       }
--- a/layout/inspector/src/inDOMUtils.cpp
+++ b/layout/inspector/src/inDOMUtils.cpp
@@ -53,17 +53,17 @@
 #include "nsIDOMWindow.h"
 #include "nsXBLBinding.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsIMutableArray.h"
 #include "nsBindingManager.h"
 #include "nsComputedDOMStyle.h"
 #include "nsEventStateManager.h"
 #include "nsIAtom.h"
-#include "nsIRange.h"
+#include "nsRange.h"
 #include "mozilla/dom/Element.h"
 
 
 ///////////////////////////////////////////////////////////////////////////////
 
 inDOMUtils::inDOMUtils()
 {
 }
@@ -350,13 +350,10 @@ inDOMUtils::GetRuleNodeForContent(nsICon
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 inDOMUtils::GetUsedFontFaces(nsIDOMRange* aRange,
                              nsIDOMFontFaceList** aFontFaceList)
 {
-  nsCOMPtr<nsIRange> range = do_QueryInterface(aRange);
-  NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED);
-
-  return range->GetUsedFontFaces(aFontFaceList);
+  return static_cast<nsRange*>(aRange)->GetUsedFontFaces(aFontFaceList);
 }
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -2190,20 +2190,17 @@ static nsresult CloneRangeToSelection(ns
   aRange->GetEndContainer(getter_AddRefs(endContainer));
   aRange->GetEndOffset(&endOffset);
   NS_ENSURE_STATE(startContainer && endContainer);
 
   nsCOMPtr<nsIDOMNode> newStart = GetEqualNodeInCloneTree(startContainer, aDoc);
   nsCOMPtr<nsIDOMNode> newEnd = GetEqualNodeInCloneTree(endContainer, aDoc);
   NS_ENSURE_STATE(newStart && newEnd);
 
-  nsCOMPtr<nsIDOMRange> range;
-  NS_NewRange(getter_AddRefs(range));
-  NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
-
+  nsRefPtr<nsRange> range = new nsRange();
   nsresult rv = range->SetStart(newStart, startOffset);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = range->SetEnd(newEnd, endOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return aSelection->AddRange(range);
 }
 
--- a/layout/reftests/bugs/598726-1.html
+++ b/layout/reftests/bugs/598726-1.html
@@ -15,30 +15,35 @@
     </style>
     <script>
       function boom() {
         var i = document.querySelector("input");
         i.addEventListener("transitionend", function() {
           i.removeEventListener("transitionend", arguments.callee, true);
           setTimeout(function() {
             i.value = "test";
+            i.getClientRects();
             setTimeout(function() {
               i.value = "";
+              i.getClientRects();
               setTimeout(function() {
                 i.addEventListener("transitionend", function() {
                   i.removeEventListener("transisionend", arguments.callee, true);
                   setTimeout(function() {
+                    i.getClientRects();
                     document.documentElement.removeAttribute("class");
                   }, 0);
                 }, true);
                 i.blur();
+                i.getClientRects();
               }, 0);
             }, 0);
           }, 0);
         }, true);
         i.focus();
+        i.getClientRects();
       }
     </script>
   </head>
-  <body onload="boom()">
+  <body onload="document.querySelector('input').getClientRects(); setTimeout(boom,0)">
     <input type="text" placeholder="foo">
   </body>
 </html>
--- a/mobile/android/base/db/LocalBrowserDB.java
+++ b/mobile/android/base/db/LocalBrowserDB.java
@@ -83,17 +83,17 @@ public class LocalBrowserDB implements B
 
     public Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter) {
         Cursor c = cr.query(appendProfileAndLimit(History.CONTENT_URI, limit),
                             new String[] { History._ID,
                                            History.URL,
                                            History.TITLE,
                                            History.FAVICON,
                                            History.THUMBNAIL },
-                            (urlFilter != null ? "(" + History.URL + " NOT LIKE ? )" : "" )+ 
+                            (urlFilter != null ? "(" + History.URL + " NOT LIKE ? ) AND " : "" ) + 
                             "(" + History.URL + " LIKE ? OR " + History.TITLE + " LIKE ?)",
                             urlFilter == null ? new String[] {"%" + constraint.toString() + "%", "%" + constraint.toString() + "%"} :
                             new String[] {urlFilter.toString(), "%" + constraint.toString() + "%", "%" + constraint.toString() + "%"},
                             // ORDER BY is number of visits times a multiplier from 1 - 120 of how recently the site
                             // was accessed with a site accessed today getting 120 and a site accessed 119 or more
                             // days ago getting 1
                             History.VISITS + " * MAX(1, (" +
                             History.DATE_LAST_VISITED + " - " + new Date().getTime() + ") / 86400000 + 120) DESC");
--- a/mobile/android/base/tests/BaseTest.java.in
+++ b/mobile/android/base/tests/BaseTest.java.in
@@ -68,25 +68,30 @@ abstract class BaseTest extends Activity
         getActivity().finish();
         super.tearDown();
     }
 
     protected final Activity getActivityFromClick(Element element) {
         Instrumentation inst = getInstrumentation();
         Instrumentation.ActivityMonitor monitor = inst.addMonitor((String)null, null, false);
         element.click();
-        return inst.waitForMonitor(monitor);
+        Activity activity = inst.waitForMonitor(monitor);
+        getInstrumentation().waitForIdleSync();
+        return activity;
+    }
+
+    protected final Activity clickOnAwesomeBar() {
+        Element awesomebar = mDriver.findElement(mActivity, "awesome_bar");
+        return getActivityFromClick(awesomebar);
     }
 
     protected final void enterUrl(String url) {
         mActions.expectGeckoEvent("Gecko:Ready").blockForEvent();
-        Element awesomebar = mDriver.findElement(mActivity, "awesome_bar");
-        Activity awesomeBarActivity = getActivityFromClick(awesomebar);
-        getInstrumentation().waitForIdleSync();
 
+        Activity awesomeBarActivity = clickOnAwesomeBar();
         Element urlbar = mDriver.findElement(awesomeBarActivity, "awesomebar_text");
         mActions.sendKeys(url);
         mAsserter.is(urlbar.getText(), url, "Awesomebar URL typed properly");
     }
 
     protected final void hitEnterAndWait() {
         Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
         mActions.sendSpecialKey(Actions.SpecialKey.ENTER);
@@ -95,16 +100,13 @@ abstract class BaseTest extends Activity
     }
 
     protected final void loadUrl(String url) {
         enterUrl(url);
         hitEnterAndWait();
     }
 
     protected final void verifyUrl(String url) {
-        Element awesomebar = mDriver.findElement(mActivity, "awesome_bar");
-        Activity awesomeBarActivity = getActivityFromClick(awesomebar);
-        getInstrumentation().waitForIdleSync();
-
+        Activity awesomeBarActivity = clickOnAwesomeBar();
         Element urlbar = mDriver.findElement(awesomeBarActivity, "awesomebar_text");
         mAsserter.is(urlbar.getText(), url, "Awesomebar URL stayed the same");
     }
 }
--- a/mobile/android/base/tests/testBookmark.java.in
+++ b/mobile/android/base/tests/testBookmark.java.in
@@ -8,20 +8,18 @@ public class testBookmark extends BaseTe
 
     public void testBookmark() {
         enterUrl(URL);
 
         //Click the top item in the list.
         mActions.sendSpecialKey(Actions.SpecialKey.DOWN);
         hitEnterAndWait();
 
-        verifyUrl(URL);
-
         //Click the Top item in the history list.
-        getInstrumentation().waitForIdleSync();
+        clickOnAwesomeBar();
         mActions.sendSpecialKey(Actions.SpecialKey.RIGHT);
         mActions.sendSpecialKey(Actions.SpecialKey.RIGHT);
         getInstrumentation().waitForIdleSync();
         mActions.sendSpecialKey(Actions.SpecialKey.DOWN);
         mActions.sendSpecialKey(Actions.SpecialKey.DOWN);
 
         hitEnterAndWait();
 
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -296,53 +296,56 @@ var BrowserApp = {
         };
         Services.obs.addObserver(restoreCleanup, "sessionstore-windows-restored", false);
       }
 
       // Start the restore
       ss.restoreLastSession(restoreToFront);
     } else {
       this.addTab(url);
+
+      // show telemetry door hanger if we aren't restoring a session
+      this._showTelemetryPrompt();
     }
 
     // notify java that gecko has loaded
     sendMessageToJava({
       gecko: {
         type: "Gecko:Ready"
       }
     });
-
+  },
+
+  _showTelemetryPrompt: function _showTelemetryPrompt() {
     let telemetryPrompted = false;
     try {
       telemetryPrompted = Services.prefs.getBoolPref("toolkit.telemetry.prompted");
-    } catch (e) {
-      // optional
-    }
-
-    if (!telemetryPrompted) {
-      let buttons = [
-        {
-          label: Strings.browser.GetStringFromName("telemetry.optin.yes"),
-          callback: function () {
-            Services.prefs.setBoolPref("toolkit.telemetry.prompted", true);
-            Services.prefs.setBoolPref("toolkit.telemetry.enabled", true);
-          }
-        },
-        {
-          label: Strings.browser.GetStringFromName("telemetry.optin.no"),
-          callback: function () {
-            Services.prefs.setBoolPref("toolkit.telemetry.prompted", true);
-            Services.prefs.setBoolPref("toolkit.telemetry.enabled", false);
-          }
+    } catch (e) { /* Optional */ }
+    if (telemetryPrompted)
+      return;
+
+    let buttons = [
+      {
+        label: Strings.browser.GetStringFromName("telemetry.optin.yes"),
+        callback: function () {
+          Services.prefs.setBoolPref("toolkit.telemetry.prompted", true);
+          Services.prefs.setBoolPref("toolkit.telemetry.enabled", true);
         }
-      ];
-      let brandShortName = Strings.brand.GetStringFromName("brandShortName");
-      let message = Strings.browser.formatStringFromName("telemetry.optin.message", [brandShortName], 1);
-      NativeWindow.doorhanger.show(message, "telemetry-optin", buttons);
-    }
+      },
+      {
+        label: Strings.browser.GetStringFromName("telemetry.optin.no"),
+        callback: function () {
+          Services.prefs.setBoolPref("toolkit.telemetry.prompted", true);
+          Services.prefs.setBoolPref("toolkit.telemetry.enabled", false);
+        }
+      }
+    ];
+    let brandShortName = Strings.brand.GetStringFromName("brandShortName");
+    let message = Strings.browser.formatStringFromName("telemetry.optin.message", [brandShortName], 1);
+    NativeWindow.doorhanger.show(message, "telemetry-optin", buttons);
   },
 
   shutdown: function shutdown() {
     NativeWindow.uninit();
     FormAssistant.uninit();
     OfflineApps.uninit();
     IndexedDB.uninit();
     ViewportHandler.uninit();
@@ -481,18 +484,37 @@ var BrowserApp = {
       evt.initUIEvent("TabSelect", true, false, window, null);
       aTab.browser.dispatchEvent(evt);
 
       sendMessageToJava(message);
     }
   },
 
   quit: function quit() {
-      window.QueryInterface(Ci.nsIDOMChromeWindow).minimize();
-      window.close();
+    // Figure out if there's at least one other browser window around.
+    let lastBrowser = true;
+    let e = Services.wm.getEnumerator("navigator:browser");
+    while (e.hasMoreElements() && lastBrowser) {
+      let win = e.getNext();
+      if (win != window)
+        lastBrowser = false;
+    }
+
+    if (lastBrowser) {
+      // Let everyone know we are closing the last browser window
+      let closingCanceled = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
+      Services.obs.notifyObservers(closingCanceled, "browser-lastwindow-close-requested", null);
+      if (closingCanceled.data)
+        return;
+
+      Services.obs.notifyObservers(null, "browser-lastwindow-close-granted", null);
+    }
+
+    window.QueryInterface(Ci.nsIDOMChromeWindow).minimize();
+    window.close();
   },
 
   saveAsPDF: function saveAsPDF(aBrowser) {
     // Create the final destination file location
     let fileName = ContentAreaUtils.getDefaultFileName(aBrowser.contentTitle, aBrowser.documentURI, null, null);
     fileName = fileName.trim() + ".pdf";
 
     let dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
--- a/mobile/xul/chrome/content/content.js
+++ b/mobile/xul/chrome/content/content.js
@@ -1449,17 +1449,17 @@ var SelectionHandler = {
           // If we couldn't select the word at the given point, bail
           return;
         }
 
         // Find the selected text rect and send it back so the handles can position correctly
         if (selection.rangeCount == 0)
           return;
 
-        let range = selection.getRangeAt(0).QueryInterface(Ci.nsIDOMNSRange);
+        let range = selection.getRangeAt(0);
         if (!range)
           return;
 
         // Cache the selected text since the selection might be gone by the time we get the "end" message
         this.selectedText = selection.toString().trim();
 
         // If the range didn't have any text, let's bail
         if (!this.selectedText.length) {
@@ -1529,17 +1529,17 @@ var SelectionHandler = {
           utils.sendMouseEventToWindow("mouseup", end.x, end.y, 0, 1, Ci.nsIDOMNSEvent.SHIFT_MASK, true);
         }
 
         // Cache the selected text since the selection might be gone by the time we get the "end" message
         let selection = this.contentWindow.getSelection()
         this.selectedText = selection.toString().trim();
 
         // Update the rect we use to test when finishing the clipboard operation
-        let range = selection.getRangeAt(0).QueryInterface(Ci.nsIDOMNSRange);
+        let range = selection.getRangeAt(0)
         this.cache.rect = this._extractFromRange(range, this.cache.offset).rect;
         break;
       }
     }
   },
 
   _extractFromRange: function sh_extractFromRange(aRange, aOffset) {
     let cache = { start: {}, end: {}, rect: { left: Number.MAX_VALUE, top: Number.MAX_VALUE, right: 0, bottom: 0 } };
--- a/testing/talos/talos.json
+++ b/testing/talos/talos.json
@@ -1,3 +1,3 @@
 {
-    "talos_zip": "http://build.mozilla.org/talos/zips/talos.zip"
+    "talos_zip": "http://build.mozilla.org/talos/zips/talos.bug714116.zip"
 }
--- a/toolkit/components/build/nsToolkitCompsCID.h
+++ b/toolkit/components/build/nsToolkitCompsCID.h
@@ -158,19 +158,19 @@
 // {59648a91-5a60-4122-8ff2-54b839c84aed}
 #define NS_PARENTALCONTROLSSERVICE_CID \
 { 0x580530e5, 0x118c, 0x4bc7, { 0xab, 0x88, 0xbc, 0x2c, 0xd2, 0xb9, 0x72, 0x23 } }
 
 // {e7f70966-9a37-48d7-8aeb-35998f31090e}
 #define NS_TYPEAHEADFIND_CID \
 { 0xe7f70966, 0x9a37, 0x48d7, { 0x8a, 0xeb, 0x35, 0x99, 0x8f, 0x31, 0x09, 0x0e} }
 
-// {7902e243-9b00-4673-9288-1b7fc246a8f8}
+// {15a892dd-cb0f-4a9f-a27f-8291d5e16653}
 #define NS_URLCLASSIFIERPREFIXSET_CID \
-{ 0x7902e243, 0x9b00, 0x4673, { 0x92, 0x88, 0x1b, 0x7f, 0xc2, 0x46, 0xa8, 0xf8} }
+{ 0x15a892dd, 0xcb0f, 0x4a9f, { 0xa2, 0x7f, 0x82, 0x91, 0xd5, 0xe1, 0x66, 0x53} }
 
 // {5eb7c3c1-ec1f-4007-87cc-eefb37d68ce6}
 #define NS_URLCLASSIFIERDBSERVICE_CID \
 { 0x5eb7c3c1, 0xec1f, 0x4007, { 0x87, 0xcc, 0xee, 0xfb, 0x37, 0xd6, 0x8c, 0xe6} }
 
 // {c2be6dc0-ef1e-4abd-86a2-4f864ddc57f6}
 #define NS_URLCLASSIFIERSTREAMUPDATER_CID \
 { 0xc2be6dc0, 0xef1e, 0x4abd, { 0x86, 0xa2, 0x4f, 0x86, 0x4d, 0xdc, 0x57, 0xf6} }
--- a/toolkit/components/maintenanceservice/Makefile.in
+++ b/toolkit/components/maintenanceservice/Makefile.in
@@ -90,9 +90,10 @@ include $(topsrcdir)/config/rules.mk
 DEFINES += -DNS_NO_XPCOM
 
 ifdef _MSC_VER
 WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
 endif
 
 # Pick up nsWindowsRestart.cpp
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre \
-  -I$(topsrcdir)/toolkit/mozapps/update/common
+  -I$(topsrcdir)/toolkit/mozapps/update/common \
+  $(NULL)
--- a/toolkit/components/maintenanceservice/maintenanceservice.cpp
+++ b/toolkit/components/maintenanceservice/maintenanceservice.cpp
@@ -49,18 +49,18 @@
 #include "updatehelper.h"
 
 SERVICE_STATUS gSvcStatus = { 0 }; 
 SERVICE_STATUS_HANDLE gSvcStatusHandle = NULL; 
 HANDLE gWorkDoneEvent = NULL;
 HANDLE gThread = NULL;
 bool gServiceControlStopping = false;
 
-// logs are pretty small ~10 lines, so 5 seems reasonable.
-#define LOGS_TO_KEEP 5
+// logs are pretty small, about 20 lines, so 10 seems reasonable.
+#define LOGS_TO_KEEP 10
 
 BOOL GetLogDirectoryPath(WCHAR *path);
 
 int 
 wmain(int argc, WCHAR **argv)
 {
   // If command-line parameter is "install", install the service
   // or upgrade if already installed
--- a/toolkit/components/maintenanceservice/servicebase.cpp
+++ b/toolkit/components/maintenanceservice/servicebase.cpp
@@ -50,22 +50,22 @@
  * @return TRUE If there was no error checking the files.
  */
 BOOL
 VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent)
 {
   sameContent = FALSE;
   nsAutoHandle file1(CreateFileW(file1Path, GENERIC_READ, FILE_SHARE_READ, 
                                  NULL, OPEN_EXISTING, 0, NULL));
-  if (!file1) {
+  if (INVALID_HANDLE_VALUE == file1) {
     return FALSE;
   }
   nsAutoHandle file2(CreateFileW(file2Path, GENERIC_READ, FILE_SHARE_READ, 
                                  NULL, OPEN_EXISTING, 0, NULL));
-  if (!file2) {
+  if (INVALID_HANDLE_VALUE == file2) {
     return FALSE;
   }
 
   DWORD fileSize1 = GetFileSize(file1, NULL);
   DWORD fileSize2 = GetFileSize(file2, NULL);
   if (INVALID_FILE_SIZE == fileSize1 || INVALID_FILE_SIZE == fileSize2) {
     return FALSE;
   }
--- a/toolkit/components/maintenanceservice/serviceinstall.cpp
+++ b/toolkit/components/maintenanceservice/serviceinstall.cpp
@@ -234,20 +234,22 @@ SvcInstall(SvcInstallAction action)
                                   newServiceBinaryPath, NULL, NULL, NULL, 
                                   NULL, NULL));
     if (!schService) {
       LOG(("Could not create Windows service. "
            "This error should never happen since a service install "
            "should only be called when elevated. (%d)\n", GetLastError()));
       return FALSE;
     } 
+  }
 
+  if (schService) {
     if (!SetUserAccessServiceDACL(schService)) {
-      LOG(("Could not set security ACE on service handle, the service will not be "
-           "able to be started from unelevated processes. "
+      LOG(("Could not set security ACE on service handle, the service will not"
+           "be able to be started from unelevated processes. "
            "This error should never happen.  (%d)\n", 
            GetLastError()));
     }
   }
 
   return TRUE;
 }
 
@@ -367,73 +369,88 @@ SetUserAccessServiceDACL(SC_HANDLE hServ
 }
 
 /**
  * Sets the access control list for user access for the specified service.
  *
  * @param  hService  The service to set the access control list on
  * @param  pNewAcl   The out param ACL which should be freed by caller
  * @param  psd       out param security descriptor, should be freed by caller
- * @return TRUE if successful
+ * @return ERROR_SUCCESS if successful
  */
 DWORD
 SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl, 
                          PSECURITY_DESCRIPTOR psd)
 {
   // Get the current security descriptor needed size
   DWORD needed = 0;
   if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, 
                                   &psd, 0, &needed)) {
     if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+      LOG(("Warning: Could not query service object security size.  (%d)\n", 
+           GetLastError()));
       return GetLastError();
     }
 
     DWORD size = needed;
     psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, size);
     if (!psd) {
+      LOG(("Warning: Could not allocate security descriptor.  (%d)\n", 
+           GetLastError()));
       return ERROR_INSUFFICIENT_BUFFER;
     }
 
     // Get the actual security descriptor now
     if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, 
                                     psd, size, &needed)) {
+      LOG(("Warning: Could not allocate security descriptor.  (%d)\n", 
+           GetLastError()));
       return GetLastError();
     }
   }
 
   // Get the current DACL from the security descriptor.
   PACL pacl = NULL;
   BOOL bDaclPresent = FALSE;
   BOOL bDaclDefaulted = FALSE;
   if ( !GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, 
                                   &bDaclDefaulted)) {
+    LOG(("Warning: Could not obtain DACL.  (%d)\n", GetLastError()));
     return GetLastError();
   }
 
-  // Build the ACE.
+  // Build the ACE, BuildExplicitAccessWithName cannot fail so it is not logged.
   EXPLICIT_ACCESS ea;
   BuildExplicitAccessWithName(&ea, TEXT("Users"), 
                               SERVICE_START | SERVICE_STOP | GENERIC_READ, 
                               SET_ACCESS, NO_INHERITANCE);
   DWORD lastError = SetEntriesInAcl(1, (PEXPLICIT_ACCESS)&ea, pacl, &pNewAcl);
   if (ERROR_SUCCESS != lastError) {
+    LOG(("Warning: Could not set entries in ACL.  (%d)\n", lastError));
     return lastError;
   }
 
   // Initialize a new security descriptor.
   SECURITY_DESCRIPTOR sd;
   if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
+    LOG(("Warning: Could not initialize security descriptor.  (%d)\n", 
+         GetLastError()));
     return GetLastError();
   }
 
   // Set the new DACL in the security descriptor.
   if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE)) {
+    LOG(("Warning: Could not set security descriptor DACL.  (%d)\n", 
+         GetLastError()));
     return GetLastError();
   }
 
   // Set the new security descriptor for the service object.
   if (!SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, &sd)) {
+    LOG(("Warning: Could not set object security.  (%d)\n", 
+         GetLastError()));
     return GetLastError();
   }
 
   // Woohoo, raise the roof
+  LOG(("User access was set successfully on the service.\n"));
   return ERROR_SUCCESS;
 }
--- a/toolkit/components/maintenanceservice/workmonitor.cpp
+++ b/toolkit/components/maintenanceservice/workmonitor.cpp
@@ -87,30 +87,40 @@ const int SERVICE_STILL_APPLYING_ON_FAIL
 */
 static BOOL
 IsStatusApplying(LPCWSTR updateDirPath, BOOL &isApplying)
 {
   isApplying = FALSE;
   WCHAR updateStatusFilePath[MAX_PATH + 1];
   wcscpy(updateStatusFilePath, updateDirPath);
   if (!PathAppendSafe(updateStatusFilePath, L"update.status")) {
+    LOG(("Warning: Could not append path for update.status file\n"));
     return FALSE;
   }
 
   nsAutoHandle statusFile(CreateFileW(updateStatusFilePath, GENERIC_READ,
                                       FILE_SHARE_READ | 
                                       FILE_SHARE_WRITE | 
                                       FILE_SHARE_DELETE,
                                       NULL, OPEN_EXISTING, 0, NULL));
+
+  if (INVALID_HANDLE_VALUE == statusFile) {
+    LOG(("Warning: Could not open update.status file\n"));
+    return FALSE;
+  }
+
   char buf[32] = { 0 };
   DWORD read;
   if (!ReadFile(statusFile, buf, sizeof(buf), &read, NULL)) {
+    LOG(("Warning: Could not read from update.status file\n"));
     return FALSE;
   }
 
+  LOG(("updater.exe returned status: %s\n", buf));
+
   const char kApplying[] = "applying";
   isApplying = strncmp(buf, kApplying, 
                        sizeof(kApplying) - 1) == 0;
   return TRUE;
 }
 
 
 /**
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -328,23 +328,27 @@ mHashMutex("Telemetry::mHashMutex")
     "search.sqlite", "signons.sqlite", "urlclassifier3.sqlite",
     "webappsstore.sqlite"
   };
 
   mTrackedDBs.Init();
   for (int i = 0; i < sizeof(trackedDBs)/sizeof(const char*); i++)
     mTrackedDBs.PutEntry(nsDependentCString(trackedDBs[i]));
 
+#ifdef DEBUG
+  // Mark immutable to prevent asserts on simultaneous access from multiple threads
+  mTrackedDBs.MarkImmutable();
+#endif
+
   mSlowSQLOnMainThread.Init();
   mSlowSQLOnOtherThread.Init();
   mHistogramMap.Init(Telemetry::HistogramCount);
 }
 
 TelemetryImpl::~TelemetryImpl() {
-  mTrackedDBs.Clear();
   mSlowSQLOnMainThread.Clear();
   mSlowSQLOnOtherThread.Clear();
   mHistogramMap.Clear();
 }
 
 NS_IMETHODIMP
 TelemetryImpl::NewHistogram(const nsACString &name, PRUint32 min, PRUint32 max, PRUint32 bucketCount, PRUint32 histogramType, JSContext *cx, jsval *ret)
 {
@@ -576,24 +580,17 @@ TelemetryImpl::ShutdownTelemetry()
   NS_IF_RELEASE(sTelemetry);
 }
 
 void
 TelemetryImpl::RecordSlowStatement(const nsACString &statement,
                                    const nsACString &dbName,
                                    PRUint32 delay)
 {
-  if (!sTelemetry) {
-    // Make the service manager hold a long-lived reference to the service
-    nsCOMPtr<nsITelemetry> telemetryService =
-      do_GetService("@mozilla.org/base/telemetry;1");
-    if (!telemetryService || !sTelemetry)
-      return;
-  }
-
+  MOZ_ASSERT(sTelemetry);
   if (!sTelemetry->mCanRecord || !sTelemetry->mTrackedDBs.GetEntry(dbName))
     return;
 
   nsTHashtable<SlowSQLEntryType> *slowSQLMap = NULL;
   if (NS_IsMainThread())
     slowSQLMap = &(sTelemetry->mSlowSQLOnMainThread);
   else
     slowSQLMap = &(sTelemetry->mSlowSQLOnOtherThread);
@@ -673,16 +670,24 @@ GetHistogramById(ID id)
 void
 RecordSlowSQLStatement(const nsACString &statement,
                        const nsACString &dbName,
                        PRUint32 delay)
 {
   TelemetryImpl::RecordSlowStatement(statement, dbName, delay);
 }
 
+void Init()
+{
+  // Make the service manager hold a long-lived reference to the service
+  nsCOMPtr<nsITelemetry> telemetryService =
+    do_GetService("@mozilla.org/base/telemetry;1");
+  MOZ_ASSERT(telemetryService);
+}
+
 } // namespace Telemetry
 } // namespace mozilla
 
 NSMODULE_DEFN(nsTelemetryModule) = &kTelemetryModule;
 
 /**
  * The XRE_TelemetryAdd function is to be used by embedding applications
  * that can't use mozilla::Telemetry::Accumulate() directly.
--- a/toolkit/components/telemetry/Telemetry.h
+++ b/toolkit/components/telemetry/Telemetry.h
@@ -55,16 +55,21 @@ enum ID {
 
 #include "TelemetryHistograms.h"
 
 #undef HISTOGRAM
 HistogramCount
 };
 
 /**
+ * Initialize the Telemetry service on the main thread at startup.
+ */
+void Init();
+
+/**
  * Adds sample to a histogram defined in TelemetryHistograms.h
  *
  * @param id - histogram id
  * @param sample - value to record.
  */
 void Accumulate(ID id, PRUint32 sample);
 
 /**
--- a/toolkit/components/telemetry/TelemetryHistograms.h
+++ b/toolkit/components/telemetry/TelemetryHistograms.h
@@ -261,16 +261,17 @@ HISTOGRAM(NETWORK_DISK_CACHE_OUTPUT_STRE
 /**
  * Url-Classifier telemetry
  */
 #ifdef MOZ_URL_CLASSIFIER
 HISTOGRAM(URLCLASSIFIER_PS_FILELOAD_TIME, 1, 1000, 10, EXPONENTIAL, "Time spent loading PrefixSet from file (ms)")
 HISTOGRAM(URLCLASSIFIER_PS_FALLOCATE_TIME, 1, 1000, 10, EXPONENTIAL, "Time spent fallocating PrefixSet (ms)")
 HISTOGRAM(URLCLASSIFIER_PS_CONSTRUCT_TIME, 1, 5000, 15, EXPONENTIAL, "Time spent constructing PrefixSet from DB (ms)")
 HISTOGRAM(URLCLASSIFIER_PS_LOOKUP_TIME, 1, 500, 10, EXPONENTIAL, "Time spent per PrefixSet lookup (ms)")
+HISTOGRAM_BOOLEAN(URLCLASSIFIER_PS_OOM, "Did UrlClassifier run out of memory during PrefixSet construction?")
 #endif
 
 /**
  * Places telemetry.
  */
 HISTOGRAM(PLACES_PAGES_COUNT, 1000, 150000, 20, EXPONENTIAL, "PLACES: Number of unique pages")
 HISTOGRAM(PLACES_BOOKMARKS_COUNT, 100, 8000, 15, EXPONENTIAL, "PLACES: Number of bookmarks")
 HISTOGRAM(PLACES_TAGS_COUNT, 1, 200, 10, EXPONENTIAL, "PLACES: Number of tags")
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
@@ -83,30 +83,30 @@
 #include "nsLayoutCID.h"
 #include "nsWidgetsCID.h"
 #include "nsIFormControl.h"
 #include "nsINameSpaceManager.h"
 #include "nsIWindowWatcher.h"
 #include "nsIObserverService.h"
 #include "nsFocusManager.h"
 #include "mozilla/dom/Element.h"
+#include "nsRange.h"
 
 #include "nsTypeAheadFind.h"
 
 NS_INTERFACE_MAP_BEGIN(nsTypeAheadFind)
   NS_INTERFACE_MAP_ENTRY(nsITypeAheadFind)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITypeAheadFind)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsTypeAheadFind)
 NS_IMPL_RELEASE(nsTypeAheadFind)
 
-static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
 static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
 
 #define NS_FIND_CONTRACTID "@mozilla.org/embedcomp/rangefind;1"
 
 nsTypeAheadFind::nsTypeAheadFind():
   mStartLinksOnlyPref(false),
   mCaretBrowsingOn(false),
   mLastFindLength(0),
@@ -122,21 +122,21 @@ nsTypeAheadFind::~nsTypeAheadFind()
     prefInternal->RemoveObserver("accessibility.browsewithcaret", this);
   }
 }
 
 nsresult
 nsTypeAheadFind::Init(nsIDocShell* aDocShell)
 {
   nsCOMPtr<nsIPrefBranch2> prefInternal(do_GetService(NS_PREFSERVICE_CONTRACTID));
-  mSearchRange = do_CreateInstance(kRangeCID);
-  mStartPointRange = do_CreateInstance(kRangeCID);
-  mEndPointRange = do_CreateInstance(kRangeCID);
+  mSearchRange = new nsRange();
+  mStartPointRange = new nsRange();
+  mEndPointRange = new nsRange();
   mFind = do_CreateInstance(NS_FIND_CONTRACTID);
-  if (!prefInternal || !mSearchRange || !mStartPointRange || !mEndPointRange || !mFind)
+  if (!prefInternal || !mFind)
     return NS_ERROR_FAILURE;
 
   SetDocShell(aDocShell);
 
   // ----------- Listen to prefs ------------------
   nsresult rv = prefInternal->AddObserver("accessibility.browsewithcaret", this, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -196,18 +196,18 @@ nsTypeAheadFind::SetDocShell(nsIDocShell
   mWebBrowserFind = do_GetInterface(aDocShell);
   NS_ENSURE_TRUE(mWebBrowserFind, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIPresShell> presShell;
   aDocShell->GetPresShell(getter_AddRefs(presShell));
   mPresShell = do_GetWeakReference(presShell);      
 
   mStartFindRange = nsnull;
-  mStartPointRange = do_CreateInstance(kRangeCID);
-  mSearchRange = do_CreateInstance(kRangeCID);
+  mStartPointRange = new nsRange();
+  mSearchRange = new nsRange();
 
   mFoundLink = nsnull;
   mFoundEditable = nsnull;
   mCurrentWindow = nsnull;
 
   mSelectionController = nsnull;
 
   return NS_OK;
--- a/toolkit/components/url-classifier/nsIUrlClassifierPrefixSet.idl
+++ b/toolkit/components/url-classifier/nsIUrlClassifierPrefixSet.idl
@@ -7,17 +7,17 @@
  * 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 Url Classifier code
+ * The Original Code is Url Classifier code.
  *
  * The Initial Developer of the Original Code is
  * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Gian-Carlo Pascutto <gpascutto@mozilla.com>
@@ -36,23 +36,32 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 #include "nsIFile.idl"
 
 interface nsIArray;
 
-[scriptable, uuid(7902e243-9b00-4673-9288-1b7fc246a8f8)]
+// Note that the PrefixSet name is historical and we do properly support
+// duplicated values, so it's really a Prefix Trie.
+// All methods are thread-safe.
+
+[scriptable, uuid(519c8519-0f30-426b-bb7b-c400ba0318e2)]
 interface nsIUrlClassifierPrefixSet : nsISupports
 {
+  // Fills the PrefixSet with the given array of prefixes.
+  // Can send an empty Array to clear the tree. A truly "empty tree"
+  // cannot be represented, so put a sentinel value if that is required
+  // Requires array to be sorted.
   void setPrefixes([const, array, size_is(aLength)] in unsigned long aPrefixes,
                    in unsigned long aLength);
-  void addPrefixes([const, array, size_is(aLength)] in unsigned long aPrefixes,
-                   in unsigned long aLength);
-  boolean contains(in unsigned long aPrefix);
+  // Do a lookup in the PrefixSet, return whether the value is present.
+  // If aReady is set, we will block until there are any entries.
+  // If not set, we will return in aReady whether we were ready or not.
   boolean probe(in unsigned long aPrefix, in unsigned long aKey,
                 inout boolean aReady);
+  // Return the key that is used to randomize the collisions in the prefixes.
   PRUint32 getKey();
   boolean isEmpty();
   void loadFromFile(in nsIFile aFile);
   void storeToFile(in nsIFile aFile);
 };
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
@@ -486,17 +486,17 @@ public:
                             PRUint32 numRequested,
                             bool before,
                             nsTArray<nsUrlClassifierEntry> &entries);
 
   // Ask the db for a random number.  This is temporary, and should be
   // replaced with nsIRandomGenerator when 419739 is fixed.
   nsresult RandomNumber(PRInt64 *randomNum);
   // Return an array with all Prefixes known
-  nsresult ReadPrefixes(nsTArray<PRUint32>& array, PRUint32 aKey);
+  nsresult ReadPrefixes(FallibleTArray<PRUint32>& array, PRUint32 aKey);
 
 
 protected:
   nsresult ReadEntries(mozIStorageStatement *statement,
                        nsTArray<nsUrlClassifierEntry>& entries);
   nsUrlClassifierDBServiceWorker *mWorker;
   nsCOMPtr<mozIStorageConnection> mConnection;
 
@@ -508,17 +508,18 @@ protected:
   nsCOMPtr<mozIStorageStatement> mExpireStatement;
 
   nsCOMPtr<mozIStorageStatement> mPartialEntriesStatement;
   nsCOMPtr<mozIStorageStatement> mPartialEntriesAfterStatement;
   nsCOMPtr<mozIStorageStatement> mLastPartialEntriesStatement;
   nsCOMPtr<mozIStorageStatement> mPartialEntriesBeforeStatement;
 
   nsCOMPtr<mozIStorageStatement> mRandomStatement;
-  nsCOMPtr<mozIStorageStatement> mAllPrefixStatement;
+  nsCOMPtr<mozIStorageStatement> mAllPrefixGetStatement;
+  nsCOMPtr<mozIStorageStatement> mAllPrefixCountStatement;
 };
 
 nsresult
 nsUrlClassifierStore::Init(nsUrlClassifierDBServiceWorker *worker,
                            mozIStorageConnection *connection,
                            const nsACString& entriesName)
 {
   mWorker = worker;
@@ -571,18 +572,23 @@ nsUrlClassifierStore::Init(nsUrlClassifi
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mConnection->CreateStatement
     (NS_LITERAL_CSTRING("SELECT abs(random())"),
      getter_AddRefs(mRandomStatement));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mConnection->CreateStatement(NS_LITERAL_CSTRING("SELECT domain, partial_data, complete_data FROM ")
-     + entriesName,
-     getter_AddRefs(mAllPrefixStatement));
+    + entriesName,
+    getter_AddRefs(mAllPrefixGetStatement));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING("SELECT COUNT(1) FROM ")
+    + entriesName,
+    getter_AddRefs(mAllPrefixCountStatement));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 void
 nsUrlClassifierStore::Close()
 {
@@ -594,17 +600,18 @@ nsUrlClassifierStore::Close()
   mExpireStatement = nsnull;
 
   mPartialEntriesStatement = nsnull;
   mPartialEntriesAfterStatement = nsnull;
   mPartialEntriesBeforeStatement = nsnull;
   mLastPartialEntriesStatement = nsnull;
   mRandomStatement = nsnull;
 
-  mAllPrefixStatement = nsnull;
+  mAllPrefixGetStatement = nsnull;
+  mAllPrefixCountStatement = nsnull;
 
   mConnection = nsnull;
 }
 
 
 bool
 nsUrlClassifierStore::ReadStatement(mozIStorageStatement* statement,
                                     nsUrlClassifierEntry& entry)
@@ -1089,16 +1096,22 @@ public:
   // Queue a lookup for the worker to perform, called in the main thread.
   nsresult QueueLookup(const nsACString& lookupKey,
                        nsIUrlClassifierLookupCallback* callback);
 
   // Handle any queued-up lookups.  We call this function during long-running
   // update operations to prevent lookups from blocking for too long.
   nsresult HandlePendingLookups();
 
+  // Blocks the PrefixSet from being updated while the main thread is doing
+  // its lookups. LockPrefixSet will return whether the PrefixSet is in a
+  // usable state. If not, we should fall through to SQLite lookups.
+  bool LockPrefixSet();
+  void UnlockPrefixSet();
+
 private:
   // No subclassing
   ~nsUrlClassifierDBServiceWorker();
 
   // Disallow copy constructor
   nsUrlClassifierDBServiceWorker(nsUrlClassifierDBServiceWorker&);
 
   // Try to open the db, DATABASE_FILENAME.
@@ -1311,16 +1324,19 @@ private:
   PRIntervalTime mUpdateStartTime;
 
   nsCOMPtr<nsICryptoHMAC> mHMAC;
   // The number of noise entries to add to the set of lookup results.
   PRInt32 mGethashNoise;
 
   // Set of prefixes known to be in the database
   nsRefPtr<nsUrlClassifierPrefixSet> mPrefixSet;
+  // Can we use the PrefixSet (low memory conditions)
+  bool mPrefixSetEnabled;
+  Mutex mPrefixSetEnabledLock;
 
   // Pending lookups are stored in a queue for processing.  The queue
   // is protected by mPendingLookupLock.
   Mutex mPendingLookupLock;
 
   class PendingLookup {
   public:
     nsCString mKey;
@@ -1350,16 +1366,18 @@ nsUrlClassifierDBServiceWorker::nsUrlCla
   , mPrimaryStream(false)
   , mHaveCachedLists(false)
   , mCachedListsTable(PR_UINT32_MAX)
   , mHaveCachedAddChunks(false)
   , mHaveCachedSubChunks(false)
   , mUpdateStartTime(0)
   , mGethashNoise(0)
   , mPrefixSet(0)
+  , mPrefixSetEnabled(true)
+  , mPrefixSetEnabledLock("mPrefixSetEnabledLock")
   , mPendingLookupLock("nsUrlClassifierDBServerWorker.mPendingLookupLock")
 {
 }
 
 nsUrlClassifierDBServiceWorker::~nsUrlClassifierDBServiceWorker()
 {
   NS_ASSERTION(!mConnection,
                "Db connection not closed, leaking memory!  Call CloseDb "
@@ -1419,24 +1437,39 @@ nsUrlClassifierDBServiceWorker::QueueLoo
 }
 
 nsresult
 nsUrlClassifierDBService::CheckClean(const nsACString &spec,
                                      bool *clean)
 {
   Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_PS_LOOKUP_TIME> timer;
 
+  // Is the PrefixSet usable?
+  bool usePrefixSet = mWorker->LockPrefixSet();
+
+  // No, bail out and pretend the URL is not clean. We will do
+  // a database lookup and get the correct result.
+  if (!usePrefixSet) {
+    mWorker->UnlockPrefixSet();
+    *clean = false;
+    return NS_OK;
+  }
+
   // Get the set of fragments to look up.
   nsTArray<nsCString> fragments;
   nsresult rv = GetLookupFragments(spec, fragments);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    goto error_checkclean;
+  }
 
   PRUint32 prefixkey;
   rv = mPrefixSet->GetKey(&prefixkey);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    goto error_checkclean;
+  }
 
   *clean = true;
 
   for (PRUint32 i = 0; i < fragments.Length(); i++) {
     nsUrlClassifierDomainHash fragmentKeyHash;
     fragmentKeyHash.FromPlaintext(fragments[i], mHash);
 
     // Find the corresponding host key
@@ -1447,30 +1480,39 @@ nsUrlClassifierDBService::CheckClean(con
          can't check these against the DB */
       continue;
     }
 
     PRUint32 hostprefix = hostkey.ToUint32();
     PRUint32 fragkey = fragmentKeyHash.ToUint32();
     PRUint32 codedkey;
     rv = KeyedHash(fragkey, hostprefix, prefixkey, &codedkey);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      goto error_checkclean;
+    }
 
     bool found = false;
     bool ready = false;  /* opportunistic probe */
     rv = mPrefixSet->Probe(codedkey, prefixkey, &ready, &found);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      goto error_checkclean;
+    }
     LOG(("CheckClean Probed %X ready: %d found: %d ",
          codedkey, ready, found));
     if (found || !ready) {
       *clean = false;
     }
   }
 
+  mWorker->UnlockPrefixSet();
   return NS_OK;
+
+ error_checkclean:
+  mWorker->UnlockPrefixSet();
+  return rv;
 }
 
 static nsresult GetHostKeys(const nsACString &spec,
                             nsTArray<nsCString> &hostKeys)
 {
   nsACString::const_iterator begin, end, iter;
   spec.BeginReading(begin);
   spec.EndReading(end);
@@ -3545,60 +3587,73 @@ static nsresult KeyedHash(PRUint32 aPref
   h1 *= c5;
   h1 ^= h1 >> 16;
 
   *aOut = h1;
 
   return NS_OK;
 }
 
-nsresult nsUrlClassifierStore::ReadPrefixes(nsTArray<PRUint32>& array,
+nsresult nsUrlClassifierStore::ReadPrefixes(FallibleTArray<PRUint32>& array,
                                             PRUint32 aKey)
 {
-  mozStorageStatementScoper scoper(mAllPrefixStatement);
+  mozStorageStatementScoper scoper(mAllPrefixGetStatement);
+  mozStorageStatementScoper scoperToo(mAllPrefixCountStatement);
   bool hasMoreData;
   PRUint32 pcnt = 0;
   PRUint32 fcnt = 0;
 
 #if defined(PR_LOGGING)
   PRIntervalTime clockStart = 0;
   if (LOG_ENABLED()) {
     clockStart = PR_IntervalNow();
   }
 #endif
 
-  while (NS_SUCCEEDED(mAllPrefixStatement->ExecuteStep(&hasMoreData)) && hasMoreData) {
+  // Make sure we allocate no more than we really need, so first
+  // check how much entries there are
+  if (NS_SUCCEEDED(mAllPrefixCountStatement->ExecuteStep(&hasMoreData)) && hasMoreData) {
+    PRUint32 count = mAllPrefixCountStatement->AsInt32(0);
+    if (!array.SetCapacity(count)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+  } else {
+    return NS_ERROR_FILE_CORRUPTED;
+  }
+
+  while (NS_SUCCEEDED(mAllPrefixGetStatement->ExecuteStep(&hasMoreData)) && hasMoreData) {
     PRUint32 prefixval;
     PRUint32 domainval;
     PRUint32 size;
 
-    const PRUint8 *blobdomain = mAllPrefixStatement->AsSharedBlob(0, &size);
+    const PRUint8 *blobdomain = mAllPrefixGetStatement->AsSharedBlob(0, &size);
     if (!blobdomain || (size != DOMAIN_LENGTH))
       return false;
 
     domainval = *(reinterpret_cast<const PRUint32*>(blobdomain));
 
-    const PRUint8 *blobprefix = mAllPrefixStatement->AsSharedBlob(1, &size);
+    const PRUint8 *blobprefix = mAllPrefixGetStatement->AsSharedBlob(1, &size);
     if (!blobprefix || (size != PARTIAL_LENGTH)) {
-      const PRUint8 *blobfull = mAllPrefixStatement->AsSharedBlob(2, &size);
+      const PRUint8 *blobfull = mAllPrefixGetStatement->AsSharedBlob(2, &size);
       if (!blobfull || (size != COMPLETE_LENGTH)) {
         prefixval = domainval;
         fcnt++;
       } else {
         prefixval = *(reinterpret_cast<const PRUint32*>(blobfull));
       }
     } else {
       prefixval = *(reinterpret_cast<const PRUint32*>(blobprefix));
     }
 
     PRUint32 keyedVal;
     nsresult rv = KeyedHash(prefixval, domainval, aKey, &keyedVal);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    array.AppendElement(keyedVal);
+    PRUint32 *res = array.AppendElement(keyedVal);
+    MOZ_ASSERT(res != nsnull);
     pcnt++;
     // Normal DB size is about 500k entries. If we are getting 10x
     // as much, the database must be corrupted.
     if (pcnt > 5000000) {
       return NS_ERROR_FILE_CORRUPTED;
     }
   }
 
@@ -3610,56 +3665,90 @@ nsresult nsUrlClassifierStore::ReadPrefi
     LOG(("Gathering took %dms\n",
          PR_IntervalToMilliseconds(clockEnd - clockStart)));
   }
 #endif
 
   return NS_OK;
 }
 
+bool nsUrlClassifierDBServiceWorker::LockPrefixSet()
+{
+  mPrefixSetEnabledLock.Lock();
+  return mPrefixSetEnabled;
+}
+
+void nsUrlClassifierDBServiceWorker::UnlockPrefixSet()
+{
+  mPrefixSetEnabledLock.Unlock();
+}
+
 nsresult
 nsUrlClassifierDBServiceWorker::ConstructPrefixSet()
 {
   Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_PS_CONSTRUCT_TIME> timer;
 
   PRUint32 key;
   nsresult rv = mPrefixSet->GetKey(&key);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsTArray<PRUint32> array;
+  FallibleTArray<PRUint32> array;
   rv = mMainStore.ReadPrefixes(array, key);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    goto error_bailout;
+  }
 
 #ifdef HASHFUNCTION_COLLISION_TEST
   array.Sort();
   PRUint32 collisions = 0;
   for (int i = 1; i < array.Length(); i++) {
     if (array[i - 1] == array[i]) {
       collisions++;
     }
   }
   LOG(("%d collisions in the set", collisions));
 #endif
 
-  // clear old tree
-  rv = mPrefixSet->SetPrefixes(nsnull, 0);
-  NS_ENSURE_SUCCESS(rv, rv);
   if (array.IsEmpty()) {
-    // DB is empty, but put a sentinel to show that we looked
-    array.AppendElement(0);
+    // DB is empty, put a sentinel to show that we loaded it
+    if (!array.AppendElement(0)) {
+      goto error_bailout;
+    }
   }
-  // construct new one
+  // SetPrefixes requires sorted arrays
+  array.Sort();
+
+  // construct new prefixset
   rv = mPrefixSet->SetPrefixes(array.Elements(), array.Length());
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    goto error_bailout;
+  }
 
   // store the new tree to disk
   rv = mPrefixSet->StoreToFile(mPSFile);
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "failed to store the prefixset");
 
+  // re-enable prefixset usage if disabled earlier
+  mPrefixSetEnabled = true;
+
   return NS_OK;
+
+ error_bailout:
+  // disable prefixset usage
+  MutexAutoLock lock(mPrefixSetEnabledLock);
+  mPrefixSetEnabled = false;
+  // load an empty prefixset
+  nsAutoTArray<PRUint32, 1> sentinel;
+  sentinel.Clear();
+  sentinel.AppendElement(0);
+  mPrefixSet->SetPrefixes(sentinel.Elements(), sentinel.Length());
+  if (rv == NS_ERROR_OUT_OF_MEMORY) {
+    Telemetry::Accumulate(Telemetry::URLCLASSIFIER_PS_OOM, 1);
+  }
+  return rv;
 }
 
 nsresult
 nsUrlClassifierDBServiceWorker::LoadPrefixSet(nsCOMPtr<nsIFile> & aFile)
 {
   bool empty;
   nsresult rv = mPrefixSet->IsEmpty(&empty);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp
@@ -184,80 +184,91 @@ nsUrlClassifierPrefixSet::InitKey()
   LOG(("Initialized PrefixSet, key = %X", mRandomKey));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsUrlClassifierPrefixSet::SetPrefixes(const PRUint32 * aArray, PRUint32 aLength)
 {
-  {
+  if (aLength <= 0) {
     MutexAutoLock lock(mPrefixSetLock);
     if (mHasPrefixes) {
       LOG(("Clearing PrefixSet"));
       mDeltas.Clear();
       mIndexPrefixes.Clear();
       mIndexStarts.Clear();
       mHasPrefixes = false;
     }
-  }
-  if (aLength > 0) {
-    // Ensure they are sorted before adding
-    nsTArray<PRUint32> prefixes;
-    prefixes.AppendElements(aArray, aLength);
-    prefixes.Sort();
-    AddPrefixes(prefixes.Elements(), prefixes.Length());
+  } else {
+    return MakePrefixSet(aArray, aLength);
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsUrlClassifierPrefixSet::AddPrefixes(const PRUint32 * prefixes, PRUint32 aLength)
+nsresult
+nsUrlClassifierPrefixSet::MakePrefixSet(const PRUint32 * prefixes, PRUint32 aLength)
 {
   if (aLength == 0) {
     return NS_OK;
   }
 
-  nsTArray<PRUint32> mNewIndexPrefixes(mIndexPrefixes);
-  nsTArray<PRUint32> mNewIndexStarts(mIndexStarts);
-  nsTArray<PRUint16> mNewDeltas(mDeltas);
+#ifdef DEBUG
+  for (PRUint32 i = 1; i < aLength; i++) {
+    MOZ_ASSERT(prefixes[i] >= prefixes[i-1]);
+  }
+#endif
 
-  mNewIndexPrefixes.AppendElement(prefixes[0]);
-  mNewIndexStarts.AppendElement(mNewDeltas.Length());
+  FallibleTArray<PRUint32> newIndexPrefixes;
+  FallibleTArray<PRUint32> newIndexStarts;
+  FallibleTArray<PRUint16> newDeltas;
+
+  if (!newIndexPrefixes.AppendElement(prefixes[0])) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  if (!newIndexStarts.AppendElement(newDeltas.Length())) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   PRUint32 numOfDeltas = 0;
   PRUint32 currentItem = prefixes[0];
   for (PRUint32 i = 1; i < aLength; i++) {
     if ((numOfDeltas >= DELTAS_LIMIT) ||
           (prefixes[i] - currentItem >= MAX_INDEX_DIFF)) {
-      mNewIndexStarts.AppendElement(mNewDeltas.Length());
-      mNewIndexPrefixes.AppendElement(prefixes[i]);
+      if (!newIndexStarts.AppendElement(newDeltas.Length())) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+      if (!newIndexPrefixes.AppendElement(prefixes[i])) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
       numOfDeltas = 0;
     } else {
       PRUint16 delta = prefixes[i] - currentItem;
-      mNewDeltas.AppendElement(delta);
+      if (!newDeltas.AppendElement(delta)) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
       numOfDeltas++;
     }
     currentItem = prefixes[i];
   }
 
-  mNewIndexPrefixes.Compact();
-  mNewIndexStarts.Compact();
-  mNewDeltas.Compact();
+  newIndexPrefixes.Compact();
+  newIndexStarts.Compact();
+  newDeltas.Compact();
 
-  LOG(("Total number of indices: %d", mNewIndexPrefixes.Length()));
-  LOG(("Total number of deltas: %d", mNewDeltas.Length()));
+  LOG(("Total number of indices: %d", newIndexPrefixes.Length()));
+  LOG(("Total number of deltas: %d", newDeltas.Length()));
 
   MutexAutoLock lock(mPrefixSetLock);
 
   // This just swaps some pointers
-  mIndexPrefixes.SwapElements(mNewIndexPrefixes);
-  mIndexStarts.SwapElements(mNewIndexStarts);
-  mDeltas.SwapElements(mNewDeltas);
+  mIndexPrefixes.SwapElements(newIndexPrefixes);
+  mIndexStarts.SwapElements(newIndexStarts);
+  mDeltas.SwapElements(newDeltas);
 
   mHasPrefixes = true;
   mSetIsReady.NotifyAll();
 
   return NS_OK;
 }
 
 PRUint32 nsUrlClassifierPrefixSet::BinSearch(PRUint32 start,
@@ -273,17 +284,17 @@ PRUint32 nsUrlClassifierPrefixSet::BinSe
       end = i - 1;
     } else {
       return i;
     }
   }
   return end;
 }
 
-NS_IMETHODIMP
+nsresult
 nsUrlClassifierPrefixSet::Contains(PRUint32 aPrefix, bool * aFound)
 {
   mPrefixSetLock.AssertCurrentThreadOwns();
 
   *aFound = false;
 
   if (!mHasPrefixes) {
     return NS_OK;
--- a/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.h
+++ b/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.h
@@ -54,31 +54,21 @@
 class nsPrefixSetReporter;
 
 class nsUrlClassifierPrefixSet : public nsIUrlClassifierPrefixSet
 {
 public:
   nsUrlClassifierPrefixSet();
   virtual ~nsUrlClassifierPrefixSet();
 
-  // Can send an empty Array to clean the tree
   NS_IMETHOD SetPrefixes(const PRUint32* aArray, PRUint32 aLength);
-  // Given prefixes must be in sorted order and bigger than
-  // anything currently in the Prefix Set
-  NS_IMETHOD AddPrefixes(const PRUint32* aArray, PRUint32 aLength);
-  // Does the PrefixSet contain this prefix? not thread-safe
-  NS_IMETHOD Contains(PRUint32 aPrefix, bool* aFound);
-  // Do a lookup in the PrefixSet
-  // if aReady is set, we will block until there are any entries
-  // if not set, we will return in aReady whether we were ready or not
   NS_IMETHOD Probe(PRUint32 aPrefix, PRUint32 aKey, bool* aReady, bool* aFound);
   NS_IMETHOD IsEmpty(bool * aEmpty);
   NS_IMETHOD LoadFromFile(nsIFile* aFile);
   NS_IMETHOD StoreToFile(nsIFile* aFile);
-  // Return a key that is used to randomize the collisions in the prefixes
   NS_IMETHOD GetKey(PRUint32* aKey);
 
   NS_DECL_ISUPPORTS
 
   // Return the estimated size of the set on disk and in memory,
   // in bytes
   size_t SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf);
 
@@ -86,29 +76,31 @@ protected:
   static const PRUint32 DELTAS_LIMIT = 100;
   static const PRUint32 MAX_INDEX_DIFF = (1 << 16);
   static const PRUint32 PREFIXSET_VERSION_MAGIC = 1;
 
   mozilla::Mutex mPrefixSetLock;
   mozilla::CondVar mSetIsReady;
   nsRefPtr<nsPrefixSetReporter> mReporter;
 
+  nsresult Contains(PRUint32 aPrefix, bool* aFound);
+  nsresult MakePrefixSet(const PRUint32* aArray, PRUint32 aLength);
   PRUint32 BinSearch(PRUint32 start, PRUint32 end, PRUint32 target);
   nsresult LoadFromFd(mozilla::AutoFDClose & fileFd);
   nsresult StoreToFd(mozilla::AutoFDClose & fileFd);
   nsresult InitKey();
 
   // boolean indicating whether |setPrefixes| has been
   // called with a non-empty array.
   bool mHasPrefixes;
   // key used to randomize hash collisions
   PRUint32 mRandomKey;
   // the prefix for each index.
-  nsTArray<PRUint32> mIndexPrefixes;
+  FallibleTArray<PRUint32> mIndexPrefixes;
   // the value corresponds to the beginning of the run
   // (an index in |_deltas|) for the index
-  nsTArray<PRUint32> mIndexStarts;
+  FallibleTArray<PRUint32> mIndexStarts;
   // array containing deltas from indices.
-  nsTArray<PRUint16> mDeltas;
+  FallibleTArray<PRUint16> mDeltas;
 
 };
 
 #endif
--- a/toolkit/components/url-classifier/tests/unit/test_prefixset.js
+++ b/toolkit/components/url-classifier/tests/unit/test_prefixset.js
@@ -61,17 +61,17 @@ function doExpectedLookups(pset, prefixe
   }
 }
 
 // testBasicPset: A very basic test of the prefix set to make sure that it
 // exists and to give a basic example of its use.
 function testBasicPset() {
   let pset = Cc["@mozilla.org/url-classifier/prefixset;1"]
                .createInstance(Ci.nsIUrlClassifierPrefixSet);
-  let prefixes = [2,100,50,2000,78000,1593203];
+  let prefixes = [2,50,100,2000,78000,1593203];
   pset.setPrefixes(prefixes, prefixes.length);
 
   do_check_true(wrappedProbe(pset, 100));
   do_check_false(wrappedProbe(pset, 100000));
   do_check_true(wrappedProbe(pset, 1593203));
   do_check_false(wrappedProbe(pset, 999));
   do_check_false(wrappedProbe(pset, 0));
 }
@@ -94,25 +94,16 @@ function testSimplePset() {
   let pset = newPset();
   let prefixes = [1,2,100,400,123456789];
   pset.setPrefixes(prefixes, prefixes.length);
 
   doRandomLookups(pset, prefixes, 100);
   doExpectedLookups(pset, prefixes, 1);
 }
 
-function testUnsortedPset() {
-  let pset = newPset();
-  let prefixes = [5,1,20,100,200000,100000];
-  pset.setPrefixes(prefixes, prefixes.length);
-
-  doRandomLookups(pset, prefixes, 100);
-  doExpectedLookups(pset, prefixes, 1);
-}
-
 function testReSetPrefixes() {
   let pset = newPset();
   let prefixes = [1, 5, 100, 1000, 150000];
   pset.setPrefixes(prefixes, prefixes.length);
 
   doExpectedLookups(pset, prefixes, 1);
 
   let secondPrefixes = [12, 50, 300, 2000, 5000, 200000];
@@ -153,17 +144,16 @@ function testTinySet() {
 
   prefixes = [];
   pset.setPrefixes(prefixes, prefixes.length);
   do_check_false(wrappedProbe(pset, 1));
 }
 
 let tests = [testBasicPset,
              testSimplePset,
-             testUnsortedPset,
              testReSetPrefixes,
              testLargeSet,
              testDuplicates,
              testTinySet];
 
 function run_test() {
   // None of the tests use |executeSoon| or any sort of callbacks, so we can
   // just run them in succession.
--- a/toolkit/mozapps/update/Makefile.in
+++ b/toolkit/mozapps/update/Makefile.in
@@ -58,16 +58,28 @@ endif
 
 XPIDLSRCS += nsIUpdateService.idl
 
 EXTRA_PP_COMPONENTS += \
   nsUpdateService.js \
   nsUpdateServiceStub.js \
   nsUpdateService.manifest \
   $(NULL)
+else
+
+# If only the maintenance service is installed and not
+# the updater, then the maintenance service may still be
+# used for other things.  We need to build update/common
+# which the maintenance service uses.
+ifdef MOZ_MAINTENANCE_SERVICE
+DIRS = ../readstrings
+ifneq ($(OS_TARGET),Android)
+DIRS += common
+endif
+endif
 endif
 
 ifdef ENABLE_TESTS
 DIRS += test_timermanager
 # Update tests require the updater binary
 ifdef MOZ_UPDATER
 DIRS += test
 ifdef MOZ_MAINTENANCE_SERVICE
--- a/widget/cocoa/nsCocoaFeatures.h
+++ b/widget/cocoa/nsCocoaFeatures.h
@@ -40,14 +40,16 @@
 #define nsCocoaFeatures_h_
 
 #include "prtypes.h"
 
 class nsCocoaFeatures {
 public:
   static PRInt32 OSXVersion();
 
-  static bool OnSnowLeopardOrLater();  
-  static bool OnLionOrLater();  
+  static bool OnSnowLeopardOrLater();
+  static bool OnLionOrLater();
+
+  static bool SupportCoreAnimationPlugins();
 private:
   static PRInt32 mOSXVersion;
 };
 #endif // nsCocoaFeatures_h_
--- a/widget/cocoa/nsCocoaFeatures.mm
+++ b/widget/cocoa/nsCocoaFeatures.mm
@@ -63,16 +63,24 @@ nsCocoaFeatures::OSXVersion()
             mOSXVersion = MAC_OS_X_VERSION_10_5_HEX;
         }
         mOSXVersion &= MAC_OS_X_VERSION_MASK;
     }
     return mOSXVersion;
 }
 
 /* static */ bool
+nsCocoaFeatures::SupportCoreAnimationPlugins()
+{
+    // Disallow Core Animation on 10.5 because of crashes.
+    // See Bug 711564.
+    return (OSXVersion() >= MAC_OS_X_VERSION_10_6_HEX);
+}
+
+/* static */ bool
 nsCocoaFeatures::OnSnowLeopardOrLater()
 {
     return (OSXVersion() >= MAC_OS_X_VERSION_10_6_HEX);
 }
 
 /* static */ bool
 nsCocoaFeatures::OnLionOrLater()
 {
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -135,16 +135,17 @@ extern nsresult nsStringInputStreamConst
 #include "nsSystemInfo.h"
 #include "nsMemoryReporterManager.h"
 
 #include <locale.h>
 #include "mozilla/Services.h"
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/Omnijar.h"
 #include "mozilla/HangMonitor.h"
+#include "mozilla/Telemetry.h"
 
 #include "nsChromeRegistry.h"
 #include "nsChromeProtocolHandler.h"
 
 #include "mozilla/scache/StartupCache.h"
 
 #include "base/at_exit.h"
 #include "base/command_line.h"
@@ -531,16 +532,18 @@ NS_InitXPCOM2(nsIServiceManager* *result
 #ifdef XP_WIN
     ScheduleMediaCacheRemover();
 #endif
 
     mozilla::MapsMemoryReporter::Init();
 
     mozilla::HangMonitor::Startup();
 
+    mozilla::Telemetry::Init();
+
     return NS_OK;
 }
 
 
 //
 // NS_ShutdownXPCOM()
 //
 // The shutdown sequence for xpcom would be
--- a/xpcom/glue/nsTHashtable.h
+++ b/xpcom/glue/nsTHashtable.h
@@ -280,16 +280,31 @@ public:
   {
     if (IsInitialized()) {
       s_SizeOfArgs args = { sizeOfEntryExcludingThis, userArg };
       return PL_DHashTableSizeOfExcludingThis(&mTable, s_SizeOfStub, mallocSizeOf, &args);
     }
     return 0;
   }
 
+#ifdef DEBUG
+  /**
+   * Mark the table as constant after initialization.
+   *
+   * This will prevent assertions when a read-only hash is accessed on multiple
+   * threads without synchronization.
+   */
+  void MarkImmutable()
+  {
+    NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
+
+    PL_DHashMarkTableImmutable(&mTable);
+  }
+#endif
+
 protected:
   PLDHashTable mTable;
 
   static const void* s_GetKey(PLDHashTable    *table,
                               PLDHashEntryHdr *entry);
 
   static PLDHashNumber s_HashKey(PLDHashTable *table,
                                  const void   *key);