Merge cvs-trunk-mirror -> mozilla-central
authorbenjamin@smedbergs.us
Tue, 11 Mar 2008 11:22:05 -0400
changeset 12886 8ea3defc129b1945fe111b0e7651f2c0aae7c11f
parent 12851 eb6c4014c87751b4f48b0f52e5ae41b7427a253d (current diff)
parent 12885 cac2e03bfb96c7f2ddb5a4aeb865edaa16b693d6 (diff)
child 12892 8b08cdbcac631ee5fcf3c73f6f660ac9624b0ab3
push idunknown
push userunknown
push dateunknown
milestone2.0a1pre
Merge cvs-trunk-mirror -> mozilla-central
configure.in
js/src/Makefile.in
js/src/js.cpp
js/src/jsinterp.cpp
js/src/jsutil.cpp
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -382,17 +382,17 @@
             </menu>
 
   <menu id="bookmarksMenu" 
         label="&bookmarksMenu.label;" accesskey="&bookmarksMenu.accesskey;"
         ondragenter="PlacesMenuDNDController.onBookmarksMenuDragEnter(event);"
         ondragdrop="nsDragAndDrop.drop(event, BookmarksMenuDropHandler);"
         ondragover="nsDragAndDrop.dragOver(event, BookmarksMenuDropHandler);">
     <menupopup id="bookmarksMenuPopup"
-               type="places" asyncinit="true"
+               type="places"
                place="place:folder=2&amp;expandQueries=1"
                context="placesContext"
                openInTabs="children"
                oncommand="BookmarksEventHandler.onCommand(event);"
                onclick="BookmarksEventHandler.onClick(event);"
                onpopupshowing="BookmarksEventHandler.onPopupShowing(event);">
       <menuitem label="&bookmarkThisPageCmd.label;" 
                 command="Browser:AddBookmarkAs" key="addBookmarkAsKb"/>
@@ -406,22 +406,33 @@
             hidden="true">
         <menupopup id="subscribeToPageSubmenuMenupopup" 
                    onpopupshowing="return FeedHandler.buildFeedList(event.target);" 
                    oncommand="return FeedHandler.subscribeToFeed(null, event);"
                    onclick="checkForMiddleClick(this, event);"/>
       </menu>
       <menuitem label="&addCurPagesCmd.label;" 
                 command="Browser:BookmarkAllTabs" key="bookmarkAllTabsKb"/>
+      <menuseparator id="organizeBookmarksSeparator"/>
       <menuitem label="&showAllBookmarksCmd2.label;" 
                 command="Browser:ShowAllBookmarks" key="manBookmarkKb"/>
+      <menu id="bookmarksToolbarFolderMenu"
+            class="menu-iconic bookmark-item"
+            container="true">
+        <menupopup id="bookmarksToolbarFolderPopup"
+                   type="places"
+                   context="placesContext"
+                   oncommand="BookmarksEventHandler.onCommand(event);"
+                   onclick="BookmarksEventHandler.onClick(event);"
+                   onpopupshowing="BookmarksEventHandler.onPopupShowing(event);"/>
+      </menu>
       <menuseparator builder="start"/>
     </menupopup>
   </menu>
-        
+
             <menu id="tools-menu" label="&toolsMenu.label;" accesskey="&toolsMenu.accesskey;">
               <menupopup id="menu_ToolsPopup">
               <menuitem label="&search.label;" accesskey="&search.accesskey;" 
                         key="key_search" command="Tools:Search"/>
               <menuseparator/>
               <menuitem id="menu_openDownloads" label="&downloads.label;"
                         accesskey="&downloads.accesskey;"
                         key="key_openDownloads" command="Tools:Downloads"/>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -255,25 +255,27 @@ function BookmarkThisTab()
   if (tab.localName != "tab")
     tab = getBrowser().mCurrentTab;
 
   PlacesCommandHook.bookmarkPage(tab.linkedBrowser,
                                  PlacesUtils.bookmarksMenuFolderId, true);
 }
 
 /**
- * Initialize the bookmarks toolbar
+ * Initialize the bookmarks toolbar and the menuitem for it.
  */
 function initBookmarksToolbar() {
+  var place = PlacesUtils.getQueryStringForFolder(PlacesUtils.bookmarks.toolbarFolder);
   var bt = document.getElementById("bookmarksBarContent");
-  if (!bt)
-    return;
-
-  bt.place =
-    PlacesUtils.getQueryStringForFolder(PlacesUtils.bookmarks.toolbarFolder);
+  if (bt)
+    bt.place = place;
+
+  document.getElementById("bookmarksToolbarFolderPopup").place = place;
+  document.getElementById("bookmarksToolbarFolderMenu").label =
+    PlacesUtils.bookmarks.getItemTitle(PlacesUtils.bookmarks.toolbarFolder);
 }
 
 const gSessionHistoryObserver = {
   observe: function(subject, topic, data)
   {
     if (topic != "browser:purge-session-history")
       return;
 
@@ -762,16 +764,22 @@ function BrowserStartup()
       // border.  Use 28px as a guess (titlebar + bottom window border)
       defaultHeight -= 28;
 #endif
     }
     document.documentElement.setAttribute("width", defaultWidth);
     document.documentElement.setAttribute("height", defaultHeight);
   }
 
+  if (gURLBar && document.documentElement.getAttribute("chromehidden").indexOf("toolbar") != -1) {
+
+    gURLBar.setAttribute("readonly", "true");
+    gURLBar.setAttribute("enablehistory", "false");
+  }
+
   setTimeout(delayedStartup, 0);
 }
 
 function HandleAppCommandEvent(evt)
 {
   evt.stopPropagation();
   switch (evt.command) {
   case "Back":
@@ -889,21 +897,16 @@ function delayedStartup()
   os.addObserver(gXPInstallObserver, "xpinstall-install-blocked", false);
 
   if (!gPrefService)
     gPrefService = Components.classes["@mozilla.org/preferences-service;1"]
                              .getService(Components.interfaces.nsIPrefBranch2);
   BrowserOffline.init();
   OfflineApps.init();
 
-  if (gURLBar && document.documentElement.getAttribute("chromehidden").indexOf("toolbar") != -1) {
-    gURLBar.setAttribute("readonly", "true");
-    gURLBar.setAttribute("enablehistory", "false");
-  }
-
   gBrowser.addEventListener("pageshow", function(evt) { setTimeout(pageShowEventHandlers, 0, evt); }, true);
 
   window.addEventListener("keypress", ctrlNumberTabSelection, false);
 
   // Ensure login manager is up and running.
   Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
 
   if (gMustLoadSidebar) {
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -772,17 +772,17 @@
           if (iconURI) {
             var spec = iconURI.spec;
             if (menuitem.getAttribute("image") != spec)
               menuitem.setAttribute("image", spec);
           }
           else
             menuitem.removeAttribute("image");
 
-          var title = aNode.title;
+          var title = PlacesUtils.getBestTitle(aNode);
           if (menuitem.getAttribute("label") != title)
             menuitem.setAttribute("label", title);
 
           if (!menuitem.hasAttribute("livemark") &&
               PlacesUtils.nodeIsLivemarkContainer(aNode))
             menuitem.setAttribute("livemark", "true");
         },
 
--- a/browser/components/places/content/toolbar.xml
+++ b/browser/components/places/content/toolbar.xml
@@ -538,46 +538,48 @@
             onToolbar = true;
             var children = this._self.childNodes;
             for (var i = 0; i < children.length; i++) {
               if (children[i].node == aNode) {
                 element = children[i];
                 break;
               }
             }
+            // Don't replace title on toolbarbuttons
+            var title = aNode.title;
           }
           else {
             var popup = this._getPopupForContainer(parentNode);
             if (!popup._built)
               return;
 
             var children = popup.childNodes;
             for (var i = 0; i < children.length; i++) {
               if (children[i].node == aNode) {
                 element = children[i];
                 break;
               }
-            }            
+            }
+            var title = PlacesUtils.getBestTitle(aNode);
           }
 
           if (PlacesUtils.nodeIsSeparator(aNode)) {
             // nothing to do when a separator changes
             return;
           }
 
           var iconURI = aNode.icon;
           if (iconURI) {
             var spec = iconURI.spec;
             if (element.getAttribute("image") != spec)
               element.setAttribute("image", spec);
           }
           else
             element.removeAttribute("image");
 
-          var title = aNode.title;
           if (element.getAttribute("label") != title) {
             element.setAttribute("label", title);
             if (onToolbar)
               this._self.updateChevron();
           }
 
           if (!element.hasAttribute("livemark") &&
               PlacesUtils.nodeIsLivemarkContainer(aNode))
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -1126,17 +1126,17 @@ PlacesTreeView.prototype = {
     switch (columnType) {
       case this.COLUMN_TYPE_TITLE:
         // normally, this is just the title, but we don't want empty items in
         // the tree view so return a special string if the title is empty.
         // Do it here so that callers can still get at the 0 length title
         // if they go through the "result" API.
         if (PlacesUtils.nodeIsSeparator(node))
           return "";
-        return node.title || PlacesUtils.getString("noTitle");
+        return PlacesUtils.getBestTitle(node);
       case this.COLUMN_TYPE_TAGS:
         return node.tags;
       case this.COLUMN_TYPE_URI:
         if (PlacesUtils.nodeIsURI(node))
           return node.uri;
         return "";
       case this.COLUMN_TYPE_DATE:
         if (node.time == 0 || !PlacesUtils.nodeIsURI(node)) {
--- a/browser/components/places/content/utils.js
+++ b/browser/components/places/content/utils.js
@@ -187,16 +187,24 @@ var PlacesUtils = {
   },
 
   get URIFixup() {
     delete this.URIFixup;
     return this.URIFixup = Cc["@mozilla.org/docshell/urifixup;1"].
                            getService(Ci.nsIURIFixup);
   },
 
+  get ellipsis() {
+    delete this.ellipsis;
+    var pref = Cc["@mozilla.org/preferences-service;1"].
+               getService(Ci.nsIPrefBranch);
+    return this.ellipsis = pref.getComplexValue("intl.ellipsis",
+                                                Ci.nsIPrefLocalizedString).data;
+  },
+
   /**
    * Makes a URI from a spec.
    * @param   aSpec
    *          The string spec of the URI
    * @returns A URI object for the spec.
    */
   _uri: function PU__uri(aSpec) {
     NS_ASSERT(aSpec, "empty URL spec");
@@ -1872,26 +1880,52 @@ var PlacesUtils = {
         element.appendChild(popup);
         if (aContainersMap)
           aContainersMap.push({ resultNode: aNode, domNode: popup });
         element.className = "menu-iconic bookmark-item";
       }
       else
         throw "Unexpected node";
 
-      element.setAttribute("label", aNode.title);
+      element.setAttribute("label", this.getBestTitle(aNode));
+
       if (iconURISpec)
         element.setAttribute("image", iconURISpec);
     }
     element.node = aNode;
     element.node.viewIndex = 0;
 
     return element;
   },
 
+  getBestTitle: function PU_getBestTitle(aNode) {
+    var title;
+    if (!aNode.title && this.uriTypes.indexOf(aNode.type) != -1) {
+      // if node title is empty, try to set the label using host and filename
+      // this._uri() will throw if aNode.uri is not a valid URI
+      try {
+        var uri = this._uri(aNode.uri);
+        var host = uri.host;
+        var fileName = uri.QueryInterface(Ci.nsIURL).fileName;
+        // if fileName is empty, use path to distinguish labels
+        title = host + (fileName ?
+                        (host ? "/" + this.ellipsis + "/" : "") + fileName :
+                        uri.path);
+      }
+      catch (e) {
+        // Use (no title) for non-standard URIs (data:, javascript:, ...)
+        title = "";
+      }
+    }
+    else
+      title = aNode.title;
+
+    return title || PlacesUtils.getString("noTitle");
+  },
+
   get leftPaneQueries() {    
     // build the map
     this.leftPaneFolderId;
     return this.leftPaneQueries;
   },
 
   // get the folder id for the organizer left-pane folder
   get leftPaneFolderId() {
--- a/browser/locales/en-US/chrome/browser/preferences/connection.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/connection.dtd
@@ -1,32 +1,32 @@
 
 <!ENTITY  connectionsDialog.title       "Connection Settings">
 <!ENTITY  window.width                  "37em">
 <!ENTITY  window.macWidth               "39em">
 
 <!ENTITY  proxyTitle.label              "Configure Proxies to Access the Internet">
 <!ENTITY  noProxyTypeRadio.label        "No proxy">
-<!ENTITY  noProxyTypeRadio.accesskey    "x">
+<!ENTITY  noProxyTypeRadio.accesskey    "y">
 <!ENTITY  systemTypeRadio.label         "Use system proxy settings">
 <!ENTITY  systemTypeRadio.accesskey     "u">
 <!ENTITY  WPADTypeRadio.label           "Auto-detect proxy settings for this network">
 <!ENTITY  WPADTypeRadio.accesskey       "w">
 <!ENTITY  manualTypeRadio.label         "Manual proxy configuration:">
 <!ENTITY  manualTypeRadio.accesskey     "m">
 <!ENTITY  autoTypeRadio.label           "Automatic proxy configuration URL:">
 <!ENTITY  autoTypeRadio.accesskey       "A">
 <!ENTITY  reload.label                  "Reload">
 <!ENTITY  reload.accesskey              "e">
 <!ENTITY  ftp.label                     "FTP Proxy:">
 <!ENTITY  ftp.accesskey                 "F">
 <!ENTITY  gopher.label                  "Gopher Proxy:">
 <!ENTITY  gopher.accesskey              "G">
 <!ENTITY  http.label                    "HTTP Proxy:">
-<!ENTITY  http.accesskey                "y">
+<!ENTITY  http.accesskey                "H">
 <!ENTITY  ssl.label                     "SSL Proxy:">
 <!ENTITY  ssl.accesskey                 "S">
 <!ENTITY  socks.label                   "SOCKS Host:">
 <!ENTITY  socks.accesskey               "C">
 <!ENTITY  socks4.label                  "SOCKS v4">
 <!ENTITY  socks4.accesskey              "K">
 <!ENTITY  socks5.label                  "SOCKS v5">
 <!ENTITY  socks5.accesskey              "v">
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -945,17 +945,17 @@ toolbar[iconsize="small"] #paste-button[
 
 #urlbar > .autocomplete-textbox-container {
   -moz-binding: url(chrome://browser/skin/browser.xml#autocomplete-security-wrapper);
 }
 
 #autocomplete-security-wrapper {
   /* keep the URL bar content LTR */
   direction: ltr;
-  -moz-box-align: center;
+  -moz-box-align: stretch;
   /* cover the white gap between the text field and the drop down button */
   margin-right: -3px;
 }
 
 #urlbar[chromedir="rtl"] > .autocomplete-textbox-container > #autocomplete-security-wrapper {
   margin-right: 0px;
   margin-left: -3px;
 }
--- a/browser/themes/gnomestripe/browser/pageInfo.css
+++ b/browser/themes/gnomestripe/browser/pageInfo.css
@@ -73,16 +73,21 @@
 #permTab {
   -moz-image-region: rect(0px, 128px, 32px, 96px)
 }
 
 #securityTab {
   -moz-image-region: rect(0px, 160px, 32px, 128px)
 }
 
+#mainDeck {
+  padding-left: 2px;
+  padding-right: 2px;
+}
+
 deck {
   padding: 10px 10px 10px 10px;
 }
 
 /* Misc */
 tree {
   margin: .5em;
 }
@@ -113,16 +118,24 @@ textbox.header {
   height: 8.5em;
 }
 
 textbox[disabled] {
   font-style: italic;
 }
 
 /* General Tab */
+#generalPanel > #titletext {
+  -moz-margin-start: 5px;
+}
+#metaTags > .groupbox-body {
+  -moz-margin-start: 5px;
+  -moz-margin-end: 1px;
+}
+
 groupbox.collapsable caption .caption-icon { 
   width: 9px;
   height: 9px;
   background-repeat: no-repeat;
   background-position: center;
   -moz-margin-start: 1px;
   -moz-margin-end: 3px;
   background-image: url("chrome://global/skin/tree/twisty-open.png");
@@ -152,16 +165,17 @@ groupbox.treebox .groupbox-body {
 #general-security-identity {
   white-space: pre-wrap;
   line-height: 2em;
 }
 
 /* Media Tab */
 #imagetree {
   min-height: 10em;
+  margin-top: 2px;
 }
 
 #mediaGrid {
   min-height: 9em;
 }
 
 #mediaLabelColumn {
   min-width: 10em;
@@ -171,17 +185,27 @@ groupbox.treebox .groupbox-body {
   margin: 1em;
 }
 
 treechildren::-moz-tree-cell-text(broken) {
   font-style: italic;
   color: graytext;
 }
 
+#mediaPreviewBox .inset {
+  -moz-appearance: listbox;
+  margin-bottom: 0;  
+}
+
 /* Feeds Tab */
+#feedPanel {
+  margin-left: 2px;
+  margin-right: 2px;
+}
+
 #feedtree {
   margin-bottom: 0px;
 }
 
 #feedListbox richlistitem {
   padding-top: 6px;
   padding-bottom: 6px;
   -moz-padding-start: 7px;
@@ -191,28 +215,34 @@ treechildren::-moz-tree-cell-text(broken
 }
 
 #feedListbox richlistitem[selected="true"] {
   background-color: -moz-Dialog;
   color: -moz-DialogText;
 }
 
 #feedListbox {
+  margin-bottom: 0;
   border: 2px solid;
   -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
   -moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
   -moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
   -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
 }
 
 .feedTitle { 
   font-weight: bold;
 }
 
 /* Permissions Tab */
+#permPanel {
+  margin-left: 6px;
+  margin-right: 6px;
+}
+
 #permList {
   -moz-appearance: listbox;
   margin-top: .5em;
   overflow: auto;
   border: 2px solid;
   -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
   -moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
   -moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
--- a/browser/themes/gnomestripe/browser/preferences/preferences.css
+++ b/browser/themes/gnomestripe/browser/preferences/preferences.css
@@ -145,16 +145,35 @@ filefield[disabled="true"] .fileFieldIco
 /* Cookies Manager */
 #cookiesChildren::-moz-tree-image(domainCol) {
   width: 16px;
   height: 16px;
   margin: 0px 2px;
   list-style-image: url("moz-icon://stock/gtk-file?size=menu");
 }
 
+#paneApplications {
+  margin-left: 4px;
+  margin-right: 4px; 
+  padding-left: 0;
+  padding-right: 0; 
+}
+
+#linksOpenInBox {
+  margin-top: 5px;
+}
+
+#paneAdvanced {
+  padding-bottom: 10px;
+}
+#advancedPrefs {
+  margin-left: 0;
+  margin-right: 0; 
+}
+
 #cookiesChildren::-moz-tree-image(domainCol, container) {
   list-style-image: url("moz-icon://stock/gtk-directory?size=menu");
 }
 
 #cookieInfoBox {
   border: 1px solid ThreeDShadow;
   -moz-border-radius: 0px;
   margin: 4px;
--- a/configure.in
+++ b/configure.in
@@ -702,17 +702,17 @@ from building Mozilla. Upgrade to Xcode 
     dnl xcodebuild needs GCC_VERSION defined in the environment, since it
     dnl doesn't respect the CC/CXX setting.  With GCC_VERSION set, it will use
     dnl /usr/bin/g(cc|++)-$GCC_VERSION.
     AC_PATH_PROGS(PBBUILD, pbbuild xcodebuild pbxbuild)
 
     case "$PBBUILD" in
       *xcodebuild*)
         changequote(,)
-        XCODEBUILD_VERSION=`$PBBUILD -version 2>/dev/null | sed -e 's/.*DevToolsCore-\([0-9]*\).*/\1/'`
+        XCODEBUILD_VERSION=`$PBBUILD -version 2>/dev/null | sed -e 's/.*DevToolsCore-\([0-9]*\).*/\1/' | tail -n 1`
         changequote([,])
         if test -n "$XCODEBUILD_VERSION" && test "$XCODEBUILD_VERSION" -ge 620 ; then
           HAS_XCODE_2_1=1;
         fi
       ;;
     esac
 
     dnl sdp was formerly in /Developer/Tools.  As of Mac OS X 10.4 (Darwin 8),
--- a/content/base/src/nsDOMAttributeMap.cpp
+++ b/content/base/src/nsDOMAttributeMap.cpp
@@ -476,17 +476,17 @@ nsDOMAttributeMap::RemoveNamedItemNS(con
 
   nsresult rv = GetNamedItemNSInternal(aNamespaceURI,
                                        aLocalName,
                                        aReturn,
                                        PR_TRUE);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!*aReturn) {
-    return NS_OK;
+    return NS_ERROR_DOM_NOT_FOUND_ERR;
   }
 
   nsCOMPtr<nsIAttribute> attr = do_QueryInterface(*aReturn);
   NS_ASSERTION(attr, "attribute returned from nsDOMAttributeMap::GetNameItemNS "
                "didn't implement nsIAttribute");
   NS_ENSURE_TRUE(attr, NS_ERROR_UNEXPECTED);
 
   nsINodeInfo *ni = attr->NodeInfo();
--- a/dom/tests/mochitest/dom-level2-core/exclusions.js
+++ b/dom/tests/mochitest/dom-level2-core/exclusions.js
@@ -54,21 +54,17 @@ dtdTests = ["attrgetownerelement01", "do
             "prefix08", "removeAttributeNS01", "removeAttributeNS02",
             "removeNamedItemNS03", "setAttributeNodeNS02", "setAttributeNS03",
             "setNamedItemNS04"];
 
 bug371552 = ["elementhasattributens02"];
 wrongDocError = ["elementsetattributenodens05", "namednodemapsetnameditemns03",
                  "setAttributeNodeNS05", "setNamedItemNS02"];
 attrAppendChild = ["elementsetattributenodens06", "importNode01"];
-removeNamedItemNS = ["namednodemapremovenameditemns06",
-                     "namednodemapremovenameditemns07",
-                     "namednodemapremovenameditemns08",
-                     "removeNamedItemNS02"];
 bogusPrefix = ["nodesetprefix05", "nodesetprefix09", "prefix06", "prefix07"];
 prefixReplacement = ["setAttributeNodeNS04"];
 
 var todoTests = {};
 var exclusions = concat(dtdTests, bug371552, wrongDocError, attrAppendChild,
-                        removeNamedItemNS, bogusPrefix, prefixReplacement);
+                        bogusPrefix, prefixReplacement);
 for (var excludedTestName in exclusions) { 
   todoTests[exclusions[excludedTestName]] = true; 
 }
--- a/gfx/public/nsIRenderingContext.h
+++ b/gfx/public/nsIRenderingContext.h
@@ -536,17 +536,18 @@ public:
                         PRInt32 aFontID = -1,
                         const nscoord* aSpacing = nsnull) = 0;
 
   enum GraphicDataType {
     NATIVE_CAIRO_CONTEXT = 1,
     NATIVE_GDK_DRAWABLE = 2,
     NATIVE_WINDOWS_DC = 3,
     NATIVE_MAC_THING = 4,
-    NATIVE_THEBES_CONTEXT = 5
+    NATIVE_THEBES_CONTEXT = 5,
+    NATIVE_OS2_PS = 6
   };
   /**
    * Retrieve the native graphic data given by aType. Return
    * nsnull if not available.
    */
   virtual void* GetNativeGraphicData(GraphicDataType aType) = 0;
 
 #ifdef MOZ_MATHML
--- a/gfx/src/thebes/nsThebesRenderingContext.cpp
+++ b/gfx/src/thebes/nsThebesRenderingContext.cpp
@@ -715,16 +715,24 @@ nsThebesRenderingContext::GetNativeGraph
 #ifdef XP_WIN
     if (aType == NATIVE_WINDOWS_DC) {
         nsRefPtr<gfxASurface> surf(mThebes->CurrentSurface());
         if (!surf || surf->CairoStatus())
             return nsnull;
         return static_cast<gfxWindowsSurface*>(static_cast<gfxASurface*>(surf.get()))->GetDC();
     }
 #endif
+#ifdef XP_OS2
+    if (aType == NATIVE_OS2_PS) {
+        nsRefPtr<gfxASurface> surf(mThebes->CurrentSurface());
+        if (!surf || surf->CairoStatus())
+            return nsnull;
+        return (void*)(static_cast<gfxOS2Surface*>(static_cast<gfxASurface*>(surf.get()))->GetPS());
+    }
+#endif
 
     return nsnull;
 }
 
 NS_IMETHODIMP
 nsThebesRenderingContext::PushFilter(const nsRect& twRect, PRBool aAreaIsOpaque, float aOpacity)
 {
     PR_LOG(gThebesGFXLog, PR_LOG_DEBUG,
--- a/gfx/thebes/src/gfxTextRunWordCache.cpp
+++ b/gfx/thebes/src/gfxTextRunWordCache.cpp
@@ -400,17 +400,17 @@ TextRunWordCache::FinishTextRun(gfxTextR
                     // URK! This case sucks! We have combining marks
                     // at the start of the text. We had to prepend a space
                     // just so we could detect these are combining marks
                     // (so we can keep this "word" out of the cache).
                     // But now the data in aNewRun is no use to us. We
                     // need to find out what the platform would do
                     // if the marks were at the start of the text.
                     tmpTextRun = aNewRun->GetFontGroup()->MakeTextRun(
-                        aTextRun->GetTextUnicode() + sourceOffset, length, aParams,
+                        source->GetTextUnicode() + sourceOffset, length, aParams,
                         aNewRun->GetFlags());
                     source = tmpTextRun;
                     sourceOffset = 0;
                     stealData = PR_TRUE;
                 }
             }
             aTextRun->CopyGlyphDataFrom(source, sourceOffset, length,
                 destOffset, stealData);
@@ -734,17 +734,17 @@ TextRunWordCache::CacheHashEntry::HashKe
 PLDHashOperator PR_CALLBACK
 TextRunWordCache::CacheDumpEntry(CacheHashEntry* aEntry, void* userArg)
 {
     FILE* output = static_cast<FILE*>(userArg);
     if (!aEntry->mTextRun) {
         fprintf(output, "<EMPTY>\n");
         return PL_DHASH_NEXT;
     }
-    fprintf(output, "Word at %x:%d => ", aEntry->mTextRun, aEntry->mWordOffset);
+    fprintf(output, "Word at %p:%d => ", static_cast<void*>(aEntry->mTextRun), aEntry->mWordOffset);
     aEntry->mTextRun->Dump(output);
     fprintf(output, " (hashed by %s)\n", aEntry->mHashedByFont ? "font" : "fontgroup");
     return PL_DHASH_NEXT;
 }
 
 void
 TextRunWordCache::Dump()
 {
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -459,32 +459,28 @@ jsds_FilterHook (JSDContext *jsdc, JSDTh
 
 /*******************************************************************************
  * c callbacks
  *******************************************************************************/
 
 JS_STATIC_DLL_CALLBACK (void)
 jsds_NotifyPendingDeadScripts (JSContext *cx)
 {
-    /* Bug 411249, we can't drop the script hook.
-     * Even if we could drop the script hook, jsds_GCCallbackProc
-     * is never cleared, so it would call us anyway.
-     *
-     * If there's no gJsds, then we can't do anything.
-     */
-    if (!gJsds)
-        return;
-
-    nsCOMPtr<jsdIScriptHook> hook = 0;   
-    gJsds->GetScriptHook (getter_AddRefs(hook));
-
 #ifdef CAUTIOUS_SCRIPTHOOK
     JSRuntime *rt = JS_GetRuntime(cx);
 #endif
-    gJsds->Pause(nsnull);
+    jsdService *jsds = gJsds;
+
+    nsCOMPtr<jsdIScriptHook> hook;
+    if (jsds) {
+        NS_ADDREF(jsds);
+        jsds->GetScriptHook (getter_AddRefs(hook));
+        jsds->Pause(nsnull);
+    }
+
     DeadScript *deadScripts = gDeadScripts;
     gDeadScripts = nsnull;
     while (deadScripts) {
         DeadScript *ds = deadScripts;
         /* get next deleted script */
         deadScripts = reinterpret_cast<DeadScript *>
                                        (PR_NEXT_LINK(&ds->links));
         if (deadScripts == ds)
@@ -506,17 +502,20 @@ jsds_NotifyPendingDeadScripts (JSContext
         PR_REMOVE_LINK(&ds->links);
 
         /* addref came from the FromPtr call in jsds_ScriptHookProc */
         NS_RELEASE(ds->script);
         /* free the struct! */
         PR_Free(ds);
     }
 
-    gJsds->UnPause(nsnull);
+    if (jsds) {
+        jsds->UnPause(nsnull);
+        NS_RELEASE(jsds);
+    }
 }
 
 JS_STATIC_DLL_CALLBACK (JSBool)
 jsds_GCCallbackProc (JSContext *cx, JSGCStatus status)
 {
 #ifdef DEBUG_verbose
     printf ("new gc status is %i\n", status);
 #endif
@@ -2557,37 +2556,36 @@ jsdService::Off (void)
 {
     if (!mOn)
         return NS_OK;
     
     if (!mCx || !mRuntime)
         return NS_ERROR_NOT_INITIALIZED;
     
     if (gDeadScripts) {
-        if (gGCStatus == JSGC_END)
-        {
-            JSContext *cx = JSD_GetDefaultJSContext(mCx);
-            jsds_NotifyPendingDeadScripts(cx);
-        }
-        else
+        if (gGCStatus != JSGC_END)
             return NS_ERROR_NOT_AVAILABLE;
+
+        JSContext *cx = JSD_GetDefaultJSContext(mCx);
+        jsds_NotifyPendingDeadScripts(cx);
     }
 
     /*
     if (gLastGCProc != jsds_GCCallbackProc)
         JS_SetGCCallbackRT (mRuntime, gLastGCProc);
     */
 
     jsdContext::InvalidateAll();
     jsdScript::InvalidateAll();
     jsdValue::InvalidateAll();
     jsdProperty::InvalidateAll();
     ClearAllBreakpoints();
 
     JSD_SetErrorReporter (mCx, NULL, NULL);
+    JSD_SetScriptHook (mCx, NULL, NULL);
     JSD_ClearThrowHook (mCx);
     JSD_ClearInterruptHook (mCx);
     JSD_ClearDebuggerHook (mCx);
     JSD_ClearDebugBreakHook (mCx);
     JSD_ClearTopLevelHook (mCx);
     JSD_ClearFunctionHook (mCx);
     
     JSD_DebuggerOff (mCx);
@@ -3273,16 +3271,26 @@ jsdService::GetFunctionHook (jsdICallHoo
     
     return NS_OK;
 }
 
 /* virtual */
 jsdService::~jsdService()
 {
     ClearFilters();
+    mErrorHook = nsnull;
+    mBreakpointHook = nsnull;
+    mDebugHook = nsnull;
+    mDebuggerHook = nsnull;
+    mInterruptHook = nsnull;
+    mScriptHook = nsnull;
+    mThrowHook = nsnull;
+    mTopLevelHook = nsnull;
+    mFunctionHook = nsnull;
+    gGCStatus = JSGC_END;
     Off();
     gJsds = nsnull;
 }
 
 jsdService *
 jsdService::GetService ()
 {
     if (!gJsds)
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -44,17 +44,17 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= js
 LIBRARY_NAME	= mozjs
 GRE_MODULE	= 1
 
 ifdef GNU_CC
-MODULE_OPTIMIZE_FLAGS = -Os
+MODULE_OPTIMIZE_FLAGS = -Os -fstrict-aliasing
 else
 ifeq ($(OS_ARCH),SunOS)
 MODULE_OPTIMIZE_FLAGS = -O
 endif
 ifeq ($(OS_ARCH),WINNT)
 MODULE_OPTIMIZE_FLAGS = -O2 -GL
 endif
 endif
--- a/js/src/js.cpp
+++ b/js/src/js.cpp
@@ -108,23 +108,16 @@ static JSBool gEnableBranchCallback = JS
 static uint32 gBranchCount;
 static uint32 gBranchLimit;
 
 int gExitCode = 0;
 JSBool gQuitting = JS_FALSE;
 FILE *gErrFile = NULL;
 FILE *gOutFile = NULL;
 
-#ifdef JSDEBUGGER
-static JSDContext *_jsdc;
-#ifdef JSDEBUGGER_JAVA_UI
-static JSDJContext *_jsdjc;
-#endif /* JSDEBUGGER_JAVA_UI */
-#endif /* JSDEBUGGER */
-
 static JSBool reportWarnings = JS_TRUE;
 static JSBool compileOnly = JS_FALSE;
 
 typedef enum JSShellErrNum {
 #define MSG_DEF(name, number, count, exception, format) \
     name = number,
 #include "jsshell.msg"
 #undef MSG_DEF
@@ -3799,22 +3792,26 @@ main(int argc, char **argv, char **envp)
     int stackDummy;
     JSRuntime *rt;
     JSContext *cx;
     JSObject *glob, *it, *envobj;
     int result;
 #ifdef LIVECONNECT
     JavaVM *java_vm = NULL;
 #endif
+#ifdef JSDEBUGGER
+    JSDContext *jsdc;
 #ifdef JSDEBUGGER_JAVA_UI
     JNIEnv *java_env;
+    JSDJContext *jsdjc;
 #endif
 #ifdef JSDEBUGGER_C_UI
     JSBool jsdbc;
 #endif /* JSDEBUGGER_C_UI */
+#endif /* JSDEBUGGER */
 
     CheckHelpMessages();
     setlocale(LC_ALL, "");
 
     gStackBase = (jsuword)&stackDummy;
 
 #ifdef XP_OS2
    /* these streams are normally line buffered on OS/2 and need a \n, *
@@ -3861,41 +3858,41 @@ main(int argc, char **argv, char **envp)
         return 1;
     if (!JS_DefineFunctions(cx, it, its_methods))
         return 1;
 
 #ifdef JSDEBUGGER
     /*
     * XXX A command line option to enable debugging (or not) would be good
     */
-    _jsdc = JSD_DebuggerOnForUser(rt, NULL, NULL);
-    if (!_jsdc)
+    jsdc = JSD_DebuggerOnForUser(rt, NULL, NULL);
+    if (!jsdc)
         return 1;
-    JSD_JSContextInUse(_jsdc, cx);
+    JSD_JSContextInUse(jsdc, cx);
 #ifdef JSD_LOWLEVEL_SOURCE
-    JS_SetSourceHandler(rt, SendSourceToJSDebugger, _jsdc);
+    JS_SetSourceHandler(rt, SendSourceToJSDebugger, jsdc);
 #endif /* JSD_LOWLEVEL_SOURCE */
 #ifdef JSDEBUGGER_JAVA_UI
-    _jsdjc = JSDJ_CreateContext();
-    if (! _jsdjc)
+    jsdjc = JSDJ_CreateContext();
+    if (! jsdjc)
         return 1;
-    JSDJ_SetJSDContext(_jsdjc, _jsdc);
-    java_env = JSDJ_CreateJavaVMAndStartDebugger(_jsdjc);
+    JSDJ_SetJSDContext(jsdjc, jsdc);
+    java_env = JSDJ_CreateJavaVMAndStartDebugger(jsdjc);
 #ifdef LIVECONNECT
     if (java_env)
         (*java_env)->GetJavaVM(java_env, &java_vm);
 #endif
     /*
     * XXX This would be the place to wait for the debugger to start.
     * Waiting would be nice in general, but especially when a js file
     * is passed on the cmd line.
     */
 #endif /* JSDEBUGGER_JAVA_UI */
 #ifdef JSDEBUGGER_C_UI
-    jsdbc = JSDB_InitDebugger(rt, _jsdc, 0);
+    jsdbc = JSDB_InitDebugger(rt, jsdc, 0);
 #endif /* JSDEBUGGER_C_UI */
 #endif /* JSDEBUGGER */
 
 #ifdef LIVECONNECT
     if (!JSJ_SimpleInit(cx, glob, java_vm, getenv("CLASSPATH")))
         return 1;
 #endif
 
@@ -3923,22 +3920,22 @@ main(int argc, char **argv, char **envp)
             return 1;
         }
     }
 #endif
 
     result = ProcessArgs(cx, glob, argv, argc);
 
 #ifdef JSDEBUGGER
-    if (_jsdc) {
+    if (jsdc) {
 #ifdef JSDEBUGGER_C_UI
         if (jsdbc)
-            JSDB_TermDebugger(_jsdc);
+            JSDB_TermDebugger(jsdc);
 #endif /* JSDEBUGGER_C_UI */
-        JSD_DebuggerOff(_jsdc);
+        JSD_DebuggerOff(jsdc);
     }
 #endif  /* JSDEBUGGER */
 
 #ifdef JS_THREADSAFE
     JS_EndRequest(cx);
 #endif
 
     JS_DestroyContext(cx);
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -6839,17 +6839,17 @@ interrupt:
         if (tracefp) {
             intN ndefs, n;
             jsval *siter;
 
             /*
              * op may be invalid here when a catch or finally handler jumps to
              * advance_pc.
              */
-            op = pc[-len];
+            op = (JSOp) pc[-len];
             ndefs = js_CodeSpec[op].ndefs;
             if (ndefs) {
                 SAVE_SP_AND_PC(fp);
                 if (op == JSOP_FORELEM && sp[-1] == JSVAL_FALSE)
                     --ndefs;
                 for (n = -ndefs; n < 0; n++) {
                     char *bytes = js_DecompileValueGenerator(cx, n, sp[n],
                                                              NULL);
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -84,28 +84,28 @@ BinToVal(uintN logscale, uintN bin)
 {
     JS_ASSERT(bin <= 10);
     if (bin <= 1 || logscale == 0)
         return bin;
     --bin;
     if (logscale == 2)
         return JS_BIT(bin);
     JS_ASSERT(logscale == 10);
-    return (uint32) pow(10, bin);
+    return (uint32) pow(10, (double) bin);
 }
 
 static uintN
 ValToBin(uintN logscale, uint32 val)
 {
     uintN bin;
 
     if (val <= 1)
         return val;
     bin = (logscale == 10)
-          ? (uintN) ceil(log10(val))
+          ? (uintN) ceil(log10((double) val))
           : (logscale == 2)
           ? (uintN) JS_CeilingLog2(val)
           : val;
     return JS_MIN(bin, 10);
 }
 
 void
 JS_BasicStatsAccum(JSBasicStats *bs, uint32 val)
@@ -193,17 +193,17 @@ JS_DumpHistogram(JSBasicStats *bs, FILE 
         cnt = bs->hist[bin];
         if (prev + 1 >= val)
             fprintf(fp, "        [%6u]", val);
         else
             fprintf(fp, "[%6u, %6u]", prev + 1, val);
         fprintf(fp, "%s %8u ", (bin == 10) ? "+" : ":", cnt);
         if (cnt != 0) {
             if (max > 1e6 && mean > 1e3)
-                cnt = (uint32) ceil(log10(cnt));
+                cnt = (uint32) ceil(log10((double) cnt));
             else if (max > 16 && mean > 8)
                 cnt = JS_CeilingLog2(cnt);
             for (i = 0; i < cnt; i++)
                 putc('*', fp);
         }
         putc('\n', fp);
     }
 }
--- a/js/src/xpconnect/src/xpc.msg
+++ b/js/src/xpconnect/src/xpc.msg
@@ -164,8 +164,54 @@ XPC_MSG_DEF(NS_SUCCESS_LOSS_OF_INSIGNIFI
 
 #ifdef XPC_IDISPATCH_SUPPORT
 XPC_MSG_DEF(NS_ERROR_XPC_COM_UNKNOWN                , "Unknown COM error occured")
 XPC_MSG_DEF(NS_ERROR_XPC_COM_ERROR                  , "COM Error")
 XPC_MSG_DEF(NS_ERROR_XPC_COM_INVALID_CLASS_ID       , "Invalid class ID")
 XPC_MSG_DEF(NS_ERROR_XPC_COM_CREATE_FAILED          , "Unable to create an instance of the desired COM class")
 XPC_MSG_DEF(NS_ERROR_XPC_IDISPATCH_NOT_ENABLED      , "IDispatch support is not enabled")
 #endif
+
+/* network related codes (from nsNetError.h) */
+
+XPC_MSG_DEF(NS_BINDING_FAILED                       , "The async request failed for some unknown reason")
+XPC_MSG_DEF(NS_BINDING_ABORTED                      , "The async request failed because it was aborted by some user action")
+XPC_MSG_DEF(NS_BINDING_REDIRECTED                   , "The async request has been redirected to a different async request")
+XPC_MSG_DEF(NS_BINDING_RETARGETED                   , "The async request has been retargeted to a different handler")
+XPC_MSG_DEF(NS_ERROR_MALFORMED_URI                  , "The URI is malformed")
+XPC_MSG_DEF(NS_ERROR_UNKNOWN_PROTOCOL               , "The URI scheme corresponds to an unknown protocol handler")
+XPC_MSG_DEF(NS_ERROR_NO_CONTENT                     , "Channel opened successfully but no data will be returned")
+XPC_MSG_DEF(NS_ERROR_IN_PROGRESS                    , "The requested action could not be completed while the object is busy")
+XPC_MSG_DEF(NS_ERROR_ALREADY_OPENED                 , "Channel is already open")
+XPC_MSG_DEF(NS_ERROR_INVALID_CONTENT_ENCODING       , "The content encoding of the source document is incorrect")
+XPC_MSG_DEF(NS_ERROR_ALREADY_CONNECTED              , "The connection is already established")
+XPC_MSG_DEF(NS_ERROR_NOT_CONNECTED                  , "The connection does not exist")
+XPC_MSG_DEF(NS_ERROR_CONNECTION_REFUSED             , "The connection was refused")
+XPC_MSG_DEF(NS_ERROR_PROXY_CONNECTION_REFUSED       , "The connection to the proxy server was refused")
+XPC_MSG_DEF(NS_ERROR_NET_TIMEOUT                    , "The connection has timed out")
+XPC_MSG_DEF(NS_ERROR_OFFLINE                        , "The requested action could not be completed in the offline state")
+XPC_MSG_DEF(NS_ERROR_PORT_ACCESS_NOT_ALLOWED        , "Establishing a connection to an unsafe or otherwise banned port was prohibited")
+XPC_MSG_DEF(NS_ERROR_NET_RESET                      , "The connection was established, but no data was ever received")
+XPC_MSG_DEF(NS_ERROR_NET_INTERRUPT                  , "The connection was established, but the data transfer was interrupted")
+XPC_MSG_DEF(NS_ERROR_NOT_RESUMABLE                  , "This request is not resumable, but it was tried to resume it, or to request resume-specific data")
+XPC_MSG_DEF(NS_ERROR_ENTITY_CHANGED                 , "It was attempted to resume the request, but the entity has changed in the meantime")
+XPC_MSG_DEF(NS_ERROR_REDIRECT_LOOP                  , "The request failed as a result of a detected redirection loop")
+XPC_MSG_DEF(NS_ERROR_UNSAFE_CONTENT_TYPE            , "The request failed because the content type returned by the server was not a type expected by the channel")
+XPC_MSG_DEF(NS_ERROR_FTP_LOGIN                      , "FTP error while logging in")
+XPC_MSG_DEF(NS_ERROR_FTP_CWD                        , "FTP error while changing directory")
+XPC_MSG_DEF(NS_ERROR_FTP_PASV                       , "FTP error while changing to passive mode")
+XPC_MSG_DEF(NS_ERROR_FTP_PWD                        , "FTP error while retrieving current directory")
+XPC_MSG_DEF(NS_ERROR_FTP_LIST                       , "FTP error while retrieving a directory listing")
+XPC_MSG_DEF(NS_ERROR_UNKNOWN_HOST                   , "The lookup of the hostname failed")
+XPC_MSG_DEF(NS_ERROR_UNKNOWN_PROXY_HOST             , "The lookup of the proxy hostname failed")
+XPC_MSG_DEF(NS_ERROR_UNKNOWN_SOCKET_TYPE            , "The specified socket type does not exist")
+XPC_MSG_DEF(NS_ERROR_SOCKET_CREATE_FAILED           , "The specified socket type could not be created")
+XPC_MSG_DEF(NS_ERROR_CACHE_KEY_NOT_FOUND            , "Cache key could not be found")
+XPC_MSG_DEF(NS_ERROR_CACHE_DATA_IS_STREAM           , "Cache data is a stream")
+XPC_MSG_DEF(NS_ERROR_CACHE_DATA_IS_NOT_STREAM       , "Cache data is not a stream")
+XPC_MSG_DEF(NS_ERROR_CACHE_WAIT_FOR_VALIDATION      , "Cache entry exists but needs to be validated first")
+XPC_MSG_DEF(NS_ERROR_CACHE_ENTRY_DOOMED             , "Cache entry has been  doomed")
+XPC_MSG_DEF(NS_ERROR_CACHE_READ_ACCESS_DENIED       , "Read access to cache denied")
+XPC_MSG_DEF(NS_ERROR_CACHE_WRITE_ACCESS_DENIED      , "Write access to cache denied")
+XPC_MSG_DEF(NS_ERROR_CACHE_IN_USE                   , "Cache is currently in use")
+XPC_MSG_DEF(NS_ERROR_DOCUMENT_NOT_CACHED            , "Document does not exist in cache")
+XPC_MSG_DEF(NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS     , "The requested number of domain levels exceeds those present in the host string")
+XPC_MSG_DEF(NS_ERROR_HOST_IS_IP_ADDRESS             , "The host string is an IP address")
--- a/js/src/xpconnect/src/xpcexception.cpp
+++ b/js/src/xpconnect/src/xpcexception.cpp
@@ -37,16 +37,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* An implementaion of nsIException. */
 
 #include "xpcprivate.h"
+#include "nsNetError.h"
 
 /***************************************************************************/
 /* Quick and dirty mapping of well known result codes to strings. We only
 *  call this when building an exception object, so iterating the short array
 *  is not too bad.
 *
 *  It sure would be nice to have exceptions declared in idl and available
 *  in some more global way at runtime.
--- a/js/tests/js1_5/extensions/regress-420612.js
+++ b/js/tests/js1_5/extensions/regress-420612.js
@@ -39,11 +39,23 @@ var gTestfile = 'regress-420612.js';
 //-----------------------------------------------------------------------------
 var BUGNUMBER = 420612;
 var summary = 'Do not assert: obj == pobj';
 var actual = 'No Crash';
 var expect = 'No Crash';
 
 printBugNumber(BUGNUMBER);
 printStatus (summary);
-this.__proto__ = []; 
-this.unwatch("x");
+try
+{
+  this.__proto__ = []; 
+  this.unwatch("x");
+}
+catch(ex)
+{
+  print(ex + '');
+  if (typeof window != 'undefined')
+  {
+    expect = 'Error: invalid __proto__ value (can only be set to null)';
+  }
+  actual = ex + '';
+}
 reportCompare(expect, actual, summary);
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -356,16 +356,18 @@ public:
   
 #ifdef XP_WIN
   void Paint(const nsRect& aDirtyRect, HDC ndc);
 #elif defined(XP_MACOSX)
   void Paint(const nsRect& aDirtyRect);  
 #elif defined(MOZ_X11)
   void Paint(nsIRenderingContext& aRenderingContext,
              const nsRect& aDirtyRect);
+#elif defined(XP_OS2)
+  void Paint(const nsRect& aDirtyRect, HPS aHPS);
 #endif
 
   // nsITimerCallback interface
   NS_DECL_NSITIMERCALLBACK
   
   void CancelTimer();
   void StartTimer(unsigned int aDelay);
 
@@ -440,17 +442,17 @@ private:
     nsPluginWindow* mWindow;
     nsIPluginInstance* mInstance;
     const nsIntRect& mDirtyRect;
   };
 #endif
 
 };
 
-#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(MOZ_X11)
+#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(MOZ_X11) || defined(XP_OS2)
 static void ConvertAppUnitsToPixels(const nsPresContext& aPresContext, const nsRect& aTwipsRect, nsIntRect& aPixelRect);
 #endif
 
   // Mac specific code to fix up port position and clip during paint
 #ifdef XP_MACOSX
 
 #ifdef DO_DIRTY_INTERSECT
   // convert relative coordinates to absolute
@@ -1178,16 +1180,25 @@ nsObjectFrame::PrintPlugin(nsIRenderingC
   /* Send data to printer */
   rv = aRenderingContext.RenderEPS(aDirtyRect, plugintmpfile);
 
   fclose(plugintmpfile);
 
   PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("plugin printing done, return code is %lx\n", (long)rv));
 #endif
 
+#elif defined(XP_OS2)
+  void *hps = aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_OS2_PS);
+  if (!hps)
+    return;
+
+  npprint.print.embedPrint.platformPrint = hps;
+  npprint.print.embedPrint.window = window;
+  // send off print info to plugin
+  rv = pi->Print(&npprint);
 #elif defined(XP_WIN)
 
   /* On Windows, we use the win32 printing surface to print.  This, in
    * turn, uses the Cairo paginated surface, which in turn uses the
    * meta surface to record all operations and then play them back.
    * This doesn't work too well for plugins, because if plugins render
    * directly into the DC, the meta surface won't have any knowledge
    * of them, and so at the end when it actually does the replay step,
@@ -1337,19 +1348,17 @@ nsObjectFrame::PaintPlugin(nsIRenderingC
   if (mInstanceOwner)
     {
       nsPluginWindow * window;
       mInstanceOwner->GetWindow(window);
 
       if (window->type == nsPluginWindowType_Drawable)
         mInstanceOwner->Paint(aRenderingContext, aDirtyRect);
     }
-#elif defined (XP_WIN) // || defined(XP_OS2)
-  // XXX for OS/2 we need to overhaul this for Cairo builds
-  //     for now just ignore plugin stuff
+#elif defined (XP_WIN) || defined(XP_OS2)
   nsCOMPtr<nsIPluginInstance> inst;
   GetPluginInstance(*getter_AddRefs(inst));
   if (inst) {
     // Look if it's windowless
     nsPluginWindow * window;
     mInstanceOwner->GetWindow(window);
 
     if (window->type == nsPluginWindowType_Drawable) {
@@ -1390,29 +1399,49 @@ nsObjectFrame::PaintPlugin(nsIRenderingC
       gfxFloat xoff, yoff;
       nsRefPtr<gfxASurface> surf = ctx->CurrentSurface(&xoff, &yoff);
 
       if (surf->CairoStatus() != 0) {
         NS_WARNING("Plugin is being asked to render to a surface that's in error!");
         return;
       }
 
+#ifdef XP_WIN
       // check if we need to update hdc
       HDC hdc = (HDC)aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
 
       if (reinterpret_cast<HDC>(window->window) != hdc) {
         window->window = reinterpret_cast<nsPluginPort*>(hdc);
         doupdatewindow = PR_TRUE;
       }
 
       SaveDC(hdc);
 
       POINT origViewportOrigin;
       GetViewportOrgEx(hdc, &origViewportOrigin);
       SetViewportOrgEx(hdc, origViewportOrigin.x + (int) xoff, origViewportOrigin.y + (int) yoff, NULL);
+#else // do something similar on OS/2
+      // check if we need to update the PS
+      HPS hps = (HPS)aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_OS2_PS);
+      if (reinterpret_cast<HPS>(window->window) != hps) {
+        window->window = reinterpret_cast<nsPluginPort*>(hps);
+        doupdatewindow = PR_TRUE;
+      }
+      LONG lPSid = GpiSavePS(hps);
+      RECTL rclViewport;
+      if (GpiQueryDevice(hps) != NULLHANDLE) { // ensure that we have an associated HDC
+        if (GpiQueryPageViewport(hps, &rclViewport)) {
+          rclViewport.xLeft += (LONG)xoff;
+          rclViewport.xRight += (LONG)xoff;
+          rclViewport.yBottom += (LONG)yoff;
+          rclViewport.yTop += (LONG)yoff;
+          GpiSetPageViewport(hps, &rclViewport);
+        }
+      }
+#endif
 
       if ((window->x != origin.x) || (window->y != origin.y)) {
         window->x = origin.x;
         window->y = origin.y;
         doupdatewindow = PR_TRUE;
       }
 
       // if our location or visible area has changed, we need to tell the plugin
@@ -1455,23 +1484,30 @@ nsObjectFrame::PaintPlugin(nsIRenderingC
 
                 inst->HandleEvent(&pluginEvent, &eventHandled);
               }
 #endif
 
         inst->SetWindow(window);        
       }
 
+#ifdef XP_WIN
       // FIXME - Bug 385435:
       // This expects a dirty rect relative to the plugin's rect
       // XXX I wonder if this breaks if we give the frame a border so the
       // frame origin and plugin origin are not the same
       mInstanceOwner->Paint(aDirtyRect, hdc);
 
       RestoreDC(hdc, -1);
+#else // do something similar on OS/2
+      mInstanceOwner->Paint(aDirtyRect, hps);
+      if (lPSid >= 1) {
+        GpiRestorePS(hps, lPSid);
+      }
+#endif
       surf->MarkDirty();
     }
   }
 #endif
 }
 
 NS_IMETHODIMP
 nsObjectFrame::HandleEvent(nsPresContext* aPresContext,
@@ -3821,16 +3857,46 @@ void nsPluginInstanceOwner::Paint(const 
   pluginEvent.event = WM_PAINT;
   pluginEvent.wParam = (uint32)ndc;
   pluginEvent.lParam = (uint32)&drc;
   PRBool eventHandled = PR_FALSE;
   mInstance->HandleEvent(&pluginEvent, &eventHandled);
 }
 #endif
 
+#ifdef XP_OS2
+void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, HPS aHPS)
+{
+  if (!mInstance || !mOwner)
+    return;
+
+  nsPluginWindow * window;
+  GetWindow(window);
+  nsRect relDirtyRect = nsRect(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
+  nsIntRect relDirtyRectInPixels;
+  ConvertAppUnitsToPixels(*mOwner->PresContext(), relDirtyRect,
+                          relDirtyRectInPixels);
+
+  // we got dirty rectangle in relative window coordinates, but we
+  // need it in absolute units and in the (left, top, right, bottom) form
+  RECTL rectl;
+  rectl.xLeft   = relDirtyRectInPixels.x + window->x;
+  rectl.yBottom = relDirtyRectInPixels.y + window->y;
+  rectl.xRight  = rectl.xLeft + relDirtyRectInPixels.width;
+  rectl.yTop    = rectl.yBottom + relDirtyRectInPixels.height;
+
+  nsPluginEvent pluginEvent;
+  pluginEvent.event = WM_PAINT;
+  pluginEvent.wParam = (uint32)aHPS;
+  pluginEvent.lParam = (uint32)&rectl;
+  PRBool eventHandled = PR_FALSE;
+  mInstance->HandleEvent(&pluginEvent, &eventHandled);
+}
+#endif
+
 #ifdef MOZ_X11
 void nsPluginInstanceOwner::Paint(nsIRenderingContext& aRenderingContext,
                                   const nsRect& aDirtyRect)
 {
   if (!mInstance || !mOwner)
     return;
  
   nsPluginWindow* window;
@@ -4179,17 +4245,17 @@ NS_IMETHODIMP nsPluginInstanceOwner::Cre
   return rv;
 }
 
 void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost* aHost)
 {
   mPluginHost = aHost;
 }
 
-#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(MOZ_X11)
+#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(MOZ_X11) || defined(XP_OS2)
 // convert frame coordinates from twips to pixels
 static void ConvertAppUnitsToPixels(const nsPresContext& aPresContext, const nsRect& aTwipsRect, nsIntRect& aPixelRect)
 {
   aPixelRect.x = aPresContext.AppUnitsToDevPixels(aTwipsRect.x);
   aPixelRect.y = aPresContext.AppUnitsToDevPixels(aTwipsRect.y);
   aPixelRect.width = aPresContext.AppUnitsToDevPixels(aTwipsRect.width);
   aPixelRect.height = aPresContext.AppUnitsToDevPixels(aTwipsRect.height);
 }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/407243-1-ref.html
@@ -0,0 +1,67 @@
+<html>
+<head><style>
+  tr        { height: 1em;  }
+  td.wide   { width: 500px; }
+
+  td.orange { background: orange;    }
+  td.purple { background: purple;    }
+  td.teal   { background: teal;      }
+  td.blue   { background: lightblue; }
+</style></head>
+<body>
+  <p>(x,x) labels indicate the column & row order of the orange cell.</p>
+
+  <br/>(0,0)
+  <table cellpadding="0" cellspacing="0">
+    <tr>
+      <td class="orange wide"></td>
+      <td class="orange"></td>
+      <td class="purple"></td>
+    </td>
+    </tr><tr>
+      <td class="teal">x</td>
+      <td class="blue" colspan="2">y z</td>
+    </tr>
+  </table>
+
+  <br/>(0,1)
+  <table cellpadding="0" cellspacing="0">
+    <tr>
+      <td class="teal">x</td>
+      <td class="blue" colspan="2">y z</td>
+    </td>
+    </tr><tr>
+      <td class="orange wide"></td>
+      <td class="orange"></td>
+
+      <td class="purple"></td>
+    </tr>
+  </table>
+
+  <br/>(1,0)
+  <table cellpadding="0" cellspacing="0">
+    <tr>
+      <td class="purple"></td>
+      <td class="orange"></td>
+      <td class="orange wide"></td>
+    </td>
+    </tr><tr>
+      <td class="blue" colspan="2">y z</td>
+      <td class="teal">x</td>
+    </tr>
+  </table>
+
+  <br/>(1,1)
+  <table cellpadding="0" cellspacing="0">
+    <tr>
+      <td class="blue" colspan="2">y z</td>
+      <td class="teal">x</td>
+    </td>
+    </tr><tr>
+      <td class="purple"></td>
+      <td class="orange"></td>
+      <td class="orange wide"></td>
+    </tr>
+  </table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/407243-1.html
@@ -0,0 +1,73 @@
+<html>
+<!-- This testcase asserts that in all the tables below, all 500px of the  --
+  -- orange colspanning cell's specified width should go to its first      --
+  -- spanned column.  Its second spanned column receives none of the       --
+  -- 500px, and it only gets a small amount of width by taking half of the --
+  -- light-blue cell's preferred width.                                    --
+  --                                                                       --
+  -- This happens because the first column starts with nonzero pref-width, --
+  -- whereas the second and third columns have zero pref-width.  Hence,    --
+  -- the orange colspanning cell favors the first column over the second,  --
+  -- whereas the lightblue colspanning cell distributes its width equally  --
+  -- between the second and third columns.                                 -->
+<head><style>
+  tr        { height: 1em;  }
+  td.wide   { width: 500px; }
+
+  td.orange { background: orange;    }
+  td.purple { background: purple;    }
+  td.teal   { background: teal;      }
+  td.blue   { background: lightblue; }
+</style></head>
+<body>
+  <p>(x,x) labels indicate the column & row order of the orange cell.</p>
+
+  <br/>(0,0)
+  <table cellpadding="0" cellspacing="0">
+    <tr>
+      <td class="orange wide" colspan="2"></td>
+      <td class="purple"></td>
+    </td>
+    </tr><tr>
+      <td class="teal">x</td>
+      <td class="blue" colspan="2">y z</td>
+    </tr>
+  </table>
+
+  <br/>(0,1)
+  <table cellpadding="0" cellspacing="0">
+    <tr>
+      <td class="teal">x</td>
+      <td class="blue" colspan="2">y z</td>
+    </td>
+    </tr><tr>
+      <td class="orange wide" colspan="2"></td>
+      <td class="purple"></td>
+    </tr>
+  </table>
+
+  <br/>(1,0)
+  <table cellpadding="0" cellspacing="0">
+    <tr>
+      <td class="purple"></td>
+      <td class="orange wide" colspan="2"></td>
+    </td>
+    </tr><tr>
+      <td class="blue" colspan="2">y z</td>
+      <td class="teal">x</td>
+    </tr>
+  </table>
+
+  <br/>(1,1)
+  <table cellpadding="0" cellspacing="0">
+    <tr>
+      <td class="blue" colspan="2">y z</td>
+      <td class="teal">x</td>
+    </td>
+    </tr><tr>
+      <td class="purple"></td>
+      <td class="orange wide" colspan="2"></td>
+    </tr>
+  </table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/413027-1-ref.html
@@ -0,0 +1,10 @@
+<html><head>
+<title>Testcase 3 for bug 413027 - Marquee height is sized too small, clipping text vertically</title>
+</head>
+<body>
+
+<div style="background-color: lime; width: 600px; float:left;">
+  <div style="margin: 100px 0px;">text</div>
+</div>
+      
+</body></html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/413027-1.html
@@ -0,0 +1,12 @@
+<html><head>
+<title>Testcase 3 for bug 413027 - Marquee height is sized too small, clipping text vertically</title>
+</head>
+<body>
+
+<div style="display: -moz-box; background-color: lime; width: 600px;">
+<div>
+  <div style="margin: 100px 0px;">text</div>
+</div>
+</div>
+      
+</body></html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/420351-1-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<title>Testcase bug - List item marker takes up room now with list-style-type: none in strict mode</title>
+<style>
+div.li {
+  border: 1px solid red;
+}
+div.inside {
+  border: 1px solid black;
+}
+</style></head>
+<body>
+
+<ul><div class="li"><div class="inside">text</div></div></ul>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/420351-1.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<title>Testcase bug - List item marker takes up room now with list-style-type: none in strict mode</title>
+<style>
+li{
+  list-style-type: none;
+  list-style-position: inside;
+  border: 1px solid red;
+}
+div {
+  border: 1px solid black;
+}
+</style></head>
+<body>
+
+<ul><li><div>text</div></li></ul>
+</body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -693,16 +693,17 @@ random == 403134-1.html 403134-1-ref.htm
 == 406568-1.html 406568-1-ref.html
 == 407016-1-a.html 407016-1-ref.html
 == 407016-1-b.html 407016-1-ref.html
 == 407016-2.html 407016-2-ref.html
 == 407078-1.html 407078-1-ref.html
 == 407095-1.html 407095-1-ref.html
 == 407111-1.html 407111-1-ref.html
 == 407227-1.html 407227-1-ref.html
+== 407243-1.html 407243-1-ref.html
 == 407937-1.html 407937-1-ref.html
 == 408493-1.html about:blank
 == 408493-2.html 408493-2-ref.html
 == 408656-1a.html 408656-1-ref.html 
 == 408656-1b.html 408656-1-ref.html
 == 408656-1c.html 408656-1-ref.html
 == 408782-1a.html 408782-1-ref.html
 == 408782-1b.html 408782-1-ref.html
@@ -714,16 +715,17 @@ random == 403134-1.html 403134-1-ref.htm
 == 409659-1d.html 409659-1-ref.html
 == 411334-1.xml 411334-1-ref.xml
 == 411792-1.html 411792-1-ref.html
 == 412093-1.html 412093-1-ref.html
 == 412607-1a.html 412607-1-ref.html
 == 412607-1b.html 412607-1-ref.html
 == 412679-1.html 412679-1-ref.html
 == 412679-2.html 412679-2-ref.html
+# == 413027-1.html 413027-1-ref.html
 == 413286-1a.html 413286-1-ref.html
 == 413286-1b.html 413286-1-ref.html
 == 413286-1c.html 413286-1-ref.html
 == 413286-2a.html 413286-2-ref.html
 == 413286-2b.html 413286-2-ref.html
 == 413286-2c.html 413286-2-ref.html
 == 413286-3.html 413286-3-ref.html 
 == 413286-4a.html 413286-4-ref.html 
@@ -745,8 +747,10 @@ random == 403134-1.html 403134-1-ref.htm
 == 417246-1.html 417246-1-ref.html
 == 417676.html 417676-ref.html
 == 418766-1a.html 418766-1-ref.html
 == 418766-1b.html 418766-1-ref.html
 == 419060.html 419060-ref.html
 == 419531-1.html 419531-1-ref.html
 == 420069-1.html 420069-1-ref.html
 == 420069-2.html 420069-2-ref.html
+# == 420351-1.html 420351-1-ref.html
+
--- a/netwerk/base/public/nsIAuthPrompt.idl
+++ b/netwerk/base/public/nsIAuthPrompt.idl
@@ -37,17 +37,17 @@
 
 #include "nsISupports.idl"
 
 interface nsIPrompt;
 
 /**
  * @status UNDER_REVIEW
  */
-[scriptable, uuid(310fae75-191c-412d-be7f-6190df509e3c)]
+[scriptable, uuid(358089f9-ee4b-4711-82fd-bcd07fc62061)]
 interface nsIAuthPrompt : nsISupports
 {         
     const PRUint32 SAVE_PASSWORD_NEVER             = 0;
     const PRUint32 SAVE_PASSWORD_FOR_SESSION       = 1;
     const PRUint32 SAVE_PASSWORD_PERMANENTLY       = 2;
 
     /**
      * Puts up a text input dialog with OK and Cancel buttons.
@@ -82,25 +82,29 @@ interface nsIAuthPrompt : nsISupports
      * @param  pwd           The password entered by the user if OK was
      *                       selected.
      * @return true for OK, false for Cancel
      */
     boolean promptUsernameAndPassword(in wstring dialogTitle,
                                       in wstring text,
                                       in wstring passwordRealm,
                                       in PRUint32 savePassword,
-                                      out wstring user, 
+                                      inout wstring user, 
                                       inout wstring pwd);
 
     /**
      * Puts up a password dialog with OK and Cancel buttons.
      * @param  dialogText    The title for the dialog.
      * @param  text          The text to display in the dialog.
      * @param  passwordRealm The "realm" the password belongs to: e.g.
-     *                       ldap://localhost/dc=test
+     *                       ldap://localhost/dc=test. If a username is
+     *                       specified (http://user@site.com) it will be used
+     *                       when matching existing logins or saving new ones.
+     *                       If no username is specified, only password-only
+     *                       logins will be matched or saved.
      * @param  savePassword  One of the SAVE_PASSWORD_* options above.
      * @param  pwd           The password entered by the user if OK was
      *                       selected.
      * @return true for OK, false for Cancel
      */
     boolean promptPassword(in wstring dialogTitle,
                            in wstring text,
                            in wstring passwordRealm,
--- a/netwerk/base/src/nsProxyAutoConfig.js
+++ b/netwerk/base/src/nsProxyAutoConfig.js
@@ -238,25 +238,24 @@ var pacUtils =
 "function shExpMatch(url, pattern) {\n" +
 "   pattern = pattern.replace(/\\./g, '\\\\.');\n" +
 "   pattern = pattern.replace(/\\*/g, '.*');\n" +
 "   pattern = pattern.replace(/\\?/g, '.');\n" +
 "   var newRe = new RegExp('^'+pattern+'$');\n" +
 "   return newRe.test(url);\n" +
 "}\n" +
 
-"var wdays = new Array('SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT');\n" +
+"var wdays = {SUN: 0, MON: 1, TUE: 2, WED: 3, THU: 4, FRI: 5, SAT: 6};\n" +
 
-"var monthes = new Array('JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC');\n"+
+"var months = {JAN: 0, FEB: 1, MAR: 2, APR: 3, MAY: 4, JUN: 5, JUL: 6, AUG: 7, SEP: 8, OCT: 9, NOV: 10, DEC: 11};\n"+
 
 "function weekdayRange() {\n" +
 "    function getDay(weekday) {\n" +
-"        for (var i = 0; i < 6; i++) {\n" +
-"            if (weekday == wdays[i]) \n" +
-"                return i;\n" +
+"        if (weekday in wdays) {\n" +
+"            return wdays[weekday];\n" +
 "        }\n" +
 "        return -1;\n" +
 "    }\n" +
 "    var date = new Date();\n" +
 "    var argc = arguments.length;\n" +
 "    var wday;\n" +
 "    if (argc < 1)\n" +
 "        return false;\n" +
@@ -269,19 +268,18 @@ var pacUtils =
 "    var wd1 = getDay(arguments[0]);\n" +
 "    var wd2 = (argc == 2) ? getDay(arguments[1]) : wd1;\n" +
 "    return (wd1 == -1 || wd2 == -1) ? false\n" +
 "                                    : (wd1 <= wday && wday <= wd2);\n" +
 "}\n" +
 
 "function dateRange() {\n" +
 "    function getMonth(name) {\n" +
-"        for (var i = 0; i < 6; i++) {\n" +
-"            if (name == monthes[i])\n" +
-"                return i;\n" +
+"        if (name in months) {\n" +
+"            return months[name];\n" +
 "        }\n" +
 "        return -1;\n" +
 "    }\n" +
 "    var date = new Date();\n" +
 "    var argc = arguments.length;\n" +
 "    if (argc < 1) {\n" +
 "        return false;\n" +
 "    }\n" +
--- a/netwerk/cache/src/nsCacheEntry.cpp
+++ b/netwerk/cache/src/nsCacheEntry.cpp
@@ -483,35 +483,24 @@ nsCacheEntryHashTable::RemoveEntry( nsCa
     nsCacheEntry *check = GetEntry(cacheEntry->mKey);
     NS_ASSERTION(check == cacheEntry, "### Attempting to remove unknown cache entry!!!");
 #endif
     (void) PL_DHashTableOperate(&table, cacheEntry->mKey, PL_DHASH_REMOVE);
 }
 
 
 void
-nsCacheEntryHashTable::VisitEntries( nsCacheEntryHashTable::Visitor *visitor)
+nsCacheEntryHashTable::VisitEntries( PLDHashEnumerator etor, void *arg)
 {
     NS_ASSERTION(initialized, "nsCacheEntryHashTable not initialized");
     if (!initialized)  return; // NS_ERROR_NOT_INITIALIZED
-    PL_DHashTableEnumerate(&table, VisitEntry, visitor);
+    PL_DHashTableEnumerate(&table, etor, arg);
 }
 
 
-PLDHashOperator PR_CALLBACK
-nsCacheEntryHashTable::VisitEntry(PLDHashTable *table,
-                                  PLDHashEntryHdr *hashEntry,
-                                  PRUint32 number,
-                                  void *arg)
-{
-    nsCacheEntry *cacheEntry = ((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry;
-    nsCacheEntryHashTable::Visitor *visitor = (nsCacheEntryHashTable::Visitor*) arg;
-    return (visitor->VisitEntry(cacheEntry) ? PL_DHASH_NEXT : PL_DHASH_STOP);
-}
-
 /**
  *  hash table operation callback functions
  */
 
 PLDHashNumber PR_CALLBACK
 nsCacheEntryHashTable::HashKey( PLDHashTable *table, const void *key)
 {
     return PL_DHashStringKey(table,((nsCString *)key)->get());
--- a/netwerk/cache/src/nsCacheEntry.h
+++ b/netwerk/cache/src/nsCacheEntry.h
@@ -290,27 +290,19 @@ public:
 
     nsresult      Init();
     void          Shutdown();
 
     nsCacheEntry *GetEntry( const nsCString * key);
     nsresult      AddEntry( nsCacheEntry *entry);
     void          RemoveEntry( nsCacheEntry *entry);
     
-    // XXX enumerate entries?
-    class Visitor {
-    public:
-        virtual PRBool VisitEntry( nsCacheEntry *entry) = 0;
-    };
-    
-    void          VisitEntries( Visitor *visitor);
-    
+    void          VisitEntries( PLDHashEnumerator etor, void *arg);
+
 private:
-    friend class nsCacheService; // XXX redefine interface so this isn't necessary
-
     // PLDHashTable operation callbacks
     static PLDHashNumber  PR_CALLBACK HashKey( PLDHashTable *table, const void *key);
 
     static PRBool         PR_CALLBACK MatchEntry( PLDHashTable *           table,
                                                   const PLDHashEntryHdr *  entry,
                                                   const void *             key);
 
     static void           PR_CALLBACK MoveEntry( PLDHashTable *table,
--- a/netwerk/cache/src/nsCacheService.cpp
+++ b/netwerk/cache/src/nsCacheService.cpp
@@ -2134,18 +2134,17 @@ nsCacheService::ClearDoomList()
          entry = next;
     }        
 }
 
 
 void
 nsCacheService::ClearActiveEntries()
 {
-    // XXX really we want a different finalize callback for mActiveEntries
-    PL_DHashTableEnumerate(&mActiveEntries.table, DeactivateAndClearEntry, nsnull);
+    mActiveEntries.VisitEntries(DeactivateAndClearEntry, nsnull);
     mActiveEntries.Shutdown();
 }
 
 
 PLDHashOperator PR_CALLBACK
 nsCacheService::DeactivateAndClearEntry(PLDHashTable *    table,
                                         PLDHashEntryHdr * hdr,
                                         PRUint32          number,
@@ -2163,17 +2162,17 @@ nsCacheService::DeactivateAndClearEntry(
 }
 
 
 void
 nsCacheService::DoomActiveEntries()
 {
     nsAutoVoidArray array;
 
-    PL_DHashTableEnumerate(&mActiveEntries.table, RemoveActiveEntry, &array);
+    mActiveEntries.VisitEntries(RemoveActiveEntry, &array);
 
     PRUint32 count = array.Count();
     for (PRUint32 i=0; i < count; ++i)
         DoomEntry_Internal((nsCacheEntry *) array[i]);
 }
 
 
 PLDHashOperator PR_CALLBACK
--- a/netwerk/cache/src/nsMemoryCacheDevice.cpp
+++ b/netwerk/cache/src/nsMemoryCacheDevice.cpp
@@ -467,50 +467,42 @@ nsMemoryCacheDevice::SetCapacity(PRInt32
 {
     PRInt32 hardLimit = capacity * 1024;  // convert k into bytes
     PRInt32 softLimit = (hardLimit * 9) / 10;
     AdjustMemoryLimits(softLimit, hardLimit);
 }
 
 
 #ifdef DEBUG
-class nsCacheHashCounter : public nsCacheEntryHashTable::Visitor {
-public:
-    nsCacheHashCounter() : entryCount(0) {}
-
-    PRBool  VisitEntry(nsCacheEntry * entry);
-    PRInt32 entryCount;
-};
-
-
-PRBool nsCacheHashCounter::VisitEntry(nsCacheEntry * entry)
+static PLDHashOperator PR_CALLBACK
+CountEntry(PLDHashTable * table, PLDHashEntryHdr * hdr, PRUint32 number, void * arg)
 {
-    ++entryCount;
-    return PR_TRUE;
+    PRInt32 *entryCount = (PRInt32 *)arg;
+    ++(*entryCount);
+    return PL_DHASH_NEXT;
 }
 
-
 void
 nsMemoryCacheDevice::CheckEntryCount()
 {
     if (!mInitialized)  return;
 
     PRInt32 evictionListCount = 0;
     for (int i=0; i<kQueueCount; ++i) {
         PRCList * elem = PR_LIST_HEAD(&mEvictionList[i]);
         while (elem != &mEvictionList[i]) {
             elem = PR_NEXT_LINK(elem);
             ++evictionListCount;
         }
     }
     NS_ASSERTION(mEntryCount == evictionListCount, "### mem cache badness");
 
-    nsCacheHashCounter hash;
-    mMemCacheEntries.VisitEntries(&hash);
-    NS_ASSERTION(mEntryCount == hash.entryCount, "### mem cache badness");    
+    PRInt32 entryCount = 0;
+    mMemCacheEntries.VisitEntries(CountEntry, &entryCount);
+    NS_ASSERTION(mEntryCount == entryCount, "### mem cache badness");    
 }
 #endif
 
 /******************************************************************************
  * nsMemoryCacheDeviceInfo - for implementing about:cache
  *****************************************************************************/
 
 
--- a/testing/extensions/community/chrome/content/tabs/bugzilla.xul
+++ b/testing/extensions/community/chrome/content/tabs/bugzilla.xul
@@ -39,20 +39,16 @@
 <!ENTITY % qaDTD SYSTEM "chrome://qa/locale/qa.dtd"> %qaDTD;
 ]>
 
 <overlay id="qa-bz-overlay"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   xmlns:html="http://www.w3.org/1999/xhtml">
 <tabpanel id="qa-tab-bugzilla">
 <vbox flex="1">
-  <label href="http://bugzilla.mozilla.org"
-         value="Help us by filing and confirming bugs in Bugzilla"
-         class="text-link" />
-
   <groupbox>
     <caption label="Bug Search" />
     <radiogroup id = "qa-bugzilla-input-radiogroup"
                   onselect="bugzilla.disableOther()">
       <hbox>
         <radio class="bug-search" selected="true" id="qa-bugzilla-radio-id"
                label="Bug Id:" />
         <textbox id="qa-bugzilla-input-id" width="75px" />
--- a/testing/extensions/community/chrome/content/tabs/help.xul
+++ b/testing/extensions/community/chrome/content/tabs/help.xul
@@ -42,17 +42,16 @@
 <overlay id="qa-help-overlay"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   xmlns:html="http://www.w3.org/1999/xhtml">
 
 <script type="application/x-javascript" src="chrome://qa/content/tabs/qa.js" />
 <tabpanel id="qa-tab-help">
 <vbox flex="1">
   <groupbox>
-    <caption label="Mozilla QA Help" />
-    <div xmlns="http://www.w3.org/1999/xhtml" id="qa-help-info" flex="1">
-    </div>
+    <caption label="&qa.help.helptitle;" />
+    <description>&qa.help.intro;</description>
   </groupbox>
   
 </vbox>
 </tabpanel>
 
 </overlay>
--- a/testing/extensions/community/chrome/locale/en-US/qa.dtd
+++ b/testing/extensions/community/chrome/locale/en-US/qa.dtd
@@ -178,20 +178,40 @@ possible, but please check the settings 
 <!ENTITY qa.setup.sysconfig.opsys	"Operating System:">
 
 <!ENTITY qa.setup.finish.header	"Setup Complete">
 
 <!ENTITY qa.bugzilla.title "Bugzilla">
 
 <!ENTITY qa.chat.title "Chat">
 <!ENTITY qa.chat.introtitle "What is IRC?">
-<!ENTITY qa.chat.intro "Internet Relay Chat (IRC) is the living room of the Mozilla QA Community. IRC is a place to ask questions, learn how you can help with the next versions of Firefox and Thunderbird, and meet other members of the community. Many of the regular QA events happen over IRC, such as Test Days and Bug Days. Come join us on IRC!">
+<!ENTITY qa.chat.intro "Internet Relay Chat (IRC) is the living room of the Mozilla QA Community.
+IRC is a place to ask questions, learn how you can help with the next versions of Firefox and Thunderbird,
+and meet other members of the community. Many of the regular QA events happen over IRC,
+such as Test Days and Bug Days. Come join us on IRC!">
 <!ENTITY qa.chat.intro2 "If you have a favorite IRC client, you can connect to <html:em>irc.mozilla.org</html:em>, channel #qa, but the easist way to get on IRC right now is through your web browser. Just click the button below.">
 <!ENTITY qa.chat.howdoItitle "How do I get on IRC?">
 <!ENTITY qa.chat.howdoI.imo "Learn more about irc.mozilla.org">
 <!ENTITY qa.chat.howdoI.imourl "http://irc.mozilla.org">
 <!ENTITY qa.chat.howdoI.irchelp "Visit irchelp.org">
 <!ENTITY qa.chat.howdoI.irchelpurl "http://www.irchelp.org">
 <!ENTITY qa.chat.howdoI.joinnow "Join IRC Now">
 
 <!ENTITY qa.help.title "Help">
+<!ENTITY qa.help.helptitle "Mozilla QA Help">
+<!ENTITY qa.help.intro "
+Visit <html:a href='http://quality.mozilla.org/' style='color: #0067ac;' target='_blank'>
+QMO</html:a>, the home of Mozilla QA, for more information about what's happening with the community.  Here are a few useful links:<html:br></html:br><html:br></html:br>
+<html:ul>
+<html:li><html:a href='http://quality.mozilla.org/qac' style='color: #0067ac;' target='_blank'>QA Companion Home</html:a></html:li>
+<html:li><html:a href='http://quality.mozilla.org/events' style='color: #0067ac;' target='_blank'>Community Events</html:a></html:li>
+<html:li><html:a href='http://quality.mozilla.org/forums' style='color: #0067ac;' target='_blank'>Discussion Forums</html:a></html:li>
+</html:ul>
+<html:h4>Litmus</html:h4>
+The Litmus tab is great for running a few quick tests, but visit <html:a href='http://litmus.mozilla.org/' style='color: #0067ac;'
+target='_blank'>Litmus</html:a> for detailed information about test cases and community activity through the Web interface.  Make sure to read
+the <html:a href='http://quality.mozilla.org/litmus' style='color: #0067ac;' target='_blank'>Litmus Tutorial</html:a>.
+<html:h4>Bugzilla</html:h4>
+The Bugzilla tab allows you to run a few basic searches, but visit <html:a href='http://bugzilla.mozilla.org/' style='color: #0067ac;'
+target='_blank'>Bugzilla</html:a> to learn more about how we handle bugs, run advanced searches or work with bugs directly.
+">
 
 <!ENTITY qa.notification.inprogress "Come Join! Event in Progress Now!">
--- a/testing/extensions/community/install.rdf
+++ b/testing/extensions/community/install.rdf
@@ -3,17 +3,17 @@
          xmlns:NC="http://home.netscape.com/NC-rdf#"
          xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
   <RDF:Description RDF:about="rdf:#$QJqvE"
                    em:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
                    em:minVersion="2.0"
                    em:maxVersion="3.0b5pre"/>
   <RDF:Description RDF:about="urn:mozilla:install-manifest"
                    em:id="{667e9f3d-0096-4d2b-b171-9a96afbabe20}"
-                   em:version="0.1.8"
+                   em:version="0.1.9"
                    em:type="2"
                    em:name="Mozilla QA Companion"
                    em:description="The QA tool for testers."
                    em:creator="Mozilla QA Team"
                    em:homepageURL="http://quality.mozilla.org/"
                    em:iconURL="chrome://qa/skin/qmo_logo_32x32.png">
     <em:targetApplication RDF:resource="rdf:#$QJqvE"/>
   </RDF:Description>
--- a/toolkit/components/passwordmgr/src/nsLoginManagerPrompter.js
+++ b/toolkit/components/passwordmgr/src/nsLoginManagerPrompter.js
@@ -214,74 +214,86 @@ LoginManagerPrompter.prototype = {
      * with a dialog, even if a username and password are found.
      */
     promptUsernameAndPassword : function (aDialogTitle, aText, aPasswordRealm,
                                          aSavePassword, aUsername, aPassword) {
         if (aSavePassword == Ci.nsIAuthPrompt.SAVE_PASSWORD_FOR_SESSION)
             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
 
         var selectedLogin = null;
-        var foundLogins;
         var checkBox = { value : false };
         var checkBoxLabel = null;
         var hostname = this._getFormattedHostname(aPasswordRealm);
 
         this.log("===== promptUsernameAndPassword() called =====");
 
         var canRememberLogin = (aSavePassword ==
                                 Ci.nsIAuthPrompt.SAVE_PASSWORD_PERMANENTLY) &&
                                this._pwmgr.getLoginSavingEnabled(hostname);
 
         // if checkBoxLabel is null, the checkbox won't be shown at all.
         if (canRememberLogin)
             checkBoxLabel = this._getLocalizedString("rememberPassword");
 
-        if (!aUsername.value && !aPassword.value) {
-            // Look for existing logins.
-            foundLogins = this._pwmgr.findLogins({}, hostname, null,
+        // Look for existing logins.
+        var foundLogins = this._pwmgr.findLogins({}, hostname, null,
                                                  aPasswordRealm);
 
-            // XXX Like the original code, we can't deal with multiple
-            // account selection. (bug 227632)
-            if (foundLogins.length > 0) {
-                selectedLogin = foundLogins[0];
-                // We've got a login, but don't return straight away because
-                // the old wallet code didn't either.
-                aUsername.value = foundLogins[0].username;
-                aPassword.value = foundLogins[0].password;
+        // XXX Like the original code, we can't deal with multiple
+        // account selection. (bug 227632)
+        if (foundLogins.length > 0) {
+            selectedLogin = foundLogins[0];
+
+            // If the caller provided a username, try to use it. If they
+            // provided only a password, this will try to find a password-only
+            // login (or return null if none exists).
+            if (aUsername.value)
+                selectedLogin = this._repickSelectedLogin(foundLogins,
+                                                          aUsername.value);
+
+            if (selectedLogin) {
+                checkBox.value = true;
+                aUsername.value = selectedLogin.username;
+                // If the caller provided a password, prefer it.
+                if (!aPassword.value)
+                    aPassword.value = selectedLogin.password;
             }
         }
 
         var ok = this._promptService.promptUsernameAndPassword(this._window,
                     aDialogTitle, aText, aUsername, aPassword,
                     checkBoxLabel, checkBox);
 
-        if (ok && checkBox.value) {
-            var newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
-                           createInstance(Ci.nsILoginInfo);
-            newLogin.init(hostname, null, aPasswordRealm,
-                          aUsername.value, aPassword.value,
-                          "", "");
+        if (!ok || !checkBox.value)
+            return ok;
+
+
+        var newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
+                       createInstance(Ci.nsILoginInfo);
+        newLogin.init(hostname, null, aPasswordRealm,
+                      aUsername.value, aPassword.value,
+                      "", "");
 
-            // If we didn't find an existing login, or if the username
-            // changed, save as a new login.
-            if (!selectedLogin || username != selectedLogin.username) {
-                // add as new
-                this.log("New login seen for " + aPasswordRealm);
+        // XXX We can't prompt with multiple logins yet (bug 227632), so
+        // the entered login might correspond to an existing login
+        // other than the one we originally selected.
+        selectedLogin = this._repickSelectedLogin(foundLogins, aUsername.value);
 
-                this._pwmgr.addLogin(newLogin);
-            } else if (selectedLogin &&
-                       password != selectedLogin.password) {
-                // update password
-                this.log("Updating password for  " + aPasswordRealm);
-                this._pwmgr.modifyLogin(foundLogins[0], newLogin);
-            } else {
-                this.log("Login unchanged, no further action needed.");
-                return ok;
-            }
+        // If we didn't find an existing login, or if the username
+        // changed, save as a new login.
+        if (!selectedLogin) {
+            // add as new
+            this.log("New login seen for " + aPasswordRealm);
+            this._pwmgr.addLogin(newLogin);
+        } else if (aPassword.value != selectedLogin.password) {
+            // update password
+            this.log("Updating password for  " + aPasswordRealm);
+            this._pwmgr.modifyLogin(selectedLogin, newLogin);
+        } else {
+            this.log("Login unchanged, no further action needed.");
         }
 
         return ok;
     },
 
 
     /*
      * promptPassword
@@ -311,25 +323,23 @@ LoginManagerPrompter.prototype = {
 
         // if checkBoxLabel is null, the checkbox won't be shown at all.
         if (canRememberLogin)
             checkBoxLabel = this._getLocalizedString("rememberPassword");
 
         if (!aPassword.value) {
             // Look for existing logins.
             var foundLogins = this._pwmgr.findLogins({}, hostname, null,
-
                                                      newRealm);
 
-            var i;
             // XXX Like the original code, we can't deal with multiple
             // account selection (bug 227632). We can deal with finding the
             // account based on the supplied username - but in this case we'll
             // just return the first match.
-            for (i = 0; i < foundLogins.length; ++i) {
+            for (var i = 0; i < foundLogins.length; ++i) {
                 if (foundLogins[i].username == username) {
                     aPassword.value = foundLogins[i].password;
                     // wallet returned straight away, so this mimics that code
                     return true;
                 }
             }
         }
 
@@ -409,58 +419,58 @@ LoginManagerPrompter.prototype = {
             // Ignore any errors and display the prompt anyway.
             epicfail = true;
             Components.utils.reportError("LoginManagerPrompter: " +
                 "Epic fail in promptAuth: " + e + "\n");
         }
 
         var ok = this._promptService.promptAuth(this._window, aChannel,
                                 aLevel, aAuthInfo, checkboxLabel, checkbox);
-        if (epicfail)
+
+        // If there's a notification box, use it to allow the user to
+        // determine if the login should be saved. If there isn't a
+        // notification box, only save the login if the user set the
+        // checkbox to do so.
+        var rememberLogin = notifyBox ? canRememberLogin : checkbox.value;
+        if (!ok || !rememberLogin || epicfail)
             return ok;
 
         try {
             var [username, password] = this._GetAuthInfo(aAuthInfo);
 
-            // If there's a notification box, use it to allow the user to
-            // determine if the login should be saved. If there isn't a
-            // notification box, only save the login if the user set the
-            // checkbox to do so.
-            var rememberLogin = notifyBox ? canRememberLogin : checkbox.value;
+            var newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
+                           createInstance(Ci.nsILoginInfo);
+            newLogin.init(hostname, null, httpRealm,
+                          username, password, "", "");
 
-            if (ok && rememberLogin) {
-                var newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
-                               createInstance(Ci.nsILoginInfo);
-                newLogin.init(hostname, null, httpRealm,
-                              username, password, "", "");
-
-                // If we didn't find an existing login, or if the username
-                // changed, save as a new login.
-                if (!selectedLogin || username != selectedLogin.username) {
+            // XXX We can't prompt with multiple logins yet (bug 227632), so
+            // the entered login might correspond to an existing login
+            // other than the one we originally selected.
+            selectedLogin = this._repickSelectedLogin(foundLogins, username);
 
-                    // add as new
-                    this.log("New login seen for " + username +
-                             " @ " + hostname + " (" + httpRealm + ")");
-                    if (notifyBox)
-                        this._showSaveLoginNotification(notifyBox, newLogin);
-                    else
-                        this._pwmgr.addLogin(newLogin);
+            // If we didn't find an existing login, or if the username
+            // changed, save as a new login.
+            if (!selectedLogin) {
+                // add as new
+                this.log("New login seen for " + username +
+                         " @ " + hostname + " (" + httpRealm + ")");
+                if (notifyBox)
+                    this._showSaveLoginNotification(notifyBox, newLogin);
+                else
+                    this._pwmgr.addLogin(newLogin);
 
-                } else if (selectedLogin &&
-                           password != selectedLogin.password) {
+            } else if (password != selectedLogin.password) {
 
-                    this.log("Updating password for " + username +
-                             " @ " + hostname + " (" + httpRealm + ")");
-                    // update password
-                    this._pwmgr.modifyLogin(foundLogins[0], newLogin);
+                this.log("Updating password for " + username +
+                         " @ " + hostname + " (" + httpRealm + ")");
+                // update password
+                this._pwmgr.modifyLogin(selectedLogin, newLogin);
 
-                } else {
-                    this.log("Login unchanged, no further action needed.");
-                    return ok;
-                }
+            } else {
+                this.log("Login unchanged, no further action needed.");
             }
         } catch (e) {
             Components.utils.reportError("LoginManagerPrompter: " +
                 "Fail2 in promptAuth: " + e + "\n");
         }
 
         return ok;
     },
@@ -895,16 +905,31 @@ LoginManagerPrompter.prototype = {
             this.log("No notification box available: " + e)
         }
 
         return null;
     },
 
 
     /*
+     * _repickSelectedLogin
+     *
+     * The user might enter a login that isn't the one we prefilled, but
+     * is the same as some other existing login. So, pick a login with a
+     * matching username, or return null.
+     */
+    _repickSelectedLogin : function (foundLogins, username) {
+        for (var i = 0; i < foundLogins.length; i++)
+            if (foundLogins[i].username == username)
+                return foundLogins[i];
+        return null;
+    },
+
+    
+    /*
      * _getLocalizedString
      *
      * Can be called as:
      *   _getLocalizedString("key1");
      *   _getLocalizedString("key2", ["arg1"]);
      *   _getLocalizedString("key3", ["arg1", "arg2"]);
      *   (etc)
      *
--- a/toolkit/components/passwordmgr/test/Makefile.in
+++ b/toolkit/components/passwordmgr/test/Makefile.in
@@ -58,16 +58,17 @@ MOCHI_TESTS = \
 		test_basic_form_3pw_1.html \
 		test_basic_form_autocomplete.html \
 		test_basic_form_pwonly.html \
 		test_bug_227640.html \
 		test_bug_242956.html \
 		test_bug_360493_1.html \
 		test_bug_360493_2.html \
 		test_bug_391514.html \
+		test_prompt.html \
 		test_zzz_finish.html \
 		$(NULL)
 
 XPCSHELL_TESTS  = unit
 
 # This test doesn't pass because we can't ensure a cross-platform
 # event that occurs between DOMContentLoaded and Pageload
 # test_bug_221634.html
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_prompt.html
@@ -0,0 +1,627 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Login Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Login Manager test: username/password prompts
+<p id="display"></p>
+
+<div id="content" style="display: none">
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Login Manager: username / password prompts. **/
+
+var pwmgr, login1, login2A, login2B;
+
+function initLogins() {
+  pwmgr = Cc["@mozilla.org/login-manager;1"].
+          getService(Ci.nsILoginManager);
+
+  login1  = Cc["@mozilla.org/login-manager/loginInfo;1"].
+            createInstance(Ci.nsILoginInfo);
+  login2A = Cc["@mozilla.org/login-manager/loginInfo;1"].
+            createInstance(Ci.nsILoginInfo);
+  login2B = Cc["@mozilla.org/login-manager/loginInfo;1"].
+            createInstance(Ci.nsILoginInfo);
+
+  login1.init("http://example.com", null, "http://example.com",
+              "", "examplepass", "", "");
+  login2A.init("http://example2.com", null, "http://example2.com",
+               "user1name", "user1pass", "", "");
+  login2B.init("http://example2.com", null, "http://example2.com",
+               "user2name", "user2pass", "", "");
+
+  pwmgr.addLogin(login1);
+  pwmgr.addLogin(login2A);
+  pwmgr.addLogin(login2B);
+}
+
+function cleanupLogins() {
+  pwmgr.removeLogin(login1);
+  pwmgr.removeLogin(login2A);
+  pwmgr.removeLogin(login2B);
+}
+
+
+function getDialogDoc() {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+  // Find the <browser> which contains notifyWindow, by looking
+  // through all the open windows and all the <browsers> in each.
+  var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
+           getService(Ci.nsIWindowMediator);
+  //var enumerator = wm.getEnumerator("navigator:browser");
+  var enumerator = wm.getXULWindowEnumerator(null);
+  var promptDoc = null;
+
+  while (!promptDoc && enumerator.hasMoreElements()) {
+    var win = enumerator.getNext();
+    var windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
+
+    var containedDocShells = windowDocShell.getDocShellEnumerator(
+                                      Ci.nsIDocShellTreeItem.typeChrome,
+                                      Ci.nsIDocShell.ENUMERATE_FORWARDS);
+    while (!promptDoc && containedDocShells.hasMoreElements()) {
+        // Get the corresponding document for this docshell
+        var childDoc = containedDocShells.getNext()
+                                         .QueryInterface(Ci.nsIDocShell)
+                                         .contentViewer
+                                         .DOMDocument;
+
+        //ok(true, "Got window: " + childDoc.location.href);
+        if (childDoc.location.href == "chrome://global/content/commonDialog.xul")
+            promptDoc = childDoc;
+    }
+  }
+
+  return promptDoc;
+}
+
+
+function handleDialog(doc, testNum) {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  ok(true, "handleDialog running for test " + testNum);
+
+  var clickOK = true;
+  var userfield = doc.getElementById("loginTextbox");
+  var passfield = doc.getElementById("password1Textbox");
+  var username = userfield.getAttribute("value");
+  var password = passfield.getAttribute("value");
+  var dialog    = doc.getElementById("commonDialog");
+
+  switch(testNum) {
+    case 1:
+        is(username, "abc", "Checking provided username");
+        userfield.setAttribute("value", "xyz");
+        break;
+
+    case 2:
+        clickOK = false;
+        break;
+
+    case 10:
+        is(password, "inputpw", "Checking provided password");
+        passfield.setAttribute("value", "secret");
+        break;
+
+    case 11:
+        is(password, "inputpw", "Checking provided password");
+        clickOK = false;
+        break;
+
+    case 12:
+        is(password, "", "Checking provided password");
+        passfield.setAttribute("value", "secret");
+        break;
+
+    case 14:
+        is(password, "", "Checking provided password");
+        passfield.setAttribute("value", "secret");
+        break;
+
+    case 100:
+        is(username, "inuser", "Checking provided username");
+        is(password, "inpass", "Checking provided password");
+        userfield.setAttribute("value", "outuser");
+        passfield.setAttribute("value", "outpass");
+        break;
+
+    case 101:
+        clickOK = false;
+        break;
+
+    case 102:
+        is(username, "", "Checking provided username");
+        is(password, "examplepass", "Checking provided password");
+        break;
+
+    case 103:
+        ok(username == "user1name" || username == "user2name", "Checking filled username");
+        ok(password == "user1pass" || password == "user2pass", "Checking filled password");
+        break;
+
+    case 104:
+        is(username, "user1name", "Checking filled username");
+        is(password, "user1pass", "Checking filled password");
+        break;
+
+    case 105:
+        is(username, "user2name", "Checking filled username");
+        is(password, "user2pass", "Checking filled password");
+        break;
+
+    case 106:
+        is(username, "user2name", "Checking filled username");
+        is(password, "user2pass", "Checking filled password");
+        passfield.setAttribute("value", "NEWuser2pass");
+        break;
+
+    case 107:
+        is(username, "user2name", "Checking filled username");
+        is(password, "NEWuser2pass", "Checking filled password");
+        passfield.setAttribute("value", "user2pass");
+        break;
+
+    case 500:
+        is(username, "inuser", "Checking unfilled username");
+        is(password, "inpass", "Checking unfilled password");
+        userfield.setAttribute("value", "outuser");
+        passfield.setAttribute("value", "outpass");
+        break;
+
+    case 501:
+        clickOK = false;
+        break;
+
+    case 502:
+        is(username, "", "Checking filled username");
+        is(password, "examplepass", "Checking filled password");
+        break;
+
+    case 503:
+        // either of the two logins might have been filled in
+        ok(username == "user1name" || username == "user2name", "Checking filled username");
+        ok(password == "user1pass" || password == "user2pass", "Checking filled password");
+        break;
+
+    case 504:
+        // either of the two logins might have been filled in
+        ok(username == "user1name" || username == "user2name", "Checking filled username");
+        ok(password == "user1pass" || password == "user2pass", "Checking filled password");
+        // enter one of the known logins, test 504+505 exercise the two possible states.
+        userfield.setAttribute("value", "user1name");
+        passfield.setAttribute("value", "user1pass");
+        break;
+
+    case 505:
+        // either of the two logins might have been filled in
+        ok(username == "user1name" || username == "user2name", "Checking filled username");
+        ok(password == "user1pass" || password == "user2pass", "Checking filled password");
+        // enter one of the known logins, test 504+505 exercise the two possible states.
+        userfield.setAttribute("value", "user2name");
+        passfield.setAttribute("value", "user2pass");
+        break;
+
+    case 506:
+        // either of the two logins might have been filled in
+        ok(username == "user1name" || username == "user2name", "Checking filled username");
+        ok(password == "user1pass" || password == "user2pass", "Checking filled password");
+        // force to user2, and change the password
+        userfield.setAttribute("value", "user2name");
+        passfield.setAttribute("value", "NEWuser2pass");
+        break;
+
+    case 507:
+        // either of the two logins might have been filled in
+        ok(username == "user1name" || username == "user2name", "Checking filled username");
+        ok(password == "user1pass" || password == "user2pass", "Checking filled password");
+        // force to user2, and change the password back
+        userfield.setAttribute("value", "user2name");
+        passfield.setAttribute("value", "user2pass");
+        break;
+
+    default:
+        ok(false, "Uhh, unhandled switch for testNum #" + testNum);
+        break;
+  }
+
+  if (clickOK)
+    dialog.acceptDialog();
+  else
+    dialog.cancelDialog();
+
+  ok(true, "handleDialog done");
+}
+
+
+netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+const Ci = Components.interfaces;
+ok(Ci != null, "Access Ci");
+const Cc = Components.classes;
+ok(Cc != null, "Access Cc");
+
+initLogins();
+
+const Cc_promptFac= Cc["@mozilla.org/passwordmanager/authpromptfactory;1"];
+ok(Cc_promptFac != null, "Access Cc[@mozilla.org/passwordmanager/authpromptfactory;1]");
+
+const Ci_promptFac = Ci.nsIPromptFactory;
+ok(Ci_promptFac != null, "Access Ci.nsIPromptFactory");
+
+const promptFac = Cc_promptFac.getService(Ci_promptFac);
+ok(promptFac != null, "promptFac getService()");
+
+
+var timer; // keep in outer scope so it's not GC'd before firing
+function startCallbackTimer() {
+    // Delay before the callback twiddles the prompt.
+    const dialogDelay = 300;
+
+    // Use a timer to invoke a callback to twiddle the authentication dialog
+    timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+    timer.init(observer, dialogDelay, Ci.nsITimer.TYPE_ONE_SHOT);
+}
+
+
+var observer = {
+    QueryInterface : function (iid) {
+        const interfaces = [Ci.nsIObserver,
+                            Ci.nsISupports, Ci.nsISupportsWeakReference];
+
+        if (!interfaces.some( function(v) { return iid.equals(v) } ))
+            throw Components.results.NS_ERROR_NO_INTERFACE;
+        return this;
+    },
+
+    observe : function (subject, topic, data) {
+        ok(true, "timer fired for test " + testNum);
+        var doc = getDialogDoc();
+        ok(doc, "Got commonDialog.xul document");
+        if (doc)
+            handleDialog(doc, testNum);
+    }
+};
+
+
+var authinfo = {
+    // QueryInterface : ... ?
+    username : "",
+    password : "",
+    domain   : "",
+
+    flags : Ci.nsIAuthInformation.AUTH_HOST,
+    authenticationScheme : "basic",
+    realm : ""
+};
+
+
+
+var prompter1 = promptFac.getPrompt(window, Ci.nsIAuthPrompt);
+var prompter2 = promptFac.getPrompt(window, Ci.nsIAuthPrompt2);
+
+function dialogTitle() { return "nsILoginManagerPrompter test #" + testNum; }
+var dialogText  = "This dialog should be modified and dismissed by the test.";
+var uname  = { value : null };
+var pword  = { value : null };
+var result = { value : null };
+var isOk;
+
+
+// ===== test 1 ===== 
+var testNum = 1;
+startCallbackTimer();
+isOk = prompter1.prompt(dialogTitle(), dialogText, "http://example.com",
+                        Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, "abc", result);
+
+ok(isOk, "Checking dialog return value (accept)");
+is(result.value, "xyz", "Checking prompt() returned value");
+
+
+// ===== test 2 =====
+testNum++;
+startCallbackTimer();
+isOk = prompter1.prompt(dialogTitle(), dialogText, "http://example.com",
+                        Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, "abc", result);
+ok(!isOk, "Checking dialog return value (cancel)");
+
+
+// ===== test 10 =====
+// Default password provided, existing logins are ignored.
+testNum = 10;
+pword.value = "inputpw";
+startCallbackTimer();
+isOk = prompter1.promptPassword(dialogTitle(), dialogText, "http://example.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(pword.value, "secret", "Checking returned password");
+
+// ===== test 11 =====
+// Default password provided, existing logins are ignored.
+testNum++;
+pword.value = "inputpw";
+startCallbackTimer();
+isOk = prompter1.promptPassword(dialogTitle(), dialogText, "http://example.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, pword);
+ok(!isOk, "Checking dialog return value (cancel)");
+
+// ===== test 12 =====
+// No default password provided, realm does not match existing login.
+testNum++;
+pword.value = null;
+startCallbackTimer();
+isOk = prompter1.promptPassword(dialogTitle(), dialogText, "http://nonexample.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(pword.value, "secret", "Checking returned password");
+
+// ===== test 13 =====
+// No default password provided, matching login is returned w/o prompting.
+testNum++;
+pword.value = null;
+isOk = prompter1.promptPassword(dialogTitle(), dialogText, "http://example.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(pword.value, "examplepass", "Checking returned password");
+
+// ===== test 14 =====
+// No default password provided, none of the logins from this host are
+// password-only so the user is prompted.
+testNum++;
+pword.value = null;
+startCallbackTimer();
+isOk = prompter1.promptPassword(dialogTitle(), dialogText, "http://example2.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(pword.value, "secret", "Checking returned password");
+
+// ===== test 15 =====
+// No default password provided, matching login is returned w/o prompting.
+testNum++;
+pword.value = null;
+isOk = prompter1.promptPassword(dialogTitle(), dialogText, "http://user1name@example2.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(pword.value, "user1pass", "Checking returned password");
+
+// ===== test 16 =====
+// No default password provided, matching login is returned w/o prompting.
+testNum++;
+pword.value = null;
+isOk = prompter1.promptPassword(dialogTitle(), dialogText, "http://user2name@example2.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(pword.value, "user2pass", "Checking returned password");
+
+// XXX test saving a password with  Ci.nsIAuthPrompt.SAVE_PASSWORD_PERMANENTLY
+
+
+// ===== test 100 =====
+testNum = 100;
+uname.value = "inuser";
+pword.value = "inpass";
+startCallbackTimer();
+isOk = prompter1.promptUsernameAndPassword(dialogTitle(), dialogText, "http://nonexample.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, uname, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(uname.value, "outuser", "Checking returned username");
+is(pword.value, "outpass", "Checking returned password");
+
+// ===== test 101 =====
+testNum++;
+uname.value = "inuser";
+pword.value = "inpass";
+startCallbackTimer();
+isOk = prompter1.promptUsernameAndPassword(dialogTitle(), dialogText, "http://nonexample.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, uname, pword);
+ok(!isOk, "Checking dialog return value (cancel)");
+
+// ===== test 102 =====
+// test filling in existing password-only login
+testNum++;
+uname.value = null;
+pword.value = null;
+startCallbackTimer();
+isOk = prompter1.promptUsernameAndPassword(dialogTitle(), dialogText, "http://example.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_PERMANENTLY, uname, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(uname.value, "", "Checking returned username");
+is(pword.value, "examplepass", "Checking returned password");
+
+// ===== test 103 =====
+// test filling in existing login (undetermined from multiple selection)
+testNum++;
+uname.value = null;
+pword.value = null;
+startCallbackTimer();
+isOk = prompter1.promptUsernameAndPassword(dialogTitle(), dialogText, "http://example2.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_PERMANENTLY, uname, pword);
+ok(isOk, "Checking dialog return value (accept)");
+ok(uname.value == "user1name" || uname.value == "user2name", "Checking returned username");
+ok(pword.value == "user1pass" || uname.value == "user2pass", "Checking returned password");
+
+// ===== test 104 =====
+// test filling in existing login (user1 from multiple selection)
+testNum++;
+uname.value = "user1name";
+pword.value = null;
+startCallbackTimer();
+isOk = prompter1.promptUsernameAndPassword(dialogTitle(), dialogText, "http://example2.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_PERMANENTLY, uname, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(uname.value, "user1name", "Checking returned username");
+is(pword.value, "user1pass", "Checking returned password");
+
+// ===== test 105 =====
+// test filling in existing login (user2 from multiple selection)
+testNum++;
+uname.value = "user2name";
+pword.value = null;
+startCallbackTimer();
+isOk = prompter1.promptUsernameAndPassword(dialogTitle(), dialogText, "http://example2.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_PERMANENTLY, uname, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(uname.value, "user2name", "Checking returned username");
+is(pword.value, "user2pass", "Checking returned password");
+
+// ===== test 106 =====
+// test changing password
+testNum++;
+uname.value = "user2name";
+pword.value = null;
+startCallbackTimer();
+isOk = prompter1.promptUsernameAndPassword(dialogTitle(), dialogText, "http://example2.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_PERMANENTLY, uname, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(uname.value, "user2name", "Checking returned username");
+is(pword.value, "NEWuser2pass", "Checking returned password");
+
+// ===== test 107 =====
+// test changing password (back to original value)
+testNum++;
+uname.value = "user2name";
+pword.value = null;
+startCallbackTimer();
+isOk = prompter1.promptUsernameAndPassword(dialogTitle(), dialogText, "http://example2.com",
+                                Ci.nsIAuthPrompt.SAVE_PASSWORD_PERMANENTLY, uname, pword);
+ok(isOk, "Checking dialog return value (accept)");
+is(uname.value, "user2name", "Checking returned username");
+is(pword.value, "user2pass", "Checking returned password");
+
+
+
+var channel1 = Cc["@mozilla.org/network/io-service;1"].
+              getService(Ci.nsIIOService).
+              newChannel("http://example.com", null, null);
+var channel2 = Cc["@mozilla.org/network/io-service;1"].
+              getService(Ci.nsIIOService).
+              newChannel("http://example2.com", null, null);
+var level = Ci.nsIAuthPrompt2.LEVEL_NONE;
+
+
+// ===== test 500 =====
+testNum = 500;
+authinfo.username = "inuser";
+authinfo.password = "inpass";
+authinfo.realm    = "some realm";
+
+startCallbackTimer();
+isOk = prompter2.promptAuth(channel1, level, authinfo);
+
+ok(isOk, "Checking dialog return value (accept)");
+is(authinfo.username, "outuser", "Checking returned username");
+is(authinfo.password, "outpass", "Checking returned password");
+
+// ===== test 501 =====
+testNum++;
+startCallbackTimer();
+isOk = prompter2.promptAuth(channel1, level, authinfo);
+
+// XXX for some reason |!isOk == false| on the OS X tinderbox, although it's
+// not when run locally (and clicking cancel does work, which is what this
+// is testing). Not sure why.
+// ok(!isOk, "Checking dialog return value (cancel)");
+ok(true, "XXX dialog returned " + isOk);
+
+// ===== test 502 =====
+// test filling in password-only login
+testNum++;
+authinfo.username = "";
+authinfo.password = "";
+authinfo.realm    = "http://example.com";
+
+startCallbackTimer();
+isOk = prompter2.promptAuth(channel1, level, authinfo);
+
+ok(isOk, "Checking dialog return value (accept)");
+is(authinfo.username, "", "Checking returned username");
+is(authinfo.password, "examplepass", "Checking returned password");
+
+// ===== test 503 =====
+// test filling in existing login (undetermined from multiple selection)
+testNum++;
+authinfo.username = "";
+authinfo.password = "";
+authinfo.realm    = "http://example2.com";
+
+startCallbackTimer();
+isOk = prompter2.promptAuth(channel2, level, authinfo);
+
+ok(isOk, "Checking dialog return value (accept)");
+ok(authinfo.username == "user1name" || authinfo.username == "user2name", "Checking returned username");
+ok(authinfo.password == "user1pass" || authinfo.password == "user2pass", "Checking returned password");
+
+// ===== test 504 =====
+// test filling in existing login (undetermined --> user1)
+testNum++;
+authinfo.username = "";
+authinfo.password = "";
+authinfo.realm    = "http://example2.com";
+
+startCallbackTimer();
+isOk = prompter2.promptAuth(channel2, level, authinfo);
+
+ok(isOk, "Checking dialog return value (accept)");
+is(authinfo.username, "user1name", "Checking returned username");
+is(authinfo.password, "user1pass", "Checking returned password");
+
+// ===== test 505 =====
+// test filling in existing login (undetermined --> user2)
+testNum++;
+authinfo.username = "";
+authinfo.password = "";
+authinfo.realm    = "http://example2.com";
+
+startCallbackTimer();
+isOk = prompter2.promptAuth(channel2, level, authinfo);
+
+ok(isOk, "Checking dialog return value (accept)");
+is(authinfo.username, "user2name", "Checking returned username");
+is(authinfo.password, "user2pass", "Checking returned password");
+
+// ===== test 506 =====
+// test changing a password (undetermined --> user2 w/ newpass)
+testNum++;
+authinfo.username = "";
+authinfo.password = "";
+authinfo.realm    = "http://example2.com";
+
+startCallbackTimer();
+isOk = prompter2.promptAuth(channel2, level, authinfo);
+
+ok(isOk, "Checking dialog return value (accept)");
+is(authinfo.username, "user2name", "Checking returned username");
+is(authinfo.password, "NEWuser2pass", "Checking returned password");
+
+// ===== test 507 =====
+// test changing a password (undetermined --> user2 w/ origpass)
+testNum++;
+authinfo.username = "";
+authinfo.password = "";
+authinfo.realm    = "http://example2.com";
+
+startCallbackTimer();
+isOk = prompter2.promptAuth(channel2, level, authinfo);
+
+ok(isOk, "Checking dialog return value (accept)");
+is(authinfo.username, "user2name", "Checking returned username");
+is(authinfo.password, "user2pass", "Checking returned password");
+
+
+// XXX check for and kill notification bar??
+// XXX check for checkbox / checkstate on old prompts?
+// XXX check NTLM domain stuff
+
+cleanupLogins();
+</script>
+</pre>
+</body>
+</html>
--- a/toolkit/content/tests/widgets/test_textbox_emptytext.xul
+++ b/toolkit/content/tests/widgets/test_textbox_emptytext.xul
@@ -1,15 +1,16 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
 <!--
   XUL Widget Test for textbox with emptyText
   -->
 <window title="Textbox with emptyText test" width="500" height="600"
+        onload="window.focus();"
         onfocus="if (!gDone) { gDone = true; doTests(); }"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <script type="application/javascript" src="/MochiKit/packed.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 
   <hbox>
     <textbox id="t1"/>
   </hbox>
--- a/toolkit/content/tests/widgets/test_textbox_number.xul
+++ b/toolkit/content/tests/widgets/test_textbox_number.xul
@@ -1,15 +1,16 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
 <!--
   XUL Widget Test for textbox type="number"
   -->
 <window title="Textbox type='number' test" width="500" height="600"
+        onload="window.focus();"
         onfocus="if (!gDone) { gDone = true; doTests(); }"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <script type="application/javascript" src="/MochiKit/packed.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
   <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>  
 
 <hbox>
   <textbox id="n1" type="number" size="4"/>
--- a/toolkit/content/tests/widgets/test_tooltip_noautohide.xul
+++ b/toolkit/content/tests/widgets/test_tooltip_noautohide.xul
@@ -1,14 +1,15 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
 
 <window title="Tooltip Noautohide Tests"
-  onfocus="setTimeout(runTests, 0);"
+  onload="window.focus();"
+  onfocus="if (!gDone) { gDone = true; setTimeout(runTests, 0); }"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <script type="application/javascript" src="/MochiKit/packed.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>      
   <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>      
 
 <tooltip id="thetooltip" noautohide="true"
          onpopupshown="setTimeout(tooltipStillShown, 6000)"
@@ -16,16 +17,17 @@
   <label id="label" value="This is a tooltip"/>
 </tooltip>
 
 <button id="button" label="Tooltip Text" tooltip="thetooltip"/>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+var gDone = false;
 var gChecked = false;
 
 SimpleTest.waitForExplicitFinish();
 
 function runTests()
 {
   var button = document.getElementById("button");
   synthesizeMouse(button, 2, 2, { type: "mouseover" });
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -1,14 +1,14 @@
 /** this should only contain XUL dialog and document window widget defaults. Defaults for widgets of
     a particular application should be in that application's style sheet.
 	For example style definitions for navigator can be found in navigator.css
 
    THIS FILE IS LOCKED DOWN.  YOU ARE NOT ALLOWED TO MODIFY IT WITHOUT FIRST HAVING YOUR
-   CHANGES REVIEWED BY mconnor@steelgryphon.com
+   CHANGES REVIEWED BY enndeakin@sympatico.ca
 **/
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
 @namespace html url("http://www.w3.org/1999/xhtml"); /* namespace for HTML elements */
 @namespace xbl url("http://www.mozilla.org/xbl"); /* namespace for XBL elements */
 
 * {
   -moz-user-focus: ignore;
@@ -48,18 +48,17 @@ window[chromehidden~="toolbar"] .chromec
   display: none;
 }
 
 /* ::::::::::
    :: Rules for forcing direction for entry and display of URIs
    :: or URI elements
    ::::: */
 
-textbox.uri-element,
-menulist.uri-element
+.uri-element
 {
   direction: ltr !important;
 }
 
 /****** elements that have no visual representation ******/
 
 script, data,
 xbl|children,
--- a/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in
+++ b/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in
@@ -431,23 +431,28 @@ nsUnknownContentTypeDialog.prototype = {
 
       // if always-save and is-executable and no-handler
       // then set up simple ui
       var mimeType = this.mLauncher.MIMEInfo.MIMEType;
       var shouldntRememberChoice = (mimeType == "application/octet-stream" || 
                                     mimeType == "application/x-msdownload" ||
                                     this.mLauncher.targetFileIsExecutable);
       if (shouldntRememberChoice && !this.openWithDefaultOK()) {
+        let acceptButton = this.mDialog.document.getButton("accept");
+        // change the accept button icon to a save one
+        acceptButton.setAttribute("icon", "save");
+        // change button labels
+        acceptButton.label =
+            this.dialogElement("strings").getString("unknownAccept.label");
+        this.mDialog.document.documentElement.getButton("cancel").label =
+            this.dialogElement("strings").getString("unknownCancel.label");
         // hide featured choice 
         this.mDialog.document.getElementById("normalBox").collapsed = "true";
         // show basic choice 
         this.mDialog.document.getElementById("basicBox").collapsed = "false";
-        // change button labels
-        this.mDialog.document.documentElement.getButton("accept").label = this.dialogElement("strings").getString("unknownAccept.label");
-        this.mDialog.document.documentElement.getButton("cancel").label = this.dialogElement("strings").getString("unknownCancel.label");
         // hide other handler
         this.mDialog.document.getElementById("openHandler").collapsed = "true";
         // set save as the selected option
         this.dialogElement("mode").selectedItem = this.dialogElement("save");
       }
       else {
         this.initAppAndSaveToDiskValues();
 
--- a/toolkit/themes/gnomestripe/mozapps/extensions/extensions.css
+++ b/toolkit/themes/gnomestripe/mozapps/extensions/extensions.css
@@ -1,13 +1,23 @@
 #extensionsBox {
-  margin: 10px 10px 0px 10px;
+  margin: 10px 8px 0 8px;
   min-width:1px;
 }
 
+/* Addons notification */
+notification {
+  background-color: transparent;
+}
+.notification-inner {
+  background-color: infobackground;
+  border-color: ThreeDShadow;
+  margin: 9px 8px 0 8px;
+}
+
 #extensionsView {
   border: 2px solid;
   -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
   -moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
   -moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
   -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
   margin: 0 !important;
 }
@@ -49,16 +59,17 @@ richlistitem[isDisabled="true"] .addonIc
 }
 
 richlistitem[isDisabled="true"] {
   color: GrayText;
 }
 
 richlistitem[newAddon="true"] {
   background-color: InfoBackground;
+  color: InfoText;
 }
 
 richlistitem[selected="true"] {
   background-color: -moz-cellhighlight;
   color: -moz-cellhighlighttext;
 }
 
 richlistitem[selected="true"] .text-link {
--- a/toolkit/themes/pinstripe/mozapps/extensions/extensions.css
+++ b/toolkit/themes/pinstripe/mozapps/extensions/extensions.css
@@ -54,16 +54,17 @@ richlistitem[isDisabled="true"] .addonIc
 }
 
 richlistitem[isDisabled="true"] {
   color: GrayText;
 }
 
 richlistitem[newAddon="true"] {
   background-color: #fdf2ab;
+  color: #585620;
 }
 
 richlistitem[selected="true"] {
   background-color: Highlight;
   color: HighlightText;
 }
 
 richlistitem[selected="true"] .text-link {
--- a/toolkit/themes/winstripe/mozapps/extensions/extensions.css
+++ b/toolkit/themes/winstripe/mozapps/extensions/extensions.css
@@ -48,16 +48,17 @@ richlistitem[isDisabled="true"] .addonIc
 }
 
 richlistitem[isDisabled="true"] {
   color: GrayText;
 }
 
 richlistitem[newAddon="true"] {
   background-color: InfoBackground;
+  color: InfoText;
 }
 
 richlistitem[selected="true"] {
   background-color: -moz-cellhighlight;
   color: -moz-cellhighlighttext;
 }
 
 richlistitem[selected="true"] .text-link {
--- a/widget/src/gtk2/gtk2drawing.c
+++ b/widget/src/gtk2/gtk2drawing.c
@@ -94,16 +94,17 @@ static GtkWidget* gHPanedWidget;
 static GtkWidget* gVPanedWidget;
 static GtkWidget* gScrolledWindowWidget;
 
 static GtkShadowType gMenuBarShadowType;
 static GtkShadowType gToolbarShadowType;
 
 static style_prop_t style_prop_func;
 static gboolean have_menu_shadow_type;
+static gboolean have_arrow_scaling;
 static gboolean is_initialized;
 
 gint
 moz_gtk_enable_style_props(style_prop_t styleGetProp)
 {
     style_prop_func = styleGetProp;
     return MOZ_GTK_SUCCESS;
 }
@@ -248,61 +249,127 @@ ensure_option_menu_widget()
 {
     if (!gOptionMenuWidget) {
         gOptionMenuWidget = gtk_option_menu_new();
         setup_widget_prototype(gOptionMenuWidget);        
     }
     return MOZ_GTK_SUCCESS;
 }
 
-static gint
-ensure_combo_box_entry_widget()
+/* We need to have pointers to the inner widgets (entry, button, arrow) of
+ * the ComboBoxEntry to get the correct rendering from theme engines which
+ * special cases their look. Since the inner layout can change, we ask GTK
+ * to NULL our pointers when they are about to become invalid because the
+ * corresponding widgets don't exist anymore. It's the role of
+ * g_object_add_weak_pointer().
+ * Note that if we don't find the inner widgets (which shouldn't happen), we
+ * fallback to use generic "non-inner" widgets, and they don't need that kind
+ * of weak pointer since they are explicit children of gProtoWindow and as
+ * such GTK holds a strong reference to them. */
+
+static void
+moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget,
+                                          gpointer client_data)
 {
-    if (!gComboBoxEntryWidget) {
-        gComboBoxEntryWidget = gtk_combo_box_entry_new();
-        setup_widget_prototype(gComboBoxEntryWidget);
-    }
-    return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_dropdown_entry_widget()
-{
-    if (!gDropdownEntryWidget) {
-        ensure_combo_box_entry_widget();
-
-        gDropdownEntryWidget = GTK_BIN(gComboBoxEntryWidget)->child;
-        gtk_widget_realize(gDropdownEntryWidget);
-    }
-    return MOZ_GTK_SUCCESS;
+    if (GTK_IS_TOGGLE_BUTTON(widget)) {
+        gDropdownButtonWidget = widget;
+        g_object_add_weak_pointer(G_OBJECT(widget),
+                                  (gpointer) &gDropdownButtonWidget);
+    } else if (GTK_IS_ENTRY(widget)) {
+        gDropdownEntryWidget = widget;
+        g_object_add_weak_pointer(G_OBJECT(widget),
+                                  (gpointer) &gDropdownEntryWidget);
+    } else
+        return;
+    gtk_widget_realize(widget);
 }
 
 static void
-moz_gtk_get_dropdown_button(GtkWidget *widget,
-                            gpointer client_data)
+moz_gtk_get_combo_box_entry_arrow(GtkWidget *widget, gpointer client_data)
+{
+    if (GTK_IS_ARROW(widget)) {
+        gArrowWidget = widget;
+        g_object_add_weak_pointer(G_OBJECT(widget),
+                                  (gpointer) &gArrowWidget);
+        gtk_widget_realize(widget);
+    }
+}
+
+static gint
+ensure_combo_box_entry_widgets()
 {
-    if (GTK_IS_TOGGLE_BUTTON(widget))
-        gDropdownButtonWidget = widget;
+    if (!gDropdownEntryWidget ||
+        !gDropdownButtonWidget ||
+        !gArrowWidget) {
+        GtkWidget* buttonChild;
+
+        /* Create a ComboBoxEntry if needed */
+        if (!gComboBoxEntryWidget) {
+            gComboBoxEntryWidget = gtk_combo_box_entry_new();
+            setup_widget_prototype(gComboBoxEntryWidget);
+        }
+
+        /* Get its inner Entry and Button */
+        gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
+                             moz_gtk_get_combo_box_entry_inner_widgets,
+                             NULL);
+
+        if (!gDropdownEntryWidget) {
+            ensure_entry_widget();
+            gDropdownEntryWidget = gEntryWidget;
+        }
+
+        if (gDropdownButtonWidget) {
+            /* Get the Arrow inside the Button */
+            buttonChild = GTK_BIN(gDropdownButtonWidget)->child;
+            if (GTK_IS_HBOX(buttonChild)) {
+                /* appears-as-list = FALSE, cell-view = TRUE; the button
+                 * contains an hbox. This hbox is there because ComboBoxEntry
+                 * inherits from ComboBox which needs to place a cell renderer,
+                 * a separator, and an arrow in the button when appears-as-list
+                 * is FALSE. Here the hbox should only contain an arrow, since
+                 * a ComboBoxEntry doesn't need all those widgets in the
+                 * button. */
+                gtk_container_forall(GTK_CONTAINER(buttonChild),
+                                     moz_gtk_get_combo_box_entry_arrow,
+                                     NULL);
+            } else if(GTK_IS_ARROW(buttonChild)) {
+                /* appears-as-list = TRUE, or cell-view = FALSE;
+                 * the button only contains an arrow */
+                gArrowWidget = buttonChild;
+                g_object_add_weak_pointer(G_OBJECT(buttonChild),
+                                          (gpointer) &gArrowWidget);
+                gtk_widget_realize(gArrowWidget);
+            }
+        } else {
+            /* Shouldn't be reached with current internal gtk implementation;
+             * we use a generic toggle button as last resort fallback to avoid
+             * crashing. */
+            ensure_toggle_button_widget();
+            gDropdownButtonWidget = gToggleButtonWidget;
+        }
+
+        if (!gArrowWidget) {
+            /* Shouldn't be reached with current internal gtk implementation;
+             * we use a generic down arrow as last resort fallback to avoid
+             * crashing. */
+            gArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+            setup_widget_prototype(gArrowWidget);
+        }
+    }
+    return MOZ_GTK_SUCCESS;
 }
 
+/* Will go away when bug 416003 lands (Use different arrow widgets for
+ * arrows in different context) */
 static gint
 ensure_arrow_widget()
 {
-    if (!gArrowWidget) {
-        ensure_combo_box_entry_widget();
-
-        gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
-                             moz_gtk_get_dropdown_button,
-                             NULL);
-
-        gArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
-        gtk_container_add(GTK_CONTAINER(GTK_BIN(gDropdownButtonWidget)->child),
-                          gArrowWidget);
-        gtk_widget_realize(gArrowWidget);
-    }
+    if (!gArrowWidget)
+        ensure_combo_box_entry_widgets();
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 ensure_handlebox_widget()
 {
     if (!gHandleBoxWidget) {
         gHandleBoxWidget = gtk_handle_box_new();
@@ -670,16 +737,18 @@ moz_gtk_button_paint(GdkDrawable* drawab
 
 gint
 moz_gtk_init()
 {
     is_initialized = TRUE;
     have_menu_shadow_type =
         (gtk_major_version > 2 ||
          (gtk_major_version == 2 && gtk_minor_version >= 1));
+    have_arrow_scaling = (gtk_major_version > 2 ||
+                          (gtk_major_version == 2 && gtk_minor_version >= 12));
 
     return MOZ_GTK_SUCCESS;
 }
 
 gint
 moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing)
 {
     ensure_checkbox_widget();
@@ -849,50 +918,58 @@ moz_gtk_toggle_paint(GdkDrawable* drawab
                             focus_width, focus_height);
         }
     }
 
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
-calculate_arrow_dimensions(GdkRectangle* rect, GdkRectangle* arrow_rect)
+calculate_arrow_dimensions(GdkRectangle* rect, GdkRectangle* arrow_rect,
+                           GtkTextDirection direction)
 {
+    /* defined in gtkarrow.c */
+    gfloat arrow_scaling = 0.7;
+    gfloat xalign, xpad;
+    gint extent;
     GtkMisc* misc = GTK_MISC(gArrowWidget);
 
-    gint extent = MIN(rect->width - misc->xpad * 2,
-                      rect->height - misc->ypad * 2);
-
-    arrow_rect->x = ((rect->x + misc->xpad) * (1.0 - misc->xalign) +
-                     (rect->x + rect->width - extent - misc->xpad) *
-                     misc->xalign);
-
-    arrow_rect->y = ((rect->y + misc->ypad) * (1.0 - misc->yalign) +
-                     (rect->y + rect->height - extent - misc->ypad) *
-                     misc->yalign);
+    if (have_arrow_scaling)
+        gtk_widget_style_get(gArrowWidget,
+                             "arrow_scaling", &arrow_scaling, NULL);
+    extent = MIN((rect->width - misc->xpad * 2),
+                 (rect->height - misc->ypad * 2)) * arrow_scaling;
+
+    xalign = direction == GTK_TEXT_DIR_LTR ? misc->xalign : 1.0 - misc->xalign;
+    xpad = misc->xpad + (rect->width - extent) * xalign;
+
+    arrow_rect->x = direction == GTK_TEXT_DIR_LTR ?
+                        floor(rect->x + xpad) : ceil(rect->x + xpad);
+    arrow_rect->y = floor(rect->y + misc->ypad +
+                          ((rect->height - extent) * misc->yalign));
 
     arrow_rect->width = arrow_rect->height = extent;
 
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
                                GdkRectangle* cliprect, GtkWidgetState* state,
                                GtkScrollbarButtonFlags flags,
                                GtkTextDirection direction)
 {
     GtkStateType state_type = ConvertGtkState(state);
     GtkShadowType shadow_type = (state->active) ?
         GTK_SHADOW_IN : GTK_SHADOW_OUT;
-    GdkRectangle button_rect;
     GdkRectangle arrow_rect;
     GtkStyle* style;
     GtkWidget *scrollbar;
     GtkArrowType arrow_type;
+    gint arrow_displacement_x, arrow_displacement_y;
     const char* detail = (flags & MOZ_GTK_STEPPER_VERTICAL) ?
                            "vscrollbar" : "hscrollbar";
 
     ensure_scrollbar_widget();
 
     if (flags & MOZ_GTK_STEPPER_VERTICAL)
         scrollbar = gVertScrollbarWidget;
     else
@@ -935,30 +1012,36 @@ moz_gtk_scrollbar_button_paint(GdkDrawab
             arrow_type = GTK_ARROW_LEFT;
             if (flags & MOZ_GTK_STEPPER_BOTTOM)
                 scrollbar->allocation.x -= 3 * rect->width;
         }
     }
 
     style = scrollbar->style;
 
-    ensure_arrow_widget();
-  
-    calculate_arrow_dimensions(rect, &button_rect);
-    TSOffsetStyleGCs(style, button_rect.x, button_rect.y);
+    TSOffsetStyleGCs(style, rect->x, rect->y);
 
     gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
-                  scrollbar, detail, button_rect.x, button_rect.y,
-                  button_rect.width, button_rect.height);
-
-    arrow_rect.width = button_rect.width / 2;
-    arrow_rect.height = button_rect.height / 2;
-    arrow_rect.x = button_rect.x + (button_rect.width - arrow_rect.width) / 2;
-    arrow_rect.y = button_rect.y +
-        (button_rect.height - arrow_rect.height) / 2;  
+                  scrollbar, detail, rect->x, rect->y,
+                  rect->width, rect->height);
+
+    arrow_rect.width = rect->width / 2;
+    arrow_rect.height = rect->height / 2;
+    arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
+    arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
+
+    if (state_type == GTK_STATE_ACTIVE) {
+        gtk_widget_style_get(scrollbar,
+                             "arrow-displacement-x", &arrow_displacement_x,
+                             "arrow-displacement-y", &arrow_displacement_y,
+                             NULL);
+
+        arrow_rect.x += arrow_displacement_x;
+        arrow_rect.y += arrow_displacement_y;
+    }
 
     gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
                     scrollbar, detail, arrow_type, TRUE, arrow_rect.x,
                     arrow_rect.y, arrow_rect.width, arrow_rect.height);
 
     return MOZ_GTK_SUCCESS;
 }
 
@@ -1573,62 +1656,72 @@ moz_gtk_downarrow_paint(GdkDrawable* dra
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 moz_gtk_dropdown_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
                              GdkRectangle* cliprect, GtkWidgetState* state,
                              gboolean input_focus, GtkTextDirection direction)
 {
-    const gfloat arrow_scaling = 0.7;
-    gint real_arrow_padding;
+    GtkBorder inner_border;
+    gboolean interior_focus;
+    gint focus_width, focus_pad;
+    gint x_displacement, y_displacement;
     GdkRectangle arrow_rect, real_arrow_rect;
     GtkStateType state_type = ConvertGtkState(state);
     GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
     GtkStyle* style;
 
-    ensure_arrow_widget();
-    ensure_dropdown_entry_widget();
-    gtk_widget_set_direction(gDropdownButtonWidget, direction);
+    ensure_combo_box_entry_widgets();
 
     if (input_focus) {
         /* Some themes draw a complementary focus ring for the dropdown button
          * when the dropdown entry has focus */
         GTK_WIDGET_SET_FLAGS(gDropdownEntryWidget, GTK_HAS_FOCUS);
     }
 
     moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
                          gDropdownButtonWidget, direction);
 
     if (input_focus)
         GTK_WIDGET_UNSET_FLAGS(gDropdownEntryWidget, GTK_HAS_FOCUS);
 
     /* This mirrors gtkbutton's child positioning */
     style = gDropdownButtonWidget->style;
-    arrow_rect.x = rect->x + 1 + XTHICKNESS(style);
-    arrow_rect.y = rect->y + 1 + YTHICKNESS(style);
-    arrow_rect.width = MAX(1, rect->width - (arrow_rect.x - rect->x) * 2);
-    arrow_rect.height = MAX(1, rect->height - (arrow_rect.y - rect->y) * 2);
-
-    calculate_arrow_dimensions(&arrow_rect, &real_arrow_rect);
+
+    moz_gtk_button_get_inner_border(gDropdownButtonWidget, &inner_border);
+    moz_gtk_widget_get_focus(gDropdownButtonWidget, &interior_focus,
+                             &focus_width, &focus_pad);
+
+    arrow_rect.x = rect->x + XTHICKNESS(style) + focus_width + focus_pad;
+    arrow_rect.x += direction == GTK_TEXT_DIR_LTR ?
+                        inner_border.left : inner_border.right;
+    arrow_rect.y = rect->y + inner_border.top + YTHICKNESS(style) +
+                   focus_width + focus_pad;
+    arrow_rect.width = MAX(1, rect->width - inner_border.left -
+       inner_border.right - (XTHICKNESS(style) + focus_pad + focus_width) * 2);
+    arrow_rect.height = MAX(1, rect->height - inner_border.top -
+       inner_border.bottom - (YTHICKNESS(style) + focus_pad + focus_width) * 2);
+
+    if (state_type == GTK_STATE_ACTIVE) {
+        gtk_widget_style_get(gDropdownButtonWidget,
+                             "child-displacement-x", &x_displacement,
+                             "child-displacement-y", &y_displacement,
+                             NULL);
+        arrow_rect.x += x_displacement;
+        arrow_rect.y += y_displacement;
+    }
+
+    calculate_arrow_dimensions(&arrow_rect, &real_arrow_rect, direction);
+
     style = gArrowWidget->style;
     TSOffsetStyleGCs(style, real_arrow_rect.x, real_arrow_rect.y);
 
-    real_arrow_rect.width = real_arrow_rect.height =
-        MIN (real_arrow_rect.width, real_arrow_rect.height) * arrow_scaling;
-
-    real_arrow_padding = floor((arrow_rect.width - real_arrow_rect.width) / 2 + 0.5);
-    real_arrow_rect.x = arrow_rect.x + real_arrow_padding;
-    if (direction == GTK_TEXT_DIR_RTL)
-        real_arrow_rect.x = arrow_rect.x + arrow_rect.width -
-                            real_arrow_rect.width - real_arrow_padding;
-    real_arrow_rect.y = floor (arrow_rect.y + ((arrow_rect.height - real_arrow_rect.height) / 2) + 0.5);
-
     gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
-                    gDropdownButtonWidget, "arrow",  GTK_ARROW_DOWN, TRUE,
+                    gArrowWidget, "arrow",  GTK_ARROW_DOWN, TRUE,
                     real_arrow_rect.x, real_arrow_rect.y,
                     real_arrow_rect.width, real_arrow_rect.height);
 
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 moz_gtk_container_paint(GdkDrawable* drawable, GdkRectangle* rect,
@@ -2400,21 +2493,21 @@ moz_gtk_get_widget_border(GtkThemeWidget
             *bottom += gTreeHeaderCellWidget->style->ythickness;
             return MOZ_GTK_SUCCESS;
         }
     case MOZ_GTK_TREE_HEADER_SORTARROW:
         ensure_tree_header_cell_widget();
         w = gTreeHeaderSortArrowWidget;
         break;
     case MOZ_GTK_DROPDOWN_ENTRY:
-        ensure_dropdown_entry_widget();
+        ensure_combo_box_entry_widgets();
         w = gDropdownEntryWidget;
         break;
     case MOZ_GTK_DROPDOWN_ARROW:
-        ensure_arrow_widget();
+        ensure_combo_box_entry_widgets();
         w = gDropdownButtonWidget;
         break;
     case MOZ_GTK_DROPDOWN:
         {
             /* We need to account for the arrow on the dropdown, so text doesn't
                come too close to the arrow, or in some cases spill into the arrow. */
             gboolean interior_focus;
             GtkRequisition indicator_size;
@@ -2573,30 +2666,27 @@ moz_gtk_get_widget_border(GtkThemeWidget
     *bottom = *top = YTHICKNESS(w->style);
 
     return MOZ_GTK_SUCCESS;
 }
 
 gint
 moz_gtk_get_dropdown_arrow_size(gint* width, gint* height)
 {
-    const gint min_arrow_size = 15;
-    ensure_arrow_widget();
-
     /*
-     * First get the border of the dropdown arrow, then add in the requested
-     * size of the arrow.  Note that the minimum arrow size is fixed at
-     * 15 pixels.
-     */
-
-    *width = 2 * (1 + XTHICKNESS(gDropdownButtonWidget->style));
-    *width += min_arrow_size + GTK_MISC(gArrowWidget)->xpad * 2;
-
-    *height = 2 * (1 + YTHICKNESS(gDropdownButtonWidget->style));
-    *height += min_arrow_size + GTK_MISC(gArrowWidget)->ypad * 2;
+     * We get the requisition of the drop down button, which includes
+     * all padding, border and focus line widths the button uses,
+     * as well as the minimum arrow size and its padding
+     * */
+    GtkRequisition requisition;
+    ensure_combo_box_entry_widgets();
+
+    gtk_widget_size_request(gDropdownButtonWidget, &requisition);
+    *width = requisition.width;
+    *height = requisition.height;
 
     return MOZ_GTK_SUCCESS;
 }
 
 gint
 moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height)
 {
     gint arrow_size;
@@ -2824,17 +2914,17 @@ moz_gtk_widget_paint(GtkThemeWidgetType 
         return moz_gtk_option_menu_paint(drawable, rect, cliprect, state,
                                          direction);
         break;
     case MOZ_GTK_DROPDOWN_ARROW:
         return moz_gtk_dropdown_arrow_paint(drawable, rect, cliprect, state,
                                             flags, direction);
         break;
     case MOZ_GTK_DROPDOWN_ENTRY:
-        ensure_dropdown_entry_widget();
+        ensure_combo_box_entry_widgets();
         return moz_gtk_entry_paint(drawable, rect, cliprect, state,
                                    gDropdownEntryWidget, direction);
         break;
     case MOZ_GTK_CHECKBUTTON_CONTAINER:
     case MOZ_GTK_RADIOBUTTON_CONTAINER:
         return moz_gtk_container_paint(drawable, rect, cliprect, state,
                                        (widget == MOZ_GTK_RADIOBUTTON_CONTAINER),
                                        direction);
--- a/widget/src/gtk2/nsNativeThemeGTK.cpp
+++ b/widget/src/gtk2/nsNativeThemeGTK.cpp
@@ -915,18 +915,19 @@ PRBool
 nsNativeThemeGTK::GetWidgetPadding(nsIDeviceContext* aContext,
                                    nsIFrame* aFrame, PRUint8 aWidgetType,
                                    nsMargin* aResult)
 {
   switch (aWidgetType) {
     case NS_THEME_BUTTON_FOCUS:
     case NS_THEME_TOOLBAR_BUTTON:
     case NS_THEME_TOOLBAR_DUAL_BUTTON:
-    case NS_THEME_TAB_SCROLLARROW_BACK :
+    case NS_THEME_TAB_SCROLLARROW_BACK:
     case NS_THEME_TAB_SCROLLARROW_FORWARD:
+    case NS_THEME_DROPDOWN_BUTTON:
     // Radios and checkboxes return a fixed size in GetMinimumWidgetSize
     // and have a meaningful baseline, so they can't have
     // author-specified padding.
     case NS_THEME_CHECKBOX:
     case NS_THEME_CHECKBOX_SMALL:
     case NS_THEME_RADIO:
     case NS_THEME_RADIO_SMALL:
       aResult->SizeTo(0, 0, 0, 0);
--- a/xpcom/threads/TimerThread.cpp
+++ b/xpcom/threads/TimerThread.cpp
@@ -272,17 +272,33 @@ NS_IMETHODIMP TimerThread::Run()
                     : -(PRInt32)PR_IntervalToMilliseconds(timer->mTimeout-now))
                   );
           }
 #endif
 
           // We are going to let the call to PostTimerEvent here handle the
           // release of the timer so that we don't end up releasing the timer
           // on the TimerThread instead of on the thread it targets.
-          timer->PostTimerEvent();
+          if (NS_FAILED(timer->PostTimerEvent())) {
+            nsrefcnt rc;
+            NS_RELEASE2(timer, rc);
+            
+            // The nsITimer interface requires that its users keep a reference
+            // to the timers they use while those timers are initialized but
+            // have not yet fired.  If this ever happens, it is a bug in the
+            // code that created and used the timer.
+            //
+            // Further, note that this should never happen even with a
+            // misbehaving user, because nsTimerImpl::Release checks for a
+            // refcount of 1 with an armed timer (a timer whose only reference
+            // is from the timer thread) and when it hits this will remove the
+            // timer from the timer thread and thus destroy the last reference,
+            // preventing this situation from occurring.
+            NS_ASSERTION(rc != 0, "destroyed timer off its target thread!");
+          }
           timer = nsnull;
 
           lock.lock();
           if (mShutdown)
             break;
 
           // Update now, as PostTimerEvent plus the locking may have taken a
           // tick or two, and we may goto next below.
@@ -324,17 +340,17 @@ NS_IMETHODIMP TimerThread::Run()
 
 nsresult TimerThread::AddTimer(nsTimerImpl *aTimer)
 {
   nsAutoLock lock(mLock);
 
   // Add the timer to our list.
   PRInt32 i = AddTimerInternal(aTimer);
   if (i < 0)
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_OUT_OF_MEMORY;
 
   // Awaken the timer thread.
   if (mCondVar && mWaiting && i == 0)
     PR_NotifyCondVar(mCondVar);
 
   return NS_OK;
 }
 
--- a/xpcom/threads/nsTimerImpl.cpp
+++ b/xpcom/threads/nsTimerImpl.cpp
@@ -445,28 +445,30 @@ void nsTimerImpl::Fire()
 
 class nsTimerEvent : public nsRunnable {
 public:
   NS_IMETHOD Run();
 
   nsTimerEvent(nsTimerImpl *timer, PRInt32 generation)
     : mTimer(timer), mGeneration(generation) {
     // timer is already addref'd for us
+    MOZ_COUNT_CTOR(nsTimerEvent);
   }
 
 #ifdef DEBUG_TIMERS
   PRIntervalTime mInitTime;
 #endif
 
 private:
   ~nsTimerEvent() { 
 #ifdef DEBUG
     if (mTimer)
       NS_WARNING("leaking reference to nsTimerImpl");
 #endif
+    MOZ_COUNT_DTOR(nsTimerEvent);
   }
 
   nsTimerImpl *mTimer;
   PRInt32      mGeneration;
 };
 
 NS_IMETHODIMP nsTimerEvent::Run()
 {
@@ -485,44 +487,50 @@ NS_IMETHODIMP nsTimerEvent::Run()
   }
 #endif
 
   timer->Fire();
 
   return NS_OK;
 }
 
-void nsTimerImpl::PostTimerEvent()
+nsresult nsTimerImpl::PostTimerEvent()
 {
   // XXX we may want to reuse this nsTimerEvent in the case of repeating timers.
 
   // Since TimerThread addref'd 'this' for us, we don't need to addref here.
   // We will release in destroyMyEvent.  We need to copy the generation number
   // from this timer into the event, so we can avoid firing a timer that was
   // re-initialized after being canceled.
 
-  nsTimerEvent* event = new nsTimerEvent(this, mGeneration);
+  nsRefPtr<nsTimerEvent> event = new nsTimerEvent(this, mGeneration);
   if (!event)
-    return;
+    return NS_ERROR_OUT_OF_MEMORY;
 
 #ifdef DEBUG_TIMERS
   if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
     event->mInitTime = PR_IntervalNow();
   }
 #endif
 
   // If this is a repeating precise timer, we need to calculate the time for
   // the next timer to fire before we make the callback.
   if (mType == TYPE_REPEATING_PRECISE) {
     SetDelayInternal(mDelay);
-    if (gThread)
-      gThread->AddTimer(this);
+    if (gThread) {
+      nsresult rv = gThread->AddTimer(this);
+      if (NS_FAILED(rv))
+        return rv;
+    }
   }
 
-  mCallingThread->Dispatch(event, NS_DISPATCH_NORMAL);
+  nsresult rv = mCallingThread->Dispatch(event, NS_DISPATCH_NORMAL);
+  if (NS_FAILED(rv) && gThread)
+    gThread->RemoveTimer(this);
+  return rv;
 }
 
 void nsTimerImpl::SetDelayInternal(PRUint32 aDelay)
 {
   PRIntervalTime delayInterval = PR_MillisecondsToInterval(aDelay);
   if (delayInterval > DELAY_INTERVAL_MAX) {
     delayInterval = DELAY_INTERVAL_MAX;
     aDelay = PR_IntervalToMilliseconds(delayInterval);
--- a/xpcom/threads/nsTimerImpl.h
+++ b/xpcom/threads/nsTimerImpl.h
@@ -39,17 +39,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsTimerImpl_h___
 #define nsTimerImpl_h___
 
 //#define FORCE_PR_LOG /* Allow logging in the release build */
 
 #include "nsITimer.h"
-#include "nsVoidArray.h"
 #include "nsIThread.h"
 #include "nsIObserver.h"
 
 #include "nsCOMPtr.h"
 
 #include "prlog.h"
 
 #if defined(PR_LOGGING)
@@ -91,17 +90,17 @@ public:
   nsTimerImpl();
 
   static NS_HIDDEN_(nsresult) Startup();
   static NS_HIDDEN_(void) Shutdown();
 
   friend class TimerThread;
 
   void Fire();
-  void PostTimerEvent();
+  nsresult PostTimerEvent();
   void SetDelayInternal(PRUint32 aDelay);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSITIMER
 
   PRInt32 GetGeneration() { return mGeneration; }
 
 private: