Merge backout of changeset ae1773250d39
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 03 Jun 2010 21:27:23 -0400
changeset 43082 cf6e948513605fbbaa9432faf460dda6337f4677
parent 43080 9065d777cf6215cba066c90915d1a759e5b45f22 (diff)
parent 43081 e5f1739ad7f1883154657fd0e10d4bb048e32bb5 (current diff)
child 43084 ff91ef9f46070a559811fc3ea118d3e71188d94c
push idunknown
push userunknown
push dateunknown
milestone1.9.3a5pre
Merge backout of changeset ae1773250d39
--- a/accessible/src/base/nsAccEvent.cpp
+++ b/accessible/src/base/nsAccEvent.cpp
@@ -309,21 +309,26 @@ nsAccReorderEvent::HasAccessibleInReason
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccStateChangeEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsAccStateChangeEvent, nsAccEvent,
                              nsIAccessibleStateChangeEvent)
 
+// Note: we pass in eAllowDupes to the base class because we don't currently
+// support correct state change coalescence (XXX Bug 569356). Also we need to
+// decide how to coalesce events created via accessible (instead of node).
 nsAccStateChangeEvent::
   nsAccStateChangeEvent(nsIAccessible *aAccessible,
                         PRUint32 aState, PRBool aIsExtraState,
-                        PRBool aIsEnabled):
-  nsAccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible),
+                        PRBool aIsEnabled, PRBool aIsAsynch,
+                        EIsFromUserInput aIsFromUserInput):
+  nsAccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible, aIsAsynch,
+             aIsFromUserInput, eAllowDupes),
   mState(aState), mIsExtraState(aIsExtraState), mIsEnabled(aIsEnabled)
 {
 }
 
 nsAccStateChangeEvent::
   nsAccStateChangeEvent(nsIDOMNode *aNode,
                         PRUint32 aState, PRBool aIsExtraState,
                         PRBool aIsEnabled):
@@ -374,22 +379,30 @@ nsAccStateChangeEvent::IsEnabled(PRBool 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccTextChangeEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsAccTextChangeEvent, nsAccEvent,
                              nsIAccessibleTextChangeEvent)
 
+// Note: we pass in eAllowDupes to the base class because we don't support text
+// events coalescence. We fire delayed text change events in nsDocAccessible but
+// we continue to base the event off the accessible object rather than just the
+// node. This means we won't try to create an accessible based on the node when
+// we are ready to fire the event and so we will no longer assert at that point
+// if the node was removed from the document. Either way, the AT won't work with
+// a defunct accessible so the behaviour should be equivalent.
+// XXX revisit this when coalescence is faster (eCoalesceFromSameSubtree)
 nsAccTextChangeEvent::
   nsAccTextChangeEvent(nsIAccessible *aAccessible,
                        PRInt32 aStart, PRUint32 aLength, PRBool aIsInserted,
                        PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput) :
   nsAccEvent(aIsInserted ? nsIAccessibleEvent::EVENT_TEXT_INSERTED : nsIAccessibleEvent::EVENT_TEXT_REMOVED,
-             aAccessible, aIsAsynch, aIsFromUserInput),
+             aAccessible, aIsAsynch, aIsFromUserInput, eAllowDupes),
   mStart(aStart), mLength(aLength), mIsInserted(aIsInserted)
 {
 #ifdef XP_WIN
   nsCOMPtr<nsIAccessibleText> textAccessible = do_QueryInterface(aAccessible);
   NS_ASSERTION(textAccessible, "Should not be firing test change event for non-text accessible!!!");
   if (textAccessible) {
     textAccessible->GetText(aStart, aStart + aLength, mModifiedText);
   }
--- a/accessible/src/base/nsAccEvent.h
+++ b/accessible/src/base/nsAccEvent.h
@@ -193,17 +193,18 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsAccReord
 
 
 class nsAccStateChangeEvent: public nsAccEvent,
                              public nsIAccessibleStateChangeEvent
 {
 public:
   nsAccStateChangeEvent(nsIAccessible *aAccessible,
                         PRUint32 aState, PRBool aIsExtraState,
-                        PRBool aIsEnabled);
+                        PRBool aIsEnabled, PRBool aIsAsynch = PR_FALSE,
+                        EIsFromUserInput aIsFromUserInput = eAutoDetect);
 
   nsAccStateChangeEvent(nsIDOMNode *aNode,
                         PRUint32 aState, PRBool aIsExtraState,
                         PRBool aIsEnabled);
 
   nsAccStateChangeEvent(nsIDOMNode *aNode,
                         PRUint32 aState, PRBool aIsExtraState);
 
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -978,20 +978,23 @@ void nsDocAccessible::ScrollPositionDidC
 ////////////////////////////////////////////////////////////////////////////////
 // nsIObserver
 
 NS_IMETHODIMP nsDocAccessible::Observe(nsISupports *aSubject, const char *aTopic,
                                        const PRUnichar *aData)
 {
   if (!nsCRT::strcmp(aTopic,"obs_documentCreated")) {    
     // State editable will now be set, readonly is now clear
+    // Normally we only fire delayed events created from the node, not an
+    // accessible object. See the nsAccStateChangeEvent constructor for details
+    // about this exceptional case.
     nsRefPtr<nsAccEvent> event =
       new nsAccStateChangeEvent(this, nsIAccessibleStates::EXT_STATE_EDITABLE,
                                 PR_TRUE, PR_TRUE);
-    nsEventShell::FireEvent(event);
+    FireDelayedAccessibleEvent(event);
   }
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIDocumentObserver
 
@@ -1484,21 +1487,24 @@ nsDocAccessible::FireTextChangeEventForT
     if (NS_FAILED(rv))
       return;
 
     rv = textAccessible->ContentToRenderedOffset(frame, start + length,
                                                  &renderedEndOffset);
     if (NS_FAILED(rv))
       return;
 
+    // Normally we only fire delayed events created from the node, not an
+    // accessible object. See the nsAccTextChangeEvent constructor for details
+    // about this exceptional case.
     nsRefPtr<nsAccEvent> event =
       new nsAccTextChangeEvent(accessible, offset,
                                renderedEndOffset - renderedStartOffset,
                                aIsInserted, PR_FALSE);
-    nsEventShell::FireEvent(event);
+    FireDelayedAccessibleEvent(event);
 
     FireValueChangeForTextFields(accessible);
   }
 }
 
 already_AddRefed<nsAccEvent>
 nsDocAccessible::CreateTextChangeEventForNode(nsAccessible *aContainerAccessible,
                                               nsIDOMNode *aChangeNode,
@@ -1986,21 +1992,24 @@ nsDocAccessible::InvalidateCacheSubtree(
       return;
 
     if (childNode != mDOMNode) { // Fire text change unless the node being removed is for this doc
       // When a node is hidden or removed, the text in an ancestor hyper text will lose characters
       // At this point we still have the frame and accessible for this node if there was one
       // XXX Collate events when a range is deleted
       // XXX We need a way to ignore SplitNode and JoinNode() when they
       // do not affect the text within the hypertext
+      // Normally we only fire delayed events created from the node, not an
+      // accessible object. See the nsAccTextChangeEvent constructor for details
+      // about this exceptional case.
       nsRefPtr<nsAccEvent> textChangeEvent =
         CreateTextChangeEventForNode(containerAccessible, childNode, childAccessible,
                                      PR_FALSE, isAsynch);
       if (textChangeEvent) {
-        nsEventShell::FireEvent(textChangeEvent);
+        FireDelayedAccessibleEvent(textChangeEvent);
       }
     }
   }
 
   // We need to get an accessible for the mutation event's container node
   // If there is no accessible for that node, we need to keep moving up the parent
   // chain so there is some accessible.
   // We will use this accessible to fire the accessible mutation event.
--- a/accessible/tests/mochitest/events/Makefile.in
+++ b/accessible/tests/mochitest/events/Makefile.in
@@ -56,15 +56,16 @@ include $(topsrcdir)/config/rules.mk
 		test_dragndrop.html \
 		test_flush.html \
 		test_focus.html \
 		test_focus.xul \
 		test_focus_name.html \
 		test_focusdoc.html \
 		test_mutation.html \
 		test_scroll.xul \
+		test_statechange.html \
 		test_text.html \
 		test_tree.xul \
 		test_valuechange.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/events/test_statechange.html
@@ -0,0 +1,102 @@
+<html>
+
+<head>
+  <title>Accessible state change event testing</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/events.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/states.js"></script>
+
+  <script type="application/javascript">
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+
+    function makeEditableDoc(aDocNode, aIsEnabled)
+    {
+      this.DOMNode = aDocNode;
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_STATE_CHANGE, getAccessible(this.DOMNode))
+      ];
+
+      this.invoke = function editabledoc_invoke() {
+        // Note: this should fire an EVENT_STATE_CHANGE
+        this.DOMNode.designMode = 'on';
+      };
+
+      this.check = function editabledoc_check(aEvent) {
+
+        testStates(aDocNode, 0, EXT_STATE_EDITABLE);
+
+        var event = null;
+        try {
+          var event = aEvent.QueryInterface(nsIAccessibleStateChangeEvent);
+        } catch (e) {
+          ok(false, "State change event was expected");
+        }
+
+        if (!event) { return; }
+
+        ok(event.isExtraState(), "Extra state change was expected");
+        is(event.state, EXT_STATE_EDITABLE, "Wrong state of statechange event");
+        ok(event.isEnabled(), "Expected editable state to be enabled");
+      }
+
+      this.getID = function editabledoc_getID() {
+        return prettyName(aDocNode) + " editable state changed";
+      };
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Do tests
+
+    var gQueue = null;
+
+    // var gA11yEventDumpID = "eventdump"; // debug stuff
+
+    function doTests()
+    {
+      gQueue = new eventQueue();
+
+      // Test delayed editable state change
+      var doc = document.getElementById("iframe").contentDocument;
+      gQueue.push(new makeEditableDoc(doc));
+
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  </script>
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=564471"
+     title="Make state change events async">
+    Mozilla Bug 564471
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div id="testContainer">
+    <iframe id="iframe"></iframe>
+  </div>
+  <div id="eventdump"></div>
+</body>
+</html>
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -82,17 +82,17 @@ function nsContextMenu(aXulMenu, aBrowse
   this.linkURI           = null;
   this.linkProtocol      = null;
   this.inFrame           = false;
   this.hasBGImage        = false;
   this.isTextSelected    = false;
   this.isContentSelected = false;
   this.shouldDisplay     = true;
   this.isDesignMode      = false;
-  this.possibleSpellChecking = false;
+  this.onEditableArea = false;
   this.ellipsis = "\u2026";
   try {
     this.ellipsis = gPrefService.getComplexValue("intl.ellipsis",
                                                  Ci.nsIPrefLocalizedString).data;
   } catch (e) { }
 
   // Initialize new menu.
   this.initMenu(aXulMenu, aBrowser);
@@ -362,17 +362,17 @@ nsContextMenu.prototype = {
     this.showItem("context-blockimage", this.onImage && hostLabel &&
       !gPrivateBrowsingUI.privateBrowsingEnabled);
   },
 
   initSpellingItems: function() {
     var canSpell = InlineSpellCheckerUI.canSpellCheck;
     var onMisspelling = InlineSpellCheckerUI.overMisspelling;
     this.showItem("spell-check-enabled", canSpell);
-    this.showItem("spell-separator", canSpell || this.possibleSpellChecking);
+    this.showItem("spell-separator", canSpell || this.onEditableArea);
     if (canSpell) {
       document.getElementById("spell-check-enabled")
               .setAttribute("checked", InlineSpellCheckerUI.enabled);
     }
 
     this.showItem("spell-add-to-dictionary", onMisspelling);
 
     // suggestion list
@@ -390,17 +390,17 @@ nsContextMenu.prototype = {
     // dictionary list
     this.showItem("spell-dictionaries", InlineSpellCheckerUI.enabled);
     if (canSpell) {
       var dictMenu = document.getElementById("spell-dictionaries-menu");
       var dictSep = document.getElementById("spell-language-separator");
       InlineSpellCheckerUI.addDictionaryListToMenu(dictMenu, dictSep);
       this.showItem("spell-add-dictionaries-main", false);
     }
-    else if (this.possibleSpellChecking) {
+    else if (this.onEditableArea) {
       // when there is no spellchecker but we might be able to spellcheck
       // add the add to dictionaries item. This will ensure that people
       // with no dictionaries will be able to download them
       this.showItem("spell-add-dictionaries-main", true);
     }
     else
       this.showItem("spell-add-dictionaries-main", false);
   },
@@ -498,17 +498,17 @@ nsContextMenu.prototype = {
     this.onLink            = false;
     this.linkURL           = "";
     this.linkURI           = null;
     this.linkProtocol      = "";
     this.onMathML          = false;
     this.inFrame           = false;
     this.hasBGImage        = false;
     this.bgImageURL        = "";
-    this.possibleSpellChecking = false;
+    this.onEditableArea = false;
 
     // Clear any old spellchecking items from the menu, this used to
     // be in the menu hiding code but wasn't getting called in all
     // situations. Here, we can ensure it gets cleaned up any time the
     // menu is shown. Note: must be before uninit because that clears the
     // internal vars
     InlineSpellCheckerUI.clearSuggestionsFromMenu();
     InlineSpellCheckerUI.clearDictionaryListFromMenu();
@@ -547,26 +547,26 @@ nsContextMenu.prototype = {
         this.onAudio = true;
         this.mediaURL = this.target.currentSrc || this.target.src;
       }
       else if (this.target instanceof HTMLInputElement ) {
         this.onTextInput = this.isTargetATextBox(this.target);
         // allow spellchecking UI on all writable text boxes except passwords
         if (this.onTextInput && ! this.target.readOnly &&
             this.target.type != "password") {
-          this.possibleSpellChecking = true;
+          this.onEditableArea = true;
           InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor);
           InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
         }
         this.onKeywordField = this.isTargetAKeywordField(this.target);
       }
       else if (this.target instanceof HTMLTextAreaElement) {
         this.onTextInput = true;
         if (!this.target.readOnly) {
-          this.possibleSpellChecking = true;
+          this.onEditableArea = true;
           InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor);
           InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
         }
       }
       else if (this.target instanceof HTMLHtmlElement) {
         var bodyElt = this.target.ownerDocument.body;
         if (bodyElt) {
           let computedURL;
@@ -657,49 +657,51 @@ nsContextMenu.prototype = {
       this.onMathML = true;
 
     // See if the user clicked in a frame.
     var docDefaultView = this.target.ownerDocument.defaultView;
     if (docDefaultView != docDefaultView.top)
       this.inFrame = true;
 
     // if the document is editable, show context menu like in text inputs
-    var win = this.target.ownerDocument.defaultView;
-    if (win) {
-      var isEditable = false;
-      try {
-        var editingSession = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                                .getInterface(Ci.nsIWebNavigation)
-                                .QueryInterface(Ci.nsIInterfaceRequestor)
-                                .getInterface(Ci.nsIEditingSession);
-        if (editingSession.windowIsEditable(win) &&
-            this.getComputedStyle(this.target, "-moz-user-modify") == "read-write") {
-          isEditable = true;
+    if (!this.onEditableArea) {
+      var win = this.target.ownerDocument.defaultView;
+      if (win) {
+        var isEditable = false;
+        try {
+          var editingSession = win.QueryInterface(Ci.nsIInterfaceRequestor)
+                                  .getInterface(Ci.nsIWebNavigation)
+                                  .QueryInterface(Ci.nsIInterfaceRequestor)
+                                  .getInterface(Ci.nsIEditingSession);
+          if (editingSession.windowIsEditable(win) &&
+              this.getComputedStyle(this.target, "-moz-user-modify") == "read-write") {
+            isEditable = true;
+          }
         }
-      }
-      catch(ex) {
-        // If someone built with composer disabled, we can't get an editing session.
-      }
+        catch(ex) {
+          // If someone built with composer disabled, we can't get an editing session.
+        }
 
-      if (isEditable) {
-        this.onTextInput       = true;
-        this.onKeywordField    = false;
-        this.onImage           = false;
-        this.onLoadedImage     = false;
-        this.onCompletedImage  = false;
-        this.onMathML          = false;
-        this.inFrame           = false;
-        this.hasBGImage        = false;
-        this.isDesignMode      = true;
-        this.possibleSpellChecking = true;
-        InlineSpellCheckerUI.init(editingSession.getEditorForWindow(win));
-        var canSpell = InlineSpellCheckerUI.canSpellCheck;
-        InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
-        this.showItem("spell-check-enabled", canSpell);
-        this.showItem("spell-separator", canSpell);
+        if (isEditable) {
+          this.onTextInput       = true;
+          this.onKeywordField    = false;
+          this.onImage           = false;
+          this.onLoadedImage     = false;
+          this.onCompletedImage  = false;
+          this.onMathML          = false;
+          this.inFrame           = false;
+          this.hasBGImage        = false;
+          this.isDesignMode      = true;
+          this.onEditableArea = true;
+          InlineSpellCheckerUI.init(editingSession.getEditorForWindow(win));
+          var canSpell = InlineSpellCheckerUI.canSpellCheck;
+          InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
+          this.showItem("spell-check-enabled", canSpell);
+          this.showItem("spell-separator", canSpell);
+        }
       }
     }
   },
 
   // Returns the computed style attribute for the given element.
   getComputedStyle: function(aElem, aProp) {
     return aElem.ownerDocument
                 .defaultView
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -65,16 +65,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug364677.html \
 		bug364677-data.xml \
 		bug364677-data.xml^headers^ \
 		test_offline_gzip.html \
 		gZipOfflineChild.html \
 		gZipOfflineChild.html^headers^ \
 		gZipOfflineChild.cacheManifest \
 		gZipOfflineChild.cacheManifest^headers^ \
+		test_bug452451.html \
 		$(NULL)
 
 # The following tests are disabled because they are unreliable:
 #   browser_bug423833.js is bug 428712
 #   browser_sanitize-download-history.js is bug 432425
 #
 # browser_sanitizeDialog_treeView.js is disabled until the tree view is added
 # back to the clear recent history dialog (santize.xul), if it ever is (bug
--- a/browser/base/content/test/browser_bug321000.js
+++ b/browser/base/content/test/browser_bug321000.js
@@ -58,72 +58,31 @@ var gTests = [
 ];
 
 // Test for bug 23485 and bug 321000.
 // Urlbar should strip newlines,
 // search bar should replace newlines with spaces.
 function test() {
   waitForExplicitFinish();
 
+  let cbHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].
+                 getService(Ci.nsIClipboardHelper);
+
   // Put a multi-line string in the clipboard.
-  info("About to put a string in clipboard");
-  Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper)
-                                             .copyString(kTestString);
-
   // Setting the clipboard value is an async OS operation, so we need to poll
   // the clipboard for valid data before going on.
-  setTimeout(poll_clipboard, 100);
-}
-
-var runCount = 0;
-function poll_clipboard() {
-  // Poll for a maximum of 5s (each run happens after 100ms).
-  if (++runCount > 50) {
-    // Log the failure.
-    ok(false, "Timed out while polling clipboard for pasted data");
-    // Cleanup and interrupt the test.
-    finish_test();
-    return;
-  }
-
-  info("Polling clipboard cycle " + runCount);
-  var clip = Cc["@mozilla.org/widget/clipboard;1"].
-             getService(Ci.nsIClipboard);
-  var trans = Cc["@mozilla.org/widget/transferable;1"].
-              createInstance(Ci.nsITransferable);
-  trans.addDataFlavor("text/unicode");
-  var str = new Object();
-  try {
-    // This code could throw if the clipboard is not set yet.
-    clip.getData(trans, clip.kGlobalClipboard);
-    trans.getTransferData("text/unicode", str, {});
-    str = str.value.QueryInterface(Ci.nsISupportsString);
-  }
-  catch(ex) {}
-
-  if (kTestString == str) {
-    next_test();
-  }
-  else
-    setTimeout(poll_clipboard, 100);
+  waitForClipboard(kTestString, function() { cbHelper.copyString(kTestString); },
+                   next_test, finish);
 }
 
 function next_test() {
-  if (gTests.length) {
-    var currentTest = gTests.shift();
-    test_paste(currentTest);
-  }
-  else {
-    // No more tests to run.
-    // Clear the clipboard, emptyClipboard would not clear the native one, so
-    // we are setting it to an empty string.
-    Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper)
-                                               .copyString("");
+  if (gTests.length)
+    test_paste(gTests.shift());
+  else
     finish();
-  }
 }
 
 function test_paste(aCurrentTest) {
   var element = aCurrentTest.element;
 
   // Register input listener.
   var inputListener = {
     test: aCurrentTest,
--- a/browser/base/content/test/browser_bug556061.js
+++ b/browser/base/content/test/browser_bug556061.js
@@ -30,129 +30,96 @@
  * 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 ***** */
 
-let cbSvc = Cc["@mozilla.org/widget/clipboard;1"].
-            getService(Ci.nsIClipboard);
-
 let testURL = "http://example.org/browser/browser/base/content/test/dummy_page.html";
 let testActionURL = "moz-action:switchtab," + testURL;
 let testTab;
-let clipboardText = "";
-let currentClipboardText = null;
-let clipboardPolls = 0;
-
-// The clipboard can have a string value without it being the one we expect, so
-// we'll check the current value against the previous value to see if it changed.
-// We can do this because our expected clipboard value should be different each
-// time we wait.
-function waitForClipboard() {
-  // Poll for a maximum of 5s (each run happens after 100ms).
-  if (++clipboardPolls > 50) {
-    // Log the failure.
-    ok(false, "Timed out while polling clipboard for pasted data");
-    // Cleanup and interrupt the test.
-    cleanup();
-    return;
-  }
-
-  let xferable = Cc["@mozilla.org/widget/transferable;1"].
-                 createInstance(Ci.nsITransferable);
-  xferable.addDataFlavor("text/unicode");
-  cbSvc.getData(xferable, cbSvc.kGlobalClipboard);
-  try {
-    let data = {};
-    xferable.getTransferData("text/unicode", data, {});
-    currentClipboardText = data.value.QueryInterface(Ci.nsISupportsString).data;
-  } catch (e) {}
-
-  if (currentClipboardText == clipboardText) {
-    setTimeout(waitForClipboard, 100);
-  } else {
-    clipboardText = currentClipboardText;
-    runNextTest();
-  }
-}
 
 function runNextTest() {
-  // reset clipboard polling count
-  clipboardPolls = 0;
-  // run next test, just assume we won't call in here without more tests
-  tests.shift()();
+  if (tests.length) {
+    let t = tests.shift();
+    waitForClipboard(t.expected, t.setup, function() {
+      t.success();
+      runNextTest();
+    }, cleanup);
+  }
+  else {
+    cleanup();
+  }
 }
 
 function cleanup() {
   gBrowser.removeTab(testTab);
   finish();
 }
 
-// Tests in order. Some tests setup for the next actual test...
 let tests = [
-  function () {
-    // Set the urlbar to include the moz-action
-    gURLBar.value = testActionURL;
-    is(gURLBar.value, testActionURL, "gURLBar.value starts with correct value");
-
-    // Focus the urlbar so we can select it all & copy
-    gURLBar.focus();
-    gURLBar.select();
-    goDoCommand("cmd_copy");
-    waitForClipboard();
-  },
-  function () {
-    is(clipboardText, testURL, "Clipboard has the correct value");
-    // We shouldn't have changed the value of gURLBar
-    is(gURLBar.value, testActionURL, "gURLBar.value didn't change when copying");
-
-    // Set selectionStart/End manually and make sure it matches the substring
-    gURLBar.selectionStart = 0;
-    gURLBar.selectionEnd = 10;
-    goDoCommand("cmd_copy");
-    waitForClipboard();
-  },
-  function () {
-    is(clipboardText, testURL.substring(0, 10), "Clipboard has the correct value");
-    is(gURLBar.value, testActionURL, "gURLBar.value didn't change when copying");
+  {
+    expected: testURL,
+    setup: function() {
+      gURLBar.value = testActionURL;
+      is(gURLBar.value, testActionURL, "gURLBar.value starts with correct value");
 
-    // Setup for cut test...
-    // Select all
-    gURLBar.select();
-    goDoCommand("cmd_cut");
-    waitForClipboard();
+      // Focus the urlbar so we can select it all & copy
+      gURLBar.focus();
+      gURLBar.select();
+      goDoCommand("cmd_copy");
+    },
+    success: function() {
+      is(gURLBar.value, testActionURL, "gURLBar.value didn't change when copying");
+    }
   },
-  function () {
-    is(clipboardText, testURL, "Clipboard has the correct value");
-    is(gURLBar.value, "", "gURLBar.value is now empty");
-
-    // Reset urlbar value
-    gURLBar.value = testActionURL;
-    // Sanity check that we have the right value
-    is(gURLBar.value, testActionURL, "gURLBar.value starts with correct value");
+  {
+    expected: testURL.substring(0, 10),
+    setup: function() {
+      // Set selectionStart/End manually and make sure it matches the substring
+      gURLBar.selectionStart = 0;
+      gURLBar.selectionEnd = 10;
+      goDoCommand("cmd_copy");
+    },
+    success: function() {
+      is(gURLBar.value, testActionURL, "gURLBar.value didn't change when copying");
+    }
+  },
+  {
+    expected: testURL,
+    setup: function() {
+      // Setup for cut test...
+      // Select all
+      gURLBar.select();
+      goDoCommand("cmd_cut");
+    },
+    success: function() {
+      is(gURLBar.value, "", "gURLBar.value is now empty");
+    }
+  },
+  {
+    expected: testURL.substring(testURL.length - 10, testURL.length),
+    setup: function() {
+      // Reset urlbar value
+      gURLBar.value = testActionURL;
+      // Sanity check that we have the right value
+      is(gURLBar.value, testActionURL, "gURLBar.value starts with correct value");
 
-    // Now just select part of the value & cut that.
-    gURLBar.selectionStart = testURL.length - 10;
-    gURLBar.selectionEnd = testURL.length;
-
-    goDoCommand("cmd_cut");
-    waitForClipboard();
-  },
-  function () {
-    is(clipboardText, testURL.substring(testURL.length - 10, testURL.length),
-       "Clipboard has the correct value");
-    is(gURLBar.value, testURL.substring(0, testURL.length - 10), "gURLBar.value has the correct value");
-
-    // We're done, so just finish up
-    cleanup();
+      // Now just select part of the value & cut that.
+      gURLBar.selectionStart = testURL.length - 10;
+      gURLBar.selectionEnd = testURL.length;
+      goDoCommand("cmd_cut");
+    },
+    success: function() {
+      is(gURLBar.value, testURL.substring(0, testURL.length - 10), "gURLBar.value has the correct value");
+    }
   }
-]
+];
 
 function test() {
   waitForExplicitFinish();
   testTab = gBrowser.addTab();
   gBrowser.selectedTab = testTab;
 
   // Kick off the testing
   runNextTest();
--- a/browser/base/content/test/subtst_contextmenu.html
+++ b/browser/base/content/test/subtst_contextmenu.html
@@ -13,11 +13,14 @@ Browser context menu subtest.
 <img id="test-image" src="ctxmenu-image.png">
 <canvas id="test-canvas" width="100" height="100" style="background-color: blue"></canvas>
 <video id="test-video-ok"  src="video.ogg" width="100" height="100" style="background-color: green"></video>
 <video id="test-video-bad" src="bogus.duh" width="100" height="100" style="background-color: orange"></video>
 <video id="test-video-bad2" width="100" height="100" style="background-color: yellow">
   <source src="bogus.duh" type="video/durrrr;">
 </video>
 <iframe id="test-iframe" width="98"  height="98" style="border: 1px solid black"></iframe>
+<textarea id="test-textarea">chssseesbbbie</textarea> <!-- a weird word which generates only one suggestion -->
+<div id="test-contenteditable" contenteditable="true">chssseefsbbbie</div> <!-- a more weird word which generates no suggestions -->
+<input id="test-input-spellcheck" type="text" spellcheck="true" autofocus value="prodkjfgigrty"> <!-- this one also generates one suggestion -->
 
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/test_bug452451.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=452451
+-->
+<head>
+  <title>Test for Bug 452451</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=452451">Mozilla Bug 452451</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 452451 **/
+
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  const prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                          .getService(Components.interfaces.nsIPrefBranch);
+
+  ok(prefs.getBoolPref("javascript.options.relimit"),
+     "relimit should be enabled by default");
+
+  /**
+   * Following tests are inspired from:
+   * js/src/tests/js1_5/extensions/regress-330569.js
+   */
+
+  var s;
+  const expected = 'InternalError: regular expression too complex';
+
+  s = '<!DOCTYPE HTML PUBLIC>' +
+      '<html>\n' +
+      '<head>\n' +
+      '<meta http-equiv="content-type" content="text/html">\n' +
+      '<title></title>\n'+
+      '</head>\n' +
+      '<body>\n' +
+      '<!-- hello -->\n' +
+      '<script language="JavaScript">\n' +
+      'var s = document. body. innerHTML;\n' +
+      'var d = s. replace (/<!--(.*|\n)*-->/, "");\n' +
+      '<\/script>\n' +
+      '<\/body>\n' +
+      '<\/html>\n';
+
+  try {
+    /<!--(.*|\n)*-->/.exec(s);
+  }
+  catch(ex) {
+    actual = ex;
+  }
+
+  is(actual, expected, "reg exp too complex error should have been thrown");
+
+  function testre( re, n )
+  {
+    var txt = '';
+    for (var i= 0; i <= n; ++i) {
+      txt += ',';
+      re.test(txt);
+    }
+  }
+
+  try {
+    testre( /(?:,*)*x/, 22 );
+  }
+  catch(ex) {
+    actual = ex;
+  }
+
+  is(actual, expected, "reg exp too complex error should have been thrown");
+
+  try {
+    testre( /(?:,|,)*x/, 22 );
+  }
+  catch(ex) {
+    actual = ex;
+  }
+
+  is(actual, expected, "reg exp too complex error should have been thrown");
+
+  try {
+    testre( /(?:,|,|,|,|,)*x/, 10 );
+  }
+  catch(ex) {
+    actual = ex;
+  }
+
+  is(actual, expected, "reg exp too complex error should have been thrown");
+</script>
+</pre>
+</body>
+</html>
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -44,24 +44,37 @@ function getVisibleMenuItems(aMenu) {
         if (item.hidden)
             continue;
 
         var key = item.accessKey;
         if (key)
             key = key.toLowerCase();
 
         if (item.nodeName == "menuitem") {
-            ok(item.id, "child menuitem #" + i + " has an ID");
+            var isSpellSuggestion = item.className == "spell-suggestion";
+            if (isSpellSuggestion) {
+              is(item.id, "", "child menuitem #" + i + " is a spelling suggestion");
+            } else {
+              ok(item.id, "child menuitem #" + i + " has an ID");
+            }
             ok(item.label.length, "menuitem " + item.id + " has a label");
-            ok(key, "menuitem " + item.id + " has an access key");
-            if (accessKeys[key])
-                ok(false, "menuitem " + item.id + " has same accesskey as " + accessKeys[key]);
-            else
-                accessKeys[key] = item.id;
-            items.push(item.id);
+            if (isSpellSuggestion) {
+              is(key, "", "Spell suggestions shouldn't have an access key");
+              items.push("*" + item.label);
+            } else if (item.id.indexOf("spell-check-dictionary-") != 0 &&
+                       item.id != "spell-no-suggestions") {
+              ok(key, "menuitem " + item.id + " has an access key");
+              if (accessKeys[key])
+                  ok(false, "menuitem " + item.id + " has same accesskey as " + accessKeys[key]);
+              else
+                  accessKeys[key] = item.id;
+            }
+            if (!isSpellSuggestion) {
+              items.push(item.id);
+            }
             items.push(!item.disabled);
         } else if (item.nodeName == "menuseparator") {
             ok(true, "--- seperator id is " + item.id);
             items.push("---");
             items.push(null);
         } else if (item.nodeName == "menu") {
             ok(item.id, "child menu #" + i + " has an ID");
             ok(key, "menu has an access key");
@@ -301,17 +314,88 @@ function runTest(testNum) {
                                "context-printframe",        true,
                                "---",                       null,
                                "context-viewframesource",   true,
                                "context-viewframeinfo",     true], null,
                           "---",                  null,
                           "context-viewsource",   true,
                           "context-viewinfo",     true]);
         closeContextMenu();
+        openContextMenuFor(textarea); // Invoke context menu for next test.
+        break;
 
+    case 12:
+        // Context menu for textarea
+        checkContextMenu(["*chubbiness",         true, // spelling suggestion
+                          "spell-add-to-dictionary", true,
+                          "---",                 null,
+                          "context-undo",        false,
+                          "---",                 null,
+                          "context-cut",         false,
+                          "context-copy",        false,
+                          "context-paste",       null, // ignore clipboard state
+                          "context-delete",      false,
+                          "---",                 null,
+                          "context-selectall",   true,
+                          "---",                 null,
+                          "spell-check-enabled", true,
+                          "spell-dictionaries",  true,
+                              ["spell-check-dictionary-en-US", true,
+                               "---",                          null,
+                               "spell-add-dictionaries",       true], null]);
+
+        closeContextMenu();
+        openContextMenuFor(contenteditable); // Invoke context menu for next test.
+        break;
+
+    case 13:
+        // Context menu for contenteditable
+        checkContextMenu(["spell-no-suggestions", false,
+                          "spell-add-to-dictionary", true,
+                          "---",                 null,
+                          "context-undo",        false,
+                          "---",                 null,
+                          "context-cut",         false,
+                          "context-copy",        false,
+                          "context-paste",       null, // ignore clipboard state
+                          "context-delete",      false,
+                          "---",                 null,
+                          "context-selectall",   true,
+                          "---",                 null,
+                          "spell-check-enabled", true,
+                          "spell-dictionaries",  true,
+                              ["spell-check-dictionary-en-US", true,
+                               "---",                          null,
+                               "spell-add-dictionaries",       true], null]);
+
+        closeContextMenu();
+        openContextMenuFor(inputspell); // Invoke context menu for next test.
+        break;
+
+    case 14:
+        // Context menu for spell-check input
+        checkContextMenu(["*prodigality",        true, // spelling suggestion
+                          "spell-add-to-dictionary", true,
+                          "---",                 null,
+                          "context-undo",        false,
+                          "---",                 null,
+                          "context-cut",         false,
+                          "context-copy",        false,
+                          "context-paste",       null, // ignore clipboard state
+                          "context-delete",      false,
+                          "---",                 null,
+                          "context-selectall",   true,
+                          "---",                 null,
+                          "spell-check-enabled", true,
+                          "spell-dictionaries",  true,
+                              ["spell-check-dictionary-en-US", true,
+                               "---",                          null,
+                               "spell-add-dictionaries",       true], null]);
+
+        closeContextMenu();
         subwindow.close();
         SimpleTest.finish();
         return;
 
     /*
      * Other things that would be nice to test:
      *  - selected text
      *  - spelling / misspelled word (in text input?)
@@ -326,17 +410,18 @@ function runTest(testNum) {
         return;
   }
 
 }
 
 
 var testNum = 1;
 var subwindow, chromeWin, contextMenu;
-var text, link, mailto, input, img, canvas, video, iframe;
+var text, link, mailto, input, img, canvas, video, iframe,
+    textarea, contenteditable, inputspell;
 
 function startTest() {
     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
     chromeWin = subwindow
                     .QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .rootTreeItem
@@ -351,16 +436,19 @@ function startTest() {
     mailto = subwindow.document.getElementById("test-mailto");
     input  = subwindow.document.getElementById("test-input");
     img    = subwindow.document.getElementById("test-image");
     canvas = subwindow.document.getElementById("test-canvas");
     video_ok   = subwindow.document.getElementById("test-video-ok");
     video_bad  = subwindow.document.getElementById("test-video-bad");
     video_bad2 = subwindow.document.getElementById("test-video-bad2");
     iframe = subwindow.document.getElementById("test-iframe");
+    textarea = subwindow.document.getElementById("test-textarea");
+    contenteditable = subwindow.document.getElementById("test-contenteditable");
+    inputspell = subwindow.document.getElementById("test-input-spellcheck");
 
     contextMenu.addEventListener("popupshown", function() { runTest(++testNum); }, false);
     runTest(1);
 }
 
 // We open this in a separate window, because the Mochitests run inside a frame.
 // The frame causes an extra menu item, and prevents running the test
 // standalone (ie, clicking the test name in the Mochitest window) to see
--- a/build/autoconf/nss.m4
+++ b/build/autoconf/nss.m4
@@ -4,17 +4,17 @@
 # Based upon gtk.m4 (also PD) by Owen Taylor
 
 dnl AM_PATH_NSS([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
 dnl Test for NSS, and define NSS_CFLAGS and NSS_LIBS
 AC_DEFUN(AM_PATH_NSS,
 [dnl
 
 AC_ARG_WITH(nss-prefix,
-	[  --with-nss-prefix=PFX  Prefix where NSS is installed],
+	[  --with-nss-prefix=PFX   Prefix where NSS is installed],
 	nss_config_prefix="$withval",
 	nss_config_prefix="")
 
 AC_ARG_WITH(nss-exec-prefix,
 	[  --with-nss-exec-prefix=PFX
                           Exec prefix where NSS is installed],
 	nss_config_exec_prefix="$withval",
 	nss_config_exec_prefix="")
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -144,24 +144,26 @@ stl_compiler = gcc
 else
 ifdef _MSC_VER
 stl_compiler = msvc
 endif
 endif
 endif
 
 ifdef stl_compiler
-stl-wrappers-sentinel: $(srcdir)/make-stl-wrappers.py $(srcdir)/$(stl_compiler)-stl-wrapper.template.h $(srcdir)/stl-headers $(GLOBAL_DEPS)
+STL_WRAPPERS_SENTINEL = $(DIST)/stl_wrappers/sentinel
+
+$(STL_WRAPPERS_SENTINEL): $(srcdir)/make-stl-wrappers.py $(srcdir)/$(stl_compiler)-stl-wrapper.template.h $(srcdir)/stl-headers $(GLOBAL_DEPS)
 	$(PYTHON) $(srcdir)/make-stl-wrappers.py stl_wrappers $(stl_compiler) $(srcdir)/$(stl_compiler)-stl-wrapper.template.h $(srcdir)/stl-headers
 	$(PYTHON) $(srcdir)/nsinstall.py stl_wrappers $(DIST)
-	touch stl-wrappers-sentinel
+	touch $(STL_WRAPPERS_SENTINEL)
 
-export:: stl-wrappers-sentinel
+export:: $(STL_WRAPPERS_SENTINEL)
 
-GARBAGE += stl-wrappers-sentinel
+GARBAGE += $(STL_WRAPPERS_SENTINEL)
 GARBAGE_DIRS += stl_wrappers
 endif
 
 install::
 	$(SYSINSTALL) $(IFLAGS1) $(DEPTH)/mozilla-config.h $(DESTDIR)$(includedir)
 
 GARBAGE += \
 	$(FINAL_LINK_COMPS) $(FINAL_LINK_LIBS) $(FINAL_LINK_COMP_NAMES) buildid $(srcdir)/*.pyc
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -591,16 +591,17 @@ MOZILLA_OFFICIAL = @MOZILLA_OFFICIAL@
 # Win32 options
 MOZ_BROWSE_INFO	= @MOZ_BROWSE_INFO@
 MOZ_TOOLS_DIR	= @MOZ_TOOLS_DIR@
 MOZ_QUANTIFY	= @MOZ_QUANTIFY@
 MSMANIFEST_TOOL = @MSMANIFEST_TOOL@
 WIN32_REDIST_DIR = @WIN32_REDIST_DIR@
 WIN32_CRT_SRC_DIR = @WIN32_CRT_SRC_DIR@
 MOZ_MEMORY_LDFLAGS = @MOZ_MEMORY_LDFLAGS@
+MOZ_CRT_CPU_ARCH = @MOZ_CRT_CPU_ARCH@
 
 # This is for custom CRT building
 ifdef MOZ_MEMORY
 ifdef WIN32_CRT_SRC_DIR
 DLLFLAGS = @DLLFLAGS@
 endif
 endif
 
--- a/configure.in
+++ b/configure.in
@@ -105,17 +105,17 @@ dnl ====================================
 _SUBDIR_HOST_CFLAGS="$HOST_CFLAGS"
 _SUBDIR_HOST_CXXFLAGS="$HOST_CXXFLAGS"
 _SUBDIR_HOST_LDFLAGS="$HOST_LDFLAGS"
 _SUBDIR_CONFIG_ARGS="$ac_configure_args"
 
 dnl Set the version number of the libs included with mozilla
 dnl ========================================================
 MOZJPEG=62
-MOZPNG=10400
+MOZPNG=10401
 MOZZLIB=0x1230
 NSPR_VERSION=4
 NSS_VERSION=3
 
 dnl Set the minimum version of toolkit libs used by mozilla
 dnl ========================================================
 GLIB_VERSION=1.2.0
 LIBIDL_VERSION=0.6.3
@@ -210,22 +210,22 @@ case "$target" in
     if test -z "$CXX"; then CXX=g++-4.2; fi
     ;;
 esac
 fi
 
 COMPILE_ENVIRONMENT=1
 MOZ_ARG_DISABLE_BOOL(compile-environment,
 [  --disable-compile-environment
-                           Disable compiler/library checks.],
+                          Disable compiler/library checks.],
     COMPILE_ENVIRONMENT= )
 AC_SUBST(COMPILE_ENVIRONMENT)
 
 MOZ_ARG_WITH_STRING(l10n-base,
-[  --with-l10n-base=DIR     path to l10n repositories],
+[  --with-l10n-base=DIR    path to l10n repositories],
     L10NBASEDIR=$withval)
 if test ! -z "$L10NBASEDIR"; then
     if test "$L10NBASEDIR" = "yes" -o "$L10NBASEDIR" = "no"; then
         AC_MSG_ERROR([--with-l10n-base must specify a path])
     elif test -d "$L10NBASEDIR"; then
         L10NBASEDIR=`cd "$L10NBASEDIR" && pwd`
     else
         AC_MSG_ERROR([Invalid value --with-l10n-base, $L10NBASEDIR doesn't exist])
@@ -241,37 +241,37 @@ fi
 
 dnl ========================================================
 dnl = Android uses a very custom (hacky) toolchain; we need to do this
 dnl = here, so that the compiler checks can succeed
 dnl ========================================================
 
 MOZ_ARG_WITH_STRING(android-ndk,
 [  --with-android-ndk=DIR
-                           location where the Android NDK can be found],
+                          location where the Android NDK can be found],
     android_ndk=$withval)
 
 MOZ_ARG_WITH_STRING(android-toolchain,
 [  --with-android-toolchain=DIR
-                           location of the android toolchain, default NDK/build/prebuilt/HOST/arm-eabi-4.4.0],
+                          location of the android toolchain, default NDK/build/prebuilt/HOST/arm-eabi-4.4.0],
     android_toolchain=$withval)
 
 MOZ_ARG_WITH_STRING(android-platform,
 [  --with-android-platform=DIR
-                           location of NDK platform dir, default NDK/build/platforms/android-5/arch-arm],
+                          location of NDK platform dir, default NDK/build/platforms/android-5/arch-arm],
     android_platform=$withval)
 
 MOZ_ARG_WITH_STRING(android-sdk,
 [  --with-android-sdk=DIR
-                           location where the Android SDK can be found (base directory, e.g. .../android/platforms/android-6)],
+                          location where the Android SDK can be found (base directory, e.g. .../android/platforms/android-6)],
     android_sdk=$withval)
 
 MOZ_ARG_WITH_STRING(android-tools,
 [  --with-android-tools=DIR
-                           location where the Android Tools can be found (base directory, e.g. .../android/tools)],
+                          location where the Android Tools can be found (base directory, e.g. .../android/tools)],
     android_tools=$withval)
 
 if test "$target" = "arm-android-eabi" ; then
     if test -z "$android_ndk" ; then
         AC_MSG_ERROR([You must specify --with-android-ndk=/path/to/ndk when targeting Android.])
     fi
 
     if test -z "$android_sdk" ; then
@@ -354,22 +354,22 @@ AR_FLAGS='cr $@'
 if test "$COMPILE_ENVIRONMENT"; then
 
 dnl Do some special WinCE toolchain stuff
 case "$target" in
 *wince|*winmo)
 
     MOZ_ARG_WITH_STRING(wince-sdk,
     [  --with-wince-sdk=WINCE_SDK_DIR
-                        The path to the Windows CE SDK],
+                          The path to the Windows CE SDK],
     WINCE_SDK_DIR=$withval)
 
     MOZ_ARG_WITH_STRING(ogles-sdk,
     [  --with-ogles-sdk=OGLES_SDK_DIR
-                        The path to the OGLES SDK],
+                          The path to the OGLES SDK],
     OGLES_SDK_DIR=$withval)
 
     AC_DEFINE(WINCE)
     
     export WINCE=1
 
     echo -----------------------------------------------------------------------------
     echo Building Windows CE Shunt Library and Tool Chain
@@ -1099,17 +1099,17 @@ esac
 AC_SUBST(MACOSX_DEPLOYMENT_TARGET)
 
 dnl ========================================================
 dnl = Mac OS X SDK support
 dnl ========================================================
 MACOS_SDK_DIR=
 NEXT_ROOT=
 MOZ_ARG_WITH_STRING(macos-sdk,
-[  --with-macos-sdk=dir   Location of platform SDK to use (Mac OS X only)],
+[  --with-macos-sdk=dir    Location of platform SDK to use (Mac OS X only)],
     MACOS_SDK_DIR=$withval)
 
 dnl MACOS_SDK_DIR will be set to the SDK location whenever one is in use.
 dnl NEXT_ROOT will be set and exported only if it's needed.
 AC_SUBST(MACOS_SDK_DIR)
 AC_SUBST(NEXT_ROOT)
 
 if test "$MACOS_SDK_DIR"; then
@@ -4646,17 +4646,17 @@ if test -n "$LIBXUL_SDK"; then
 else
     LIBXUL_DIST="$MOZ_BUILD_ROOT/dist"
 fi
 AC_SUBST(LIBXUL_DIST)
 
 SYSTEM_LIBXUL=
 
 MOZ_ARG_WITH_BOOL(system-libxul,
-[  --with-system-libxul   Use system installed libxul SDK],
+[  --with-system-libxul    Use system installed libxul SDK],
     SYSTEM_LIBXUL=1)
 
 if test -n "$SYSTEM_LIBXUL" && test -z "$MOZ_ENABLE_LIBXUL"; then
     AC_MSG_ERROR([--with-system-libxul needs --with-libxul-sdk])
 fi
 
 dnl ========================================================
 dnl = If NSPR was not detected in the system, 
@@ -4735,17 +4735,17 @@ AC_SUBST(MOZ_LIBEVENT_INCLUDES)
 AC_SUBST(MOZ_LIBEVENT_LIBS)
 
 dnl ========================================================
 dnl = If NSS was not detected in the system, 
 dnl = use the one in the source tree (mozilla/security/nss)
 dnl ========================================================
 
 MOZ_ARG_WITH_BOOL(system-nss,
-[  --with-system-nss      Use system installed NSS],
+[  --with-system-nss       Use system installed NSS],
     _USE_SYSTEM_NSS=1 )
 
 if test -n "$_USE_SYSTEM_NSS"; then
     AM_PATH_NSS(3.12.6, [MOZ_NATIVE_NSS=1], [MOZ_NATIVE_NSS=])
 fi
 
 if test -n "$MOZ_NATIVE_NSS"; then
    NSS_LIBS="$NSS_LIBS -lcrmf"
@@ -4930,44 +4930,47 @@ if test "${PNG_DIR}" -a -d "${PNG_DIR}" 
     PNG_LIBS="-L${PNG_DIR}/lib ${PNG_LIBS}"
 fi
 
 fi # SKIP_LIBRARY_CHECKS
 
 dnl system HunSpell Support
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(system-hunspell,
-[  --enable-system-hunspell  Use system hunspell (located with pkgconfig)],
+[  --enable-system-hunspell
+                          Use system hunspell (located with pkgconfig)],
     SYSTEM_HUNSPELL=1 )
 
 if test -n "$SYSTEM_HUNSPELL"; then
     PKG_CHECK_MODULES(MOZ_HUNSPELL, hunspell)
 fi
 
 AC_SUBST(SYSTEM_HUNSPELL)
 
 dnl ========================================================
 dnl Java SDK support
 dnl ========================================================
 JAVA_INCLUDE_PATH=
 MOZ_ARG_WITH_STRING(java-include-path,
-[  --with-java-include-path=dir   Location of Java SDK headers],
+[  --with-java-include-path=dir
+                          Location of Java SDK headers],
     JAVA_INCLUDE_PATH=$withval)
 
 JAVA_BIN_PATH=
 MOZ_ARG_WITH_STRING(java-bin-path,
-[  --with-java-bin-path=dir   Location of Java binaries (java, javac, jar)],
+[  --with-java-bin-path=dir
+                          Location of Java binaries (java, javac, jar)],
     JAVA_BIN_PATH=$withval)
 
 dnl ========================================================
 dnl Use ARM userspace kernel helpers; tell NSPR to enable
 dnl their usage and use them in spidermonkey.
 dnl ========================================================
 MOZ_ARG_WITH_BOOL(arm-kuser,
-[  --with-arm-kuser         Use kuser helpers (Linux/ARM only -- requires kernel 2.6.13 or later)],
+[  --with-arm-kuser        Use kuser helpers (Linux/ARM only -- requires kernel 2.6.13 or later)],
     USE_ARM_KUSER=1,
     USE_ARM_KUSER=)
 if test -n "$USE_ARM_KUSER"; then
    AC_DEFINE(USE_ARM_KUSER)
 fi
 
 dnl ========================================================
 dnl =
@@ -5324,17 +5327,18 @@ dnl ====================================
 dnl = startup-notification support module
 dnl ========================================================
 
 if test "$MOZ_ENABLE_GTK2"
 then
     MOZ_ENABLE_STARTUP_NOTIFICATION=
 
     MOZ_ARG_ENABLE_BOOL(startup-notification,
-    [  --enable-startup-notification       Enable startup-notification support (default: disabled) ],
+    [  --enable-startup-notification
+                          Enable startup-notification support (default: disabled) ],
         MOZ_ENABLE_STARTUP_NOTIFICATION=force,
         MOZ_ENABLE_STARTUP_NOTIFICATION=)
     if test "$MOZ_ENABLE_STARTUP_NOTIFICATION"
     then
         PKG_CHECK_MODULES(MOZ_STARTUP_NOTIFICATION,
                           libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_VERSION,
         [MOZ_ENABLE_STARTUP_NOTIFICATION=1], [
             if test "$MOZ_ENABLE_STARTUP_NOTIFICATION" = "force"
@@ -5420,17 +5424,18 @@ MOZ_ARG_ENABLE_STRING(ui-locale,
                           Select the user interface locale (default: en-US)],
     MOZ_UI_LOCALE=$enableval )
 AC_SUBST(MOZ_UI_LOCALE)
 
 dnl ========================================================
 dnl = Trademarked Branding 
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(official-branding,
-[  --enable-official-branding Enable Official mozilla.org Branding
+[  --enable-official-branding
+                          Enable Official mozilla.org Branding
                           Do not distribute builds with
                           --enable-official-branding unless you have
                           permission to use trademarks per
                           http://www.mozilla.org/foundation/trademarks/ .],
 [
   if test -z "$MOZ_OFFICIAL_BRANDING_DIRECTORY"; then
     AC_MSG_ERROR([You must specify MOZ_OFFICIAL_BRANDING_DIRECTORY to use --enable-official-branding.])
   else
@@ -5440,17 +5445,17 @@ MOZ_ARG_ENABLE_BOOL(official-branding,
 ], MOZ_OFFICIAL_BRANDING=)
 
 AC_SUBST(MOZ_OFFICIAL_BRANDING)
 if test -n "$MOZ_OFFICIAL_BRANDING"; then
   AC_DEFINE(MOZ_OFFICIAL_BRANDING)
 fi
 
 MOZ_ARG_WITH_STRING(branding,
-[  --with-branding=dir    Use branding from the specified directory.],
+[  --with-branding=dir     Use branding from the specified directory.],
     MOZ_BRANDING_DIRECTORY=$withval)
 
 REAL_BRANDING_DIRECTORY="${MOZ_BRANDING_DIRECTORY}"
 if test -z "$REAL_BRANDING_DIRECTORY"; then
   REAL_BRANDING_DIRECTORY=${MOZ_BUILD_APP}/branding/nightly
 fi
 
 if test -f "${_topsrcdir}/$REAL_BRANDING_DIRECTORY/configure.sh"; then
@@ -5458,33 +5463,34 @@ if test -f "${_topsrcdir}/$REAL_BRANDING
 fi
 
 AC_SUBST(MOZ_BRANDING_DIRECTORY)
 
 dnl ========================================================
 dnl = Distribution ID
 dnl ========================================================
 MOZ_ARG_WITH_STRING(distribution-id,
-[  --with-distribution-id=ID  Set distribution-specific id (default=org.mozilla)],
+[  --with-distribution-id=ID
+                          Set distribution-specific id (default=org.mozilla)],
 [ val=`echo $withval`
     MOZ_DISTRIBUTION_ID="$val"])
 
 if test -z "$MOZ_DISTRIBUTION_ID"; then
    MOZ_DISTRIBUTION_ID="org.mozilla"
 fi
 
 AC_DEFINE_UNQUOTED(MOZ_DISTRIBUTION_ID,"$MOZ_DISTRIBUTION_ID")
 AC_SUBST(MOZ_DISTRIBUTION_ID)
 
 
 dnl ========================================================
 dnl complex text support off by default
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(pango,
-[  --disable-pango Disable usage of Pango ],
+[  --disable-pango         Disable usage of Pango ],
     MOZ_PANGO=,
     MOZ_PANGO=1)
 
 dnl ========================================================
 dnl = Pango
 dnl ========================================================
 if test "$MOZ_ENABLE_GTK2"
 then
@@ -5627,17 +5633,17 @@ dnl ====================================
 dnl = libnotify support
 dnl ========================================================
 
 if test "$MOZ_ENABLE_GTK2"
 then
     MOZ_ENABLE_LIBNOTIFY=1
 
     MOZ_ARG_DISABLE_BOOL(libnotify,
-    [  --disable-libnotify       Disable libnotify support ],
+    [  --disable-libnotify     Disable libnotify support ],
     MOZ_ENABLE_LIBNOTIFY=,
     MOZ_ENABLE_LIBNOTIFY=1)
 
     if test "$MOZ_ENABLE_LIBNOTIFY"
     then
         AC_DEFINE(MOZ_ENABLE_LIBNOTIFY)
     fi
 fi
@@ -5713,17 +5719,17 @@ dnl ====================================
 dnl = dbus support
 dnl ========================================================
 
 if test "$MOZ_ENABLE_GTK2" || test "$MOZ_ENABLE_QT"
 then
     MOZ_ENABLE_DBUS=1
 
     MOZ_ARG_DISABLE_BOOL(dbus,
-    [  --disable-dbus       Disable dbus support ],
+    [  --disable-dbus          Disable dbus support ],
         MOZ_ENABLE_DBUS=,
         MOZ_ENABLE_DBUS=1)
 
     if test "$MOZ_ENABLE_DBUS"
     then
         PKG_CHECK_MODULES(MOZ_DBUS, dbus-1 >= $DBUS_VERSION)
         PKG_CHECK_MODULES(MOZ_DBUS_GLIB, dbus-glib-1 >= $DBUS_VERSION)
         AC_DEFINE(MOZ_ENABLE_DBUS)
@@ -5799,17 +5805,17 @@ MOZ_ARG_DISABLE_BOOL(plugins,
 [  --disable-plugins       Disable plugins support],
     MOZ_PLUGINS=,
     MOZ_PLUGINS=1)
 
 dnl ========================================================
 dnl = Disable building dbm
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(dbm,
-[  --disable-dbm       Disable building dbm],
+[  --disable-dbm           Disable building dbm],
     NSS_DISABLE_DBM=1,
     NSS_DISABLE_DBM=)
 
 dnl bi-directional support always on
 IBMBIDI=1
 AC_DEFINE(IBMBIDI)
 
 dnl ========================================================
@@ -5850,17 +5856,17 @@ dnl ====================================
 if test "$MOZ_JSLOADER"; then
     AC_DEFINE(MOZ_JSLOADER)
 fi
 
 dnl ========================================================
 dnl Disable printing
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(printing,
-[  --disable-printing  Disable printing support],
+[  --disable-printing      Disable printing support],
     NS_PRINTING=,
     NS_PRINTING=1 )
 
 if test "$MOZ_WIDGET_TOOLKIT" = "qt"; then
     AC_MSG_WARN([Printing does not work with Qt at this time. Omitting printing support.])
     NS_PRINTING=
 fi
 
@@ -5896,17 +5902,18 @@ MOZ_ARG_ENABLE_BOOL(plaintext-editor-onl
     MOZ_PLAINTEXT_EDITOR_ONLY= )
 dnl Note the #define is MOZILLA, not MOZ, for compat with the Mac build.
 AC_SUBST(MOZ_PLAINTEXT_EDITOR_ONLY)
 
 dnl ========================================================
 dnl = Disable Fast Load
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(xpcom-fastload,
-[  --disable-xpcom-fastload           Disable XPCOM fastload support],
+[  --disable-xpcom-fastload
+                          Disable XPCOM fastload support],
     MOZ_NO_FAST_LOAD=1,
     MOZ_NO_FAST_LOAD=)
 
 AC_SUBST(MOZ_NO_FAST_LOAD)
 
 if test -n "$MOZ_NO_FAST_LOAD"; then
     AC_DEFINE(MOZ_NO_FAST_LOAD)
 fi
@@ -6065,30 +6072,48 @@ case "${target}" in
 esac
 
 MOZ_ARG_ENABLE_BOOL(javaxpcom,
 [  --enable-javaxpcom
                           Enable Java-XPCOM bridge],
     MOZ_JAVAXPCOM=1,
     MOZ_JAVAXPCOM= )
 
+case "$host_os" in
+  cygwin*|msvc*|mks*)
+    if test -n "$JAVA_HOME"; then
+      JAVA_HOME=`cygpath -u \`cygpath -m -s "$JAVA_HOME"\``
+    fi
+    ;;
+  *mingw*)
+    if test -n "$JAVA_HOME"; then
+      JAVA_HOME=`cd "$JAVA_HOME" && pwd`
+    fi
+    ;;
+esac
+
+if test -n "${JAVA_BIN_PATH}"; then
+  dnl Look for javac and jar in the specified path.
+  JAVA_PATH="$JAVA_BIN_PATH"
+else
+  dnl No path specified, so look for javac and jar in $JAVA_HOME & $PATH.
+  JAVA_PATH="$JAVA_HOME/bin:$PATH"
+fi
+
+MOZ_PATH_PROG(JAVA, java, :, [$JAVA_PATH])
+MOZ_PATH_PROG(JAVAC, javac, :, [$JAVA_PATH])
+MOZ_PATH_PROG(JAR, jar, :, [$JAVA_PATH])
+
+if test -n "${JAVA_BIN_PATH}" || test "$OS_TARGET" = Android; then
+  if test -z "$JAVA" || test "$JAVA" = ":" || test -z "$JAVAC" || test "$JAVAC" = ":" || test -z "$JAR" || test "$JAR" = ":"; then
+    AC_MSG_ERROR([The programs java, javac and jar were not found.  Set \$JAVA_HOME to your java sdk directory or use --with-java-bin-path={java-bin-dir}])
+  fi
+fi
+
 if test -n "${MOZ_JAVAXPCOM}"; then
-  case "$host_os" in
-    cygwin*|msvc*|mks*)
-      if test -n "$JAVA_HOME"; then
-        JAVA_HOME=`cygpath -u \`cygpath -m -s "$JAVA_HOME"\``
-      fi
-      ;;
-    *mingw*)
-      if test -n "$JAVA_HOME"; then
-        JAVA_HOME=`cd "$JAVA_HOME" && pwd`
-      fi
-      ;;
-  esac
-
   if test -n "${JAVA_INCLUDE_PATH}"; then
     dnl Make sure jni.h exists in the given include path.
     if test ! -f "$JAVA_INCLUDE_PATH/jni.h"; then
       AC_MSG_ERROR([jni.h was not found in given include path $JAVA_INCLUDE_PATH.])
     fi
   else
     case "$target_os" in
       darwin*)
@@ -6099,31 +6124,16 @@ if test -n "${MOZ_JAVAXPCOM}"; then
         dnl Try $JAVA_HOME
         JAVA_INCLUDE_PATH="$JAVA_HOME/include"
         ;;
     esac
     if test ! -f "$JAVA_INCLUDE_PATH/jni.h"; then
       AC_MSG_ERROR([The header jni.h was not found.  Set \$JAVA_HOME to your java sdk directory, use --with-java-bin-path={java-bin-dir}, or reconfigure with --disable-javaxpcom.])
     fi
   fi
-
-  if test -n "${JAVA_BIN_PATH}"; then
-    dnl Look for javac and jar in the specified path.
-    JAVA_PATH="$JAVA_BIN_PATH"
-  else
-    dnl No path specified, so look for javac and jar in $JAVA_HOME & $PATH.
-    JAVA_PATH="$JAVA_HOME/bin:$PATH"
-  fi
-
-  MOZ_PATH_PROG(JAVA, java, :, [$JAVA_PATH])
-  MOZ_PATH_PROG(JAVAC, javac, :, [$JAVA_PATH])
-  MOZ_PATH_PROG(JAR, jar, :, [$JAVA_PATH])
-  if test -z "$JAVA" || test "$JAVA" = ":" || test -z "$JAVAC" || test "$JAVAC" = ":" || test -z "$JAR" || test "$JAR" = ":"; then
-    AC_MSG_ERROR([The programs java, javac and jar were not found.  Set \$JAVA_HOME to your java sdk directory, use --with-java-bin-path={java-bin-dir}, or reconfigure with --disable-javaxpcom.])
-  fi
 fi
 
 dnl ========================================================
 dnl = Breakpad crash reporting (on by default on supported platforms)
 dnl ========================================================
 
 case $target in
 i?86-*-mingw*)
@@ -6136,17 +6146,17 @@ i?86-*-linux*|x86_64-*-linux*|arm-*-linu
   MOZ_CRASHREPORTER=1
   ;;
 *solaris*)
   MOZ_CRASHREPORTER=1
   ;;
 esac
 
 MOZ_ARG_DISABLE_BOOL(crashreporter,
-[  --disable-crashreporter          Disable breakpad crash reporting],
+[  --disable-crashreporter Disable breakpad crash reporting],
     MOZ_CRASHREPORTER=,
     MOZ_CRASHREPORTER=1)
 
 if test -n "$MOZ_CRASHREPORTER"; then
    AC_DEFINE(MOZ_CRASHREPORTER)
 
   if (test "$OS_ARCH" = "Linux" || test "$OS_ARCH" = "SunOS") && \
     test -z "$SKIP_LIBRARY_CHECKS"; then
@@ -6154,17 +6164,18 @@ if test -n "$MOZ_CRASHREPORTER"; then
     AC_SUBST(MOZ_GTHREAD_CFLAGS)
     AC_SUBST(MOZ_GTHREAD_LIBS)
 
     AC_CHECK_HEADERS([curl/curl.h], [], [AC_MSG_ERROR([Couldn't find curl/curl.h which is required for the crash reporter.  Use --disable-crashreporter to disable the crash reporter.])])
   fi
 fi
 
 MOZ_ARG_WITH_STRING(crashreporter-enable-percent,
-[  --with-crashreporter-enable-percent=NN  Enable sending crash reports by default on NN% of users. (default=100)],
+[  --with-crashreporter-enable-percent=NN
+                          Enable sending crash reports by default on NN% of users. (default=100)],
 [ val=`echo $withval | sed 's/[^0-9]//g'`
     MOZ_CRASHREPORTER_ENABLE_PERCENT="$val"])
 
 if test -z "$MOZ_CRASHREPORTER_ENABLE_PERCENT"; then
    MOZ_CRASHREPORTER_ENABLE_PERCENT=100
 fi
 AC_DEFINE_UNQUOTED(MOZ_CRASHREPORTER_ENABLE_PERCENT, $MOZ_CRASHREPORTER_ENABLE_PERCENT)
 
@@ -6357,44 +6368,44 @@ MOZ_ARG_DISABLE_BOOL(mathml,
 if test "$MOZ_MATHML"; then
   AC_DEFINE(MOZ_MATHML)
 fi
 
 dnl ========================================================
 dnl SVG
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(svg,
-[  --disable-svg            Disable SVG support],
+[  --disable-svg           Disable SVG support],
     MOZ_SVG=,
     MOZ_SVG=1 )
 if test -n "$MOZ_SVG"; then
   AC_DEFINE(MOZ_SVG)
 fi
 
 dnl ========================================================
 dnl SMIL
 dnl ========================================================
 MOZ_SMIL=1
 MOZ_ARG_DISABLE_BOOL(smil,
-[  --disable-smil           Disable SMIL animation support],
+[  --disable-smil          Disable SMIL animation support],
     MOZ_SMIL=,
     MOZ_SMIL=1 )
 # Automatically disable SMIL if SVG is disabled
 if test -z "$MOZ_SVG"; then
   MOZ_SMIL=
 fi
 if test -n "$MOZ_SMIL"; then
   AC_DEFINE(MOZ_SMIL)
 fi
 
 dnl ========================================================
 dnl Build Freetype in the tree
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(tree-freetype,
-[  --enable-tree-freetype         Enable Tree FreeType],
+[  --enable-tree-freetype  Enable Tree FreeType],
     MOZ_TREE_FREETYPE=1,
     MOZ_TREE_FREETYPE= )
 if test -n "$MOZ_TREE_FREETYPE"; then
    AC_DEFINE(MOZ_TREE_FREETYPE)
    AC_SUBST(MOZ_TREE_FREETYPE)
    MOZ_ENABLE_CAIRO_FT=1       
    FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
    FT2_CFLAGS='-I$(topsrcdir)/modules/freetype2/include'
@@ -6459,28 +6470,28 @@ MOZ_ARG_DISABLE_BOOL(updater,
 [  --disable-updater       Disable building of updater],
     MOZ_UPDATER=,
     MOZ_UPDATER=1 )
 AC_SUBST(MOZ_UPDATER)
 
 # app update channel is 'default' when not supplied.
 MOZ_ARG_ENABLE_STRING([update-channel],
 [  --enable-update-channel=CHANNEL
-                           Select application update channel (default=default)],
+                          Select application update channel (default=default)],
     MOZ_UPDATE_CHANNEL=`echo $enableval | tr A-Z a-z`)
 
 if test -z "$MOZ_UPDATE_CHANNEL"; then
     MOZ_UPDATE_CHANNEL=default
 fi
 AC_DEFINE_UNQUOTED(MOZ_UPDATE_CHANNEL, $MOZ_UPDATE_CHANNEL)
 
 # tools/update-packaging is not checked out by default.
 MOZ_ARG_ENABLE_BOOL(update-packaging,
 [  --enable-update-packaging
-                           Enable tools/update-packaging],
+                          Enable tools/update-packaging],
     MOZ_UPDATE_PACKAGING=1,
     MOZ_UPDATE_PACKAGING= )
 AC_SUBST(MOZ_UPDATE_PACKAGING)
 
 dnl ========================================================
 dnl ActiveX
 dnl ========================================================
 
@@ -6539,17 +6550,17 @@ MOZ_ARG_DISABLE_BOOL(tests,
     ENABLE_TESTS=,
     ENABLE_TESTS=1 )
 
 dnl ========================================================
 dnl parental controls (for Windows Vista)
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(parental-controls,
 [  --disable-parental-controls
-                           Do not build parental controls],
+                          Do not build parental controls],
    MOZ_DISABLE_PARENTAL_CONTROLS=1,
    MOZ_DISABLE_PARENTAL_CONTROLS=)
 if test -n "$MOZ_DISABLE_PARENTAL_CONTROLS"; then
     AC_DEFINE(MOZ_DISABLE_PARENTAL_CONTROLS)
 fi
 
 AC_SUBST(MOZ_DISABLE_PARENTAL_CONTROLS)
 
@@ -6559,17 +6570,17 @@ dnl = Module specific options
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Individual module options)
 
 dnl ========================================================
 dnl = Disable feed handling components
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(feeds,
-[  --disable-feeds        Disable feed handling and processing components],
+[  --disable-feeds         Disable feed handling and processing components],
     MOZ_FEEDS=,
     MOZ_FEEDS=1 )
 if test -n "$MOZ_FEEDS"; then
     AC_DEFINE(MOZ_FEEDS)
 else
     if test "$MOZ_BUILD_APP" = "browser"; then
         AC_MSG_ERROR([Cannot build Firefox with --disable-feeds.])
     fi
@@ -6705,67 +6716,67 @@ if test -n "$MOZ_HELP_VIEWER"; then
      dnl Do this if defined in confvars.sh
      AC_DEFINE(MOZ_HELP_VIEWER)
 fi
 
 dnl ========================================================
 dnl = Enable safe browsing (anti-phishing)
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(safe-browsing,
-[  --enable-safe-browsing        Enable safe browsing (anti-phishing) implementation],
+[  --enable-safe-browsing  Enable safe browsing (anti-phishing) implementation],
     MOZ_SAFE_BROWSING=1,
     MOZ_SAFE_BROWSING= )
 if test -n "$MOZ_SAFE_BROWSING"; then
     AC_DEFINE(MOZ_SAFE_BROWSING)
 fi
 AC_SUBST(MOZ_SAFE_BROWSING)
 
 dnl ========================================================
 dnl = Enable faststart component
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(faststart,
-[  --enable-faststart            Enable the faststart component],
+[  --enable-faststart      Enable the faststart component],
     MOZ_FASTSTART=1,
     MOZ_FASTSTART= )
 if test -n "$MOZ_FASTSTART"; then
     AC_DEFINE(MOZ_FASTSTART)
 fi
 AC_SUBST(MOZ_FASTSTART)
 
 dnl ========================================================
 dnl = Enable url-classifier
 dnl ========================================================
 dnl Implicitly enabled by default if building with safe-browsing
 if test -n "$MOZ_SAFE_BROWSING"; then
     MOZ_URL_CLASSIFIER=1
 fi
 MOZ_ARG_ENABLE_BOOL(url-classifier,
-[  --enable-url-classifier        Enable url classifier module],
+[  --enable-url-classifier Enable url classifier module],
     MOZ_URL_CLASSIFIER=1,
     MOZ_URL_CLASSIFIER= )
 if test -n "$MOZ_URL_CLASSIFIER"; then
     AC_DEFINE(MOZ_URL_CLASSIFIER)
 fi
 AC_SUBST(MOZ_URL_CLASSIFIER)
 
 dnl ========================================================
 dnl = Disable zipwriter
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(zipwriter,
-[  --disable-zipwriter             Disable zipwriter component],
+[  --disable-zipwriter     Disable zipwriter component],
     MOZ_ZIPWRITER=,
     MOZ_ZIPWRITER=1 )
 AC_SUBST(MOZ_ZIPWRITER)
 
 dnl ========================================================
 dnl = Disable libconic
 dnl ========================================================
 MOZ_ENABLE_LIBCONIC=1
 MOZ_ARG_DISABLE_BOOL(libconic,
-[  --disable-libconic              Disable libconic],
+[  --disable-libconic      Disable libconic],
     MOZ_ENABLE_LIBCONIC=,
     MOZ_ENABLE_LIBCONIC=1 )
 
 if test -n "$MOZ_ENABLE_LIBCONIC"; then
     PKG_CHECK_MODULES(LIBCONIC, conic,
                       MOZ_ENABLE_LIBCONIC=1,
                       MOZ_ENABLE_LIBCONIC=)
 fi
@@ -6780,17 +6791,17 @@ AC_SUBST(LIBCONIC_LIBS)
 dnl ========================================================
 dnl = Maemo checks
 dnl ========================================================
 
 MAEMO_SDK_TARGET_VER=-1
 
 MOZ_ARG_WITH_STRING(maemo-version,
 [  --with-maemo-version=MAEMO_SDK_TARGET_VER
-                        Maemo SDK Version],
+                          Maemo SDK Version],
   MAEMO_SDK_TARGET_VER=$withval)
 
 case "$MAEMO_SDK_TARGET_VER" in
 5)
     MOZ_PLATFORM_MAEMO=5
     ;;
 
 6)
@@ -6867,17 +6878,17 @@ if test $MOZ_PLATFORM_MAEMO; then
    AC_SUBST(MOZ_PLATFORM_MAEMO_LIBS)
    AC_SUBST(MOZ_PLATFORM_MAEMO_CFLAGS)
 fi
 
 dnl ========================================================
 dnl = Enable building the Thumb2 instruction set
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(thumb2,
- [  --enable-thumb2              Enable Thumb2 instruction set],
+ [  --enable-thumb2         Enable Thumb2 instruction set],
     MOZ_THUMB2=1,
     MOZ_THUMB2=)
 
 if test -n "$MOZ_THUMB2"; then
   case "$target_cpu" in
     arm*)
       if test "$GNU_CC"; then
         CFLAGS="$CFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb"
@@ -6892,17 +6903,17 @@ if test -n "$MOZ_THUMB2"; then
     ;;
   esac
 fi
 
 dnl ========================================================
 dnl = faststripe theme
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(faststripe,
-[  --enable-faststripe  Use faststripe theme],
+[  --enable-faststripe     Use faststripe theme],
     MOZ_THEME_FASTSTRIPE=1,
     MOZ_THEME_FASTSTRIPE= )
 AC_SUBST(MOZ_THEME_FASTSTRIPE)
 
 dnl ========================================================
 dnl =
 dnl = Feature options that require extra sources to be pulled
 dnl =
@@ -6956,18 +6967,18 @@ MOZ_ARG_ENABLE_STRING(debug,
   else
     MOZ_DEBUG=
   fi ],
   MOZ_DEBUG=)
 
 MOZ_DEBUG_ENABLE_DEFS="-DDEBUG -D_DEBUG"
 MOZ_ARG_WITH_STRING(debug-label,
 [  --with-debug-label=LABELS
-                           Define DEBUG_<value> for each comma-separated
-                           value given.],
+                          Define DEBUG_<value> for each comma-separated
+                          value given.],
 [ for option in `echo $withval | sed 's/,/ /g'`; do
     MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_${option}"
 done])
 
  case "${target_os}" in
     beos*)
         MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_${USER}"
         ;;
@@ -6996,17 +7007,18 @@ if test -n "$MOZ_DEBUG"; then
     fi
     CFLAGS=$_SAVE_CFLAGS
 fi
 
 dnl ========================================================
 dnl enable mobile optimizations
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(mobile-optimize,
-[  --enable-mobile-optimize   Enable mobile optimizations],
+[  --enable-mobile-optimize
+                          Enable mobile optimizations],
     MOZ_GFX_OPTIMIZE_MOBILE=1)
 
 AC_SUBST(MOZ_GFX_OPTIMIZE_MOBILE)
 
 if test "$MOZ_GFX_OPTIMIZE_MOBILE"; then
     AC_DEFINE(MOZ_GFX_OPTIMIZE_MOBILE)
 fi
 
@@ -7062,18 +7074,18 @@ MOZ_ARG_ENABLE_STRING(debugger-info-modu
     AC_MSG_WARN([--enable-debugger-info-modules is deprecated, use --enable-debug-symbols instead])
     MOZ_DEBUG_SYMBOLS=1
   fi ])
 
 dnl ========================================================
 dnl = Enable generation of debug symbols
 dnl ========================================================
 MOZ_ARG_ENABLE_STRING(debug-symbols,
-[  --enable-debug-symbols[=DBG]    Enable debugging symbols
-                                   (using compiler flags DBG)],
+[  --enable-debug-symbols[=DBG]
+                          Enable debugging symbols (using compiler flags DBG)],
 [ if test "$enableval" != "no"; then
       MOZ_DEBUG_SYMBOLS=1
       if test -n "$enableval" -a "$enableval" != "yes"; then
           if test -z "$_MOZ_DEBUG_FLAGS_SET"; then
               MOZ_DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'`
           else
               AC_MSG_ERROR([--enable-debug-symbols flags cannot be used with --enable-debug flags])
           fi
@@ -7084,17 +7096,18 @@ if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBU
     AC_DEFINE(MOZ_DEBUG_SYMBOLS)
     export MOZ_DEBUG_SYMBOLS
 fi
 
 dnl ========================================================
 dnl = Disable any treating of compile warnings as errors
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(warnings-as-errors,
-[  --disable-warnings-as-errors       Disable treating of warnings as errors],
+[  --disable-warnings-as-errors
+                          Disable treating of warnings as errors],
     MOZ_DISABLE_WARNINGS_AS_ERRORS=1,
     MOZ_DISABLE_WARNINGS_AS_ERRORS= )
 if test "$MOZ_DISABLE_WARNINGS_AS_ERRORS"; then
    WARNINGS_AS_ERRORS=''
 fi
 
 dnl ========================================================
 dnl = Disable runtime logging checks
@@ -7209,29 +7222,34 @@ if test "$MOZ_MEMORY"; then
         AC_MSG_ERROR([When building jemalloc, set WIN32_CRT_SRC_DIR to the path to the Visual C++ CRT source (usually VCINSTALLDIR\crt\src, but VCINSTALLDIR is not set, so I can't autodetect it for you).])
       else
         WIN32_CRT_SRC_DIR="$VCINSTALLDIR\crt\src"
       fi
     fi
     dnl cpu check
     case "${target_cpu}" in
     i*86)
-      _WIN32_CRT_CPU=intel
+      MOZ_CRT_CPU_ARCH=intel
+      ;;
+    x86_64)
+      MOZ_CRT_CPU_ARCH=amd64
       ;;
     *)
       AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
       ;;
     esac
 
+    AC_SUBST(MOZ_CRT_CPU_ARCH)
+
     if test ! -d "$WIN32_CRT_SRC_DIR"; then
       AC_MSG_ERROR([Invalid Win32 CRT source directory: ${WIN32_CRT_SRC_DIR}])
     fi
     WIN32_CRT_SRC_DIR=`cd "$WIN32_CRT_SRC_DIR" && pwd -W`
     _objdir_win=`pwd -W`
-    WIN32_CUSTOM_CRT_DIR="$_objdir_win/memory/jemalloc/crtsrc/build/$_WIN32_CRT_CPU"
+    WIN32_CUSTOM_CRT_DIR="$_objdir_win/memory/jemalloc/crtsrc/build/$MOZ_CRT_CPU_ARCH"
     MOZ_MEMORY_LDFLAGS="-MANIFEST:NO -LIBPATH:\"$WIN32_CUSTOM_CRT_DIR\" -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt19 -DEFAULTLIB:mozcpp19"
     dnl Also pass this to NSPR/NSS
     DLLFLAGS="$DLLFLAGS $MOZ_MEMORY_LDFLAGS"
     export DLLFLAGS
     ;;
   *-*wince)
     AC_DEFINE(MOZ_MEMORY_WINCE)
     AC_DEFINE(MOZ_MEMORY_WINDOWS)
@@ -7297,17 +7315,17 @@ MOZ_ARG_ENABLE_BOOL(tracevis,
 if test -n "$MOZ_TRACEVIS"; then
     AC_DEFINE(MOZ_TRACEVIS)
 fi
 
 dnl ========================================================
 dnl = Use GCTimer
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(gctimer,
-[  --enable-gctimer       Enable GC timer (default=no)],
+[  --enable-gctimer        Enable GC timer (default=no)],
     MOZ_GCTIMER=1,
     MOZ_GCTIMER= )
 if test -n "$MOZ_GCTIMER"; then
     AC_DEFINE(MOZ_GCTIMER)
 fi
 
 dnl ========================================================
 dnl = Use Valgrind
@@ -7366,30 +7384,30 @@ MOZ_ARG_ENABLE_BOOL(vtune,
 if test -n "$MOZ_VTUNE"; then
     AC_DEFINE(MOZ_VTUNE)
 fi
 
 dnl ========================================================
 dnl Zealous JavaScript GC
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(gczeal,
-[  --enable-gczeal          Enable zealous JavaScript GCing],
+[  --enable-gczeal         Enable zealous JavaScript GCing],
     JS_GC_ZEAL=1,
     JS_GC_ZEAL= )
 if test -n "$JS_GC_ZEAL"; then
     AC_DEFINE(JS_GC_ZEAL)
 fi
 
 dnl ========================================================
 dnl = Enable static checking using gcc-dehydra
 dnl ========================================================
 
 MOZ_ARG_WITH_STRING(static-checking,
 [  --with-static-checking=path/to/gcc_dehydra.so
-                            Enable static checking of code using GCC-dehydra],
+                          Enable static checking of code using GCC-dehydra],
     DEHYDRA_PATH=$withval,
     DEHYDRA_PATH= )
 
 if test -n "$DEHYDRA_PATH"; then
     if test ! -f "$DEHYDRA_PATH"; then
         AC_MSG_ERROR([The dehydra plugin is not at the specified path.])
     fi
     AC_DEFINE(NS_STATIC_CHECKING)
@@ -7441,17 +7459,17 @@ if test -n "$MOZ_TIMELINE"; then
 fi
 
 dnl ========================================================
 dnl = Enable NS_FUNCTION_TIMER, which provides Function 
 dnl = timing for identifying code bottlenecks 
 dnl = NS_FUNCTION_TIMER is off by default.
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(functiontimer,
-[  --enable-functiontimer       Enable NS_FUNCTION_TIMER ],
+[  --enable-functiontimer  Enable NS_FUNCTION_TIMER ],
     NS_FUNCTION_TIMER=1,
     NS_FUNCTION_TIMER= )
 if test -n "$NS_FUNCTION_TIMER"; then
     AC_DEFINE(NS_FUNCTION_TIMER)
 fi
 
 dnl ========================================================
 dnl Turn on reflow counting
@@ -7478,17 +7496,17 @@ if test -n "$_ENABLE_CODESIGHS"; then
         AC_MSG_ERROR([Codesighs directory $srcdir/tools/codesighs required.])
     fi
 fi
 
 dnl ========================================================
 dnl = Support for Quantify (Windows)
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(quantify,
-[  --enable-quantify      Enable Quantify support (Windows only) ],
+[  --enable-quantify       Enable Quantify support (Windows only) ],
     MOZ_QUANTIFY=1,
     MOZ_QUANTIFY= )
 
 dnl ========================================================
 dnl = Support for demangling undefined symbols
 dnl ========================================================
 if test -z "$SKIP_LIBRARY_CHECKS"; then
     AC_LANG_SAVE
@@ -7664,17 +7682,17 @@ dnl Profile guided optimization
 dnl ========================================================
 dnl Test for profiling options
 dnl Under gcc 3.3, use -fprofile-arcs/-fbranch-probabilities
 dnl Under gcc 3.4+, use -fprofile-generate/-fprofile-use
 
 dnl Provide a switch to disable PGO even when called via profiledbuild.
 MOZ_ARG_DISABLE_BOOL(profile-guided-optimization,
 [  --disable-profile-guided-optimization
-                           Don't build with PGO even if called via make profiledbuild],
+                          Don't build with PGO even if called via make profiledbuild],
 MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE=1,
 MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE=)
 
 AC_SUBST(MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE)
 
 _SAVE_CFLAGS="$CFLAGS"
 CFLAGS="$CFLAGS -fprofile-generate -fprofile-correction"
 
@@ -8124,17 +8142,17 @@ AC_SUBST(HOST_LIBIDL_LIBS)
 
 dnl ========================================================
 dnl Check for cairo
 dnl ========================================================
 MOZ_CAIRO_CFLAGS='-I$(LIBXUL_DIST)/include/cairo'
 
 MOZ_TREE_CAIRO=1
 MOZ_ARG_ENABLE_BOOL(system-cairo,
-[ --enable-system-cairo Use system cairo (located with pkgconfig)],
+[  --enable-system-cairo   Use system cairo (located with pkgconfig)],
 MOZ_TREE_CAIRO=,
 MOZ_TREE_CAIRO=1 )
 
 # Check for headers defining standard int types.
 AC_CHECK_HEADERS(stdint.h inttypes.h sys/int_types.h)
 
 if test "$MOZ_TREE_CAIRO"; then
     AC_DEFINE(MOZ_TREE_CAIRO)
@@ -8311,17 +8329,18 @@ fi
 AC_SUBST(MOZ_XUL)
 
 dnl ========================================================
 dnl disable profile locking
 dnl   do no use this in applications that can have more than
 dnl   one process accessing the profile directory.
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(profilelocking,
-[  --disable-profilelocking           Disable profile locking],
+[  --disable-profilelocking
+                          Disable profile locking],
     MOZ_PROFILELOCKING=,
     MOZ_PROFILELOCKING=1 )
 if test "$MOZ_PROFILELOCKING"; then
   AC_DEFINE(MOZ_PROFILELOCKING)
 fi
 
 dnl ========================================================
 dnl disable rdf services
@@ -8379,17 +8398,17 @@ AC_SUBST(NECKO_DISK_CACHE)
 if test "$NECKO_DISK_CACHE"; then
     AC_DEFINE(NECKO_DISK_CACHE)
 fi
 
 dnl
 dnl option to disable necko's wifi scanner
 dnl
 MOZ_ARG_DISABLE_BOOL(necko-wifi,
-[  --disable-necko-wifi   Disable necko wifi scanner],
+[  --disable-necko-wifi    Disable necko wifi scanner],
     NECKO_WIFI=,
     NECKO_WIFI=1
 )
 
 if test "$OS_ARCH" = "OS2"; then
   dnl OS/2 implementation of Necko-WiFi support will be added in bug 506566
   NECKO_WIFI=
 fi
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1346,22 +1346,16 @@ public:
   static PRUint32 FilterDropEffect(PRUint32 aAction, PRUint32 aEffectAllowed);
 
   /**
    * Return true if aURI is a local file URI (i.e. file://).
    */
   static PRBool URIIsLocalFile(nsIURI *aURI);
 
   /**
-   * If aContent is an HTML element with a DOM level 0 'name', then
-   * return the name. Otherwise return null.
-   */
-  static nsIAtom* IsNamedItem(Element* aElement);
-
-  /**
    * Get the application manifest URI for this document.  The manifest URI
    * is specified in the manifest= attribute of the root element of the
    * document.
    *
    * @param aDocument The document that lists the manifest.
    * @param aURI The manifest URI.
    */
   static void GetOfflineAppManifest(nsIDocument *aDocument, nsIURI **aURI);
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -66,18 +66,18 @@ enum nsLinkState {
   eLinkState_Unknown    = 0,
   eLinkState_Unvisited  = 1,
   eLinkState_Visited    = 2,
   eLinkState_NotLink    = 3
 };
 
 // IID for the nsIContent interface
 #define NS_ICONTENT_IID       \
-{ 0x9e3b1a15, 0x72d5, 0x4e4f, \
-  { 0x8f, 0x4b, 0x75, 0xde, 0x07, 0x9c, 0x16, 0xdc } }
+{ 0x1450010b, 0xcdca, 0x451c, \
+  { 0xba, 0xdc, 0x07, 0x90, 0x89, 0x7b, 0xce, 0xb8 } }
 
 /**
  * A node of content in a document's content model. This interface
  * is supported by all content objects.
  */
 class nsIContent : public nsINode {
 public:
 #ifdef MOZILLA_INTERNAL_API
@@ -773,17 +773,22 @@ public:
   // PRInt32.  We should really use PRUint32 instead.
   virtual PRInt32 IntrinsicState() const;
 
   /**
    * Get the ID of this content node (the atom corresponding to the
    * value of the null-namespace attribute whose name is given by
    * GetIDAttributeName().  This may be null if there is no ID.
    */
-  virtual nsIAtom* GetID() const = 0;
+  nsIAtom* GetID() const {
+    if (HasFlag(NODE_HAS_ID)) {
+      return DoGetID();
+    }
+    return nsnull;
+  }
 
   /**
    * Get the class list of this content node (this corresponds to the
    * value of the null-namespace attribute whose name is given by
    * GetClassAttributeName()).  This may be null if there are no
    * classes, but that's not guaranteed.
    */
   const nsAttrValue* GetClasses() const {
@@ -910,16 +915,23 @@ public:
                               nsAString& aNamespaceURI) const;
 
   nsIAtom* LookupPrefix(const nsAString& aNamespaceURI);
 
   PRBool IsEqual(nsIContent *aOther);
 
   virtual PRBool IsEqualNode(nsINode* aOther);
 
+protected:
+  /**
+   * Hook for implementing GetID.  This is guaranteed to only be
+   * called if the NODE_HAS_ID flag is set.
+   */
+  virtual nsIAtom* DoGetID() const = 0;
+
 private:
   /**
    * Hook for implementing GetClasses.  This is guaranteed to only be
    * called if the NODE_MAY_HAVE_CLASS flag is set.
    */
   virtual const nsAttrValue* DoGetClasses() const = 0;
 
   /**
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -111,18 +111,18 @@ class Loader;
 
 namespace dom {
 class Link;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID      \
-{ 0xdf6c0752, 0xe780, 0x4576, \
-  { 0x95, 0x3c, 0x7e, 0xf1, 0xde, 0x9f, 0xd7, 0xf0 } }
+{ 0x3ee6a14b, 0x83b5, 0x4629, \
+  { 0x96, 0x9b, 0xe9, 0x84, 0x7c, 0x57, 0x24, 0x3c } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 // Document states
 
 // RTL locale: specific to the XUL localedir attribute
 #define NS_DOCUMENT_STATE_RTL_LOCALE              (1 << 0)
@@ -665,16 +665,27 @@ public:
     return mRemovedFromDocShell ? GetInnerWindowInternal() : mWindow;
   }
 
   /**
    * Get the script loader for this document
    */ 
   virtual nsScriptLoader* ScriptLoader() = 0;
 
+  /**
+   * Add/Remove an element to the document's id and name hashes
+   */
+  virtual void AddToIdTable(mozilla::dom::Element* aElement, nsIAtom* aId) = 0;
+  virtual void RemoveFromIdTable(mozilla::dom::Element* aElement,
+                                 nsIAtom* aId) = 0;
+  virtual void AddToNameTable(mozilla::dom::Element* aElement,
+                              nsIAtom* aName) = 0;
+  virtual void RemoveFromNameTable(mozilla::dom::Element* aElement,
+                                   nsIAtom* aName) = 0;
+
   //----------------------------------------------------------------------
 
   // Document notification API's
 
   /**
    * Add a new observer of document change notifications. Whenever
    * content is changed, appended, inserted or removed the observers are
    * informed.  An observer that is already observing the document must
@@ -797,16 +808,20 @@ public:
   virtual void GetXMLDeclaration(nsAString& aVersion,
                                  nsAString& aEncoding,
                                  nsAString& Standalone) = 0;
 
   PRBool IsHTML() const
   {
     return mIsRegularHTML;
   }
+  PRBool IsXUL() const
+  {
+    return mIsXUL;
+  }
 
   virtual PRBool IsScriptEnabled() = 0;
 
   virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement) = 0;
 
   /**
    * Create an element with the specified name, prefix and namespace ID.
    * If aDocumentDefaultType is true we create an element of the default type
@@ -1364,18 +1379,17 @@ public:
   virtual void SetChangeScrollPosWhenScrollingToRef(PRBool aValue) = 0;
 
   /**
    * This method is similar to GetElementById() from nsIDOMDocument but it
    * returns a mozilla::dom::Element instead of a nsIDOMElement.
    * It prevents converting nsIDOMElement to mozill:dom::Element which is
    * already converted from mozilla::dom::Element.
    */
-  virtual mozilla::dom::Element* GetElementById(const nsAString& aElementId,
-                                                nsresult* aResult) = 0;
+  virtual mozilla::dom::Element* GetElementById(const nsAString& aElementId) = 0;
 
 protected:
   ~nsIDocument()
   {
     // XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and
     //     releasing it) happens in the nsDocument destructor. We'd prefer to
     //     do it here but nsNodeInfoManager is a concrete class that we don't
     //     want to expose to users of the nsIDocument API outside of Gecko.
@@ -1457,16 +1471,17 @@ protected:
   // basically be true only for documents that exist in newly-opened windows or
   // documents created to satisfy a GetDocument() on a window when there's no
   // document in it.
   PRPackedBool mIsInitialDocumentInWindow;
 
   PRPackedBool mShellIsHidden;
 
   PRPackedBool mIsRegularHTML;
+  PRPackedBool mIsXUL;
 
   // True if we're loaded as data and therefor has any dangerous stuff, such
   // as scripts and plugins, disabled.
   PRPackedBool mLoadedAsData;
 
   // If true, whoever is creating the document has gotten it to the
   // point where it's safe to start layout on it.
   PRPackedBool mMayStartLayout;
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -112,19 +112,20 @@ enum {
   // in the document and therefore should get bindings attached.
   NODE_FORCE_XBL_BINDINGS =      0x00000040U,
 
   // Whether a binding manager may have a pointer to this
   NODE_MAY_BE_IN_BINDING_MNGR =  0x00000080U,
 
   NODE_IS_EDITABLE =             0x00000100U,
 
-  // Optimizations to quickly check whether element may have ID, class or style
-  // attributes. Not all element implementations may use these!
-  NODE_MAY_HAVE_ID =             0x00000200U,
+  // Set to true if the element has a non-empty id attribute. This can in rare
+  // cases lie for nsXMLElement, such as when the node has been moved between
+  // documents with different id mappings.
+  NODE_HAS_ID =                  0x00000200U,
   // For all Element nodes, NODE_MAY_HAVE_CLASS is guaranteed to be set if the
   // node in fact has a class, but may be set even if it doesn't.
   NODE_MAY_HAVE_CLASS =          0x00000400U,
   NODE_MAY_HAVE_STYLE =          0x00000800U,
 
   NODE_IS_INSERTION_PARENT =     0x00001000U,
 
   // Node has an :empty or :-moz-only-whitespace selector
@@ -165,19 +166,25 @@ enum {
 
   // At least one descendant in the flattened tree has NODE_NEEDS_FRAME set.
   // This should be set on every node on the flattened tree path between the
   // node(s) with NODE_NEEDS_FRAME and the root content.
   NODE_DESCENDANTS_NEED_FRAMES = 0x00100000U,
 
   // Set if the node is an element.
   NODE_IS_ELEMENT              = 0x00200000U,
+  
+  // Set if the node has the accesskey attribute set.
+  NODE_HAS_ACCESSKEY           = 0x00400000U,
+
+  // Set if the node has the accesskey attribute set.
+  NODE_HAS_NAME                = 0x00800000U,
 
   // Four bits for the script-type ID
-  NODE_SCRIPT_TYPE_OFFSET =               22,
+  NODE_SCRIPT_TYPE_OFFSET =               24,
 
   NODE_SCRIPT_TYPE_SIZE =                  4,
 
   // Remaining bits are node type specific.
   NODE_TYPE_SPECIFIC_BITS_OFFSET =
     NODE_SCRIPT_TYPE_OFFSET + NODE_SCRIPT_TYPE_SIZE
 };
 
--- a/content/base/src/nsAttrValue.cpp
+++ b/content/base/src/nsAttrValue.cpp
@@ -1137,47 +1137,54 @@ nsAttrValue::SetColorValue(nscolor aColo
   cont->mStringBits = reinterpret_cast<PtrBits>(buf) | eStringBase;
 }
 
 PRBool
 nsAttrValue::ParseColor(const nsAString& aString, nsIDocument* aDocument)
 {
   ResetIfSet();
 
+  // FIXME (partially, at least): HTML5's algorithm says we shouldn't do
+  // the whitespace compression, trimming, or the test for emptiness.
+  // (I'm a little skeptical that we shouldn't do the whitespace
+  // trimming; WebKit also does it.)
   nsAutoString colorStr(aString);
   colorStr.CompressWhitespace(PR_TRUE, PR_TRUE);
   if (colorStr.IsEmpty()) {
     return PR_FALSE;
   }
 
   nscolor color;
   // No color names begin with a '#'; in standards mode, all acceptable
   // numeric colors do.
   if (colorStr.First() == '#') {
-    colorStr.Cut(0, 1);
-    if (NS_HexToRGB(colorStr, &color)) {
+    nsDependentString withoutHash(colorStr.get() + 1, colorStr.Length() - 1);
+    if (NS_HexToRGB(withoutHash, &color)) {
       SetColorValue(color, aString);
       return PR_TRUE;
     }
   } else {
     if (NS_ColorNameToRGB(colorStr, &color)) {
       SetColorValue(color, aString);
       return PR_TRUE;
     }
   }
 
-  if (aDocument->GetCompatibilityMode() != eCompatibility_NavQuirks) {
-    return PR_FALSE;
+  // FIXME (maybe): HTML5 says we should handle system colors.  This
+  // means we probably need another storage type, since we'd need to
+  // handle dynamic changes.  However, I think this is a bad idea:
+  // http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2010-May/026449.html
+
+  // Use NS_LooseHexToRGB as a fallback if nothing above worked.
+  if (NS_LooseHexToRGB(colorStr, &color)) {
+    SetColorValue(color, aString);
+    return PR_TRUE;
   }
 
-  // In compatibility mode, try LooseHexToRGB as a fallback for either
-  // of the above two possibilities.
-  NS_LooseHexToRGB(colorStr, &color);
-  SetColorValue(color, aString);
-  return PR_TRUE;
+  return PR_FALSE;
 }
 
 PRBool nsAttrValue::ParseFloatValue(const nsAString& aString)
 {
   ResetIfSet();
 
   PRInt32 ec;
   float val = PromiseFlatString(aString).ToFloat(&ec);
--- a/content/base/src/nsAttrValue.h
+++ b/content/base/src/nsAttrValue.h
@@ -269,17 +269,18 @@ public:
    * http://dev.w3.org/html5/spec/common-dom-interfaces.html#limited-to-only-non-negative-numbers-greater-than-zero
    *
    * @param aString       the string to parse
    * @return              whether the value was valid
    */
   PRBool ParsePositiveIntValue(const nsAString& aString);
 
   /**
-   * Parse a string into a color.
+   * Parse a string into a color.  This implements what HTML5 calls the
+   * "rules for parsing a legacy color value".
    *
    * @param aString the string to parse
    * @param aDocument the document (to find out whether we're in quirks mode)
    * @return whether the value could be parsed
    */
   PRBool ParseColor(const nsAString& aString, nsIDocument* aDocument);
 
   /**
--- a/content/base/src/nsContentIterator.cpp
+++ b/content/base/src/nsContentIterator.cpp
@@ -41,16 +41,17 @@
 #include "nsIContentIterator.h"
 #include "nsRange.h"
 #include "nsIContent.h"
 #include "nsIDOMText.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsContentUtils.h"
 #include "nsINode.h"
+#include "nsCycleCollectionParticipant.h"
 
 // couple of utility static functs
 
 ///////////////////////////////////////////////////////////////////////////
 // ContentHasChildren: returns true if the node has children
 //
 static inline PRBool
 NodeHasChildren(nsINode *aNode)
@@ -113,17 +114,18 @@ NodeIsInTraversalRange(nsINode *aNode, P
 
 
 /*
  *  A simple iterator class for traversing the content in "close tag" order
  */
 class nsContentIterator : public nsIContentIterator //, public nsIEnumerator
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsContentIterator)
 
   nsContentIterator();
   virtual ~nsContentIterator();
 
   // nsIContentIterator interface methods ------------------------------
 
   virtual nsresult Init(nsINode* aRoot);
 
@@ -247,18 +249,30 @@ nsresult NS_NewPreContentIterator(nsICon
   return NS_OK;
 }
 
 
 /******************************************************
  * XPCOM cruft
  ******************************************************/
  
-NS_IMPL_ISUPPORTS1(nsContentIterator, nsIContentIterator)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsContentIterator)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsContentIterator)
 
+NS_INTERFACE_MAP_BEGIN(nsContentIterator)
+  NS_INTERFACE_MAP_ENTRY(nsIContentIterator)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentIterator)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsContentIterator)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_4(nsContentIterator,
+                           mCurNode,
+                           mFirst,
+                           mLast,
+                           mCommonParent)
 
 /******************************************************
  * constructor/destructor
  ******************************************************/
 
 nsContentIterator::nsContentIterator() :
   // don't need to explicitly initialize |nsCOMPtr|s, they will automatically be NULL
   mCachedIndex(0), mIsDone(PR_FALSE), mPre(PR_FALSE)
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -4891,45 +4891,16 @@ nsContentUtils::EqualsIgnoreASCIICase(co
 
 /* static */
 void
 nsAutoGCRoot::Shutdown()
 {
   NS_IF_RELEASE(sJSRuntimeService);
 }
 
-nsIAtom*
-nsContentUtils::IsNamedItem(Element* aElement)
-{
-  // Only the content types reflected in Level 0 with a NAME
-  // attribute are registered. Images, layers and forms always get
-  // reflected up to the document. Applets and embeds only go
-  // to the closest container (which could be a form).
-  nsGenericHTMLElement* elm = nsGenericHTMLElement::FromContent(aElement);
-  if (!elm) {
-    return nsnull;
-  }
-
-  nsIAtom* tag = elm->Tag();
-  if (tag != nsGkAtoms::img    &&
-      tag != nsGkAtoms::form   &&
-      tag != nsGkAtoms::applet &&
-      tag != nsGkAtoms::embed  &&
-      tag != nsGkAtoms::object) {
-    return nsnull;
-  }
-
-  const nsAttrValue* val = elm->GetParsedAttr(nsGkAtoms::name);
-  if (val && val->Type() == nsAttrValue::eAtom) {
-    return val->GetAtomValue();
-  }
-
-  return nsnull;
-}
-
 /* static */
 nsIInterfaceRequestor*
 nsContentUtils::GetSameOriginChecker()
 {
   if (!sSameOriginChecker) {
     sSameOriginChecker = new nsSameOriginChecker();
     NS_IF_ADDREF(sSameOriginChecker);
   }
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1449,17 +1449,17 @@ nsDocument::~nsDocument()
   if (mSubDocuments) {
     PL_DHashTableDestroy(mSubDocuments);
 
     mSubDocuments = nsnull;
   }
 
   // Destroy link map now so we don't waste time removing
   // links one by one
-  DestroyLinkMap();
+  DestroyElementMaps();
 
   nsAutoScriptBlocker scriptBlocker;
 
   PRInt32 indx; // must be signed
   PRUint32 count = mChildren.ChildCount();
   for (indx = PRInt32(count) - 1; indx >= 0; --indx) {
     mChildren.ChildAt(indx)->UnbindFromTree();
     mChildren.RemoveChildAt(indx);
@@ -1878,34 +1878,32 @@ nsDocument::ResetToURI(nsIURI *aURI, nsI
 #ifdef PR_LOGGING
   if (gDocumentLeakPRLog && PR_LOG_TEST(gDocumentLeakPRLog, PR_LOG_DEBUG)) {
     nsCAutoString spec;
     aURI->GetSpec(spec);
     PR_LogPrint("DOCUMENT %p ResetToURI %s", this, spec.get());
   }
 #endif
 
-  mIdentifierMap.Clear();
-
   SetPrincipal(nsnull);
   mSecurityInfo = nsnull;
 
   mDocumentLoadGroup = nsnull;
 
   // Delete references to sub-documents and kill the subdocument map,
   // if any. It holds strong references
   if (mSubDocuments) {
     PL_DHashTableDestroy(mSubDocuments);
 
     mSubDocuments = nsnull;
   }
 
   // Destroy link map now so we don't waste time removing
   // links one by one
-  DestroyLinkMap();
+  DestroyElementMaps();
 
   PRUint32 count = mChildren.ChildCount();
   { // Scope for update
     MOZ_AUTO_DOC_UPDATE(this, UPDATE_CONTENT_MODEL, PR_TRUE);    
     for (PRInt32 i = PRInt32(count) - 1; i >= 0; i--) {
       nsCOMPtr<nsIContent> content = mChildren.ChildAt(i);
 
       if (nsINode::GetFirstChild() == content) {
@@ -2329,189 +2327,70 @@ nsDocument::GetLastModified(nsAString& a
     // (or even the current time), fall back to what NS4.x returned.
     aLastModified.Assign(NS_LITERAL_STRING("01/01/1970 00:00:00"));
   }
 
   return NS_OK;
 }
 
 void
-nsDocument::UpdateNameTableEntry(Element *aElement)
+nsDocument::AddToNameTable(Element *aElement, nsIAtom* aName)
 {
   if (!mIsRegularHTML)
     return;
 
-  nsIAtom* name = nsContentUtils::IsNamedItem(aElement);
-  if (!name)
-    return;
-
-  nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(name);
-  if (!entry) {
-    // We're not tracking the elements with this name
-    return;
-  }
-
-  entry->AddNameElement(aElement);
+  nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aName);
+
+  // entry is null if we're not tracking the elements with this name
+
+  if (entry) {
+    entry->AddNameElement(aElement);
+  }
 }
 
 void
-nsDocument::RemoveFromNameTable(Element *aElement)
-{
-  if (!mIsRegularHTML)
+nsDocument::RemoveFromNameTable(Element *aElement, nsIAtom* aName)
+{
+  // Speed up document teardown
+  if (!mIsRegularHTML || mIdentifierMap.Count() == 0)
     return;
 
-  nsIAtom* name = nsContentUtils::IsNamedItem(aElement);
-  if (!name)
+  nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aName);
+  if (!entry) // Should never be false unless we had OOM when adding the entry
     return;
 
-  nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(name);
-  if (!entry) {
-    // We're not tracking the elements with this name
-    return;
-  }
-
   entry->RemoveNameElement(aElement);
 }
 
 void
-nsDocument::UpdateIdTableEntry(Element *aElement)
-{
-  nsIAtom* id = aElement->GetID();
-  if (!id)
-    return;
-
-  nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(id);
+nsDocument::AddToIdTable(Element *aElement, nsIAtom* aId)
+{
+  nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(aId);
 
   if (entry) { /* True except on OOM */
     entry->AddIdElement(aElement);
   }
 }
 
 void
-nsDocument::RemoveFromIdTable(Element *aElement)
-{
-  nsIAtom* id = aElement->GetID();
-  if (!id)
+nsDocument::RemoveFromIdTable(Element *aElement, nsIAtom* aId)
+{
+  NS_ASSERTION(aId, "huhwhatnow?");
+
+  // Speed up document teardown
+  if (mIdentifierMap.Count() == 0) {
     return;
-
-  nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(id);
-  if (!entry) /* Should be false unless we had OOM when adding the entry */
+  }
+
+  nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aId);
+  if (!entry) // Can be null for XML elements with changing ids.
     return;
 
   if (entry->RemoveIdElement(aElement)) {
-    mIdentifierMap.RemoveEntry(id);
-  }
-}
-
-void
-nsDocument::UnregisterNamedItems(nsIContent *aContent)
-{
-  if (!aContent->IsElement()) {
-    // non-element nodes are not named items nor can they have children.
-    return;
-  }
-
-  RemoveFromNameTable(aContent->AsElement());
-  RemoveFromIdTable(aContent->AsElement());
-
-  for (nsINode::ChildIterator iter(aContent); !iter.IsDone(); iter.Next()) {
-    UnregisterNamedItems(iter);
-  }
-}
-
-void
-nsDocument::RegisterNamedItems(nsIContent *aContent)
-{
-  if (!aContent->IsElement()) {
-    // non-element nodes are not named items nor can they have children.
-    return;
-  }
-
-  UpdateNameTableEntry(aContent->AsElement());
-  UpdateIdTableEntry(aContent->AsElement());
-
-  for (nsINode::ChildIterator iter(aContent); !iter.IsDone(); iter.Next()) {
-    RegisterNamedItems(iter);
-  }
-}
-
-void
-nsDocument::ContentAppended(nsIDocument* aDocument,
-                            nsIContent* aContainer,
-                            nsIContent* aFirstNewContent,
-                            PRInt32 aNewIndexInContainer)
-{
-  NS_ASSERTION(aDocument == this, "unexpected doc");
-
-  for (nsINode::ChildIterator iter(aContainer, aNewIndexInContainer);
-       !iter.IsDone();
-       iter.Next()) {
-    RegisterNamedItems(iter);
-  }
-}
-
-void
-nsDocument::ContentInserted(nsIDocument* aDocument,
-                            nsIContent* aContainer,
-                            nsIContent* aContent,
-                            PRInt32 aIndexInContainer)
-{
-  NS_ASSERTION(aDocument == this, "unexpected doc");
-
-  NS_ABORT_IF_FALSE(aContent, "Null content!");
-
-  RegisterNamedItems(aContent);
-}
-
-void
-nsDocument::ContentRemoved(nsIDocument* aDocument,
-                           nsIContent* aContainer,
-                           nsIContent* aChild,
-                           PRInt32 aIndexInContainer)
-{
-  NS_ASSERTION(aDocument == this, "unexpected doc");
-
-  NS_ABORT_IF_FALSE(aChild, "Null content!");
-
-  UnregisterNamedItems(aChild);
-}
-
-void
-nsDocument::AttributeWillChange(nsIDocument* aDocument,
-                                nsIContent* aContent, PRInt32 aNameSpaceID,
-                                nsIAtom* aAttribute, PRInt32 aModType)
-{
-  NS_ABORT_IF_FALSE(aContent && aContent->IsElement(), "Null content!");
-  NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!");
-
-  if (aNameSpaceID != kNameSpaceID_None)
-    return;
-  if (aAttribute == nsGkAtoms::name) {
-    RemoveFromNameTable(aContent->AsElement());
-  } else if (aAttribute == aContent->GetIDAttributeName()) {
-    RemoveFromIdTable(aContent->AsElement());
-  }
-}
-
-void
-nsDocument::AttributeChanged(nsIDocument* aDocument,
-                             nsIContent* aContent, PRInt32 aNameSpaceID,
-                             nsIAtom* aAttribute, PRInt32 aModType)
-{
-  NS_ASSERTION(aDocument == this, "unexpected doc");
-
-  NS_ABORT_IF_FALSE(aContent && aContent->IsElement(), "Null content!");
-  NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!");
-
-  if (aNameSpaceID != kNameSpaceID_None)
-    return;
-  if (aAttribute == nsGkAtoms::name) {
-    UpdateNameTableEntry(aContent->AsElement());
-  } else if (aAttribute == aContent->GetIDAttributeName()) {
-    UpdateIdTableEntry(aContent->AsElement());
+    mIdentifierMap.RemoveEntry(aId);
   }
 }
 
 nsIPrincipal*
 nsDocument::GetPrincipal()
 {
   return NodePrincipal();
 }
@@ -3320,17 +3199,17 @@ nsDocument::RemoveChildAt(PRUint32 aInde
   NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutations on document child removal.");
   nsCOMPtr<nsIContent> oldKid = GetChildAt(aIndex);
   if (!oldKid) {
     return NS_OK;
   }
 
   if (oldKid->IsElement()) {
     // Destroy the link map up front before we mess with the child list.
-    DestroyLinkMap();
+    DestroyElementMaps();
   }
 
   nsresult rv =
     doRemoveChildAt(aIndex, aNotify, oldKid, mChildren, aMutationEvent);
   mCachedRootElement = nsnull;
   return rv;
 }
 
@@ -3854,118 +3733,70 @@ nsDocument::CheckGetElementByIdArg(const
         EmptyString(), 0, 0,
         nsIScriptError::warningFlag,
         "DOM");
     return PR_FALSE;
   }
   return PR_TRUE;
 }
 
-nsIdentifierMapEntry*
-nsDocument::GetElementByIdInternal(nsIAtom* aID)
-{
-  // We don't have to flush before we do the initial hashtable lookup, since if
-  // the id is already in the hashtable it couldn't have been removed without
-  // us being notified (all removals notify immediately, as far as I can tell).
-  // So do the lookup first.
-  nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(aID);
-  NS_ENSURE_TRUE(entry, nsnull);
-
-  if (entry->GetIdElement())
-    return entry;
-
-  // Now we have to flush.  It could be that we know nothing about this ID yet
-  // but more content has been added to the document since.  Note that we have
-  // to flush notifications, so that the entry will get updated properly.
-
-  // Make sure to stash away the current generation so we can check whether
-  // the table changes when we flush.
-  PRUint32 generation = mIdentifierMap.GetGeneration();
-  
-  FlushPendingNotifications(Flush_ContentAndNotify);
-
-  if (generation != mIdentifierMap.GetGeneration()) {
-    // Table changed, so the entry pointer is no longer valid; look up the
-    // entry again, adding if necessary (the adding may be necessary in case
-    // the flush actually deleted entries).
-    entry = mIdentifierMap.PutEntry(aID);
-  }
-  
-  return entry;
-}
-
 Element*
-nsDocument::GetElementById(const nsAString& aElementId, nsresult *aResult)
+nsDocument::GetElementById(const nsAString& aElementId)
 {
   nsCOMPtr<nsIAtom> idAtom(do_GetAtom(aElementId));
   if (!idAtom) {
-    *aResult = NS_ERROR_OUT_OF_MEMORY;
-
+    // This can only fail due to OOM when the atom doesn't exist, in which
+    // case there can't be an entry for it.
     return nsnull;
   }
 
   if (!CheckGetElementByIdArg(idAtom)) {
-    *aResult = NS_OK;
-
     return nsnull;
   }
 
-  nsIdentifierMapEntry *entry = GetElementByIdInternal(idAtom);
-  if (!entry) {
-    *aResult = NS_ERROR_OUT_OF_MEMORY;
-
-    return nsnull;
-  }
-
-  *aResult = NS_OK;
-
-  return entry->GetIdElement();
+  nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(idAtom);
+  return entry ? entry->GetIdElement() : nsnull;
 }
 
 NS_IMETHODIMP
 nsDocument::GetElementById(const nsAString& aId, nsIDOMElement** aReturn)
 {
-  nsresult rv;
-  Element *content = GetElementById(aId, &rv);
+  Element *content = GetElementById(aId);
   if (content) {
-    rv = CallQueryInterface(content, aReturn);
-  }
-  else {
-    *aReturn = nsnull;
-  }
-
-  return rv;
+    return CallQueryInterface(content, aReturn);
+  }
+
+  *aReturn = nsnull;
+
+  return NS_OK;
 }
 
 Element*
 nsDocument::AddIDTargetObserver(nsIAtom* aID, IDTargetObserver aObserver,
                                 void* aData)
 {
   if (!CheckGetElementByIdArg(aID))
     return nsnull;
 
-  nsIdentifierMapEntry *entry = GetElementByIdInternal(aID);
+  nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(aID);
   NS_ENSURE_TRUE(entry, nsnull);
 
   entry->AddContentChangeCallback(aObserver, aData);
   return entry->GetIdElement();
 }
 
 void
 nsDocument::RemoveIDTargetObserver(nsIAtom* aID,
                                    IDTargetObserver aObserver, void* aData)
 {
   if (!CheckGetElementByIdArg(aID))
     return;
 
   nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aID);
   if (!entry) {
-    // We don't need to do the stuff that GetElementByIdInternal does;
-    // if there's no entry already in mIdentifierMap, then there's no
-    // callback to remove.
     return;
   }
 
   entry->RemoveContentChangeCallback(aObserver, aData);
 }
 
 void
 nsDocument::DispatchContentLoadedEvents()
@@ -7375,22 +7206,23 @@ nsDocument::ForgetLink(Link* aLink)
   nsPtrHashKey<Link>* entry = mStyledLinks.GetEntry(aLink);
   NS_ASSERTION(entry || mStyledLinksCleared,
                "Document knows nothing about this Link!");
 #endif
   (void)mStyledLinks.RemoveEntry(aLink);
 }
 
 void
-nsDocument::DestroyLinkMap()
+nsDocument::DestroyElementMaps()
 {
 #ifdef DEBUG
   mStyledLinksCleared = true;
 #endif
   mStyledLinks.Clear();
+  mIdentifierMap.Clear();
 }
 
 static
 PLDHashOperator
 EnumerateStyledLinks(nsPtrHashKey<Link>* aEntry, void* aArray)
 {
   nsTArray<Link*>* array = static_cast<nsTArray<Link*>*>(aArray);
   (void)array->AppendElement(aEntry->GetKey());
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -646,16 +646,27 @@ public:
   virtual nsIScriptGlobalObject* GetScopeObject();
 
   /**
    * Get the script loader for this document
    */
   virtual nsScriptLoader* ScriptLoader();
 
   /**
+   * Add/Remove an element to the document's id and name hashes
+   */
+  virtual void AddToIdTable(mozilla::dom::Element* aElement, nsIAtom* aId);
+  virtual void RemoveFromIdTable(mozilla::dom::Element* aElement,
+                                 nsIAtom* aId);
+  virtual void AddToNameTable(mozilla::dom::Element* aElement,
+                              nsIAtom* aName);
+  virtual void RemoveFromNameTable(mozilla::dom::Element* aElement,
+                                   nsIAtom* aName);
+
+  /**
    * Add a new observer of document change notifications. Whenever
    * content is changed, appended, inserted or removed the observers are
    * informed.
    */
   virtual void AddObserver(nsIDocumentObserver* aObserver);
 
   /**
    * Remove an observer of document change notifications. This will
@@ -802,23 +813,16 @@ public:
   NS_DECL_NSIDOMEVENTTARGET
 
   // nsIDOM3EventTarget
   NS_DECL_NSIDOM3EVENTTARGET
 
   // nsIDOMNSEventTarget
   NS_DECL_NSIDOMNSEVENTTARGET
 
-  // nsIMutationObserver
-  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
-  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
-  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
-  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
-  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
-
   // nsIScriptObjectPrincipal
   virtual nsIPrincipal* GetPrincipal();
 
   // nsIApplicationCacheContainer
   NS_DECL_NSIAPPLICATIONCACHECONTAINER
 
   virtual nsresult Init();
   
@@ -932,27 +936,20 @@ public:
   virtual void SetChangeScrollPosWhenScrollingToRef(PRBool aValue);
 
   already_AddRefed<nsContentList>
     GetElementsByTagName(const nsAString& aTagName);
   already_AddRefed<nsContentList>
     GetElementsByTagNameNS(const nsAString& aNamespaceURI,
                            const nsAString& aLocalName);
 
-  virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId,
-                                                nsresult *aResult);
+  virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId);
 
 protected:
   friend class nsNodeUtils;
-  void RegisterNamedItems(nsIContent *aContent);
-  void UnregisterNamedItems(nsIContent *aContent);
-  void UpdateNameTableEntry(Element *aElement);
-  void UpdateIdTableEntry(Element *aElement);
-  void RemoveFromNameTable(Element *aElement);
-  void RemoveFromIdTable(Element *aElement);
 
   /**
    * Check that aId is not empty and log a message to the console
    * service if it is.
    * @returns PR_TRUE if aId looks correct, PR_FALSE otherwise.
    */
   static PRBool CheckGetElementByIdArg(const nsIAtom* aId);
   nsIdentifierMapEntry* GetElementByIdInternal(nsIAtom* aID);
@@ -961,18 +958,18 @@ protected:
 
   void RetrieveRelevantHeaders(nsIChannel *aChannel);
 
   static PRBool TryChannelCharset(nsIChannel *aChannel,
                                   PRInt32& aCharsetSource,
                                   nsACString& aCharset);
 
   // Call this before the document does something that will unbind all content.
-  // That will stop us from resolving URIs for all links as they are removed.
-  void DestroyLinkMap();
+  // That will stop us from doing a lot of work as each element is removed.
+  void DestroyElementMaps();
 
   // Refreshes the hrefs of all the links in the document.
   void RefreshLinkHrefs();
 
   nsIContent* GetFirstBaseNodeWithHref();
   nsresult SetFirstBaseNodeWithHref(nsIContent *node);
 
   // Get the first <title> element with the given IsNodeOfType type, or
--- a/content/base/src/nsDocumentFragment.cpp
+++ b/content/base/src/nsDocumentFragment.cpp
@@ -149,16 +149,19 @@ public:
   }
   virtual const nsAttrName* GetAttrNameAt(PRUint32 aIndex) const
   {
     return nsnull;
   }
 
   virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
 
+  virtual nsIAtom* DoGetID() const;
+  virtual nsIAtom *GetIDAttributeName() const;
+
 protected:
   nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 };
 
 nsresult
 NS_NewDocumentFragment(nsIDOMDocumentFragment** aInstancePtrResult,
                        nsNodeInfoManager *aNodeInfoManager)
 {
@@ -190,16 +193,28 @@ nsDocumentFragment::~nsDocumentFragment(
 }
 
 PRBool
 nsDocumentFragment::IsNodeOfType(PRUint32 aFlags) const
 {
   return !(aFlags & ~(eCONTENT | eDOCUMENT_FRAGMENT));
 }
 
+nsIAtom*
+nsDocumentFragment::DoGetID() const
+{
+  return nsnull;  
+}
+
+nsIAtom*
+nsDocumentFragment::GetIDAttributeName() const
+{
+  return nsnull;
+}
+
 DOMCI_DATA(DocumentFragment, nsDocumentFragment)
 
 // QueryInterface implementation for nsDocumentFragment
 NS_INTERFACE_TABLE_HEAD(nsDocumentFragment)
   NS_NODE_INTERFACE_TABLE2(nsDocumentFragment, nsIDOMNode,
                            nsIDOMDocumentFragment)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DocumentFragment)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericElement)
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -560,17 +560,17 @@ nsGenericDOMDataNode::UnbindFromTree(PRB
   UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
              NS_REFRAME_IF_WHITESPACE);
   
   nsIDocument *document = GetCurrentDoc();
   if (document) {
     // Notify XBL- & nsIAnonymousContentCreator-generated
     // anonymous content that the document is changing.
     // This is needed to update the insertion point.
-    document->BindingManager()->ChangeDocumentFor(this, document, nsnull);
+    document->BindingManager()->RemovedFromDocument(this, document);
   }
 
   mParentPtrBits = aNullParent ? 0 : mParentPtrBits & ~PARENT_BIT_INDOCUMENT;
 
   nsDataSlots *slots = GetExistingDataSlots();
   if (slots) {
     slots->mBindingParent = nsnull;
   }
@@ -1103,17 +1103,17 @@ already_AddRefed<nsIAtom>
 nsGenericDOMDataNode::GetCurrentValueAtom()
 {
   nsAutoString val;
   GetData(val);
   return NS_NewAtom(val);
 }
 
 nsIAtom*
-nsGenericDOMDataNode::GetID() const
+nsGenericDOMDataNode::DoGetID() const
 {
   return nsnull;
 }
 
 const nsAttrValue*
 nsGenericDOMDataNode::DoGetClasses() const
 {
   NS_NOTREACHED("Shouldn't ever be called");
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -243,17 +243,17 @@ public:
 #endif
 
   virtual nsIContent *GetBindingParent() const;
   virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
 
   virtual already_AddRefed<nsIURI> GetBaseURI() const;
   virtual PRBool IsLink(nsIURI** aURI) const;
 
-  virtual nsIAtom* GetID() const;
+  virtual nsIAtom* DoGetID() const;
   virtual const nsAttrValue* DoGetClasses() const;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
   virtual nsICSSStyleRule* GetInlineStyleRule();
   NS_IMETHOD SetInlineStyleRule(nsICSSStyleRule* aStyleRule, PRBool aNotify);
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               PRInt32 aModType) const;
   virtual nsIAtom *GetClassAttributeName() const;
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -2964,17 +2964,17 @@ nsGenericElement::UnbindFromTree(PRBool 
   nsIDocument *document =
     HasFlag(NODE_FORCE_XBL_BINDINGS) ? GetOwnerDoc() : GetCurrentDoc();
 
   mParentPtrBits = aNullParent ? 0 : mParentPtrBits & ~PARENT_BIT_INDOCUMENT;
 
   if (document) {
     // Notify XBL- & nsIAnonymousContentCreator-generated
     // anonymous content that the document is changing.
-    document->BindingManager()->ChangeDocumentFor(this, document, nsnull);
+    document->BindingManager()->RemovedFromDocument(this, document);
 
     document->ClearBoxObjectFor(this);
   }
 
   // Ensure that CSS transitions don't continue on an element at a
   // different place in the tree (even if reinserted before next
   // animation refresh).
   // FIXME (Bug 522599): Need a test for this.
@@ -3244,48 +3244,16 @@ nsGenericElement::DispatchDOMEvent(nsEve
                                    nsPresContext* aPresContext,
                                    nsEventStatus* aEventStatus)
 {
   return nsEventDispatcher::DispatchDOMEvent(static_cast<nsIContent*>(this),
                                              aEvent, aDOMEvent,
                                              aPresContext, aEventStatus);
 }
 
-nsIAtom*
-nsGenericElement::GetID() const
-{
-  if (!HasFlag(NODE_MAY_HAVE_ID)) {
-    return nsnull;
-  }
-
-  nsIAtom* IDName = GetIDAttributeName();
-  if (IDName) {
-    const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(IDName);
-    if (attrVal){
-      if (attrVal->Type() == nsAttrValue::eAtom) {
-        return attrVal->GetAtomValue();
-      }
-      if(attrVal->IsEmptyString()){
-        return nsnull;
-      }
-      // Check if the ID has been stored as a string.
-      // This would occur if the ID attribute name changed after 
-      // the ID was parsed. 
-      if (attrVal->Type() == nsAttrValue::eString) {
-        nsAutoString idVal(attrVal->GetStringValue());
-
-        // Create an atom from the value and set it into the attribute list. 
-        const_cast<nsAttrValue*>(attrVal)->ParseAtom(idVal);
-        return attrVal->GetAtomValue();
-      }
-    }
-  }
-  return nsnull;
-}
-
 const nsAttrValue*
 nsGenericElement::DoGetClasses() const
 {
   NS_NOTREACHED("Shouldn't ever be called");
   return nsnull;
 }
 
 NS_IMETHODIMP
@@ -3367,22 +3335,16 @@ nsGenericElement::IsAttributeMapped(cons
 nsChangeHint
 nsGenericElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                          PRInt32 aModType) const
 {
   return nsChangeHint(0);
 }
 
 nsIAtom *
-nsGenericElement::GetIDAttributeName() const
-{
-  return mNodeInfo->GetIDAttributeAtom();
-}
-
-nsIAtom *
 nsGenericElement::GetClassAttributeName() const
 {
   return nsnull;
 }
 
 PRBool
 nsGenericElement::FindAttributeDependence(const nsIAtom* aAttribute,
                                           const MappedAttributeEntry* const aMaps[],
@@ -3799,17 +3761,17 @@ nsGenericElement::GetPrimaryFrame(mozFlu
   return GetPrimaryFrame();
 }
 
 void
 nsGenericElement::DestroyContent()
 {
   nsIDocument *document = GetOwnerDoc();
   if (document) {
-    document->BindingManager()->ChangeDocumentFor(this, document, nsnull);
+    document->BindingManager()->RemovedFromDocument(this, document);
     document->ClearBoxObjectFor(this);
   }
 
   // XXX We really should let cycle collection do this, but that currently still
   //     leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
   nsContentUtils::ReleaseWrapper(this, this);
 
   PRUint32 i, count = mAttrsAndChildren.ChildCount();
@@ -4360,19 +4322,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
       if (tmp->IsXUL())
         NS_IF_RELEASE(slots->mControllers);
       slots->mChildrenList = nsnull;
     }
   }
 
   {
     nsIDocument *doc;
-    if (!tmp->GetNodeParent() && (doc = tmp->GetOwnerDoc()) &&
-        tmp->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-      doc->BindingManager()->ChangeDocumentFor(tmp, doc, nsnull);
+    if (!tmp->GetNodeParent() && (doc = tmp->GetOwnerDoc())) {
+      doc->BindingManager()->RemovedFromDocument(tmp, doc);
     }
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGenericElement)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
@@ -4728,25 +4689,16 @@ nsGenericElement::SetAttrAndNotify(PRInt
 }
 
 PRBool
 nsGenericElement::ParseAttribute(PRInt32 aNamespaceID,
                                  nsIAtom* aAttribute,
                                  const nsAString& aValue,
                                  nsAttrValue& aResult)
 {
-  if (aNamespaceID == kNameSpaceID_None &&
-      aAttribute == GetIDAttributeName() && !aValue.IsEmpty()) {
-    SetFlags(NODE_MAY_HAVE_ID);
-    // Store id as an atom.  id="" means that the element has no id,
-    // not that it has an emptystring as the id.
-    aResult.ParseAtom(aValue);
-    return PR_TRUE;
-  }
-
   return PR_FALSE;
 }
 
 PRBool
 nsGenericElement::SetMappedAttribute(nsIDocument* aDocument,
                                      nsIAtom* aName,
                                      nsAttrValue& aValue,
                                      nsresult* aRetval)
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -374,17 +374,16 @@ public:
 
   // nsIContent interface methods
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
                               PRBool aNullParent = PR_TRUE);
   virtual already_AddRefed<nsINodeList> GetChildren(PRInt32 aChildType);
-  virtual nsIAtom *GetIDAttributeName() const;
   virtual nsIAtom *GetClassAttributeName() const;
   virtual already_AddRefed<nsINodeInfo> GetExistingAttrNameFromQName(const nsAString& aStr) const;
   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, PRBool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
   }
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
@@ -446,17 +445,16 @@ public:
   {
     List(out, aIndent, EmptyCString());
   }
   virtual void DumpContent(FILE* out, PRInt32 aIndent, PRBool aDumpAll) const;
   void List(FILE* out, PRInt32 aIndent, const nsCString& aPrefix) const;
   void ListAttributes(FILE* out) const;
 #endif
 
-  virtual nsIAtom* GetID() const;
   virtual const nsAttrValue* DoGetClasses() const;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
   virtual nsICSSStyleRule* GetInlineStyleRule();
   NS_IMETHOD SetInlineStyleRule(nsICSSStyleRule* aStyleRule, PRBool aNotify);
   NS_IMETHOD_(PRBool)
     IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               PRInt32 aModType) const;
@@ -989,25 +987,39 @@ protected:
   void UnregisterFreezableElement() {
     nsIDocument* doc = GetOwnerDoc();
     if (doc) {
       doc->UnregisterFreezableElement(this);
     }
   }
 
   /**
-   * GetContentsAsText will take all the textnodes that are children
-   * of |this| and concatenate the text in them into aText.  It
-   * completely ignores any non-text-node children of |this|; in
-   * particular it does not descend into any children of |this| that
-   * happen to be container elements.
-   *
-   * @param aText the resulting text [OUT]
+   * Add/remove this element to the documents id cache
    */
-  void GetContentsAsText(nsAString& aText);
+  void AddToIdTable(nsIAtom* aId) {
+    NS_ASSERTION(HasFlag(NODE_HAS_ID), "Node lacking NODE_HAS_ID flag");
+    nsIDocument* doc = GetCurrentDoc();
+    if (doc && (!IsInAnonymousSubtree() || doc->IsXUL())) {
+      doc->AddToIdTable(this, aId);
+    }
+  }
+  void RemoveFromIdTable() {
+    if (HasFlag(NODE_HAS_ID)) {
+      nsIDocument* doc = GetCurrentDoc();
+      if (doc) {
+        nsIAtom* id = DoGetID();
+        // id can be null during mutation events evilness. Also, XUL elements
+        // loose their proto attributes during cc-unlink, so this can happen
+        // during cc-unlink too.
+        if (id) {
+          doc->RemoveFromIdTable(this, DoGetID());
+        }
+      }
+    }
+  }
 
   /**
    * Functions to carry out event default actions for links of all types
    * (HTML links, XLinks, SVG "XLinks", etc.)
    */
 
   /**
    * Check that we meet the conditions to handle a link event
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -573,23 +573,16 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
     // aNode's children.
     PRUint32 i, length = aNode->GetChildCount();
     for (i = 0; i < length; ++i) {
       nsCOMPtr<nsINode> child;
       rv = CloneAndAdopt(aNode->GetChildAt(i), aClone, PR_TRUE, nodeInfoManager,
                          aCx, aOldScope, aNewScope, aNodesWithProperties,
                          clone, getter_AddRefs(child));
       NS_ENSURE_SUCCESS(rv, rv);
-      if (isDeepDocumentClone) {
-        NS_ASSERTION(child->IsNodeOfType(nsINode::eCONTENT),
-                     "A clone of a child of a node is not nsIContent?");
-
-        nsIContent* content = static_cast<nsIContent*>(child.get());
-        static_cast<nsDocument*>(clone.get())->RegisterNamedItems(content);
-      }
     }
   }
 
   // XXX setting document on some nodes not in a document so XBL will bind
   // and chrome won't break. Make XBL bind to document-less nodes!
   // XXXbz Once this is fixed, fix up the asserts in all implementations of
   // BindToTree to assert what they would like to assert, and fix the
   // ChangeDocumentFor() call in nsXULElement::BindToTree as well.  Also,
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -66,16 +66,30 @@ nsStyledElement::GetClassAttributeName()
 }
 
 nsIAtom*
 nsStyledElement::GetIDAttributeName() const
 {
   return nsGkAtoms::id;
 }
 
+nsIAtom*
+nsStyledElement::DoGetID() const
+{
+  NS_ASSERTION(HasFlag(NODE_HAS_ID), "Unexpected call");
+
+  // The nullcheck here is needed because nsGenericElement::UnsetAttr calls
+  // out to various code between removing the attribute and we get a chance to
+  // clear the NODE_HAS_ID flag.
+
+  const nsAttrValue* attr = mAttrsAndChildren.GetAttr(nsGkAtoms::id);
+
+  return attr ? attr->GetAtomValue() : nsnull;
+}
+
 const nsAttrValue*
 nsStyledElement::DoGetClasses() const
 {
   NS_ASSERTION(HasFlag(NODE_MAY_HAVE_CLASS), "Unexpected call");
   return mAttrsAndChildren.GetAttr(nsGkAtoms::_class);
 }
 
 PRBool
@@ -88,22 +102,55 @@ nsStyledElement::ParseAttribute(PRInt32 
       ParseStyleAttribute(aValue, aResult, PR_FALSE);
       return PR_TRUE;
     }
     if (aAttribute == nsGkAtoms::_class) {
       SetFlags(NODE_MAY_HAVE_CLASS);
       aResult.ParseAtomArray(aValue);
       return PR_TRUE;
     }
+    if (aAttribute == nsGkAtoms::id) {
+      // Store id as an atom.  id="" means that the element has no id,
+      // not that it has an emptystring as the id.
+      RemoveFromIdTable();
+      if (aValue.IsEmpty()) {
+        UnsetFlags(NODE_HAS_ID);
+        return PR_FALSE;
+      }
+      aResult.ParseAtom(aValue);
+      SetFlags(NODE_HAS_ID);
+      AddToIdTable(aResult.GetAtomValue());
+      return PR_TRUE;
+    }
   }
 
   return nsStyledElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                              aResult);
 }
 
+nsresult
+nsStyledElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
+                           PRBool aNotify)
+{
+  PRBool isId = PR_FALSE;
+  if (aAttribute == nsGkAtoms::id && aNameSpaceID == kNameSpaceID_None) {
+    // Have to do this before clearing flag. See RemoveFromIdTable
+    RemoveFromIdTable();
+    isId = PR_TRUE;
+  }
+  
+  nsresult rv = nsGenericElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
+
+  if (isId) {
+    UnsetFlags(NODE_HAS_ID);
+  }
+
+  return rv;
+}
+
 NS_IMETHODIMP
 nsStyledElement::SetInlineStyleRule(nsICSSStyleRule* aStyleRule, PRBool aNotify)
 {
   SetFlags(NODE_MAY_HAVE_STYLE);
   PRBool modification = PR_FALSE;
   nsAutoString oldValueStr;
 
   PRBool hasListeners = aNotify &&
@@ -158,23 +205,38 @@ nsStyledElement::BindToTree(nsIDocument*
                             nsIContent* aBindingParent,
                             PRBool aCompileEventHandlers)
 {
   nsresult rv = nsStyledElementBase::BindToTree(aDocument, aParent,
                                                 aBindingParent,
                                                 aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // XXXbz if we already have a style attr parsed, this won't do
-  // anything... need to fix that.
-  ReparseStyleAttribute(PR_FALSE);
+  if (aDocument && HasFlag(NODE_HAS_ID) && !GetBindingParent()) {
+    aDocument->AddToIdTable(this, DoGetID());
+  }
+
+  if (!IsXUL()) {
+    // XXXbz if we already have a style attr parsed, this won't do
+    // anything... need to fix that.
+    ReparseStyleAttribute(PR_FALSE);
+  }
 
-  return rv;
+  return NS_OK;
 }
 
+void
+nsStyledElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
+{
+  RemoveFromIdTable();
+
+  nsStyledElementBase::UnbindFromTree(aDeep, aNullParent);
+}
+
+
 // ---------------------------------------------------------------
 // Others and helpers
 
 nsresult
 nsStyledElement::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
 {
   nsGenericElement::nsDOMSlots *slots = GetDOMSlots();
   NS_ENSURE_TRUE(slots, NS_ERROR_OUT_OF_MEMORY);
--- a/content/base/src/nsStyledElement.h
+++ b/content/base/src/nsStyledElement.h
@@ -59,27 +59,32 @@ class nsStyledElement : public nsStyledE
 protected:
 
   inline nsStyledElement(nsINodeInfo *aNodeInfo)
     : nsStyledElementBase(aNodeInfo)
   {}
 
 public:
 
-  // nsIContent interface methods for styling
+  // nsIContent interface methods
   virtual nsIAtom* GetClassAttributeName() const;
   virtual nsIAtom* GetIDAttributeName() const;
+  virtual nsIAtom* DoGetID() const;
   virtual const nsAttrValue* DoGetClasses() const;
 
   virtual nsICSSStyleRule* GetInlineStyleRule();
   NS_IMETHOD SetInlineStyleRule(nsICSSStyleRule* aStyleRule, PRBool aNotify);
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
+  virtual void UnbindFromTree(PRBool aDeep, PRBool aNullParent);
+
+  virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
+                             PRBool aNotify);
 
 protected:
 
   /**
    * Parse a style attr value into a CSS rulestruct (or, if there is no
    * document, leave it as a string) and return as nsAttrValue.
    *
    * @param aValue the value to parse
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -338,16 +338,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug543870.html \
 		file_bug543870_img.jpg \
 		file_bug543870_inner.html \
 		file_bug543870_doc.html \
 		file_bug543870_text.txt \
 		test_bug475156.html \
 		bug475156.sjs \
 		test_bug544642.html \
+		test_bug564863.xhtml \
 		test_copypaste.html \
 		test_bug503481.html \
 		file_bug503481.sjs \
 		test_bug503481b.html \
 		file_bug503481b_inner.html \
 		test_viewport_scroll.html \
 		test_CSP.html \
 		file_CSP.sjs \
@@ -385,16 +386,18 @@ include $(topsrcdir)/config/rules.mk
 		file_csp_redirects_resource.sjs \
 		test_bug346485.html \
 		test_bug560780.html \
 		test_bug562652.html \
 		test_bug562137.html \
 		file_bug562137.txt \
 		test_bug548193.html \
 		file_bug548193.sjs \
+		test_html_colors_quirks.html \
+		test_html_colors_standards.html \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
 _TEST_FILES2 += 	test_copyimage.html \
 		$(NULL)
 endif
 
--- a/content/base/test/test_bug493881.html
+++ b/content/base/test/test_bug493881.html
@@ -10,17 +10,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="test_bug493881.js"></script>     
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <style type="text/css">
 
   </style>
 </head>
 
-<body>
+<body id="body">
 
 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=493881"
    target="_blank" >Mozilla Bug 493881</a>
 
 <p id="display"></p>
 
 <a id="nonvisitedlink" href="http://www.example.com/">Non-visited link</a>
 <a id="visitedlink" href="">Visited link</a>
--- a/content/base/test/test_bug493881.js
+++ b/content/base/test/test_bug493881.js
@@ -5,17 +5,17 @@
  */
 
 SimpleTest.waitForExplicitFinish();
 
 var legacyProps = ["fgColor", "bgColor", "linkColor", "vlinkColor", "alinkColor"];
 var testColors = ["blue", "silver", "green", "orange", "red"];
 var rgbTestColors = ["rgb(255, 0, 0)", "rgb(192, 192, 192)", "rgb(0, 128, 0)", "rgb(255, 165, 0)", "rgb(255, 0, 0)"];
 var idPropList = [ {id: "plaintext", prop: "color"},
-                   {id: "plaintext", prop: "background-color"},
+                   {id: "body", prop: "background-color"},
                    {id: "nonvisitedlink", prop: "color"},
                    {id: "visitedlink", prop: "color"} ];
 var initialValues = [];
 
 function setAndTestProperty(prop, color) {
   var initial = document[prop];
   document[prop] = color;
   is(document[prop], initial, "document[" + prop + "] not ignored before body");
@@ -53,20 +53,20 @@ addLoadEvent( function() {
   // Verify that setting legacy color props to undefined after BODY loads will cause them
   // to be read as the string "undefined".
   for (var i = 0; i < legacyProps.length; i++) {
     document[legacyProps[i]] = undefined;
     is(document[legacyProps[i]], "undefined", 
       "Unexpected value of " + legacyProps[i] + " after setting to undefined");
   }
   
-  // Verify that setting legacy color props to undefined did not affect rendering 
-  // (computed styles).
+  // Verify that setting legacy color props to undefined led to result
+  // of parsing undefined as a color.
   for (i = 0; i < idPropList.length; i++) {
     var style = window.getComputedStyle(document.getElementById(idPropList[i].id), null);
     var color = style.getPropertyValue(idPropList[i].prop);
-    is(color, idPropList[i].initialComputedColor, 
-      "element's style changed by setting legacy prop to undefined");
+    is(color, "rgb(0, 239, 14)", 
+      "element's style should get result of parsing undefined as a color");
   }
 
   // Mark the test as finished.
   setTimeout(SimpleTest.finish, 0);
 });
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug564863.xhtml
@@ -0,0 +1,328 @@
+<!DOCTYPE html [
+<!ATTLIST ns:x id ID #REQUIRED>
+<!ATTLIST ns2:x id_2 ID #REQUIRED>
+]>
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+      xmlns:svg="http://www.w3.org/2000/svg"
+      xmlns:ns="urn:namespace"
+      xmlns:ns2="urn:namespace">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=564863
+-->
+<head>
+  <title>Test for Bug 564863</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<style>
+#div_id {
+  color: rgb(10, 10, 10);
+}
+#a_id {
+  color: rgb(20, 20, 20);
+}
+#xul_id {
+  color: rgb(30, 30, 30);
+}
+#svg_id {
+  color: rgb(40, 40, 40);
+}
+#ns_id {
+  color: rgb(50, 50, 50);
+}
+#ns2_id {
+  color: rgb(60, 60, 60);
+}
+</style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=564863">Mozilla Bug 564863</a>
+<!-- Elements to ensure we have nodeinfos with id-attribute set -->
+<div><ns:x id="ns-holder"/><ns2:x id_2="ns2-holder"/></div>
+
+<!-- DOM to muck around with for tests -->
+<p id="root">
+<div id="div_id" />
+<a id="a_id" />
+<xul:button id="xul_id" />
+<svg:svg><svg:g id="svg_id" /></svg:svg>
+<ns:x id="ns_id" />
+</p>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+
+root = $('root');
+div = root.children[0];
+a = root.children[1];
+xul = root.children[2];
+svg = root.children[3].firstChild;
+nsx = root.children[4];
+
+var div_cs = getComputedStyle(div, "");
+var a_cs = getComputedStyle(a, "");
+var xul_cs = getComputedStyle(xul, "");
+var svg_cs = getComputedStyle(svg, "");
+var nsx_cs = getComputedStyle(nsx, "");
+
+function checkHasId(test) {
+  // Check computed style first to avoid flushes from hiding problems
+  checkHasIdNoGEBI(test);
+
+  is($("div_id"), div, "div getElementById " + test);
+  is($("a_id"),   a,   "a getElementById " + test);
+  is($("xul_id"), xul, "xul getElementById " + test);
+  is($("svg_id"), svg, "svg getElementById " + test);
+  is($("ns_id"),  nsx, "ns getElementById " + test);
+}
+
+function checkHasIdNoGEBI(test) {
+  is(div_cs.color, "rgb(10, 10, 10)", "div color " + test);
+  is(a_cs.color,   "rgb(20, 20, 20)", "a color " + test);
+  is(xul_cs.color, "rgb(30, 30, 30)", "xul color " + test);
+  is(svg_cs.color, "rgb(40, 40, 40)", "svg color " + test);
+  is(nsx_cs.color, "rgb(50, 50, 50)", "nsx color " + test);
+
+  is(div.id, "div_id", "div id " + test);
+  is(a.id,   "a_id",   "a id " + test);
+  is(xul.id, "xul_id", "xul id " + test);
+  is(svg.id, "svg_id", "svg id " + test);
+  is (nsx.getAttribute("id"), "ns_id", "ns id " + test);
+}
+
+function checkHasNoId(removed, test) {
+  is(div_cs.color, "rgb(0, 0, 0)", "div color " + test);
+  is(a_cs.color,   "rgb(0, 0, 0)", "a color " + test);
+  is(xul_cs.color, "rgb(0, 0, 0)", "xul color " + test);
+  is(svg_cs.color, "rgb(0, 0, 0)", "svg color " + test);
+  is(nsx_cs.color, "rgb(0, 0, 0)", "nsx color " + test);
+
+  attrValue = removed ? null : "";
+
+  is(div.id, "", "div id " + test);
+  is(a.id,   "", "a id " + test);
+  is(xul.id, "", "xul id " + test);
+  is(svg.id, "", "svg id " + test);
+
+  is(div.getAttribute("id"), attrValue, "div getAttribute " + test);
+  is(a.getAttribute("id"),   attrValue, "a getAttribute " + test);
+  is(xul.getAttribute("id"), "",        "xul getAttribute " + test);
+  is(svg.getAttribute("id"), attrValue, "svg getAttribute " + test);
+  is(nsx.getAttribute("id"), attrValue, "ns getAttribute " + test);
+  
+  is($("div_id"), null, "div getElementById " + test);
+  is($("a_id"),   null, "a getElementById " + test);
+  is($("xul_id"), null, "xul getElementById " + test);
+  is($("svg_id"), null, "svg getElementById " + test);
+  is($("ns_id"),  null, "ns getElementById " + test);
+}
+
+// Check that dynamic modifications of attribute work
+
+checkHasId("in markup");
+
+div.id = "";
+a.id = "";
+xul.id = "";
+svg.id = "";
+nsx.setAttribute("id", "");
+
+checkHasNoId(false, "set to empty");
+
+div.id = "div_id";
+a.id = "a_id";
+xul.id = "xul_id";
+svg.id = "svg_id";
+nsx.setAttribute("id", "ns_id");
+
+checkHasId("set using .id");
+
+div.setAttribute("id", "");
+a.setAttribute("id",   "");
+xul.setAttribute("id", "");
+svg.setAttribute("id", "");
+nsx.setAttribute("id", "");
+
+checkHasNoId(false, "setAttribute to empty");
+
+div.id = "div_id";
+a.id = "a_id";
+xul.id = "xul_id";
+svg.id = "svg_id";
+nsx.setAttribute("id", "ns_id");
+
+checkHasId("set again using .id");
+
+div.removeAttribute("id");
+a.removeAttribute("id");
+xul.removeAttribute("id");
+svg.removeAttribute("id");
+nsx.removeAttribute("id");
+
+checkHasNoId(true, "removed attribute");
+
+div.setAttribute("id", "div_id");
+a.setAttribute("id",   "a_id");
+xul.setAttribute("id", "xul_id");
+svg.setAttribute("id", "svg_id");
+nsx.setAttribute("id", "ns_id");
+
+checkHasId("set using setAttribute");
+
+t1 = document.createElement("div");
+t1.id = "div_id";
+t2 = document.createElement("a");
+t2.id = "a_id";
+t3 = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "button");
+t3.id = "xul_id";
+t4 = document.createElementNS("http://www.w3.org/2000/svg", "g");
+t4.id = "svg_id";
+t5 = document.createElementNS("urn:namespace", "ns:x");
+t5.setAttribute("id", "ns_id");
+
+// Check that inserting elements before/after existing work
+
+function insertAfter(newChild, existing) {
+  existing.parentNode.insertBefore(newChild, existing.nextSibling);
+}
+function insertBefore(newChild, existing) {
+  existing.parentNode.insertBefore(newChild, existing);
+}
+function removeNode(child) {
+  child.parentNode.removeChild(child);
+}
+
+insertAfter(t1, div);
+insertAfter(t2, a);
+insertAfter(t3, xul);
+insertAfter(t4, svg);
+insertAfter(t5, nsx);
+
+checkHasId("inserted after");
+
+insertBefore(t1, div);
+insertBefore(t2, a);
+insertBefore(t3, xul);
+insertBefore(t4, svg);
+insertBefore(t5, nsx);
+
+checkHasIdNoGEBI("inserted before");
+is($("div_id"), t1, "div getElementById inserted before");
+is($("a_id"),   t2,   "a getElementById inserted before");
+is($("xul_id"), t3, "xul getElementById inserted before");
+is($("svg_id"), t4, "svg getElementById inserted before");
+is($("ns_id"),  t5, "ns getElementById inserted before");
+
+t1.removeAttribute("id");
+t2.removeAttribute("id");
+t3.removeAttribute("id");
+t4.removeAttribute("id");
+t5.removeAttribute("id");
+
+checkHasId("removed tx attribute");
+
+t1.setAttribute("id", "div_id");
+t2.setAttribute("id",   "a_id");
+t3.setAttribute("id", "xul_id");
+t4.setAttribute("id", "svg_id");
+t5.setAttribute("id", "ns_id");
+
+checkHasIdNoGEBI("setAttribute before");
+is($("div_id"), t1, "div getElementById setAttribute before");
+is($("a_id"),   t2,   "a getElementById setAttribute before");
+is($("xul_id"), t3, "xul getElementById setAttribute before");
+is($("svg_id"), t4, "svg getElementById setAttribute before");
+is($("ns_id"),  t5, "ns getElementById setAttribute before");
+
+removeNode(t1);
+removeNode(t2);
+removeNode(t3);
+removeNode(t4);
+removeNode(t5);
+
+checkHasId("removed temporaries");
+
+removeNode(div);
+removeNode(a);
+removeNode(xul);
+removeNode(svg);
+removeNode(nsx);
+
+checkHasIdNoGEBI("removed node");
+
+// Check that removing an element during UnsetAttr works
+is(div.id, "div_id", "div still has id set");
+var mutateFired = false;
+root.appendChild(div);
+var f = function(e) {
+  div.removeEventListener("DOMAttrModified", f, false);
+  is(e.target, div, "target is div");
+  is(div.id, "", "div no longer has id");
+  is(div.getAttribute("id"), null, "div no longer has id attr");
+  removeNode(div);
+  is(div.parentNode, null, "div was removed");
+  mutateFired = true;
+}
+div.addEventListener("DOMAttrModified", f, false);
+div.removeAttribute("id");
+ok(mutateFired, "mutation event fired");
+
+// Check same for XML elements
+is(nsx.getAttribute("id"), "ns_id", "nsx still has id set");
+mutateFired = false;
+root.appendChild(nsx);
+var f2 = function(e) {
+  nsx.removeEventListener("DOMAttrModified", f2, false);
+  is(e.target, nsx, "target is nsx");
+  is(nsx.getAttribute("id"), null, "nsx no longer has id attr");
+  removeNode(nsx);
+  is(nsx.parentNode, null, "nsx was removed");
+  mutateFired = true;
+}
+nsx.addEventListener("DOMAttrModified", f2, false);
+nsx.removeAttribute("id");
+ok(mutateFired, "mutation event fired");
+
+
+// Check that modifying the id-name of an XML element works
+ok($("ns-holder"), "ns-holder exists");
+ok($("ns2-holder"), "ns2-holder exists");
+root.appendChild(nsx);
+nsx.setAttribute("id", "ns_id");
+is(nsx_cs.color, "rgb(50, 50, 50)", "nsx has initial id");
+is($("ns_id"), nsx, "gEBI works on old id");
+nsx.setAttribute("id_2", "ns2_id");
+nsx.prefix = "ns2";
+removeNode(nsx);
+root.appendChild(nsx);
+is(nsx_cs.color, "rgb(60, 60, 60)", "nsx has new id");
+is($("ns2_id"), nsx, "gEBI works on new id");
+
+// Need to change id and then CC to ensure that we don't end up with dangling pointers
+function gc() {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+        .getInterface(Components.interfaces.nsIDOMWindowUtils)
+        .garbageCollect();
+}
+ok($("ns-holder"), "ns-holder exists");
+ok($("ns2-holder"), "ns2-holder exists");
+tempNode = document.createElementNS("urn:namespace", "ns:x");
+tempNode.setAttribute("id", "tempNode_id");
+document.body.appendChild(tempNode);
+is($("tempNode_id"), tempNode, "tempNode in gEBI table");
+tempNode.prefix = "ns2";
+removeNode(tempNode);
+tempNode = null;
+gc();
+$("tempNode_id");
+ok(true, "Didn't crash when accessing old id");
+
+
+]]>
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_html_colors_quirks.html
@@ -0,0 +1,712 @@
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=121738
+-->
+<head>
+  <meta charset="UTF-8">
+  <title>Test for Bug 121738</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=121738">Mozilla Bug 121738</a>
+<table id="table0"></table>
+<table id="table1"></table>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 121738 **/
+
+String.prototype.toAsciiLowerCase = function () {
+  var output = "";
+  for (var i = 0, len = this.length; i < len; ++i) {
+    if (this.charCodeAt(i) >= 0x41 && this.charCodeAt(i) <= 0x5A) {
+      output += String.fromCharCode(this.charCodeAt(i) + 0x20)
+    } else {
+      output += this.charAt(i);
+    }
+  }
+  return output;
+}
+
+var tests = [
+"#135",
+" #135",
+"#135 ",
+" #135 ",
+"# 135",
+"#   135",
+"#123456",
+" #123456",
+"#123456 ",
+" #123456 ",
+"# 123456",
+"#   123456",
+"aliceblue",
+"ALICEBLUE",
+"alıceblue",
+"alİceblue",
+" aliceblue",
+"aliceblue ",
+"  aliceblue   ",
+"antiquewhite",
+"aqua",
+"aquamarine",
+"azure",
+"beige",
+"bisque",
+"black",
+"blanchedalmond",
+"blue",
+"blueviolet",
+"brown",
+"burlywood",
+"cadetblue",
+"chartreuse",
+"chocolate",
+"coral",
+"cornflowerblue",
+"cornsilk",
+"crimson",
+"cyan",
+"darkblue",
+"darkcyan",
+"darkgoldenrod",
+"darkgray",
+"darkgreen",
+"darkgrey",
+"darkkhaki",
+"darkmagenta",
+"darkolivegreen",
+"darkorange",
+"darkorchid",
+"darkred",
+"darksalmon",
+"darkseagreen",
+"darkslateblue",
+"darkslategray",
+"darkslategrey",
+"darkturquoise",
+"darkviolet",
+"deeppink",
+"deepskyblue",
+"dimgray",
+"dimgrey",
+"dodgerblue",
+"firebrick",
+"floralwhite",
+"forestgreen",
+"fuchsia",
+"gainsboro",
+"ghostwhite",
+"gold",
+"goldenrod",
+"gray",
+"green",
+"greenyellow",
+"grey",
+"honeydew",
+"hotpink",
+"indianred",
+"indigo",
+"ivory",
+"khaki",
+"lavender",
+"lavenderblush",
+"lawngreen",
+"lemonchiffon",
+"lightblue",
+"lightcoral",
+"lightcyan",
+"lightgoldenrodyellow",
+"lightgray",
+"lightgreen",
+"lightgrey",
+"lightpink",
+"lightsalmon",
+"lightseagreen",
+"lightskyblue",
+"lightslategray",
+"lightslategrey",
+"lightsteelblue",
+"lightyellow",
+"lime",
+"limegreen",
+"linen",
+"magenta",
+"maroon",
+"mediumaquamarine",
+"mediumblue",
+"mediumorchid",
+"mediumpurple",
+"mediumseagreen",
+"mediumslateblue",
+"mediumspringgreen",
+"mediumturquoise",
+"mediumvioletred",
+"midnightblue",
+"mintcream",
+"mistyrose",
+"moccasin",
+"navajowhite",
+"navy",
+"oldlace",
+"olive",
+"olivedrab",
+"orange",
+"orangered",
+"orchid",
+"palegoldenrod",
+"palegreen",
+"paleturquoise",
+"palevioletred",
+"papayawhip",
+"peachpuff",
+"peru",
+"pink",
+"plum",
+"powderblue",
+"purple",
+"red",
+"rosybrown",
+"royalblue",
+"saddlebrown",
+"salmon",
+"sandybrown",
+"seagreen",
+"seashell",
+"sienna",
+"silver",
+"skyblue",
+"slateblue",
+"slategray",
+"slategrey",
+"snow",
+"springgreen",
+"steelblue",
+"tan",
+"teal",
+"thistle",
+"tomato",
+"turquoise",
+"violet",
+"wheat",
+"white",
+"whitesmoke",
+"yellow",
+"yellowgreen",
+"transparent",
+"TRANSPARENT",
+"",
+"inherit",
+"INHERIT",
+"KQ@m?-ldxNK{zH+(FL_owz>YNH^]",
+"aj9c)r+J&3)0E,- Lzv6K6nT@6?I}BY^\\g",
+"Cf}qJN|3D>m:^[7B*fhu>lC[B3\"T_-F",
+"h<s1pMd-8H[,\\caWH1oW3%M",
+"z{y]VZj)%)ZV<OTbO9\\Nbc|YL}4BI<DlUBk$EV`EbN}x/@SDN0(",
+"PSX2Ol8@",
+"d+gYXKUM'&D'S]o<9T\\:hj_i!|l!)e6R4Bo)-(965rlK\"K01C68pgkJ] fx?kjT.O&sY4",
+"[4\"tk)a/v17?0W!F`AyI[='2~;:DF6I>_<O$ he213u",
+"F|r9T&N69MWq3Jrj6",
+"dYR7}n&:Rq[J",
+"M;Z]r@(R([6aT`<sN?uO'2Kb~3U\\\\tQUDxLN1f/D(,Q0w|K;,t`,tQ~[W/c!uQg)d|:D\\U33!DK&d*C`Zc'U#",
+"kV)DKUb~h{SQCM;T*g2!Rj?>Sl=jY;3W9M{Fliu!=>tDY]5",
+"y>X\\kKN|~=J+7Pqp|%9R!nZ,@>mUW9<o;|02LV<fxihsBSKVaTdcae",
+"Q>jc|/:#qwzHL`lL%e~DbhQ+d^tpf9sx%o)jC1Nm}`G;rT2jo+M$=$?BC'|O^]hW^BBo_J->bWG1",
+"OIxA\\5HB7g3Rv;PD)z?jGe?<x`4~9&D9dSDP=ilUauI'qb",
+"aND[Al/^#;n'|V\"Vl$bh5\\G#{%y4#\\W0:ZgXe73ZuXrWcL4gr|B7,ijZZi{p)M+R9{C/&249G",
+"7xK-d6Tx]BU|T,DY.qCwusmV%Ksset",
+"I=UwM''S",
+"w|_;Qw(R:>Clf[#3JFr_+?'1D&}WaY_xaRyTpwio>C;Pjf/kIW{]KK:R&ARiP=_g_UqRVvFKG(OQo6y'wF]Fc",
+"G:",
+"+XZ%s7L3FmGFn]Y!J;.vpAUoGU,&WY8eQeGWW?Jq7ANeM}[?gsV) H\\@{8z_t$oS(_jSq]|9?W*sG%' (d%",
+"*P\"?'?NHA \\!{.S=+LD8Ltr^'=,$4uQ=tVL/T_b6m!PJ8*s*v`;6kp(+8i.}T!9p6{",
+"_@(w<\\DjMk c8/\"/ifJNT_2R>V'}{&72C2+7otvd,$M@Yqc)L=O.muEp28m&AY",
+"J!M#$z|n:+:6@7n*v)UCbkVp0;\"1#}o:i4B9oh=%'I",
+"0",
+"Krq?xAul2cRe&`*Fg2)bV/r>oJ`Z(ae,z%+`E@VkWH&`-jMZ<UW~jxDek;^j2\\Uq;C,Ss",
+"#b\\l~=y5H=#Jy(6FwH5]jU;6D",
+"YO|tw;`E_'G<d~juVPCla%K]q x\"oA-aW|Y@P$_$",
+"}rI\\5x724b29MEauSSX&!AT[J1ce?,rtLAA8X",
+"hlo8jd$D-dI=I#Be:BATkZPR~%Vfe0g_Xw^+wwhHQhC1;sn+P<b&J:~HfxVBX}9b/#HHPS",
+"+#[?UFGUVFn0Zn7yE#TEo{FV\\{6*+s+a=fR",
+"lhv.f!ENs~)?5)z:1^i@BQ|ol}9Cnkw&yV.PPx |y]@,?IL]0L_# b1'wl-]",
+"&DhZ!g%v.sF}4NoP~4<vKpaM0[12!2K!ziYC3`505I*D*J6k\\skbXJ}44J#4y2",
+"oK][N&iIV\"AEs3rIT-::L3&J^Sn42_J2yL= 2xI4o!b\"#2JiAt=",
+"^c;C^{0wD%|y~Z1X'z\\o^gI8L=@2^p3g/L6G?]Nuif;Zf15dF`IPt8",
+"62t-!*`U\\l%BFxi5B~[^~G!}h]DtXrd}y}af3",
+"?N5d9ydHPi?IhwU=41'",
+"GSZeLtA3YahI@oLy/6vT_[B`[PRZ1^.(n8`,8TyqVoCzMd!=9 e",
+"Yck5`_#NgS",
+"K9?z&o",
+"Isl2>%RB8T+,9?B{~A2{fEb[%",
+"&fV(`<ha/(T7J&X\\{YHt+5 =>%SaJ&W0_j]]\"",
+">!sQ/IYU\"Ikc\\ei;HlCcVJ\":G2/m]h1,GvOmxFOOvTUHjHu:LWE\"QU=) ",
+"7Fyx#>\"(\"N",
+"MO6\"Hd2H]r8BJ}z)%J18b<VZ5lrhI",
+"BGQ|tqdwj4};#x@?%ka[`DwgFWg*J+q/}]-\\\\-y#T",
+"zZ=JrTPxh}.(%frt58Cy=C4(*,4]:Gnz5(~iv4@u4re~6yp:zbU0(o.S+qd9eB]A5",
+"n]V3}^{9O<0cO\"rtglDO4Wc)_7Nu_JnK2EBbzRMV3b.Mj\"$9#,+-T\"N=7iPdD F<9_YWw3ZN*V;??*8VN8z?^MXi",
+"fGRSl*i>^*uy|c;5B}tKXu>5hZX:>CB{oWIrxE8@B/f{:u9]:bLO0/ZWeHoNfCc|kSh{/fXs9Y:UKaJ95vFFtB2Y",
+".&-4UOcxR\"Tbgc--@& hoUavCcQW^^fT}:I(d%o}J2t*BRA1{YGXB9>AYu^Bv#rEu`pN65_-r.IQD.?Cc/B({YtK[2KMmVOC3*2J",
+"H3<MOq'81C#\\nUjQc  xlsF@c2R<e);T~G]^N0_*M<j!jub~k,mgZ(.>GERhwS;kmmKC?1l} qQ&zcXK?g)S OmF^=E^TlTC)/",
+"8\\5tFz:sod",
+"ILUc5c!'K.7.P&=S,pSYB{",
+"%\\(6.jC\"C4\\2{TYdx,Ln^",
+"tL3HnWq q!'k!#R@2bkvIAI]hk)64-i?uk]oK(nQiKg$`m6tx|#l>m1bEK^&.X[o'b\"\\',A16n>9ZAPI9>",
+"{#Mn0,S~a\"!gw",
+"dv+6'7Dd)fz",
+"9o1*Q:{6#3f uHx\"_",
+".43_zr}X+BtruMV!H!xw 8!9I_}zlBT3W52)rh,9ngeu0o[V_s*z'8x9*yjF!",
+"y3Nm`>P:seF'V'?+<={oU5QQ",
+".#Os_jv,\"@-zsY8j'POOYnY?0ONn?i#d4tqp?~.OF#VC.=<t<+feuf{#@O7lXC@+#t_uKGue%Dk9z",
+"0Ep=zwydU-V<)9<9\\`[4,d^B&Gbo#'HTSEC;qU&1| ocNd69#{nbmYJMlj6Mfs3`w&pc(poie *ZOJIp7%}cVnfml",
+"746}e(rye4lT7#B.Or8j1->Xs@o8f0}/e>uvvkNS[3UC2F]#[>^f74jxoo&9{^ED#,CV\"k'0|xI",
+".D1{.:9gHW}]36RlUQ?!-\"0dn:+(/e@b)|'B",
+"!Nh9xY2y?5ku5f}%]JWw~OfeYdcgI#It` T)3VzYl5gChve[I'rEqyJ \"@(z.Y%fEJ:9k(",
+"J^$^L8:qI=yrerd0kxJBEwby6[>9[) NpqN%)h",
+"l&\\K{s9]aL(,dX?B\"1g1*@9BY~=UO+AWvVRI;ar4p8Tsy~Qk-=x(yp38:j|g'5H~e4",
+"(]Pe,1fTS_P%[xY96#,rwQz=P?z",
+")PC#?b'&|maJBt.6Izz%vV5e!9Sy|G!*Q",
+"pzAG^@/J&)Dc}GP*xO]ezW:*PV|Dt^fF<8GgF_1i=A\"@>nt?yOa|zS<8`/;uY~^ozjvX!K#%us!>2IYITh]Zy<^dq?&\"nqV]ZdZ",
+"T<xz*/H&}36<(4E^/Z1m<#_G0R:=qX?1`*6Y&r'SIO]9OR;m5-Zq?PU^jvLKPLW2wPf",
+")CLhmCI%TwB+t:h.@Vp-#({d0W/R_(^f34LC=V)A",
+"yCT_hl%fUL<T&e;ePsT.pJG@|jO,[pN]]Q<Yu=Lp6X6&$Ka#",
+" $4X",
+"rp",
+"t^(*U<Qdi$!vyg5D\"yQZd<K6<Qptsvzi~D}.Uf?P$E>}t8VP^;3Tamv2Z$1<",
+",",
+"EGCXZ_{eqIwfG-o7o\\\"!ZWTPLd,U-k$Cz]%:vNWdo}vDh!ONtM>mMP{/Cg+2<.J\"a*n#Rtnha",
+"LQ3sIr7Q_ wSD7Zzv$-vxr|3P`pas0#Ze/---{PSwJ3{!a*[k'nFgC\"W+@4URi?qJk&Tt@`abNms40#A^XcAt}",
+"^i356'hX\"hKaZGfTZ|C@#}b3LGz1\">qcH{L8{Fs?O5%:EqQWuro_lc=]gWLVR\\~!J\"[>,H",
+"i{*q<O{Dt^n|FY3,FG>WIRqPH.os$9^P=|yA9?P;MOw;VBwZ^>K=\"%J9SBlv%0+o5k73rW!`l_",
+"-PCM&!G~o#Za^s&)qJELr\\P^\\={_xTFp:%@JF.PeRX\\7b8K",
+"V_sFicB+wx5",
+"\"X^\\d}b9.W.2\"O!yAL21\"Ny5:)=Q3*D|TAzzr^0Yflzjdc!p*.yW,B",
+"kZ`wCP>9Bq5S!r!Vi|Uy/C&H[kz/f^{(Z[OGw'S0\"",
+"Jn%1^rUnNB|%=q%^v*bN|I40}#Htn{G!#~CNAN0KvZcB>Ita(,n",
+"-PlhE[^J55Ui",
+"z`h`uQJ{J",
+"eV\\q5Q4o@Y*,IRMcnpqj5>Id\\yBe?pKH3uF&c<c}:E9[uaH$ 8dXCmI+!C'q@PkE<NVRq~GRW<tfyt/i@%dwI&rL",
+"UGzLF+o3)Ezs=nMxqd^\"=q.Ik}Tk2I`X)R8]Zmy/WQp,|]TdbP)5  J+#Hm6SmWtQ+h?.MQ1W#oyp\\F,'JL>rLtjiHOA",
+"&joOSw7XZVvSt4ZCT*:aq:3ns!v|r);~7gN8'_D",
+"Y<q|Mhn5Nrcb+dR=10pQF5]r@/*7P`79w/htSm2,C~1&sUW{N@v:t9d;HPG&xrI\"YD;V9Y$'g,W'J=GV3,YK",
+"Gx&#{;]l/?[{SyX`kTeo",
+"30PU7@<'58.hRWsJTa9L.hVQ8}7=$}ih4|$Y*9z3[aooT!]}+>b{1JH^.jjEU{,dAXSCbtEh6",
+"%2~x8=A!RW@8N/`hQz`)gl}1DOU9{>Ie'L> 4e]m;kt =isEQ(\\TeI7hWgK-K! p^K'\":3;dxTLO",
+"\\ ):{Woay[4",
+"\\{Ih&}*8^x6@`V@DZB`rSuhYm4i@TW^t9Hx[^`IVumjXc1vA\"~wt8^Jf:US6Z\\xaS&",
+"lo $6<EP|=gAEpd\\M6YDg\"*0m",
+/*
+"ActiveBorder",
+"ActiveCaption",
+"AppWorkspace",
+"Background",
+"ButtonFace",
+"ButtonHighlight",
+"ButtonShadow",
+"ButtonText",
+"CaptionText",
+"GrayText",
+"Highlight",
+"HighlightText",
+"InactiveBorder",
+"InactiveCaption",
+"InactiveCaptionText",
+"InfoBackground",
+"InfoText",
+"Menu",
+"MenuText",
+"Scrollbar",
+"ThreeDDarkShadow",
+"ThreeDFace",
+"ThreeDHighlight",
+"ThreeDLightShadow",
+"ThreeDShadow",
+"Window",
+"WindowFrame",
+"WindowText",
+*/
+"currentColor",
+"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f",
+"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f",
+"#000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f",
+"#0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f",
+"#",
+"#1",
+"#12",
+"#123",
+"#1234",
+"#12x",
+"abc",
+"123",
+"#0ab0cd0ef",
+"#0ab0cd0e",
+"#0ab0cd0",
+"#0ab0cdaef",
+"#0ab0cdae",
+"#0ab0cda"
+];
+
+var references = [
+"#113355",
+"#001350",
+"#135000",
+"#001350",
+"#013500",
+"#000135",
+"#123456",
+"#002356",
+"#124500",
+"#002356",
+"#013460",
+"#001245",
+"#f0f8ff",
+"#f0f8ff",
+"#a0ce00",
+"#a0ce00",
+"#0ace0e",
+"#a0ebe0",
+"#00cee0",
+"#faebd7",
+"#00ffff",
+"#7fffd4",
+"#f0ffff",
+"#f5f5dc",
+"#ffe4c4",
+"#000000",
+"#ffebcd",
+"#0000ff",
+"#8a2be2",
+"#a52a2a",
+"#deb887",
+"#5f9ea0",
+"#7fff00",
+"#d2691e",
+"#ff7f50",
+"#6495ed",
+"#fff8dc",
+"#dc143c",
+"#00ffff",
+"#00008b",
+"#008b8b",
+"#b8860b",
+"#a9a9a9",
+"#006400",
+"#a9a9a9",
+"#bdb76b",
+"#8b008b",
+"#556b2f",
+"#ff8c00",
+"#9932cc",
+"#8b0000",
+"#e9967a",
+"#8fbc8f",
+"#483d8b",
+"#2f4f4f",
+"#2f4f4f",
+"#00ced1",
+"#9400d3",
+"#ff1493",
+"#00bfff",
+"#696969",
+"#696969",
+"#1e90ff",
+"#b22222",
+"#fffaf0",
+"#228b22",
+"#ff00ff",
+"#dcdcdc",
+"#f8f8ff",
+"#ffd700",
+"#daa520",
+"#808080",
+"#008000",
+"#adff2f",
+"#808080",
+"#f0fff0",
+"#ff69b4",
+"#cd5c5c",
+"#4b0082",
+"#fffff0",
+"#f0e68c",
+"#e6e6fa",
+"#fff0f5",
+"#7cfc00",
+"#fffacd",
+"#add8e6",
+"#f08080",
+"#e0ffff",
+"#fafad2",
+"#d3d3d3",
+"#90ee90",
+"#d3d3d3",
+"#ffb6c1",
+"#ffa07a",
+"#20b2aa",
+"#87cefa",
+"#778899",
+"#778899",
+"#b0c4de",
+"#ffffe0",
+"#00ff00",
+"#32cd32",
+"#faf0e6",
+"#ff00ff",
+"#800000",
+"#66cdaa",
+"#0000cd",
+"#ba55d3",
+"#9370db",
+"#3cb371",
+"#7b68ee",
+"#00fa9a",
+"#48d1cc",
+"#c71585",
+"#191970",
+"#f5fffa",
+"#ffe4e1",
+"#ffe4b5",
+"#ffdead",
+"#000080",
+"#fdf5e6",
+"#808000",
+"#6b8e23",
+"#ffa500",
+"#ff4500",
+"#da70d6",
+"#eee8aa",
+"#98fb98",
+"#afeeee",
+"#db7093",
+"#ffefd5",
+"#ffdab9",
+"#cd853f",
+"#ffc0cb",
+"#dda0dd",
+"#b0e0e6",
+"#800080",
+"#ff0000",
+"#bc8f8f",
+"#4169e1",
+"#8b4513",
+"#fa8072",
+"#f4a460",
+"#2e8b57",
+"#fff5ee",
+"#a0522d",
+"#c0c0c0",
+"#87ceeb",
+"#6a5acd",
+"#708090",
+"#708090",
+"#fffafa",
+"#00ff7f",
+"#4682b4",
+"#d2b48c",
+"#008080",
+"#d8bfd8",
+"#ff6347",
+"#40e0d0",
+"#ee82ee",
+"#f5deb3",
+"#ffffff",
+"#f5f5f5",
+"#ffff00",
+"#9acd32",
+"transparent",
+"transparent",
+"transparent",
+"#00e000",
+"#00e000",
+"#0df000",
+"#0000b0",
+"#007b30",
+"#008001",
+"#004b00",
+"#002080",
+"#099600",
+"#0120e2",
+"#f00630",
+"#d00000",
+"#200000",
+"#0c00d0",
+"#07900a",
+"#db020b",
+"#7000a0",
+"#b00c02",
+"#d6d000",
+"#000000",
+"#1d00f0",
+"#000000",
+"#a00000",
+"#00b600",
+"#007028",
+"#00b0b9",
+"#000000",
+"#f00000",
+"#b00005",
+"#0ea000",
+"#72000a",
+"#ba0c00",
+"#0fe000",
+"#50000b",
+"#000c44",
+"#ae4202",
+"#00005d",
+"#0000af",
+"#5d0041",
+"#a00000",
+"#c00000",
+"#090000",
+"#0209fe",
+"#a00500",
+"#c0100e",
+"#7f0000",
+"#600000",
+"#d00d00",
+"#0004d9",
+"#c00000",
+"#0500ff",
+"#0000c3",
+"#200000",
+"#80f00d",
+"#0c7000",
+"#00c4d0",
+"#a000a0",
+"#00a000",
+"#d0070f",
+"#900600",
+"#002090",
+"#30ef00",
+"#0000e0",
+"#b000c0",
+"#80c200",
+"#0900e0",
+"#0005e0",
+"#800b00",
+"#b0a000",
+"#e00000",
+"#000690",
+"#d00000",
+"#010020",
+"#0000c0",
+"#000060",
+"#004000",
+"#000000",
+"#000da0",
+"#000000",
+"#00d000",
+"#000fa0",
+"#0c5000",
+"#000030",
+"#a0007b",
+"#00cb05",
+"#023000",
+"#9bc000",
+"#b000b0",
+"#00e055",
+"#000000",
+"#0dc0d0",
+"#20600a",
+"#70a070",
+"#f50000",
+"#0000e0",
+"#a900cb",
+"#0000d0",
+"#000a40",
+"#d00060",
+"#000ad0",
+/*
+"ActiveBorder",
+"ActiveCaption",
+"AppWorkspace",
+"Background",
+"ButtonFace",
+"ButtonHighlight",
+"ButtonShadow",
+"ButtonText",
+"CaptionText",
+"GrayText",
+"Highlight",
+"HighlightText",
+"InactiveBorder",
+"InactiveCaption",
+"InactiveCaptionText",
+"InfoBackground",
+"InfoText",
+"Menu",
+"MenuText",
+"Scrollbar",
+"ThreeDDarkShadow",
+"ThreeDFace",
+"ThreeDHighlight",
+"ThreeDLightShadow",
+"ThreeDShadow",
+"Window",
+"WindowFrame",
+"WindowText",
+*/
+"#c0e000",
+"#0000f0",
+"#000000",
+"#0000f0",
+"#000000",
+"#000000",
+"#010000",
+"#010200",
+"#112233",
+"#123400",
+"#010200",
+"#0a0b0c",
+"#010203",
+"#abcdef",
+"#abcde0",
+"#abcd00",
+"#0a0cae",
+"#0a0cae",
+"#0a0ca0"
+];
+
+var todos = {
+" #135": true,
+"#135 ": true,
+" #135 ": true,
+"#   135": true,
+" #123456": true,
+"#123456 ": true,
+" #123456 ": true,
+"#   123456": true,
+" aliceblue": true,
+"aliceblue ": true,
+"  aliceblue   ": true,
+"H3<MOq'81C#\\nUjQc  xlsF@c2R<e);T~G]^N0_*M<j!jub~k,mgZ(.>GERhwS;kmmKC?1l} qQ&zcXK?g)S OmF^=E^TlTC)/": true,
+" $4X": true,
+"UGzLF+o3)Ezs=nMxqd^\"=q.Ik}Tk2I`X)R8]Zmy/WQp,|]TdbP)5  J+#Hm6SmWtQ+h?.MQ1W#oyp\\F,'JL>rLtjiHOA": true
+};
+
+var table0 = document.getElementById("table0");
+var table1 = document.getElementById("table1");
+var cs0 = document.defaultView.getComputedStyle(table0, "");
+var cs1 = document.defaultView.getComputedStyle(table1, "");
+var result;
+var reference;
+var log = "";
+var len = tests.length;
+is(tests.length, references.length, "array length mismatch");
+for (var i = 0; i < len; ++i) {
+  table0.setAttribute("bgColor", tests[i]);
+  table1.style.backgroundColor = references[i];
+  ((tests[i] in todos) ? todo_is : is)(
+     cs0.getPropertyValue("background-color"),
+     cs1.getPropertyValue("background-color"),
+     "html color '" + tests[i] + "' should match '" + references[i] + "'");
+}
+</script>
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_html_colors_standards.html
@@ -0,0 +1,713 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=121738
+-->
+<head>
+  <meta charset="UTF-8">
+  <title>Test for Bug 121738</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=121738">Mozilla Bug 121738</a>
+<table id="table0"></table>
+<table id="table1"></table>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 121738 **/
+
+String.prototype.toAsciiLowerCase = function () {
+  var output = "";
+  for (var i = 0, len = this.length; i < len; ++i) {
+    if (this.charCodeAt(i) >= 0x41 && this.charCodeAt(i) <= 0x5A) {
+      output += String.fromCharCode(this.charCodeAt(i) + 0x20)
+    } else {
+      output += this.charAt(i);
+    }
+  }
+  return output;
+}
+
+var tests = [
+"#135",
+" #135",
+"#135 ",
+" #135 ",
+"# 135",
+"#   135",
+"#123456",
+" #123456",
+"#123456 ",
+" #123456 ",
+"# 123456",
+"#   123456",
+"aliceblue",
+"ALICEBLUE",
+"alıceblue",
+"alİceblue",
+" aliceblue",
+"aliceblue ",
+"  aliceblue   ",
+"antiquewhite",
+"aqua",
+"aquamarine",
+"azure",
+"beige",
+"bisque",
+"black",
+"blanchedalmond",
+"blue",
+"blueviolet",
+"brown",
+"burlywood",
+"cadetblue",
+"chartreuse",
+"chocolate",
+"coral",
+"cornflowerblue",
+"cornsilk",
+"crimson",
+"cyan",
+"darkblue",
+"darkcyan",
+"darkgoldenrod",
+"darkgray",
+"darkgreen",
+"darkgrey",
+"darkkhaki",
+"darkmagenta",
+"darkolivegreen",
+"darkorange",
+"darkorchid",
+"darkred",
+"darksalmon",
+"darkseagreen",
+"darkslateblue",
+"darkslategray",
+"darkslategrey",
+"darkturquoise",
+"darkviolet",
+"deeppink",
+"deepskyblue",
+"dimgray",
+"dimgrey",
+"dodgerblue",
+"firebrick",
+"floralwhite",
+"forestgreen",
+"fuchsia",
+"gainsboro",
+"ghostwhite",
+"gold",
+"goldenrod",
+"gray",
+"green",
+"greenyellow",
+"grey",
+"honeydew",
+"hotpink",
+"indianred",
+"indigo",
+"ivory",
+"khaki",
+"lavender",
+"lavenderblush",
+"lawngreen",
+"lemonchiffon",
+"lightblue",
+"lightcoral",
+"lightcyan",
+"lightgoldenrodyellow",
+"lightgray",
+"lightgreen",
+"lightgrey",
+"lightpink",
+"lightsalmon",
+"lightseagreen",
+"lightskyblue",
+"lightslategray",
+"lightslategrey",
+"lightsteelblue",
+"lightyellow",
+"lime",
+"limegreen",
+"linen",
+"magenta",
+"maroon",
+"mediumaquamarine",
+"mediumblue",
+"mediumorchid",
+"mediumpurple",
+"mediumseagreen",
+"mediumslateblue",
+"mediumspringgreen",
+"mediumturquoise",
+"mediumvioletred",
+"midnightblue",
+"mintcream",
+"mistyrose",
+"moccasin",
+"navajowhite",
+"navy",
+"oldlace",
+"olive",
+"olivedrab",
+"orange",
+"orangered",
+"orchid",
+"palegoldenrod",
+"palegreen",
+"paleturquoise",
+"palevioletred",
+"papayawhip",
+"peachpuff",
+"peru",
+"pink",
+"plum",
+"powderblue",
+"purple",
+"red",
+"rosybrown",
+"royalblue",
+"saddlebrown",
+"salmon",
+"sandybrown",
+"seagreen",
+"seashell",
+"sienna",
+"silver",
+"skyblue",
+"slateblue",
+"slategray",
+"slategrey",
+"snow",
+"springgreen",
+"steelblue",
+"tan",
+"teal",
+"thistle",
+"tomato",
+"turquoise",
+"violet",
+"wheat",
+"white",
+"whitesmoke",
+"yellow",
+"yellowgreen",
+"transparent",
+"TRANSPARENT",
+"",
+"inherit",
+"INHERIT",
+"KQ@m?-ldxNK{zH+(FL_owz>YNH^]",
+"aj9c)r+J&3)0E,- Lzv6K6nT@6?I}BY^\\g",
+"Cf}qJN|3D>m:^[7B*fhu>lC[B3\"T_-F",
+"h<s1pMd-8H[,\\caWH1oW3%M",
+"z{y]VZj)%)ZV<OTbO9\\Nbc|YL}4BI<DlUBk$EV`EbN}x/@SDN0(",
+"PSX2Ol8@",
+"d+gYXKUM'&D'S]o<9T\\:hj_i!|l!)e6R4Bo)-(965rlK\"K01C68pgkJ] fx?kjT.O&sY4",
+"[4\"tk)a/v17?0W!F`AyI[='2~;:DF6I>_<O$ he213u",
+"F|r9T&N69MWq3Jrj6",
+"dYR7}n&:Rq[J",
+"M;Z]r@(R([6aT`<sN?uO'2Kb~3U\\\\tQUDxLN1f/D(,Q0w|K;,t`,tQ~[W/c!uQg)d|:D\\U33!DK&d*C`Zc'U#",
+"kV)DKUb~h{SQCM;T*g2!Rj?>Sl=jY;3W9M{Fliu!=>tDY]5",
+"y>X\\kKN|~=J+7Pqp|%9R!nZ,@>mUW9<o;|02LV<fxihsBSKVaTdcae",
+"Q>jc|/:#qwzHL`lL%e~DbhQ+d^tpf9sx%o)jC1Nm}`G;rT2jo+M$=$?BC'|O^]hW^BBo_J->bWG1",
+"OIxA\\5HB7g3Rv;PD)z?jGe?<x`4~9&D9dSDP=ilUauI'qb",
+"aND[Al/^#;n'|V\"Vl$bh5\\G#{%y4#\\W0:ZgXe73ZuXrWcL4gr|B7,ijZZi{p)M+R9{C/&249G",
+"7xK-d6Tx]BU|T,DY.qCwusmV%Ksset",
+"I=UwM''S",
+"w|_;Qw(R:>Clf[#3JFr_+?'1D&}WaY_xaRyTpwio>C;Pjf/kIW{]KK:R&ARiP=_g_UqRVvFKG(OQo6y'wF]Fc",
+"G:",
+"+XZ%s7L3FmGFn]Y!J;.vpAUoGU,&WY8eQeGWW?Jq7ANeM}[?gsV) H\\@{8z_t$oS(_jSq]|9?W*sG%' (d%",
+"*P\"?'?NHA \\!{.S=+LD8Ltr^'=,$4uQ=tVL/T_b6m!PJ8*s*v`;6kp(+8i.}T!9p6{",
+"_@(w<\\DjMk c8/\"/ifJNT_2R>V'}{&72C2+7otvd,$M@Yqc)L=O.muEp28m&AY",
+"J!M#$z|n:+:6@7n*v)UCbkVp0;\"1#}o:i4B9oh=%'I",
+"0",
+"Krq?xAul2cRe&`*Fg2)bV/r>oJ`Z(ae,z%+`E@VkWH&`-jMZ<UW~jxDek;^j2\\Uq;C,Ss",
+"#b\\l~=y5H=#Jy(6FwH5]jU;6D",
+"YO|tw;`E_'G<d~juVPCla%K]q x\"oA-aW|Y@P$_$",
+"}rI\\5x724b29MEauSSX&!AT[J1ce?,rtLAA8X",
+"hlo8jd$D-dI=I#Be:BATkZPR~%Vfe0g_Xw^+wwhHQhC1;sn+P<b&J:~HfxVBX}9b/#HHPS",
+"+#[?UFGUVFn0Zn7yE#TEo{FV\\{6*+s+a=fR",
+"lhv.f!ENs~)?5)z:1^i@BQ|ol}9Cnkw&yV.PPx |y]@,?IL]0L_# b1'wl-]",
+"&DhZ!g%v.sF}4NoP~4<vKpaM0[12!2K!ziYC3`505I*D*J6k\\skbXJ}44J#4y2",
+"oK][N&iIV\"AEs3rIT-::L3&J^Sn42_J2yL= 2xI4o!b\"#2JiAt=",
+"^c;C^{0wD%|y~Z1X'z\\o^gI8L=@2^p3g/L6G?]Nuif;Zf15dF`IPt8",
+"62t-!*`U\\l%BFxi5B~[^~G!}h]DtXrd}y}af3",
+"?N5d9ydHPi?IhwU=41'",
+"GSZeLtA3YahI@oLy/6vT_[B`[PRZ1^.(n8`,8TyqVoCzMd!=9 e",
+"Yck5`_#NgS",
+"K9?z&o",
+"Isl2>%RB8T+,9?B{~A2{fEb[%",
+"&fV(`<ha/(T7J&X\\{YHt+5 =>%SaJ&W0_j]]\"",
+">!sQ/IYU\"Ikc\\ei;HlCcVJ\":G2/m]h1,GvOmxFOOvTUHjHu:LWE\"QU=) ",
+"7Fyx#>\"(\"N",
+"MO6\"Hd2H]r8BJ}z)%J18b<VZ5lrhI",
+"BGQ|tqdwj4};#x@?%ka[`DwgFWg*J+q/}]-\\\\-y#T",
+"zZ=JrTPxh}.(%frt58Cy=C4(*,4]:Gnz5(~iv4@u4re~6yp:zbU0(o.S+qd9eB]A5",
+"n]V3}^{9O<0cO\"rtglDO4Wc)_7Nu_JnK2EBbzRMV3b.Mj\"$9#,+-T\"N=7iPdD F<9_YWw3ZN*V;??*8VN8z?^MXi",
+"fGRSl*i>^*uy|c;5B}tKXu>5hZX:>CB{oWIrxE8@B/f{:u9]:bLO0/ZWeHoNfCc|kSh{/fXs9Y:UKaJ95vFFtB2Y",
+".&-4UOcxR\"Tbgc--@& hoUavCcQW^^fT}:I(d%o}J2t*BRA1{YGXB9>AYu^Bv#rEu`pN65_-r.IQD.?Cc/B({YtK[2KMmVOC3*2J",
+"H3<MOq'81C#\\nUjQc  xlsF@c2R<e);T~G]^N0_*M<j!jub~k,mgZ(.>GERhwS;kmmKC?1l} qQ&zcXK?g)S OmF^=E^TlTC)/",
+"8\\5tFz:sod",
+"ILUc5c!'K.7.P&=S,pSYB{",
+"%\\(6.jC\"C4\\2{TYdx,Ln^",
+"tL3HnWq q!'k!#R@2bkvIAI]hk)64-i?uk]oK(nQiKg$`m6tx|#l>m1bEK^&.X[o'b\"\\',A16n>9ZAPI9>",
+"{#Mn0,S~a\"!gw",
+"dv+6'7Dd)fz",
+"9o1*Q:{6#3f uHx\"_",
+".43_zr}X+BtruMV!H!xw 8!9I_}zlBT3W52)rh,9ngeu0o[V_s*z'8x9*yjF!",
+"y3Nm`>P:seF'V'?+<={oU5QQ",
+".#Os_jv,\"@-zsY8j'POOYnY?0ONn?i#d4tqp?~.OF#VC.=<t<+feuf{#@O7lXC@+#t_uKGue%Dk9z",
+"0Ep=zwydU-V<)9<9\\`[4,d^B&Gbo#'HTSEC;qU&1| ocNd69#{nbmYJMlj6Mfs3`w&pc(poie *ZOJIp7%}cVnfml",
+"746}e(rye4lT7#B.Or8j1->Xs@o8f0}/e>uvvkNS[3UC2F]#[>^f74jxoo&9{^ED#,CV\"k'0|xI",
+".D1{.:9gHW}]36RlUQ?!-\"0dn:+(/e@b)|'B",
+"!Nh9xY2y?5ku5f}%]JWw~OfeYdcgI#It` T)3VzYl5gChve[I'rEqyJ \"@(z.Y%fEJ:9k(",
+"J^$^L8:qI=yrerd0kxJBEwby6[>9[) NpqN%)h",
+"l&\\K{s9]aL(,dX?B\"1g1*@9BY~=UO+AWvVRI;ar4p8Tsy~Qk-=x(yp38:j|g'5H~e4",
+"(]Pe,1fTS_P%[xY96#,rwQz=P?z",
+")PC#?b'&|maJBt.6Izz%vV5e!9Sy|G!*Q",
+"pzAG^@/J&)Dc}GP*xO]ezW:*PV|Dt^fF<8GgF_1i=A\"@>nt?yOa|zS<8`/;uY~^ozjvX!K#%us!>2IYITh]Zy<^dq?&\"nqV]ZdZ",
+"T<xz*/H&}36<(4E^/Z1m<#_G0R:=qX?1`*6Y&r'SIO]9OR;m5-Zq?PU^jvLKPLW2wPf",
+")CLhmCI%TwB+t:h.@Vp-#({d0W/R_(^f34LC=V)A",
+"yCT_hl%fUL<T&e;ePsT.pJG@|jO,[pN]]Q<Yu=Lp6X6&$Ka#",
+" $4X",
+"rp",
+"t^(*U<Qdi$!vyg5D\"yQZd<K6<Qptsvzi~D}.Uf?P$E>}t8VP^;3Tamv2Z$1<",
+",",
+"EGCXZ_{eqIwfG-o7o\\\"!ZWTPLd,U-k$Cz]%:vNWdo}vDh!ONtM>mMP{/Cg+2<.J\"a*n#Rtnha",
+"LQ3sIr7Q_ wSD7Zzv$-vxr|3P`pas0#Ze/---{PSwJ3{!a*[k'nFgC\"W+@4URi?qJk&Tt@`abNms40#A^XcAt}",
+"^i356'hX\"hKaZGfTZ|C@#}b3LGz1\">qcH{L8{Fs?O5%:EqQWuro_lc=]gWLVR\\~!J\"[>,H",
+"i{*q<O{Dt^n|FY3,FG>WIRqPH.os$9^P=|yA9?P;MOw;VBwZ^>K=\"%J9SBlv%0+o5k73rW!`l_",
+"-PCM&!G~o#Za^s&)qJELr\\P^\\={_xTFp:%@JF.PeRX\\7b8K",
+"V_sFicB+wx5",
+"\"X^\\d}b9.W.2\"O!yAL21\"Ny5:)=Q3*D|TAzzr^0Yflzjdc!p*.yW,B",
+"kZ`wCP>9Bq5S!r!Vi|Uy/C&H[kz/f^{(Z[OGw'S0\"",
+"Jn%1^rUnNB|%=q%^v*bN|I40}#Htn{G!#~CNAN0KvZcB>Ita(,n",
+"-PlhE[^J55Ui",
+"z`h`uQJ{J",
+"eV\\q5Q4o@Y*,IRMcnpqj5>Id\\yBe?pKH3uF&c<c}:E9[uaH$ 8dXCmI+!C'q@PkE<NVRq~GRW<tfyt/i@%dwI&rL",
+"UGzLF+o3)Ezs=nMxqd^\"=q.Ik}Tk2I`X)R8]Zmy/WQp,|]TdbP)5  J+#Hm6SmWtQ+h?.MQ1W#oyp\\F,'JL>rLtjiHOA",
+"&joOSw7XZVvSt4ZCT*:aq:3ns!v|r);~7gN8'_D",
+"Y<q|Mhn5Nrcb+dR=10pQF5]r@/*7P`79w/htSm2,C~1&sUW{N@v:t9d;HPG&xrI\"YD;V9Y$'g,W'J=GV3,YK",
+"Gx&#{;]l/?[{SyX`kTeo",
+"30PU7@<'58.hRWsJTa9L.hVQ8}7=$}ih4|$Y*9z3[aooT!]}+>b{1JH^.jjEU{,dAXSCbtEh6",
+"%2~x8=A!RW@8N/`hQz`)gl}1DOU9{>Ie'L> 4e]m;kt =isEQ(\\TeI7hWgK-K! p^K'\":3;dxTLO",
+"\\ ):{Woay[4",
+"\\{Ih&}*8^x6@`V@DZB`rSuhYm4i@TW^t9Hx[^`IVumjXc1vA\"~wt8^Jf:US6Z\\xaS&",
+"lo $6<EP|=gAEpd\\M6YDg\"*0m",
+/*
+"ActiveBorder",
+"ActiveCaption",
+"AppWorkspace",
+"Background",
+"ButtonFace",
+"ButtonHighlight",
+"ButtonShadow",
+"ButtonText",
+"CaptionText",
+"GrayText",
+"Highlight",
+"HighlightText",
+"InactiveBorder",
+"InactiveCaption",
+"InactiveCaptionText",
+"InfoBackground",
+"InfoText",
+"Menu",
+"MenuText",
+"Scrollbar",
+"ThreeDDarkShadow",
+"ThreeDFace",
+"ThreeDHighlight",
+"ThreeDLightShadow",
+"ThreeDShadow",
+"Window",
+"WindowFrame",
+"WindowText",
+*/
+"currentColor",
+"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f",
+"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f",
+"#000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f",
+"#0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f",
+"#",
+"#1",
+"#12",
+"#123",
+"#1234",
+"#12x",
+"abc",
+"123",
+"#0ab0cd0ef",
+"#0ab0cd0e",
+"#0ab0cd0",
+"#0ab0cdaef",
+"#0ab0cdae",
+"#0ab0cda"
+];
+
+var references = [
+"#113355",
+"#001350",
+"#135000",
+"#001350",
+"#013500",
+"#000135",
+"#123456",
+"#002356",
+"#124500",
+"#002356",
+"#013460",
+"#001245",
+"#f0f8ff",
+"#f0f8ff",
+"#a0ce00",
+"#a0ce00",
+"#0ace0e",
+"#a0ebe0",
+"#00cee0",
+"#faebd7",
+"#00ffff",
+"#7fffd4",
+"#f0ffff",
+"#f5f5dc",
+"#ffe4c4",
+"#000000",
+"#ffebcd",
+"#0000ff",
+"#8a2be2",
+"#a52a2a",
+"#deb887",
+"#5f9ea0",
+"#7fff00",
+"#d2691e",
+"#ff7f50",
+"#6495ed",
+"#fff8dc",
+"#dc143c",
+"#00ffff",
+"#00008b",
+"#008b8b",
+"#b8860b",
+"#a9a9a9",
+"#006400",
+"#a9a9a9",
+"#bdb76b",
+"#8b008b",
+"#556b2f",
+"#ff8c00",
+"#9932cc",
+"#8b0000",
+"#e9967a",
+"#8fbc8f",
+"#483d8b",
+"#2f4f4f",
+"#2f4f4f",
+"#00ced1",
+"#9400d3",
+"#ff1493",
+"#00bfff",
+"#696969",
+"#696969",
+"#1e90ff",
+"#b22222",
+"#fffaf0",
+"#228b22",
+"#ff00ff",
+"#dcdcdc",
+"#f8f8ff",
+"#ffd700",
+"#daa520",
+"#808080",
+"#008000",
+"#adff2f",
+"#808080",
+"#f0fff0",
+"#ff69b4",
+"#cd5c5c",
+"#4b0082",
+"#fffff0",
+"#f0e68c",
+"#e6e6fa",
+"#fff0f5",
+"#7cfc00",
+"#fffacd",
+"#add8e6",
+"#f08080",
+"#e0ffff",
+"#fafad2",
+"#d3d3d3",
+"#90ee90",
+"#d3d3d3",
+"#ffb6c1",
+"#ffa07a",
+"#20b2aa",
+"#87cefa",
+"#778899",
+"#778899",
+"#b0c4de",
+"#ffffe0",
+"#00ff00",
+"#32cd32",
+"#faf0e6",
+"#ff00ff",
+"#800000",
+"#66cdaa",
+"#0000cd",
+"#ba55d3",
+"#9370db",
+"#3cb371",
+"#7b68ee",
+"#00fa9a",
+"#48d1cc",
+"#c71585",
+"#191970",
+"#f5fffa",
+"#ffe4e1",
+"#ffe4b5",
+"#ffdead",
+"#000080",
+"#fdf5e6",
+"#808000",
+"#6b8e23",
+"#ffa500",
+"#ff4500",
+"#da70d6",
+"#eee8aa",
+"#98fb98",
+"#afeeee",
+"#db7093",
+"#ffefd5",
+"#ffdab9",
+"#cd853f",
+"#ffc0cb",
+"#dda0dd",
+"#b0e0e6",
+"#800080",
+"#ff0000",
+"#bc8f8f",
+"#4169e1",
+"#8b4513",
+"#fa8072",
+"#f4a460",
+"#2e8b57",
+"#fff5ee",
+"#a0522d",
+"#c0c0c0",
+"#87ceeb",
+"#6a5acd",
+"#708090",
+"#708090",
+"#fffafa",
+"#00ff7f",
+"#4682b4",
+"#d2b48c",
+"#008080",
+"#d8bfd8",
+"#ff6347",
+"#40e0d0",
+"#ee82ee",
+"#f5deb3",
+"#ffffff",
+"#f5f5f5",
+"#ffff00",
+"#9acd32",
+"transparent",
+"transparent",
+"transparent",
+"#00e000",
+"#00e000",
+"#0df000",
+"#0000b0",
+"#007b30",
+"#008001",
+"#004b00",
+"#002080",
+"#099600",
+"#0120e2",
+"#f00630",
+"#d00000",
+"#200000",
+"#0c00d0",
+"#07900a",
+"#db020b",
+"#7000a0",
+"#b00c02",
+"#d6d000",
+"#000000",
+"#1d00f0",
+"#000000",
+"#a00000",
+"#00b600",
+"#007028",
+"#00b0b9",
+"#000000",
+"#f00000",
+"#b00005",
+"#0ea000",
+"#72000a",
+"#ba0c00",
+"#0fe000",
+"#50000b",
+"#000c44",
+"#ae4202",
+"#00005d",
+"#0000af",
+"#5d0041",
+"#a00000",
+"#c00000",
+"#090000",
+"#0209fe",
+"#a00500",
+"#c0100e",
+"#7f0000",
+"#600000",
+"#d00d00",
+"#0004d9",
+"#c00000",
+"#0500ff",
+"#0000c3",
+"#200000",
+"#80f00d",
+"#0c7000",
+"#00c4d0",
+"#a000a0",
+"#00a000",
+"#d0070f",
+"#900600",
+"#002090",
+"#30ef00",
+"#0000e0",
+"#b000c0",
+"#80c200",
+"#0900e0",
+"#0005e0",
+"#800b00",
+"#b0a000",
+"#e00000",
+"#000690",
+"#d00000",
+"#010020",
+"#0000c0",
+"#000060",
+"#004000",
+"#000000",
+"#000da0",
+"#000000",
+"#00d000",
+"#000fa0",
+"#0c5000",
+"#000030",
+"#a0007b",
+"#00cb05",
+"#023000",
+"#9bc000",
+"#b000b0",
+"#00e055",
+"#000000",
+"#0dc0d0",
+"#20600a",
+"#70a070",
+"#f50000",
+"#0000e0",
+"#a900cb",
+"#0000d0",
+"#000a40",
+"#d00060",
+"#000ad0",
+/*
+"ActiveBorder",
+"ActiveCaption",
+"AppWorkspace",
+"Background",
+"ButtonFace",
+"ButtonHighlight",
+"ButtonShadow",
+"ButtonText",
+"CaptionText",
+"GrayText",
+"Highlight",
+"HighlightText",
+"InactiveBorder",
+"InactiveCaption",
+"InactiveCaptionText",
+"InfoBackground",
+"InfoText",
+"Menu",
+"MenuText",
+"Scrollbar",
+"ThreeDDarkShadow",
+"ThreeDFace",
+"ThreeDHighlight",
+"ThreeDLightShadow",
+"ThreeDShadow",
+"Window",
+"WindowFrame",
+"WindowText",
+*/
+"#c0e000",
+"#0000f0",
+"#000000",
+"#0000f0",
+"#000000",
+"#000000",
+"#010000",
+"#010200",
+"#112233",
+"#123400",
+"#010200",
+"#0a0b0c",
+"#010203",
+"#abcdef",
+"#abcde0",
+"#abcd00",
+"#0a0cae",
+"#0a0cae",
+"#0a0ca0"
+];
+
+var todos = {
+" #135": true,
+"#135 ": true,
+" #135 ": true,
+"#   135": true,
+" #123456": true,
+"#123456 ": true,
+" #123456 ": true,
+"#   123456": true,
+" aliceblue": true,
+"aliceblue ": true,
+"  aliceblue   ": true,
+"H3<MOq'81C#\\nUjQc  xlsF@c2R<e);T~G]^N0_*M<j!jub~k,mgZ(.>GERhwS;kmmKC?1l} qQ&zcXK?g)S OmF^=E^TlTC)/": true,
+" $4X": true,
+"UGzLF+o3)Ezs=nMxqd^\"=q.Ik}Tk2I`X)R8]Zmy/WQp,|]TdbP)5  J+#Hm6SmWtQ+h?.MQ1W#oyp\\F,'JL>rLtjiHOA": true
+};
+
+var table0 = document.getElementById("table0");
+var table1 = document.getElementById("table1");
+var cs0 = document.defaultView.getComputedStyle(table0, "");
+var cs1 = document.defaultView.getComputedStyle(table1, "");
+var result;
+var reference;
+var log = "";
+var len = tests.length;
+is(tests.length, references.length, "array length mismatch");
+for (var i = 0; i < len; ++i) {
+  table0.setAttribute("bgColor", tests[i]);
+  table1.style.backgroundColor = references[i];
+  ((tests[i] in todos) ? todo_is : is)(
+     cs0.getPropertyValue("background-color"),
+     cs1.getPropertyValue("background-color"),
+     "html color '" + tests[i] + "' should match '" + references[i] + "'");
+}
+</script>
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/canvas/src/WebGLContextNotSupported.cpp
+++ b/content/canvas/src/WebGLContextNotSupported.cpp
@@ -45,8 +45,9 @@ DUMMY(NS_NewCanvasRenderingContextWebGL,
 
 DOMCI_DATA(CanvasRenderingContextWebGL, void)
 DOMCI_DATA(WebGLBuffer, void)
 DOMCI_DATA(WebGLTexture, void)
 DOMCI_DATA(WebGLProgram, void)
 DOMCI_DATA(WebGLShader, void)
 DOMCI_DATA(WebGLFramebuffer, void)
 DOMCI_DATA(WebGLRenderbuffer, void)
+DOMCI_DATA(WebGLUniformLocation, void)
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -908,30 +908,34 @@ nsGenericHTMLElement::UpdateEditableStat
   // XXX Should we do this only when in a document?
   ContentEditableTristate value = GetContentEditableValue();
   if (value != eInherit) {
     SetEditableFlag(!!value);
 
     return;
   }
 
-  nsGenericElement::UpdateEditableState();
+  nsStyledElement::UpdateEditableState();
 }
 
 nsresult
 nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                  nsIContent* aBindingParent,
                                  PRBool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElementBase::BindToTree(aDocument, aParent,
                                                      aBindingParent,
                                                      aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
+    if (HasFlag(NODE_HAS_NAME)) {
+      aDocument->
+        AddToNameTable(this, GetParsedAttr(nsGkAtoms::name)->GetAtomValue());
+    }
     if (HasFlag(NODE_IS_EDITABLE) && GetContentEditableValue() == eTrue) {
       nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(aDocument);
       if (htmlDocument) {
         htmlDocument->ChangeContentEditableCount(this, +1);
       }
     }
   }
 
@@ -943,17 +947,17 @@ nsGenericHTMLElement::UnbindFromTree(PRB
 {
   if (GetContentEditableValue() == eTrue) {
     nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(GetCurrentDoc());
     if (htmlDocument) {
       htmlDocument->ChangeContentEditableCount(this, -1);
     }
   }
 
-  nsGenericElement::UnbindFromTree(aDeep, aNullParent);
+  nsStyledElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 nsHTMLFormElement*
 nsGenericHTMLElement::FindForm(nsHTMLFormElement* aCurrentForm)
 {
   // Make sure we don't end up finding a form that's anonymous from
   // our point of view.
   nsIContent* bindingParent = GetBindingParent();
@@ -1156,18 +1160,18 @@ nsGenericHTMLElement::SetAttr(PRInt32 aN
   PRBool contentEditable = aNameSpaceID == kNameSpaceID_None &&
                            aName == nsGkAtoms::contenteditable;
   PRInt32 change;
   if (contentEditable) {
     change = GetContentEditableValue() == eTrue ? -1 : 0;
     SetFlags(NODE_MAY_HAVE_CONTENT_EDITABLE_ATTR);
   }
 
-  nsresult rv = nsGenericElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
-                                          aNotify);
+  nsresult rv = nsStyledElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
+                                         aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (contentEditable) {
     if (aValue.IsEmpty() || aValue.LowerCaseEqualsLiteral("true")) {
       change += 1;
     }
 
     ChangeEditableState(change);
@@ -1180,17 +1184,22 @@ nsresult
 nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                                 PRBool aNotify)
 {
   PRBool contentEditable = PR_FALSE;
   PRInt32 contentEditableChange;
 
   // Check for event handlers
   if (aNameSpaceID == kNameSpaceID_None) {
-    if (aAttribute == nsGkAtoms::contenteditable) {
+    if (aAttribute == nsGkAtoms::name) {
+      // Have to do this before clearing flag. See RemoveFromNameTable
+      RemoveFromNameTable();
+      UnsetFlags(NODE_HAS_NAME);
+    }
+    else if (aAttribute == nsGkAtoms::contenteditable) {
       contentEditable = PR_TRUE;
       contentEditableChange = GetContentEditableValue() == eTrue ? -1 : 0;
     }
     else if (nsContentUtils::IsEventAttributeName(aAttribute,
                                                   EventNameType_HTML)) {
       nsIEventListenerManager* manager = GetListenerManager(PR_FALSE);
       if (manager) {
         manager->RemoveScriptEventListener(aAttribute);
@@ -1217,36 +1226,57 @@ nsGenericHTMLElement::GetBaseTarget(nsAS
     ownerDoc->GetBaseTarget(aBaseTarget);
   } else {
     aBaseTarget.Truncate();
   }
 }
 
 //----------------------------------------------------------------------
 
+static PRBool
+CanHaveName(nsIAtom* aTag)
+{
+  return aTag == nsGkAtoms::img ||
+         aTag == nsGkAtoms::form ||
+         aTag == nsGkAtoms::applet ||
+         aTag == nsGkAtoms::embed ||
+         aTag == nsGkAtoms::object;
+}
 
 PRBool
 nsGenericHTMLElement::ParseAttribute(PRInt32 aNamespaceID,
                                      nsIAtom* aAttribute,
                                      const nsAString& aValue,
                                      nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::dir) {
       return aResult.ParseEnumValue(aValue, kDirTable, PR_FALSE);
     }
   
     if (aAttribute == nsGkAtoms::tabindex) {
       return aResult.ParseIntWithBounds(aValue, -32768, 32767);
     }
 
-    if (aAttribute == nsGkAtoms::name && !aValue.IsEmpty()) {
+    if (aAttribute == nsGkAtoms::name) {
       // Store name as an atom.  name="" means that the element has no name,
       // not that it has an emptystring as the name.
+      RemoveFromNameTable();
+      if (aValue.IsEmpty()) {
+        UnsetFlags(NODE_HAS_NAME);
+        return PR_FALSE;
+      }
+
       aResult.ParseAtom(aValue);
+
+      if (CanHaveName(Tag())) {
+        SetFlags(NODE_HAS_NAME);
+        AddToNameTable(aResult.GetAtomValue());
+      }
+      
       return PR_TRUE;
     }
 
     if (aAttribute == nsGkAtoms::contenteditable) {
       aResult.ParseAtom(aValue);
       return PR_TRUE;
     }
   }
@@ -2496,16 +2526,18 @@ nsGenericHTMLFormElement::BindToTree(nsI
   return NS_OK;
 }
 
 void
 nsGenericHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
   // Save state before doing anything
   SaveState();
+  
+  RemoveFromNameTable();
 
   if (mForm) {
     // Might need to unset mForm
     if (aNullParent) {
       // No more parent means no more form
       ClearForm(PR_TRUE, PR_TRUE);
     } else {
       // Recheck whether we should still have an mForm.
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -494,22 +494,57 @@ public:
   /**
    * Locate an nsIEditor rooted at this content node, if there is one.
    */
   NS_HIDDEN_(nsresult) GetEditor(nsIEditor** aEditor);
   NS_HIDDEN_(nsresult) GetEditorInternal(nsIEditor** aEditor);
 
 protected:
   /**
+   * Add/remove this element to the documents name cache
+   */
+  void AddToNameTable(nsIAtom* aName) {
+    NS_ASSERTION(HasFlag(NODE_HAS_NAME), "Node lacking NODE_HAS_NAME flag");
+    nsIDocument* doc = GetCurrentDoc();
+    if (doc && !IsInAnonymousSubtree()) {
+      doc->AddToNameTable(this, aName);
+    }
+  }
+  void RemoveFromNameTable() {
+    if (HasFlag(NODE_HAS_NAME)) {
+      nsIDocument* doc = GetCurrentDoc();
+      if (doc) {
+        doc->RemoveFromNameTable(this, GetParsedAttr(nsGkAtoms::name)->
+                                         GetAtomValue());
+      }
+    }
+  }
+
+  /**
    * Register or unregister an access key to this element based on the
    * accesskey attribute.
-   * @param aDoReg true to register, false to unregister
    */
+  void RegAccessKey()
+  {
+    if (HasFlag(NODE_HAS_ACCESSKEY)) {
+      RegUnRegAccessKey(PR_TRUE);
+    }
+  }
+
+  void UnregAccessKey()
+  {
+    if (HasFlag(NODE_HAS_ACCESSKEY)) {
+      RegUnRegAccessKey(PR_FALSE);
+    }
+  }
+
+private:
   void RegUnRegAccessKey(PRBool aDoReg);
 
+protected:
   /**
    * Determine whether an attribute is an event (onclick, etc.)
    * @param aName the attribute
    * @return whether the name is an event handler name
    */
   PRBool IsEventName(nsIAtom* aName);
 
   virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
--- a/content/html/content/src/nsHTMLAnchorElement.cpp
+++ b/content/html/content/src/nsHTMLAnchorElement.cpp
@@ -203,17 +203,17 @@ nsHTMLAnchorElement::BindToTree(nsIDocum
   Link::ResetLinkState(false);
 
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
-    RegUnRegAccessKey(PR_TRUE);
+    RegAccessKey();
   }
 
   // Prefetch links
   if (aDocument && nsHTMLDNSPrefetch::IsAllowed(GetOwnerDoc())) {
     nsHTMLDNSPrefetch::PrefetchLow(this);
   }
   return rv;
 }
@@ -221,17 +221,17 @@ nsHTMLAnchorElement::BindToTree(nsIDocum
 void
 nsHTMLAnchorElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
   // If this link is ever reinserted into a document, it might
   // be under a different xml:base, so forget the cached state now.
   Link::ResetLinkState(false);
 
   if (IsInDoc()) {
-    RegUnRegAccessKey(PR_FALSE);
+    UnregAccessKey();
   }
 
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 NS_IMETHODIMP
 nsHTMLAnchorElement::Blur()
 {
@@ -429,17 +429,17 @@ nsHTMLAnchorElement::GetHrefURI() const
 }
 
 nsresult
 nsHTMLAnchorElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                              nsIAtom* aPrefix, const nsAString& aValue,
                              PRBool aNotify)
 {
   if (aName == nsGkAtoms::accesskey && kNameSpaceID_None == aNameSpaceID) {
-    RegUnRegAccessKey(PR_FALSE);
+    UnregAccessKey();
   }
 
   bool reset = false;
   if (aName == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
     nsAutoString val;
     GetHref(val);
     if (!val.Equals(aValue)) {
       reset = true;
@@ -455,29 +455,32 @@ nsHTMLAnchorElement::SetAttr(PRInt32 aNa
   // that content states have changed will call IntrinsicState, which will try
   // to get updated information about the visitedness from Link.
   if (reset) {
     Link::ResetLinkState(!!aNotify);
   }
 
   if (aName == nsGkAtoms::accesskey && kNameSpaceID_None == aNameSpaceID &&
       !aValue.IsEmpty()) {
-    RegUnRegAccessKey(PR_TRUE);
+    SetFlags(NODE_HAS_ACCESSKEY);
+    RegAccessKey();
   }
 
   return rv;
 }
 
 nsresult
 nsHTMLAnchorElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                                PRBool aNotify)
 {
   if (aAttribute == nsGkAtoms::accesskey &&
       kNameSpaceID_None == aNameSpaceID) {
-    RegUnRegAccessKey(PR_FALSE);
+    // Have to unregister before clearing flag. See UnregAccessKey
+    UnregAccessKey();
+    UnsetFlags(NODE_HAS_ACCESSKEY);
   }
 
   nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute,
                                                 aNotify);
 
   // The ordering of the parent class's UnsetAttr call and Link::ResetLinkState
   // is important here!  The attribute is not unset until UnsetAttr returns, and
   // we will need the updated attribute value because notifying the document
--- a/content/html/content/src/nsHTMLAreaElement.cpp
+++ b/content/html/content/src/nsHTMLAreaElement.cpp
@@ -209,72 +209,75 @@ nsHTMLAreaElement::BindToTree(nsIDocumen
   Link::ResetLinkState(false);
 
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
-    RegUnRegAccessKey(PR_TRUE);
+    RegAccessKey();
   }
 
   return rv;
 }
 
 void
 nsHTMLAreaElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
   // If this link is ever reinserted into a document, it might
   // be under a different xml:base, so forget the cached state now.
   Link::ResetLinkState(false);
 
   if (IsInDoc()) {
-    RegUnRegAccessKey(PR_FALSE);
+    UnregAccessKey();
   }
 
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 nsresult
 nsHTMLAreaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            PRBool aNotify)
 {
   if (aName == nsGkAtoms::accesskey && aNameSpaceID == kNameSpaceID_None) {
-    RegUnRegAccessKey(PR_FALSE);
+    UnregAccessKey();
   }
 
   nsresult rv =
     nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, aNotify);
 
   // The ordering of the parent class's SetAttr call and Link::ResetLinkState
   // is important here!  The attribute is not set until SetAttr returns, and
   // we will need the updated attribute value because notifying the document
   // that content states have changed will call IntrinsicState, which will try
   // to get updated information about the visitedness from Link.
   if (aName == nsGkAtoms::href && aNameSpaceID == kNameSpaceID_None) {
     Link::ResetLinkState(!!aNotify);
   }
 
   if (aName == nsGkAtoms::accesskey && aNameSpaceID == kNameSpaceID_None &&
       !aValue.IsEmpty()) {
-    RegUnRegAccessKey(PR_TRUE);
+    SetFlags(NODE_HAS_ACCESSKEY);
+    RegAccessKey();
   }
 
   return rv;
 }
 
 nsresult
 nsHTMLAreaElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                              PRBool aNotify)
 {
   if (aAttribute == nsGkAtoms::accesskey &&
       aNameSpaceID == kNameSpaceID_None) {
-    RegUnRegAccessKey(PR_FALSE);
+    // Have to unregister before clearing flag. See UnregAccessKey
+    UnregAccessKey();
+    UnsetFlags(NODE_HAS_ACCESSKEY);
   }
 
   nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute,
                                                 aNotify);
 
   // The ordering of the parent class's UnsetAttr call and Link::ResetLinkState
   // is important here!  The attribute is not unset until UnsetAttr returns, and
   // we will need the updated attribute value because notifying the document
--- a/content/html/content/src/nsHTMLLabelElement.cpp
+++ b/content/html/content/src/nsHTMLLabelElement.cpp
@@ -203,27 +203,27 @@ nsHTMLLabelElement::BindToTree(nsIDocume
                                PRBool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
                                                      aBindingParent,
                                                      aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
-    RegUnRegAccessKey(PR_TRUE);
+    RegAccessKey();
   }
 
   return rv;
 }
 
 void
 nsHTMLLabelElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
   if (IsInDoc()) {
-    RegUnRegAccessKey(PR_FALSE);
+    UnregAccessKey();
   }
 
   nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 static PRBool
 EventTargetIn(nsEvent *aEvent, nsIContent *aChild, nsIContent *aStop)
 {
@@ -357,38 +357,41 @@ nsHTMLLabelElement::SubmitNamesValues(ns
   return NS_OK;
 }
 
 nsresult
 nsHTMLLabelElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
                             const nsAString& aValue, PRBool aNotify)
 {
   if (aName == nsGkAtoms::accesskey && kNameSpaceID_None == aNameSpaceID) {
-    RegUnRegAccessKey(PR_FALSE);
+    UnregAccessKey();
   }
 
   nsresult rv =
       nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
                                     aNotify);
 
   if (aName == nsGkAtoms::accesskey && kNameSpaceID_None == aNameSpaceID &&
       !aValue.IsEmpty()) {
-    RegUnRegAccessKey(PR_TRUE);
+    SetFlags(NODE_HAS_ACCESSKEY);
+    RegAccessKey();
   }
 
   return rv;
 }
 
 nsresult
 nsHTMLLabelElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                               PRBool aNotify)
 {
   if (aAttribute == nsGkAtoms::accesskey &&
       kNameSpaceID_None == aNameSpaceID) {
-    RegUnRegAccessKey(PR_FALSE);
+    // Have to unregister before clearing flag. See UnregAccessKey
+    UnregAccessKey();
+    UnsetFlags(NODE_HAS_ACCESSKEY);
   }
 
   return nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
 }
 
 void
 nsHTMLLabelElement::PerformAccesskey(PRBool aKeyCausesActivation,
                                      PRBool aIsTrustedEvent)
@@ -428,19 +431,17 @@ nsHTMLLabelElement::GetControlContent()
 
   // We have a @for. The id has to be linked to an element in the same document
   // and this element should be a labelable form control.
   nsIDocument* doc = GetCurrentDoc();
   if (!doc) {
     return nsnull;
   }
 
-  nsresult rv;
-  nsIContent* content = doc->GetElementById(elementId, &rv);
-  NS_ENSURE_SUCCESS(rv, nsnull);
+  nsIContent* content = doc->GetElementById(elementId);
   if (!content) {
     return nsnull;
   }
 
   nsCOMPtr<nsIFormControl> element = do_QueryInterface(content);
   if (element && element->IsLabelableControl()) {
     NS_ADDREF(content);
     return content;
--- a/content/html/content/src/nsHTMLLegendElement.cpp
+++ b/content/html/content/src/nsHTMLLegendElement.cpp
@@ -214,36 +214,39 @@ nsHTMLLegendElement::GetAttributeChangeH
 nsresult
 nsHTMLLegendElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                              nsIAtom* aPrefix, const nsAString& aValue,
                              PRBool aNotify)
 {
   PRBool accesskey = (aAttribute == nsGkAtoms::accesskey &&
                       aNameSpaceID == kNameSpaceID_None);
   if (accesskey) {
-    RegUnRegAccessKey(PR_FALSE);
+    UnregAccessKey();
   }
 
   nsresult rv = nsGenericHTMLFormElement::SetAttr(aNameSpaceID, aAttribute,
                                                   aPrefix, aValue, aNotify);
 
   if (accesskey && !aValue.IsEmpty()) {
-    RegUnRegAccessKey(PR_TRUE);
+    SetFlags(NODE_HAS_ACCESSKEY);
+    RegAccessKey();
   }
 
   return rv;
 }
 
 nsresult
 nsHTMLLegendElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                                PRBool aNotify)
 {
   if (aAttribute == nsGkAtoms::accesskey &&
       aNameSpaceID == kNameSpaceID_None) {
-    RegUnRegAccessKey(PR_FALSE);
+    // Have to unregister before clearing flag. See UnregAccessKey
+    UnregAccessKey();
+    UnsetFlags(NODE_HAS_ACCESSKEY);
   }
 
   return nsGenericHTMLFormElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
 }
 
 nsresult
 nsHTMLLegendElement::Reset()
 {
@@ -256,27 +259,27 @@ nsHTMLLegendElement::BindToTree(nsIDocum
                                 PRBool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
                                                      aBindingParent,
                                                      aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
-    RegUnRegAccessKey(PR_TRUE);
+    RegAccessKey();
   }
 
   return rv;
 }
 
 void
 nsHTMLLegendElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
   if (IsInDoc()) {
-    RegUnRegAccessKey(PR_FALSE);
+    UnregAccessKey();
   }
 
   nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 NS_IMETHODIMP
 nsHTMLLegendElement::Focus()
 {
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2630,36 +2630,28 @@ static void
 FindNamedItems(nsIAtom* aName, nsIContent *aContent,
                nsIdentifierMapEntry* aEntry)
 {
   NS_ASSERTION(aEntry->HasNameContentList(),
                "Entry w/o content list passed to FindNamedItems()!");
   NS_ASSERTION(!aEntry->IsInvalidName(),
                "Entry that should never have a list passed to FindNamedItems()!");
 
-  if (!aContent->IsElement()) {
-    // non-elements are not named items nor can they have children.
-    return;
-  }
-
-  Element* element = aContent->AsElement();
-
-  if (aName == nsContentUtils::IsNamedItem(element)) {
-    aEntry->AddNameElement(element);
+  if (aContent->HasFlag(NODE_HAS_NAME)) {
+    NS_ASSERTION(nsGenericHTMLElement::FromContent(aContent),
+                 "Only HTML Elements should have a name");
+  
+    nsGenericHTMLElement* elm = static_cast<nsGenericHTMLElement*>(aContent);
+    if (elm->GetParsedAttr(nsGkAtoms::name)->GetAtomValue() == aName) {
+      aEntry->AddNameElement(elm);
+    }
   }
 
-  if (!aEntry->GetIdElement() &&
-      // Maybe this node has the right id?
-      aName == element->GetID()) {
-    aEntry->AddIdElement(element);
-  }
-
-  PRUint32 i, count = element->GetChildCount();
-  for (i = 0; i < count; ++i) {
-    FindNamedItems(aName, element->GetChildAt(i), aEntry);
+  for (nsINode::ChildIterator iter(aContent); !iter.IsDone(); iter.Next()) {
+    FindNamedItems(aName, iter, aEntry);
   }
 }
 
 nsresult
 nsHTMLDocument::ResolveName(const nsAString& aName,
                             nsIDOMHTMLFormElement *aForm,
                             nsISupports **aResult)
 {
@@ -2672,37 +2664,17 @@ nsHTMLDocument::ResolveName(const nsAStr
   nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(name);
   NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
 
   if (entry->IsInvalidName()) {
     // There won't be any named items by this name -- it's reserved
     return NS_OK;
   }
 
-  // Now we know we _might_ have items.  Before looking at
-  // entry->mNameContentList, make sure to flush out content (see
-  // bug 69826).
-  // This is a perf killer while the document is loading!
-
-  // Make sure to stash away the current generation so we can check whether the
-  // table changes when we flush.
-  PRUint32 generation = mIdentifierMap.GetGeneration();
-  
-  // If we already have an entry->mNameContentList, we need to flush out
-  // notifications too, so that it will get updated properly.
-  FlushPendingNotifications(entry->HasNameContentList() ?
-                            Flush_ContentAndNotify : Flush_Content);
-
-  if (generation != mIdentifierMap.GetGeneration()) {
-    // Table changed, so the entry pointer is no longer valid; look up the
-    // entry again, adding if necessary (the adding may be necessary in case
-    // the flush actually deleted entries).
-    entry = mIdentifierMap.PutEntry(name);
-    NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
-  }
+  // Now we know we _might_ have items.
 
   if (!entry->HasNameContentList()) {
 #ifdef DEBUG_jst
     {
       printf ("nsHTMLDocument name cache miss for name '%s'\n",
               NS_ConvertUTF16toUTF8(aName).get());
     }
 #endif
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -235,20 +235,19 @@ public:
   }
 
   virtual nsresult SetEditingState(EditingState aState);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual NS_HIDDEN_(void) RemovedFromDocShell();
 
-  virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId,
-                                                nsresult *aResult)
+  virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId)
   {
-    return nsDocument::GetElementById(aElementId, aResult);
+    return nsDocument::GetElementById(aElementId);
   }
 
 protected:
   nsresult GetBodySize(PRInt32* aWidth,
                        PRInt32* aHeight);
 
   nsresult PrePopulateIdentifierMap();
 
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -616,27 +616,21 @@ nsBindingManager::SetWrappedJS(nsIConten
 {
   if (mDestroyed) {
     return NS_OK;
   }
 
   return SetOrRemoveObject(mWrapperTable, aContent, aWrappedJS);
 }
 
-nsresult
-nsBindingManager::ChangeDocumentFor(nsIContent* aContent, nsIDocument* aOldDocument,
-                                    nsIDocument* aNewDocument)
+void
+nsBindingManager::RemovedFromDocumentInternal(nsIContent* aContent,
+                                              nsIDocument* aOldDocument)
 {
-  // XXXbz this code is pretty broken, since moving from one document
-  // to another always passes through a null document!
   NS_PRECONDITION(aOldDocument != nsnull, "no old document");
-  NS_PRECONDITION(!aNewDocument,
-                  "Changing to a non-null new document not supported yet");
-  if (! aOldDocument)
-    return NS_ERROR_NULL_POINTER;
 
   // Hold a ref to the binding so it won't die when we remove it from our
   // table.
   nsRefPtr<nsXBLBinding> binding = GetBinding(aContent);
   if (aContent->HasFlag(NODE_IS_INSERTION_PARENT)) {
     nsRefPtr<nsXBLBinding> parentBinding = GetBinding(aContent->GetBindingParent());
     if (parentBinding) {
       parentBinding->RemoveInsertionParent(aContent);
@@ -645,28 +639,24 @@ nsBindingManager::ChangeDocumentFor(nsIC
       if (!binding || !binding->HasInsertionParent(aContent)) {
         RemoveInsertionParent(aContent);
         aContent->UnsetFlags(NODE_IS_INSERTION_PARENT);
       }
     }
   }
 
   if (binding) {
-    binding->ChangeDocument(aOldDocument, aNewDocument);
+    binding->ChangeDocument(aOldDocument, nsnull);
     SetBinding(aContent, nsnull);
-    if (aNewDocument)
-      aNewDocument->BindingManager()->SetBinding(aContent, binding);
   }
 
   // Clear out insertion parents and content lists.
   SetInsertionParent(aContent, nsnull);
   SetContentListFor(aContent, nsnull);
   SetAnonymousNodesFor(aContent, nsnull);
-
-  return NS_OK;
 }
 
 nsIAtom*
 nsBindingManager::ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID)
 {
   nsXBLBinding *binding = GetBinding(aContent);
   
   if (binding) {
--- a/content/xbl/src/nsBindingManager.h
+++ b/content/xbl/src/nsBindingManager.h
@@ -79,31 +79,32 @@ public:
   nsXBLBinding* GetBinding(nsIContent* aContent);
   nsresult SetBinding(nsIContent* aContent, nsXBLBinding* aBinding);
 
   nsIContent* GetInsertionParent(nsIContent* aContent);
   nsresult SetInsertionParent(nsIContent* aContent, nsIContent* aResult);
 
   /**
    * Notify the binding manager that an element
-   * has been moved from one document to another,
+   * has been removed from its document,
    * so that it can update any bindings or
    * nsIAnonymousContentCreator-created anonymous
    * content that may depend on the document.
    * @param aContent the element that's being moved
    * @param aOldDocument the old document in which the
-   *   content resided. May be null if the the content
-   *   was not in any document.
-   * @param aNewDocument the document in which the
-   *   content will reside. May be null if the content
-   *   will not reside in any document, or if the
-   *   content is being destroyed.
+   *   content resided.
    */
-  nsresult ChangeDocumentFor(nsIContent* aContent, nsIDocument* aOldDocument,
-                             nsIDocument* aNewDocument);
+  void RemovedFromDocument(nsIContent* aContent, nsIDocument* aOldDocument)
+  {
+    if (aContent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
+      RemovedFromDocumentInternal(aContent, aOldDocument);
+    }
+  }
+  void RemovedFromDocumentInternal(nsIContent* aContent,
+                                   nsIDocument* aOldDocument);
 
   nsIAtom* ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID);
 
   /**
    * Return a list of all explicit children, including any children
    * that may have been inserted via XBL insertion points.
    */
   nsresult GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult);
--- a/content/xml/content/src/nsXMLElement.cpp
+++ b/content/xml/content/src/nsXMLElement.cpp
@@ -58,13 +58,118 @@ NS_INTERFACE_TABLE_HEAD(nsXMLElement)
   NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsXMLElement)
     NS_INTERFACE_TABLE_ENTRY(nsXMLElement, nsIDOMNode)
     NS_INTERFACE_TABLE_ENTRY(nsXMLElement, nsIDOMElement)
   NS_OFFSET_AND_INTERFACE_TABLE_END
   NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Element)
 NS_ELEMENT_INTERFACE_MAP_END
 
-
 NS_IMPL_ADDREF_INHERITED(nsXMLElement, nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsXMLElement, nsGenericElement)
 
 NS_IMPL_ELEMENT_CLONE(nsXMLElement)
+
+nsresult
+nsXMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
+                        PRBool aNotify)
+{
+  PRBool isId = PR_FALSE;
+  if (aAttribute == GetIDAttributeName() &&
+      aNameSpaceID == kNameSpaceID_None) {
+    // Have to do this before clearing flag. See RemoveFromIdTable
+    RemoveFromIdTable();
+    isId = PR_TRUE;
+  }
+  
+  nsresult rv = nsGenericElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
+  
+  if (isId) {
+    UnsetFlags(NODE_HAS_ID);
+  }
+  
+  return rv;
+}
+
+nsIAtom *
+nsXMLElement::GetIDAttributeName() const
+{
+  return mNodeInfo->GetIDAttributeAtom();
+}
+
+nsIAtom*
+nsXMLElement::DoGetID() const
+{
+  NS_ASSERTION(HasFlag(NODE_HAS_ID), "Unexpected call");
+
+  nsIAtom* IDName = GetIDAttributeName();
+  if (IDName) {
+    const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(IDName);
+    if (attrVal) {
+      if (attrVal->Type() == nsAttrValue::eAtom) {
+        return attrVal->GetAtomValue();
+      }
+      if (attrVal->IsEmptyString()) {
+        return nsnull;
+      }
+      // Check if the ID has been stored as a string.
+      // This would occur if the ID attribute name changed after 
+      // the ID was parsed. 
+      if (attrVal->Type() == nsAttrValue::eString) {
+        nsAutoString idVal(attrVal->GetStringValue());
+
+        // Create an atom from the value and set it into the attribute list. 
+        const_cast<nsAttrValue*>(attrVal)->ParseAtom(idVal);
+        return attrVal->GetAtomValue();
+      }
+    }
+  }
+  return nsnull;
+}
+
+PRBool
+nsXMLElement::ParseAttribute(PRInt32 aNamespaceID,
+                             nsIAtom* aAttribute,
+                             const nsAString& aValue,
+                             nsAttrValue& aResult)
+{
+  if (aAttribute == GetIDAttributeName() &&
+      aNamespaceID == kNameSpaceID_None) {
+    // Store id as an atom.  id="" means that the element has no id,
+    // not that it has an emptystring as the id.
+    RemoveFromIdTable();
+    if (aValue.IsEmpty()) {
+      UnsetFlags(NODE_HAS_ID);
+      return PR_FALSE;
+    }
+    aResult.ParseAtom(aValue);
+    SetFlags(NODE_HAS_ID);
+    AddToIdTable(aResult.GetAtomValue());
+    return PR_TRUE;
+  }
+
+  return PR_FALSE;
+}
+
+nsresult
+nsXMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                         nsIContent* aBindingParent,
+                         PRBool aCompileEventHandlers)
+{
+  nsresult rv = nsGenericElement::BindToTree(aDocument, aParent,
+                                             aBindingParent,
+                                             aCompileEventHandlers);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aDocument && HasFlag(NODE_HAS_ID) && !GetBindingParent()) {
+    aDocument->AddToIdTable(this, DoGetID());
+  }
+
+  return NS_OK;
+}
+
+void
+nsXMLElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
+{
+  RemoveFromIdTable();
+
+  return nsGenericElement::UnbindFromTree(aDeep, aNullParent);
+}
--- a/content/xml/content/src/nsXMLElement.h
+++ b/content/xml/content/src/nsXMLElement.h
@@ -57,11 +57,25 @@ public:
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericElement::)
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT(nsGenericElement::)
 
   // nsINode interface methods
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  // nsIContent interface methods
+  virtual nsIAtom *GetIDAttributeName() const;
+  virtual nsIAtom* DoGetID() const;
+  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              PRBool aCompileEventHandlers);
+  virtual void UnbindFromTree(PRBool aDeep, PRBool aNullParent);
+  virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
+                             PRBool aNotify);
+  virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
+                                nsIAtom* aAttribute,
+                                const nsAString& aValue,
+                                nsAttrValue& aResult);
 };
 
 #endif // nsXMLElement_h___
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -267,17 +267,17 @@ nsXULElement::Create(nsXULPrototypeEleme
                      PRBool aIsScriptable)
 {
     nsXULElement *element = new nsXULElement(aNodeInfo);
     if (element) {
         NS_ADDREF(element);
 
         element->mPrototype = aPrototype;
         if (aPrototype->mHasIdAttribute) {
-            element->SetFlags(NODE_MAY_HAVE_ID);
+            element->SetFlags(NODE_HAS_ID);
         }
         if (aPrototype->mHasClassAttribute) {
             element->SetFlags(NODE_MAY_HAVE_CLASS);
         }
         if (aPrototype->mHasStyleAttribute) {
             element->SetFlags(NODE_MAY_HAVE_STYLE);
         }
 
@@ -869,22 +869,19 @@ nsXULElement::MaybeAddPopupListener(nsIA
 //
 
 nsresult
 nsXULElement::BindToTree(nsIDocument* aDocument,
                          nsIContent* aParent,
                          nsIContent* aBindingParent,
                          PRBool aCompileEventHandlers)
 {
-  // Calling the nsStyledElementBase method on purpose to skip over
-  // nsStyledElement, since we don't want the style attribute
-  // reparsing it does.
-  nsresult rv = nsStyledElementBase::BindToTree(aDocument, aParent,
-                                                aBindingParent,
-                                                aCompileEventHandlers);
+  nsresult rv = nsStyledElement::BindToTree(aDocument, aParent,
+                                            aBindingParent,
+                                            aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
       NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                    "Missing a script blocker!");
       // We're in a document now.  Kick off the frame load.
       LoadSrc();
   }
@@ -1301,16 +1298,23 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpa
         FindPrototypeAttribute(aNameSpaceID, aName);
     if (protoattr) {
         // We've got an attribute on the prototype, so we need to
         // fully fault and remove the local copy.
         rv = MakeHeavyweight();
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
+    PRBool isId = PR_FALSE;
+    if (aName == nsGkAtoms::id && aNameSpaceID == kNameSpaceID_None) {
+      // Have to do this before clearing flag. See RemoveFromIdTable
+      RemoveFromIdTable();
+      isId = PR_TRUE;
+    }
+
     PRInt32 index = mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID);
     if (index < 0) {
         NS_ASSERTION(!protoattr, "we used to have a protoattr, we should now "
                                  "have a normal one");
 
         return NS_OK;
     }
 
@@ -1354,16 +1358,20 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpa
     // the attribute from the attribute map even though the attribute is still
     // on the element
     // https://bugzilla.mozilla.org/show_bug.cgi?id=296205
 
     // Deal with modification of magical attributes that side-effect
     // other things.
     // XXX Know how to remove POPUP event listeners when an attribute is unset?
 
+    if (isId) {
+        UnsetFlags(NODE_HAS_ID);
+    }
+
     if (aNameSpaceID == kNameSpaceID_None) {
         if (aName == nsGkAtoms::hidechrome &&
             mNodeInfo->Equals(nsGkAtoms::window)) {
             HideWindowChrome(PR_FALSE);
         }
 
         if (doc && doc->GetRootElement() == this) {
             if ((aName == nsGkAtoms::activetitlebarcolor ||
@@ -1712,36 +1720,32 @@ nsXULElement::GetBuilder(nsIXULTemplateB
 
     return NS_OK;
 }
 
 
 //----------------------------------------------------------------------
 // Implementation methods
 
-/// XXX GetID must be defined here because we have proto attrs.
+// XXX DoGetID and DoGetClasses must be defined here because we have proto
+// attributes.
 nsIAtom*
-nsXULElement::GetID() const
+nsXULElement::DoGetID() const
 {
-    if (!HasFlag(NODE_MAY_HAVE_ID)) {
-        return nsnull;
-    }
-
-    const nsAttrValue* attrVal = FindLocalOrProtoAttr(kNameSpaceID_None, nsGkAtoms::id);
-
-    NS_ASSERTION(!attrVal ||
-                 attrVal->Type() == nsAttrValue::eAtom ||
-                 (attrVal->Type() == nsAttrValue::eString &&
-                  attrVal->GetStringValue().IsEmpty()),
-                 "unexpected attribute type");
-
-    if (attrVal && attrVal->Type() == nsAttrValue::eAtom) {
-        return attrVal->GetAtomValue();
-    }
-    return nsnull;
+    NS_ASSERTION(HasFlag(NODE_HAS_ID), "Unexpected call");
+    const nsAttrValue* attr =
+        FindLocalOrProtoAttr(kNameSpaceID_None, nsGkAtoms::id);
+
+    // We need the nullcheck here because during unlink the prototype looses
+    // all of its attributes. We might want to change that.
+    // The nullcheck would also be needed if we make UnsetAttr use
+    // nsGenericElement::UnsetAttr as that calls out to various code between
+    // removing the attribute and clearing the NODE_HAS_ID flag.
+
+    return attr ? attr->GetAtomValue() : nsnull;
 }
 
 const nsAttrValue*
 nsXULElement::DoGetClasses() const
 {
     NS_ASSERTION(HasFlag(NODE_MAY_HAVE_CLASS), "Unexpected call");
     return FindLocalOrProtoAttr(kNameSpaceID_None, nsGkAtoms::_class);
 }
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -523,17 +523,17 @@ public:
 
     virtual void PerformAccesskey(PRBool aKeyCausesActivation,
                                   PRBool aIsTrustedEvent);
     nsresult ClickWithInputSource(PRUint16 aInputSource);
 
     virtual nsIContent *GetBindingParent() const;
     virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
     virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull, PRBool aWithMouse = PR_FALSE);
-    virtual nsIAtom* GetID() const;
+    virtual nsIAtom* DoGetID() const;
     virtual const nsAttrValue* DoGetClasses() const;
 
     NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
     virtual nsICSSStyleRule* GetInlineStyleRule();
     virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                                 PRInt32 aModType) const;
     NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
--- a/content/xul/document/public/nsIXULDocument.h
+++ b/content/xul/document/public/nsIXULDocument.h
@@ -42,40 +42,32 @@
 #include "nsString.h"
 #include "nsCOMArray.h"
 
 class nsIXULTemplateBuilder;
 class nsIContent;
 class nsIScriptGlobalObjectOwner;
 
 
-// {E486EA2A-5B37-4107-905F-EE062FB4FF97}
+// 3e872e97-b678-418e-a7e3-41b8305d4e75
 #define NS_IXULDOCUMENT_IID \
-{ 0xe486ea2a, 0x5b37, 0x4107, \
-  { 0x90, 0x5f, 0xee, 0x06, 0x2f, 0xb4, 0xff, 0x97 }}
+{ 0x3e872e97, 0xb678, 0x418e, \
+  { 0xa7, 0xe3, 0x41, 0xb8, 0x30, 0x5d, 0x4e, 0x75 } }
 
 
 /*
  * An XUL-specific extension to nsIDocument. Includes methods for
  * setting the root resource of the document content model, a factory
  * method for constructing the children of a node, etc.
  */
 class nsIXULDocument : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXULDOCUMENT_IID)
 
-  // The resource-to-element map is a one-to-many mapping of RDF
-  // resources to content elements.
-
-  /**
-   * Add an entry to the ID-to-element map.
-   */
-  NS_IMETHOD AddElementForID(nsIContent* aElement) = 0;
-
   /**
    * Get the elements for a particular resource --- all elements whose 'id'
    * or 'ref' is aID. The nsCOMArray will be truncated and filled in with
    * nsIContent pointers.
    */
   NS_IMETHOD GetElementsForID(const nsAString& aID, nsCOMArray<nsIContent>& aElements) = 0;
 
   /**
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -233,16 +233,17 @@ nsXULDocument::nsXULDocument(void)
 
     // NOTE! nsDocument::operator new() zeroes out all members, so don't
     // bother initializing members to 0.
 
     // Override the default in nsDocument
     mCharacterSet.AssignLiteral("UTF-8");
 
     mDefaultElementType = kNameSpaceID_XUL;
+    mIsXUL = PR_TRUE;
 
     mDelayFrameLoaderInitialization = PR_TRUE;
 }
 
 nsXULDocument::~nsXULDocument()
 {
     NS_ASSERTION(mNextSrcLoadWaiter == nsnull,
         "unreferenced document still waiting for script source to load?");
@@ -975,35 +976,28 @@ nsXULDocument::AttributeWillChange(nsIDo
     NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!");
 
     // XXXbz check aNameSpaceID, dammit!
     // See if we need to update our ref map.
     if (aAttribute == nsGkAtoms::ref ||
         (aAttribute == nsGkAtoms::id && !aContent->GetIDAttributeName())) {
         RemoveElementFromRefMap(aContent->AsElement());
     }
-    
-    nsXMLDocument::AttributeWillChange(aDocument, aContent, aNameSpaceID,
-                                       aAttribute, aModType);
 }
 
 void
 nsXULDocument::AttributeChanged(nsIDocument* aDocument,
                                 nsIContent* aElementContent, PRInt32 aNameSpaceID,
                                 nsIAtom* aAttribute, PRInt32 aModType)
 {
     NS_ASSERTION(aDocument == this, "unexpected doc");
 
     // XXXbz once we change AttributeChanged to take Element, we can nix this line
     Element* aElement = aElementContent->AsElement();
 
-    // Do this here so that all the exit paths below don't leave this undone
-    nsXMLDocument::AttributeChanged(aDocument, aElement, aNameSpaceID,
-                                    aAttribute, aModType);
-
     // XXXbz check aNameSpaceID, dammit!
     // See if we need to update our ref map.
     if (aAttribute == nsGkAtoms::ref ||
         (aAttribute == nsGkAtoms::id && !aElement->GetIDAttributeName())) {
         AddElementToRefMap(aElement);
     }
     
     nsresult rv;
@@ -1095,66 +1089,46 @@ nsXULDocument::ContentAppended(nsIDocume
     NS_ASSERTION(aDocument == this, "unexpected doc");
     
     // Update our element map
     nsresult rv = NS_OK;
     for (nsIContent* cur = aFirstNewContent; cur && NS_SUCCEEDED(rv);
          cur = cur->GetNextSibling()) {
         rv = AddSubtreeToDocument(cur);
     }
-
-    nsXMLDocument::ContentAppended(aDocument, aContainer, aFirstNewContent,
-                                   aNewIndexInContainer);
 }
 
 void
 nsXULDocument::ContentInserted(nsIDocument* aDocument,
                                nsIContent* aContainer,
                                nsIContent* aChild,
                                PRInt32 aIndexInContainer)
 {
     NS_ASSERTION(aDocument == this, "unexpected doc");
 
     AddSubtreeToDocument(aChild);
-
-    nsXMLDocument::ContentInserted(aDocument, aContainer, aChild, aIndexInContainer);
 }
 
 void
 nsXULDocument::ContentRemoved(nsIDocument* aDocument,
                               nsIContent* aContainer,
                               nsIContent* aChild,
                               PRInt32 aIndexInContainer)
 {
     NS_ASSERTION(aDocument == this, "unexpected doc");
 
     RemoveSubtreeFromDocument(aChild);
-
-    nsXMLDocument::ContentRemoved(aDocument, aContainer, aChild, aIndexInContainer);
 }
 
 //----------------------------------------------------------------------
 //
 // nsIXULDocument interface
 //
 
 NS_IMETHODIMP
-nsXULDocument::AddElementForID(nsIContent* aElement)
-{
-    NS_PRECONDITION(aElement != nsnull, "null ptr");
-    if (! aElement)
-        return NS_ERROR_NULL_POINTER;
-    if (!aElement->IsElement())
-        return NS_ERROR_UNEXPECTED;
-
-    UpdateIdTableEntry(aElement->AsElement());
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 nsXULDocument::GetElementsForID(const nsAString& aID,
                                 nsCOMArray<nsIContent>& aElements)
 {
     aElements.Clear();
 
     nsCOMPtr<nsIAtom> atom = do_GetAtom(aID);
     if (!atom)
         return NS_ERROR_OUT_OF_MEMORY;
@@ -1656,27 +1630,25 @@ NS_IMETHODIMP
 nsXULDocument::GetCommandDispatcher(nsIDOMXULCommandDispatcher** aTracker)
 {
     *aTracker = mCommandDispatcher;
     NS_IF_ADDREF(*aTracker);
     return NS_OK;
 }
 
 Element*
-nsXULDocument::GetElementById(const nsAString& aId, nsresult *aResult)
+nsXULDocument::GetElementById(const nsAString& aId)
 {
     nsCOMPtr<nsIAtom> atom(do_GetAtom(aId));
     if (!atom) {
-        *aResult = NS_ERROR_OUT_OF_MEMORY;
-
+        // This can only fail due OOM if the atom doesn't exist, in which
+        // case there couldn't possibly exist an entry for it.
         return nsnull;
     }
 
-    *aResult = NS_OK;
-
     if (!CheckGetElementByIdArg(atom))
         return nsnull;
 
     nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(atom);
     if (entry) {
         Element* element = entry->GetIdElement();
         if (element)
             return element;
@@ -1695,17 +1667,20 @@ nsXULDocument::AddElementToDocumentPre(E
 {
     // Do a bunch of work that's necessary when an element gets added
     // to the XUL Document.
     nsresult rv;
 
     // 1. Add the element to the resource-to-element map. Also add it to
     // the id map, since it seems this can be called when creating
     // elements from prototypes.
-    UpdateIdTableEntry(aElement);
+    nsIAtom* id = aElement->GetID();
+    if (id) {
+        AddToIdTable(aElement, id);
+    }
     rv = AddElementToRefMap(aElement);
     if (NS_FAILED(rv)) return rv;
 
     // 2. If the element is a 'command updater' (i.e., has a
     // "commandupdater='true'" attribute), then add the element to the
     // document's command dispatcher
     if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::commandupdater,
                               nsGkAtoms::_true, eCaseMatters)) {
@@ -1830,17 +1805,20 @@ nsXULDocument::RemoveSubtreeFromDocument
         if (NS_FAILED(rv))
             return rv;
     }
 
     // 2. Remove the element from the resource-to-element map.
     // Also remove it from the id map, since we added it in
     // AddElementToDocumentPre().
     RemoveElementFromRefMap(aElement);
-    RemoveFromIdTable(aElement);
+    nsIAtom* id = aElement->GetID();
+    if (id) {
+        RemoveFromIdTable(aElement, id);
+    }
 
     // 3. If the element is a 'command updater', then remove the
     // element from the document's command dispatcher.
     if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::commandupdater,
                               nsGkAtoms::_true, eCaseMatters)) {
         nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(aElement);
         NS_ASSERTION(domelement != nsnull, "not a DOM element");
         if (! domelement)
@@ -2467,18 +2445,16 @@ nsXULDocument::PrepareToWalk()
     if (mState == eState_Master) {
         // Add the root element
         rv = CreateElementFromPrototype(proto, getter_AddRefs(root));
         if (NS_FAILED(rv)) return rv;
 
         rv = AppendChildTo(root, PR_FALSE);
         if (NS_FAILED(rv)) return rv;
         
-        // Add the root element to the XUL document's ID-to-element map.
-        UpdateIdTableEntry(root);
         rv = AddElementToRefMap(root);
         if (NS_FAILED(rv)) return rv;
 
         // Block onload until we've finished building the complete
         // document content model.
         BlockOnload();
     }
 
--- a/content/xul/document/src/nsXULDocument.h
+++ b/content/xul/document/src/nsXULDocument.h
@@ -143,17 +143,16 @@ public:
     // nsIMutationObserver interface
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
     NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
     NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
 
     // nsIXULDocument interface
-    NS_IMETHOD AddElementForID(nsIContent* aElement);
     NS_IMETHOD GetElementsForID(const nsAString& aID,
                                 nsCOMArray<nsIContent>& aElements);
 
     NS_IMETHOD GetScriptGlobalObjectOwner(nsIScriptGlobalObjectOwner** aGlobalOwner);
     NS_IMETHOD AddSubtreeToDocument(nsIContent* aContent);
     NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aContent);
     NS_IMETHOD SetTemplateBuilderFor(nsIContent* aContent,
                                      nsIXULTemplateBuilder* aBuilder);
@@ -165,18 +164,17 @@ public:
     // nsIDOMNode interface overrides
     NS_IMETHOD CloneNode(PRBool deep, nsIDOMNode **_retval);
 
     // nsDocument interface overrides
     NS_IMETHOD GetElementById(const nsAString& aId, nsIDOMElement** aReturn)
     {
         return nsDocument::GetElementById(aId, aReturn);
     }
-    virtual mozilla::dom::Element* GetElementById(const nsAString & elementId,
-                                                  nsresult *aResult);
+    virtual mozilla::dom::Element* GetElementById(const nsAString & elementId);
 
     // nsIDOMXULDocument interface
     NS_DECL_NSIDOMXULDOCUMENT
 
     // nsIDOMNSDocument
     NS_IMETHOD GetContentType(nsAString& aContentType);
 
     // nsICSSLoaderObserver
--- a/content/xul/templates/src/nsXULContentBuilder.cpp
+++ b/content/xul/templates/src/nsXULContentBuilder.cpp
@@ -629,27 +629,16 @@ nsXULContentBuilder::BuildContentFromTem
             rv = aChild->GetId(id);
             if (NS_FAILED(rv))
                 return rv;
 
             rv = realKid->SetAttr(kNameSpaceID_None, nsGkAtoms::id, id, PR_FALSE);
             if (NS_FAILED(rv))
                 return rv;
 
-            if (! aNotify) {
-                // XUL document will watch us, and take care of making
-                // sure that we get added to or removed from the
-                // element map if aNotify is true. If not, we gotta do
-                // it ourselves. Yay.
-                nsCOMPtr<nsIXULDocument> xuldoc =
-                    do_QueryInterface(mRoot->GetDocument());
-                if (xuldoc)
-                    xuldoc->AddElementForID(realKid);
-            }
-
             // Set up the element's 'container' and 'empty' attributes.
             SetContainerAttrs(realKid, aChild, PR_TRUE, PR_FALSE);
         }
         else if (tag == nsGkAtoms::textnode &&
                  nameSpaceID == kNameSpaceID_XUL) {
             // <xul:text value="..."> is replaced by text of the
             // actual value of the 'rdf:resource' attribute for the
             // given node.
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -3040,17 +3040,18 @@ static JSPropertySpec OptionsProperties[
   {0}
 };
 
 static JSBool
 GetOptionsProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 {
   if (JSVAL_IS_INT(id)) {
     uint32 optbit = (uint32) JSVAL_TO_INT(id);
-    if ((optbit & (optbit - 1)) == 0 && optbit <= JSOPTION_WERROR)
+    if (((optbit & (optbit - 1)) == 0 && optbit <= JSOPTION_WERROR) ||
+          optbit == JSOPTION_RELIMIT)
       *vp = (JS_GetOptions(cx) & optbit) ? JSVAL_TRUE : JSVAL_FALSE;
   }
   return JS_TRUE;
 }
 
 static JSBool
 SetOptionsProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 {
--- a/editor/composer/src/nsEditorSpellCheck.cpp
+++ b/editor/composer/src/nsEditorSpellCheck.cpp
@@ -55,18 +55,28 @@
 #include "nsISupportsPrimitives.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIChromeRegistry.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsITextServicesFilter.h"
 #include "mozilla/Services.h"
 
-NS_IMPL_ISUPPORTS1(nsEditorSpellCheck,
-                   nsIEditorSpellCheck)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsEditorSpellCheck)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsEditorSpellCheck)
+
+NS_INTERFACE_MAP_BEGIN(nsEditorSpellCheck)
+  NS_INTERFACE_MAP_ENTRY(nsIEditorSpellCheck)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditorSpellCheck)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsEditorSpellCheck)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_2(nsEditorSpellCheck,
+                           mSpellChecker,
+                           mTxtSrvFilter)
 
 nsEditorSpellCheck::nsEditorSpellCheck()
   : mSuggestedWordIndex(0)
   , mDictionaryIndex(0)
 {
 }
 
 nsEditorSpellCheck::~nsEditorSpellCheck()
--- a/editor/composer/src/nsEditorSpellCheck.h
+++ b/editor/composer/src/nsEditorSpellCheck.h
@@ -39,30 +39,32 @@
 
 #ifndef nsEditorSpellCheck_h___
 #define nsEditorSpellCheck_h___
 
 
 #include "nsIEditorSpellCheck.h"
 #include "nsISpellChecker.h"
 #include "nsCOMPtr.h"
+#include "nsCycleCollectionParticipant.h"
 
 #define NS_EDITORSPELLCHECK_CID                     \
 { /* {75656ad9-bd13-4c5d-939a-ec6351eea0cc} */        \
     0x75656ad9, 0xbd13, 0x4c5d,                       \
     { 0x93, 0x9a, 0xec, 0x63, 0x51, 0xee, 0xa0, 0xcc }\
 }
 
 class nsEditorSpellCheck : public nsIEditorSpellCheck
 {
 public:
   nsEditorSpellCheck();
   virtual ~nsEditorSpellCheck();
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsEditorSpellCheck)
 
   /* Declare all methods in the nsIEditorSpellCheck interface */
   NS_DECL_NSIEDITORSPELLCHECK
 
 protected:
   nsCOMPtr<nsISpellChecker> mSpellChecker;
 
   nsTArray<nsString>  mSuggestedWordList;
--- a/editor/txtsvc/src/nsFilteredContentIterator.cpp
+++ b/editor/txtsvc/src/nsFilteredContentIterator.cpp
@@ -60,17 +60,31 @@ nsFilteredContentIterator::nsFilteredCon
 }
 
 //------------------------------------------------------------
 nsFilteredContentIterator::~nsFilteredContentIterator()
 {
 }
 
 //------------------------------------------------------------
-NS_IMPL_ISUPPORTS1(nsFilteredContentIterator, nsIContentIterator)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFilteredContentIterator)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFilteredContentIterator)
+
+NS_INTERFACE_MAP_BEGIN(nsFilteredContentIterator)
+  NS_INTERFACE_MAP_ENTRY(nsIContentIterator)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentIterator)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsFilteredContentIterator)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_5(nsFilteredContentIterator,
+                           mCurrentIterator,
+                           mIterator,
+                           mPreIterator,
+                           mFilter,
+                           mRange)
 
 //------------------------------------------------------------
 nsresult
 nsFilteredContentIterator::Init(nsINode* aRoot)
 {
   NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
   NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
   mIsOutOfRange    = PR_FALSE;
--- a/editor/txtsvc/src/nsFilteredContentIterator.h
+++ b/editor/txtsvc/src/nsFilteredContentIterator.h
@@ -39,26 +39,28 @@
 #define nsFilteredContentIterator_h__
 
 #include "nsIContentIterator.h"
 #include "nsCOMPtr.h"
 #include "nsIAtom.h"
 #include "nsITextServicesFilter.h"
 #include "nsIDOMNSRange.h"
 #include "nsIRangeUtils.h"
+#include "nsCycleCollectionParticipant.h"
 
 /**
  * 
  */
 class nsFilteredContentIterator : public nsIContentIterator
 {
 public:
 
   // nsISupports interface...
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsFilteredContentIterator)
 
   nsFilteredContentIterator(nsITextServicesFilter* aFilter);
 
   virtual ~nsFilteredContentIterator();
 
   /* nsIContentIterator */
   virtual nsresult Init(nsINode* aRoot);
   virtual nsresult Init(nsIDOMRange* aRange);
--- a/editor/txtsvc/src/nsTextServicesDocument.cpp
+++ b/editor/txtsvc/src/nsTextServicesDocument.cpp
@@ -142,43 +142,34 @@ nsTextServicesDocument::RegisterAtoms()
 
 /* static */
 void
 nsTextServicesDocument::Shutdown()
 {
   NS_IF_RELEASE(sRangeHelper);
 }
 
-#define DEBUG_TEXT_SERVICES__DOCUMENT_REFCNT 1
-
-#ifdef DEBUG_TEXT_SERVICES__DOCUMENT_REFCNT
-
-nsrefcnt nsTextServicesDocument::AddRef(void)
-{
-  return ++mRefCnt;
-}
-
-nsrefcnt nsTextServicesDocument::Release(void)
-{
-  NS_PRECONDITION(0 != mRefCnt, "dup release");
-  if (--mRefCnt == 0) {
-    NS_DELETEXPCOM(this);
-    return 0;
-  }
-  return mRefCnt;
-}
-
-#else
-
-NS_IMPL_ADDREF(nsTextServicesDocument)
-NS_IMPL_RELEASE(nsTextServicesDocument)
-
-#endif
-
-NS_IMPL_QUERY_INTERFACE1(nsTextServicesDocument, nsITextServicesDocument)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTextServicesDocument)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTextServicesDocument)
+
+NS_INTERFACE_MAP_BEGIN(nsTextServicesDocument)
+  NS_INTERFACE_MAP_ENTRY(nsITextServicesDocument)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITextServicesDocument)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsTextServicesDocument)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_8(nsTextServicesDocument,
+                           mDOMDocument,
+                           mSelCon,
+                           mIterator,
+                           mPrevTextBlock,
+                           mNextTextBlock,
+                           mNotifier,
+                           mExtent,
+                           mTxtSvcFilter)
 
 NS_IMETHODIMP
 nsTextServicesDocument::InitWithEditor(nsIEditor *aEditor)
 {
   nsresult result = NS_OK;
   nsCOMPtr<nsISelectionController> selCon;
   nsCOMPtr<nsIDOMDocument> doc;
 
--- a/editor/txtsvc/src/nsTextServicesDocument.h
+++ b/editor/txtsvc/src/nsTextServicesDocument.h
@@ -46,16 +46,17 @@
 #include "nsIEditor.h"
 #include "nsIEditActionListener.h"
 #include "nsITextServicesDocument.h"
 #include "nsTArray.h"
 #include "nsTSDNotifier.h"
 #include "nsISelectionController.h"
 #include "nsITextServicesFilter.h"
 #include "nsWeakReference.h"
+#include "nsCycleCollectionParticipant.h"
 
 class nsIRangeUtils;
 class OffsetEntry;
 
 /** implementation of a text services object.
  *
  */
 class nsTextServicesDocument : public nsITextServicesDocument
@@ -130,17 +131,18 @@ public:
    */
   static void RegisterAtoms();
 
   /** To be called at module shutdown
    */
   static void Shutdown();
 
   /* Macro for AddRef(), Release(), and QueryInterface() */
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsTextServicesDocument)
 
   /* nsITextServicesDocument method implementations. */
   NS_IMETHOD InitWithEditor(nsIEditor *aEditor);
   NS_IMETHOD GetDocument(nsIDOMDocument **aDoc);
   NS_IMETHOD SetExtent(nsIDOMRange* aDOMRange);
   NS_IMETHOD ExpandRangeToWordBoundaries(nsIDOMRange *aRange);
   NS_IMETHOD SetFilter(nsITextServicesFilter *aFilter);
   NS_IMETHOD GetCurrentTextBlock(nsString *aStr);
--- a/embedding/Makefile.in
+++ b/embedding/Makefile.in
@@ -47,9 +47,13 @@ MODULE       = embed
 
 DIRS = base components browser
 
 ifdef ENABLE_TESTS
 XPCSHELL_TESTS = tests/unit
 DIRS += test
 endif
 
+ifeq ($(OS_TARGET),Android)
+TOOL_DIRS = android
+endif
+
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/embedding/android/AndroidManifest.xml.in
@@ -0,0 +1,66 @@
+#filter substitution
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="org.mozilla.@MOZ_APP_NAME@"
+      android:versionCode="1"
+      android:versionName="1.9.3"
+      android:sharedUserId="org.mozilla.sharedID">
+    <uses-sdk android:minSdkVersion="5"
+              android:targetSdkVersion="5"/>
+
+    <uses-permission android:name="android.permission.INTERNET"/> 
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
+
+    <application android:label="@MOZ_APP_DISPLAYNAME@"
+		 android:icon="@drawable/icon">
+        <activity android:name="App"
+                  android:label="@MOZ_APP_DISPLAYNAME@"
+                  android:configChanges="keyboard|keyboardHidden|orientation|mcc|mnc"
+                  android:windowSoftInputMode="stateUnspecified|adjustResize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+
+            <!-- Default browser intents -->
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="http" />
+                <data android:scheme="https" />
+                <data android:scheme="about" />
+                <data android:scheme="javascript" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="http" />
+                <data android:scheme="https" />
+                <data android:mimeType="text/html"/>
+                <data android:mimeType="text/plain"/>
+                <data android:mimeType="application/xhtml+xml"/>
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.WEB_SEARCH" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="" />
+                <data android:scheme="http" />
+                <data android:scheme="https" />
+            </intent-filter>
+
+            <!-- For debugging -->
+            <intent-filter>
+                <action android:name="org.mozilla.gecko.DEBUG" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+	<receiver android:enabled="true" android:name="Restarter">
+	  <intent-filter>
+            <action android:name="org.mozilla.gecko.restart@MOZ_APP_NAME@" />
+	  </intent-filter>
+	</receiver>
+    </application>
+</manifest> 
new file mode 100644
--- /dev/null
+++ b/embedding/android/App.java.in
@@ -0,0 +1,48 @@
+/* -*- Mode: Java; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** 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 Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brad Lassey <blassey@mozilla.com>
+ *
+ * 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 ***** */
+
+#filter substitution
+package org.mozilla.@MOZ_APP_NAME@;
+
+import org.mozilla.gecko.GeckoApp;
+
+public class App extends GeckoApp {
+    public String getAppName() {
+	return "@MOZ_APP_NAME@";
+    }
+};
+
new file mode 100644
--- /dev/null
+++ b/embedding/android/GeckoApp.java
@@ -0,0 +1,372 @@
+/* -*- Mode: Java; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** 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 Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009-2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * 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 ***** */
+
+package org.mozilla.gecko;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import java.nio.*;
+
+import android.os.*;
+import android.app.*;
+import android.text.*;
+import android.view.*;
+import android.view.inputmethod.*;
+import android.content.*;
+import android.graphics.*;
+import android.widget.*;
+import android.hardware.*;
+
+import android.util.*;
+
+abstract public class GeckoApp
+    extends Activity
+{
+    public static FrameLayout mainLayout;
+    public static GeckoSurfaceView surfaceView;
+    public static GeckoApp mAppContext;
+
+    public static boolean useSoftwareDrawing;
+
+    void launch()
+    {
+        // unpack files in the components directory
+        unpackComponents();
+        // and then fire us up
+        Intent i = getIntent();
+        String env = i.getStringExtra("env0");
+        Log.i("GeckoApp", "env0: "+ env);
+        for (int c = 1; env != null; c++) {
+            GeckoAppShell.putenv(env);
+            env = i.getStringExtra("env" + c);
+            Log.i("GeckoApp", "env"+ c +": "+ env);
+        }
+        GeckoAppShell.runGecko(getApplication().getPackageResourcePath(),
+                               i.getStringExtra("args"),
+                               i.getDataString());
+    }
+
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState)
+    {
+        super.onCreate(savedInstanceState);
+
+        mAppContext = this;
+
+        // hide our window's title, we don't want it
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+        surfaceView = new GeckoSurfaceView(this);
+        
+        mainLayout = new FrameLayout(this);
+        mainLayout.addView(surfaceView,
+                           new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,
+                                                        FrameLayout.LayoutParams.FILL_PARENT));
+
+        boolean useLaunchButton = false;
+
+        String intentAction = getIntent().getAction();
+        if (intentAction != null && intentAction.equals("org.mozilla.gecko.DEBUG"))
+            useLaunchButton = true;
+
+        setContentView(mainLayout,
+                       new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
+                                                  ViewGroup.LayoutParams.FILL_PARENT));
+
+        useSoftwareDrawing = true; //isInEmulator() == 1;
+
+        if (!GeckoAppShell.sGeckoRunning) {
+            // Load our JNI libs; we need to do this before launch() because
+            // setInitialSize will be called even before Gecko is actually up
+            // and running.
+            GeckoAppShell.loadGeckoLibs();
+
+            if (useLaunchButton) {
+                final Button b = new Button(this);
+                b.setText("Launch");
+                b.setOnClickListener(new Button.OnClickListener() {
+                        public void onClick (View v) {
+                            // hide the button so we can't be launched again
+                            mainLayout.removeView(b);
+                            launch();
+                        }
+                    });
+                mainLayout.addView(b, 300, 200);
+            } else {
+                launch();
+            }
+        }
+
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public void onPause()
+    {
+        // The user is navigating away from this activity, but nothing
+        // has come to the foreground yet; for Gecko, we may want to
+        // stop repainting, for example.
+
+        // Whatever we do here should be fast, because we're blocking
+        // the next activity from showing up until we finish.
+
+        // onPause will be followed by either onResume or onStop.
+        super.onPause();
+    }
+
+    @Override
+    public void onResume()
+    {
+        // After an onPause, the activity is back in the foreground.
+        // Undo whatever we did in onPause.
+        super.onResume();
+    }
+
+    @Override
+    public void onStop()
+    {
+        // We're about to be stopped, potentially in preparation for
+        // being destroyed.  We're killable after this point -- as I
+        // understand it, in extreme cases the process can be terminated
+        // without going through onDestroy.
+        //
+        // We might also get an onRestart after this; not sure what
+        // that would mean for Gecko if we were to kill it here.
+        // Instead, what we should do here is save prefs, session,
+        // etc., and generally mark the profile as 'clean', and then
+        // dirty it again if we get an onResume.
+
+        // XXX do the above.
+
+        super.onStop();
+    }
+
+    @Override
+    public void onDestroy()
+    {
+        // Tell Gecko to shutting down; we'll end up calling System.exit()
+        // in onXreExit.
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_STOPPING));
+
+        super.onDestroy();
+    }
+
+    @Override
+    public void onConfigurationChanged(android.content.res.Configuration newConfig)
+    {
+        // nothing, just ignore
+        super.onConfigurationChanged(newConfig);
+    }
+
+    @Override
+    public void onLowMemory()
+    {
+        // XXX TODO
+        super.onLowMemory();
+    }
+
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_VOLUME_UP:
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+                return false;
+            default:
+                GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
+                return true;
+        }
+    }
+
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
+        return true;
+    }
+
+    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
+        return true;
+    }
+
+    abstract public String getAppName();
+
+    protected void unpackComponents()
+    {
+        ZipFile zip;
+        InputStream listStream;
+
+        try {
+            File componentsDir = new File("/data/data/org.mozilla." + getAppName() +"/components");
+            componentsDir.mkdir();
+            zip = new ZipFile(getApplication().getPackageResourcePath());
+
+            ZipEntry componentsList = zip.getEntry("components/components.list");
+            if (componentsList == null) {
+                Log.i("GeckoAppJava", "Can't find components.list !");
+                return;
+            }
+
+            listStream = new BufferedInputStream(zip.getInputStream(componentsList));
+        } catch (Exception e) {
+            Log.i("GeckoAppJava", e.toString());
+            return;
+        }
+
+        byte[] buf = new byte[8192];
+
+        StreamTokenizer tkn = new StreamTokenizer(new InputStreamReader(listStream));
+        String line = "components/";
+        int status;
+        tkn.eolIsSignificant(true);
+        do {
+            try {
+                status = tkn.nextToken();
+            } catch (IOException e) {
+                Log.i("GeckoAppJava", e.toString());
+                return;
+            }
+            switch (status) {
+            case StreamTokenizer.TT_WORD:
+                line += tkn.sval;
+                break;
+            case StreamTokenizer.TT_NUMBER:
+                line += tkn.nval;
+                break;
+            case StreamTokenizer.TT_EOF:
+            case StreamTokenizer.TT_EOL:
+                if (!line.endsWith(".js"))
+                    unpackFile(zip, buf, null, line);
+                line = "components/";
+                break;
+            }
+        } while (status != StreamTokenizer.TT_EOF);
+
+        unpackFile(zip, buf, null, "application.ini");
+    }
+
+    private void unpackFile(ZipFile zip, byte[] buf, ZipEntry fileEntry, String name)
+    {
+        if (fileEntry == null)
+            fileEntry = zip.getEntry(name);
+        if (fileEntry == null) {
+            Log.i("GeckoAppJava", "Can't find " + name + " in " + zip.getName());
+            return;
+        }
+
+        File outFile = new File("/data/data/org.mozilla." + getAppName() + "/" + name);
+        if (outFile.exists() &&
+            outFile.lastModified() >= fileEntry.getTime() &&
+            outFile.length() == fileEntry.getSize())
+            return;
+
+        try {
+            File dir = outFile.getParentFile();
+            if (!outFile.exists())
+                dir.mkdirs();
+        } catch (Exception e) {
+            Log.i("GeckoAppJava", e.toString());
+            return;
+        }
+
+        InputStream fileStream;
+        try {
+            fileStream = zip.getInputStream(fileEntry);
+        } catch (Exception e) {
+            Log.i("GeckoAppJava", e.toString());
+            return;
+        }
+
+        OutputStream outStream;
+        try {
+            outStream = new FileOutputStream(outFile);
+
+            while (fileStream.available() > 0) {
+                int read = fileStream.read(buf, 0, buf.length);
+                outStream.write(buf, 0, read);
+            }
+
+            fileStream.close();
+            outStream.close();
+        } catch (Exception e) {
+            Log.i("GeckoAppJava", e.toString());
+            return;
+        }
+    }
+    
+    public String getEnvString() {
+        Map<String,String> envMap = System.getenv();
+        Set<Map.Entry<String,String>> envSet = envMap.entrySet();
+        Iterator<Map.Entry<String,String>> envIter = envSet.iterator();
+        StringBuffer envstr = new StringBuffer();
+        int c = 0;
+        while (envIter.hasNext()) {
+            Map.Entry<String,String> entry = envIter.next();
+            // No need to pass env vars that we know the system provides
+            // Unnecessary vars need to be trimmed since amount of data
+            // we can pass this way is limited
+            if (!entry.getKey().equals("BOOTCLASSPATH") &&
+                !entry.getKey().equals("ANDROID_SOCKET_zygote") && 
+                !entry.getKey().equals("TMPDIR") &&
+                !entry.getKey().equals("ANDROID_BOOTLOGO") &&
+                !entry.getKey().equals("EXTERNAL_STORAGE") &&
+                !entry.getKey().equals("ANDROID_ASSETS") &&
+                !entry.getKey().equals("PATH") &&
+                !entry.getKey().equals("TERMINFO") &&
+                !entry.getKey().equals("LD_LIBRARY_PATH") &&
+                !entry.getKey().equals("ANDROID_DATA") &&
+                !entry.getKey().equals("ANDROID_PROPERTY_WORKSPACE") &&
+                !entry.getKey().equals("ANDROID_ROOT")) {
+                envstr.append(" --es env" + c + " " + entry.getKey() + "=" 
+                              + entry.getValue());
+                c++;
+            }
+        }
+        return envstr.toString();        
+    }
+
+    public void doRestart() {
+        try {
+            String action = "org.mozilla.gecko.restart" + getAppName();
+            String amCmd = "/system/bin/am broadcast -a " + action + getEnvString() + " -n org.mozilla." + getAppName() + "/org.mozilla." + getAppName() + ".Restarter";
+            Log.i("GeckoAppJava", amCmd);
+            Runtime.getRuntime().exec(amCmd);
+        } catch (Exception e) {
+            Log.i("GeckoAppJava", e.toString());
+        }
+        System.exit(0);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/embedding/android/GeckoAppShell.java
@@ -0,0 +1,219 @@
+/* -*- Mode: Java; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** 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 Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * 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 ***** */
+
+package org.mozilla.gecko;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import java.nio.*;
+
+import android.os.*;
+import android.app.*;
+import android.text.*;
+import android.view.*;
+import android.view.inputmethod.*;
+import android.content.*;
+import android.graphics.*;
+import android.widget.*;
+import android.hardware.*;
+
+import android.util.*;
+import android.content.DialogInterface; 
+
+class GeckoAppShell
+{
+    static {
+        sGeckoRunning = false;
+    }
+
+    // static members only
+    private GeckoAppShell() { }
+
+    static boolean sGeckoRunning;
+
+    static private boolean gRestartScheduled = false;
+
+    /* The Android-side API: API methods that Android calls */
+
+    // Initialization methods
+    public static native void nativeInit();
+    public static native void nativeRun(String args);
+
+    // helper methods
+    public static native void setInitialSize(int width, int height);
+    public static native void setSurfaceView(GeckoSurfaceView sv);
+    public static native void putenv(String map);
+
+    // java-side stuff
+    public static void loadGeckoLibs() {
+        // The package data lib directory isn't placed in ld.so's
+        // search path, so we have to manually load libraries that
+        // libxul will depend on.  Not ideal.
+
+        // MozAlloc
+        System.loadLibrary("mozalloc");
+
+        // NSPR
+        System.loadLibrary("nspr4");
+        System.loadLibrary("plc4");
+        System.loadLibrary("plds4");
+
+        // SQLite
+        System.loadLibrary("mozsqlite3");
+
+        // NSS
+        System.loadLibrary("nssutil3");
+        System.loadLibrary("nss3");
+        System.loadLibrary("ssl3");
+        System.loadLibrary("smime3");
+
+        // JS
+        System.loadLibrary("mozjs");
+
+        // XUL
+        System.loadLibrary("xul");
+
+        // xpcom glue -- needed to load binary components
+        System.loadLibrary("xpcom");                                          
+
+        // Root certs. someday we may teach security/manager/ssl/src/nsNSSComponent.cpp to find ckbi itself
+        System.loadLibrary("nssckbi");
+    }
+
+    public static void runGecko(String apkPath, String args, String url) {
+        // run gecko -- it will spawn its own thread
+        GeckoAppShell.nativeInit();
+
+        // Tell Gecko where the target surface view is for rendering
+        GeckoAppShell.setSurfaceView(GeckoApp.surfaceView);
+
+        sGeckoRunning = true;
+
+        // First argument is the .apk path
+        String combinedArgs = apkPath;
+        if (args != null)
+            combinedArgs += " " + args;
+        if (url != null)
+            combinedArgs += " " + url;
+        // and go
+        GeckoAppShell.nativeRun(combinedArgs);
+    }
+
+    private static GeckoEvent mLastDrawEvent;
+
+    public static void sendEventToGecko(GeckoEvent e) {
+        if (sGeckoRunning)
+            notifyGeckoOfEvent(e);
+    }
+
+    // Tell the Gecko event loop that an event is available.
+    public static native void notifyGeckoOfEvent(GeckoEvent event);
+
+    /*
+     *  The Gecko-side API: API methods that Gecko calls
+     */
+    public static void scheduleRedraw() {
+        // Redraw everything
+        scheduleRedraw(0, -1, -1, -1, -1);
+    }
+
+    public static void scheduleRedraw(int nativeWindow, int x, int y, int w, int h) {
+        GeckoEvent e;
+
+        if (x == -1) {
+            e = new GeckoEvent(GeckoEvent.DRAW, null);
+        } else {
+            e = new GeckoEvent(GeckoEvent.DRAW, new Rect(x, y, w, h));
+        }
+
+        e.mNativeWindow = nativeWindow;
+
+        sendEventToGecko(e);
+    }
+
+    public static void showIME(int state) {
+        InputMethodManager imm = (InputMethodManager) 
+            GeckoApp.surfaceView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+
+        GeckoApp.surfaceView.mIMEState = state;
+        if (state != 0)
+            imm.showSoftInput(GeckoApp.surfaceView, 0);
+        else
+            imm.hideSoftInputFromWindow(GeckoApp.surfaceView.getWindowToken(), 0);
+    }
+
+    public static void enableAccelerometer(boolean enable) {
+        SensorManager sm = (SensorManager) 
+            GeckoApp.surfaceView.getContext().getSystemService(Context.SENSOR_SERVICE);
+
+        if (enable) {
+            Sensor accelSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+            if (accelSensor == null)
+                return;
+
+            sm.registerListener(GeckoApp.surfaceView, accelSensor, SensorManager.SENSOR_DELAY_GAME);
+        } else {
+            sm.unregisterListener(GeckoApp.surfaceView);
+        }
+    }
+
+    public static void returnIMEQueryResult(String result, int selectionStart, int selectionEnd) {
+        GeckoApp.surfaceView.inputConnection.mSelectionStart = selectionStart;
+        GeckoApp.surfaceView.inputConnection.mSelectionEnd = selectionEnd;
+        try {
+            GeckoApp.surfaceView.inputConnection.mQueryResult.put(result);
+        } catch (InterruptedException e) {
+        }
+    }
+
+    static void onXreExit() {
+        sGeckoRunning = false;
+        Log.i("GeckoAppJava", "XRE exited");
+        if (gRestartScheduled) {
+            GeckoApp.mAppContext.doRestart();
+        } else {
+            Log.i("GeckoAppJava", "we're done, good bye");
+            System.exit(0);
+        }
+
+    }
+    static void scheduleRestart() {
+        Log.i("GeckoAppJava", "scheduling restart");
+        gRestartScheduled = true;        
+    }
+}
new file mode 100644
--- /dev/null
+++ b/embedding/android/GeckoEvent.java
@@ -0,0 +1,165 @@
+/* -*- Mode: Java; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** 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 Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009-2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * 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 ***** */
+
+package org.mozilla.gecko;
+
+import android.os.*;
+import android.app.*;
+import android.view.*;
+import android.content.*;
+import android.graphics.*;
+import android.widget.*;
+import android.hardware.*;
+
+import android.util.Log;
+
+/* We're not allowed to hold on to most events given to us
+ * so we save the parts of the events we want to use in GeckoEvent.
+ * Fields have different meanings depending on the event type.
+ */
+
+public class GeckoEvent {
+    public static final int INVALID = -1;
+    public static final int NATIVE_POKE = 0;
+    public static final int KEY_EVENT = 1;
+    public static final int MOTION_EVENT = 2;
+    public static final int SENSOR_EVENT = 3;
+    public static final int IME_EVENT = 4;
+    public static final int DRAW = 5;
+    public static final int SIZE_CHANGED = 6;
+    public static final int ACTIVITY_STOPPING = 7;
+
+    public static final int IME_BATCH_END = 0;
+    public static final int IME_BATCH_BEGIN = 1;
+    public static final int IME_SET_TEXT = 2;
+    public static final int IME_GET_TEXT = 3;
+    public static final int IME_DELETE_TEXT = 4;
+
+    public int mType;
+    public int mAction;
+    public long mTime;
+    public Point mP0, mP1;
+    public Rect mRect;
+    public float mX, mY, mZ;
+
+    public int mMetaState, mFlags;
+    public int mKeyCode, mUnicodeChar;
+    public int mCount, mCount2;
+    public String mCharacters;
+
+    public int mNativeWindow;
+
+    public GeckoEvent() {
+        mType = NATIVE_POKE;
+    }
+
+    public GeckoEvent(int evType) {
+        mType = evType;
+    }
+
+    public GeckoEvent(KeyEvent k) {
+        mType = KEY_EVENT;
+        mAction = k.getAction();
+        mTime = k.getEventTime();
+        mMetaState = k.getMetaState();
+        mFlags = k.getFlags();
+        mKeyCode = k.getKeyCode();
+        mUnicodeChar = k.getUnicodeChar();
+        mCharacters = k.getCharacters();
+    }
+
+    public GeckoEvent(MotionEvent m) {
+        mType = MOTION_EVENT;
+        mAction = m.getAction();
+        mTime = m.getEventTime();
+        mP0 = new Point((int)m.getX(), (int)m.getY());
+    }
+
+    public GeckoEvent(SensorEvent s) {
+        mType = SENSOR_EVENT;
+        mX = s.values[0] / SensorManager.GRAVITY_EARTH;
+        mY = s.values[1] / SensorManager.GRAVITY_EARTH;
+        mZ = s.values[2] / SensorManager.GRAVITY_EARTH;
+    }
+
+    public GeckoEvent(boolean batchEdit, String text) {
+        mType = IME_EVENT;
+        if (text != null)
+            mAction = IME_SET_TEXT;
+        else
+            mAction = batchEdit ? IME_BATCH_BEGIN : IME_BATCH_END;
+        mCharacters = text;
+    }
+
+    public GeckoEvent(boolean forward, int count) {
+        mType = IME_EVENT;
+        mAction = IME_GET_TEXT;
+        if (forward)
+            mCount = count;
+        else
+            mCount2 = count;
+    }
+
+    public GeckoEvent(int leftLen, int rightLen) {
+        mType = IME_EVENT;
+        mAction = IME_DELETE_TEXT;
+        mCount = leftLen;
+        mCount2 = rightLen;
+    }
+
+    public GeckoEvent(int etype, Rect dirty) {
+        if (etype != DRAW) {
+            mType = INVALID;
+            return;
+        }
+
+        mType = etype;
+        mRect = dirty;
+    }
+
+    public GeckoEvent(int etype, int w, int h, int oldw, int oldh) {
+        if (etype != SIZE_CHANGED) {
+            mType = INVALID;
+            return;
+        }
+
+        mType = etype;
+
+        mP0 = new Point(w, h);
+        mP1 = new Point(oldw, oldh);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/embedding/android/GeckoSurfaceView.java
@@ -0,0 +1,838 @@
+/* -*- Mode: Java; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** 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 Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * 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 ***** */
+
+package org.mozilla.gecko;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
+import java.util.zip.*;
+import java.nio.*;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGL11;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+import javax.microedition.khronos.opengles.GL;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.os.*;
+import android.app.*;
+import android.text.*;
+import android.view.*;
+import android.view.inputmethod.*;
+import android.content.*;
+import android.graphics.*;
+import android.widget.*;
+import android.hardware.*;
+
+import android.util.*;
+
+/*
+ * GeckoSurfaceView implements a GL surface view,
+ * similar to GLSurfaceView.  However, since we
+ * already have a thread for Gecko, we don't really want
+ * a separate renderer thread that GLSurfaceView provides.
+ */
+class GeckoSurfaceView
+    extends SurfaceView
+    implements SurfaceHolder.Callback, SensorEventListener
+{
+    public GeckoSurfaceView(Context context) {
+        super(context);
+
+        getHolder().addCallback(this);
+        inputConnection = new GeckoInputConnection(this);
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+
+        if (!GeckoApp.useSoftwareDrawing)
+            startEgl();
+
+        mWidth = 0;
+        mHeight = 0;
+        mBufferWidth = 0;
+        mBufferHeight = 0;
+
+        mSurfaceLock = new ReentrantLock();
+    }
+
+    protected void finalize() throws Throwable {
+        super.finalize();
+        if (!GeckoApp.useSoftwareDrawing)
+            finishEgl();
+    }
+
+    private static final int EGL_OPENGL_ES2_BIT = 4;
+    private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+
+    private void printConfig(EGL10 egl, EGLDisplay display,
+                             EGLConfig config) {
+        int[] attributes = {
+            EGL10.EGL_BUFFER_SIZE,
+            EGL10.EGL_ALPHA_SIZE,
+            EGL10.EGL_BLUE_SIZE,
+            EGL10.EGL_GREEN_SIZE,
+            EGL10.EGL_RED_SIZE,
+            EGL10.EGL_DEPTH_SIZE,
+            EGL10.EGL_STENCIL_SIZE,
+            EGL10.EGL_CONFIG_CAVEAT,
+            EGL10.EGL_CONFIG_ID,
+            EGL10.EGL_LEVEL,
+            EGL10.EGL_MAX_PBUFFER_HEIGHT,
+            EGL10.EGL_MAX_PBUFFER_PIXELS,
+            EGL10.EGL_MAX_PBUFFER_WIDTH,
+            EGL10.EGL_NATIVE_RENDERABLE,
+            EGL10.EGL_NATIVE_VISUAL_ID,
+            EGL10.EGL_NATIVE_VISUAL_TYPE,
+            0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
+            EGL10.EGL_SAMPLES,
+            EGL10.EGL_SAMPLE_BUFFERS,
+            EGL10.EGL_SURFACE_TYPE,
+            EGL10.EGL_TRANSPARENT_TYPE,
+            EGL10.EGL_TRANSPARENT_RED_VALUE,
+            EGL10.EGL_TRANSPARENT_GREEN_VALUE,
+            EGL10.EGL_TRANSPARENT_BLUE_VALUE,
+            0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
+            0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
+            0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
+            0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
+            EGL10.EGL_LUMINANCE_SIZE,
+            EGL10.EGL_ALPHA_MASK_SIZE,
+            EGL10.EGL_COLOR_BUFFER_TYPE,
+            EGL10.EGL_RENDERABLE_TYPE,
+            0x3042 // EGL10.EGL_CONFORMANT
+        };
+        String[] names = {
+            "EGL_BUFFER_SIZE",
+            "EGL_ALPHA_SIZE",
+            "EGL_BLUE_SIZE",
+            "EGL_GREEN_SIZE",
+            "EGL_RED_SIZE",
+            "EGL_DEPTH_SIZE",
+            "EGL_STENCIL_SIZE",
+            "EGL_CONFIG_CAVEAT",
+            "EGL_CONFIG_ID",
+            "EGL_LEVEL",
+            "EGL_MAX_PBUFFER_HEIGHT",
+            "EGL_MAX_PBUFFER_PIXELS",
+            "EGL_MAX_PBUFFER_WIDTH",
+            "EGL_NATIVE_RENDERABLE",
+            "EGL_NATIVE_VISUAL_ID",
+            "EGL_NATIVE_VISUAL_TYPE",
+            "EGL_PRESERVED_RESOURCES",
+            "EGL_SAMPLES",
+            "EGL_SAMPLE_BUFFERS",
+            "EGL_SURFACE_TYPE",
+            "EGL_TRANSPARENT_TYPE",
+            "EGL_TRANSPARENT_RED_VALUE",
+            "EGL_TRANSPARENT_GREEN_VALUE",
+            "EGL_TRANSPARENT_BLUE_VALUE",
+            "EGL_BIND_TO_TEXTURE_RGB",
+            "EGL_BIND_TO_TEXTURE_RGBA",
+            "EGL_MIN_SWAP_INTERVAL",
+            "EGL_MAX_SWAP_INTERVAL",
+            "EGL_LUMINANCE_SIZE",
+            "EGL_ALPHA_MASK_SIZE",
+            "EGL_COLOR_BUFFER_TYPE",
+            "EGL_RENDERABLE_TYPE",
+            "EGL_CONFORMANT"
+        };
+        int[] value = new int[1];
+        for (int i = 0; i < attributes.length; i++) {
+            int attribute = attributes[i];
+            String name = names[i];
+            if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
+                Log.w("GeckoAppJava", String.format("  %s: %d\n", name, value[0]));
+            } else {
+                Log.w("GeckoAppJava", String.format("  %s: failed\n", name));
+                // while (egl.eglGetError() != EGL10.EGL_SUCCESS);
+            }
+        }
+    }
+
+    public void startEgl() {
+        if (mEgl != null)
+            return;
+
+        mEgl = (EGL10) EGLContext.getEGL();
+        mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+
+        // initialize egl
+        int[] version = new int[2];
+        mEgl.eglInitialize(mEglDisplay, version);
+
+        // flip this to true to dump all the EGL configs
+        if (false) {
+            int[] cs = { EGL10.EGL_NONE };
+            int[] ptrnum = new int[1];
+
+            mEgl.eglChooseConfig(mEglDisplay, cs, null, 0, ptrnum);
+
+            int num = ptrnum[0];
+            EGLConfig[] confs = new EGLConfig[num];
+
+            mEgl.eglChooseConfig(mEglDisplay, cs, confs, num, ptrnum);
+
+            for (int i = 0; i < num; ++i) {
+                Log.w("GeckoAppJava", "===  EGL config " + i + " ===");
+                printConfig(mEgl, mEglDisplay, confs[i]);
+            }
+        }
+    }
+
+    public void finishEgl() {
+        if (mEglDisplay != null) {
+            mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
+                                EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+        }
+
+        if (mEglContext != null) {
+            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+            mEglContext = null;
+        }
+
+        if (mEglSurface != null) {
+            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+            mEglSurface = null;
+        }
+
+        if (mEglDisplay != null) {
+            mEgl.eglTerminate(mEglDisplay);
+            mEglDisplay = null;
+        }
+
+        mEglConfig = null;
+        mEgl = null;
+
+        mSurfaceChanged = false;
+    }
+
+    public void chooseEglConfig() {
+        int redBits, greenBits, blueBits, alphaBits;
+
+        // There are some shenanigans here.
+        // We're required to choose an exact EGL config to match
+        // the surface format, or we get an error.  However,
+        // on Droid at least, the format is -1, which is PixelFormat.OPAQUE.
+        // That's not a valid format to be reported; that should just be a
+        // valid value for *setFormat*.  We have a catch-all case that
+        // assumes 565 for those cases, but it's pretty ugly.
+
+        Log.i("GeckoAppJava", "GeckoView PixelFormat format is " + mFormat);
+        if (mFormat == PixelFormat.RGB_565) {
+            redBits = 5;
+            greenBits = 6;
+            blueBits = 5;
+            alphaBits = 0;
+        } else if (mFormat == PixelFormat.RGB_888 ||
+                   mFormat == PixelFormat.RGBX_8888)
+        {
+            redBits = 8;
+            greenBits = 8;
+            blueBits = 8;
+            alphaBits = 0;
+        } else if (mFormat == PixelFormat.RGBA_8888) {
+            redBits = 8;
+            greenBits = 8;
+            blueBits = 8;
+            alphaBits = 8;
+        } else {
+            Log.w("GeckoAppJava", "Unknown PixelFormat for surface (format is " + mFormat + "), assuming 5650!");
+            redBits = 5;
+            greenBits = 6;
+            blueBits = 5;
+            alphaBits = 0;
+        }
+
+        // PowerVR SGX (Droid) seems to really want depth == 24 for
+        // performance, even 0 is slower.  However, other platforms,
+        // like Tegra, don't -have- a 24 bit depth config (have 16).
+        // So that's not good.  We'll try with 24 first, and if
+        // nothing, then we'll go to 0.  I'm not sure what the nexus
+        // one chip wants.
+
+        int[] confSpec = new int[] {
+            // DEPTH_SIZE must be the first pair
+            EGL10.EGL_DEPTH_SIZE, 24,
+            EGL10.EGL_RED_SIZE, redBits,
+            EGL10.EGL_GREEN_SIZE, greenBits,
+            EGL10.EGL_BLUE_SIZE, blueBits,
+            EGL10.EGL_ALPHA_SIZE, alphaBits,
+            EGL10.EGL_STENCIL_SIZE, 0,
+            EGL10.EGL_CONFIG_CAVEAT, EGL10.EGL_NONE,
+            EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+            EGL10.EGL_NONE };
+
+        // so tortured to pass an int as an out param...
+        int[] ptrNumConfigs = new int[1];
+        mEgl.eglChooseConfig(mEglDisplay, confSpec, null, 0, ptrNumConfigs);
+
+        int numConfigs = ptrNumConfigs[0];
+
+        if (numConfigs == 0) {
+            // twiddle the DEPTH_SIZE value
+            confSpec[1] = 0;
+            Log.i("GeckoAppJava", "Couldn't find any valid EGL configs with 24 bit depth, trying 0.");
+
+            mEgl.eglChooseConfig(mEglDisplay, confSpec, null, 0, ptrNumConfigs);
+            numConfigs = ptrNumConfigs[0];
+        }
+
+        if (numConfigs <= 0) {
+            // couldn't find a config?
+            Log.w("GeckoAppJava", "Couldn't find any valid EGL configs, blindly trying them all!");
+
+            int[] fallbackConfSpec = new int[] {
+                EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+                EGL10.EGL_NONE };
+            confSpec = fallbackConfSpec;
+
+            mEgl.eglChooseConfig(mEglDisplay, confSpec, null, 0, ptrNumConfigs);
+            numConfigs = ptrNumConfigs[0];
+
+            if (numConfigs == 0) {
+                Log.e("GeckoAppJava", "There aren't any EGL configs available on this system.");
+                finishEgl();
+                mSurfaceValid = false;
+                return;
+            }
+        }
+
+        EGLConfig[] configs = new EGLConfig[numConfigs];
+        mEgl.eglChooseConfig(mEglDisplay, confSpec, configs, numConfigs, ptrNumConfigs);
+
+        // Find the first config that has the exact RGB sizes that we
+        // need for our window surface.
+        int[] ptrVal = new int[1];
+        for (int i = 0; i < configs.length; ++i) {
+            int confRed = -1, confGreen = -1, confBlue = -1, confAlpha = -1;
+
+            if (mEgl.eglGetConfigAttrib(mEglDisplay, configs[i], EGL10.EGL_RED_SIZE, ptrVal))
+                confRed = ptrVal[0];
+            if (mEgl.eglGetConfigAttrib(mEglDisplay, configs[i], EGL10.EGL_GREEN_SIZE, ptrVal))
+                confGreen = ptrVal[0];
+            if (mEgl.eglGetConfigAttrib(mEglDisplay, configs[i], EGL10.EGL_BLUE_SIZE, ptrVal))
+                confBlue = ptrVal[0];
+            if (mEgl.eglGetConfigAttrib(mEglDisplay, configs[i], EGL10.EGL_ALPHA_SIZE, ptrVal))
+                confAlpha = ptrVal[0];
+
+            if (confRed == redBits &&
+                confGreen == greenBits &&
+                confBlue == blueBits &&
+                confAlpha == alphaBits)
+            {
+                mEglConfig = configs[i];
+                break;
+            }
+        }
+
+        if (mEglConfig == null) {
+            Log.w("GeckoAppJava", "Couldn't find EGL config matching colors; using first, hope it works!");
+            mEglConfig = configs[0];
+        }
+
+        Log.i("GeckoAppJava", "====== Chosen config: ======");
+        printConfig(mEgl, mEglDisplay, mEglConfig);
+
+        mEglContext = null;
+        mEglSurface = null;
+    }
+
+    /*
+     * Called on main thread
+     */
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        mSurfaceLock.lock();
+
+        try {
+            if (mInDrawing) {
+                Log.w("GeckoAppJava", "surfaceChanged while mInDrawing is true!");
+            }
+
+            mFormat = format;
+            mWidth = width;
+            mHeight = height;
+            mSurfaceValid = true;
+
+            Log.i("GeckoAppJava", "surfaceChanged: fmt: " + format + " dim: " + width + " " + height);
+
+            if (!GeckoApp.useSoftwareDrawing) {
+                chooseEglConfig();
+            }
+
+            // XXX This code doesn't seem to actually get hit
+            if (!GeckoAppShell.sGeckoRunning) {
+                GeckoAppShell.setInitialSize(width, height);
+                return;
+            }
+
+            GeckoEvent e = new GeckoEvent(GeckoEvent.SIZE_CHANGED, width, height, -1, -1);
+            GeckoAppShell.sendEventToGecko(e);
+
+            if (mSurfaceNeedsRedraw) {
+                GeckoAppShell.scheduleRedraw();
+                mSurfaceNeedsRedraw = false;
+            }
+
+            mSurfaceChanged = true;
+
+            //Log.i("GeckoAppJava", "<< surfaceChanged");
+        } finally {
+            mSurfaceLock.unlock();
+        }
+    }
+ 
+    public void surfaceCreated(SurfaceHolder holder) {
+        if (GeckoAppShell.sGeckoRunning)
+            mSurfaceNeedsRedraw = true;
+    }
+ 
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        Log.i("GeckoAppJava", "surface destroyed");
+        mSurfaceValid = false;
+    }
+
+    public ByteBuffer getSoftwareDrawBuffer() {
+        //#ifdef DEBUG
+        if (!mSurfaceLock.isHeldByCurrentThread())
+            Log.e("GeckoAppJava", "getSoftwareDrawBuffer called outside of mSurfaceLock!");
+        //#endif
+
+        return mSoftwareBuffer;
+    }
+
+    /*
+     * Called on Gecko thread
+     */
+
+    public static final int DRAW_ERROR = 0;
+    public static final int DRAW_GLES_2 = 1;
+    public static final int DRAW_SOFTWARE = 2;
+
+    int innerBeginDrawing() {
+        /*
+         * Software (non-GL) rendering
+         */
+        if (GeckoApp.useSoftwareDrawing) {
+            if (mWidth != mBufferWidth ||
+                mHeight != mBufferHeight ||
+                mSurfaceChanged)
+            {
+                if (mWidth*mHeight != mBufferWidth*mBufferHeight)
+                    mSoftwareBuffer = ByteBuffer.allocateDirect(mWidth*mHeight*4);
+
+                mSoftwareBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
+
+                mBufferWidth = mWidth;
+                mBufferHeight = mHeight;
+                mSurfaceChanged = false;
+            }
+
+            mSoftwareCanvas = getHolder().lockCanvas(null);
+            if (mSoftwareCanvas == null) {
+                Log.e("GeckoAppJava", "lockCanvas failed! << beginDrawing");
+                return DRAW_ERROR;
+            }
+
+            return DRAW_SOFTWARE;
+        }
+
+        /*
+         * GL rendering
+         */
+
+        if (mEgl == null || mEglDisplay == null || mEglConfig == null) {
+            Log.e("GeckoAppJava", "beginDrawing called, but EGL was never initialized!");
+
+            mSurfaceLock.unlock();
+            return DRAW_ERROR;
+        }
+
+        /*
+         * If the surface doesn't exist, or if its dimensions or something else changed,
+         * recreate it.
+         */
+        if (mEglSurface == null ||
+            mWidth != mBufferWidth ||
+            mHeight != mBufferHeight ||
+            mSurfaceChanged)
+        {
+            if (mEglContext != null) {
+                mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+                mEglContext = null;
+            }
+
+            if (mEglSurface != null)
+                mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+
+            mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, getHolder(), null);
+            if (mEglSurface == EGL10.EGL_NO_SURFACE)
+            {
+                Log.e("GeckoAppJava", "eglCreateWindowSurface failed!");
+                mSurfaceValid = false;
+                return DRAW_ERROR;
+            }
+
+            mBufferWidth = mWidth;
+            mBufferHeight = mHeight;
+
+            mSurfaceChanged = false;
+        }
+
+        if (mEglContext == null) {
+            int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2,
+                                  EGL10.EGL_NONE };
+            mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+            if (mEglContext == EGL10.EGL_NO_CONTEXT)
+            {
+                Log.e("GeckoAppJava", "eglCreateContext failed! " + mEgl.eglGetError());
+                mSurfaceValid = false;
+                return DRAW_ERROR;
+            }
+
+            Log.i("GeckoAppJava", "EglContext created");
+        }
+
+        // Hmm, should we issue this makecurrent for each frame?
+        // We'll likely have to, as other bits might switch the context (e.g.
+        // WebGL, video, etc.).
+
+        if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+            int err = mEgl.eglGetError();
+            Log.e("GeckoAppJava", "eglMakeCurrent failed! " + err);
+            return DRAW_ERROR;
+        }
+
+        return DRAW_GLES_2;
+    }
+
+    public int beginDrawing() {
+        //Log.i("GeckoAppJava", ">> beginDrawing");
+
+        if (mInDrawing) {
+            Log.e("GeckoAppJava", "Recursive beginDrawing call!");
+            return DRAW_ERROR;
+        }
+
+        /* Grab the lock, which we'll hold while we're drawing.
+         * It gets released in endDrawing(), and is also used in surfaceChanged
+         * to make sure that we don't change our surface details while
+         * we're in the middle of drawing (and especially in the middle of
+         * executing beginDrawing/endDrawing).
+         *
+         * We might not need to hold this lock in between
+         * beginDrawing/endDrawing, and might just be able to make
+         * surfaceChanged, beginDrawing, and endDrawing synchronized,
+         * but this way is safer for now.
+         */
+        mSurfaceLock.lock();
+
+        if (!mSurfaceValid) {
+            Log.e("GeckoAppJava", "Surface not valid");
+            mSurfaceLock.unlock();
+            return DRAW_ERROR;
+        }
+
+        // call the inner function to do the work, so we can sanely unlock on error
+        int result = innerBeginDrawing();
+
+        if (result == DRAW_ERROR) {
+            mSurfaceLock.unlock();
+            return DRAW_ERROR;
+        }
+
+        mInDrawing = true;
+        return result;
+    }
+
+    public void endDrawing() {
+        //Log.w("GeckoAppJava", ">> endDrawing");
+
+        if (!mInDrawing) {
+            Log.e("GeckoAppJava", "endDrawing without beginDrawing!");
+            return;
+        }
+
+        try {
+            if (!mSurfaceValid) {
+                Log.e("GeckoAppJava", "endDrawing with false mSurfaceValid");
+                return;
+            }
+
+            if (GeckoApp.useSoftwareDrawing) {
+                if (!mSurfaceChanged) {
+                    mSoftwareBitmap.copyPixelsFromBuffer(mSoftwareBuffer);
+                    mSoftwareCanvas.drawBitmap(mSoftwareBitmap, 0, 0, null);
+
+                    getHolder().unlockCanvasAndPost(mSoftwareCanvas);
+                    mSoftwareCanvas = null;
+                }
+            } else {
+                // If the surface was changed while we were drawing;
+                // don't even bother trying to swap, it won't work,
+                // and may cause further problems.  Note that
+                // eglSwapBuffers might also throw an
+                // IllegalArgumentException; we catch that as well.
+                if (!mSurfaceChanged) {
+                    mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
+                    if (mEgl.eglGetError() == EGL11.EGL_CONTEXT_LOST)
+                        mSurfaceChanged = true;
+                }
+            }
+        } catch (java.lang.IllegalArgumentException ex) {
+            mSurfaceChanged = true;
+        } finally {
+            mInDrawing = false;
+
+            //#ifdef DEBUG
+            if (!mSurfaceLock.isHeldByCurrentThread())
+                Log.e("GeckoAppJava", "endDrawing while mSurfaceLock not held by current thread!");
+            //#endif
+
+            mSurfaceLock.unlock();
+        }
+    }
+
+    @Override
+    public boolean onCheckIsTextEditor () {
+        return false;
+    }
+
+    @Override
+    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+        outAttrs.inputType = InputType.TYPE_CLASS_TEXT |
+                             InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
+        return inputConnection;
+    }
+
+    public void onAccuracyChanged(Sensor sensor, int accuracy)
+    {
+    }
+
+    public void onSensorChanged(SensorEvent event)
+    {
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
+    }
+
+    // event stuff
+    public boolean onTouchEvent(MotionEvent event) {
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
+        return true;
+    }
+
+    // Is this surface valid for drawing into?
+    boolean mSurfaceValid;
+
+    // Do we need to force a redraw on surfaceChanged?
+    boolean mSurfaceNeedsRedraw;
+
+    // Has this surface been changed?  (That is,
+    // do we need to recreate buffers?)
+    boolean mSurfaceChanged;
+
+    // Are we actively between beginDrawing/endDrawing?
+    boolean mInDrawing;
+
+    // let's not change stuff around while we're in the middle of
+    // starting drawing, ending drawing, or changing surface
+    // characteristics
+    ReentrantLock mSurfaceLock;
+
+    // Surface format, from surfaceChanged.  Largely
+    // useless.
+    int mFormat;
+
+    // the dimensions of the surface
+    int mWidth;
+    int mHeight;
+
+    // the dimensions of the buffer we're using for drawing,
+    // that is the software buffer or the EGLSurface
+    int mBufferWidth;
+    int mBufferHeight;
+
+    // IME stuff
+    GeckoInputConnection inputConnection;
+    int mIMEState;
+
+    // Software rendering
+    ByteBuffer mSoftwareBuffer;
+    Bitmap mSoftwareBitmap;
+    Canvas mSoftwareCanvas;
+
+    // GL rendering
+    EGL10 mEgl;
+    EGLDisplay mEglDisplay;
+    EGLSurface mEglSurface;
+    EGLConfig mEglConfig;
+    EGLContext mEglContext;
+}
+
+class GeckoInputConnection
+    extends BaseInputConnection
+{
+    public GeckoInputConnection (View targetView) {
+        super(targetView, true);
+        mQueryResult = new SynchronousQueue<String>();
+        mExtractedText.partialStartOffset = -1;
+        mExtractedText.partialEndOffset = -1;
+    }
+
+    @Override
+    public Editable getEditable() {
+        Log.i("GeckoAppJava", "getEditable");
+        return null;
+    }
+
+    @Override
+    public boolean beginBatchEdit() {
+        if (mComposing)
+            return true;
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(true, null));
+        mComposing = true;
+        return true;
+    }
+    @Override
+    public boolean commitCompletion(CompletionInfo text) {
+        Log.i("GeckoAppJava", "Stub: commitCompletion");
+        return true;
+    }
+    @Override
+    public boolean commitText(CharSequence text, int newCursorPosition) {
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(true, text.toString()));
+        endBatchEdit();
+        return true;
+    }
+    @Override
+    public boolean deleteSurroundingText(int leftLength, int rightLength) {
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(leftLength, rightLength));
+        updateExtractedText();
+        return true;
+    }
+    @Override
+    public boolean endBatchEdit() {
+        updateExtractedText();
+        if (!mComposing)
+            return true;
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(false, null));
+        mComposing = false;
+        return true;
+    }
+    @Override
+    public boolean finishComposingText() {
+        endBatchEdit();
+        return true;
+    }
+    @Override
+    public int getCursorCapsMode(int reqModes) {
+        return 0;
+    }
+    @Override
+    public ExtractedText getExtractedText(ExtractedTextRequest req, int flags) {
+        mExtractToken = req.token;
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(false, 0));
+        try {
+            mExtractedText.text = mQueryResult.take();
+            mExtractedText.selectionStart = mSelectionStart;
+            mExtractedText.selectionEnd = mSelectionEnd;
+        } catch (InterruptedException e) {
+            Log.i("GeckoAppJava", "getExtractedText: Interrupted!");
+        }
+        return mExtractedText;
+    }
+    @Override
+    public CharSequence getTextAfterCursor(int length, int flags) {
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(true, length));
+        try {
+            String result = mQueryResult.take();
+            return result;
+        } catch (InterruptedException e) {
+            Log.i("GeckoAppJava", "getTextAfterCursor: Interrupted!");
+        }
+        return null;
+    }
+    @Override
+    public CharSequence getTextBeforeCursor(int length, int flags) {
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(false, length));
+        try {
+            String result = mQueryResult.take();
+            return result;
+        } catch (InterruptedException e) {
+            Log.i("GeckoAppJava", "getTextBeforeCursor: Interrupted!");
+        }
+        return null;
+    }
+    @Override
+    public boolean setComposingText(CharSequence text, int newCursorPosition) {
+        beginBatchEdit();
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(true, text.toString()));
+        return true;
+    }
+    @Override
+    public boolean setSelection(int start, int end) {
+        Log.i("GeckoAppJava", "Stub: setSelection " + start + " " + end);
+        return true;
+    }
+
+    private void updateExtractedText() {
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(false, 0));
+        try {
+            mExtractedText.text = mQueryResult.take();
+            mExtractedText.selectionStart = mSelectionStart;
+            mExtractedText.selectionEnd = mSelectionEnd;
+        } catch (InterruptedException e) {
+            Log.i("GeckoAppJava", "getExtractedText: Interrupted!");
+        }
+
+        InputMethodManager imm = (InputMethodManager)
+            GeckoApp.surfaceView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+        imm.updateExtractedText(GeckoApp.surfaceView, mExtractToken, mExtractedText);
+    }
+
+    boolean mComposing;
+    int mExtractToken;
+    final ExtractedText mExtractedText = new ExtractedText();
+
+    int mSelectionStart, mSelectionEnd;
+    SynchronousQueue<String> mQueryResult;
+}
new file mode 100644
--- /dev/null
+++ b/embedding/android/Makefile.in
@@ -0,0 +1,182 @@
+# ***** 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 the Mozilla browser.
+#
+# The Initial Developer of the Original Code is
+#   Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2009-2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Vladimir Vukicevic <vladimir@pobox.com>
+#
+# 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 *****
+
+DEPTH		= ../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DX=$(ANDROID_SDK)/tools/dx
+AAPT=$(ANDROID_SDK)/tools/aapt
+APKBUILDER=$(ANDROID_SDK)/../../tools/apkbuilder
+ZIPALIGN=$(ANDROID_SDK)/../../tools/zipalign
+
+JAVAFILES = \
+  GeckoApp.java \
+  GeckoAppShell.java \
+  GeckoEvent.java \
+  GeckoSurfaceView.java \
+  $(NULL)
+
+DEFINES += \
+  -DMOZ_APP_DISPLAYNAME=$(MOZ_APP_DISPLAYNAME) \
+  -DMOZ_APP_NAME=$(MOZ_APP_NAME)
+
+GARBAGE += \
+  AndroidManifest.xml  \
+  classes.dex  \
+  $(MOZ_APP_NAME).apk  \
+  App.java \
+  Restarter.java \
+  gecko.ap_  \
+  gecko-unaligned.apk  \
+  gecko-unsigned-unaligned.apk \
+  $(NULL)
+
+GARBAGE_DIRS += res libs dist classes
+
+ifdef JARSIGNER
+  APKBUILDER_FLAGS += -u
+endif
+
+# Bug 567884 - Need a way to find appropriate icons during packaging
+ifeq ($(MOZ_APP_NAME),fennec)
+ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_48x48.png
+ICON_PATH_HI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_72x72.png
+else
+ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon48.png
+ICON_PATH_HI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon64.png
+endif
+
+NATIVE_LIBS = $(shell cat $(DIST)/bin/dependentlibs.list) libxpcom.so libnssckbi.so libfreebl3.so
+FULL_LIBS = $(addprefix libs/armeabi/,$(NATIVE_LIBS))
+
+# We'll strip all the libs by default, due to size, but we might
+# want to have a non-stripped version for debugging.  We should
+# really pull out debuginfo and stuff.
+ifdef NO_STRIP
+DO_STRIP=echo not stripping
+else
+DO_STRIP=$(STRIP)
+endif
+
+# The set of files/directories from the dist/bin dir that we'll make available in the apk
+# some directories not listed due to special handling
+DIST_LINK_FILES = \
+  modules \
+  res \
+  application.ini \
+  platform.ini \
+  greprefs.js \
+  browserconfig.properties \
+  blocklist.xml \
+  $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+# rules.mk has some java stuff, but we're going to ignore it for now
+JAVAC_FLAGS = \
+  -target 1.5 \
+  -classpath $(ANDROID_SDK)/android.jar \
+  -bootclasspath $(ANDROID_SDK)/android.jar \
+  -encoding ascii \
+  -g \
+  $(NULL)
+
+tools:: $(MOZ_APP_NAME).apk
+
+# Note that we're going to set up a dependency directly between embed_android.dex and the java files
+# Instead of on the .class files, since more than one .class file might be produced per .java file
+classes.dex: $(JAVAFILES) App.java Restarter.java
+	$(NSINSTALL) -D classes
+	$(JAVAC) $(JAVAC_FLAGS) -d classes  $(addprefix $(srcdir)/,$(JAVAFILES)) App.java Restarter.java
+	$(DX) --dex --output=$@ classes
+
+AndroidManifest.xml App.java Restarter.java : % : %.in
+	$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
+             $(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
+
+res/drawable/icon.png: $(MOZ_APP_ICON)
+	$(NSINSTALL) -D res/drawable
+	cp $(ICON_PATH) $@
+
+res/drawable-hdpi/icon.png: $(MOZ_APP_ICON)
+	$(NSINSTALL) -D res/drawable-hdpi
+	cp $(ICON_PATH_HI) $@
+
+gecko.ap_: AndroidManifest.xml res/drawable/icon.png res/drawable-hdpi/icon.png
+	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar  -S res -F $@
+
+libs/armeabi/%: $(DIST)/lib/%
+	@$(NSINSTALL) -D libs/armeabi
+	@cp -L -v $< $@
+	@$(DO_STRIP) $@
+
+# Bug 567873 - Android packaging should use standard packaging code
+dist: FORCE
+	$(NSINSTALL) -D dist/components
+	rm -f dist/components/*
+	@(for f in $(DIST)/bin/components/* ; do ln -sf ../../$$f dist/components ; done)
+	$(DIST)/host/bin/host_xpt_link gecko.xpt dist/components/*.xpt
+	rm dist/components/*.xpt
+	mv gecko.xpt dist/components
+	$(NSINSTALL) -D dist/chrome
+	rm -f dist/chrome/*
+	@(for f in $(DIST)/bin/chrome/* ; do ln -sf ../../$$f dist/chrome ; done)
+	@(for MANIFEST in dist/chrome/*.manifest ; do cat "$$MANIFEST" >> chrome.manifest ; echo >> chrome.manifest; rm "$$MANIFEST" ; done )
+	mv chrome.manifest dist/chrome/
+	$(NSINSTALL) -D dist/defaults
+	rm -f dist/defaults/*
+	@(for f in $(DIST)/bin/defaults/* ; do ln -sf ../../$$f dist/defaults ; done )
+	@(for PREF in $(DIST)/bin/defaults/pref/*.js ; do cat "$$PREF" >> dist/defaults/prefs.js ; echo >> dist/defaults/prefs.js ; done )
+	rm dist/defaults/pref
+	@(for f in $(DIST_LINK_FILES) ; do if [ -e $(DIST)/bin/$$f ] ; then echo $$f ; ln -sf ../$(DIST)/bin/$$f dist ; fi ; done)
+
+gecko-unsigned-unaligned.apk: gecko.ap_ classes.dex dist $(FULL_LIBS)
+	$(APKBUILDER) $@ -v $(APKBUILDER_FLAGS) -z gecko.ap_ -f classes.dex -nf `pwd`/libs -rf dist
+
+gecko-unaligned.apk: gecko-unsigned-unaligned.apk
+	cp gecko-unsigned-unaligned.apk $@
+ifdef JARSIGNER
+	$(JARSIGNER) $@
+endif
+
+$(MOZ_APP_NAME).apk: gecko-unaligned.apk
+	$(ZIPALIGN) -f -v 4 gecko-unaligned.apk $@
+
new file mode 100644
--- /dev/null
+++ b/embedding/android/Restarter.java.in
@@ -0,0 +1,91 @@
+/* -*- Mode: Java; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** 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 Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brad Lassey <blassey@mozilla.com>
+ *
+ * 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 ***** */
+
+#filter substitution
+package org.mozilla.@MOZ_APP_NAME@;
+
+import android.content.*;
+import android.util.Log;
+import java.io.*;
+
+public class Restarter extends BroadcastReceiver {
+    @Override 
+    public void onReceive(Context context, Intent intent) {
+        Log.i("Restarter", "trying to restart @MOZ_APP_NAME@");
+        try { 
+            boolean stillRunning;
+            do {
+                stillRunning = false;
+                Process p = Runtime.getRuntime().exec("/system/bin/ps");
+                BufferedReader psOut = new BufferedReader(new InputStreamReader(p.getInputStream()));
+                String line;
+                Log.i("Restarter", "pid: " + new Integer(android.os.Process.myPid()).toString());
+                while((line = psOut.readLine()) != null) {
+                    Log.i("Restarter", "ps: " + line);
+                    if (line.contains("org.mozilla.@MOZ_APP_NAME@.App")){
+                        if (!line.contains(new Integer(android.os.Process.myPid()).toString())){
+                            Log.i("Restarter", "app still running, wait a bit");
+                            stillRunning = true;
+                            Thread.sleep(500);
+                            break; // don't need to look at the rest
+                        } else {
+                            Log.i("Restarter", "found ourselves");
+                        }
+                    }
+                }
+            } while(stillRunning);
+        } catch (Exception e) {
+                Log.i("Restarter", e.toString());
+        }
+        try {
+            String action = "android.intent.action.MAIN";
+            String env;
+            StringBuffer envstr = new StringBuffer();
+            for (int c = 0; (env = intent.getStringExtra("env" + c)) != null; c++) {
+                envstr.append(" --es env" + c + " " + env);
+            }
+            String amCmd = "/system/bin/am start -a " + action + envstr.toString() + 
+                " -n org.mozilla.@MOZ_APP_NAME@/org.mozilla.@MOZ_APP_NAME@.App";
+            Log.i("Restarter", amCmd);
+
+            Runtime.getRuntime().exec(amCmd);
+        } catch (Exception e) {
+            Log.i("Restarter", e.toString());
+        }
+        System.exit(0);    
+    }
+};
--- a/extensions/spellcheck/hunspell/src/mozHunspell.cpp
+++ b/extensions/spellcheck/hunspell/src/mozHunspell.cpp
@@ -70,20 +70,31 @@
 #include "nsUnicharUtilCIID.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include <stdlib.h>
 
 static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
 static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
 
-NS_IMPL_ISUPPORTS3(mozHunspell,
-                   mozISpellCheckingEngine,
-                   nsIObserver,
-                   nsISupportsWeakReference)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(mozHunspell)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(mozHunspell)
+
+NS_INTERFACE_MAP_BEGIN(mozHunspell)
+  NS_INTERFACE_MAP_ENTRY(mozISpellCheckingEngine)
+  NS_INTERFACE_MAP_ENTRY(nsIObserver)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellCheckingEngine)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozHunspell)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_3(mozHunspell,
+                           mPersonalDictionary,
+                           mEncoder,
+                           mDecoder)
 
 nsresult
 mozHunspell::Init()
 {
   if (!mDictionaries.Init())
     return NS_ERROR_OUT_OF_MEMORY;
 
   LoadDictionaryList();
--- a/extensions/spellcheck/hunspell/src/mozHunspell.h
+++ b/extensions/spellcheck/hunspell/src/mozHunspell.h
@@ -64,31 +64,33 @@
 #include "mozIPersonalDictionary.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIObserver.h"
 #include "nsIUnicodeEncoder.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsInterfaceHashtable.h"
 #include "nsWeakReference.h"
+#include "nsCycleCollectionParticipant.h"
 
 #define MOZ_HUNSPELL_CONTRACTID "@mozilla.org/spellchecker/engine;1"
 #define MOZ_HUNSPELL_CID         \
 /* 56c778e4-1bee-45f3-a689-886692a97fe7 */   \
 { 0x56c778e4, 0x1bee, 0x45f3, \
   { 0xa6, 0x89, 0x88, 0x66, 0x92, 0xa9, 0x7f, 0xe7 } }
 
 class mozHunspell : public mozISpellCheckingEngine,
                    public nsIObserver,
                    public nsSupportsWeakReference
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_MOZISPELLCHECKINGENGINE
   NS_DECL_NSIOBSERVER
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(mozHunspell, mozISpellCheckingEngine)
 
   mozHunspell() : mHunspell(nsnull) { }
   virtual ~mozHunspell();
 
   nsresult Init();
 
   void LoadDictionaryList();
   void LoadDictionariesFromDir(nsIFile* aDir);
--- a/extensions/spellcheck/osxspell/src/mozOSXSpell.h
+++ b/extensions/spellcheck/osxspell/src/mozOSXSpell.h
@@ -40,30 +40,32 @@
 
 #ifndef mozOSXSpell_h__
 #define mozOSXSpell_h__
 
 #include "mozISpellCheckingEngine.h"
 #include "mozIPersonalDictionary.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
+#include "nsCycleCollectionParticipant.h"
 
 // Use the same contract ID as the Hunspell spellchecker so we get picked up
 // instead on Mac OS X but we have our own CID. 
 #define MOZ_OSXSPELL_CONTRACTID "@mozilla.org/spellchecker/engine;1"
 #define MOZ_OSXSPELL_CID         \
 { /* BAABBAF4-71C3-47F4-A576-E75469E485E2 */  \
 0xBAABBAF4, 0x71C3, 0x47F4,                    \
 { 0xA5, 0x76, 0xE7, 0x54, 0x69, 0xE4, 0x85, 0xE2} }
 
 class mozOSXSpell : public mozISpellCheckingEngine
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_MOZISPELLCHECKINGENGINE
+  NS_DECL_CYCLE_COLLECTION_CLASS(mozOSXSpell)
 
   mozOSXSpell();
 
 private:
  
   ~mozOSXSpell();
 
   // NSSpellChecker provides the ability to add words to the local dictionary,
--- a/extensions/spellcheck/osxspell/src/mozOSXSpell.mm
+++ b/extensions/spellcheck/osxspell/src/mozOSXSpell.mm
@@ -47,17 +47,26 @@
 
 // utility category we need for PRUnichar<->NSString conversion (taken from Camino)
 @interface NSString(PRUnicharUtils)
 + (id)stringWithPRUnichars:(const PRUnichar*)inString;
 - (PRUnichar*)createNewUnicodeBuffer;
 @end
 
 
-NS_IMPL_ISUPPORTS1(mozOSXSpell, mozISpellCheckingEngine)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(mozOSXSpell)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(mozOSXSpell)
+
+NS_INTERFACE_MAP_BEGIN(mozOSXSpell)
+  NS_INTERFACE_MAP_ENTRY(mozISpellCheckingEngine)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellCheckingEngine)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozOSXSpell)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_1(mozOSXSpell, mPersonalDictionary);
 
 mozOSXSpell::mozOSXSpell()
 {
 }
 
 mozOSXSpell::~mozOSXSpell()
 {
 }
--- a/extensions/spellcheck/src/mozEnglishWordUtils.cpp
+++ b/extensions/spellcheck/src/mozEnglishWordUtils.cpp
@@ -37,17 +37,29 @@
 
 #include "mozEnglishWordUtils.h"
 #include "nsICharsetAlias.h"
 #include "nsReadableUtils.h"
 #include "nsIServiceManager.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsCRT.h"
 
-NS_IMPL_ISUPPORTS1(mozEnglishWordUtils, mozISpellI18NUtil)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(mozEnglishWordUtils)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(mozEnglishWordUtils)
+
+NS_INTERFACE_MAP_BEGIN(mozEnglishWordUtils)
+  NS_INTERFACE_MAP_ENTRY(mozISpellI18NUtil)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellI18NUtil)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozEnglishWordUtils)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_3(mozEnglishWordUtils,
+                           mCaseConv,
+                           mCategories,
+                           mURLDetector)
 
 mozEnglishWordUtils::mozEnglishWordUtils()
 {
   mLanguage.AssignLiteral("en");
 
   nsresult rv;
   mURLDetector = do_CreateInstance(MOZ_TXTTOHTMLCONV_CONTRACTID, &rv);
   mCaseConv = do_GetService(NS_UNICHARUTIL_CONTRACTID);
--- a/extensions/spellcheck/src/mozEnglishWordUtils.h
+++ b/extensions/spellcheck/src/mozEnglishWordUtils.h
@@ -42,22 +42,24 @@
 #include "mozISpellI18NUtil.h"
 #include "nsIUnicodeEncoder.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsString.h"
 #include "nsICaseConversion.h"
 #include "nsIUGenCategory.h"
 
 #include "mozITXTToHTMLConv.h" 
+#include "nsCycleCollectionParticipant.h"
 
 class mozEnglishWordUtils : public mozISpellI18NUtil
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_MOZISPELLI18NUTIL
+  NS_DECL_CYCLE_COLLECTION_CLASS(mozEnglishWordUtils)
 
   mozEnglishWordUtils();
   virtual ~mozEnglishWordUtils();
   /* additional members */
   enum myspCapitalization{
     NoCap,InitCap,AllCap,HuhCap
   };  
 
--- a/extensions/spellcheck/src/mozGenericWordUtils.cpp
+++ b/extensions/spellcheck/src/mozGenericWordUtils.cpp
@@ -31,17 +31,26 @@
  * 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 "mozGenericWordUtils.h"
 
-NS_IMPL_ISUPPORTS1(mozGenericWordUtils, mozISpellI18NUtil)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(mozGenericWordUtils)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(mozGenericWordUtils)
+
+NS_INTERFACE_MAP_BEGIN(mozGenericWordUtils)
+  NS_INTERFACE_MAP_ENTRY(mozISpellI18NUtil)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellI18NUtil)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozGenericWordUtils)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_0(mozGenericWordUtils)
 
   // do something sensible but generic ... eventually.  For now whine.
 
 mozGenericWordUtils::mozGenericWordUtils()
 {
   /* member initializers and constructor code */
 }
 
--- a/extensions/spellcheck/src/mozGenericWordUtils.h
+++ b/extensions/spellcheck/src/mozGenericWordUtils.h
@@ -35,20 +35,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozGenericWordUtils_h__
 #define mozGenericWordUtils_h__
 
 #include "nsCOMPtr.h"
 #include "mozISpellI18NUtil.h"
+#include "nsCycleCollectionParticipant.h"
 
 class mozGenericWordUtils : public mozISpellI18NUtil
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_MOZISPELLI18NUTIL
+  NS_DECL_CYCLE_COLLECTION_CLASS(mozGenericWordUtils)
 
   mozGenericWordUtils();
   virtual ~mozGenericWordUtils();
 };
 
 #endif
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -517,20 +517,28 @@ NS_INTERFACE_MAP_BEGIN(mozInlineSpellChe
 NS_INTERFACE_MAP_ENTRY(nsIInlineSpellChecker)
 NS_INTERFACE_MAP_ENTRY(nsIEditActionListener)
 NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener)
 NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMKeyListener)
 NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMKeyListener)
+NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozInlineSpellChecker)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_ADDREF(mozInlineSpellChecker)
-NS_IMPL_RELEASE(mozInlineSpellChecker)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(mozInlineSpellChecker)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(mozInlineSpellChecker)
+
+NS_IMPL_CYCLE_COLLECTION_5(mozInlineSpellChecker,
+                           mSpellCheck,
+                           mTextServicesDocument,
+                           mTreeWalker,
+                           mConverter,
+                           mCurrentSelectionAnchorNode)
 
 mozInlineSpellChecker::SpellCheckingState
   mozInlineSpellChecker::gCanEnableSpellChecking =
   mozInlineSpellChecker::SpellCheck_Uninitialized;
 
 mozInlineSpellChecker::mozInlineSpellChecker() :
     mNumWordsInSpellSelection(0),
     mMaxNumWordsInSpellSelection(250),
--- a/extensions/spellcheck/src/mozInlineSpellChecker.h
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.h
@@ -48,16 +48,17 @@
 #include "nsIDOMTreeWalker.h"
 #include "nsWeakReference.h"
 #include "nsIEditor.h"
 #include "nsIDOMFocusListener.h"
 #include "nsIDOMMouseListener.h"
 #include "nsIDOMKeyListener.h"
 #include "nsWeakReference.h"
 #include "mozISpellI18NUtil.h"
+#include "nsCycleCollectionParticipant.h"
 
 class nsIDOMDocumentRange;
 class nsIDOMMouseEventListener;
 class mozInlineSpellWordUtil;
 class mozInlineSpellChecker;
 class mozInlineSpellResume;
 
 class mozInlineSpellStatus
@@ -213,19 +214,20 @@ private:
     kOpSetAbsolutePosition = 3015,
     kOpRemoveAbsolutePosition = 3016,
     kOpDecreaseZIndex      = 3017,
     kOpIncreaseZIndex      = 3018
   };
 
 public:
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIEDITACTIONLISTENER
   NS_DECL_NSIINLINESPELLCHECKER
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(mozInlineSpellChecker, nsIDOMKeyListener)
 
   // returns true if it looks likely that we can enable real-time spell checking
   static PRBool CanEnableInlineSpellChecking();
 
   /*BEGIN implementations of focus event handler interface*/
   NS_IMETHOD Focus(nsIDOMEvent* aEvent);
   NS_IMETHOD Blur(nsIDOMEvent* aEvent);
   /*END implementations of focus event handler interface*/
--- a/extensions/spellcheck/src/mozPersonalDictionary.cpp
+++ b/extensions/spellcheck/src/mozPersonalDictionary.cpp
@@ -63,17 +63,28 @@ const int kMaxWordLen=256;
  *
  * Allowing personal words to be associated with only certain dictionaries maybe.
  *
  * TODO:
  * Implement the suggestion record.
  */
 
 
-NS_IMPL_ISUPPORTS3(mozPersonalDictionary, mozIPersonalDictionary, nsIObserver, nsISupportsWeakReference)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(mozPersonalDictionary)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(mozPersonalDictionary)
+
+NS_INTERFACE_MAP_BEGIN(mozPersonalDictionary)
+  NS_INTERFACE_MAP_ENTRY(mozIPersonalDictionary)
+  NS_INTERFACE_MAP_ENTRY(nsIObserver)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozIPersonalDictionary)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozPersonalDictionary)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_1(mozPersonalDictionary, mEncoder)
 
 mozPersonalDictionary::mozPersonalDictionary()
  : mDirty(PR_FALSE)
 {
 }
 
 mozPersonalDictionary::~mozPersonalDictionary()
 {
--- a/extensions/spellcheck/src/mozPersonalDictionary.h
+++ b/extensions/spellcheck/src/mozPersonalDictionary.h
@@ -43,16 +43,17 @@
 #include "nsVoidArray.h"
 #include "mozIPersonalDictionary.h"
 #include "nsIUnicodeEncoder.h"
 #include "nsIObserver.h"
 #include "nsWeakReference.h"
 #include "nsTHashtable.h"
 #include "nsTArray.h"
 #include "nsCRT.h"
+#include "nsCycleCollectionParticipant.h"
 
 #define MOZ_PERSONALDICTIONARY_CONTRACTID "@mozilla.org/spellchecker/personaldictionary;1"
 #define MOZ_PERSONALDICTIONARY_CID         \
 { /* 7EF52EAF-B7E1-462B-87E2-5D1DBACA9048 */  \
 0X7EF52EAF, 0XB7E1, 0X462B, \
   { 0X87, 0XE2, 0X5D, 0X1D, 0XBA, 0XCA, 0X90, 0X48 } }
 
 class nsUniCharEntry : public PLDHashEntryHdr
@@ -87,19 +88,20 @@ private:
 };
 
 
 class mozPersonalDictionary : public mozIPersonalDictionary, 
                               public nsIObserver,
                               public nsSupportsWeakReference
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_MOZIPERSONALDICTIONARY
   NS_DECL_NSIOBSERVER
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(mozPersonalDictionary, mozIPersonalDictionary)
 
   mozPersonalDictionary();
   virtual ~mozPersonalDictionary();
 
   nsresult Init();
 
 protected:
   nsTArray<nsString>  mDictionary;  /* use something a little smarter eventually*/
--- a/extensions/spellcheck/src/mozSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozSpellChecker.cpp
@@ -40,17 +40,29 @@
 #include "nsIStringEnumerator.h"
 #include "nsICategoryManager.h"
 #include "nsISupportsPrimitives.h"
 
 #define UNREASONABLE_WORD_LENGTH 64
 
 #define DEFAULT_SPELL_CHECKER "@mozilla.org/spellchecker/engine;1"
 
-NS_IMPL_ISUPPORTS1(mozSpellChecker, nsISpellChecker)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(mozSpellChecker)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(mozSpellChecker)
+
+NS_INTERFACE_MAP_BEGIN(mozSpellChecker)
+  NS_INTERFACE_MAP_ENTRY(nsISpellChecker)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISpellChecker)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozSpellChecker)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_3(mozSpellChecker,
+                           mConverter,
+                           mTsDoc,
+                           mPersonalDictionary)
 
 mozSpellChecker::mozSpellChecker()
 {
 }
 
 mozSpellChecker::~mozSpellChecker()
 {
   if(mPersonalDictionary){
--- a/extensions/spellcheck/src/mozSpellChecker.h
+++ b/extensions/spellcheck/src/mozSpellChecker.h
@@ -43,21 +43,23 @@
 #include "nsString.h"
 #include "nsITextServicesDocument.h"
 #include "mozIPersonalDictionary.h"
 #include "mozISpellCheckingEngine.h"
 #include "nsClassHashtable.h"
 #include "nsVoidArray.h"
 #include "nsTArray.h"
 #include "mozISpellI18NUtil.h"
+#include "nsCycleCollectionParticipant.h"
 
 class mozSpellChecker : public nsISpellChecker
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(mozSpellChecker)
 
   mozSpellChecker();
   virtual ~mozSpellChecker();
 
   nsresult Init();
 
   // nsISpellChecker
   NS_IMETHOD SetDocument(nsITextServicesDocument *aDoc, PRBool aFromStartofDoc);
--- a/extensions/spellcheck/src/mozSpellI18NManager.cpp
+++ b/extensions/spellcheck/src/mozSpellI18NManager.cpp
@@ -35,17 +35,26 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozSpellI18NManager.h"
 #include "mozEnglishWordUtils.h"
 #include "mozGenericWordUtils.h"
 #include "nsString.h"
 
-NS_IMPL_ISUPPORTS1(mozSpellI18NManager, mozISpellI18NManager)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(mozSpellI18NManager)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(mozSpellI18NManager)
+
+NS_INTERFACE_MAP_BEGIN(mozSpellI18NManager)
+  NS_INTERFACE_MAP_ENTRY(mozISpellI18NManager)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellI18NManager)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozSpellI18NManager)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_0(mozSpellI18NManager)
 
 mozSpellI18NManager::mozSpellI18NManager()
 {
   /* member initializers and constructor code */
 }
 
 mozSpellI18NManager::~mozSpellI18NManager()
 {
--- a/extensions/spellcheck/src/mozSpellI18NManager.h
+++ b/extensions/spellcheck/src/mozSpellI18NManager.h
@@ -35,26 +35,28 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozSpellI18NManager_h__
 #define mozSpellI18NManager_h__
 
 #include "nsCOMPtr.h"
 #include "mozISpellI18NManager.h"
+#include "nsCycleCollectionParticipant.h"
 
 #define MOZ_SPELLI18NMANAGER_CONTRACTID "@mozilla.org/spellchecker/i18nmanager;1"
 #define MOZ_SPELLI18NMANAGER_CID         \
 { /* {AEB8936F-219C-4D3C-8385-D9382DAA551A} */  \
 0xaeb8936f, 0x219c, 0x4d3c, \
   { 0x83, 0x85, 0xd9, 0x38, 0x2d, 0xaa, 0x55, 0x1a } }
 
 class mozSpellI18NManager : public mozISpellI18NManager
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_MOZISPELLI18NMANAGER
+  NS_DECL_CYCLE_COLLECTION_CLASS(mozSpellI18NManager)
 
   mozSpellI18NManager();
   virtual ~mozSpellI18NManager();
 };
 #endif
 
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -109,15 +109,17 @@ fix-win32-show-glyphs-clipping.patch: fi
 native-clipping.patch: Add support for a native clipping api
 
 quartz-is-clear.patch: Propagate the quartz is_clear flag.
 
 cairo-qt-compile.patch: Fix compile error, return not reached, and clone_similar interface
 
 ==== pixman patches ====
 
+pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.
+
 pixman-rename-and-endian.patch: include cairo-platform.h for renaming of external symbols and endian macros
 
 NOTE: we previously supported ARM assembler on MSVC, this has been removed because of the maintenance burden
 
 ==== disable printing patch ====
 
 disable-printing.patch:  allows us to use NS_PRINTING to disable printing.
--- a/gfx/cairo/libpixman/src/pixman-cpu.c
+++ b/gfx/cairo/libpixman/src/pixman-cpu.c
@@ -234,16 +234,54 @@ pixman_have_arm_neon (void)
 
 static pixman_bool_t arm_has_v7 = FALSE;
 static pixman_bool_t arm_has_v6 = FALSE;
 static pixman_bool_t arm_has_vfp = FALSE;
 static pixman_bool_t arm_has_neon = FALSE;
 static pixman_bool_t arm_has_iwmmxt = FALSE;
 static pixman_bool_t arm_tests_initialized = FALSE;
 
+#ifdef ANDROID
+
+/* on Android, we can't reliably access /proc/self/auxv,
+ * so instead read the text version in /proc/cpuinfo and
+ * parse that instead.
+ */
+
+static void
+pixman_arm_read_auxv()
+{
+    char buf[1024];
+    char* pos;
+    const char* ver_token = "CPU architecture: ";
+    FILE* f = fopen("/proc/cpuinfo", "r");
+    if (!f) {
+	arm_tests_initialized = TRUE;
+	return;
+    }
+
+    fread(buf, sizeof(char), 1024, f);
+    fclose(f);
+    pos = strstr(buf, ver_token);
+    if (pos) {
+	char vchar = *(pos + strlen(ver_token));
+	if (vchar >= '0' && vchar <= '9') {
+	    int ver = vchar - '0';
+	    arm_has_v7 = ver >= 7;
+	    arm_has_v6 = ver >= 6;
+	}
+    }
+    arm_has_neon = strstr(buf, "neon") != NULL;
+    arm_has_vfp = strstr(buf, "vfp") != NULL;
+    arm_has_iwmmxt = strstr(buf, "iwmmxt") != NULL;
+    arm_tests_initialized = TRUE;
+}
+
+#else
+
 static void
 pixman_arm_read_auxv ()
 {
     int fd;
     Elf32_auxv_t aux;
 
     fd = open ("/proc/self/auxv", O_RDONLY);
     if (fd >= 0)
@@ -275,16 +313,17 @@ pixman_arm_read_auxv ()
 		}
 	    }
 	}
 	close (fd);
     }
 
     arm_tests_initialized = TRUE;
 }
+#endif
 
 #if defined(USE_ARM_SIMD)
 pixman_bool_t
 pixman_have_arm_simd (void)
 {
     if (!arm_tests_initialized)
 	pixman_arm_read_auxv ();
 
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/pixman-android-cpu-detect.patch
@@ -0,0 +1,29 @@
+diff --git a/gfx/cairo/libpixman/src/pixman-cpu.c b/gfx/cairo/libpixman/src/pixman-cpu.c
+--- a/gfx/cairo/libpixman/src/pixman-cpu.c
++++ b/gfx/cairo/libpixman/src/pixman-cpu.c
+@@ -257,19 +257,22 @@ pixman_arm_read_auxv()
+ 	arm_tests_initialized = TRUE;
+ 	return;
+     }
+ 
+     fread(buf, sizeof(char), 1024, f);
+     fclose(f);
+     pos = strstr(buf, ver_token);
+     if (pos) {
+-	int ver = *(pos + strlen(ver_token)) - '0';
+-	arm_has_v7 = ver >= 7;
+-	arm_has_v6 = ver >= 6;
++	char vchar = *(pos + strlen(ver_token));
++	if (vchar >= '0' && vchar <= '9') {
++	    int ver = vchar - '0';
++	    arm_has_v7 = ver >= 7;
++	    arm_has_v6 = ver >= 6;
++	}
+     }
+     arm_has_neon = strstr(buf, "neon") != NULL;
+     arm_has_vfp = strstr(buf, "vfp") != NULL;
+     arm_has_iwmmxt = strstr(buf, "iwmmxt") != NULL;
+     arm_tests_initialized = TRUE;
+ }
+ 
+ #else
--- a/gfx/src/nsColor.cpp
+++ b/gfx/src/nsColor.cpp
@@ -150,59 +150,87 @@ NS_GFX_(PRBool) NS_HexToRGB(const nsStri
       // single digit to compute the new value.
       r = (r << 4) | r;
       g = (g << 4) | g;
       b = (b << 4) | b;
     }
     NS_ASSERTION((r >= 0) && (r <= 255), "bad r");
     NS_ASSERTION((g >= 0) && (g <= 255), "bad g");
     NS_ASSERTION((b >= 0) && (b <= 255), "bad b");
-    if (nsnull != aResult) {
-      *aResult = NS_RGB(r, g, b);
-    }
+    *aResult = NS_RGB(r, g, b);
     return PR_TRUE;
   }
 
   // Improperly formatted color value
   return PR_FALSE;
 }
 
-// compatible with legacy Nav behavior
+// This implements part of the algorithm for legacy behavior described in
+// http://www.whatwg.org/specs/web-apps/current-work/complete/common-microsyntaxes.html#rules-for-parsing-a-legacy-color-value
 NS_GFX_(PRBool) NS_LooseHexToRGB(const nsString& aColorSpec, nscolor* aResult)
 {
+  if (aColorSpec.EqualsLiteral("transparent")) {
+    return PR_FALSE;
+  }
+
   int nameLen = aColorSpec.Length();
   const PRUnichar* colorSpec = aColorSpec.get();
+  if (nameLen > 128) {
+    nameLen = 128;
+  }
+
   if ('#' == colorSpec[0]) {
     ++colorSpec;
     --nameLen;
   }
 
-  if (3 < nameLen) {
-    // Convert the ascii to binary
-    int dpc = (nameLen / 3) + (((nameLen % 3) != 0) ? 1 : 0);
-    if (4 < dpc) {
-      dpc = 4;
-    }
+  // digits per component
+  int dpc = (nameLen + 2) / 3;
+  int newdpc = dpc;
+
+  // Use only the rightmost 8 characters of each component.
+  if (newdpc > 8) {
+    nameLen -= newdpc - 8;
+    colorSpec += newdpc - 8;
+    newdpc = 8;
+  }
 
-    // Translate components from hex to binary
-    int r = ComponentValue(colorSpec, nameLen, 0, dpc);
-    int g = ComponentValue(colorSpec, nameLen, 1, dpc);
-    int b = ComponentValue(colorSpec, nameLen, 2, dpc);
-    NS_ASSERTION((r >= 0) && (r <= 255), "bad r");
-    NS_ASSERTION((g >= 0) && (g <= 255), "bad g");
-    NS_ASSERTION((b >= 0) && (b <= 255), "bad b");
-    if (nsnull != aResult) {
-      *aResult = NS_RGB(r, g, b);
+  // And then keep trimming characters at the left until we'd trim one
+  // that would leave a nonzero value, but not past 2 characters per
+  // component.
+  while (newdpc > 2) {
+    PRBool haveNonzero = PR_FALSE;
+    for (int c = 0; c < 3; ++c) {
+      NS_ABORT_IF_FALSE(c * dpc < nameLen,
+                        "should not pass end of string while newdpc > 2");
+      PRUnichar ch = colorSpec[c * dpc];
+      if (('1' <= ch && ch <= '9') ||
+          ('A' <= ch && ch <= 'F') ||
+          ('a' <= ch && ch <= 'f')) {
+        haveNonzero = PR_TRUE;
+        break;
+      }
     }
+    if (haveNonzero) {
+      break;
+    }
+    --newdpc;
+    --nameLen;
+    ++colorSpec;
   }
-  else {
-    if (nsnull != aResult) {
-      *aResult = NS_RGB(0, 0, 0);
-    }
-  }
+
+  // Translate components from hex to binary
+  int r = ComponentValue(colorSpec, nameLen, 0, dpc);
+  int g = ComponentValue(colorSpec, nameLen, 1, dpc);
+  int b = ComponentValue(colorSpec, nameLen, 2, dpc);
+  NS_ASSERTION((r >= 0) && (r <= 255), "bad r");
+  NS_ASSERTION((g >= 0) && (g <= 255), "bad g");
+  NS_ASSERTION((b >= 0) && (b <= 255), "bad b");
+
+  *aResult = NS_RGB(r, g, b);
   return PR_TRUE;
 }
 
 NS_GFX_(PRBool) NS_ColorNameToRGB(const nsAString& aColorName, nscolor* aResult)
 {
   if (!gColorTable) return PR_FALSE;
 
   PRInt32 id = gColorTable->Lookup(aColorName);
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -1659,17 +1659,16 @@ def _generateCxxUnion(ud):
     refClsType = Type(ud.name, ref=1)
     typetype = Type('Type')
     valuetype = Type('Value')
     mtypevar = ExprVar('mType')
     mvaluevar = ExprVar('mValue')
     maybedtorvar = ExprVar('MaybeDestroy')
     assertsanityvar = ExprVar('AssertSanity')
     tnonevar = ExprVar('T__None')
-    tfirstvar = ExprVar('T__First')
     tlastvar = ExprVar('T__Last')
 
     def callAssertSanity(uvar=None, expectTypeVar=None):
         func = assertsanityvar
         args = [ ]
         if uvar is not None:
             func = ExprSelect(uvar, '.', assertsanityvar.name)
         if expectTypeVar is not None:
@@ -1695,17 +1694,16 @@ def _generateCxxUnion(ud):
     # the |Type| enum, used to switch on the discunion's real type
     cls.addstmt(Label.PUBLIC)
     typeenum = TypeEnum(typetype.name)
     typeenum.addId(tnonevar.name, 0)
     firstid = ud.components[0].enum()
     typeenum.addId(firstid, 1)
     for c in ud.components[1:]:
         typeenum.addId(c.enum())
-    typeenum.addId(tfirstvar.name, firstid)
     typeenum.addId(tlastvar.name, ud.components[-1].enum())
     cls.addstmts([ StmtDecl(Decl(typeenum,'')),
                    Whitespace.NL ])
 
     cls.addstmt(Label.PRIVATE)
     cls.addstmts(
         usingTypedefs
         # hacky typedef's that allow placement dtors of builtins
@@ -1769,17 +1767,17 @@ def _generateCxxUnion(ud):
     ])
     cls.addstmts([ maybedtor, Whitespace.NL ])
 
     # add helper methods that ensure the discunion has a
     # valid type
     sanity = MethodDefn(MethodDecl(
         assertsanityvar.name, ret=Type.VOID, const=1, force_inline=1))
     sanity.addstmts([
-        _abortIfFalse(ExprBinary(tfirstvar, '<=', mtypevar),
+        _abortIfFalse(ExprBinary(tnonevar, '<=', mtypevar),
                       'invalid type tag'),
         _abortIfFalse(ExprBinary(mtypevar, '<=', tlastvar),
                       'invalid type tag') ])
     cls.addstmt(sanity)
 
     atypevar = ExprVar('aType')
     sanity2 = MethodDefn(
         MethodDecl(assertsanityvar.name,
@@ -1822,16 +1820,18 @@ def _generateCxxUnion(ud):
         copyswitch.addcase(
             CaseLabel(c.enum()),
             StmtBlock([
                 StmtExpr(c.callCtor(
                     ExprCall(ExprSelect(othervar,
                                         '.', c.getConstTypeName())))),
                 StmtBreak()
             ]))
+    copyswitch.addcase(CaseLabel(tnonevar.name),
+                       StmtBlock([ StmtBreak() ]))
     copyswitch.addcase(
         DefaultLabel(),
         StmtBlock([ _runtimeAbort('unreached'), StmtReturn() ]))
     copyctor.addstmts([
         StmtExpr(callAssertSanity(uvar=othervar)),
         copyswitch,
         StmtExpr(ExprAssn(mtypevar, othertype))
     ])
@@ -1875,16 +1875,19 @@ def _generateCxxUnion(ud):
         case = StmtBlock()
         case.addstmts([
             maybeReconstruct(c, rhstypevar),
             StmtExpr(c.callOperatorEq(
                 ExprCall(ExprSelect(rhsvar, '.', c.getConstTypeName())))),
             StmtBreak()
         ])
         opeqswitch.addcase(CaseLabel(c.enum()), case)
+    opeqswitch.addcase(CaseLabel(tnonevar.name),
+                       StmtBlock([ StmtExpr(callMaybeDestroy(rhstypevar)),
+                                   StmtBreak() ]))
     opeqswitch.addcase(
         DefaultLabel(),
         StmtBlock([ _runtimeAbort('unreached'), StmtBreak() ]))
     opeq.addstmts([
         StmtExpr(callAssertSanity(uvar=rhsvar)),
         StmtDecl(Decl(typetype, rhstypevar.name), init=ud.callType(rhsvar)),
         opeqswitch,
         StmtExpr(ExprAssn(mtypevar, rhstypevar)),
--- a/ipc/ipdl/test/cxx/PTestDataStructures.ipdl
+++ b/ipc/ipdl/test/cxx/PTestDataStructures.ipdl
@@ -1,10 +1,12 @@
 include protocol PTestDataStructuresSub;
 
+using mozilla::null_t;
+
 namespace mozilla {
 namespace _foo {
 
 union IntDouble {
     int;
     double;
 };
 
@@ -62,16 +64,33 @@ union WithStructs {
 struct WithUnions {
     int i;
     int[] ai;
     PTestDataStructuresSub[] ap;
     Actors[] aa;
     Unions[] au;
 };
 
+struct CommonAttrs { bool dummy; };
+struct FooAttrs { int dummy; };
+struct BarAttrs { float dummy; };
+union SpecificAttrs {
+    FooAttrs;
+    BarAttrs;
+};
+struct Attrs {
+    CommonAttrs common;
+    SpecificAttrs specific;
+};
+struct SetAttrs {
+    PTestDataStructuresSub x;
+    Attrs attrs;
+};
+union Op { null_t; SetAttrs; };
+
 } // namespace _foo
 } // namespace mozilla
 
 namespace mozilla {
 namespace _ipdltest {
 
 sync protocol PTestDataStructures {
     manages PTestDataStructuresSub;
@@ -151,35 +170,38 @@ parent:
                  WithStructs o2,
                  WithStructs o3,
                  WithStructs o4,
                  WithStructs o5);
 
     sync Test16(WithUnions i)
         returns (WithUnions o);
 
+    sync Test17(Op[] ops);
+
 state START:
     send Start goto TEST1;
 
 state TEST1:   recv Test1 goto TEST2;
 state TEST2:   recv Test2 goto TEST3;
 state TEST3:   recv Test3 goto TEST4;
 state TEST4:   recv Test4 goto TEST5;
 state TEST5:   recv Test5 goto TEST6;
 state TEST6:   recv Test6 goto TEST7;
 state TEST7:   recv Test7 goto TEST8;
 state TEST8:   recv Test8 goto TEST9;
 state TEST9:   recv Test9 goto TEST10;
 state TEST10:  recv Test10 goto TEST11;
 state TEST11:  recv Test11 goto TEST12;
-state TEST12:  recv Test11 goto TEST13;
-state TEST13:  recv Test11 goto TEST14;
-state TEST14:  recv Test11 goto TEST15;
-state TEST15:  recv Test11 goto TEST16;
-state TEST16:  recv Test11 goto DEAD;
+state TEST12:  recv Test12 goto TEST13;
+state TEST13:  recv Test13 goto TEST14;
+state TEST14:  recv Test14 goto TEST15;
+state TEST15:  recv Test15 goto TEST16;
+state TEST16:  recv Test16 goto TEST17;
+state TEST17:  recv Test17 goto DEAD;
 
 state DEAD:
     recv __delete__;
 };
 
 } // namespace _ipdltest
 } // namespace mozilla
 
--- a/ipc/ipdl/test/cxx/TestDataStructures.cpp
+++ b/ipc/ipdl/test/cxx/TestDataStructures.cpp
@@ -412,16 +412,23 @@ bool TestDataStructuresParent::RecvTest1
                         iau[3].get_ArrayOfActors()[0]
                         .get_ArrayOfPTestDataStructuresSubParent());
 
     *o = i;
 
     return true;
 }
 
+bool TestDataStructuresParent::RecvTest17(const nsTArray<Op>& sa)
+{
+    test_assert(sa.Length() == 1 && Op::TSetAttrs == sa[0].type(),
+                "wrong value");
+    return true;
+}
+
 //-----------------------------------------------------------------------------
 // child
 
 TestDataStructuresChild::TestDataStructuresChild()
 {
     MOZ_COUNT_CTOR(TestDataStructuresChild);
 }
 
@@ -446,16 +453,17 @@ TestDataStructuresChild::RecvStart()
     Test9();
     Test10();
     Test11();
     Test12();
     Test13();
     Test14();
     Test15();
     Test16();
+    Test17();
 
     for (uint32 i = 0; i < nactors; ++i)
         if (!PTestDataStructuresSubChild::Send__delete__(mKids[i]))
             fail("can't send dtor");
 
     Close();
 
     return true;
@@ -868,10 +876,26 @@ TestDataStructuresChild::Test16()
                         mKids);
     assert_arrays_equal(oau[3].get_ArrayOfActors()[0]
                         .get_ArrayOfPTestDataStructuresSubChild(),
                         mKids);
 
     printf("  passed %s\n", __FUNCTION__);
 }
 
+void
+TestDataStructuresChild::Test17()
+{
+    Attrs attrs;
+    attrs.common() = CommonAttrs(true);
+    attrs.specific() = BarAttrs(1.0f);
+
+    nsTArray<Op> ops;
+    ops.AppendElement(SetAttrs(NULL, mKids[0], attrs));
+
+    if (!SendTest17(ops))
+        fail("sending Test17");
+
+    printf("  passed %s\n", __FUNCTION__);
+}
+
 } // namespace _ipdltest
 } // namespace mozilla
--- a/ipc/ipdl/test/cxx/TestDataStructures.h
+++ b/ipc/ipdl/test/cxx/TestDataStructures.h
@@ -151,16 +151,19 @@ protected:
             WithStructs* o5);
 
     NS_OVERRIDE
     virtual bool RecvTest16(
             const WithUnions& i,
             WithUnions* o);
 
     NS_OVERRIDE
+    virtual bool RecvTest17(const nsTArray<Op>& sa);
+
+    NS_OVERRIDE
     virtual void ActorDestroy(ActorDestroyReason why)
     {
         if (NormalShutdown != why)
             fail("unexpected destruction!");  
         passed("ok");
         QuitParent();
     }
 
@@ -215,16 +218,17 @@ private:
     void Test9();
     void Test10();
     void Test11();
     void Test12();
     void Test13();
     void Test14();
     void Test15();
     void Test16();
+    void Test17();
 
     nsTArray<PTestDataStructuresSubChild*> mKids;
 };
 
 
 } // namespace _ipdltest
 } // namespace mozilla
 
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -197,38 +197,37 @@ case "$target" in
     if test -z "$CXX"; then CXX=g++-4.2; fi
     ;;
 esac
 fi
 
 COMPILE_ENVIRONMENT=1
 MOZ_ARG_ENABLE_BOOL(compile-environment,
 [  --disable-compile-environment
-                           Disable compiler/library checks.],
+                          Disable compiler/library checks.],
     COMPILE_ENVIRONMENT=1,
     COMPILE_ENVIRONMENT= )
 
 dnl ========================================================
 dnl = Android uses a very custom (hacky) toolchain; we need to do this
 dnl = here, so that the compiler checks can succeed
 dnl ========================================================
 
 MOZ_ARG_WITH_STRING(android-ndk,
-[  --with-android-ndk=DIR
-                           location where the Android NDK can be found],
+[  --with-android-ndk=DIR  location where the Android NDK can be found],
     android_ndk=$withval)
 
 MOZ_ARG_WITH_STRING(android-toolchain,
 [  --with-android-toolchain=DIR
-                           location of the android toolchain, default NDK/build/prebuilt/HOST/arm-eabi-4.4.0],
+                          location of the android toolchain, default NDK/build/prebuilt/HOST/arm-eabi-4.4.0],
     android_toolchain=$withval)
 
 MOZ_ARG_WITH_STRING(android-platform,
 [  --with-android-platform=DIR
-                           location of platform dir, default NDK/build/platforms/android-5/arch-arm],
+                          location of platform dir, default NDK/build/platforms/android-5/arch-arm],
     android_platform=$withval)
 
 if test "$target" = "arm-android-eabi" ; then
     if test -z "$android_ndk" ; then
         AC_MSG_ERROR([You must specify --with-android-ndk=/path/to/ndk when targeting Android.])
     fi
 
     if test -z "$android_toolchain" ; then
@@ -355,17 +354,17 @@ if test "$target" != "$host"; then
         CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CXXFLAGS"
         ;;
     esac
 
     case "$target" in
     *symbian*)
         AC_ARG_WITH(symbian-sdk,
         [  --with-symbian-sdk=SYMBIAN_SDK_DIR
-                              The path to the Symbian SDK],
+                          The path to the Symbian SDK],
         SYMBIAN_SDK_DIR=$withval)
 
         OS_EXE_CFLAGS="$OS_EXE_CFLAGS -D__EXE__"
         CFLAGS="-MD -nostdinc"
         SYMBIAN_SYS_INCLUDE="-I$SYMBIAN_SDK_DIR/Epoc32/include -I$SYMBIAN_SDK_DIR/Epoc32/include/variant -I$SYMBIAN_SDK_DIR/Epoc32/include/stdapis"
 
         case "$target" in
         *-symbianelf)
@@ -883,17 +882,17 @@ esac
 AC_SUBST(MACOSX_DEPLOYMENT_TARGET)
 
 dnl ========================================================
 dnl = Mac OS X SDK support
 dnl ========================================================
 MACOS_SDK_DIR=
 NEXT_ROOT=
 MOZ_ARG_WITH_STRING(macos-sdk,
-[  --with-macos-sdk=dir   Location of platform SDK to use (Mac OS X only)],
+[  --with-macos-sdk=dir    Location of platform SDK to use (Mac OS X only)],
     MACOS_SDK_DIR=$withval)
 
 dnl MACOS_SDK_DIR will be set to the SDK location whenever one is in use.
 dnl NEXT_ROOT will be set and exported only if it's needed.
 AC_SUBST(MACOS_SDK_DIR)
 AC_SUBST(NEXT_ROOT)
 
 if test "$MACOS_SDK_DIR"; then
@@ -1988,17 +1987,18 @@ ia64*-hpux*)
     MOZ_ENABLE_POSTSCRIPT=
     MOZ_USER_DIR="Mozilla"
 
     dnl Default to Windows Mobile components enabled
     WINCE_WINDOWS_MOBILE=1
 
     MOZ_ARG_DISABLE_BOOL(windows-mobile-components,
     [  --disable-windows-mobile-components
-         Disable Windows Mobile specific components from CE build],
+                          Disable Windows Mobile specific components from
+                          CE build],
     WINCE_WINDOWS_MOBILE=,
     WINCE_WINDOWS_MOBILE=1)
  
     if test "$WINCE_WINDOWS_MOBILE"; then
         AC_DEFINE(WINCE_WINDOWS_MOBILE)
     fi
 ;;
 
@@ -2594,17 +2594,17 @@ arm*-*)
     ;;
 sparc*-*)
     ENABLE_TRACEJIT=1
     NANOJIT_ARCH=Sparc
     ;;
 esac
 
 MOZ_ARG_DISABLE_BOOL(tracejit,
-[  --disable-tracejit           Disable tracing JIT support],
+[  --disable-tracejit      Disable tracing JIT support],
   ENABLE_TRACEJIT=)
 
 if test "$ENABLE_TRACEJIT"; then
 
 AC_DEFINE(FEATURE_NANOJIT)
 AC_DEFINE(JS_TRACER)
 
 case "$target" in
@@ -3969,17 +3969,18 @@ MOZ_ARG_WITH_BOOL(system-nspr,
                           Use the 'nspr-config' script in the current path,
                           or look for the script in the directories given with
                           --with-nspr-exec-prefix or --with-nspr-prefix.
                           (Those flags are only checked if you specify
                           --with-system-nspr.)],
     _USE_SYSTEM_NSPR=1 )
 
 MOZ_ARG_WITH_STRING(nspr-cflags,
-[  --with-nspr-cflags=FLAGS Pass FLAGS to CC when building code that uses NSPR.
+[  --with-nspr-cflags=FLAGS
+                          Pass FLAGS to CC when building code that uses NSPR.
                           Use this when there's no accurate nspr-config
                           script available.  This is the case when building
                           SpiderMonkey as part of the Mozilla tree: the
                           top-level configure script computes NSPR flags
                           that accomodate the quirks of that environment.],
     NSPR_CFLAGS=$withval)
 MOZ_ARG_WITH_STRING(nspr-libs,
 [  --with-nspr-libs=LIBS   Pass LIBS to LD when linking code that uses NSPR.
@@ -4017,17 +4018,17 @@ if test -n "$MOZ_NATIVE_NSPR"; then
     CFLAGS=$_SAVE_CFLAGS
 fi
 
 dnl ========================================================
 dnl Use ARM userspace kernel helpers; tell NSPR to enable
 dnl their usage and use them in spidermonkey.
 dnl ========================================================
 MOZ_ARG_WITH_BOOL(arm-kuser,
-[  --with-arm-kuser         Use kuser helpers (Linux/ARM only -- requires kernel 2.6.13 or later)],
+[  --with-arm-kuser        Use kuser helpers (Linux/ARM only -- requires kernel 2.6.13 or later)],
     USE_ARM_KUSER=1,
     USE_ARM_KUSER=)
 if test -n "$USE_ARM_KUSER"; then
    AC_DEFINE(USE_ARM_KUSER)
 fi
 
 dnl ========================================================
 dnl =
@@ -4048,17 +4049,17 @@ dnl ====================================
 MOZ_ARG_HEADER(Components and Features)
 
 dnl ========================================================
 
 dnl ========================================================
 dnl = Enable building the Thumb2 instruction set
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(thumb2,
- [  --enable-thumb2              Enable Thumb2 instruction set],
+ [  --enable-thumb2         Enable Thumb2 instruction set],
     MOZ_THUMB2=1,)
 
 if test -n "$MOZ_THUMB2"; then
   case "$target_cpu" in
     arm*)
       if test "$GNU_CC"; then
         CFLAGS="$CFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb"
         CXXFLAGS="$CXXFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb"
@@ -4229,18 +4230,18 @@ MOZ_ARG_ENABLE_STRING(debugger-info-modu
     AC_MSG_WARN([--enable-debugger-info-modules is deprecated, use --enable-debug-symbols instead])
     MOZ_DEBUG_SYMBOLS=1
   fi ])
 
 dnl ========================================================
 dnl = Enable generation of debug symbols
 dnl ========================================================
 MOZ_ARG_ENABLE_STRING(debug-symbols,
-[  --enable-debug-symbols[=DBG]    Enable debugging symbols
-                                   (using compiler flags DBG)],
+[  --enable-debug-symbols[=DBG]
+                          Enable debugging symbols (using compiler flags DBG)],
 [ if test "$enableval" != "no"; then
       MOZ_DEBUG_SYMBOLS=1
       if test -n "$enableval" -a "$enableval" != "yes"; then
           if test -z "$_MOZ_DEBUG_FLAGS_SET"; then
               MOZ_DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'`
           else
               AC_MSG_ERROR([--enable-debug-symbols flags cannot be used with --enable-debug flags])
           fi
@@ -4251,17 +4252,17 @@ if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBU
     AC_DEFINE(MOZ_DEBUG_SYMBOLS)
     export MOZ_DEBUG_SYMBOLS
 fi
 
 dnl ========================================================
 dnl Enable Narcissus
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(narcissus,
-[  --enable-narcissus          Build with Narcissus code enabled],
+[  --enable-narcissus      Build with Narcissus code enabled],
     NARCISSUS=1,
     NARCISSUS= )
 if test -n "$NARCISSUS"; then
     AC_DEFINE(NARCISSUS)
 fi
 
 dnl ========================================================
 dnl = Enable trace malloc
@@ -4408,17 +4409,17 @@ if test -n "$MOZ_TRACEVIS"; then
        AC_MSG_ERROR([--enable-tracevis is incompatible with --disable-tracejit])
     fi
 fi
 
 dnl ========================================================
 dnl = Use GCTimer
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(gctimer,
-[  --enable-gctimer       Enable GC timer (default=no)],
+[  --enable-gctimer        Enable GC timer (default=no)],
     MOZ_GCTIMER=1,
     MOZ_GCTIMER= )
 if test -n "$MOZ_GCTIMER"; then
     AC_DEFINE(MOZ_GCTIMER)
 fi
 
 dnl ========================================================
 dnl = Use Valgrind
@@ -4477,30 +4478,30 @@ MOZ_ARG_ENABLE_BOOL(vtune,
 if test -n "$MOZ_VTUNE"; then
     AC_DEFINE(MOZ_VTUNE)
 fi
 
 dnl ========================================================
 dnl Zealous GC
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(gczeal,
-[  --enable-gczeal          Enable zealous GCing],
+[  --enable-gczeal         Enable zealous GCing],
     JS_GC_ZEAL=1,
     JS_GC_ZEAL= )
 if test -n "$JS_GC_ZEAL"; then
     AC_DEFINE(JS_GC_ZEAL)
 fi
 
 dnl ========================================================
 dnl = Enable static checking using gcc-dehydra
 dnl ========================================================
 
 MOZ_ARG_WITH_STRING(static-checking,
 [  --with-static-checking=path/to/gcc_dehydra.so
-                            Enable static checking of code using GCC-dehydra],
+                          Enable static checking of code using GCC-dehydra],
     DEHYDRA_PATH=$withval,
     DEHYDRA_PATH= )
 
 if test -n "$DEHYDRA_PATH"; then
     if test ! -f "$DEHYDRA_PATH"; then
         AC_MSG_ERROR([The dehydra plugin is not at the specified path.])
     fi
     AC_DEFINE(NS_STATIC_CHECKING)
@@ -4542,17 +4543,17 @@ MOZ_ARG_ENABLE_BOOL(timeline,
 if test -n "$MOZ_TIMELINE"; then
     AC_DEFINE(MOZ_TIMELINE)
 fi
 
 dnl ========================================================
 dnl = Support for Quantify (Windows)
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(quantify,
-[  --enable-quantify      Enable Quantify support (Windows only) ],
+[  --enable-quantify       Enable Quantify support (Windows only) ],
     MOZ_QUANTIFY=1,
     MOZ_QUANTIFY= )
 
 dnl ========================================================
 dnl = Support for demangling undefined symbols
 dnl ========================================================
 if test -z "$SKIP_LIBRARY_CHECKS"; then
     AC_LANG_SAVE
@@ -4640,17 +4641,17 @@ dnl Profile guided optimization
 dnl ========================================================
 dnl Test for profiling options
 dnl Under gcc 3.3, use -fprofile-arcs/-fbranch-probabilities
 dnl Under gcc 3.4+, use -fprofile-generate/-fprofile-use
 
 dnl Provide a switch to disable PGO even when called via profiledbuild.
 MOZ_ARG_DISABLE_BOOL(profile-guided-optimization,