Merge mozilla-central and tracemonkey. (a=blockers)
authorChris Leary <cdleary@mozilla.com>
Fri, 14 Jan 2011 09:29:15 -0800
changeset 60603 2fdb8bbd034141d326e8c51199d8a393a3ac3cd9
parent 60602 fbcba31f6380f931db2f9dbe4b514161ada03936 (current diff)
parent 60522 088b1b76dc615c5255b97841af1123ef37d90592 (diff)
child 60604 4e0501a0c5e5eae34fd3e8f754cff5e4c66b5260
child 60775 1681112ed440542ae3b151de07f3ec6c8ed4c68b
push idunknown
push userunknown
push dateunknown
reviewersblockers
milestone2.0b10pre
Merge mozilla-central and tracemonkey. (a=blockers)
toolkit/crashreporter/test/nsITestCrasher.idl
toolkit/crashreporter/test/testcrasher.manifest
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1454,17 +1454,18 @@
               this._endRemoveTab(aTab);
               return;
             }
 
             this._blurTab(aTab);
             aTab.removeAttribute("fadein");
 
             setTimeout(function (tab, tabbrowser) {
-              if (tab.parentNode) {
+              if (tab.parentNode &&
+                  window.getComputedStyle(tab).maxWidth == "0.1px") {
                 NS_ASSERT(false, "Giving up waiting for the tab closing animation to finish (bug 608589)");
                 tabbrowser._endRemoveTab(tab);
               }
             }, 3000, aTab, this);
           ]]>
         </body>
       </method>
 
--- a/browser/base/content/tabview/search.js
+++ b/browser/base/content/tabview/search.js
@@ -331,51 +331,58 @@ SearchEventHandlerClass.prototype = {
     });
     
     iQ("#searchbox").keyup(function() {
       performSearch();
     });
     
     iQ("#searchbutton").mousedown(function() {
       self.initiatedBy = "buttonclick";
-      ensureSearchShown(null);
+      ensureSearchShown();
       self.switchToInMode();      
     });
     
     this.initiatedBy = "";
     this.currentHandler = null;
     this.switchToBeforeMode();
   },
   
   // ----------
   // Function: beforeSearchKeyHandler
-  // Handles all keypresses before the search interface is brought up.
+  // Handles all keydown before the search interface is brought up.
   beforeSearchKeyHandler: function (event) {
     // Only match reasonable text-like characters for quick search.
-    // TODO: Also include funky chars. Bug 593904
-    if (!String.fromCharCode(event.which).match(/[a-zA-Z0-9]/) || event.altKey || 
-        event.ctrlKey || event.metaKey)
+    if (event.altKey || event.ctrlKey || event.metaKey)
       return;
 
+    if ((event.keyCode > 0 && event.keyCode <= event.DOM_VK_DELETE) ||
+        event.keyCode == event.DOM_VK_CONTEXT_MENU ||
+        event.keyCode == event.DOM_VK_SLEEP ||
+        (event.keyCode >= event.DOM_VK_F1 &&
+         event.keyCode <= event.DOM_VK_SCROLL_LOCK) ||
+        event.keyCode == event.DOM_VK_META) {
+      return;
+    }
+
     // If we are already in an input field, allow typing as normal.
     if (event.target.nodeName == "INPUT")
       return;
 
     this.switchToInMode();
-    this.initiatedBy = "keypress";
-    ensureSearchShown(event);
+    this.initiatedBy = "keydown";
+    ensureSearchShown();
   },
 
   // ----------
   // Function: inSearchKeyHandler
-  // Handles all keypresses while search mode.
+  // Handles all keydown while search mode.
   inSearchKeyHandler: function (event) {
     let term = iQ("#searchbox").val();
     if ((event.keyCode == event.DOM_VK_ESCAPE) || 
-        (event.keyCode == event.DOM_VK_BACK_SPACE && term.length <= 1 && this.initiatedBy == "keypress")) {
+        (event.keyCode == event.DOM_VK_BACK_SPACE && term.length <= 1 && this.initiatedBy == "keydown")) {
       hideSearch(event);
       return;
     }
 
     let matcher = createSearchTabMacher();
     let matches = matcher.matched();
     let others =  matcher.matchedTabsFromOtherWindows();
     if ((event.keyCode == event.DOM_VK_RETURN || 
@@ -391,31 +398,31 @@ SearchEventHandlerClass.prototype = {
 
   // ----------
   // Function: switchToBeforeMode
   // Make sure the event handlers are appropriate for
   // the before-search mode. 
   switchToBeforeMode: function switchToBeforeMode() {
     let self = this;
     if (this.currentHandler)
-      iQ(window).unbind("keypress", this.currentHandler);
+      iQ(window).unbind("keydown", this.currentHandler);
     this.currentHandler = function(event) self.beforeSearchKeyHandler(event);
-    iQ(window).keypress(this.currentHandler);
+    iQ(window).keydown(this.currentHandler);
   },
   
   // ----------
   // Function: switchToInMode
   // Make sure the event handlers are appropriate for
   // the in-search mode.   
   switchToInMode: function switchToInMode() {
     let self = this;
     if (this.currentHandler)
-      iQ(window).unbind("keypress", this.currentHandler);
+      iQ(window).unbind("keydown", this.currentHandler);
     this.currentHandler = function(event) self.inSearchKeyHandler(event);
-    iQ(window).keypress(this.currentHandler);
+    iQ(window).keydown(this.currentHandler);
   }
 };
 
 var TabHandlers = {
   onMatch: function(tab, index){
     tab.addClass("onTop");
     index != 0 ? tab.addClass("notMainMatch") : tab.removeClass("notMainMatch");
 
@@ -529,39 +536,35 @@ function performSearch() {
   // hide the display area.
   iQ("#results").empty();
   iQ("#otherresults").hide();
   iQ("#otherresults>.label").text(tabviewString("search.otherWindowTabs"));
 
   matcher.doSearch(TabHandlers.onMatch, TabHandlers.onUnmatch, TabHandlers.onOther);
 }
 
-function ensureSearchShown(event){
+function ensureSearchShown(){
   var $search = iQ("#search");
   var $searchShade = iQ("#searchshade");
   var $searchbox = iQ("#searchbox");
   iQ("#searchbutton").css({ opacity: 1 });
 
   if (!isSearchEnabled()) {
     $searchShade.show();
     $search.show();
     var mainWindow = gWindow.document.getElementById("main-window");
     mainWindow.setAttribute("activetitlebarcolor", "#717171");       
 
-    // Marshal the focusing, otherwise you end up with
-    // a race condition where only sometimes would the
-    // first keystroke be registered by the search box.
-    // When you marshal it never gets registered, so we
-    // manually 
-    setTimeout(function focusSearch() {
-      $searchbox[0].focus();
-      $searchbox[0].val = '0';
-      if (event != null)
-        $searchbox.val(String.fromCharCode(event.charCode));        
+    $searchbox[0].focus();
+    $searchbox[0].val = '0';
 
+    // NOTE: when this function is called by keydown handler, next keypress
+    // event or composition events of IME will be fired on the focused editor.
+
+    setTimeout(function dispatchTabViewSearchEnabledEvent() {
       let newEvent = document.createEvent("Events");
       newEvent.initEvent("tabviewsearchenabled", false, false);
       dispatchEvent(newEvent);
     }, 0);
   }
 }
 
 function isSearchEnabled() {
--- a/browser/base/content/test/tabview/browser_tabview_bug595191.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug595191.js
@@ -74,17 +74,17 @@ function escapeTest(contentWindow) {
       "tabviewsearchdisabled", onSearchDisabled, false);
 
     let search = contentWindow.document.getElementById("search");
     ok(search.style.display == "none", "Search is disabled");
     toggleTabViewTest(contentWindow);
   }
   contentWindow.addEventListener("tabviewsearchdisabled", onSearchDisabled, 
     false);
-  EventUtils.synthesizeKey("VK_ESCAPE", { type: "keypress" }, contentWindow);
+  EventUtils.synthesizeKey("VK_ESCAPE", { }, contentWindow);
 }
 
 function toggleTabViewTest(contentWindow) {
   let onTabViewHidden = function() {
     contentWindow.removeEventListener("tabviewhidden", onTabViewHidden, false);
 
     ok(!TabView.isVisible(), "Tab View is hidden");
     finish();
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -154,16 +154,24 @@
 }
 
 @media all and (-moz-windows-classic) {
   #appmenu-button {
     margin-bottom: 1px;
   }
 }
 
+%ifndef WINSTRIPE_AERO
+@media all and (-moz-windows-default-theme) {
+  #main-window[sizemode="normal"] #appmenu-button {
+    margin-bottom: 5px;
+  }
+}
+%endif
+
 #main-window[privatebrowsingmode=temporary] #appmenu-button {
   background-image: -moz-linear-gradient(rgb(153,38,211), rgb(105,19,163) 95%);
   border-color: rgba(43,8,65,.9);
 }
 
 #appmenu-button:hover:not(:active):not([open]) {
   background-image: -moz-radial-gradient(center bottom, farthest-side, rgba(252,240,89,.5) 10%, rgba(252,240,89,0) 70%),
                     -moz-radial-gradient(center bottom, farthest-side, rgb(236,133,0), rgba(255,229,172,0)),
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -280,16 +280,19 @@ public:
   }
 
   virtual nsresult SetBaseURI(nsIURI* aURI) = 0;
 
   /**
    * Get/Set the base target of a link in a document.
    */
   virtual void GetBaseTarget(nsAString &aBaseTarget) = 0;
+  void SetBaseTarget(const nsString& aBaseTarget) {
+    mBaseTarget = aBaseTarget;
+  }
 
   /**
    * Return a standard name for the document's character set.
    */
   const nsCString& GetDocumentCharacterSet() const
   {
     return mCharacterSet;
   }
@@ -1741,16 +1744,19 @@ protected:
 
   nsCOMPtr<nsIDocumentEncoder> mCachedEncoder;
 
   AnimationListenerList mAnimationFrameListeners;
 
   // The session history entry in which we're currently bf-cached. Non-null
   // if and only if we're currently in the bfcache.
   nsISHEntry* mSHEntry;
+
+  // Our base target.
+  nsString mBaseTarget;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
 
 /**
  * mozAutoSubtreeModified batches DOM mutations so that a DOMSubtreeModified
  * event is dispatched, if necessary, when the outermost mozAutoSubtreeModified
  * object is deleted.
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2961,29 +2961,17 @@ nsDocument::SetBaseURI(nsIURI* aURI)
   RefreshLinkHrefs();
 
   return NS_OK;
 }
 
 void
 nsDocument::GetBaseTarget(nsAString &aBaseTarget)
 {
-  aBaseTarget.Truncate();
-  Element* head = GetHeadElement();
-  if (!head) {
-    return;
-  }
-  
-  for (ChildIterator iter(head); !iter.IsDone(); iter.Next()) {
-    nsIContent* child = iter;
-    if (child->NodeInfo()->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
-        child->GetAttr(kNameSpaceID_None, nsGkAtoms::target, aBaseTarget)) {
-      return;
-    }
-  }
+  aBaseTarget = mBaseTarget;
 }
 
 void
 nsDocument::SetDocumentCharacterSet(const nsACString& aCharSetID)
 {
   if (!mCharacterSet.Equals(aCharSetID)) {
     mCharacterSet = aCharSetID;
 
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1160,18 +1160,16 @@ protected:
   // The channel that got passed to StartDocumentLoad(), if any
   nsCOMPtr<nsIChannel> mChannel;
   nsRefPtr<nsHTMLStyleSheet> mAttrStyleSheet;
   nsRefPtr<nsHTMLCSSStyleSheet> mStyleAttrStyleSheet;
   nsRefPtr<nsXMLEventsManager> mXMLEventsManager;
 
   nsCOMPtr<nsIScriptEventManager> mScriptEventManager;
 
-  nsString mBaseTarget;
-
   // Our update nesting level
   PRUint32 mUpdateNestLevel;
 
   // The application cache that this document is associated with, if
   // any.  This can change during the lifetime of the document.
   nsCOMPtr<nsIApplicationCache> mApplicationCache;
 
   nsCOMPtr<nsIContent> mFirstBaseNodeWithHref;
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1650,17 +1650,16 @@ nsXMLHttpRequest::CheckChannelForCrossSi
 NS_IMETHODIMP
 nsXMLHttpRequest::OpenRequest(const nsACString& method,
                               const nsACString& url,
                               PRBool async,
                               const nsAString& user,
                               const nsAString& password)
 {
   NS_ENSURE_ARG(!method.IsEmpty());
-  NS_ENSURE_ARG(!url.IsEmpty());
 
   NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
 
   // Disallow HTTP/1.1 TRACE method (see bug 302489)
   // and MS IIS equivalent TRACK (see bug 381264)
   if (method.LowerCaseEqualsLiteral("trace") ||
       method.LowerCaseEqualsLiteral("track")) {
     return NS_ERROR_INVALID_ARG;
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -450,16 +450,17 @@ include $(topsrcdir)/config/rules.mk
 		file_bug604660-6.xsl \
 		test_bug605982.html \
 		test_bug606729.html \
 		test_treewalker_nextsibling.xml \
 		test_bug614058.html \
 		test_bug590771.html \
 		test_bug622117.html \
 		test_bug622246.html \
+		test_bug484396.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
 
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug484396.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=484396
+-->
+<head>
+  <title>Test for Bug 484396</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=484396">Mozilla Bug 484396</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var msg = 'xhr.open() succeeds with empty url';
+var xhr = new XMLHttpRequest();
+
+try {
+  xhr.open('GET', '');
+  ok(true, msg);
+} catch (e) {
+  ok(false, msg);
+}
+
+xhr.onerror = function () {
+  ok(false, 'xhr.send() succeeds with empty url');
+}
+
+xhr.onreadystatechange = function () {
+  if (4 == xhr.readyState) {
+    is(xhr.status, 200, 'xhr.status is 200 OK');
+    ok(-1 < xhr.responseText.indexOf('Bug 484396'), 'xhr.responseText contains the calling page');
+    
+    SimpleTest.finish();
+  }
+};
+
+xhr.send('');
+</script>
+</pre>
+</body>
+</html>
--- a/content/base/test/test_bug515401.html
+++ b/content/base/test/test_bug515401.html
@@ -103,40 +103,40 @@ verifyBase("base5/", "unset href on seco
 // Insert base with href before existing
 var basehref0 = document.createElement("base");
 basehref0.href = "base6/";
 verifyBase("base5/", "nothing modified");
 head.insertBefore(basehref0, head.firstChild);
 verifyBase("base6/", "insert base with href before existing");
 
 // Insert base as grandchild of head
-var baseerr = document.createElement("base");
-baseerr.href = "baseerr/";
+var basehref3 = document.createElement("base");
+basehref3.href = "base7/";
 var tmp = document.createElement("head");
-tmp.appendChild(baseerr);
+tmp.appendChild(basehref3);
 head.insertBefore(tmp, head.firstChild);
-verifyBase("base6/", "inserted base as grandchild of head");
-is(baseerr.parentNode.parentNode, head, "base got inserted correctly");
+verifyBase("base7/", "inserted base as grandchild of head at the beginning of head");
+is(basehref3.parentNode.parentNode, head, "base got inserted correctly");
 
 // Remove secondary bases
 var tmp, tmp2;
 for (tmp = head.firstChild; tmp = tmp.nextSibling; tmp) {
   if (tmp.localName == "base" && tmp != basehref0) {
     tmp2 = tmp.previousSibling;
     head.removeChild(tmp);
     tmp = tmp2;
   }
-  verifyBase("base6/", "remove unneeded base");
+  verifyBase("base7/", "remove unneeded base");
 }
 
 // Remove head
 document.documentElement.removeChild(head);
 verifyBase("", "removed head");
 
 // Insert base in body
-document.body.insertBefore(baseerr, document.body.firstChild);
-verifyBase("", "inserted base in body");
+document.body.insertBefore(basehref3, document.body.firstChild);
+verifyBase("base7/", "inserted base in body");
 
 </script>
 </pre>
 </body>
 </html>
 
--- a/content/canvas/src/CustomQS_Canvas2D.h
+++ b/content/canvas/src/CustomQS_Canvas2D.h
@@ -344,19 +344,22 @@ nsIDOMCanvasRenderingContext2D_PutImageD
             !JS_ValueToECMAInt32(cx, argv[4], &dirtyY) ||
             !JS_ValueToECMAInt32(cx, argv[5], &dirtyWidth) ||
             !JS_ValueToECMAInt32(cx, argv[6], &dirtyHeight))
             return JS_FALSE;
 
         hasDirtyRect = PR_TRUE;
     }
 
-    if (!JS_GetProperty(cx, dataObject, "data", tv.jsval_addr()) ||
-        JSVAL_IS_PRIMITIVE(tv.jsval_value()))
+    if (!JS_GetProperty(cx, dataObject, "data", tv.jsval_addr()))
         return JS_FALSE;
+
+    if (JSVAL_IS_PRIMITIVE(tv.jsval_value()))
+        return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
+
     darray = JSVAL_TO_OBJECT(tv.jsval_value());
 
     js::AutoValueRooter tsrc_tvr(cx);
 
     js::TypedArray *tsrc = NULL;
     if (darray->getClass() == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8] ||
         darray->getClass() == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8_CLAMPED])
     {
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -76,16 +76,17 @@ include $(topsrcdir)/config/rules.mk
 	test_2d.composite.image.destination-in.html \
 	test_2d.composite.image.source-in.html \
 	test_2d.composite.image.source-out.html \
 	test_2d.composite.uncovered.image.destination-in.html \
 	test_2d.composite.uncovered.image.source-in.html \
 	test_2d.composite.uncovered.image.source-out.html \
 	test_mozGetAsFile.html \
 	test_canvas_strokeStyle_getter.html \
+	test_bug613794.html \
 	$(NULL)
 
 ifneq (1_Linux,$(MOZ_SUITE)_$(OS_ARCH))
 # This test fails in Suite on Linux for some reason, disable it there
 _TEST_FILES_0 += test_2d.composite.uncovered.image.destination-atop.html
 endif
 
 # xor and lighter aren't well handled by cairo; they mostly work, but we don't want
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_bug613794.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=613794
+-->
+<head>
+  <title>Test for Bug 613794</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=613794">Mozilla Bug 613794</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 613794 **/
+
+var c = document.createElement("canvas");
+c.width = c.height = 1;
+
+c = c.getContext("2d");
+
+SimpleTest.waitForExplicitFinish();
+
+var threw = true;
+try {
+  c.putImageData({ width: 1, height: 1, data: [ 0, 0, 0, 0] }, 0, 0);
+  threw = false;
+} catch(e) {
+  threw = true;
+}
+
+is(threw, false, "Should be able to pass in custom imagedata objects with array data");
+
+threw = false;
+try {
+  c.putImageData({ width: 1, height: 1, data: null }, 0, 0);
+  threw = false;
+} catch(e) {
+  threw = e.code;
+}
+
+is(threw, DOMException.TYPE_MISMATCH_ERR,
+   "Should throw type error when data is not an array");
+SimpleTest.finish();
+
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/html/content/src/nsHTMLButtonElement.cpp
+++ b/content/html/content/src/nsHTMLButtonElement.cpp
@@ -442,17 +442,17 @@ nsHTMLButtonElement::PostHandleEvent(nsE
                   aVisitor.mPresContext->EventStateManager();
                 nsEventStateManager::SetActiveManager(
                   static_cast<nsEventStateManager*>(esm), this);
               }
               nsIFocusManager* fm = nsFocusManager::GetFocusManager();
               if (fm)
                 fm->SetFocus(this, nsIFocusManager::FLAG_BYMOUSE |
                                    nsIFocusManager::FLAG_NOSCROLL);
-              aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
+              aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_ANCHOR_ACTIONS;
             } else if (static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
                          nsMouseEvent::eMiddleButton ||
                        static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
                          nsMouseEvent::eRightButton) {
               // cancel all of these events for buttons
               //XXXsmaug What to do with these events? Why these should be cancelled?
               if (aVisitor.mDOMEvent) {
                 aVisitor.mDOMEvent->StopPropagation();
--- a/content/html/content/src/nsHTMLSharedElement.cpp
+++ b/content/html/content/src/nsHTMLSharedElement.cpp
@@ -372,148 +372,163 @@ nsHTMLSharedElement::IsAttributeMapped(c
     };
 
     return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
   }
 
   return nsGenericHTMLElement::IsAttributeMapped(aAttribute);
 }
 
-void
-SetBaseURIUsingFirstBaseWithHref(nsIContent* aHead, nsIContent* aMustMatch)
+static void
+SetBaseURIUsingFirstBaseWithHref(nsIDocument* aDocument, nsIContent* aMustMatch)
 {
-  NS_PRECONDITION(aHead && aHead->GetOwnerDoc() &&
-                  aHead->GetOwnerDoc()->GetHeadElement() == aHead,
-                  "Bad head");
+  NS_PRECONDITION(aDocument, "Need a document!");
 
-  nsIDocument* doc = aHead->GetOwnerDoc();
-
-  for (nsINode::ChildIterator iter(aHead); !iter.IsDone(); iter.Next()) {
-    nsIContent* child = iter;
-    if (child->NodeInfo()->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
+  for (nsIContent* child = aDocument->GetFirstChild(); child;
+       child = child->GetNextNode()) {
+    if (child->IsHTML(nsGkAtoms::base) &&
         child->HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
       if (aMustMatch && child != aMustMatch) {
         return;
       }
 
       // Resolve the <base> element's href relative to our document URI
       nsAutoString href;
       child->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
 
       nsCOMPtr<nsIURI> newBaseURI;
       nsContentUtils::NewURIWithDocumentCharset(
-        getter_AddRefs(newBaseURI), href, doc, doc->GetDocumentURI());
+        getter_AddRefs(newBaseURI), href, aDocument,
+        aDocument->GetDocumentURI());
 
       // Try to set our base URI.  If that fails, try to set base URI to null
-      nsresult rv = doc->SetBaseURI(newBaseURI);
+      nsresult rv = aDocument->SetBaseURI(newBaseURI);
       if (NS_FAILED(rv)) {
-        doc->SetBaseURI(nsnull);
+        aDocument->SetBaseURI(nsnull);
       }
       return;
     }
   }
 
-  doc->SetBaseURI(nsnull);
+  aDocument->SetBaseURI(nsnull);
+}
+
+static void
+SetBaseTargetUsingFirstBaseWithTarget(nsIDocument* aDocument,
+                                      nsIContent* aMustMatch)
+{
+  NS_PRECONDITION(aDocument, "Need a document!");
+
+  for (nsIContent* child = aDocument->GetFirstChild(); child;
+       child = child->GetNextNode()) {
+    if (child->IsHTML(nsGkAtoms::base) &&
+        child->HasAttr(kNameSpaceID_None, nsGkAtoms::target)) {
+      if (aMustMatch && child != aMustMatch) {
+        return;
+      }
+
+      nsString target;
+      child->GetAttr(kNameSpaceID_None, nsGkAtoms::target, target);
+      aDocument->SetBaseTarget(target);
+      return;
+    }
+  }
+
+  aDocument->SetBaseTarget(EmptyString());
 }
 
 nsresult
 nsHTMLSharedElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                              nsIAtom* aPrefix, const nsAString& aValue,
                              PRBool aNotify)
 {
   nsresult rv =  nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
                                                aValue, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If the href attribute of a <base> tag is changing, we may need to update
   // the document's base URI, which will cause all the links on the page to be
-  // re-resolved given the new base.
-  nsIContent* head;
-  if (mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
-      aName == nsGkAtoms::href &&
+  // re-resolved given the new base.  If the target attribute is changing, we
+  // similarly need to change the base target.
+  if (mNodeInfo->Equals(nsGkAtoms::base) &&
       aNameSpaceID == kNameSpaceID_None &&
-      IsInDoc() &&
-      (head = GetParent()) &&
-      head == GetOwnerDoc()->GetHeadElement()) {
-    SetBaseURIUsingFirstBaseWithHref(head, this);
+      IsInDoc()) {
+    if (aName == nsGkAtoms::href) {
+      SetBaseURIUsingFirstBaseWithHref(GetCurrentDoc(), this);
+    } else if (aName == nsGkAtoms::target) {
+      SetBaseTargetUsingFirstBaseWithTarget(GetCurrentDoc(), this);
+    }
   }
 
   return NS_OK;
 }
 
 nsresult
 nsHTMLSharedElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                                PRBool aNotify)
 {
   nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aName, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If we're the first <base> with an href and our href attribute is being
   // unset, then we're no longer the first <base> with an href, and we need to
-  // find the new one.
-  nsIContent* head;
-  if (mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
-      aName == nsGkAtoms::href &&
+  // find the new one.  Similar for target.
+  if (mNodeInfo->Equals(nsGkAtoms::base) &&
       aNameSpaceID == kNameSpaceID_None &&
-      IsInDoc() &&
-      (head = GetParent()) &&
-      head == GetOwnerDoc()->GetHeadElement()) {
-    SetBaseURIUsingFirstBaseWithHref(head, nsnull);
+      IsInDoc()) {
+    if (aName == nsGkAtoms::href) {
+      SetBaseURIUsingFirstBaseWithHref(GetCurrentDoc(), nsnull);
+    } else if (aName == nsGkAtoms::target) {
+      SetBaseTargetUsingFirstBaseWithTarget(GetCurrentDoc(), nsnull);
+    }
   }
 
   return NS_OK;
 }
 
 nsresult
 nsHTMLSharedElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                 nsIContent* aBindingParent,
                                 PRBool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // The document stores a pointer to its first <base> element, which we may
+  // The document stores a pointer to its base URI and base target, which we may
   // need to update here.
-  if (mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
-      HasAttr(kNameSpaceID_None, nsGkAtoms::href) &&
-      aDocument && aParent &&
-      aDocument->GetHeadElement() == aParent) {
-
-    SetBaseURIUsingFirstBaseWithHref(aParent, this);
+  if (mNodeInfo->Equals(nsGkAtoms::base) &&
+      aDocument) {
+    if (HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
+      SetBaseURIUsingFirstBaseWithHref(aDocument, this);
+    }
+    if (HasAttr(kNameSpaceID_None, nsGkAtoms::target)) {
+      SetBaseTargetUsingFirstBaseWithTarget(aDocument, this);
+    }
   }
 
   return NS_OK;
 }
 
 void
 nsHTMLSharedElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
-  nsIDocument* doc;
-  nsIContent* parent;
-  PRBool inHeadBase = mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
-                      (doc = GetCurrentDoc()) &&
-                      (parent = GetParent()) &&
-                      parent->NodeInfo()->Equals(nsGkAtoms::head,
-                                                 kNameSpaceID_XHTML);
+  nsIDocument* doc = GetCurrentDoc();
 
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 
   // If we're removing a <base> from a document, we may need to update the
-  // document's record of the first base node.
-  if (inHeadBase) {
-    // We might have gotten here as a result of the <head> being removed
-    // from the document. In that case we need to call SetBaseURI(nsnull)
-    Element* head = doc->GetHeadElement();
-    if (head) {
-      SetBaseURIUsingFirstBaseWithHref(head, nsnull);
+  // document's base URI and base target
+  if (doc && mNodeInfo->Equals(nsGkAtoms::base)) {
+    if (HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
+      SetBaseURIUsingFirstBaseWithHref(doc, nsnull);
     }
-    else {
-      doc->SetBaseURI(nsnull);
+    if (HasAttr(kNameSpaceID_None, nsGkAtoms::target)) {
+      SetBaseTargetUsingFirstBaseWithTarget(doc, nsnull);
     }
   }
 }
 
 nsMapRuleToAttributesFunc
 nsHTMLSharedElement::GetAttributeMappingFunction() const
 {
   if (mNodeInfo->Equals(nsGkAtoms::dir) || mNodeInfo->Equals(nsGkAtoms::menu)) {
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -245,12 +245,13 @@ include $(topsrcdir)/config/rules.mk
 		test_bug605125-2.html \
 		test_bug612730.html \
 		test_bug613722.html \
 		test_bug613979.html \
 		test_bug615833.html \
 		test_bug601030.html \
 		test_bug610687.html \
 		test_bug618948.html \
+		test_bug623291.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug623291.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=623291
+-->
+<head>
+  <title>Test for Bug 623291</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=623291">Mozilla Bug 623291</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<input id="textField" onfocus="next()" onblur="done();">
+<button id="b">a button</button>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 623291 **/
+
+function runTest() {
+  document.getElementById("textField").focus();
+}
+
+function next() {
+  synthesizeMouseAtCenter(document.getElementById('b'), {}, window);
+}
+
+function done() {
+  isnot(document.activeElement, document.getElementById("textField"),
+        "TextField should not be active anymore!");
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTest);
+
+</script>
+</pre>
+</body>
+</html>
--- a/docshell/base/nsDSURIContentListener.cpp
+++ b/docshell/base/nsDSURIContentListener.cpp
@@ -141,16 +141,22 @@ nsDSURIContentListener::DoContent(const 
     {
         // XXX: Why does this not stop the content too?
         mDocShell->Stop(nsIWebNavigation::STOP_NETWORK);
 
         mDocShell->SetLoadType(aIsContentPreferred ? LOAD_LINK : LOAD_NORMAL);
     }
 
     rv = mDocShell->CreateContentViewer(aContentType, request, aContentHandler);
+
+    if (rv == NS_ERROR_REMOTE_XUL) {
+      request->Cancel(rv);
+      return NS_OK;
+    }
+
     if (NS_FAILED(rv)) {
        // it's okay if we don't know how to handle the content   
         return NS_OK;
     }
 
     if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) {
         nsCOMPtr<nsIDOMWindowInternal> domWindow = do_GetInterface(static_cast<nsIDocShell*>(mDocShell));
         NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3917,16 +3917,46 @@ nsDocShell::DisplayLoadError(nsresult aE
         case NS_ERROR_PROXY_CONNECTION_REFUSED:
             // Proxy connection was refused.
             error.AssignLiteral("proxyConnectFailure");
             break;
         case NS_ERROR_INVALID_CONTENT_ENCODING:
             // Bad Content Encoding.
             error.AssignLiteral("contentEncodingError");
             break;
+        case NS_ERROR_REMOTE_XUL:
+        {
+            error.AssignLiteral("remoteXUL");
+
+            /**
+             * We want to set an hardcoded messageStr which uses the
+             * brandShortName.
+             */
+            nsCOMPtr<nsIStringBundleService> stringBundleService =
+                mozilla::services::GetStringBundleService();
+            if (!stringBundleService) {
+                return NS_ERROR_FAILURE;
+            }
+
+            nsCOMPtr<nsIStringBundle> brandBundle;
+            rv = stringBundleService->CreateBundle(kBrandBundleURL,
+                                                   getter_AddRefs(brandBundle));
+            NS_ENSURE_SUCCESS(rv, rv);
+
+            nsXPIDLString brandName;
+            rv = brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
+                                                getter_Copies(brandName));
+
+            // We could use something like nsTextFormatter::smprintf.
+            messageStr.AssignLiteral("This page uses an unsupported technology "
+                                     "that is no longer available in ");
+            messageStr.Append(brandName);
+            messageStr.AppendLiteral(".");
+            break;
+        }
         case NS_ERROR_UNSAFE_CONTENT_TYPE:
             // Channel refused to load from an unrecognized content type.
             error.AssignLiteral("unsafeContentType");
             break;
         }
     }
 
     // Test if the error should be displayed
@@ -6248,16 +6278,17 @@ nsDocShell::EndPageLoad(nsIWebProgress *
         else if (aStatus == NS_ERROR_NET_TIMEOUT ||
                  aStatus == NS_ERROR_REDIRECT_LOOP ||
                  aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
                  aStatus == NS_ERROR_NET_INTERRUPT ||
                  aStatus == NS_ERROR_NET_RESET ||
                  aStatus == NS_ERROR_MALWARE_URI ||
                  aStatus == NS_ERROR_PHISHING_URI ||
                  aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
+                 aStatus == NS_ERROR_REMOTE_XUL ||
                  NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) {
             DisplayLoadError(aStatus, url, nsnull, aChannel);
         }
         else if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
             /* A document that was requested to be fetched *only* from
              * the cache is not in cache. May be this is one of those 
              * postdata results. Throw a  dialog to the user,
              * saying that the page has expired from cache and ask if 
@@ -7287,17 +7318,17 @@ nsDocShell::CreateContentViewer(const ch
     NS_ASSERTION(mLoadGroup, "Someone ignored return from Init()?");
 
     // Instantiate the content viewer object
     nsCOMPtr<nsIContentViewer> viewer;
     nsresult rv = NewContentViewerObj(aContentType, request, mLoadGroup,
                                       aContentHandler, getter_AddRefs(viewer));
 
     if (NS_FAILED(rv))
-        return NS_ERROR_FAILURE;
+        return rv;
 
     // Notify the current document that it is about to be unloaded!!
     //
     // It is important to fire the unload() notification *before* any state
     // is changed within the DocShell - otherwise, javascript will get the
     // wrong information :-(
     //
 
@@ -7469,24 +7500,24 @@ nsDocShell::NewContentViewerObj(const ch
     nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
         cutils->FindInternalContentViewer(aContentType);
     if (!docLoaderFactory) {
         return NS_ERROR_FAILURE;
     }
 
     // Now create an instance of the content viewer
     // nsLayoutDLF makes the determination if it should be a "view-source" instead of "view"
-    NS_ENSURE_SUCCESS(docLoaderFactory->CreateInstance("view",
-                                                       aOpenedChannel,
-                                                       aLoadGroup, aContentType,
-                                                       static_cast<nsIContentViewerContainer*>(this),
-                                                       nsnull,
-                                                       aContentHandler,
-                                                       aViewer),
-                      NS_ERROR_FAILURE);
+    nsresult rv = docLoaderFactory->CreateInstance("view",
+                                                   aOpenedChannel,
+                                                   aLoadGroup, aContentType,
+                                                   static_cast<nsIContentViewerContainer*>(this),
+                                                   nsnull,
+                                                   aContentHandler,
+                                                   aViewer);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     (*aViewer)->SetContainer(static_cast<nsIContentViewerContainer *>(this));
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
 {
--- a/docshell/base/nsDocShellEnumerator.cpp
+++ b/docshell/base/nsDocShellEnumerator.cpp
@@ -65,19 +65,21 @@ NS_IMETHODIMP nsDocShellEnumerator::GetN
   *outCurItem = nsnull;
   
   nsresult rv = EnsureDocShellArray();
   if (NS_FAILED(rv)) return rv;
   
   if (mCurIndex >= mItemArray.Length()) {
     return NS_ERROR_FAILURE;
   }
-  
+
   // post-increment is important here
-  return CallQueryInterface(mItemArray[mCurIndex++], outCurItem);
+  nsCOMPtr<nsISupports> item = do_QueryReferent(mItemArray[mCurIndex++], &rv);
+  item.forget(outCurItem);
+  return rv;
 }
 
 /* boolean hasMoreElements (); */
 NS_IMETHODIMP nsDocShellEnumerator::HasMoreElements(PRBool *outHasMore)
 {
   NS_ENSURE_ARG_POINTER(outHasMore);
   *outHasMore = PR_FALSE;
 
@@ -86,24 +88,24 @@ NS_IMETHODIMP nsDocShellEnumerator::HasM
 
   *outHasMore = (mCurIndex < mItemArray.Length());
   return NS_OK;
 }
 
 nsresult nsDocShellEnumerator::GetEnumerationRootItem(nsIDocShellTreeItem * *aEnumerationRootItem)
 {
   NS_ENSURE_ARG_POINTER(aEnumerationRootItem);
-  *aEnumerationRootItem = mRootItem;
-  NS_IF_ADDREF(*aEnumerationRootItem);
+  nsCOMPtr<nsIDocShellTreeItem> item = do_QueryReferent(mRootItem);
+  item.forget(aEnumerationRootItem);
   return NS_OK;
 }
 
 nsresult nsDocShellEnumerator::SetEnumerationRootItem(nsIDocShellTreeItem * aEnumerationRootItem)
 {
-  mRootItem = aEnumerationRootItem;
+  mRootItem = do_GetWeakReference(aEnumerationRootItem);
   ClearState();
   return NS_OK;
 }
 
 nsresult nsDocShellEnumerator::GetEnumDocShellType(PRInt32 *aEnumerationItemType)
 {
   NS_ENSURE_ARG_POINTER(aEnumerationItemType);
   *aEnumerationItemType = mDocShellType;
@@ -137,35 +139,36 @@ nsresult nsDocShellEnumerator::EnsureDoc
 nsresult nsDocShellEnumerator::ClearState()
 {
   mItemArray.Clear();
   mArrayValid = PR_FALSE;
   mCurIndex = 0;
   return NS_OK;
 }
 
-nsresult nsDocShellEnumerator::BuildDocShellArray(nsTArray<nsIDocShellTreeItem*>& inItemArray)
+nsresult nsDocShellEnumerator::BuildDocShellArray(nsTArray<nsWeakPtr>& inItemArray)
 {
   NS_ENSURE_TRUE(mRootItem, NS_ERROR_NOT_INITIALIZED);
   inItemArray.Clear();
-  return BuildArrayRecursive(mRootItem, inItemArray);
+  nsCOMPtr<nsIDocShellTreeItem> item = do_QueryReferent(mRootItem);
+  return BuildArrayRecursive(item, inItemArray);
 }
 
-nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsIDocShellTreeItem*>& inItemArray)
+nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray)
 {
   nsresult rv;
   nsCOMPtr<nsIDocShellTreeNode> itemAsNode = do_QueryInterface(inItem, &rv);
   if (NS_FAILED(rv)) return rv;
 
   PRInt32   itemType;
   // add this item to the array
   if ((mDocShellType == nsIDocShellTreeItem::typeAll) ||
       (NS_SUCCEEDED(inItem->GetItemType(&itemType)) && (itemType == mDocShellType)))
   {
-    if (!inItemArray.AppendElement(inItem))
+    if (!inItemArray.AppendElement(do_GetWeakReference(inItem)))
       return NS_ERROR_OUT_OF_MEMORY;
   }
 
   PRInt32   numChildren;
   rv = itemAsNode->GetChildCount(&numChildren);
   if (NS_FAILED(rv)) return rv;
   
   for (PRInt32 i = 0; i < numChildren; ++i)
@@ -177,17 +180,17 @@ nsresult nsDocShellForwardsEnumerator::B
     rv = BuildArrayRecursive(curChild, inItemArray);
     if (NS_FAILED(rv)) return rv;
   }
 
   return NS_OK;
 }
 
 
-nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsIDocShellTreeItem*>& inItemArray)
+nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray)
 {
   nsresult rv;
   nsCOMPtr<nsIDocShellTreeNode> itemAsNode = do_QueryInterface(inItem, &rv);
   if (NS_FAILED(rv)) return rv;
 
   PRInt32   numChildren;
   rv = itemAsNode->GetChildCount(&numChildren);
   if (NS_FAILED(rv)) return rv;
@@ -202,17 +205,17 @@ nsresult nsDocShellBackwardsEnumerator::
     if (NS_FAILED(rv)) return rv;
   }
 
   PRInt32   itemType;
   // add this item to the array
   if ((mDocShellType == nsIDocShellTreeItem::typeAll) ||
       (NS_SUCCEEDED(inItem->GetItemType(&itemType)) && (itemType == mDocShellType)))
   {
-    if (!inItemArray.AppendElement(inItem))
+    if (!inItemArray.AppendElement(do_GetWeakReference(inItem)))
       return NS_ERROR_OUT_OF_MEMORY;
   }
 
 
   return NS_OK;
 }
 
 
--- a/docshell/base/nsDocShellEnumerator.h
+++ b/docshell/base/nsDocShellEnumerator.h
@@ -38,16 +38,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 
 
 #include "nsIEnumerator.h"
 
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
+#include "nsIWeakReference.h"
+#include "nsIWeakReferenceUtils.h"
 
 class nsIDocShellTreeItem;
 
 
 /*
 // {13cbc281-35ae-11d5-be5b-bde0edece43c}
 #define NS_DOCSHELL_FORWARDS_ENUMERATOR_CID  \
 { 0x13cbc281, 0x35ae, 0x11d5, { 0xbe, 0x5b, 0xbd, 0xe0, 0xed, 0xec, 0xe4, 0x3c } }
@@ -93,24 +95,24 @@ public:
     
   nsresult                    First();
 
 protected:
 
   nsresult                    EnsureDocShellArray();
   nsresult                    ClearState();
   
-  nsresult                    BuildDocShellArray(nsTArray<nsIDocShellTreeItem*>& inItemArray);
-  virtual nsresult            BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsIDocShellTreeItem*>& inItemArray) = 0;
+  nsresult                    BuildDocShellArray(nsTArray<nsWeakPtr>& inItemArray);
+  virtual nsresult            BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray) = 0;
     
 protected:
 
-  nsIDocShellTreeItem*        mRootItem;      // weak ref!
+  nsWeakPtr                   mRootItem;      // weak ref!
   
-  nsTArray<nsIDocShellTreeItem*> mItemArray; // flattened list of items with matching type
+  nsTArray<nsWeakPtr>         mItemArray;     // flattened list of items with matching type
   PRUint32                    mCurIndex;
   
   PRInt32                     mDocShellType;  // only want shells of this type
   PRPackedBool                mArrayValid;    // is mItemArray up to date?
 
   const PRInt8                mEnumerationDirection;
 };
 
@@ -121,25 +123,25 @@ public:
 
                               nsDocShellForwardsEnumerator()
                               : nsDocShellEnumerator(enumerateForwards)
                               {                              
                               }
 
 protected:
 
-  virtual nsresult            BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsIDocShellTreeItem*>& inItemArray);
+  virtual nsresult            BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray);
 
 };
 
 class nsDocShellBackwardsEnumerator : public nsDocShellEnumerator
 {
 public:
 
                               nsDocShellBackwardsEnumerator()
                               : nsDocShellEnumerator(enumerateBackwards)
                               {                              
                               }
 protected:
 
-  virtual nsresult            BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsIDocShellTreeItem*>& inItemArray);
+  virtual nsresult            BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray);
 
 };
--- a/docshell/resources/content/netError.xhtml
+++ b/docshell/resources/content/netError.xhtml
@@ -181,16 +181,22 @@
           faviconParent.removeChild(favicon);
           favicon.setAttribute("href", "chrome://global/skin/icons/" + className + "_favicon.png");
           faviconParent.appendChild(favicon);
         }
         if (className == "expertBadCert") {
           showSecuritySection();
         }
 
+        if (err == "remoteXUL") {
+          // Remove the "Try again" button for remote XUL errors given that
+          // it is useless.
+          document.getElementById("errorTryAgain").style.display = "none";
+        }
+
         if (err == "cspFrameAncestorBlocked") {
           // Remove the "Try again" button for CSP frame ancestors violation, since it's
           // almost certainly useless. (Bug 553180)
           document.getElementById("errorTryAgain").style.display = "none";
         }
 
         if (err == "nssBadCert") {
           // Remove the "Try again" button for security exceptions, since it's
@@ -317,16 +323,17 @@
         <h1 id="et_proxyResolveFailure">&proxyResolveFailure.title;</h1>
         <h1 id="et_proxyConnectFailure">&proxyConnectFailure.title;</h1>
         <h1 id="et_contentEncodingError">&contentEncodingError.title;</h1>
         <h1 id="et_unsafeContentType">&unsafeContentType.title;</h1>
         <h1 id="et_nssFailure2">&nssFailure2.title;</h1>
         <h1 id="et_nssBadCert">&nssBadCert.title;</h1>
         <h1 id="et_malwareBlocked">&malwareBlocked.title;</h1>
         <h1 id="et_cspFrameAncestorBlocked">&cspFrameAncestorBlocked.title;</h1>
+        <h1 id="et_remoteXUL">Remote XUL</h1>
       </div>
       <div id="errorDescriptionsContainer">
         <div id="ed_generic">&generic.longDesc;</div>
         <div id="ed_dnsNotFound">&dnsNotFound.longDesc;</div>
         <div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
         <div id="ed_malformedURI">&malformedURI.longDesc;</div>
         <div id="ed_protocolNotFound">&protocolNotFound.longDesc;</div>
         <div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
@@ -340,16 +347,17 @@
         <div id="ed_proxyResolveFailure">&proxyResolveFailure.longDesc;</div>
         <div id="ed_proxyConnectFailure">&proxyConnectFailure.longDesc;</div>
         <div id="ed_contentEncodingError">&contentEncodingError.longDesc;</div>
         <div id="ed_unsafeContentType">&unsafeContentType.longDesc;</div>
         <div id="ed_nssFailure2">&nssFailure2.longDesc;</div>
         <div id="ed_nssBadCert">&nssBadCert.longDesc2;</div>
         <div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div>
         <div id="ed_cspFrameAncestorBlocked">&cspFrameAncestorBlocked.longDesc;</div>
+        <div id="ed_remoteXUL"><ul><li>Please contact the website owners to inform them of this problem.</li></ul></div>
       </div>
     </div>
 
     <!-- PAGE CONTAINER (for styling purposes only) -->
     <div id="errorPageContainer">
     
       <!-- Error Title -->
       <div id="errorTitle">
--- a/dom/plugins/PluginInstanceChild.cpp
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -2539,17 +2539,16 @@ PluginInstanceChild::PaintRectToPlatform
 {
     UpdateWindowAttributes();
 #ifdef MOZ_X11
 #if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
     // On maemo5 we do support Image rendering NPAPI
     if (mMaemoImageRendering &&
         aSurface->GetType() == gfxASurface::SurfaceTypeImage) {
         aSurface->Flush();
-        mPendingPluginCall = PR_TRUE;
         gfxImageSurface* image = static_cast<gfxImageSurface*>(aSurface);
         NPImageExpose imgExp;
         imgExp.depth = gfxUtils::ImageFormatToDepth(image->Format());
         imgExp.x = aRect.x;
         imgExp.y = aRect.y;
         imgExp.width = aRect.width;
         imgExp.height = aRect.height;
         imgExp.stride = image->Stride();
@@ -2572,67 +2571,61 @@ PluginInstanceChild::PaintRectToPlatform
         exposeEvent.height = imgExp.height;
         exposeEvent.count = 0;
         // information not set:
         exposeEvent.serial = 0;
         exposeEvent.send_event = False;
         exposeEvent.major_code = 0;
         exposeEvent.minor_code = 0;
         mPluginIface->event(&mData, reinterpret_cast<void*>(&exposeEvent));
-        mPendingPluginCall = PR_FALSE;
         return;
     }
 #endif
     NS_ASSERTION(aSurface->GetType() == gfxASurface::SurfaceTypeXlib,
                  "Non supported platform surface type");
 
-    mPendingPluginCall = true;
     NPEvent pluginEvent;
     XGraphicsExposeEvent& exposeEvent = pluginEvent.xgraphicsexpose;
     exposeEvent.type = GraphicsExpose;
     exposeEvent.display = mWsInfo.display;
     exposeEvent.drawable = static_cast<gfxXlibSurface*>(aSurface)->XDrawable();
     exposeEvent.x = aRect.x;
     exposeEvent.y = aRect.y;
     exposeEvent.width = aRect.width;
     exposeEvent.height = aRect.height;
     exposeEvent.count = 0;
     // information not set:
     exposeEvent.serial = 0;
     exposeEvent.send_event = False;
     exposeEvent.major_code = 0;
     exposeEvent.minor_code = 0;
     mPluginIface->event(&mData, reinterpret_cast<void*>(&exposeEvent));
-    mPendingPluginCall = false;
     return;
 #endif
 
 #ifdef XP_WIN
     NS_ASSERTION(SharedDIBSurface::IsSharedDIBSurface(aSurface),
                  "Expected (SharedDIB) image surface.");
 
-    mPendingPluginCall = true;
-
     // This rect is in the window coordinate space. aRect is in the plugin
     // coordinate space.
     RECT rect = {
         mWindow.x + aRect.x,
         mWindow.y + aRect.y,
         mWindow.x + aRect.x + aRect.width,
         mWindow.y + aRect.y + aRect.height
     };
     NPEvent paintEvent = {
         WM_PAINT,
         uintptr_t(mWindow.window),
         uintptr_t(&rect)
     };
     ::SetViewportOrgEx((HDC) mWindow.window, -mWindow.x, -mWindow.y, NULL);
 
     mPluginIface->event(&mData, reinterpret_cast<void*>(&paintEvent));
-    mPendingPluginCall = false;
     return;
 #endif
 
     NS_RUNTIMEABORT("Surface type not implemented.");
 }
 
 void
 PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect,
@@ -2732,16 +2725,19 @@ PluginInstanceChild::PaintRectWithAlphaE
 
 bool
 PluginInstanceChild::ShowPluginFrame()
 {
     if (mPendingPluginCall) {
         return false;
     }
 
+    AutoRestore<bool> pending(mPendingPluginCall);
+    mPendingPluginCall = true;
+
     if (!EnsureCurrentBuffer()) {
         return false;
     }
 
     // Make expose rect not bigger than clip rect
     mAccumulatedInvalidRect.IntersectRect(mAccumulatedInvalidRect,
         nsIntRect(mWindow.clipRect.left, mWindow.clipRect.top,
                   mWindow.clipRect.right - mWindow.clipRect.left,
--- a/embedding/components/printingui/src/win/nsPrintDialogUtil.cpp
+++ b/embedding/components/printingui/src/win/nsPrintDialogUtil.cpp
@@ -867,21 +867,16 @@ ShowNativePrintDialog(HWND              
     if(!::OpenPrinterW(const_cast<wchar_t*>(printerName.get()), &hPrinter, NULL)) {
       // If the last used printer is not found, we should use default printer.
       GetDefaultPrinterNameFromGlobalPrinters(printerName);
     } else {
       ::ClosePrinter(hPrinter);
     }
   }
 
-  NS_ASSERTION(!printerName.IsEmpty(), "We have to have a printer name");
-  if (printerName.IsEmpty()) {
-    return NS_ERROR_FAILURE;
-  }
-
   // Now create a DEVNAMES struct so the the dialog is initialized correctly.
 
   PRUint32 len = printerName.Length();
   hDevNames = (HGLOBAL)::GlobalAlloc(GHND, sizeof(wchar_t) * (len + 1) + 
                                      sizeof(DEVNAMES));
   if (!hDevNames) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -686,16 +686,53 @@ gfxWindowsPlatform::WindowsOSVersion()
             winVersion = kWindowsUnknown;
         } else {
             winVersion = PRInt32(vinfo.dwMajorVersion << 16) + vinfo.dwMinorVersion;
         }
     }
     return winVersion;
 }
 
+void 
+gfxWindowsPlatform::GetDLLVersion(PRUnichar *aDLLPath, nsAString& aVersion)
+{
+    DWORD versInfoSize, vers[4] = {0};
+    // version info not available case
+    aVersion.Assign(NS_LITERAL_STRING("0.0.0.0"));
+    versInfoSize = GetFileVersionInfoSizeW(aDLLPath, NULL);
+    nsAutoTArray<BYTE,512> versionInfo;
+    
+    if (!versionInfo.AppendElements(PRUint32(versInfoSize))) {
+        return;
+    }
+    if (!GetFileVersionInfoW(aDLLPath, NULL, versInfoSize, 
+           LPBYTE(versionInfo.Elements()))) {
+        return;
+    } 
+
+    UINT len;
+    VS_FIXEDFILEINFO *fileInfo;
+    if (!VerQueryValue(LPBYTE(versionInfo.Elements()), TEXT("\\"),
+           (LPVOID *)&fileInfo , &len)) {
+        return;
+    }
+
+    DWORD fileVersMS = fileInfo->dwFileVersionMS; 
+    DWORD fileVersLS = fileInfo->dwFileVersionLS;
+
+    vers[0] = HIWORD(fileVersMS);
+    vers[1] = LOWORD(fileVersMS);
+    vers[2] = HIWORD(fileVersLS);
+    vers[3] = LOWORD(fileVersLS);
+
+    char buf[256];
+    sprintf(buf, "%d.%d.%d.%d", vers[0], vers[1], vers[2], vers[3]);
+    aVersion.Assign(NS_ConvertUTF8toUTF16(buf));
+}
+
 void
 gfxWindowsPlatform::FontsPrefsChanged(nsIPrefBranch *aPrefBranch, const char *aPref)
 {
     PRBool clearTextFontCaches = PR_TRUE;
 
     gfxPlatform::FontsPrefsChanged(aPrefBranch, aPref);
 
     if (!aPref) {
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -222,16 +222,18 @@ public:
         kWindowsXP = 0x50001,
         kWindowsServer2003 = 0x50002,
         kWindowsVista = 0x60000,
         kWindows7 = 0x60001
     };
 
     static PRInt32 WindowsOSVersion();
 
+    static void GetDLLVersion(PRUnichar *aDLLPath, nsAString& aVersion);
+
     virtual void FontsPrefsChanged(nsIPrefBranch *aPrefBranch, const char *aPref);
 
 #ifdef CAIRO_HAS_DWRITE_FONT
     IDWriteFactory *GetDWriteFactory() { return mDWriteFactory; }
     inline PRBool DWriteEnabled() { return mUseDirectWrite; }
 #else
     inline PRBool DWriteEnabled() { return PR_FALSE; }
 #endif
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -8786,19 +8786,39 @@ nsCSSFrameConstructor::ReplicateFixedFra
   // Iterate across fixed frames and replicate each whose placeholder is a
   // descendant of aFrame. (We don't want to explicitly copy placeholders that
   // are within fixed frames, because that would cause duplicates on the new
   // page - bug 389619)
   for (nsIFrame* fixed = firstFixed; fixed; fixed = fixed->GetNextSibling()) {
     nsIFrame* prevPlaceholder = mPresShell->FrameManager()->GetPlaceholderFrameFor(fixed);
     if (prevPlaceholder &&
         nsLayoutUtils::IsProperAncestorFrame(prevCanvasFrame, prevPlaceholder)) {
-      nsresult rv = ConstructFrame(state, fixed->GetContent(),
-                                   canvasFrame, fixedPlaceholders);
-      NS_ENSURE_SUCCESS(rv, rv);
+      // We want to use the same style as the primary style frame for
+      // our content
+      nsIContent* content = fixed->GetContent();
+      nsStyleContext* styleContext =
+        nsLayoutUtils::GetStyleFrame(content->GetPrimaryFrame())->
+          GetStyleContext();
+      FrameConstructionItemList items;
+      AddFrameConstructionItemsInternal(state, content, canvasFrame,
+                                        content->Tag(),
+                                        content->GetNameSpaceID(),
+                                        PR_TRUE,
+                                        styleContext,
+                                        ITEM_ALLOW_XBL_BASE |
+                                          ITEM_ALLOW_PAGE_BREAK,
+                                        items);
+      for (FCItemIterator iter(items); !iter.IsDone(); iter.Next()) {
+        NS_ASSERTION(iter.item().DesiredParentType() ==
+                       GetParentType(canvasFrame),
+                     "This is not going to work");
+        nsresult rv =
+          ConstructFramesFromItem(state, iter, canvasFrame, fixedPlaceholders);
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
     }
   }
 
   // Add the placeholders to our primary child list.
   // XXXbz this is a little screwed up, since the fixed frames will have 
   // broken auto-positioning. Oh, well.
   NS_ASSERTION(!canvasFrame->GetFirstChild(nsnull),
                "leaking frames; doc root continuation must be empty");
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -2283,17 +2283,17 @@ nsCSSRendering::PaintBackgroundWithSC(ns
     // don't need to draw outside the padding area.  In either case,
     // if the borders are rounded, make sure we use the same inner
     // radii as the border code will.
     // The background-color is drawn based on the bottom
     // background-clip.
     currentBackgroundClip = bg->BottomLayer().mClip;
     isSolidBorder =
       (aFlags & PAINTBG_WILL_PAINT_BORDER) && IsOpaqueBorder(aBorder);
-    if (isSolidBorder)
+    if (isSolidBorder && currentBackgroundClip == NS_STYLE_BG_CLIP_BORDER)
       currentBackgroundClip = NS_STYLE_BG_CLIP_PADDING;
     SetupBackgroundClip(ctx, currentBackgroundClip, aForFrame,
                         aBorderArea, aDirtyRect, haveRoundedCorners,
                         bgRadii, appUnitsPerPixel, &autoSR,
                         &bgClipArea, &dirtyRect, &dirtyRectGfx);
   }
 
   // If we might be using a background color, go ahead and set it now.
--- a/layout/build/nsContentDLF.cpp
+++ b/layout/build/nsContentDLF.cpp
@@ -276,18 +276,21 @@ nsContentDLF::CreateInstance(const char*
                             aContainer, kSVGDocumentCID,
                             aDocListener, aDocViewer);
     }
   }
 
   // Try XUL
   typeIndex = 0;
   while (gXULTypes[typeIndex]) {
-    if (0 == PL_strcmp(gXULTypes[typeIndex++], aContentType) &&
-        MayUseXULXBL(aChannel)) {
+    if (0 == PL_strcmp(gXULTypes[typeIndex++], aContentType)) {
+      if (!MayUseXULXBL(aChannel)) {
+        return NS_ERROR_REMOTE_XUL;
+      }
+
       return CreateXULDocument(aCommand,
                                aChannel, aLoadGroup,
                                aContentType, aContainer,
                                aExtraInfo, aDocListener, aDocViewer);
     }
   }
 
 #ifdef MOZ_MEDIA
--- a/layout/printing/nsPrintObject.cpp
+++ b/layout/printing/nsPrintObject.cpp
@@ -39,37 +39,44 @@
 #include "nsIContentViewer.h"
 #include "nsIDOMDocument.h"
 #include "nsContentUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsGkAtoms.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIDocShellTreeItem.h"
-
+#include "nsIBaseWindow.h"
+                                                   
 //---------------------------------------------------
 //-- nsPrintObject Class Impl
 //---------------------------------------------------
 nsPrintObject::nsPrintObject() :
   mContent(nsnull), mFrameType(eFrame), mParent(nsnull),
   mHasBeenPrinted(PR_FALSE), mDontPrint(PR_TRUE), mPrintAsIs(PR_FALSE),
-  mSharedPresShell(PR_FALSE), mInvisible(PR_FALSE),
+  mSharedPresShell(PR_FALSE), mInvisible(PR_FALSE), mDidCreateDocShell(PR_FALSE),
   mShrinkRatio(1.0), mZoomRatio(1.0)
 {
 }
 
 
 nsPrintObject::~nsPrintObject()
 {
   for (PRUint32 i=0;i<mKids.Length();i++) {
     nsPrintObject* po = mKids[i];
     delete po;
   }
 
   DestroyPresentation();
+  if (mDidCreateDocShell && mDocShell) {
+    nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(mDocShell));
+    if (baseWin) {
+      baseWin->Destroy();
+    }
+  }                            
   mDocShell = nsnull;
   mTreeOwner = nsnull; // mTreeOwner must be released after mDocShell; 
 }
 
 //------------------------------------------------------------------
 nsresult 
 nsPrintObject::Init(nsIDocShell* aDocShell, nsIDOMDocument* aDoc,
                     PRBool aPrintPreview)
@@ -81,16 +88,17 @@ nsPrintObject::Init(nsIDocShell* aDocShe
   } else {
     mTreeOwner = do_GetInterface(aDocShell);
     nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(aDocShell);
     PRInt32 itemType = 0;
     item->GetItemType(&itemType);
     // Create a container docshell for printing.
     mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
     NS_ENSURE_TRUE(mDocShell, NS_ERROR_OUT_OF_MEMORY);
+    mDidCreateDocShell = PR_TRUE;
     nsCOMPtr<nsIDocShellTreeItem> newItem = do_QueryInterface(mDocShell);
     newItem->SetItemType(itemType);
     newItem->SetTreeOwner(mTreeOwner);
   }
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIDOMDocument> dummy = do_GetInterface(mDocShell);
   nsCOMPtr<nsIContentViewer> viewer;
--- a/layout/printing/nsPrintObject.h
+++ b/layout/printing/nsPrintObject.h
@@ -84,16 +84,17 @@ public:
   nsTArray<nsPrintObject*> mKids;
   nsPrintObject*   mParent;
   PRPackedBool     mHasBeenPrinted;
   PRPackedBool     mDontPrint;
   PRPackedBool     mPrintAsIs;
   PRPackedBool     mSharedPresShell;
   PRPackedBool     mInvisible;        // Indicates PO is set to not visible by CSS
   PRPackedBool     mPrintPreview;
+  PRPackedBool     mDidCreateDocShell;
   float            mShrinkRatio;
   float            mZoomRatio;
 
 private:
   nsPrintObject& operator=(const nsPrintObject& aOther); // not implemented
 
 };
 
new file mode 100644
--- /dev/null
+++ b/layout/reftests/backgrounds/background-clip-2-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <div style="padding: 10px;
+                width: 100px;
+                height: 100px;
+                border: 10px solid black">
+      <div style="width: 100px; height: 100px; background: black">
+      </div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/backgrounds/background-clip-2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <div style="padding: 10px;
+                width: 100px;
+                height: 100px;
+                background-color: black;
+                border: 10px solid black;
+                background-clip: content-box;">
+    </div>
+  </body>
+</html>
--- a/layout/reftests/backgrounds/reftest.list
+++ b/layout/reftests/backgrounds/reftest.list
@@ -22,16 +22,17 @@
 == continuous-inline-3.html continuous-inline-3-ref.html
 == continuous-inline-4a.html continuous-inline-4-ref.html
 == continuous-inline-4b.html continuous-inline-4-ref.html
 == continuous-inline-5a.html continuous-inline-5-ref.html
 == continuous-inline-5b.html continuous-inline-5-ref.html
 == background-redraw-237766.html background-redraw-237766-ref.html
 
 == background-clip-1.html background-clip-1-ref.html
+== background-clip-2.html background-clip-2-ref.html
 
 == background-size-auto-auto.html background-size-auto-ref.html
 == background-size-auto.html background-size-auto-ref.html
 == background-size-contain.html background-size-contain-ref.html
 == background-size-cover.html background-size-cover-ref.html
 == background-size-auto-length.html background-size-auto-length-ref.html
 == background-size-length-auto.html background-size-auto-length-ref.html
 == background-size-length.html background-size-auto-length-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/printing/577450-1-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html class="reftest-print">
+  <body>
+    <div style="position: fixed; color: green; font-size: 2em">Big green text</div>
+    <!-- force two pages -->
+    <div style="height: 3in; width: 2in"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/printing/577450-1.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html class="reftest-print">
+  <body style="color: green; font-size: 2em">
+    <div style="position: fixed">Big green text</div>
+    <!-- force two pages -->
+    <div style="height: 3in; width: 2in"></div>
+  </body>
+</html>
--- a/layout/reftests/printing/reftest.list
+++ b/layout/reftests/printing/reftest.list
@@ -4,8 +4,9 @@
 # Bugs
 == 272830-1.html 272830-1-ref.html
 == 318022-1.html 318022-1-ref.html
 == 403669-1.html 403669-1-ref.html
 == 381497-n.html 381497-f.html
 == test-async-print.html 272830-1-ref.html
 == 129941-1a.html 129941-1-ref.html
 == 129941-1b.html 129941-1-ref.html
+== 577450-1.html 577450-1-ref.html
--- a/modules/plugin/base/src/nsPluginTags.cpp
+++ b/modules/plugin/base/src/nsPluginTags.cpp
@@ -280,17 +280,17 @@ static nsresult ConvertToUTF8(nsIUnicode
   buffer.SetLength(outUnicodeLen);
   CopyUTF16toUTF8(buffer, aString);
   
   return NS_OK;
 }
 
 nsresult nsPluginTag::EnsureMembersAreUTF8()
 {
-#ifdef XP_WIN
+#if defined(XP_WIN) || defined(XP_MACOSX)
   return NS_OK;
 #else
   nsresult rv;
   
   nsCOMPtr<nsIPlatformCharset> pcs =
   do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIUnicodeDecoder> decoder;
--- a/modules/plugin/base/src/nsPluginsDirDarwin.cpp
+++ b/modules/plugin/base/src/nsPluginsDirDarwin.cpp
@@ -119,22 +119,37 @@ PRBool nsPluginsDir::IsPluginFile(nsIFil
     return PR_FALSE;
   }
   return PR_TRUE;
 }
 
 // Caller is responsible for freeing returned buffer.
 static char* CFStringRefToUTF8Buffer(CFStringRef cfString)
 {
-  int bufferLength = ::CFStringGetLength(cfString) + 1;
+  const char* buffer = ::CFStringGetCStringPtr(cfString, kCFStringEncodingUTF8);
+  if (buffer) {
+    return PL_strdup(buffer);
+  }
+
+  int bufferLength =
+    ::CFStringGetMaximumSizeForEncoding(::CFStringGetLength(cfString),
+                                        kCFStringEncodingUTF8) + 1;
   char* newBuffer = static_cast<char*>(NS_Alloc(bufferLength));
-  if (newBuffer && !::CFStringGetCString(cfString, newBuffer, bufferLength, kCFStringEncodingUTF8)) {
+  if (!newBuffer) {
+    return nsnull;
+  }
+
+  if (!::CFStringGetCString(cfString, newBuffer, bufferLength,
+                            kCFStringEncodingUTF8)) {
     NS_Free(newBuffer);
-    newBuffer = nsnull;
+    return nsnull;
   }
+
+  newBuffer = static_cast<char*>(NS_Realloc(newBuffer,
+                                            PL_strlen(newBuffer) + 1));
   return newBuffer;
 }
 
 class AutoCFTypeObject {
 public:
   AutoCFTypeObject(CFTypeRef object)
   {
     mObject = object;
--- a/modules/plugin/test/mochitest/Makefile.in
+++ b/modules/plugin/test/mochitest/Makefile.in
@@ -124,26 +124,23 @@ ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 
 _MOCHICHROME_FILES += \
   test_xulbrowser_plugin_visibility.xul \
   xulbrowser_plugin_visibility.xul \
   plugin_visibility_loader.html \
   $(NULL)
 endif
 
-# Temporarily disable the tests on Linux, see bug 573290 and bug 583591.
-ifneq ($(OS_ARCH),Linux)
 ifdef MOZ_CRASHREPORTER
 _MOCHICHROME_FILES += \
   test_crash_notify.xul \
   test_crash_notify_no_report.xul \
   test_crash_submit.xul \
   $(NULL)
 endif
-endif
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _MOCHICHROME_FILES += \
   test_convertpoint.xul \
   $(NULL)
 
 _MOCHITEST_FILES += \
   test_cocoa_window_focus.html \
--- a/netwerk/base/public/nsNetError.h
+++ b/netwerk/base/public/nsNetError.h
@@ -235,16 +235,24 @@
 /**
  * The request failed because the content type returned by the server was
  * not a type expected by the channel (for nested channels such as the JAR
  * channel).
  */
 #define NS_ERROR_UNSAFE_CONTENT_TYPE \
     NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 74)
 
+/**
+ * The request failed because the user tried to access to a remote XUL document
+ * from a website that is not in its white-list.
+ */
+#define NS_ERROR_REMOTE_XUL \
+    NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 75)
+
+
 /******************************************************************************
  * FTP specific error codes:
  *
  * XXX document me
  */
 
 #define NS_ERROR_FTP_LOGIN \
     NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 21)
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -144,19 +144,17 @@ nsHtml5TreeBuilder::createElement(PRInt3
           nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
           NS_ASSERTION(treeOp, "Tree op allocation failed.");
           treeOp->Init(eTreeOpSetStyleLineNumber, content, tokenizer->getLineNumber());
         } else if (nsHtml5Atoms::html == aName) {
           nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST);
           if (url) {
             mSpeculativeLoadQueue.AppendElement()->InitManifest(*url);
           }
-        } else if (nsHtml5Atoms::base == aName &&
-            (mode == NS_HTML5TREE_BUILDER_IN_HEAD ||
-             mode == NS_HTML5TREE_BUILDER_AFTER_HEAD)) {
+        } else if (nsHtml5Atoms::base == aName) {
           nsString* url =
               aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
           if (url) {
             mSpeculativeLoadQueue.AppendElement()->InitBase(*url);
           }
         }
         break;
       case kNameSpaceID_SVG:
--- a/testing/mochitest/tests/SimpleTest/EventUtils.js
+++ b/testing/mochitest/tests/SimpleTest/EventUtils.js
@@ -294,16 +294,91 @@ function synthesizeMouseScroll(aTarget, 
     if (aEvent.isMomentum) {
       scrollFlags |= kIsMomentum;
     }
     utils.sendMouseScrollEvent(type, left + aOffsetX, top + aOffsetY, button,
                                scrollFlags, aEvent.delta, modifiers);
   }
 }
 
+function _computeKeyCodeFromChar(aChar)
+{
+  if (aChar.length != 1) {
+    return 0;
+  }
+  const nsIDOMKeyEvent = Components.interfaces.nsIDOMKeyEvent;
+  if (aChar >= 'a' && aChar <= 'z') {
+    return nsIDOMKeyEvent.DOM_VK_A + aChar.charCodeAt(0) - 'a'.charCodeAt(0);
+  }
+  if (aChar >= 'A' && aChar <= 'Z') {
+    return nsIDOMKeyEvent.DOM_VK_A + aChar.charCodeAt(0) - 'A'.charCodeAt(0);
+  }
+  if (aChar >= '0' && aChar <= '9') {
+    return nsIDOMKeyEvent.DOM_VK_0 + aChar.charCodeAt(0) - '0'.charCodeAt(0);
+  }
+  // returns US keyboard layout's keycode
+  switch (aChar) {
+    case '~':
+    case '`':
+      return nsIDOMKeyEvent.DOM_VK_BACK_QUOTE;
+    case '!':
+      return nsIDOMKeyEvent.DOM_VK_1;
+    case '@':
+      return nsIDOMKeyEvent.DOM_VK_2;
+    case '#':
+      return nsIDOMKeyEvent.DOM_VK_3;
+    case '$':
+      return nsIDOMKeyEvent.DOM_VK_4;
+    case '%':
+      return nsIDOMKeyEvent.DOM_VK_5;
+    case '^':
+      return nsIDOMKeyEvent.DOM_VK_6;
+    case '&':
+      return nsIDOMKeyEvent.DOM_VK_7;
+    case '*':
+      return nsIDOMKeyEvent.DOM_VK_8;
+    case '(':
+      return nsIDOMKeyEvent.DOM_VK_9;
+    case ')':
+      return nsIDOMKeyEvent.DOM_VK_0;
+    case '-':
+    case '_':
+      return nsIDOMKeyEvent.DOM_VK_SUBTRACT;
+    case '+':
+    case '=':
+      return nsIDOMKeyEvent.DOM_VK_EQUALS;
+    case '{':
+    case '[':
+      return nsIDOMKeyEvent.DOM_VK_OPEN_BRACKET;
+    case '}':
+    case ']':
+      return nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET;
+    case '|':
+    case '\\':
+      return nsIDOMKeyEvent.DOM_VK_BACK_SLASH;
+    case ':':
+    case ';':
+      return nsIDOMKeyEvent.DOM_VK_SEMICOLON;
+    case '\'':
+    case '"':
+      return nsIDOMKeyEvent.DOM_VK_QUOTE;
+    case '<':
+    case ',':
+      return nsIDOMKeyEvent.DOM_VK_COMMA;
+    case '>':
+    case '.':
+      return nsIDOMKeyEvent.DOM_VK_PERIOD;
+    case '?':
+    case '/':
+      return nsIDOMKeyEvent.DOM_VK_SLASH;
+    default:
+      return 0;
+  }
+}
+
 /**
  * Synthesize a key event. It is targeted at whatever would be targeted by an
  * actual keypress by the user, typically the focused element.
  *
  * aKey should be either a character or a keycode starting with VK_ such as
  * VK_ENTER.
  *
  * aEvent is an object which may contain the properties:
@@ -322,30 +397,34 @@ function synthesizeKey(aKey, aEvent, aWi
     aWindow = window;
 
   var utils = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
                       getInterface(Components.interfaces.nsIDOMWindowUtils);
   if (utils) {
     var keyCode = 0, charCode = 0;
     if (aKey.indexOf("VK_") == 0)
       keyCode = KeyEvent["DOM_" + aKey];
-    else
+    else {
       charCode = aKey.charCodeAt(0);
+      keyCode = _computeKeyCodeFromChar(aKey.charAt(0));
+    }
 
     var modifiers = _parseModifiers(aEvent);
 
-    if (aEvent.type) {
-      utils.sendKeyEvent(aEvent.type, keyCode, charCode, modifiers);
-    }
-    else {
+    if (aEvent.type == "keypress") {
+      utils.sendKeyEvent(aEvent.type, charCode ? 0 : keyCode,
+                         charCode, modifiers);
+    } else if (aEvent.type) {
+      utils.sendKeyEvent(aEvent.type, keyCode, 0, modifiers);
+    } else {
       var keyDownDefaultHappened =
-          utils.sendKeyEvent("keydown", keyCode, charCode, modifiers);
-      utils.sendKeyEvent("keypress", keyCode, charCode, modifiers,
-                         !keyDownDefaultHappened);
-      utils.sendKeyEvent("keyup", keyCode, charCode, modifiers);
+          utils.sendKeyEvent("keydown", keyCode, 0, modifiers);
+      utils.sendKeyEvent("keypress", charCode ? 0 : keyCode, charCode,
+                         modifiers, !keyDownDefaultHappened);
+      utils.sendKeyEvent("keyup", keyCode, 0, modifiers);
     }
   }
 }
 
 var _gSeenEvent = false;
 
 /**
  * Indicate that an event with an original target of aExpectedTarget and
--- a/toolkit/components/commandlines/src/nsCommandLine.cpp
+++ b/toolkit/components/commandlines/src/nsCommandLine.cpp
@@ -53,17 +53,17 @@
 #include "nsNativeCharsetUtils.h"
 #include "nsNetUtil.h"
 #include "nsUnicharUtils.h"
 #include "nsTArray.h"
 #include "nsTextFormatter.h"
 #include "nsXPCOMCID.h"
 #include "plstr.h"
 
-#ifdef XP_MACOSX
+#ifdef MOZ_WIDGET_COCOA
 #include <CoreFoundation/CoreFoundation.h>
 #include "nsILocalFileMac.h"
 #elif defined(XP_WIN)
 #include <windows.h>
 #include <shlobj.h>
 #elif defined(XP_BEOS)
 #include <Path.h>
 #include <Directory.h>
@@ -282,17 +282,17 @@ nsCommandLine::ResolveFile(const nsAStri
   NS_ENSURE_TRUE(mWorkingDir, NS_ERROR_NOT_INITIALIZED);
 
   // This is some seriously screwed-up code. nsILocalFile.appendRelativeNativePath
   // explicitly does not accept .. or . path parts, but that is exactly what we
   // need here. So we hack around it.
 
   nsresult rv;
 
-#if defined(XP_MACOSX)
+#if defined(MOZ_WIDGET_COCOA)
   nsCOMPtr<nsILocalFileMac> lfm (do_QueryInterface(mWorkingDir));
   NS_ENSURE_TRUE(lfm, NS_ERROR_NO_INTERFACE);
 
   nsCOMPtr<nsILocalFileMac> newfile (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
   NS_ENSURE_TRUE(newfile, NS_ERROR_OUT_OF_MEMORY);
 
   CFURLRef baseurl;
   rv = lfm->GetCFURL(&baseurl);
--- a/toolkit/components/places/tests/bookmarks/test_393498.js
+++ b/toolkit/components/places/tests/bookmarks/test_393498.js
@@ -77,19 +77,19 @@ bmsvc.addObserver(observer, false);
 // main
 function run_test() {
   var testFolder = bmsvc.createFolder(bmsvc.placesRoot, "test Folder",
                                       bmsvc.DEFAULT_INDEX);
   var bookmarkId = bmsvc.insertBookmark(testFolder, uri("http://google.com/"),
                                    bmsvc.DEFAULT_INDEX, "");
   do_check_true(observer.itemChangedProperty == null);
 
-  // We set lastModified 1us in the past to workaround a timing bug on
+  // We set lastModified in the past to workaround a timing bug on
   // virtual machines, see bug 427142 for details.
-  var newDate = Date.now() * 1000 - 1;
+  var newDate = (Date.now() - 10) * 1000;
   bmsvc.setItemDateAdded(bookmarkId, newDate);
   // test notification
   do_check_eq(observer._itemChangedProperty, "dateAdded");
   do_check_eq(observer._itemChangedValue, newDate);
   // test saved value
   var dateAdded = bmsvc.getItemDateAdded(bookmarkId);
   do_check_eq(dateAdded, newDate);
 
@@ -124,17 +124,17 @@ function run_test() {
 
   // confirm current dates match node properties
   do_check_eq(bmsvc.getItemDateAdded(bookmarkId), childNode.dateAdded);
   do_check_eq(bmsvc.getItemLastModified(bookmarkId), childNode.lastModified);
 
   // test live update of lastModified caused by other changes:
   // We set lastModified in the past to workaround timers resolution,
   // see bug 427142 for details.
-  var pastDate = Date.now() * 1000 - 20000;
+  var pastDate = (Date.now() - 10) * 1000;
   bmsvc.setItemLastModified(bookmarkId, pastDate);
   // set title (causing update of last modified)
   var oldLastModified = bmsvc.getItemLastModified(bookmarkId);
   bmsvc.setItemTitle(bookmarkId, "Google");
   // test that lastModified is updated
   is_time_ordered(oldLastModified, childNode.lastModified);
   // test that node value matches db value
   do_check_eq(bmsvc.getItemLastModified(bookmarkId), childNode.lastModified);
--- a/toolkit/content/aboutSupport.js
+++ b/toolkit/content/aboutSupport.js
@@ -228,22 +228,26 @@ function populateGraphicsSection() {
       }
     }
     trGraphics.push(createParentElement("tr", [
       createHeader(bundle.GetStringFromName("direct2DEnabled")),
       createElement("td", d2dMessage),
     ]));
 
     var dwEnabled = false;
+    var dwriteEnabledStr = dwEnabled.toString();
+    var dwriteVersion;
     try {
       dwEnabled = gfxInfo.DWriteEnabled;
+      dwriteVersion = gfxInfo.DWriteVersion;
+      dwriteEnabledStr = dwEnabled.toString() + " (" + dwriteVersion + ")";
     } catch(e) {}
     trGraphics.push(createParentElement("tr", [
       createHeader(bundle.GetStringFromName("directWriteEnabled")),
-      createElement("td", dwEnabled),
+      createElement("td", dwriteEnabledStr),
     ]));
 
     var webglrenderer;
     try {
       webglrenderer = gfxInfo.getWebGLParameter("full-renderer");
     } catch (e) {
       webglrenderer = "(WebGL unavailable)";
     }
--- a/toolkit/crashreporter/Makefile.in
+++ b/toolkit/crashreporter/Makefile.in
@@ -117,15 +117,12 @@ CPPSRCS = \
 
 FORCE_STATIC_LIB = 1
 
 EXTRA_JS_MODULES = \
   CrashSubmit.jsm \
   $(NULL)
 
 ifdef ENABLE_TESTS
-# Temporarily disable the tests on Linux, see bug 573290 and bug 583591
-ifneq ($(OS_ARCH),Linux)
 TOOL_DIRS = test
 endif
-endif
 
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h
@@ -74,17 +74,19 @@
 // Minidump::ReadString will return a string object to the user, and the user
 // is responsible for its deletion.
 //
 // Author: Mark Mentovai
 
 #ifndef GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__
 #define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__
 
+#ifndef _WIN32
 #include <unistd.h>
+#endif
 
 #include <iostream>
 #include <map>
 #include <string>
 #include <vector>
 
 #include "google_breakpad/common/minidump_format.h"
 #include "google_breakpad/processor/code_module.h"
--- a/toolkit/crashreporter/google-breakpad/src/processor/logging.cc
+++ b/toolkit/crashreporter/google-breakpad/src/processor/logging.cc
@@ -39,23 +39,31 @@
 #include <string.h>
 #include <time.h>
 
 #include "processor/logging.h"
 #include "processor/pathname_stripper.h"
 
 namespace google_breakpad {
 
+#ifdef _WIN32
+#define snprintf _snprintf
+#endif
+
 LogStream::LogStream(std::ostream &stream, Severity severity,
                      const char *file, int line)
     : stream_(stream) {
   time_t clock;
   time(&clock);
   struct tm tm_struct;
+#ifdef _WIN32
+  localtime_s(&tm_struct, &clock);
+#else
   localtime_r(&clock, &tm_struct);
+#endif
   char time_string[20];
   strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", &tm_struct);
 
   const char *severity_string = "UNKNOWN_SEVERITY";
   switch (severity) {
     case SEVERITY_INFO:
       severity_string = "INFO";
       break;
--- a/toolkit/crashreporter/google-breakpad/src/processor/logging.h
+++ b/toolkit/crashreporter/google-breakpad/src/processor/logging.h
@@ -63,16 +63,25 @@
 #include "google_breakpad/common/breakpad_types.h"
 
 #ifdef BP_LOGGING_INCLUDE
 #include BP_LOGGING_INCLUDE
 #endif  // BP_LOGGING_INCLUDE
 
 namespace google_breakpad {
 
+// These are defined in Microsoft headers.
+#ifdef SEVERITY_ERROR
+#undef SEVERITY_ERROR
+#endif
+
+#ifdef ERROR
+#undef ERROR
+#endif
+
 class LogStream {
  public:
   enum Severity {
     SEVERITY_INFO,
     SEVERITY_ERROR
   };
 
   // Begin logging a message to the stream identified by |stream|, at the
--- a/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc
+++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc
@@ -35,24 +35,25 @@
 
 #include "google_breakpad/processor/minidump.h"
 
 #include <assert.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
-#include <unistd.h>
+
 #ifdef _WIN32
 #include <io.h>
 typedef SSIZE_T ssize_t;
-#define open _open
-#define read _read
-#define lseek _lseek
+#define PRIx64 "llx"
+#define PRIx32 "lx"
+#define snprintf _snprintf
 #else  // _WIN32
+#include <unistd.h>
 #define O_BINARY 0
 #endif  // _WIN32
 
 #include <fstream>
 #include <iostream>
 #include <limits>
 #include <map>
 #include <vector>
@@ -1096,17 +1097,17 @@ MinidumpMemoryRegion::~MinidumpMemoryReg
   delete memory_;
 }
 
 
 void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) {
   descriptor_ = descriptor;
   valid_ = descriptor &&
            descriptor_->memory.data_size <=
-               numeric_limits<uint64_t>::max() -
+               numeric_limits<u_int64_t>::max() -
                descriptor_->start_of_memory_range;
 }
 
 
 const u_int8_t* MinidumpMemoryRegion::GetMemory() const {
   if (!valid_) {
     BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory";
     return NULL;
@@ -3683,17 +3684,21 @@ void Minidump::Print() {
 
   printf("MDRawHeader\n");
   printf("  signature            = 0x%x\n",    header_.signature);
   printf("  version              = 0x%x\n",    header_.version);
   printf("  stream_count         = %d\n",      header_.stream_count);
   printf("  stream_directory_rva = 0x%x\n",    header_.stream_directory_rva);
   printf("  checksum             = 0x%x\n",    header_.checksum);
   struct tm timestruct;
+#ifdef _WIN32
+  gmtime_s(&timestruct, reinterpret_cast<time_t*>(&header_.time_date_stamp));
+#else
   gmtime_r(reinterpret_cast<time_t*>(&header_.time_date_stamp), &timestruct);
+#endif
   char timestr[20];
   strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
   printf("  time_date_stamp      = 0x%x %s\n", header_.time_date_stamp,
                                                timestr);
   printf("  flags                = 0x%" PRIx64 "\n",  header_.flags);
   printf("\n");
 
   for (unsigned int stream_index = 0;
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -204,20 +204,16 @@ static const char kAvailableVirtualMemor
 static const int kAvailableVirtualMemoryParameterLen =
   sizeof(kAvailableVirtualMemoryParameter)-1;
 
 // this holds additional data sent via the API
 static AnnotationTable* crashReporterAPIData_Hash;
 static nsCString* crashReporterAPIData = nsnull;
 static nsCString* notesField = nsnull;
 
-#if defined(XP_WIN)
-static HMODULE dbghelp = NULL;
-#endif
-
 #if defined(MOZ_IPC)
 // OOP crash reporting
 static CrashGenerationServer* crashServer; // chrome process has this
 
 #  if defined(XP_WIN) || defined(XP_MACOSX)
 // If crash reporting is disabled, we hand out this "null" pipe to the
 // child process and don't attempt to connect to a parent server.
 static const char kNullNotifyPipe[] = "-";
@@ -718,27 +714,33 @@ nsresult SetExceptionHandler(nsILocalFil
       attr_ocount != attr_count) {
     posix_spawnattr_destroy(&spawnattr);
     return NS_ERROR_FAILURE;
   }
 #endif
 
 #ifdef XP_WIN
   // Try to determine what version of dbghelp.dll we're using.
-  // MinidumpWithFullMemoryInfo is only available in 6.2 or newer.
-  dbghelp = LoadLibraryW(L"dbghelp.dll");
+  // MinidumpWithFullMemoryInfo is only available in 6.1.x or newer.
   MINIDUMP_TYPE minidump_type = MiniDumpNormal;
-  if (dbghelp) {
-    typedef LPAPI_VERSION (WINAPI *ImagehlpApiVersionPtr)(void);
-    ImagehlpApiVersionPtr imagehlp_api_version =
-      (ImagehlpApiVersionPtr)GetProcAddress(dbghelp, "ImagehlpApiVersion");
-    if (imagehlp_api_version) {
-      LPAPI_VERSION api_version = imagehlp_api_version();
-      if (api_version->MajorVersion > 6 ||
-          (api_version->MajorVersion == 6 && api_version->MinorVersion > 1)) {
+  DWORD version_size = GetFileVersionInfoSizeW(L"dbghelp.dll", NULL);
+  if (version_size > 0) {
+    std::vector<BYTE> buffer(version_size);
+    if (GetFileVersionInfoW(L"dbghelp.dll",
+                           0,
+                           version_size,
+                           &buffer[0])) {
+      UINT len;
+      VS_FIXEDFILEINFO* file_info;
+      VerQueryValue(&buffer[0], L"\\", (void**)&file_info, &len);
+      WORD major = HIWORD(file_info->dwFileVersionMS),
+           minor = LOWORD(file_info->dwFileVersionMS),
+           revision = HIWORD(file_info->dwFileVersionLS);
+      if (major > 6 || (major == 6 && minor > 1) ||
+          (major == 6 && minor == 1 && revision >= 7600)) {
         minidump_type = MiniDumpWithFullMemoryInfo;
       }
     }
   }
 #endif
 
   // now set the exception handler
   gExceptionHandler = new google_breakpad::
@@ -1023,22 +1025,16 @@ nsresult SetupExtraData(nsILocalFile* aA
 }
 
 static void OOPDeinit();
 
 nsresult UnsetExceptionHandler()
 {
   delete gExceptionHandler;
 
-#if defined(XP_WIN)
-  if (dbghelp) {
-    FreeLibrary(dbghelp);
-  }
-#endif
-
   // do this here in the unlikely case that we succeeded in allocating
   // our strings but failed to allocate gExceptionHandler.
   if (crashReporterAPIData_Hash) {
     delete crashReporterAPIData_Hash;
     crashReporterAPIData_Hash = nsnull;
   }
 
   if (crashReporterAPIData) {
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/test/CrashTestUtils.jsm
@@ -0,0 +1,42 @@
+var EXPORTED_SYMBOLS = ["CrashTestUtils"];
+
+let CrashTestUtils = {
+  // These will be defined using ctypes APIs below.
+  crash: null,
+  lockDir: null,
+  dumpHasStream: null,
+
+  // Constants for crash()
+  // Keep these in sync with nsTestCrasher.cpp!
+  CRASH_INVALID_POINTER_DEREF: 0,
+  CRASH_PURE_VIRTUAL_CALL:     1,
+  CRASH_RUNTIMEABORT:          2,
+
+  // Constants for dumpHasStream()
+  // From google_breakpad/common/minidump_format.h
+  MD_THREAD_LIST_STREAM:       3,
+  MD_MEMORY_INFO_LIST_STREAM:  16
+};
+
+// Grab APIs from the testcrasher shared library
+Components.utils.import("resource://gre/modules/ctypes.jsm");
+let dir = __LOCATION__.parent;
+let file = dir.clone();
+file.append(ctypes.libraryName("testcrasher"));
+let lib = ctypes.open(file.path);
+CrashTestUtils.crash = lib.declare("Crash",
+                                   ctypes.default_abi,
+                                   ctypes.void_t,
+                                   ctypes.int16_t);
+
+CrashTestUtils.lockDir = lib.declare("LockDir",
+                                     ctypes.default_abi,
+                                     ctypes.voidptr_t,   // nsILocalFile*
+                                     ctypes.voidptr_t);  // nsISupports*
+
+
+CrashTestUtils.dumpHasStream = lib.declare("DumpHasStream",
+                                           ctypes.default_abi,
+                                           ctypes.bool,
+                                           ctypes.char.ptr,
+                                           ctypes.uint32_t);
--- a/toolkit/crashreporter/test/Makefile.in
+++ b/toolkit/crashreporter/test/Makefile.in
@@ -42,26 +42,36 @@ VPATH		= @srcdir@
 relativesrcdir  = toolkit/crashreporter/test
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = crashreporter_test
 XPCSHELL_TESTS = unit
 
 LIBRARY_NAME = testcrasher
-IS_COMPONENT    = 1
 NO_DIST_INSTALL = 1
 
-XPIDLSRCS = nsITestCrasher.idl
+VPATH += \
+  $(srcdir)/../google-breakpad/src/processor/ \
+  $(srcdir)/../google-breakpad/src/common/ \
+  $(NULL)
 
 CPPSRCS = \
   nsTestCrasher.cpp \
+  dumputils.cpp \
+  basic_code_modules.cc \
+  logging.cc \
+  minidump.cc \
+  pathname_stripper.cc \
   $(NULL)
 
-LOCAL_INCLUDES += -I$(XPIDL_GEN_DIR)
+LOCAL_INCLUDES += \
+  -I$(XPIDL_GEN_DIR) \
+  -I$(srcdir)/../google-breakpad/src/ \
+  $(NULL)
 EXTRA_DSO_LIBS += xpcom
 EXTRA_DSO_LDOPTS += $(LIBS_DIR) $(MOZ_COMPONENT_LIBS)
 
 ifdef MOZ_ENABLE_LIBXUL
 EXTRA_DSO_LDOPTS += $(XPCOM_GLUE_LDOPTS)
 else
 
 MOZILLA_INTERNAL_API = 1
@@ -71,31 +81,30 @@ EXTRA_DSO_LDOPTS += $(DIST)/bin/XUL
 else
 EXTRA_DSO_LIBS += xul
 endif
 
 EXTRA_DSO_LDOPTS += $(EXTRA_DSO_LIBS) $(XPCOM_LIBS)
 
 endif
 
-EXTRA_PP_COMPONENTS = testcrasher.manifest
+EXTRA_JS_MODULES = CrashTestUtils.jsm
 
 include $(topsrcdir)/config/rules.mk
 
-DEFINES += -DSHARED_LIBRARY=$(SHARED_LIBRARY)
+DEFINES += -DSHARED_LIBRARY=$(SHARED_LIBRARY) -DNOMINMAX
 
 ifneq (mobile,$(MOZ_BUILD_APP))
 _BROWSER_FILES = \
   browser/aboutcrashes_utils.js \
   browser/crashreport.sjs \
   browser/browser_aboutCrashes.js \
   browser/browser_bug471404.js \
   browser/browser_aboutCrashesResubmit.js \
   $(NULL)
 
 libs::  $(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)/browser
 endif
 
-libs:: $(SHARED_LIBRARY) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt
-	$(NSINSTALL) -D $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/components
-	$(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/components
-	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $(srcdir)/testcrasher.manifest > $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/components/testcrasher.manifest
+libs:: $(SHARED_LIBRARY) $(EXTRA_JS_MODULES)
+	$(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/
+
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/test/dumputils.cpp
@@ -0,0 +1,19 @@
+#include "google_breakpad/processor/minidump.h"
+#include "nscore.h"
+
+using namespace google_breakpad;
+
+extern "C"
+NS_EXPORT bool
+DumpHasStream(const char* dump_file, u_int32_t stream_type)
+{
+  Minidump dump(dump_file);
+  if (!dump.Read())
+    return false;
+
+  u_int32_t length;
+  if (!dump.SeekToStreamType(stream_type, &length) || length == 0)
+    return false;
+
+  return true;
+}
deleted file mode 100644
--- a/toolkit/crashreporter/test/nsITestCrasher.idl
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "nsISupports.idl"
-
-interface nsILocalFile;
-
-[scriptable, uuid(95464a04-6949-46cb-b621-d167790704a0)]
-interface nsITestCrasher : nsISupports
-{
-  void crash(in short how);
-
-  /**
-   * Lock a directory using XRE_LockProfileDirectory.
-   * 
-   * @param directory The directory to lock
-   * @return          An opaque lock object.
-   */
-  nsISupports lockDir(in nsILocalFile directory);
-
-  const short CRASH_INVALID_POINTER_DEREF  = 0;
-  const short CRASH_PURE_VIRTUAL_CALL      = 1;
-  const short CRASH_RUNTIMEABORT           = 2;
-};
--- a/toolkit/crashreporter/test/nsTestCrasher.cpp
+++ b/toolkit/crashreporter/test/nsTestCrasher.cpp
@@ -1,28 +1,10 @@
-#include "nsServiceManagerUtils.h"
-#include "nsIComponentManager.h"
-#include "nsITestCrasher.h"
+#include "nscore.h"
 #include "nsXULAppAPI.h"
-#include "mozilla/ModuleUtils.h"
-
-class nsTestCrasher : public nsITestCrasher
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSITESTCRASHER
-
-  nsTestCrasher() {}
-
-private:
-  ~nsTestCrasher() {};
-};
-
-
-NS_IMPL_ISUPPORTS1(nsTestCrasher, nsITestCrasher)
 
 /*
  * This pure virtual call example is from MSDN
  */
 class A;
 
 void fcn( A* );
 
@@ -44,64 +26,44 @@ void fcn( A* p )
 }
 
 void PureVirtualCall()
 {
   // generates a pure virtual function call
   B b;
 }
 
-/* void crash (); */
-NS_IMETHODIMP nsTestCrasher::Crash(PRInt16 how)
+// Keep these in sync with CrashTestUtils.jsm!
+const PRInt16 CRASH_INVALID_POINTER_DEREF = 0;
+const PRInt16 CRASH_PURE_VIRTUAL_CALL     = 1;
+const PRInt16 CRASH_RUNTIMEABORT          = 2;
+
+extern "C" NS_EXPORT
+void Crash(PRInt16 how)
 {
   switch (how) {
-  case nsITestCrasher::CRASH_INVALID_POINTER_DEREF: {
+  case CRASH_INVALID_POINTER_DEREF: {
     volatile int* foo = (int*)0x42;
     *foo = 0;
     // not reached
     break;
   }
-  case nsITestCrasher::CRASH_PURE_VIRTUAL_CALL: {
+  case CRASH_PURE_VIRTUAL_CALL: {
     PureVirtualCall();
     // not reached
     break;
   }
-  case nsITestCrasher::CRASH_RUNTIMEABORT: {
+  case CRASH_RUNTIMEABORT: {
     NS_RUNTIMEABORT("Intentional crash");
     break;
   }
   default:
-    return NS_ERROR_INVALID_ARG;
+    break;
   }
-  return NS_OK;
-}
-
-/* nsISupports LockDir (in nsILocalFile directory); */
-NS_IMETHODIMP nsTestCrasher::LockDir(nsILocalFile *directory,
-                                     nsISupports **_retval NS_OUTPARAM)
-{
-  return XRE_LockProfileDirectory(directory, _retval);
 }
 
-// 54afce51-38d7-4df0-9750-2f90f9ffbca2
-#define NS_TESTCRASHER_CID \
-{ 0x54afce51, 0x38d7, 0x4df0, {0x97, 0x50, 0x2f, 0x90, 0xf9, 0xff, 0xbc, 0xa2} }
-
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsTestCrasher)
-NS_DEFINE_NAMED_CID(NS_TESTCRASHER_CID);
-
-static const mozilla::Module::CIDEntry kTestCrasherCIDs[] = {
-  { &kNS_TESTCRASHER_CID, false, NULL, nsTestCrasherConstructor },
-  { NULL }
-};
-
-static const mozilla::Module::ContractIDEntry kTestCrasherContracts[] = {
-  { "@mozilla.org/testcrasher;1", &kNS_TESTCRASHER_CID },
-  { NULL }
-};
-
-static const mozilla::Module kTestCrasherModule = {
-  mozilla::Module::kVersion,
-  kTestCrasherCIDs,
-  kTestCrasherContracts
-};
-
-NSMODULE_DEFN(nsTestCrasherModule) = &kTestCrasherModule;
+extern "C" NS_EXPORT
+nsISupports* LockDir(nsILocalFile *directory)
+{
+  nsISupports* lockfile = nsnull;
+  XRE_LockProfileDirectory(directory, &lockfile);
+  return lockfile;
+}
deleted file mode 100644
--- a/toolkit/crashreporter/test/testcrasher.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-#filter substitution
-binary-component @SHARED_LIBRARY@
-interfaces crashreporter_test.xpt
--- a/toolkit/crashreporter/test/unit/crasher_subprocess_head.js
+++ b/toolkit/crashreporter/test/unit/crasher_subprocess_head.js
@@ -2,14 +2,17 @@
 let cwd = Components.classes["@mozilla.org/file/directory_service;1"]
       .getService(Components.interfaces.nsIProperties)
       .get("CurWorkD", Components.interfaces.nsILocalFile);
 let crashReporter =
   Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
     .getService(Components.interfaces.nsICrashReporter);
 crashReporter.enabled = true;
 crashReporter.minidumpPath = cwd;
-let cd = cwd.clone();
-cd.append("components");
-cd.append("testcrasher.manifest");
-Components.manager instanceof Components.interfaces.nsIComponentRegistrar;
-Components.manager.autoRegister(cd);
-let crashType = Components.interfaces.nsITestCrasher.CRASH_INVALID_POINTER_DEREF;
+
+let ios = Components.classes["@mozilla.org/network/io-service;1"]
+            .getService(Components.interfaces.nsIIOService);
+let protocolHandler = ios.getProtocolHandler("resource")
+                        .QueryInterface(Components.interfaces.nsIResProtocolHandler);
+let curDirURI = ios.newFileURI(cwd);
+protocolHandler.setSubstitution("test", curDirURI);
+Components.utils.import("resource://test/CrashTestUtils.jsm");
+let crashType = CrashTestUtils.CRASH_INVALID_POINTER_DEREF;
--- a/toolkit/crashreporter/test/unit/crasher_subprocess_tail.js
+++ b/toolkit/crashreporter/test/unit/crasher_subprocess_tail.js
@@ -1,3 +1,2 @@
 // now actually crash
-let crasher = Components.classes["@mozilla.org/testcrasher;1"].createInstance(Components.interfaces.nsITestCrasher);
-crasher.crash(crashType);
+CrashTestUtils.crash(crashType);
--- a/toolkit/crashreporter/test/unit/head_crashreporter.js
+++ b/toolkit/crashreporter/test/unit/head_crashreporter.js
@@ -17,17 +17,17 @@
  *        crashes. It will be passed (minidump, extra), where
  *         minidump is an nsILocalFile of the minidump file produced,
  *         and extra is an object containing the key,value pairs from
  *         the .extra file.
  *
  * @param canReturnZero
  *       If true, the subprocess may return with a zero exit code.
  *       Certain types of crashes may not cause the process to
- *       exit with an error. 
+ *       exit with an error.
  */
 function do_crash(setup, callback, canReturnZero)
 {
   // get current process filename (xpcshell)
   let ds = Components.classes["@mozilla.org/file/directory_service;1"]
     .getService(Components.interfaces.nsIProperties);
   let bin = ds.get("CurProcD", Components.interfaces.nsILocalFile);
   bin.append("xpcshell");
@@ -76,16 +76,24 @@ function do_crash(setup, callback, canRe
     }
   }
 
   if (minidump == null)
     do_throw("No minidump found!");
 
   let extrafile = minidump.clone();
   extrafile.leafName = extrafile.leafName.slice(0, -4) + ".extra";
+
+  // Just in case, don't let these files linger.
+  do_register_cleanup(function() {
+          if (minidump.exists())
+              minidump.remove(false);
+          if (extrafile.exists())
+              extrafile.remove(false);
+      });
   do_check_true(extrafile.exists());
   let extra = parseKeyValuePairsFromFile(extrafile);
 
   if (callback)
     callback(minidump, extra);
 
   if (minidump.exists())
     minidump.remove(false);
@@ -124,8 +132,11 @@ function parseKeyValuePairsFromFile(file
   var contents = '';
   while (is.readString(4096, str) != 0) {
     contents += str.value;
   }
   is.close();
   fstream.close();
   return parseKeyValuePairs(contents);
 }
+
+// Import binary APIs via js-ctypes.
+Components.utils.import("resource://test/CrashTestUtils.jsm");
--- a/toolkit/crashreporter/test/unit/test_crash_purevirtual.js
+++ b/toolkit/crashreporter/test/unit/test_crash_purevirtual.js
@@ -8,17 +8,17 @@ function run_test()
   var isOSX = ("nsILocalFileMac" in Components.interfaces);
   if (isOSX) {
      dump("INFO | test_crash_purevirtual.js | TODO: purecalls not caught on OS X\n");
     return;
   }
 
   // Try crashing with a pure virtual call
   do_crash(function() {
-             crashType = Components.interfaces.nsITestCrasher.CRASH_PURE_VIRTUAL_CALL;
+             crashType = CrashTestUtils.CRASH_PURE_VIRTUAL_CALL;
              crashReporter.annotateCrashReport("TestKey", "TestValue");
            },
            function(mdump, extra) {
              do_check_eq(extra.TestKey, "TestValue");
            },
           // process will exit with a zero exit status
           true);
 }
--- a/toolkit/crashreporter/test/unit/test_crash_runtimeabort.js
+++ b/toolkit/crashreporter/test/unit/test_crash_runtimeabort.js
@@ -1,18 +1,18 @@
 function run_test()
 {
   if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) {
-    dump("INFO | test_crash_purevirtual.js | Can't test crashreporter in a non-libxul build.\n");
+    dump("INFO | test_crash_runtimeabort.js | Can't test crashreporter in a non-libxul build.\n");
     return;
   }
 
   // Try crashing with a runtime abort
   do_crash(function() {
-             crashType = Components.interfaces.nsITestCrasher.CRASH_RUNTIMEABORT;
+             crashType = CrashTestUtils.CRASH_RUNTIMEABORT;
              crashReporter.annotateCrashReport("TestKey", "TestValue");
            },
            function(mdump, extra) {
              do_check_eq(extra.TestKey, "TestValue");
            },
           // process will exit with a zero exit status
           true);
 }
--- a/toolkit/crashreporter/test/unit/test_crashreporter_crash.js
+++ b/toolkit/crashreporter/test/unit/test_crashreporter_crash.js
@@ -1,21 +1,33 @@
 function run_test()
 {
   if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) {
     dump("INFO | test_crashreporter.js | Can't test crashreporter in a non-libxul build.\n");
     return;
   }
 
+  var is_win7_or_newer = false;
+  var ph = Components.classes["@mozilla.org/network/protocol;1?name=http"]
+             .getService(Components.interfaces.nsIHttpProtocolHandler);
+  var match = ph.userAgent.match(/Windows NT (\d+).(\d+)/);
+  if (match && (parseInt(match[1]) > 6 ||
+                parseInt(match[1]) == 6 && parseInt(match[2]) >= 1)) {
+      is_win7_or_newer = true;
+  }
+
   // try a basic crash
   do_crash(null, function(mdump, extra) {
              do_check_true(mdump.exists());
              do_check_true(mdump.fileSize > 0);
              do_check_true('StartupTime' in extra);
              do_check_true('CrashTime' in extra);
+             do_check_true(CrashTestUtils.dumpHasStream(mdump.path, CrashTestUtils.MD_THREAD_LIST_STREAM));
+             if (is_win7_or_newer)
+               do_check_true(CrashTestUtils.dumpHasStream(mdump.path, CrashTestUtils.MD_MEMORY_INFO_LIST_STREAM));
            });
 
   // check setting some basic data
   do_crash(function() {
              crashReporter.annotateCrashReport("TestKey", "TestValue");
              crashReporter.appendAppNotesToCrashReport("Junk");
              crashReporter.appendAppNotesToCrashReport("MoreJunk");
            },
--- a/toolkit/crashreporter/test/unit/test_crashreporter_crash_profile_lock.js
+++ b/toolkit/crashreporter/test/unit/test_crashreporter_crash_profile_lock.js
@@ -11,17 +11,16 @@ function run_test()
   do_crash(function() {
              let env = Components.classes["@mozilla.org/process/environment;1"]
                .getService(Components.interfaces.nsIEnvironment);
              // the python harness sets this in the environment for us
              let profd = env.get("XPCSHELL_TEST_PROFILE_DIR");
              let dir = Components.classes["@mozilla.org/file/local;1"]
                .createInstance(Components.interfaces.nsILocalFile);
              dir.initWithPath(profd);
-             let mycrasher = Components.classes["@mozilla.org/testcrasher;1"].createInstance(Components.interfaces.nsITestCrasher);
-             let lock = mycrasher.lockDir(dir);
+             let lock = CrashTestUtils.lockDir(dir);
              // when we crash, the lock file should be cleaned up
            },
            function(mdump, extra) {
              // if we got here, we have a minidump, so that's all we wanted
              do_check_true(true);
            });
 }
--- a/widget/public/nsIGfxInfo.idl
+++ b/widget/public/nsIGfxInfo.idl
@@ -35,24 +35,25 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
 /* NOTE: this interface is completely undesigned, not stable and likely to change */
 
-[scriptable, uuid(d2bfa0fd-8f73-4660-9609-f999680243b1)]
+[scriptable, uuid(5c5de1e7-f7f4-46b4-9ced-03ab1f869eaf)]
 interface nsIGfxInfo : nsISupports
 {
   /*
    * These are win32-specific
    */
   readonly attribute boolean D2DEnabled;
   readonly attribute boolean DWriteEnabled;
+  readonly attribute DOMString DWriteVersion;
   
   /**
    * The name of the display adapter.
    */
   readonly attribute DOMString adapterDescription;
 
   readonly attribute DOMString adapterDriver;
   
--- a/widget/src/android/GfxInfo.cpp
+++ b/widget/src/android/GfxInfo.cpp
@@ -66,16 +66,23 @@ GfxInfo::GetD2DEnabled(PRBool *aEnabled)
 }
 
 nsresult
 GfxInfo::GetDWriteEnabled(PRBool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
 
+/* readonly attribute DOMString DWriteVersion; */
+NS_IMETHODIMP
+GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
+{
+  return NS_ERROR_FAILURE;
+}
+
 void
 GfxInfo::Init()
 {
 }
 
 
 /* readonly attribute DOMString adapterDescription; */
 NS_IMETHODIMP
--- a/widget/src/cocoa/GfxInfo.mm
+++ b/widget/src/cocoa/GfxInfo.mm
@@ -101,16 +101,23 @@ GfxInfo::GetD2DEnabled(PRBool *aEnabled)
 }
 
 NS_IMETHODIMP
 GfxInfo::GetDWriteEnabled(PRBool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
 
+/* readonly attribute DOMString DWriteVersion; */
+NS_IMETHODIMP
+GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
+{
+  return NS_ERROR_FAILURE;
+}
+
 /* readonly attribute DOMString adapterDescription; */
 NS_IMETHODIMP
 GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
 {
   aAdapterDescription = mRendererIDsString;
   return NS_OK;
 }
 
--- a/widget/src/gtk2/nsGtkIMModule.cpp
+++ b/widget/src/gtk2/nsGtkIMModule.cpp
@@ -358,27 +358,28 @@ nsGtkIMModule::OnBlurWindow(nsWindow* aW
     if (!mIsIMFocused || mLastFocusedWindow != aWindow) {
         return;
     }
 
     Blur();
 }
 
 PRBool
-nsGtkIMModule::OnKeyEvent(nsWindow* aCaller, GdkEventKey* aEvent)
+nsGtkIMModule::OnKeyEvent(nsWindow* aCaller, GdkEventKey* aEvent,
+                          PRBool aKeyDownEventWasSent /* = PR_FALSE */)
 {
     NS_PRECONDITION(aEvent, "aEvent must be non-null");
 
     if (!IsEditable() || NS_UNLIKELY(IsDestroyed())) {
         return PR_FALSE;
     }
 
     PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
-        ("GtkIMModule(%p): OnKeyEvent, aCaller=%p",
-         this, aCaller));
+        ("GtkIMModule(%p): OnKeyEvent, aCaller=%p, aKeyDownEventWasSent=%s",
+         this, aCaller, aKeyDownEventWasSent ? "TRUE" : "FALSE"));
     PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
         ("    aEvent: type=%s, keyval=0x%X, unicode=0x%X",
          aEvent->type == GDK_KEY_PRESS ? "GDK_KEY_PRESS" :
          aEvent->type == GDK_KEY_RELEASE ? "GDK_KEY_RELEASE" : "Unknown",
          aEvent->keyval, gdk_keyval_to_unicode(aEvent->keyval)));
 
     if (aCaller != mLastFocusedWindow) {
         PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
@@ -389,16 +390,17 @@ nsGtkIMModule::OnKeyEvent(nsWindow* aCal
 
     GtkIMContext* im = GetContext();
     if (NS_UNLIKELY(!im)) {
         PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
             ("    FAILED, there are no context"));
         return PR_FALSE;
     }
 
+    mKeyDownEventWasSent = aKeyDownEventWasSent;
     mFilterKeyEvent = PR_TRUE;
     mProcessingKeyEvent = aEvent;
     gboolean isFiltered = gtk_im_context_filter_keypress(im, aEvent);
     mProcessingKeyEvent = nsnull;
 
     // We filter the key event if the event was not committed (because
     // it's probably part of a composition) or if the key event was
     // committed _and_ changed.  This way we still let key press
@@ -1035,23 +1037,26 @@ nsGtkIMModule::DispatchCompositionStart(
     if (!selection.mSucceeded || selection.mReply.mOffset == PR_UINT32_MAX) {
         PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
             ("    FAILED, cannot query the selection offset"));
         return PR_FALSE;
     }
 
     mCompositionStart = selection.mReply.mOffset;
 
-    if (mProcessingKeyEvent && mProcessingKeyEvent->type == GDK_KEY_PRESS) {
+    if (mProcessingKeyEvent && !mKeyDownEventWasSent &&
+        mProcessingKeyEvent->type == GDK_KEY_PRESS) {
         // If this composition is started by a native keydown event, we need to
         // dispatch our keydown event here (before composition start).
         nsCOMPtr<nsIWidget> kungFuDeathGrip = mLastFocusedWindow;
         PRBool isCancelled;
         mLastFocusedWindow->DispatchKeyDownEvent(mProcessingKeyEvent,
                                                  &isCancelled);
+        PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
+            ("    keydown event is dispatched"));
         if (static_cast<nsWindow*>(kungFuDeathGrip.get())->IsDestroyed() ||
             kungFuDeathGrip != mLastFocusedWindow) {
             PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
                 ("    NOTE, the focused widget was destroyed/changed by keydown event"));
             return PR_FALSE;
         }
     }
 
--- a/widget/src/gtk2/nsGtkIMModule.h
+++ b/widget/src/gtk2/nsGtkIMModule.h
@@ -84,31 +84,36 @@ protected:
 
 public:
     // aOwnerWindow is a pointer of the owner window.  When aOwnerWindow is
     // destroyed, the related IME contexts are released (i.e., IME cannot be
     // used with the instance after that).
     nsGtkIMModule(nsWindow* aOwnerWindow);
     ~nsGtkIMModule();
 
+    // "Enabled" means the users can use all IMEs.
+    // I.e., the focus is in the normal editors.
+    PRBool IsEnabled();
+
     // OnFocusWindow is a notification that aWindow is going to be focused.
     void OnFocusWindow(nsWindow* aWindow);
     // OnBlurWindow is a notification that aWindow is going to be unfocused.
     void OnBlurWindow(nsWindow* aWindow);
     // OnDestroyWindow is a notification that aWindow is going to be destroyed.
     void OnDestroyWindow(nsWindow* aWindow);
     // OnFocusChangeInGecko is a notification that an editor gets focus.
     void OnFocusChangeInGecko(PRBool aFocus);
 
     // OnKeyEvent is called when aWindow gets a native key press event or a
     // native key release event.  If this returns TRUE, the key event was
     // filtered by IME.  Otherwise, this returns FALSE.
     // NOTE: When the keypress event starts composition, this returns TRUE but
     //       this dispatches keydown event before compositionstart event.
-    PRBool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent);
+    PRBool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent,
+                      PRBool aKeyDownEventWasSent = PR_FALSE);
 
     // IME related nsIWidget methods.
     nsresult ResetInputState(nsWindow* aCaller);
     nsresult SetInputMode(nsWindow* aCaller, const IMEContext* aContext);
     nsresult GetInputMode(IMEContext* aContext);
     nsresult CancelIMEComposition(nsWindow* aCaller);
 
     // If a software keyboard has been opened, this returns TRUE.
@@ -174,16 +179,22 @@ protected:
     // be processed as simple key event, this is set to TRUE by the commit
     // handler.
     PRPackedBool mFilterKeyEvent;
     // When mIgnoreNativeCompositionEvent is TRUE, all native composition
     // should be ignored except that the compositon should be restarted in
     // another content (nsIContent).  Don't refer this value directly, use
     // ShouldIgnoreNativeCompositionEvent().
     PRPackedBool mIgnoreNativeCompositionEvent;
+    // mKeyDownEventWasSent is used by OnKeyEvent() and
+    // DispatchCompositionStart().  DispatchCompositionStart() dispatches
+    // a keydown event if the composition start is caused by a native
+    // keypress event.  If this is true, the keydown event has been dispatched.
+    // Then, DispatchCompositionStart() doesn't dispatch keydown event.
+    PRPackedBool mKeyDownEventWasSent;
 
     // sLastFocusedModule is a pointer to the last focused instance of this
     // class.  When a instance is destroyed and sLastFocusedModule refers it,
     // this is cleared.  So, this refers valid pointer always.
     static nsGtkIMModule* sLastFocusedModule;
 
     // Callback methods for native IME events.  These methods should call
     // the related instance methods simply.
@@ -214,20 +225,16 @@ protected:
     void OnStartCompositionNative(GtkIMContext *aContext);
     void OnEndCompositionNative(GtkIMContext *aContext);
 
 
     // GetContext() returns current IM context which is chosen by the enabled
     // state.  So, this means *current* IM context.
     GtkIMContext* GetContext();
 
-    // "Enabled" means the users can use all IMEs.
-    // I.e., the focus is in the normal editors.
-    PRBool IsEnabled();
-
     // "Editable" means the users can input characters. They may be not able to
     // use IMEs but they can use dead keys.
     // I.e., the focus is in the normal editors or the password editors or
     // the |ime-mode: disabled;| editors.
     PRBool IsEditable();
 
     // If the owner window and IM context have been destroyed, returns TRUE.
     PRBool IsDestroyed() { return !mOwnerWindow; }
--- a/widget/src/gtk2/nsWindow.cpp
+++ b/widget/src/gtk2/nsWindow.cpp
@@ -3009,18 +3009,22 @@ nsWindow::DispatchKeyDownEvent(GdkEventK
 
 gboolean
 nsWindow::OnKeyPressEvent(GtkWidget *aWidget, GdkEventKey *aEvent)
 {
     LOGFOCUS(("OnKeyPressEvent [%p]\n", (void *)this));
 
     // if we are in the middle of composing text, XIM gets to see it
     // before mozilla does.
-    if (mIMModule && mIMModule->OnKeyEvent(this, aEvent)) {
-        return TRUE;
+    PRBool IMEWasEnabled = PR_FALSE;
+    if (mIMModule) {
+        IMEWasEnabled = mIMModule->IsEnabled();
+        if (mIMModule->OnKeyEvent(this, aEvent)) {
+            return TRUE;
+        }
     }
 
     nsEventStatus status;
 
     // work around for annoying things.
     if (IsCtrlAltTab(aEvent)) {
         return TRUE;
     }
@@ -3034,16 +3038,27 @@ nsWindow::OnKeyPressEvent(GtkWidget *aWi
     // KEYDOWN -> KEYPRESS -> KEYUP -> KEYDOWN -> KEYPRESS -> KEYUP...
 
     PRBool isKeyDownCancelled = PR_FALSE;
     if (DispatchKeyDownEvent(aEvent, &isKeyDownCancelled) &&
         NS_UNLIKELY(mIsDestroyed)) {
         return TRUE;
     }
 
+    // If a keydown event handler causes to enable IME, i.e., it moves
+    // focus from IME unusable content to IME usable editor, we should
+    // send the native key event to IME for the first input on the editor.
+    if (!IMEWasEnabled && mIMModule && mIMModule->IsEnabled()) {
+        // Notice our keydown event was already dispatched.  This prevents
+        // unnecessary DOM keydown event in the editor.
+        if (mIMModule->OnKeyEvent(this, aEvent, PR_TRUE)) {
+            return TRUE;
+        }
+    }
+
     // Don't pass modifiers as NS_KEY_PRESS events.
     // TODO: Instead of selectively excluding some keys from NS_KEY_PRESS events,
     //       we should instead selectively include (as per MSDN spec; no official
     //       spec covers KeyPress events).
     if (aEvent->keyval == GDK_Shift_L
         || aEvent->keyval == GDK_Shift_R
         || aEvent->keyval == GDK_Control_L
         || aEvent->keyval == GDK_Control_R
--- a/widget/src/windows/GfxInfo.cpp
+++ b/widget/src/windows/GfxInfo.cpp
@@ -69,16 +69,24 @@ GfxInfo::GetD2DEnabled(PRBool *aEnabled)
 
 nsresult
 GfxInfo::GetDWriteEnabled(PRBool *aEnabled)
 {
   *aEnabled = gfxWindowsPlatform::GetPlatform()->DWriteEnabled();
   return NS_OK;
 }
 
+/* readonly attribute DOMString DWriteVersion; */
+NS_IMETHODIMP
+GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
+{
+  gfxWindowsPlatform::GetPlatform()->GetDLLVersion(L"dwrite.dll", aDwriteVersion);
+  return NS_OK;
+}
+
 /* XXX: GfxInfo doesn't handle multiple GPUs. We should try to do that. Bug #591057 */
 
 static nsresult GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName, nsAString& destString, int type)
 {
   HKEY key;
   DWORD dwcbData;
   DWORD dValue;
   DWORD resultType;
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -311,16 +311,18 @@ LPFNLRESULTFROMOBJECT
 
 #ifdef MOZ_IPC
 // Used in OOPP plugin focus processing.
 const PRUnichar* kOOPPPluginFocusEventId   = L"OOPP Plugin Focus Widget Event";
 PRUint32        nsWindow::sOOPPPluginFocusEvent   =
                   RegisterWindowMessageW(kOOPPPluginFocusEventId);
 #endif
 
+MSG             nsWindow::sRedirectedKeyDown;
+
 /**************************************************************
  *
  * SECTION: globals variables
  *
  **************************************************************/
 
 static const char *sScreenManagerContractID       = "@mozilla.org/gfx/screenmanager;1";
 
@@ -455,16 +457,18 @@ nsWindow::nsWindow() : nsBaseWidget()
 #if !defined(WINCE)
     InitInputHackDefaults();
 #endif
 
     // Init titlebar button info for custom frames.
     nsUXThemeData::InitTitlebarInfo();
     // Init theme data
     nsUXThemeData::UpdateNativeThemeInfo();
+
+    ForgetRedirectedKeyDownMessage();
   } // !sInstanceCount
 
   mIdleService = nsnull;
 
   sInstanceCount++;
 }
 
 nsWindow::~nsWindow()
@@ -5317,16 +5321,21 @@ PRBool nsWindow::ProcessMessage(UINT msg
     {
       LPWINDOWPOS info = (LPWINDOWPOS) lParam;
       OnWindowPosChanging(info);
     }
     break;
 #endif
 
     case WM_SETFOCUS:
+      // If previous focused window isn't ours, it must have received the
+      // redirected message.  So, we should forget it.
+      if (!IsOurProcessWindow(HWND(wParam))) {
+        ForgetRedirectedKeyDownMessage();
+      }
       if (sJustGotActivate) {
         result = DispatchFocusToTopLevelWindow(NS_ACTIVATE);
       }
 
 #ifdef ACCESSIBILITY
       if (nsWindow::sIsAccessibilityOn) {
         // Create it for the first time so that it can start firing events
         nsAccessible *rootAccessible = GetRootAccessible();
@@ -5875,16 +5884,35 @@ void nsWindow::PostSleepWakeNotification
 {
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
   if (observerService)
     observerService->NotifyObservers(nsnull, aNotification, nsnull);
 }
 #endif
 
+// RemoveNextCharMessage() should be called by WM_KEYDOWN or WM_SYSKEYDOWM
+// message handler.  If there is no WM_(SYS)CHAR message for it, this
+// method does nothing.
+// NOTE: WM_(SYS)CHAR message is posted by TranslateMessage() API which is
+// called in message loop.  So, WM_(SYS)KEYDOWN message should have
+// WM_(SYS)CHAR message in the queue if the keydown event causes character
+// input.
+
+/* static */
+void nsWindow::RemoveNextCharMessage(HWND aWnd)
+{
+  MSG msg;
+  if (::PeekMessageW(&msg, aWnd,
+                     WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD) &&
+      (msg.message == WM_CHAR || msg.message == WM_SYSCHAR)) {
+    ::GetMessageW(&msg, aWnd, msg.message, msg.message);
+  }
+}
+
 LRESULT nsWindow::ProcessCharMessage(const MSG &aMsg, PRBool *aEventDispatched)
 {
   NS_PRECONDITION(aMsg.message == WM_CHAR || aMsg.message == WM_SYSCHAR,
                   "message is not keydown event");
   PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
          ("%s charCode=%d scanCode=%d\n",
          aMsg.message == WM_SYSCHAR ? "WM_SYSCHAR" : "WM_CHAR",
          aMsg.wParam, HIWORD(aMsg.lParam) & 0xFF));
@@ -5936,16 +5964,22 @@ LRESULT nsWindow::ProcessKeyDownMessage(
                                         PRBool *aEventDispatched)
 {
   PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
          ("%s VK=%d\n", aMsg.message == WM_SYSKEYDOWN ?
                           "WM_SYSKEYDOWN" : "WM_KEYDOWN", aMsg.wParam));
   NS_PRECONDITION(aMsg.message == WM_KEYDOWN || aMsg.message == WM_SYSKEYDOWN,
                   "message is not keydown event");
 
+  // If this method doesn't call OnKeyDown(), this method must clean up the
+  // redirected message information itself.  For more information, see above
+  // comment of AutoForgetRedirectedKeyDownMessage struct definition in
+  // nsWindow.h.
+  AutoForgetRedirectedKeyDownMessage forgetRedirectedMessage(this, aMsg);
+
   nsModifierKeyState modKeyState;
 
   // Note: the original code passed (HIWORD(lParam)) to OnKeyDown as
   // scan code. However, this breaks Alt+Num pad input.
   // MSDN states the following:
   //  Typically, ToAscii performs the translation based on the
   //  virtual-key code. In some cases, however, bit 15 of the
   //  uScanCode parameter may be used to distinguish between a key
@@ -5957,16 +5991,19 @@ LRESULT nsWindow::ProcessKeyDownMessage(
       IS_VK_DOWN(NS_VK_SPACE))
     return FALSE;
 
   LRESULT result = 0;
   if (modKeyState.mIsAltDown && nsIMM32Handler::IsStatusChanged()) {
     nsIMM32Handler::NotifyEndStatusChange();
   } else if (!nsIMM32Handler::IsComposingOn(this)) {
     result = OnKeyDown(aMsg, modKeyState, aEventDispatched, nsnull);
+    // OnKeyDown cleaned up the redirected message information itself, so,
+    // we should do nothing.
+    forgetRedirectedMessage.mCancel = PR_TRUE;
   }
 
 #ifndef WINCE
   if (aMsg.wParam == VK_MENU ||
       (aMsg.wParam == VK_F10 && !modKeyState.mIsShiftDown)) {
     // We need to let Windows handle this keypress,
     // by returning PR_FALSE, if there's a native menu
     // bar somewhere in our containing window hierarchy.
@@ -6668,48 +6705,118 @@ UINT nsWindow::MapFromNativeToDOM(UINT a
     case VK_OEM_PLUS:  return NS_VK_ADD;           // 0xBB, For any country/region, the '+' key
     case VK_OEM_MINUS: return NS_VK_SUBTRACT;      // 0xBD, For any country/region, the '-' key
   }
 #endif
 
   return aNativeKeyCode;
 }
 
+/* static */
+PRBool nsWindow::IsRedirectedKeyDownMessage(const MSG &aMsg)
+{
+  return (aMsg.message == WM_KEYDOWN || aMsg.message == WM_SYSKEYDOWN) &&
+         (sRedirectedKeyDown.message == aMsg.message &&
+          GetScanCode(sRedirectedKeyDown.lParam) == GetScanCode(aMsg.lParam));
+}
+
 /**
  * nsWindow::OnKeyDown peeks into the message queue and pulls out
  * WM_CHAR messages for processing. During testing we don't want to
  * mess with the real message queue. Instead we pass a
  * pseudo-WM_CHAR-message using this structure, and OnKeyDown will use
  * that as if it was in the message queue, and refrain from actually
  * looking at or touching the message queue.
  */
 LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
                             nsModifierKeyState &aModKeyState,
                             PRBool *aEventDispatched,
                             nsFakeCharMessage* aFakeCharMessage)
 {
-  UINT virtualKeyCode = aMsg.wParam;
+  UINT virtualKeyCode =
+    aMsg.wParam != VK_PROCESSKEY ? aMsg.wParam : ::ImmGetVirtualKey(mWnd);
 
 #ifndef WINCE
-  gKbdLayout.OnKeyDown (virtualKeyCode);
+  gKbdLayout.OnKeyDown(virtualKeyCode);
 #endif
 
   // Use only DOMKeyCode for XP processing.
-  // Use aVirtualKeyCode for gKbdLayout and native processing.
+  // Use virtualKeyCode for gKbdLayout and native processing.
   UINT DOMKeyCode = nsIMM32Handler::IsComposingOn(this) ?
                       virtualKeyCode : MapFromNativeToDOM(virtualKeyCode);
 
 #ifdef DEBUG
   //printf("In OnKeyDown virt: %d\n", DOMKeyCode);
 #endif
 
-  PRBool noDefault =
-    DispatchKeyEvent(NS_KEY_DOWN, 0, nsnull, DOMKeyCode, &aMsg, aModKeyState);
-  if (aEventDispatched)
-    *aEventDispatched = PR_TRUE;
+  static PRBool sRedirectedKeyDownEventPreventedDefault = PR_FALSE;
+  PRBool noDefault;
+  if (aFakeCharMessage || !IsRedirectedKeyDownMessage(aMsg)) {
+    HIMC oldIMC = mOldIMC;
+    noDefault =
+      DispatchKeyEvent(NS_KEY_DOWN, 0, nsnull, DOMKeyCode, &aMsg, aModKeyState);
+    if (aEventDispatched) {
+      *aEventDispatched = PR_TRUE;
+    }
+
+    // If IMC wasn't associated to the window but is associated it now (i.e.,
+    // focus is moved from a non-editable editor to an editor by keydown
+    // event handler), WM_CHAR and WM_SYSCHAR shouldn't cause first character
+    // inputting if IME is opened.  But then, we should redirect the native
+    // keydown message to IME.
+    // However, note that if focus has been already moved to another
+    // application, we shouldn't redirect the message to it because the keydown
+    // message is processed by us, so, nobody shouldn't process it.
+    HWND focusedWnd = ::GetFocus();
+    if (!noDefault && !aFakeCharMessage && oldIMC && !mOldIMC && focusedWnd &&
+        !PluginHasFocus()) {
+      RemoveNextCharMessage(focusedWnd);
+
+      INPUT keyinput;
+      keyinput.type = INPUT_KEYBOARD;
+      keyinput.ki.wVk = aMsg.wParam;
+      keyinput.ki.wScan = GetScanCode(aMsg.lParam);
+      keyinput.ki.dwFlags = KEYEVENTF_SCANCODE;
+      if (IsExtendedScanCode(aMsg.lParam)) {
+        keyinput.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
+      }
+      keyinput.ki.time = 0;
+      keyinput.ki.dwExtraInfo = NULL;
+
+      sRedirectedKeyDownEventPreventedDefault = noDefault;
+      sRedirectedKeyDown = aMsg;
+
+      ::SendInput(1, &keyinput, sizeof(keyinput));
+
+      // Return here.  We shouldn't dispatch keypress event for this WM_KEYDOWN.
+      // If it's needed, it will be dispatched after next (redirected)
+      // WM_KEYDOWN.
+      return PR_TRUE;
+    }
+
+    if (mOnDestroyCalled) {
+      // If this was destroyed by the keydown event handler, we shouldn't
+      // dispatch keypress event on this window.
+      return PR_TRUE;
+    }
+  } else {
+    noDefault = sRedirectedKeyDownEventPreventedDefault;
+    // If this is redirected keydown message, we have dispatched the keydown
+    // event already.
+    if (aEventDispatched) {
+      *aEventDispatched = PR_TRUE;
+    }
+  }
+
+  ForgetRedirectedKeyDownMessage();
+
+  // If the key was processed by IME, we shouldn't dispatch keypress event.
+  if (aMsg.wParam == VK_PROCESSKEY) {
+    return noDefault;
+  }
 
   // If we won't be getting a WM_CHAR, WM_SYSCHAR or WM_DEADCHAR, synthesize a keypress
   // for almost all keys
   switch (DOMKeyCode) {
     case NS_VK_SHIFT:
     case NS_VK_CONTROL:
     case NS_VK_ALT:
     case NS_VK_CAPS_LOCK:
@@ -7403,24 +7510,29 @@ PRBool nsWindow::OnHotKey(WPARAM wParam,
 
 void nsWindow::OnSettingsChange(WPARAM wParam, LPARAM lParam)
 {
   if (mWindowType == eWindowType_dialog ||
       mWindowType == eWindowType_toplevel )
     nsWindowGfx::OnSettingsChangeGfx(wParam);
 }
 
-static PRBool IsOurProcessWindow(HWND aHWND)
-{
+/* static */
+PRBool nsWindow::IsOurProcessWindow(HWND aHWND)
+{
+  if (!aHWND) {
+    return PR_FALSE;
+  }
   DWORD processId = 0;
   ::GetWindowThreadProcessId(aHWND, &processId);
   return processId == ::GetCurrentProcessId();
 }
 
-static HWND FindOurProcessWindow(HWND aHWND)
+/* static */
+HWND nsWindow::FindOurProcessWindow(HWND aHWND)
 {
   for (HWND wnd = ::GetParent(aHWND); wnd; wnd = ::GetParent(wnd)) {
     if (IsOurProcessWindow(wnd)) {
       return wnd;
     }
   }
   return nsnull;
 }
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -331,26 +331,29 @@ protected:
   static void             InitInputHackDefaults();
 #endif
   static PRBool           UseTrackPointHack();
   static void             GetMainWindowClass(nsAString& aClass);
   PRBool                  HasGlass() const {
     return mTransparencyMode == eTransparencyGlass ||
            mTransparencyMode == eTransparencyBorderlessGlass;
   }
+  PRBool                  IsOurProcessWindow(HWND aHWND);
+  HWND                    FindOurProcessWindow(HWND aHWND);
 
   /**
    * Event processing helpers
    */
   PRBool                  DispatchPluginEvent(const MSG &aMsg);
   PRBool                  DispatchFocusToTopLevelWindow(PRUint32 aEventType);
   PRBool                  DispatchFocus(PRUint32 aEventType);
   PRBool                  DispatchStandardEvent(PRUint32 aMsg);
   PRBool                  DispatchCommandEvent(PRUint32 aEventCommand);
   void                    RelayMouseEvent(UINT aMsg, WPARAM wParam, LPARAM lParam);
+  static void             RemoveNextCharMessage(HWND aWnd);
   void                    RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, UINT aLastMsg);
   static MSG              InitMSG(UINT aMessage, WPARAM wParam, LPARAM lParam);
   virtual PRBool          ProcessMessage(UINT msg, WPARAM &wParam,
                                          LPARAM &lParam, LRESULT *aRetValue);
   PRBool                  ProcessMessageForPlugin(const MSG &aMsg,
                                                   LRESULT *aRetValue, PRBool &aCallDefWndProc);
   LRESULT                 ProcessCharMessage(const MSG &aMsg,
                                              PRBool *aEventDispatched);
@@ -363,16 +366,29 @@ protected:
   static PRBool           ConvertStatus(nsEventStatus aStatus);
   static void             PostSleepWakeNotification(const char* aNotification);
   PRBool                  HandleScrollingPlugins(UINT aMsg, WPARAM aWParam, 
                                                  LPARAM aLParam,
                                                  PRBool& aResult,
                                                  LRESULT* aRetValue,
                                                  PRBool& aQuitProcessing);
   PRInt32                 ClientMarginHitTestPoint(PRInt32 mx, PRInt32 my);
+  static WORD             GetScanCode(LPARAM aLParam)
+  {
+    return (aLParam >> 16) & 0xFF;
+  }
+  static PRBool           IsExtendedScanCode(LPARAM aLParam)
+  {
+    return (aLParam & 0x1000000) != 0;
+  }
+  static PRBool           IsRedirectedKeyDownMessage(const MSG &aMsg);
+  static void             ForgetRedirectedKeyDownMessage()
+  {
+    sRedirectedKeyDown.message = WM_NULL;
+  }
 
   /**
    * Event handlers
    */
   virtual void            OnDestroy();
   virtual PRBool          OnMove(PRInt32 aX, PRInt32 aY);
   virtual PRBool          OnResize(nsIntRect &aWindowRect);
   LRESULT                 OnChar(const MSG &aMsg,
@@ -603,16 +619,55 @@ protected:
   static PRBool         sSoftKeyboardState;
 #endif // defined(WINCE_HAVE_SOFTKB)
 
 #ifdef ACCESSIBILITY
   static BOOL           sIsAccessibilityOn;
   static HINSTANCE      sAccLib;
   static LPFNLRESULTFROMOBJECT sLresultFromObject;
 #endif // ACCESSIBILITY
+
+  // sRedirectedKeyDown is WM_KEYDOWN message or WM_SYSKEYDOWN message which
+  // was reirected to SendInput() API by OnKeyDown().
+  static MSG            sRedirectedKeyDown;
+
+  // If a window receives WM_KEYDOWN message or WM_SYSKEYDOWM message which is
+  // redirected message, OnKeyDowm() prevents to dispatch NS_KEY_DOWN event
+  // because it has been dispatched before the message was redirected.
+  // However, in some cases, ProcessKeyDownMessage() doesn't call OnKeyDown().
+  // Then, ProcessKeyDownMessage() needs to forget the redirected message and
+  // remove WM_CHAR message or WM_SYSCHAR message for the redirected keydown
+  // message.  AutoForgetRedirectedKeyDownMessage struct is a helper struct
+  // for doing that.  This must be created in stack.
+  struct AutoForgetRedirectedKeyDownMessage
+  {
+    AutoForgetRedirectedKeyDownMessage(nsWindow* aWindow, const MSG &aMsg) :
+      mCancel(!nsWindow::IsRedirectedKeyDownMessage(aMsg)),
+      mWindow(aWindow), mMsg(aMsg)
+    {
+    }
+
+    ~AutoForgetRedirectedKeyDownMessage()
+    {
+      if (mCancel) {
+        return;
+      }
+      // Prevent unnecessary keypress event
+      if (!mWindow->mOnDestroyCalled) {
+        nsWindow::RemoveNextCharMessage(mWindow->mWnd);
+      }
+      // Foreget the redirected message
+      nsWindow::ForgetRedirectedKeyDownMessage();
+    }
+
+    PRBool mCancel;
+    nsCOMPtr<nsWindow> mWindow;
+    const MSG &mMsg;
+  };
+
 };
 
 /**
  * A child window is a window with different style.
  */
 class ChildWindow : public nsWindow {
 
 public:
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -989,18 +989,16 @@ struct nsCycleCollector
 
     nsCycleCollectorParams mParams;
 
     nsTPtrArray<PtrInfo> *mWhiteNodes;
     PRUint32 mWhiteNodeCount;
 
     nsPurpleBuffer mPurpleBuf;
 
-    nsCOMPtr<nsICycleCollectorListener> mListener;
-
     void RegisterRuntime(PRUint32 langID, 
                          nsCycleCollectionLanguageRuntime *rt);
     nsCycleCollectionLanguageRuntime * GetRuntime(PRUint32 langID);
     void ForgetRuntime(PRUint32 langID);
 
     void SelectPurple(GCGraphBuilder &builder);
     void MarkRoots(GCGraphBuilder &builder);
     void ScanRoots();
@@ -1402,17 +1400,17 @@ class GCGraphBuilder : public nsCycleCol
 {
 private:
     NodePool::Builder mNodeBuilder;
     EdgePool::Builder mEdgeBuilder;
     PLDHashTable mPtrToNodeMap;
     PtrInfo *mCurrPi;
     nsCycleCollectionLanguageRuntime **mRuntimes; // weak, from nsCycleCollector
     nsCString mNextEdgeName;
-    nsCOMPtr<nsICycleCollectorListener> mListener;
+    nsICycleCollectorListener *mListener;
 
 public:
     GCGraphBuilder(GCGraph &aGraph,
                    nsCycleCollectionLanguageRuntime **aRuntimes,
                    nsICycleCollectorListener *aListener);
     ~GCGraphBuilder();
     bool Initialized();
 
@@ -2494,17 +2492,16 @@ nsCycleCollector::PrepareForCollection(n
 
     return PR_TRUE;
 }
 
 void
 nsCycleCollector::CleanupAfterCollection()
 {
     mWhiteNodes = nsnull;
-    mListener = nsnull;
     mCollectionInProgress = PR_FALSE;
 
 #ifdef XP_OS2
     // Now that the cycle collector has freed some memory, we can try to
     // force the C library to give back as much memory to the system as
     // possible.
     _heapmin();
 #endif
@@ -2522,24 +2519,16 @@ PRUint32
 nsCycleCollector::Collect(PRUint32 aTryCollections,
                           nsICycleCollectorListener *aListener)
 {
     nsAutoTPtrArray<PtrInfo, 4000> whiteNodes;
 
     if (!PrepareForCollection(&whiteNodes))
         return 0;
 
-#ifdef DEBUG_CC
-    nsCOMPtr<nsICycleCollectorListener> tempListener;
-    if (!aListener && mParams.mDrawGraphs) {
-        tempListener = new nsCycleCollectorLogger();
-        aListener = tempListener;
-    }
-#endif
-
     PRUint32 totalCollections = 0;
     while (aTryCollections > totalCollections) {
         // Synchronous cycle collection. Always force a JS GC as well.
         if (!(BeginCollection(PR_TRUE, aListener) && FinishCollection()))
             break;
 
         ++totalCollections;
     }
@@ -3280,17 +3269,17 @@ nsCycleCollector_DEBUG_wasFreed(nsISuppo
         sCollector->WasFreed(n);
 #endif
 }
 #endif
 
 class nsCycleCollectorRunner : public nsRunnable
 {
     nsCycleCollector *mCollector;
-    nsCOMPtr<nsICycleCollectorListener> mListener;
+    nsICycleCollectorListener *mListener;
     Mutex mLock;
     CondVar mRequest;
     CondVar mReply;
     PRBool mRunning;
     PRBool mCollected;
     PRBool mJSGCHasRun;
 
 public:
@@ -3325,16 +3314,17 @@ public:
             mReply.Notify();
         }
 
         return NS_OK;
     }
 
     nsCycleCollectorRunner(nsCycleCollector *collector)
         : mCollector(collector),
+          mListener(nsnull),
           mLock("cycle collector lock"),
           mRequest(mLock, "cycle collector request condvar"),
           mReply(mLock, "cycle collector reply condvar"),
           mRunning(PR_FALSE),
           mCollected(PR_FALSE),
           mJSGCHasRun(PR_FALSE)
     {
         NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@@ -3464,19 +3454,26 @@ nsCycleCollector_startup()
 
     return rv;
 }
 
 PRUint32
 nsCycleCollector_collect(nsICycleCollectorListener *aListener)
 {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+    nsCOMPtr<nsICycleCollectorListener> listener(aListener);
+#ifdef DEBUG_CC
+    if (!aListener && sCollector.mParams.mDrawGraphs) {
+        listener = new nsCycleCollectorLogger();
+    }
+#endif
+
     if (sCollectorRunner)
-        return sCollectorRunner->Collect(aListener);
-    return sCollector ? sCollector->Collect(1, aListener) : 0;
+        return sCollectorRunner->Collect(listener);
+    return sCollector ? sCollector->Collect(1, listener) : 0;
 }
 
 void
 nsCycleCollector_shutdownThreads()
 {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     if (sCollectorRunner) {
         nsRefPtr<nsCycleCollectorRunner> runner;
--- a/xpcom/glue/nsTObserverArray.h
+++ b/xpcom/glue/nsTObserverArray.h
@@ -36,16 +36,26 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsTObserverArray_h___
 #define nsTObserverArray_h___
 
 #include "nsTArray.h"
 
+/**
+ * An array of observers. Like a normal array, but supports iterators that are
+ * stable even if the array is modified during iteration.
+ * The template parameter T is the observer type the array will hold;
+ * N is the number of built-in storage slots that come with the array.
+ * NOTE: You probably want to use nsTObserverArray, unless you specifically
+ * want built-in storage. See below.
+ * @see nsTObserverArray, nsTArray
+ */
+
 class NS_COM_GLUE nsTObserverArray_base {
   public:
     typedef PRUint32 index_type;
     typedef PRUint32 size_type;
     typedef PRInt32  diff_type;
 
   protected:
     class Iterator_base {
@@ -85,26 +95,16 @@ class NS_COM_GLUE nsTObserverArray_base 
     /**
      * Clears iterators when the array is destroyed.
      */
     void ClearIterators();
 
     mutable Iterator_base* mIterators;
 };
 
-/**
- * An array of observers. Like a normal array, but supports iterators that are
- * stable even if the array is modified during iteration.
- * The template parameter T is the observer type the array will hold;
- * N is the number of built-in storage slots that come with the array.
- * NOTE: You probably want to use nsTObserverArray, unless you specifically
- * want built-in storage. See below.
- * @see nsTObserverArray, nsTArray
- */
-
 template<class T, PRUint32 N>
 class nsAutoTObserverArray : protected nsTObserverArray_base {
   public:
     typedef T           elem_type;
     typedef nsTArray<T> array_type;
 
     nsAutoTObserverArray() {
     }
--- a/xpcom/tests/unit/test_nsIProcess.js
+++ b/xpcom/tests/unit/test_nsIProcess.js
@@ -244,23 +244,23 @@ function test_kill_2()
     process.init(file);
 
     process.run(false, [], 0);
 
     try {
       process.kill();
     }
     catch (e) { }
+
+    // We need to ensure that we process any events on the main thread -
+    // this allow threads to clean up properly and avoid out of memory
+    // errors during the test.
+    while (thread.hasPendingEvents())
+      thread.processNextEvent(false);
   }
-
-  // We need to ensure that we process any events on the main thread -
-  // this allow threads to clean up properly and avoid out of memory
-  // errors during the test.
-  while (thread.hasPendingEvents())
-    thread.processNextEvent(false);
 }
 
 function run_test() {
   set_environment();
   test_kill();
   test_quick();
   test_arguments();
   test_unicode_arguments();