Merging mozilla-central to Places.
authorShawn Wilsher <me@shawnwilsher.com>
Fri, 29 Oct 2010 11:39:41 -0700
changeset 59318 b3e9f47ca21fcec72bd825cb9e86035b47b5f2c3
parent 59317 165b1dfdd63911d1e34946ccd75d86427b846aaf (current diff)
parent 56684 3b73e3b886531fae356cbbeebcf5d70023cff7f9 (diff)
child 59319 b926caf698b23d612f57bc3a2fc922d067acd04b
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
milestone2.0b8pre
Merging mozilla-central to Places.
js/src/jit-test/README
js/src/jit-test/tests/basic/bug557841.js
js/src/jit-test/tests/basic/bug579740.js
js/src/jit-test/tests/basic/bug584499-1.js
js/src/jit-test/tests/basic/bug584499-2.js
js/src/jit-test/tests/basic/call2.js
js/src/jit-test/tests/basic/testPutOnEmptyArgsObject.js
js/src/jit-test/tests/jaeger/bug554580-5.js
js/src/jit-test/tests/jaeger/bug555155.js
js/src/jit-test/tests/jaeger/bug555543.js
js/src/jit-test/tests/jaeger/bug556525.js
js/src/jit-test/tests/jaeger/bug573433.js
js/src/jit-test/tests/jaeger/bug580884.js
js/src/jit-test/tests/jaeger/bug582286.js
js/src/jit-test/tests/jaeger/bug583158.js
js/src/jit-test/tests/jaeger/bug585341.js
js/src/jit-test/tests/jaeger/bug588338.js
js/src/jit-test/tests/jaeger/bug588363-2.js
js/src/jit-test/tests/jaeger/crash-on-compare.js
js/src/jit-test/tests/jaeger/fused-eq-ifeq.js
js/src/jit-test/tests/sunspider/check-3d-morph.js
js/src/jit-test/tests/sunspider/check-3d-raytrace.js
js/src/jit-test/tests/sunspider/check-access-binary-trees.js
js/src/jit-test/tests/sunspider/check-access-fannkuch.js
js/src/jit-test/tests/sunspider/check-access-nbody.js
js/src/jit-test/tests/sunspider/check-access-nsieve.js
js/src/jit-test/tests/sunspider/check-bitops-3bit-bits-in-byte.js
js/src/jit-test/tests/sunspider/check-bitops-bits-in-byte.js
js/src/jit-test/tests/sunspider/check-bitops-bitwise-and.js
js/src/jit-test/tests/sunspider/check-bitops-nsieve-bits.js
js/src/jit-test/tests/sunspider/check-controlflow-recursive.js
js/src/jit-test/tests/sunspider/check-date-format-tofte.js
js/src/jit-test/tests/sunspider/check-mont.js
js/src/tests/js1_8_1/jit/browser.js
js/src/tests/js1_8_1/jit/regress-458838.js
js/src/tests/js1_8_1/jit/regress-462459-01.js
js/src/tests/js1_8_1/jit/regress-462459-02.js
js/src/tests/js1_8_1/jit/regress-462459-03.js
js/src/tests/js1_8_1/jit/regress-462459-04.js
js/src/tests/js1_8_1/jit/regress-462459-05.js
js/src/tests/js1_8_1/jit/regress-462459-06.js
js/src/tests/js1_8_1/jit/regress-462459-07.js
js/src/tests/js1_8_1/jit/regress-462459-08.js
js/src/tests/js1_8_1/jit/regress-462459-09.js
js/src/tests/js1_8_1/jit/regress-462459-10.js
js/src/tests/js1_8_1/jit/regress-462459-11.js
js/src/tests/js1_8_1/jit/regress-462459-12.js
js/src/tests/js1_8_1/jit/regress-471635.js
services/crypto/modules/threaded.js
toolkit/components/places/src/History.cpp
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -86,24 +86,16 @@ nsAccDocManager::FindAccessibleInCache(n
   arg.mNode = aNode;
 
   mDocAccessibleCache.EnumerateRead(SearchAccessibleInDocCache,
                                     static_cast<void*>(&arg));
 
   return arg.mAccessible;
 }
 
-void
-nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocument *aDocument)
-{
-  nsCOMPtr<nsISupports> container = aDocument->GetContainer();
-  nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(container);
-  ShutdownDocAccessiblesInTree(treeItem, aDocument);
-}
-
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccDocManager protected
 
 PRBool
 nsAccDocManager::Init()
 {
   mDocAccessibleCache.Init(4);
@@ -127,31 +119,16 @@ nsAccDocManager::Shutdown()
     do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
 
   if (progress)
     progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this));
 
   ClearDocCache();
 }
 
-void
-nsAccDocManager::ShutdownDocAccessible(nsIDocument *aDocument)
-{
-  nsDocAccessible* docAccessible = mDocAccessibleCache.GetWeak(aDocument);
-  if (!docAccessible)
-    return;
-
-  // We're allowed to not remove listeners when accessible document is shutdown
-  // since we don't keep strong reference on chrome event target and listeners
-  // are removed automatically when chrome event target goes away.
-
-  docAccessible->Shutdown();
-  mDocAccessibleCache.Remove(aDocument);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
 NS_IMPL_THREADSAFE_ISUPPORTS3(nsAccDocManager,
                               nsIWebProgressListener,
                               nsIDOMEventListener,
                               nsISupportsWeakReference)
 
@@ -311,17 +288,24 @@ nsAccDocManager::HandleEvent(nsIDOMEvent
     NS_LOG_ACCDOCDESTROY("received 'pagehide' event", document)
 
     // Ignore 'pagehide' on temporary documents since we ignore them entirely in
     // accessibility.
     if (document->IsInitialDocument())
       return NS_OK;
 
     // Shutdown this one and sub document accessibles.
-    ShutdownDocAccessiblesInTree(document);
+
+    // We're allowed to not remove listeners when accessible document is
+    // shutdown since we don't keep strong reference on chrome event target and
+    // listeners are removed automatically when chrome event target goes away.
+    nsDocAccessible* docAccessible = mDocAccessibleCache.GetWeak(document);
+    if (docAccessible)
+      docAccessible->Shutdown();
+
     return NS_OK;
   }
 
   // XXX: handle error pages loading separately since they get neither
   // webprogress notifications nor 'pageshow' event.
   if (type.EqualsLiteral("DOMContentLoaded") &&
       nsCoreUtils::IsErrorPage(document)) {
     NS_LOG_ACCDOCLOAD2("handled 'DOMContentLoaded' event", document)
@@ -495,45 +479,16 @@ nsAccDocManager::CreateDocOrRootAccessib
   }
 
   NS_LOG_ACCDOCCREATE("document creation finished", aDocument)
 
   AddListeners(aDocument, isRootDoc);
   return docAcc;
 }
 
-void
-nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem,
-                                              nsIDocument *aDocument)
-{
-  nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(aTreeItem));
-
-  if (treeNode) {
-    PRInt32 subDocumentsCount = 0;
-    treeNode->GetChildCount(&subDocumentsCount);
-    for (PRInt32 idx = 0; idx < subDocumentsCount; idx++) {
-      nsCOMPtr<nsIDocShellTreeItem> treeItemChild;
-      treeNode->GetChildAt(idx, getter_AddRefs(treeItemChild));
-      NS_ASSERTION(treeItemChild, "No tree item when there should be");
-      if (!treeItemChild)
-        continue;
-
-      nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(treeItemChild));
-      nsCOMPtr<nsIContentViewer> contentViewer;
-      docShell->GetContentViewer(getter_AddRefs(contentViewer));
-      if (!contentViewer)
-        continue;
-
-      ShutdownDocAccessiblesInTree(treeItemChild, contentViewer->GetDocument());
-    }
-  }
-
-  ShutdownDocAccessible(aDocument);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccDocManager static
 
 PLDHashOperator
 nsAccDocManager::ClearDocCacheEntry(const nsIDocument* aKey,
                                     nsRefPtr<nsDocAccessible>& aDocAccessible,
                                     void* aUserArg)
 {
--- a/accessible/src/base/nsAccDocManager.h
+++ b/accessible/src/base/nsAccDocManager.h
@@ -71,48 +71,44 @@ public:
 
   /**
    * Search through all document accessibles for an accessible with the given
    * unique id.
    */
   nsAccessible* FindAccessibleInCache(nsINode* aNode) const;
 
   /**
-   * Shutdown document accessibles in the tree starting from the given one.
-   *
-   * @param  aDocument  [in] the DOM document of start document accessible
-   */
-  void ShutdownDocAccessiblesInTree(nsIDocument *aDocument);
-
-  /**
    * Return document accessible from the cache. Convenient method for testing.
    */
   inline nsDocAccessible* GetDocAccessibleFromCache(nsIDocument* aDocument) const
   {
     return mDocAccessibleCache.GetWeak(aDocument);
   }
 
+  /**
+   * Called by document accessible when it gets shutdown.
+   */
+  inline void NotifyOfDocumentShutdown(nsIDocument* aDocument)
+  {
+    mDocAccessibleCache.Remove(aDocument);
+  }
+
 protected:
   nsAccDocManager() { };
 
   /**
    * Initialize the manager.
    */
   PRBool Init();
 
   /**
    * Shutdown the manager.
    */
   void Shutdown();
 
-  /**
-   * Shutdown the document accessible.
-   */
-  void ShutdownDocAccessible(nsIDocument* aDocument);
-
 private:
   nsAccDocManager(const nsAccDocManager&);
   nsAccDocManager& operator =(const nsAccDocManager&);
 
 private:
   /**
    * Create an accessible document if it was't created and fire accessibility
    * events if needed.
@@ -151,22 +147,16 @@ private:
    */
   void AddListeners(nsIDocument *aDocument, PRBool aAddPageShowListener);
 
   /**
    * Create document or root accessible.
    */
   nsDocAccessible *CreateDocOrRootAccessible(nsIDocument *aDocument);
 
-  /**
-   * Shutdown document accessibles in the tree starting from given tree item.
-   */
-  void ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem,
-                                    nsIDocument *aDocument);
-
   typedef nsRefPtrHashtable<nsPtrHashKey<const nsIDocument>, nsDocAccessible>
     nsDocAccessibleHashtable;
 
   /**
    * Shutdown and remove the document accessible from cache.
    */
   static PLDHashOperator
     ClearDocCacheEntry(const nsIDocument* aKey,
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -377,17 +377,18 @@ nsAccessNode::ScrollTo(PRUint32 aScrollT
   nsIFrame *frame = GetFrame();
   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIContent> content = frame->GetContent();
   NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
 
   PRInt16 vPercent, hPercent;
   nsCoreUtils::ConvertScrollTypeToPercents(aScrollType, &vPercent, &hPercent);
-  return shell->ScrollContentIntoView(content, vPercent, hPercent);
+  return shell->ScrollContentIntoView(content, vPercent, hPercent,
+                                      nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
 }
 
 NS_IMETHODIMP
 nsAccessNode::ScrollToPoint(PRUint32 aCoordinateType, PRInt32 aX, PRInt32 aY)
 {
   nsIFrame *frame = GetFrame();
   if (!frame)
     return NS_ERROR_FAILURE;
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -538,17 +538,20 @@ nsAccessibilityService::PresShellDestroy
   // pagehide event for the iframe's underlying document and its presshell is
   // destroyed before we're notified styles were changed. Shutdown the document
   // accessible early.
   nsIDocument* doc = aPresShell->GetDocument();
   if (!doc)
     return;
 
   NS_LOG_ACCDOCDESTROY("presshell destroyed", doc)
-  ShutdownDocAccessible(doc);
+
+  nsDocAccessible* docAccessible = GetDocAccessibleFromCache(doc);
+  if (docAccessible)
+    docAccessible->Shutdown();
 }
 
 void
 nsAccessibilityService::RecreateAccessible(nsIPresShell* aPresShell,
                                            nsIContent* aContent)
 {
   nsDocAccessible* document = GetDocAccessible(aPresShell->GetDocument());
   if (document)
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -2363,17 +2363,18 @@ nsAccessible::DispatchClickEvent(nsICont
 {
   if (IsDefunct())
     return;
 
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
 
   // Scroll into view.
   presShell->ScrollContentIntoView(aContent, NS_PRESSHELL_SCROLL_ANYWHERE,
-                                   NS_PRESSHELL_SCROLL_ANYWHERE);
+                                   NS_PRESSHELL_SCROLL_ANYWHERE,
+                                   nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
 
   // Fire mouse down and mouse up events.
   PRBool res = nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,
                                                aContent);
   if (!res)
     return;
 
   nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, presShell, aContent);
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -670,27 +670,33 @@ nsDocAccessible::Shutdown()
   if (mParent) {
     nsDocAccessible* parentDocument = mParent->GetDocAccessible();
     if (parentDocument)
       parentDocument->RemoveChildDocument(this);
 
     mParent->RemoveChild(this);
   }
 
+  PRUint32 childDocCount = mChildDocuments.Length();
+  for (PRUint32 idx = 0; idx < childDocCount; idx++)
+    mChildDocuments[idx]->Shutdown();
+
   mChildDocuments.Clear();
 
   mWeakShell = nsnull;  // Avoid reentrancy
 
   mNodeToAccessibleMap.Clear();
   ClearCache(mAccessibleCache);
 
   nsCOMPtr<nsIDocument> kungFuDeathGripDoc = mDocument;
   mDocument = nsnull;
 
   nsHyperTextAccessibleWrap::Shutdown();
+
+  GetAccService()->NotifyOfDocumentShutdown(kungFuDeathGripDoc);
 }
 
 nsIFrame*
 nsDocAccessible::GetFrame()
 {
   nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
 
   nsIFrame* root = nsnull;
--- a/accessible/src/base/nsOuterDocAccessible.cpp
+++ b/accessible/src/base/nsOuterDocAccessible.cpp
@@ -164,17 +164,17 @@ nsOuterDocAccessible::Shutdown()
   // any to avoid hanging document accessible.
   NS_LOG_ACCDOCDESTROY_MSG("A11y outerdoc shutdown")
   NS_LOG_ACCDOCDESTROY_ACCADDRESS("outerdoc", this)
 
   nsAccessible *childAcc = mChildren.SafeElementAt(0, nsnull);
   if (childAcc) {
     NS_LOG_ACCDOCDESTROY("outerdoc's child document shutdown",
                          childAcc->GetDocumentNode())
-    GetAccService()->ShutdownDocAccessiblesInTree(childAcc->GetDocumentNode());
+    childAcc->Shutdown();
   }
 
   nsAccessibleWrap::Shutdown();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible public
 
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -821,22 +821,17 @@
 <deck flex="1" id="tab-view-deck">
 <vbox flex="1">
 
   <toolbox id="navigator-toolbox"
            defaultmode="icons" mode="icons"
 #ifdef WINCE
            defaulticonsize="small" iconsize="small"
 #endif
-#ifdef XP_WIN
            tabsontop="true"
-#endif
-#ifdef XP_MACOSX
-           tabsontop="true"
-#endif
            persist="tabsontop">
     <!-- Menu -->
     <toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
              defaultset="menubar-items"
              mode="icons" iconsize="small" defaulticonsize="small"
              lockiconsize="true"
 #ifdef MENUBAR_CAN_AUTOHIDE
              toolbarname="&menubarCmd.label;"
--- a/content/base/src/CSPUtils.jsm
+++ b/content/base/src/CSPUtils.jsm
@@ -375,18 +375,17 @@ CSPRep.prototype = {
         return false;
       }
     }
     return (this.allowsInlineScripts === that.allowsInlineScripts)
         && (this.allowsEvalInScripts === that.allowsEvalInScripts);
   },
 
   /**
-   * Generates string representation of the policy.  Should be fairly similar
-   * to the original.
+   * Generates canonical string representation of the policy.
    */
   toString:
   function csp_toString() {
     var dirs = [];
 
     if (this._allowEval || this._allowInlineScripts) {
       dirs.push("options " + (this._allowEval ? "eval-script" : "")
                            + (this._allowInlineScripts ? "inline-script" : ""));
@@ -602,18 +601,17 @@ CSPSourceList.prototype = {
       if (!a_sorted[i].equals(b_sorted[i])) {
         return false;
       }
     }
     return true;
   },
 
   /**
-   * Generates string representation of the Source List.
-   * Should be fairly similar to the original.
+   * Generates canonical string representation of the Source List.
    */
   toString:
   function() {
     if (this.isNone()) {
       return "'none'";
     }
     if (this._permitAllSources) {
       return "*";
@@ -634,17 +632,17 @@ CSPSourceList.prototype = {
    * Returns whether or not this source list permits all sources (*).
    */
   isAll:
   function() {
     return this._permitAllSources;
   },
 
   /**
-   * Makes a new instance that resembles this object.
+   * Makes a new deep copy of this object.
    * @returns
    *      a new CSPSourceList
    */
   clone:
   function() {
     var aSL = new CSPSourceList();
     aSL._permitAllSources = this._permitAllSources;
     for (var i in this._sources) {
@@ -946,17 +944,17 @@ CSPSource.fromString = function(aStr, se
     // is the first bit a scheme?
     else if (CSPSource.validSchemeName(chunks[0])) {
       sObj._scheme = chunks[0];
       // then the second bit *must* be a host or empty
       if (chunks[1] === "") {
         // Allow scheme-only sources!  These default to wildcard host/port,
         // especially since host and port don't always matter.
         // Example: "javascript:" and "data:" 
-        if (!sObj._host) sObj._host = "*";
+        if (!sObj._host) sObj._host = CSPHost.fromString("*");
         if (!sObj._port) sObj._port = "*";
       } else {
         // some host was defined.
         // ... remove <= 3 leading slashes (from the scheme) and parse
         var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
         // ... and parse
         sObj._host = CSPHost.fromString(cleanHost);
         if (!sObj._host) {
@@ -1045,18 +1043,17 @@ CSPSource.prototype = {
     }
     // if there was no scheme (and thus no default scheme), return self.port
     if (this._self && this._self.port) return this._self.port;
 
     return undefined;
   },
 
   /**
-   * Generates string representation of the Source.
-   * Should be fairly similar to the original.
+   * Generates canonical string representation of the Source.
    */
   toString:
   function() {
     if (this._isSelf) 
       return this._self.toString();
 
     var s = "";
     if (this._scheme)
@@ -1064,17 +1061,17 @@ CSPSource.prototype = {
     if (this._host)
       s = s + this._host;
     if (this._port)
       s = s + ":" + this._port;
     return s;
   },
 
   /**
-   * Makes a new instance that resembles this object.
+   * Makes a new deep copy of this object.
    * @returns
    *      a new CSPSource
    */
   clone:
   function() {
     var aClone = new CSPSource();
     aClone._self = this._self ? this._self.clone() : undefined;
     aClone._scheme = this._scheme;
@@ -1167,23 +1164,38 @@ CSPSource.prototype = {
     else if (that._scheme === this._scheme)
       newSource._scheme = this._scheme;
     else {
       CSPError("Could not intersect " + this + " with " + that
                + " due to scheme problems.");
       return null;
     }
 
+    // NOTE: Both sources must have a host, if they don't, something funny is
+    // going on.  The fromString() factory method should have set the host to
+    // * if there's no host specified in the input. Regardless, if a host is
+    // not present either the scheme is hostless or any host should be allowed.
+    // This means we can use the other source's host as the more restrictive
+    // host expression, or if neither are present, we can use "*", but the
+    // error should still be reported.
+
     // host
-    if (!this._host)
-      newSource._host = that._host;
-    else if (!that._host)
-      newSource._host = this._host;
-    else // both this and that have hosts
+    if (this._host && that._host) {
       newSource._host = this._host.intersectWith(that._host);
+    } else if (this._host) {
+      CSPError("intersecting source with undefined host: " + that.toString());
+      newSource._host = this._host.clone();
+    } else if (that._host) {
+      CSPError("intersecting source with undefined host: " + this.toString());
+      newSource._host = that._host.clone();
+    } else {
+      CSPError("intersecting two sources with undefined hosts: " +
+               this.toString() + " and " + that.toString());
+      newSource._host = CSPHost.fromString("*");
+    }
 
     return newSource;
   },
 
   /**
    * Compares one CSPSource to another.
    *
    * @param that
@@ -1261,26 +1273,25 @@ CSPHost.fromString = function(aStr) {
       return null;
     }
   }
   return hObj;
 };
 
 CSPHost.prototype = {
   /**
-   * Generates string representation of the Source.
-   * Should be fairly similar to the original.
+   * Generates canonical string representation of the Host.
    */
   toString:
   function() {
     return this._segments.join(".");
   },
 
   /**
-   * Makes a new instance that resembles this object.
+   * Makes a new deep copy of this object.
    * @returns
    *      a new CSPHost
    */
   clone:
   function() {
     var aHost = new CSPHost();
     for (var i in this._segments) {
       aHost._segments[i] = this._segments[i];
@@ -1292,17 +1303,17 @@ CSPHost.prototype = {
    * Returns true if this host accepts the provided host (or the other way
    * around).
    * @param aHost
    *        the FQDN in question (CSPHost or String)
    * @returns
    */
   permits:
   function(aHost) {
-    if (!aHost) return false;
+    if (!aHost) aHost = CSPHost.fromString("*");
 
     if (!(aHost instanceof CSPHost)) {
       // -- compare CSPHost to String
       return this.permits(CSPHost.fromString(aHost));
     }
     var thislen = this._segments.length;
     var thatlen = aHost._segments.length;
 
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -5320,17 +5320,17 @@ nsGenericElement::PostHandleEventForLink
           if (fm) {
             nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
             fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOUSE |
                                nsIFocusManager::FLAG_NOSCROLL);
           }
 
           nsIEventStateManager* esm =
             aVisitor.mPresContext->EventStateManager();
-          nsEventStateManager::SetGlobalActiveContent(
+          nsEventStateManager::SetActiveManager(
             static_cast<nsEventStateManager*>(esm), this);
         }
       }
     }
     break;
 
   case NS_MOUSE_CLICK:
     if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
--- a/content/base/test/unit/test_csputils.js
+++ b/content/base/test/unit/test_csputils.js
@@ -30,16 +30,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 //load('CSPUtils.jsm');
 Components.utils.import('resource://gre/modules/CSPUtils.jsm');
+Components.utils.import('resource://gre/modules/NetUtil.jsm');
 
 // load the HTTP server
 do_load_httpd_js();
 
 var httpServer = new nsHttpServer();
 
 const POLICY_FROM_URI = "allow 'self'; img-src *";
 const POLICY_PORT = 9000;
@@ -185,16 +186,17 @@ test(
       do_check_neq(null, CSPSource.fromString("*.a.com"));
 
       //print(" --- Ignore the following two errors if they print ---");
       //"wildcard should not work in non-first token for host.");
       do_check_eq(null, CSPSource.fromString("x.*.a.com"));
 
       //"funny characters (#) should not work for host.");
       do_check_eq(null, CSPSource.fromString("a#2-c.com"));
+
       //print(" --- Stop ignoring errors that print ---\n");
 
       //"failed to parse host with port.");
       do_check_neq(null, CSPSource.create("a.com:23"));
       //"failed to parse host with scheme.");
       do_check_neq(null, CSPSource.create("https://a.com"));
       //"failed to parse host with scheme and port.");
       do_check_neq(null, CSPSource.create("https://a.com:200"));
@@ -224,16 +226,26 @@ test(
       //"src should inherit port *
       do_check_true(src.permits("https://foobar.com:443"));
       //"src should inherit and require https scheme
       do_check_false(src.permits("http://foobar.com"));
       //"src should inherit scheme 'https'"
       do_check_true(src.permits("https://foobar.com"));
       //"src should reject other hosts"
       do_check_false(src.permits("https://a.com"));
+
+      src = CSPSource.create("javascript:", "https://foobar.com:443");
+      //"hostless schemes should be parseable."
+      var aUri = NetUtil.newURI("javascript:alert('foo');");
+      do_check_true(src.permits(aUri));
+      //"src should reject other hosts"
+      do_check_false(src.permits("https://a.com"));
+      //"nothing else should be allowed"
+      do_check_false(src.permits("https://foobar.com"));
+
     });
 
 ///////////////////// Test the source list //////////////////////
 
 test(
     function test_CSPSourceList_fromString() {
       var sd = CSPSourceList.fromString("'none'");
       //"'none' -- should parse"
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -2069,16 +2069,17 @@ nsEventStateManager::GenerateDragGesture
       // draggesture events, make it read only so that the data doesn't
       // change during the drag.
       dataTransfer->SetReadOnly();
 
       if (status != nsEventStatus_eConsumeNoDefault) {
         PRBool dragStarted = DoDefaultDragStart(aPresContext, event, dataTransfer,
                                                 targetContent, isSelection);
         if (dragStarted) {
+          sActiveESM = nsnull;
           aEvent->flags |= NS_EVENT_FLAG_STOP_DISPATCH;
         }
       }
 
       // Note that frame event handling doesn't care about NS_DRAGDROP_GESTURE,
       // which is just as well since we don't really know which frame to
       // send it to
 
@@ -2930,29 +2931,29 @@ nsEventStateManager::PostHandleEvent(nsP
           // to obtain our parent element and put it into :active
           // instead.
           nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(activeContent));
           if (!elt) {
             nsIContent* par = activeContent->GetParent();
             if (par)
               activeContent = par;
           }
-          SetGlobalActiveContent(this, activeContent);
         }
       }
       else {
         // if we're here, the event handler returned false, so stop
         // any of our own processing of a drag. Workaround for bug 43258.
         StopTrackingDragGesture();
       }
+      SetActiveManager(this, activeContent);
     }
     break;
   case NS_MOUSE_BUTTON_UP:
     {
-      ClearGlobalActiveContent();
+      ClearGlobalActiveContent(this);
       if (IsMouseEventReal(aEvent)) {
         if (!mCurrentTarget) {
           nsIFrame* targ;
           GetEventTarget(&targ);
         }
         if (mCurrentTarget) {
           ret = CheckForAndDispatchClick(presContext, (nsMouseEvent*)aEvent,
                                          aStatus);
@@ -3201,16 +3202,17 @@ nsEventStateManager::PostHandleEvent(nsP
 
         nsEventStatus status = nsEventStatus_eIgnore;
         nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
         if (presShell) {
           presShell->HandleEventWithTarget(&event, mCurrentTarget,
                                            targetContent, &status);
         }
       }
+      ClearGlobalActiveContent(this);
       break;
     }
   case NS_DRAGDROP_EXIT:
      // make sure to fire the enter and exit_synth events after the
      // NS_DRAGDROP_EXIT event, otherwise we'll clean up too early
     GenerateDragDropEnterExit(presContext, (nsGUIEvent*)aEvent);
     break;
 
@@ -4701,28 +4703,31 @@ nsEventStateManager::DoContentCommandScr
   }
 
   // The caller may want synchronous scrolling.
   sf->ScrollBy(pt, scrollUnit, nsIScrollableFrame::INSTANT);
   return NS_OK;
 }
 
 void
-nsEventStateManager::SetGlobalActiveContent(nsEventStateManager* aNewESM,
-                                            nsIContent* aContent)
+nsEventStateManager::SetActiveManager(nsEventStateManager* aNewESM,
+                                      nsIContent* aContent)
 {
   if (sActiveESM && aNewESM != sActiveESM) {
     sActiveESM->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE);
   }
   sActiveESM = aNewESM;
-  if (sActiveESM) {
+  if (sActiveESM && aContent) {
     sActiveESM->SetContentState(aContent, NS_EVENT_STATE_ACTIVE);
   }
 }
 
 void
-nsEventStateManager::ClearGlobalActiveContent()
+nsEventStateManager::ClearGlobalActiveContent(nsEventStateManager* aClearer)
 {
-  if (sActiveESM) {
+  if (aClearer) {
+    aClearer->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE);
+  }
+  if (sActiveESM && aClearer != sActiveESM) {
     sActiveESM->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE);
   }
   sActiveESM = nsnull;
 }
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -154,18 +154,20 @@ public:
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsEventStateManager,
                                            nsIEventStateManager)
 
   static nsIDocument* sMouseOverDocument;
 
   static nsIEventStateManager* GetActiveEventStateManager() { return sActiveESM; }
 
-  static void SetGlobalActiveContent(nsEventStateManager* aNewESM,
-                                     nsIContent* aContent);
+  // Sets aNewESM to be the active event state manager, and
+  // if aContent is non-null, marks the object as active.
+  static void SetActiveManager(nsEventStateManager* aNewESM,
+                               nsIContent* aContent);
 protected:
   void UpdateCursor(nsPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus);
   /**
    * Turn a GUI mouse event into a mouse event targeted at the specified
    * content.  This returns the primary frame for the content (or null
    * if it goes away during the event).
    */
   nsIFrame* DispatchMouseEvent(nsGUIEvent* aEvent, PRUint32 aMessage,
@@ -410,17 +412,17 @@ protected:
   PRPackedBool mLastLineScrollConsumedY;
 
   static PRInt32 sUserInputEventDepth;
   
   static PRBool sNormalLMouseEventInProcess;
 
   static nsEventStateManager* sActiveESM;
   
-  static void ClearGlobalActiveContent();
+  static void ClearGlobalActiveContent(nsEventStateManager* aClearer);
 
   // Functions used for click hold context menus
   PRBool mClickHoldContextMenu;
   nsCOMPtr<nsITimer> mClickHoldTimer;
   void CreateClickHoldTimer ( nsPresContext* aPresContext, nsIFrame* inDownFrame,
                               nsGUIEvent* inMouseDownEvent ) ;
   void KillClickHoldTimer ( ) ;
   void FireContextClick ( ) ;
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -803,17 +803,18 @@ nsGenericHTMLElement::ScrollIntoView(PRB
   if (!optional_argc) {
     aTop = PR_TRUE;
   }
 
   PRIntn vpercent = aTop ? NS_PRESSHELL_SCROLL_TOP :
     NS_PRESSHELL_SCROLL_BOTTOM;
 
   presShell->ScrollContentIntoView(this, vpercent,
-                                   NS_PRESSHELL_SCROLL_ANYWHERE);
+                                   NS_PRESSHELL_SCROLL_ANYWHERE,
+                                   nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGenericHTMLElement::GetSpellcheck(PRBool* aSpellcheck)
 {
   NS_ENSURE_ARG_POINTER(aSpellcheck);
--- a/content/html/content/src/nsHTMLButtonElement.cpp
+++ b/content/html/content/src/nsHTMLButtonElement.cpp
@@ -434,17 +434,17 @@ nsHTMLButtonElement::PostHandleEvent(nsE
       case NS_MOUSE_BUTTON_DOWN:
         {
           if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT) {
             if (static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
                   nsMouseEvent::eLeftButton) {
               if (NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) {
                 nsIEventStateManager* esm =
                   aVisitor.mPresContext->EventStateManager();
-                nsEventStateManager::SetGlobalActiveContent(
+                nsEventStateManager::SetActiveManager(
                   static_cast<nsEventStateManager*>(esm), this);
               }
               nsIFocusManager* fm = nsFocusManager::GetFocusManager();
               if (fm)
                 fm->SetFocus(this, nsIFocusManager::FLAG_BYMOUSE |
                                    nsIFocusManager::FLAG_NOSCROLL);
               aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
             } else if (static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -231,12 +231,14 @@ include $(topsrcdir)/config/rules.mk
 		test_bug557087-5.html \
 		test_bug557087-6.html \
 		test_bug586763.html \
 		test_bug598643.html \
 		test_bug596350.html \
 		test_bug600155.html \
 		test_bug556007.html \
 		test_bug606817.html \
+		test_bug297761.html \
+		file_bug297761.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/file_bug297761.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <base href="http://www.mozilla.org/">
+  </head>
+  <body>
+    <form action="">
+      <input type='submit' formaction="">
+      <button type='submit' formaction=""></button>
+      <input id='i' type='image' formaction="">
+    </form>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug297761.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=297761
+-->
+<head>
+  <title>Test for Bug 297761</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=297761">Mozilla Bug 297761</a>
+<p id="display"></p>
+<div id="content">
+  <iframe src="file_bug297761.html"></iframe>
+  <iframe src="file_bug297761.html"></iframe>
+  <iframe src="file_bug297761.html"></iframe>
+  <iframe src="file_bug297761.html"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 297761 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var nbTests = 4;
+var curTest = 0;
+
+function nextTest()
+{
+  if (curTest == 3) {
+    frames[curTest].document.forms[0].submit();
+  } else {
+    var el = null;
+    if (curTest == 2) {
+      el = frames[curTest].document.getElementById('i');
+    } else {
+      el = frames[curTest].document.forms[0].elements[curTest];
+    }
+
+    el.focus();
+    el.click();
+  }
+}
+
+function frameLoaded(aFrame)
+{
+  var documentLocation = location.href.replace(/\.html.*/, "\.html");
+  is(aFrame.contentWindow.location.href.replace(/\?x=0&y=0/, ""),
+     documentLocation.replace(/test_bug/, "file_bug"),
+     "form should have been submitted to the document location");
+
+  if (++curTest == nbTests) {
+    SimpleTest.finish();
+  } else {
+    nextTest();
+  }
+}
+
+function runTest()
+{
+  // Initialize event handlers.
+  var frames = document.getElementsByTagName('iframe');
+  for (var i=0; i<nbTests; ++i) {
+    frames[i].setAttribute('onload', "frameLoaded(this);");
+  }
+
+  nextTest();
+}
+
+addLoadEvent(runTest);
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/html/content/test/test_bug392567.html
+++ b/content/html/content/test/test_bug392567.html
@@ -17,64 +17,75 @@ https://bugzilla.mozilla.org/show_bug.cg
     <input type="text" name="key" />
   </form>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 392567 **/
 
-var dataUrl = "http://mochi.test:8888/tests/content/html/content/test/bug392567.jar";
-var jarUrl = "jar:" + dataUrl + "!/index.html";
-var httpUrl = location.href.replace(/\.html.*/, "_404");
-var previousDir = location.href.replace(/test\/[^\/]*$/, "");
-
-var form = document.forms.testForm;
-var frame = frames.testFrame;
-document.getElementById("testFrame").onload = processTestResult;
+SimpleTest.waitForExplicitFinish();
 
-// List of tests to run, each test consists of form action URL and expected result URL
-var tests = [
-  [jarUrl, jarUrl + "?$PARAMS", null],
-  [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null],
-  [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null],
-  ["data:text/html,<html></html>", "data:text/html,<html></html>?$PARAMS", null],
-  ["data:text/html,<html>How%20about%20this?</html>", "data:text/html,<html>How%20about%20this?$PARAMS", null],
-  [httpUrl, httpUrl + "?$PARAMS", null],
-  [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ],
-  [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null],
-  ["", jarUrl + "?key=value0", null],
-  [" ", jarUrl + "?key=value0", document.location],
-  ["../", previousDir + "?$PARAMS", previousDir],
-];
-
-var currentTest = -1;
-
-SimpleTest.waitForExplicitFinish(); 
-runNextTest();
-
-function runNextTest() {
-  currentTest++;
-  if (currentTest >= tests.length) {
-    SimpleTest.finish();
+function runTests()
+{
+  if (window.location.search.match(/\?key=value/)) {
     return;
   }
 
-  form.setAttribute("action", tests[currentTest][0]);
-  is(form.action, tests[currentTest][0],
-     "action IDL attribute should reflect the action content attribute");
-  is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0],
-     "mozActionUri IDL attribute should resolve the action URI");
-  form.key.value = "value" + currentTest;
-  form.submit();
+  var dataUrl = "http://mochi.test:8888/tests/content/html/content/test/bug392567.jar";
+  var jarUrl = "jar:" + dataUrl + "!/index.html";
+  var httpUrl = location.href.replace(/\.html.*/, "_404");
+  var previousDir = location.href.replace(/test\/[^\/]*$/, "");
+  var documentURL = location.href.replace(/\.html.*/, "\.html");
+
+  var form = document.forms.testForm;
+  var frame = frames.testFrame;
+  document.getElementById("testFrame").onload = processTestResult;
+
+  // List of tests to run, each test consists of form action URL and expected result URL
+  var tests = [
+    [jarUrl, jarUrl + "?$PARAMS", null],
+    [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null],
+    [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null],
+    ["data:text/html,<html></html>", "data:text/html,<html></html>?$PARAMS", null],
+    ["data:text/html,<html>How%20about%20this?</html>", "data:text/html,<html>How%20about%20this?$PARAMS", null],
+    [httpUrl, httpUrl + "?$PARAMS", null],
+    [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ],
+    [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null],
+    ["", documentURL + "?$PARAMS", null],
+    [" ", documentURL + "?$PARAMS", document.location],
+    ["../", previousDir + "?$PARAMS", previousDir],
+  ];
+
+  var currentTest = -1;
+
+  runNextTest();
+
+  function runNextTest() {
+    currentTest++;
+    if (currentTest >= tests.length) {
+      SimpleTest.finish();
+      return;
+    }
+
+    form.setAttribute("action", tests[currentTest][0]);
+    is(form.action, tests[currentTest][0],
+       "action IDL attribute should reflect the action content attribute");
+    is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0],
+       "mozActionUri IDL attribute should resolve the action URI");
+    form.key.value = "value" + currentTest;
+    form.submit();
+  }
+
+  function processTestResult() {
+    var expected = tests[currentTest][1].replace(/\$PARAMS/, "key=value" + currentTest);
+    is(frame.location.href, expected, "Submitting to " + tests[currentTest][0]);
+
+    setTimeout(runNextTest, 0);
+  }
 }
 
-function processTestResult() {
-  var expected = tests[currentTest][1].replace(/\$PARAMS/, "key=value" + currentTest);
-  is(frame.location.href, expected, "Submitting to " + tests[currentTest][0]);
-
-  setTimeout(runNextTest, 0);
-}
+addLoadEvent(runTests);
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/xul/document/src/nsXULPrototypeCache.cpp
+++ b/content/xul/document/src/nsXULPrototypeCache.cpp
@@ -140,16 +140,17 @@ NS_NewXULPrototypeCache(nsISupports* aOu
     nsresult rv = result->QueryInterface(aIID, aResult);
 
     nsCOMPtr<nsIObserverService> obsSvc =
         mozilla::services::GetObserverService();
     if (obsSvc && NS_SUCCEEDED(rv)) {
         nsXULPrototypeCache *p = result;
         obsSvc->AddObserver(p, "chrome-flush-skin-caches", PR_FALSE);
         obsSvc->AddObserver(p, "chrome-flush-caches", PR_FALSE);
+        obsSvc->AddObserver(p, "startupcache-invalidate", PR_FALSE);
     }
 
     return rv;
 }
 
 /* static */ nsXULPrototypeCache*
 nsXULPrototypeCache::GetInstance()
 {
@@ -405,50 +406,59 @@ static PRBool gChecksumXULFastLoadFile =
 
 void
 nsXULPrototypeCache::AbortFastLoads()
 {
 #ifdef DEBUG_brendan
     NS_BREAK();
 #endif
 
-    // Save a strong ref to the FastLoad file, so we can remove it after we
-    // close open streams to it.
-    nsCOMPtr<nsIFile> file = gFastLoadFile;
-
     // Flush the XUL cache for good measure, in case we cached a bogus/downrev
     // script, somehow.
     Flush();
 
     // Clear the FastLoad set
     mFastLoadURITable.Clear();
 
-    if (! gFastLoadService)
-        return;
+    nsCOMPtr<nsIFastLoadService> fastLoadService = gFastLoadService;
+    nsCOMPtr<nsIFile> file = gFastLoadFile;
+
+    nsresult rv;
+
+    if (! fastLoadService) {
+        fastLoadService = do_GetFastLoadService();
+        if (! fastLoadService)
+            return;
+
+        rv = fastLoadService->NewFastLoadFile(XUL_FASTLOAD_FILE_BASENAME,
+                                              getter_AddRefs(file));
+        if (NS_FAILED(rv))
+            return;
+    }
 
     // Fetch the current input (if FastLoad file existed) or output (if we're
     // creating the FastLoad file during this app startup) stream.
     nsCOMPtr<nsIObjectInputStream> objectInput;
     nsCOMPtr<nsIObjectOutputStream> objectOutput;
-    gFastLoadService->GetInputStream(getter_AddRefs(objectInput));
-    gFastLoadService->GetOutputStream(getter_AddRefs(objectOutput));
+    fastLoadService->GetInputStream(getter_AddRefs(objectInput));
+    fastLoadService->GetOutputStream(getter_AddRefs(objectOutput));
 
     if (objectOutput) {
-        gFastLoadService->SetOutputStream(nsnull);
+        fastLoadService->SetOutputStream(nsnull);
 
         if (NS_SUCCEEDED(objectOutput->Close()) && gChecksumXULFastLoadFile)
-            gFastLoadService->CacheChecksum(gFastLoadFile,
-                                            objectOutput);
+            fastLoadService->CacheChecksum(file,
+                                           objectOutput);
     }
 
     if (objectInput) {
         // If this is the last of one or more XUL master documents loaded
         // together at app startup, close the FastLoad service's singleton
         // input stream now.
-        gFastLoadService->SetInputStream(nsnull);
+        fastLoadService->SetInputStream(nsnull);
         objectInput->Close();
     }
 
     // Now rename or remove the file.
     if (file) {
 #ifdef DEBUG
         // Remove any existing Aborted.mfasl files generated in previous runs.
         nsCOMPtr<nsIFile> existingAbortedFile;
@@ -457,23 +467,25 @@ nsXULPrototypeCache::AbortFastLoads()
             existingAbortedFile->SetLeafName(NS_LITERAL_STRING("Aborted.mfasl"));
             PRBool fileExists = PR_FALSE;
             existingAbortedFile->Exists(&fileExists);
             if (fileExists)
                 existingAbortedFile->Remove(PR_FALSE);
         }
         file->MoveToNative(nsnull, NS_LITERAL_CSTRING("Aborted.mfasl"));
 #else
-        file->Remove(PR_FALSE);
+        rv = file->Remove(PR_FALSE);
+        if (NS_FAILED(rv))
+            NS_WARNING("Failed to remove fastload file, fastload data may be outdated");
 #endif
     }
 
     // If the list is empty now, the FastLoad process is done.
-    NS_RELEASE(gFastLoadService);
-    NS_RELEASE(gFastLoadFile);
+    NS_IF_RELEASE(gFastLoadService);
+    NS_IF_RELEASE(gFastLoadFile);
 }
 
 
 void
 nsXULPrototypeCache::RemoveFromFastLoadSet(nsIURI* aURI)
 {
     mFastLoadURITable.Remove(aURI);
 }
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -1795,17 +1795,18 @@ void
 nsFocusManager::ScrollIntoView(nsIPresShell* aPresShell,
                                nsIContent* aContent,
                                PRUint32 aFlags)
 {
   // if the noscroll flag isn't set, scroll the newly focused element into view
   if (!(aFlags & FLAG_NOSCROLL))
     aPresShell->ScrollContentIntoView(aContent,
                                       NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
-                                      NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
+                                      NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
+                                      nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
 }
 
 
 void
 nsFocusManager::RaiseWindow(nsPIDOMWindow* aWindow)
 {
   // don't raise windows that are already raised or are in the process of
   // being lowered
--- a/dom/plugins/PluginInstanceChild.cpp
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -1047,17 +1047,16 @@ PluginInstanceChild::CreatePluginWindow(
                        WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0,
                        0, 0, NULL, 0, GetModuleHandle(NULL), 0);
     if (!mPluginWindowHWND)
         return false;
     if (!SetProp(mPluginWindowHWND, kPluginInstanceChildProperty, this))
         return false;
 
     // Apparently some plugins require an ASCII WndProc.
-    printf("setting DefWindowProcA\n");
     SetWindowLongPtrA(mPluginWindowHWND, GWLP_WNDPROC,
                       reinterpret_cast<LONG_PTR>(DefWindowProcA));
 
     return true;
 }
 
 void
 PluginInstanceChild::DestroyPluginWindow()
--- a/embedding/android/CrashReporter.java.in
+++ b/embedding/android/CrashReporter.java.in
@@ -52,16 +52,17 @@ import java.util.*;
 import java.io.*;
 import java.net.*;
 import java.nio.channels.*;
 
 public class CrashReporter extends Activity
 {
   static final String kMiniDumpPathKey = "upload_file_minidump";
   static final String kPageURLKey = "URL";
+  static final String kNotesKey = "Notes";
   ProgressDialog mProgressDialog;
   File mPendingMinidumpFile;
   File mPendingExtrasFile;
   HashMap<String, String> mExtrasStringMap;
 
   boolean moveFile(File inFile, File outFile)
   {
     Log.i("GeckoCrashReporter", "moving " + inFile + " to " + outFile);
@@ -225,20 +226,45 @@ public class CrashReporter extends Activ
 
       OutputStream os = conn.getOutputStream();
       Iterator<String> keys = extras.keySet().iterator();
       while (keys.hasNext()) {
         String key = keys.next();
         if (key.equals(kPageURLKey)) {
           if (includeURLCheckbox.isChecked())
             sendPart(os, boundary, key, extras.get(key));
-        } else if (!key.equals("ServerURL")){
+        } else if (!key.equals("ServerURL") && !key.equals(kNotesKey)) {
           sendPart(os, boundary, key, extras.get(key));
         }
       }
+
+      // Add some extra information to notes so its displayed by 
+      // crash-stats.mozilla.org. Remove this when bug 607942 is fixed.
+      String notes = extras.containsKey(kNotesKey) ? extras.get(kNotesKey) + 
+        "\n" : "";
+      if (@MOZ_MIN_CPU_VERSION@ < 7)
+        notes += "nothumb Build\n";
+      notes += Build.MANUFACTURER + " ";
+      notes += Build.MODEL + "\n";
+      notes += Build.FINGERPRINT;
+      sendPart(os, boundary, kNotesKey, notes);
+
+      sendPart(os, boundary, "Min_ARM_Version", "@MOZ_MIN_CPU_VERSION@");
+      sendPart(os, boundary, "Android_Manufacturer", Build.MANUFACTURER);
+      sendPart(os, boundary, "Android_Model", Build.MODEL);
+      sendPart(os, boundary, "Android_Board", Build.BOARD);
+      sendPart(os, boundary, "Android_Brand", Build.BRAND);
+      sendPart(os, boundary, "Android_CPU_ABI", Build.CPU_ABI); 
+      sendPart(os, boundary, "Android_CPU_ABI2", Build.CPU_ABI2);
+      sendPart(os, boundary, "Android_Device", Build.DEVICE);
+      sendPart(os, boundary, "Android_Display", Build.DISPLAY);
+      sendPart(os, boundary, "Android_Fingerprint", Build.FINGERPRINT);
+      sendPart(os, boundary, "Android_Hardware", Build.HARDWARE);
+      sendPart(os, boundary, "Android_Version",  Build.VERSION.SDK_INT + " (" + Build.VERSION.CODENAME + ")");
+
       sendFile(os, boundary, kMiniDumpPathKey, minidumpFile);
       os.write(("\r\n--" + boundary + "--\r\n").getBytes());
       os.flush();
       os.close();
       BufferedReader br = new BufferedReader(
         new InputStreamReader(conn.getInputStream()));
       HashMap<String, String>  responseMap = new HashMap<String, String>();
       readStringsFromReader(br, responseMap);
--- a/gfx/thebes/gfxQtPlatform.cpp
+++ b/gfx/thebes/gfxQtPlatform.cpp
@@ -76,17 +76,21 @@
 #include FT_FREETYPE_H
 #endif
 
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 
 // Because the QPainter backend has some problems with glyphs rendering
 // it is better to use image or xlib cairo backends by default
+#if (MOZ_PLATFORM_MAEMO == 6)
 #define DEFAULT_RENDER_MODE RENDER_BUFFERED
+#else
+#define DEFAULT_RENDER_MODE RENDER_DIRECT
+#endif
 
 static QPaintEngine::Type sDefaultQtPaintEngineType = QPaintEngine::X11;
 gfxFontconfigUtils *gfxQtPlatform::sFontconfigUtils = nsnull;
 static cairo_user_data_key_t cairo_qt_pixmap_key;
 static void do_qt_pixmap_unref (void *data)
 {
     QPixmap *pmap = (QPixmap*)data;
     delete pmap;
@@ -141,16 +145,19 @@ gfxQtPlatform::gfxQtPlatform()
 
     switch (ival) {
         case 0:
             mRenderMode = RENDER_QPAINTER;
             break;
         case 1:
             mRenderMode = RENDER_BUFFERED;
             break;
+        case 2:
+            mRenderMode = RENDER_DIRECT;
+            break;
         default:
             mRenderMode = RENDER_QPAINTER;
     }
 
     // Qt doesn't provide a public API to detect the graphicssystem type. We hack
     // around this by checking what type of graphicssystem a test QPixmap uses.
     QPixmap pixmap(1, 1);
     sDefaultQtPaintEngineType = pixmap.paintEngine()->type();
@@ -202,17 +209,17 @@ gfxQtPlatform::CreateOffscreenSurface(co
 
 #ifdef CAIRO_HAS_QT_SURFACE
     if (mRenderMode == RENDER_QPAINTER) {
       newSurface = new gfxQPainterSurface(size, imageFormat);
       return newSurface.forget();
     }
 #endif
 
-    if (mRenderMode == RENDER_BUFFERED &&
+    if ((mRenderMode == RENDER_BUFFERED || mRenderMode == RENDER_DIRECT) &&
         sDefaultQtPaintEngineType != QPaintEngine::X11) {
       newSurface = new gfxImageSurface(size, imageFormat);
       return newSurface.forget();
     }
 
 #ifdef MOZ_X11
     XRenderPictFormat* xrenderFormat =
         gfxXlibSurface::FindRenderFormat(QX11Info().display(), imageFormat);
--- a/gfx/thebes/gfxQtPlatform.h
+++ b/gfx/thebes/gfxQtPlatform.h
@@ -55,16 +55,18 @@ class FontEntry;
 class THEBES_API gfxQtPlatform : public gfxPlatform {
 public:
 
     enum RenderMode {
         /* Use QPainter surfaces */
         RENDER_QPAINTER = 0,
         /* Use offscreen buffer for rendering with image or xlib gfx backend */
         RENDER_BUFFERED,
+        /* Direct rendering to Widget surface */
+        RENDER_DIRECT,
         /* max */
         RENDER_MODE_MAX
     };
 
     gfxQtPlatform();
     virtual ~gfxQtPlatform();
 
     static gfxQtPlatform *GetPlatform() {
--- a/gfx/thebes/gfxWindowsNativeDrawing.cpp
+++ b/gfx/thebes/gfxWindowsNativeDrawing.cpp
@@ -85,35 +85,39 @@ gfxWindowsNativeDrawing::BeginNativeDraw
         // redirect rendering to our own HDC; in some cases,
         // we may be able to use the HDC from the surface directly.
         if ((surf->GetType() == gfxASurface::SurfaceTypeWin32 ||
              surf->GetType() == gfxASurface::SurfaceTypeWin32Printing) &&
             (surf->GetContentType() == gfxASurface::CONTENT_COLOR ||
              (surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA &&
               (mNativeDrawFlags & CAN_DRAW_TO_COLOR_ALPHA))))
         {
-            if (mTransformType == TRANSLATION_ONLY) {
-                mRenderState = RENDER_STATE_NATIVE_DRAWING;
+            // grab the DC. This can fail if there is a complex clipping path,
+            // in which case we'll have to fall back.
+            mWinSurface = static_cast<gfxWindowsSurface*>(static_cast<gfxASurface*>(surf.get()));
+            mDC = mWinSurface->GetDCWithClip(mContext);
 
-                mTranslation = m.GetTranslation();
+            if (mDC) {
+                if (mTransformType == TRANSLATION_ONLY) {
+                    mRenderState = RENDER_STATE_NATIVE_DRAWING;
 
-                mWinSurface = static_cast<gfxWindowsSurface*>(static_cast<gfxASurface*>(surf.get()));
-            } else if (((mTransformType == AXIS_ALIGNED_SCALE)
-                        && (mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) ||
-                       (mNativeDrawFlags & CAN_COMPLEX_TRANSFORM))
-            {
-                mWorldTransform.eM11 = (FLOAT) m.xx;
-                mWorldTransform.eM12 = (FLOAT) m.yx;
-                mWorldTransform.eM21 = (FLOAT) m.xy;
-                mWorldTransform.eM22 = (FLOAT) m.yy;
-                mWorldTransform.eDx  = (FLOAT) m.x0;
-                mWorldTransform.eDy  = (FLOAT) m.y0;
+                    mTranslation = m.GetTranslation();
+                } else if (((mTransformType == AXIS_ALIGNED_SCALE)
+                            && (mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) ||
+                           (mNativeDrawFlags & CAN_COMPLEX_TRANSFORM))
+                {
+                    mWorldTransform.eM11 = (FLOAT) m.xx;
+                    mWorldTransform.eM12 = (FLOAT) m.yx;
+                    mWorldTransform.eM21 = (FLOAT) m.xy;
+                    mWorldTransform.eM22 = (FLOAT) m.yy;
+                    mWorldTransform.eDx  = (FLOAT) m.x0;
+                    mWorldTransform.eDy  = (FLOAT) m.y0;
 
-                mRenderState = RENDER_STATE_NATIVE_DRAWING;
-                mWinSurface = static_cast<gfxWindowsSurface*>(static_cast<gfxASurface*>(surf.get()));
+                    mRenderState = RENDER_STATE_NATIVE_DRAWING;
+                }
             }
         }
 
         // If we couldn't do native drawing, then we have to do two-buffer drawing
         // and do alpha recovery
         if (mRenderState == RENDER_STATE_INIT) {
             mRenderState = RENDER_STATE_ALPHA_RECOVERY_BLACK;
 
@@ -151,19 +155,16 @@ gfxWindowsNativeDrawing::BeginNativeDraw
                 mTempSurfaceSize.height = (PRInt32) NS_ceil(mNativeRect.size.height * mScale.height + 1);
             }
         }
     }
 
     if (mRenderState == RENDER_STATE_NATIVE_DRAWING) {
         // we can just do native drawing directly to the context's surface
 
-        // grab the DC
-        mDC = mWinSurface->GetDCWithClip(mContext);
-
         // do we need to use SetWorldTransform?
         if (mTransformType != TRANSLATION_ONLY) {
             SetGraphicsMode(mDC, GM_ADVANCED);
             GetWorldTransform(mDC, &mOldWorldTransform);
             SetWorldTransform(mDC, &mWorldTransform);
         }
 
 #ifdef WINCE
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -99,28 +99,16 @@ js_GetStringChars(JSContext *cx, JSStrin
     if (!js_MakeStringImmutable(cx, str))
         return NULL;
     return str->flatChars();
 }
 
 void
 JSString::flatten()
 {
-    // Diagnostic: serialize all calls to this function to see
-    // if concurrent calls are crashing us.
-    JS_LOCK_RUNTIME(asCell()->compartment()->rt);
-    // The main body of this function can be executed only if
-    // the string is a rope. With multiple threads, it's possible
-    // we waited while another one ran, and the string has
-    // already been flattened for us.
-    if (!isRope()) {
-        JS_UNLOCK_RUNTIME(asCell()->compartment()->rt);
-        return;
-    }
-
     JSString *topNode;
     jschar *chars;
     size_t capacity;
     JS_ASSERT(isRope());
 
     /*
      * This can be called from any string in the rope, so first traverse to the
      * top node.
@@ -188,18 +176,16 @@ JSString::flatten()
             JS_NOT_REACHED("bad traversal count");
         }
     }
 
     JS_ASSERT(pos == length);
     /* Set null terminator. */
     chars[pos] = 0;
     topNode->initFlatMutable(chars, pos, capacity);
-
-    JS_UNLOCK_RUNTIME(asCell()->compartment()->rt);
 }
 
 #ifdef JS_TRACER
 
 int32 JS_FASTCALL
 js_Flatten(JSString* str)
 {
     str->flatten();
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -250,17 +250,17 @@ JSWrapper::hasInstance(JSContext *cx, JS
 }
 
 JSString *
 JSWrapper::obj_toString(JSContext *cx, JSObject *wrapper)
 {
     JSString *str;
     if (!enter(cx, wrapper, JSID_VOID, GET))
         return NULL;
-    str = JSProxyHandler::obj_toString(cx, wrapper);
+    str = obj_toStringHelper(cx, wrappedObject(wrapper));
     leave(cx, wrapper);
     return str;
 }
 
 JSString *
 JSWrapper::fun_toString(JSContext *cx, JSObject *wrapper, uintN indent)
 {
     JSString *str;
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -1619,16 +1619,18 @@ DocumentViewerImpl::Destroy()
   }
 
   if (mPresContext) {
     mPresContext->SetContainer(nsnull);
     mPresContext->SetLinkHandler(nsnull);
     mPresContext = nsnull;
   }
 
+  mWindow = nsnull;
+  mViewManager = nsnull;
   mContainer = nsnull;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DocumentViewerImpl::Stop(void)
 {
@@ -2674,17 +2676,18 @@ NS_IMETHODIMP DocumentViewerImpl::Scroll
    // get the primary frame
 
    nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
    NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
 
    // Tell the PresShell to scroll to the primary frame of the content.
    NS_ENSURE_SUCCESS(presShell->ScrollContentIntoView(content,
                                                       NS_PRESSHELL_SCROLL_TOP,
-                                                      NS_PRESSHELL_SCROLL_ANYWHERE),
+                                                      NS_PRESSHELL_SCROLL_ANYWHERE,
+                                                      nsIPresShell::SCROLL_OVERFLOW_HIDDEN),
                      NS_ERROR_FAILURE);
    return NS_OK;
 }
 
 void
 DocumentViewerImpl::CallChildren(CallChildFunc aFunc, void* aClosure)
 {
   nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryReferent(mContainer));
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -17,16 +17,17 @@
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1998
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Steve Clark <buster@netscape.com>
  *   Dan Rosen <dr@netscape.com>
+ *   Mihai Șucan <mihai.sucan@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -134,18 +135,18 @@ typedef struct CapturingContentInfo {
   nsIContent* mContent;
 
   CapturingContentInfo() :
     mAllowed(PR_FALSE), mRetargetToElement(PR_FALSE), mPreventDrag(PR_FALSE),
     mContent(nsnull) { }
 } CapturingContentInfo;
 
 #define NS_IPRESSHELL_IID     \
- { 0xb79574cd, 0x2555, 0x4b57, \
-    { 0xb3, 0xf8, 0x27, 0x57, 0x3e, 0x60, 0x74, 0x01 } }
+ { 0xd1978bee, 0x43b9, 0x40de, \
+    { 0x95, 0x47, 0x85, 0x06, 0x5e, 0x02, 0xec, 0xb4 } }
 
 // Constants for ScrollContentIntoView() function
 #define NS_PRESSHELL_SCROLL_TOP      0
 #define NS_PRESSHELL_SCROLL_BOTTOM   100
 #define NS_PRESSHELL_SCROLL_LEFT     0
 #define NS_PRESSHELL_SCROLL_RIGHT    100
 #define NS_PRESSHELL_SCROLL_CENTER   50
 #define NS_PRESSHELL_SCROLL_ANYWHERE -1
@@ -539,20 +540,28 @@ public:
    *                  100 (NS_PRESSHELL_SCROLL_RIGHT) means the frame's right
    *                  edge is aligned with the right edge of the visible area.
    *                  For values in between, the point "aVPercent" across the frame
    *                  is placed at the point "aVPercent" across the visible area.
    *                  A value of 50 (NS_PRESSHELL_SCROLL_CENTER) centers the frame
    *                  horizontally . A value of NS_PRESSHELL_SCROLL_ANYWHERE means move
    *                  the frame the minimum amount necessary in order for the entire
    *                  frame to be visible horizontally (if possible)
+   * @param aFlags    If SCROLL_FIRST_ANCESTOR_ONLY is set, only the nearest
+   *                  scrollable ancestor is scrolled, otherwise all
+   *                  scrollable ancestors may be scrolled if necessary.
+   *                  If SCROLL_OVERFLOW_HIDDEN is set then we may scroll in a
+   *                  direction even if overflow:hidden is specified in that
+   *                  direction; otherwise we will not scroll in that direction
+   *                  when overflow:hidden is set for that direction.
    */
   virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent,
                                                      PRIntn      aVPercent,
-                                                     PRIntn      aHPercent) = 0;
+                                                     PRIntn      aHPercent,
+                                                     PRUint32    aFlags) = 0;
 
   enum {
     SCROLL_FIRST_ANCESTOR_ONLY = 0x01,
     SCROLL_OVERFLOW_HIDDEN = 0x02
   };
   /**
    * Scrolls the view of the document so that the given area of a frame
    * is visible, if possible. Layout is not flushed before scrolling.
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -21,16 +21,17 @@
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Steve Clark <buster@netscape.com>
  *   Håkan Waara <hwaara@chello.se>
  *   Dan Rosen <dr@netscape.com>
  *   Daniel Glazman <glazman@netscape.com>
  *   Mats Palmgren <matspal@gmail.com>
+ *   Mihai Șucan <mihai.sucan@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -768,17 +769,18 @@ public:
 
   virtual NS_HIDDEN_(void) ClearFrameRefs(nsIFrame* aFrame);
   virtual NS_HIDDEN_(already_AddRefed<nsIRenderingContext>) GetReferenceRenderingContext();
   virtual NS_HIDDEN_(nsresult) GoToAnchor(const nsAString& aAnchorName, PRBool aScroll);
   virtual NS_HIDDEN_(nsresult) ScrollToAnchor();
 
   virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent,
                                                      PRIntn      aVPercent,
-                                                     PRIntn      aHPercent);
+                                                     PRIntn      aHPercent,
+                                                     PRUint32    aFlags);
   virtual PRBool ScrollFrameRectIntoView(nsIFrame*     aFrame,
                                          const nsRect& aRect,
                                          PRIntn        aVPercent,
                                          PRIntn        aHPercent,
                                          PRUint32      aFlags);
   virtual nsRectVisibility GetRectVisibility(nsIFrame *aFrame,
                                              const nsRect &aRect,
                                              nscoord aMinTwips) const;
@@ -1000,17 +1002,18 @@ protected:
 #ifdef DEBUG
   void DoVerifyReflow();
   void VerifyHasDirtyRootAncestor(nsIFrame* aFrame);
 #endif
 
   // Helper for ScrollContentIntoView
   void DoScrollContentIntoView(nsIContent* aContent,
                                PRIntn      aVPercent,
-                               PRIntn      aHPercent);
+                               PRIntn      aHPercent,
+                               PRUint32    aFlags);
 
   friend struct AutoRenderingStateSaveRestore;
   friend struct RenderingState;
 
   struct RenderingState {
     RenderingState(PresShell* aPresShell) 
       : mRenderFlags(aPresShell->mRenderFlags)
       , mDisplayPort(aPresShell->mDisplayPort)
@@ -3901,17 +3904,18 @@ PresShell::GoToAnchor(const nsAString& a
 
 #ifdef ACCESSIBILITY
   nsIContent *anchorTarget = content;
 #endif
 
   if (content) {
     if (aScroll) {
       rv = ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_TOP,
-                                 NS_PRESSHELL_SCROLL_ANYWHERE);
+                                 NS_PRESSHELL_SCROLL_ANYWHERE,
+                                 SCROLL_OVERFLOW_HIDDEN);
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsIScrollableFrame* rootScroll = GetRootScrollFrameAsScrollable();
       if (rootScroll) {
         mLastAnchorScrolledTo = content;
         mLastAnchorScrollPositionY = rootScroll->GetScrollPosition().y;
       }
     }
@@ -4008,17 +4012,18 @@ PresShell::ScrollToAnchor()
   NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
 
   nsIScrollableFrame* rootScroll = GetRootScrollFrameAsScrollable();
   if (!rootScroll ||
       mLastAnchorScrollPositionY != rootScroll->GetScrollPosition().y)
     return NS_OK;
 
   nsresult rv = ScrollContentIntoView(mLastAnchorScrolledTo, NS_PRESSHELL_SCROLL_TOP,
-                                      NS_PRESSHELL_SCROLL_ANYWHERE);
+                                      NS_PRESSHELL_SCROLL_ANYWHERE,
+                                      SCROLL_OVERFLOW_HIDDEN);
   mLastAnchorScrolledTo = nsnull;
   return rv;
 }
 
 /*
  * Helper (per-continuation) for ScrollContentIntoView.
  *
  * @param aContainerFrame [in] the frame which aRect is relative to
@@ -4191,17 +4196,18 @@ static void ScrollToShowRect(nsIScrollab
   }
 
   aScrollFrame->ScrollTo(scrollPt, nsIScrollableFrame::INSTANT);
 }
 
 nsresult
 PresShell::ScrollContentIntoView(nsIContent* aContent,
                                  PRIntn      aVPercent,
-                                 PRIntn      aHPercent)
+                                 PRIntn      aHPercent,
+                                 PRUint32    aFlags)
 {
   nsCOMPtr<nsIContent> content = aContent; // Keep content alive while flushing.
   NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsIDocument> currentDoc = content->GetCurrentDoc();
   NS_ENSURE_STATE(currentDoc);
 
   NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
 
@@ -4216,25 +4222,26 @@ PresShell::ScrollContentIntoView(nsICont
   // (or suppressed it altogether because we're suppressing interruptible
   // flushes right now) and won't necessarily get the position correct, but do
   // a best-effort scroll here.  The other option would be to do this inside
   // FlushPendingNotifications, but I'm not sure the repeated scrolling that
   // could trigger if reflows keep getting interrupted would be more desirable
   // than a single best-effort scroll followed by one final scroll on the first
   // completed reflow.
   if (mContentToScrollTo) {
-    DoScrollContentIntoView(content, aVPercent, aHPercent);
+    DoScrollContentIntoView(content, aVPercent, aHPercent, aFlags);
   }
   return NS_OK;
 }
 
 void
 PresShell::DoScrollContentIntoView(nsIContent* aContent,
                                    PRIntn      aVPercent,
-                                   PRIntn      aHPercent)
+                                   PRIntn      aHPercent,
+                                   PRUint32    aFlags)
 {
   NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
 
   nsIFrame* frame = aContent->GetPrimaryFrame();
   if (!frame) {
     mContentToScrollTo = nsnull;
     return;
   }
@@ -4267,17 +4274,17 @@ PresShell::DoScrollContentIntoView(nsICo
   PRBool haveRect = PR_FALSE;
   PRBool useWholeLineHeightForInlines = aVPercent != NS_PRESSHELL_SCROLL_ANYWHERE;
   do {
     AccumulateFrameBounds(container, frame, useWholeLineHeightForInlines,
                           frameBounds, haveRect);
   } while ((frame = frame->GetNextContinuation()));
 
   ScrollFrameRectIntoView(container, frameBounds, aVPercent, aHPercent,
-                          SCROLL_OVERFLOW_HIDDEN);
+                          aFlags);
 }
 
 PRBool
 PresShell::ScrollFrameRectIntoView(nsIFrame*     aFrame,
                                    const nsRect& aRect,
                                    PRIntn        aVPercent,
                                    PRIntn        aHPercent,
                                    PRUint32      aFlags)
@@ -4868,17 +4875,18 @@ PresShell::FlushPendingNotifications(moz
 
     if (aType >= (mSuppressInterruptibleReflows ? Flush_Layout : Flush_InterruptibleLayout) &&
         !mIsDestroying) {
       mFrameConstructor->RecalcQuotesAndCounters();
       mViewManager->FlushDelayedResize(PR_TRUE);
       if (ProcessReflowCommands(aType < Flush_Layout) && mContentToScrollTo) {
         // We didn't get interrupted.  Go ahead and scroll to our content
         DoScrollContentIntoView(mContentToScrollTo, mContentScrollVPosition,
-                                mContentScrollHPosition);
+                                mContentScrollHPosition,
+                                SCROLL_OVERFLOW_HIDDEN);
         mContentToScrollTo = nsnull;
       }
     }
 
     if (aType >= Flush_Layout) {
       // Flush plugin geometry. Don't flush plugin geometry for
       // interruptible layouts, since WillPaint does an interruptible
       // layout.
@@ -7156,17 +7164,18 @@ PresShell::PrepareToUseCaretPosition(nsI
     // frame is actually in view. The result is that the frame is aligned with
     // the top of the window, but the menu is still at the bottom.
     //
     // Doing this call first forces the frame to be in view, eliminating the
     // problem. The only difference in the result is that if your cursor is in
     // an edit box below the current view, you'll get the edit box aligned with
     // the top of the window. This is arguably better behavior anyway.
     rv = ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
-                                        NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
+                                        NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
+                                        SCROLL_OVERFLOW_HIDDEN);
     NS_ENSURE_SUCCESS(rv, PR_FALSE);
     frame = content->GetPrimaryFrame();
     NS_WARN_IF_FALSE(frame, "No frame for focused content?");
   }
 
   // Actually scroll the selection (ie caret) into view. Note that this must
   // be synchronous since we will be checking the caret position on the screen.
   //
@@ -7219,17 +7228,18 @@ PresShell::PrepareToUseCaretPosition(nsI
 void
 PresShell::GetCurrentItemAndPositionForElement(nsIDOMElement *aCurrentEl,
                                                nsIContent** aTargetToUse,
                                                nsIntPoint& aTargetPt,
                                                nsIWidget *aRootWidget)
 {
   nsCOMPtr<nsIContent> focusedContent(do_QueryInterface(aCurrentEl));
   ScrollContentIntoView(focusedContent, NS_PRESSHELL_SCROLL_ANYWHERE,
-                                        NS_PRESSHELL_SCROLL_ANYWHERE);
+                                        NS_PRESSHELL_SCROLL_ANYWHERE,
+                                        SCROLL_OVERFLOW_HIDDEN);
 
   nsPresContext* presContext = GetPresContext();
 
   PRBool istree = PR_FALSE, checkLineHeight = PR_TRUE;
   nscoord extraTreeY = 0;
 
 #ifdef MOZ_XUL
   // Set the position to just underneath the current item for multi-select
--- a/layout/base/tests/test_bug603550.html
+++ b/layout/base/tests/test_bug603550.html
@@ -49,28 +49,75 @@ function sendMouseDown(el) {
 function sendMouseUp(el) {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   var rect = el.getBoundingClientRect();
   var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                     .getInterface(Components.interfaces.nsIDOMWindowUtils);
   utils.sendMouseEvent('mouseup', rect.left + 5, rect.top + 5, 0, 1, 0);
 }
 
+function fireEvent(target, event) {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  var utils =
+    window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+           getInterface(Components.interfaces.nsIDOMWindowUtils);
+  utils.dispatchDOMEventViaPresShell(target, event, true);
+}
+
+function fireDrop(element) {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  var ds = Components.classes["@mozilla.org/widget/dragservice;1"].
+    getService(Components.interfaces.nsIDragService);
+
+  ds.startDragSession();
+
+  var event = document.createEvent("DragEvents");
+  event.initDragEvent("dragover", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, null);
+  fireEvent(element, event);
+
+  event = document.createEvent("DragEvents");
+  event.initDragEvent("drop", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, null);
+  fireEvent(element, event);
+
+  ds.endDragSession(false);
+  ok(!ds.getCurrentSession(), "There shouldn't be a drag session anymore!");
+}
+
 function runTest() {
   var d1 = document.getElementById("d1");
   var didGetMouseMove = false;
   sendMouseDown(d1);
   document.addEventListener("mousemove",
     function (e) {
       didGetMouseMove = (e.target == document);
     },
     true);
   sendMouseMoveFaraway(d1);
   ok(didGetMouseMove, "Should have got mousemove!");
-  sendMouseUp(d1)
+  sendMouseUp(d1);
+  
+  didGetMouseMove = false;
+  document.addEventListener("mousedown",
+    function (e) {
+      e.preventDefault();
+    },
+    true);
+  sendMouseDown(d1);
+  sendMouseMoveFaraway(d1);
+  ok(didGetMouseMove, "Should have got mousemove! (2)");
+  sendMouseUp(d1);
+  
+  didGetMouseMove = false;
+  sendMouseDown(d1);
+  fireDrop(d1);
+  sendMouseMoveFaraway(d1);
+  ok(!didGetMouseMove, "Shouldn't have got mousemove!");
+  
+  
+  
   SimpleTest.finish();
 }
 
 
 </script>
 </pre>
 <div class="test" id="d1">&nbsp;</div>
 </body>
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -360,16 +360,17 @@ public:
 #ifdef XP_MACOSX
   NPDrawingModel GetDrawingModel();
   NPEventModel GetEventModel();
   static void CARefresh(nsITimer *aTimer, void *aClosure);
   static void AddToCARefreshTimer(nsPluginInstanceOwner *aPluginInstance);
   static void RemoveFromCARefreshTimer(nsPluginInstanceOwner *aPluginInstance);
   void SetupCARefresh();
   void* FixUpPluginWindow(PRInt32 inPaintState);
+  void HidePluginWindow();
   // Set a flag that (if true) indicates the plugin port info has changed and
   // SetWindow() needs to be called.
   void SetPluginPortChanged(PRBool aState) { mPluginPortChanged = aState; }
   // Return a pointer to the internal nsPluginPort structure that's used to
   // store a copy of plugin port info and to detect when it's been changed.
   void* GetPluginPortCopy();
   // Set plugin port info in the plugin (in the 'window' member of the
   // NPWindow structure passed to the plugin by SetWindow()) and set a
@@ -1097,18 +1098,16 @@ nsObjectFrame::CallSetWindow()
   nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
 #ifdef XP_MACOSX
   mInstanceOwner->FixUpPluginWindow(ePluginPaintDisable);
 #endif
 
   if (IsHidden())
     return;
 
-  PRBool windowless = (window->type == NPWindowTypeDrawable);
-
   // refresh the plugin port as well
   window->window = mInstanceOwner->GetPluginPortFromWidget();
 
   // Adjust plugin dimensions according to pixel snap results
   // and reduce amount of SetWindow calls
   nsPresContext* presContext = PresContext();
   nsRootPresContext* rootPC = presContext->GetRootPresContext();
   if (!rootPC)
@@ -2458,17 +2457,21 @@ DoStopPlugin(nsPluginInstanceOwner *aIns
 
     if (window) 
       window->CallSetWindow(nullinst);
     else 
       inst->SetWindow(nsnull);
     
     if (DoDelayedStop(aInstanceOwner, aDelayedStop))
       return;
-    
+
+#if defined(XP_MACOSX)
+    aInstanceOwner->HidePluginWindow();
+#endif
+
     inst->Stop();
 
     nsCOMPtr<nsIPluginHost> pluginHost = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
     if (pluginHost)
       pluginHost->StopPluginInstance(inst);
 
     // the frame is going away along with its widget so tell the
     // window to forget its widget too
@@ -2549,17 +2552,16 @@ nsObjectFrame::StopPluginInternal(PRBool
 
       // Make sure the plugin is hidden in case an update of plugin geometry
       // hasn't happened since this plugin became hidden.
       nsIWidget* parent = mWidget->GetParent();
       if (parent) {
         nsTArray<nsIWidget::Configuration> configurations;
         GetEmptyClipConfiguration(&configurations);
         parent->ConfigureChildren(configurations);
-        DidSetWidgetGeometry();
       }
     }
     else {
       NS_ASSERTION(PresContext()->PresShell()->IsFrozen(),
                    "unable to unregister the plugin frame");
     }
   }
 
@@ -6424,16 +6426,29 @@ void* nsPluginInstanceOwner::FixUpPlugin
 #ifdef MAC_CARBON_PLUGINS
   if (drawingModel == NPDrawingModelCoreGraphics && eventModel == NPEventModelCarbon)
     return static_cast<NP_CGContext*>(pluginPort)->window;
 #endif
 
   return nsnull;
 }
 
+void
+nsPluginInstanceOwner::HidePluginWindow()
+{
+  if (!mPluginWindow || !mInstance) {
+    return;
+  }
+
+  mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
+  mPluginWindow->clipRect.right  = mPluginWindow->clipRect.left;
+  mWidgetVisible = PR_FALSE;
+  mInstance->SetWindow(mPluginWindow);
+}
+
 #endif // XP_MACOSX
 
 // Little helper function to resolve relative URL in
 // |value| for certain inputs of |name|
 void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value)
 {
   if (name.LowerCaseEqualsLiteral("pluginurl") ||
       name.LowerCaseEqualsLiteral("pluginspage")) {        
--- a/layout/inspector/src/inFlasher.cpp
+++ b/layout/inspector/src/inFlasher.cpp
@@ -191,17 +191,18 @@ inFlasher::ScrollElementIntoView(nsIDOME
   nsCOMPtr<nsIPresShell> presShell = inLayoutUtils::GetPresShellFor(window);
   if (!presShell) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
   presShell->ScrollContentIntoView(content,
                                    NS_PRESSHELL_SCROLL_ANYWHERE /* VPercent */,
-                                   NS_PRESSHELL_SCROLL_ANYWHERE /* HPercent */);
+                                   NS_PRESSHELL_SCROLL_ANYWHERE /* HPercent */,
+                                   nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
 
   return NS_OK;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // inFlasher
 
 void
new file mode 100644
--- /dev/null
+++ b/layout/reftests/native-theme/border-radius-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<div style="padding:50px; border-radius:50px; width:400px; height:400px;">
+  <input type="radio">
+  <input type="checkbox">
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/native-theme/border-radius.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<div style="padding:50px; border-radius:50px; width:400px; height:400px; overflow:hidden;">
+  <input type="radio">
+  <input type="checkbox">
+</div>
+</body>
+</html>
--- a/layout/reftests/native-theme/reftest.list
+++ b/layout/reftests/native-theme/reftest.list
@@ -56,9 +56,11 @@ random-if(d2d) == resizer-bottomend.xul 
 != resizer-bottomend.xul resizer-bottomend-rtl.xul
 skip-if(gtk2Widget) != resizer-bottomend-rtl.xul blank-window.xul
 skip-if(gtk2Widget) random-if(d2d) == resizer-bottomend-rtl.xul resizer-bottomend-flipped.xul # bug 581086
 
 # Windows-only, depends on native scrollbar metrics
 skip-if(!winWidget) == scroll-thumb-minimum-size-notheme.html scroll-thumb-minimum-size-notheme-ref.html
 # skip-if(!winWidget) == scroll-thumb-minimum-size-theme.html scroll-thumb-minimum-size-theme-ref.html # Bug 512206
 
+== border-radius.html border-radius-ref.html
+
 == checkbox-dynamic-1.html checkbox-dynamic-1-ref.html
--- a/layout/xul/base/src/nsScrollBoxObject.cpp
+++ b/layout/xul/base/src/nsScrollBoxObject.cpp
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1998
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Original Author: David W. Hyatt (hyatt@netscape.com)
+ *   Mihai Șucan <mihai.sucan@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -249,66 +250,28 @@ NS_IMETHODIMP nsScrollBoxObject::ScrollT
   sf->ScrollTo(nsPoint(0, y), nsIScrollableFrame::INSTANT);
   return NS_OK;
 }
 
 /* void scrollToElement (in nsIDOMElement child); */
 NS_IMETHODIMP nsScrollBoxObject::ScrollToElement(nsIDOMElement *child)
 {
     NS_ENSURE_ARG_POINTER(child);
-    nsIScrollableFrame* sf = GetScrollFrame();
-    if (!sf)
-       return NS_ERROR_FAILURE;
 
     nsCOMPtr<nsIPresShell> shell = GetPresShell(PR_FALSE);
     if (!shell) {
       return NS_ERROR_UNEXPECTED;
     }
 
-    nsIFrame* scrolledBox = GetScrolledBox(this);
-    if (!scrolledBox)
-       return NS_ERROR_FAILURE;
-
-    nsRect rect, crect;
-    nsCOMPtr<nsIDOMDocument> doc;
-    child->GetOwnerDocument(getter_AddRefs(doc));
-    nsCOMPtr<nsIDocument> nsDoc(do_QueryInterface(doc));
-    if(!nsDoc)
-      return NS_ERROR_UNEXPECTED;
-
-    nsCOMPtr<nsIBoxObject> childBoxObject;
-    nsDoc->GetBoxObjectFor(child, getter_AddRefs(childBoxObject));
-    if(!childBoxObject)
-      return NS_ERROR_UNEXPECTED;
-
-    PRInt32 x,y;
-    childBoxObject->GetX(&x);
-    childBoxObject->GetY(&y);
-    // get the twips rectangle from the boxobject (which has pixels)    
-    rect.x = nsPresContext::CSSPixelsToAppUnits(x);
-    rect.y = nsPresContext::CSSPixelsToAppUnits(y);
-
-    // TODO: make sure the child is inside the box
-
-    // get our current info
-    nsPoint cp = sf->GetScrollPosition();
-    nsIntRect prect;
-    GetOffsetRect(prect);
-    crect = prect.ToAppUnits(nsPresContext::AppUnitsPerCSSPixel());
-    nscoord newx=cp.x, newy=cp.y;
-
-    // we only scroll in the direction of the scrollbox orientation
-    // always scroll to left or top edge of child element
-    if (scrolledBox->IsHorizontal()) {
-        newx = rect.x - crect.x;
-    } else {
-        newy = rect.y - crect.y;
-    }
-    // scroll away
-    sf->ScrollTo(nsPoint(newx, newy), nsIScrollableFrame::INSTANT);
+    nsCOMPtr<nsIContent> content = do_QueryInterface(child);
+    shell->ScrollContentIntoView(content,
+                                 NS_PRESSHELL_SCROLL_TOP,
+                                 NS_PRESSHELL_SCROLL_LEFT,
+                                 nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY |
+                                 nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
     return NS_OK;
 }
 
 /* void scrollToIndex (in long index); */
 NS_IMETHODIMP nsScrollBoxObject::ScrollToIndex(PRInt32 index)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
@@ -342,78 +305,27 @@ NS_IMETHODIMP nsScrollBoxObject::GetScro
     return NS_OK;
 }
 
 /* void ensureElementIsVisible (in nsIDOMElement child); */
 NS_IMETHODIMP nsScrollBoxObject::EnsureElementIsVisible(nsIDOMElement *child)
 {
     NS_ENSURE_ARG_POINTER(child);
 
-    // Start with getting info about the child, since that will flush
-    // layout and possibly destroy scrollable views, presshells, etc.
-    nsCOMPtr<nsIDOMDocument> doc;
-    // XXXbz sXBL/XBL2 issue -- which document?
-    child->GetOwnerDocument(getter_AddRefs(doc));
-    nsCOMPtr<nsIDocument> nsDoc(do_QueryInterface(doc));
-    if(!nsDoc)
-        return NS_ERROR_UNEXPECTED;
-
-    nsCOMPtr<nsIBoxObject> childBoxObject;
-    nsDoc->GetBoxObjectFor(child, getter_AddRefs(childBoxObject));
-    if(!childBoxObject)
+    nsCOMPtr<nsIPresShell> shell = GetPresShell(PR_FALSE);
+    if (!shell) {
       return NS_ERROR_UNEXPECTED;
-
-    PRInt32 x, y, width, height;
-    childBoxObject->GetX(&x);
-    childBoxObject->GetY(&y);
-    childBoxObject->GetWidth(&width);
-    childBoxObject->GetHeight(&height);
-
-    nsIScrollableFrame* sf = GetScrollFrame();
-    if (!sf)
-       return NS_ERROR_FAILURE;
-
-    nsIFrame* scrolledBox = GetScrolledBox(this);
-    if (!scrolledBox)
-       return NS_ERROR_FAILURE;
+    }
 
-    nsRect rect, crect;
-    // get the twips rectangle from the boxobject (which has pixels)    
-    rect.x = nsPresContext::CSSPixelsToAppUnits(x);
-    rect.y = nsPresContext::CSSPixelsToAppUnits(y);
-    rect.width = nsPresContext::CSSPixelsToAppUnits(width);
-    rect.height = nsPresContext::CSSPixelsToAppUnits(height);
-
-    // TODO: make sure the child is inside the box
-
-    // get our current info
-    nsPoint cp = sf->GetScrollPosition();
-    nsIntRect prect;
-    GetOffsetRect(prect);
-    crect = prect.ToAppUnits(nsPresContext::AppUnitsPerCSSPixel());
-
-    nscoord newx=cp.x, newy=cp.y;
-
-    // we only scroll in the direction of the scrollbox orientation
-    if (scrolledBox->IsHorizontal()) {
-        if ((rect.x - crect.x) + rect.width > cp.x + crect.width) {
-            newx = cp.x + (((rect.x - crect.x) + rect.width)-(cp.x + crect.width));
-        } else if (rect.x - crect.x < cp.x) {
-            newx = rect.x - crect.x;
-        }
-    } else {
-        if ((rect.y - crect.y) + rect.height > cp.y + crect.height) {
-            newy = cp.y + (((rect.y - crect.y) + rect.height)-(cp.y + crect.height));
-        } else if (rect.y - crect.y < cp.y) {
-            newy = rect.y - crect.y;
-        }
-    }
-    
-    // scroll away
-    sf->ScrollTo(nsPoint(newx, newy), nsIScrollableFrame::INSTANT);
+    nsCOMPtr<nsIContent> content = do_QueryInterface(child);
+    shell->ScrollContentIntoView(content,
+                                 NS_PRESSHELL_SCROLL_ANYWHERE,
+                                 NS_PRESSHELL_SCROLL_ANYWHERE,
+                                 nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY |
+                                 nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
     return NS_OK;
 }
 
 /* void ensureIndexIsVisible (in long index); */
 NS_IMETHODIMP nsScrollBoxObject::EnsureIndexIsVisible(PRInt32 index)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
--- a/netwerk/base/src/nsServerSocket.cpp
+++ b/netwerk/base/src/nsServerSocket.cpp
@@ -94,34 +94,34 @@ nsServerSocket::~nsServerSocket()
   // release our reference to the STS
   nsSocketTransportService *serv = gSocketTransportService;
   NS_RELEASE(serv);
 }
 
 void
 nsServerSocket::OnMsgClose()
 {
-  LOG(("nsServerSocket::OnMsgClose [this=%p]\n", this));
+  SOCKET_LOG(("nsServerSocket::OnMsgClose [this=%p]\n", this));
 
   if (NS_FAILED(mCondition))
     return;
 
   // tear down socket.  this signals the STS to detach our socket handler.
   mCondition = NS_BINDING_ABORTED;
 
   // if we are attached, then we'll close the socket in our OnSocketDetached.
   // otherwise, call OnSocketDetached from here.
   if (!mAttached)
     OnSocketDetached(mFD);
 }
 
 void
 nsServerSocket::OnMsgAttach()
 {
-  LOG(("nsServerSocket::OnMsgAttach [this=%p]\n", this));
+  SOCKET_LOG(("nsServerSocket::OnMsgAttach [this=%p]\n", this));
 
   if (NS_FAILED(mCondition))
     return;
 
   mCondition = TryAttach();
   
   // if we hit an error while trying to attach then bail...
   if (NS_FAILED(mCondition))
--- a/netwerk/base/src/nsSocketTransport2.cpp
+++ b/netwerk/base/src/nsSocketTransport2.cpp
@@ -135,17 +135,17 @@ static PRErrorCode RandomizeConnectError
             // This error will cause this socket transport to error out;
             // however, if the consumer is HTTP, then the HTTP transaction
             // should be restarted when this error occurs.
             //
             { PR_CONNECT_RESET_ERROR, "PR_CONNECT_RESET_ERROR" },
         };
         n = n % (sizeof(errors)/sizeof(errors[0]));
         code = errors[n].err_code;
-        LOG(("simulating NSPR error %d [%s]\n", code, errors[n].err_name));
+        SOCKET_LOG(("simulating NSPR error %d [%s]\n", code, errors[n].err_name));
     }
     return code;
 }
 #endif
 
 //-----------------------------------------------------------------------------
 
 static PRBool
@@ -197,17 +197,17 @@ ErrorAccordingToNSPR(PRErrorCode errorCo
     case PR_CONNECT_TIMEOUT_ERROR:
         rv = NS_ERROR_NET_TIMEOUT;
         break;
     default:
         if (IsNSSErrorCode(errorCode))
             rv = GetXPCOMFromNSSError(errorCode);
         break;
     }
-    LOG(("ErrorAccordingToNSPR [in=%d out=%x]\n", errorCode, rv));
+    SOCKET_LOG(("ErrorAccordingToNSPR [in=%d out=%x]\n", errorCode, rv));
     return rv;
 }
 
 //-----------------------------------------------------------------------------
 // socket input stream impl 
 //-----------------------------------------------------------------------------
 
 nsSocketInputStream::nsSocketInputStream(nsSocketTransport *trans)
@@ -225,17 +225,17 @@ nsSocketInputStream::~nsSocketInputStrea
 
 // called on the socket transport thread...
 //
 //   condition : failure code if socket has been closed
 //
 void
 nsSocketInputStream::OnSocketReady(nsresult condition)
 {
-    LOG(("nsSocketInputStream::OnSocketReady [this=%x cond=%x]\n",
+    SOCKET_LOG(("nsSocketInputStream::OnSocketReady [this=%x cond=%x]\n",
         this, condition));
 
     NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
     nsCOMPtr<nsIInputStreamCallback> callback;
     {
         nsAutoLock lock(mTransport->mLock);
 
@@ -279,17 +279,17 @@ NS_IMETHODIMP
 nsSocketInputStream::Close()
 {
     return CloseWithStatus(NS_BASE_STREAM_CLOSED);
 }
 
 NS_IMETHODIMP
 nsSocketInputStream::Available(PRUint32 *avail)
 {
-    LOG(("nsSocketInputStream::Available [this=%x]\n", this));
+    SOCKET_LOG(("nsSocketInputStream::Available [this=%x]\n", this));
 
     *avail = 0;
 
     PRFileDesc *fd;
     {
         nsAutoLock lock(mTransport->mLock);
 
         if (NS_FAILED(mCondition))
@@ -324,40 +324,40 @@ nsSocketInputStream::Available(PRUint32 
     if (NS_FAILED(rv))
         mTransport->OnInputClosed(rv);
     return rv;
 }
 
 NS_IMETHODIMP
 nsSocketInputStream::Read(char *buf, PRUint32 count, PRUint32 *countRead)
 {
-    LOG(("nsSocketInputStream::Read [this=%x count=%u]\n", this, count));
+    SOCKET_LOG(("nsSocketInputStream::Read [this=%x count=%u]\n", this, count));
 
     *countRead = 0;
 
     PRFileDesc *fd;
     {
         nsAutoLock lock(mTransport->mLock);
 
         if (NS_FAILED(mCondition))
             return (mCondition == NS_BASE_STREAM_CLOSED) ? NS_OK : mCondition;
 
         fd = mTransport->GetFD_Locked();
         if (!fd)
             return NS_BASE_STREAM_WOULD_BLOCK;
     }
 
-    LOG(("  calling PR_Read [count=%u]\n", count));
+    SOCKET_LOG(("  calling PR_Read [count=%u]\n", count));
 
     // cannot hold lock while calling NSPR.  (worried about the fact that PSM
     // synchronously proxies notifications over to the UI thread, which could
     // mistakenly try to re-enter this code.)
     PRInt32 n = PR_Read(fd, buf, count);
 
-    LOG(("  PR_Read returned [n=%d]\n", n));
+    SOCKET_LOG(("  PR_Read returned [n=%d]\n", n));
 
     nsresult rv;
     {
         nsAutoLock lock(mTransport->mLock);
 
 #ifdef ENABLE_SOCKET_TRACING
         if (n > 0)
             mTransport->TraceInBuf(buf, n);
@@ -398,17 +398,17 @@ nsSocketInputStream::IsNonBlocking(PRBoo
 {
     *nonblocking = PR_TRUE;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSocketInputStream::CloseWithStatus(nsresult reason)
 {
-    LOG(("nsSocketInputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason));
+    SOCKET_LOG(("nsSocketInputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason));
 
     // may be called from any thread
  
     nsresult rv;
     {
         nsAutoLock lock(mTransport->mLock);
 
         if (NS_SUCCEEDED(mCondition))
@@ -422,17 +422,17 @@ nsSocketInputStream::CloseWithStatus(nsr
 }
 
 NS_IMETHODIMP
 nsSocketInputStream::AsyncWait(nsIInputStreamCallback *callback,
                                PRUint32 flags,
                                PRUint32 amount,
                                nsIEventTarget *target)
 {
-    LOG(("nsSocketInputStream::AsyncWait [this=%x]\n", this));
+    SOCKET_LOG(("nsSocketInputStream::AsyncWait [this=%x]\n", this));
 
     // This variable will be non-null when we want to call the callback
     // directly from this function, but outside the lock.
     // (different from callback when target is not null)
     nsCOMPtr<nsIInputStreamCallback> directCallback;
     {
         nsAutoLock lock(mTransport->mLock);
 
@@ -484,17 +484,17 @@ nsSocketOutputStream::~nsSocketOutputStr
 
 // called on the socket transport thread...
 //
 //   condition : failure code if socket has been closed
 //
 void
 nsSocketOutputStream::OnSocketReady(nsresult condition)
 {
-    LOG(("nsSocketOutputStream::OnSocketReady [this=%x cond=%x]\n",
+    SOCKET_LOG(("nsSocketOutputStream::OnSocketReady [this=%x cond=%x]\n",
         this, condition));
 
     NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
     nsCOMPtr<nsIOutputStreamCallback> callback;
     {
         nsAutoLock lock(mTransport->mLock);
 
@@ -544,17 +544,17 @@ NS_IMETHODIMP
 nsSocketOutputStream::Flush()
 {
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSocketOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *countWritten)
 {
-    LOG(("nsSocketOutputStream::Write [this=%x count=%u]\n", this, count));
+    SOCKET_LOG(("nsSocketOutputStream::Write [this=%x count=%u]\n", this, count));
 
     *countWritten = 0;
 
     if (count == 0)
         return NS_OK;
 
     PRFileDesc *fd;
     {
@@ -563,24 +563,24 @@ nsSocketOutputStream::Write(const char *
         if (NS_FAILED(mCondition))
             return mCondition;
         
         fd = mTransport->GetFD_Locked();
         if (!fd)
             return NS_BASE_STREAM_WOULD_BLOCK;
     }
 
-    LOG(("  calling PR_Write [count=%u]\n", count));
+    SOCKET_LOG(("  calling PR_Write [count=%u]\n", count));
 
     // cannot hold lock while calling NSPR.  (worried about the fact that PSM
     // synchronously proxies notifications over to the UI thread, which could
     // mistakenly try to re-enter this code.)
     PRInt32 n = PR_Write(fd, buf, count);
 
-    LOG(("  PR_Write returned [n=%d]\n", n));
+    SOCKET_LOG(("  PR_Write returned [n=%d]\n", n));
     NS_ASSERTION(n != 0, "unexpected return value");
 
     nsresult rv;
     {
         nsAutoLock lock(mTransport->mLock);
 
 #ifdef ENABLE_SOCKET_TRACING
     if (n > 0)
@@ -640,17 +640,17 @@ nsSocketOutputStream::IsNonBlocking(PRBo
 {
     *nonblocking = PR_TRUE;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSocketOutputStream::CloseWithStatus(nsresult reason)
 {
-    LOG(("nsSocketOutputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason));
+    SOCKET_LOG(("nsSocketOutputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason));
 
     // may be called from any thread
  
     nsresult rv;
     {
         nsAutoLock lock(mTransport->mLock);
 
         if (NS_SUCCEEDED(mCondition))
@@ -664,17 +664,17 @@ nsSocketOutputStream::CloseWithStatus(ns
 }
 
 NS_IMETHODIMP
 nsSocketOutputStream::AsyncWait(nsIOutputStreamCallback *callback,
                                 PRUint32 flags,
                                 PRUint32 amount,
                                 nsIEventTarget *target)
 {
-    LOG(("nsSocketOutputStream::AsyncWait [this=%x]\n", this));
+    SOCKET_LOG(("nsSocketOutputStream::AsyncWait [this=%x]\n", this));
 
     {
         nsAutoLock lock(mTransport->mLock);
 
         if (callback && target) {
             //
             // build event proxy
             //
@@ -716,27 +716,27 @@ nsSocketTransport::nsSocketTransport()
     , mLock(PR_NewLock())
     , mFD(nsnull)
     , mFDref(0)
     , mFDconnected(PR_FALSE)
     , mInput(this)
     , mOutput(this)
     , mQoSBits(0x00)
 {
-    LOG(("creating nsSocketTransport @%x\n", this));
+    SOCKET_LOG(("creating nsSocketTransport @%x\n", this));
 
     NS_ADDREF(gSocketTransportService);
 
     mTimeouts[TIMEOUT_CONNECT]    = PR_UINT16_MAX; // no timeout
     mTimeouts[TIMEOUT_READ_WRITE] = PR_UINT16_MAX; // no timeout
 }
 
 nsSocketTransport::~nsSocketTransport()
 {
-    LOG(("destroying nsSocketTransport @%x\n", this));
+    SOCKET_LOG(("destroying nsSocketTransport @%x\n", this));
 
     // cleanup socket type info
     if (mTypes) {
         PRUint32 i;
         for (i=0; i<mTypeCount; ++i)
             PL_strfree(mTypes[i]);
         free(mTypes);
     }
@@ -774,17 +774,17 @@ nsSocketTransport::Init(const char **typ
         // grab proxy type (looking for "socks" for example)
         proxyType = proxyInfo->Type();
         if (proxyType && (strcmp(proxyType, "http") == 0 ||
                           strcmp(proxyType, "direct") == 0 ||
                           strcmp(proxyType, "unknown") == 0))
             proxyType = nsnull;
     }
 
-    LOG(("nsSocketTransport::Init [this=%x host=%s:%hu proxy=%s:%hu]\n",
+    SOCKET_LOG(("nsSocketTransport::Init [this=%x host=%s:%hu proxy=%s:%hu]\n",
         this, mHost.get(), mPort, mProxyHost.get(), mProxyPort));
 
     // include proxy type as a socket type if proxy type is not "http"
     mTypeCount = typeCount + (proxyType != nsnull);
     if (!mTypeCount)
         return NS_OK;
 
     // if we have socket types, then the socket provider service had
@@ -864,40 +864,40 @@ nsSocketTransport::InitWithConnectedSock
     mFDconnected = 1;
 
     // make sure new socket is non-blocking
     PRSocketOptionData opt;
     opt.option = PR_SockOpt_Nonblocking;
     opt.value.non_blocking = PR_TRUE;
     PR_SetSocketOption(mFD, &opt);
 
-    LOG(("nsSocketTransport::InitWithConnectedSocket [this=%p addr=%s:%hu]\n",
+    SOCKET_LOG(("nsSocketTransport::InitWithConnectedSocket [this=%p addr=%s:%hu]\n",
         this, mHost.get(), mPort));
 
     // jump to InitiateSocket to get ourselves attached to the STS poll list.
     return PostEvent(MSG_RETRY_INIT_SOCKET);
 }
 
 nsresult
 nsSocketTransport::PostEvent(PRUint32 type, nsresult status, nsISupports *param)
 {
-    LOG(("nsSocketTransport::PostEvent [this=%p type=%u status=%x param=%p]\n",
+    SOCKET_LOG(("nsSocketTransport::PostEvent [this=%p type=%u status=%x param=%p]\n",
         this, type, status, param));
 
     nsCOMPtr<nsIRunnable> event = new nsSocketEvent(this, type, status, param);
     if (!event)
         return NS_ERROR_OUT_OF_MEMORY;
 
     return gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL);
 }
 
 void
 nsSocketTransport::SendStatus(nsresult status)
 {
-    LOG(("nsSocketTransport::SendStatus [this=%x status=%x]\n", this, status));
+    SOCKET_LOG(("nsSocketTransport::SendStatus [this=%x status=%x]\n", this, status));
 
     nsCOMPtr<nsITransportEventSink> sink;
     PRUint64 progress;
     {
         nsAutoLock lock(mLock);
         sink = mEventSink;
         switch (status) {
         case STATUS_SENDING_TO:
@@ -913,17 +913,17 @@ nsSocketTransport::SendStatus(nsresult s
     }
     if (sink)
         sink->OnTransportStatus(this, status, progress, LL_MAXUINT);
 }
 
 nsresult
 nsSocketTransport::ResolveHost()
 {
-    LOG(("nsSocketTransport::ResolveHost [this=%x]\n", this));
+    SOCKET_LOG(("nsSocketTransport::ResolveHost [this=%x]\n", this));
 
     nsresult rv;
 
     if (!mProxyHost.IsEmpty()) {
         if (!mProxyTransparent || mProxyTransparentResolvesHost) {
             // When not resolving mHost locally, we still want to ensure that
             // it only contains valid characters.  See bug 304904 for details.
             if (!net_IsValidHostName(mHost))
@@ -950,29 +950,29 @@ nsSocketTransport::ResolveHost()
 
     PRUint32 dnsFlags = 0;
     if (mConnectionFlags & nsSocketTransport::BYPASS_CACHE)
         dnsFlags = nsIDNSService::RESOLVE_BYPASS_CACHE;
 
     rv = dns->AsyncResolve(SocketHost(), dnsFlags, this, nsnull,
                            getter_AddRefs(mDNSRequest));
     if (NS_SUCCEEDED(rv)) {
-        LOG(("  advancing to STATE_RESOLVING\n"));
+        SOCKET_LOG(("  advancing to STATE_RESOLVING\n"));
         mState = STATE_RESOLVING;
         // only report that we are resolving if we are still resolving...
         if (mResolving)
             SendStatus(STATUS_RESOLVING);
     }
     return rv;
 }
 
 nsresult
 nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool &usingSSL)
 {
-    LOG(("nsSocketTransport::BuildSocket [this=%x]\n", this));
+    SOCKET_LOG(("nsSocketTransport::BuildSocket [this=%x]\n", this));
 
     nsresult rv;
 
     proxyTransparent = PR_FALSE;
     usingSSL = PR_FALSE;
 
     if (mTypeCount == 0) {
         fd = PR_OpenTCPSocket(mNetAddr.raw.family);
@@ -990,17 +990,17 @@ nsSocketTransport::BuildSocket(PRFileDes
         const char *proxyHost  = mProxyHost.IsEmpty() ? nsnull : mProxyHost.get();
         PRInt32     proxyPort  = (PRInt32) mProxyPort;
         PRUint32    proxyFlags = 0;
 
         PRUint32 i;
         for (i=0; i<mTypeCount; ++i) {
             nsCOMPtr<nsISocketProvider> provider;
 
-            LOG(("  pushing io layer [%u:%s]\n", i, mTypes[i]));
+            SOCKET_LOG(("  pushing io layer [%u:%s]\n", i, mTypes[i]));
 
             rv = spserv->GetSocketProvider(mTypes[i], getter_AddRefs(provider));
             if (NS_FAILED(rv))
                 break;
 
             if (mProxyTransparentResolvesHost)
                 proxyFlags |= nsISocketProvider::PROXY_RESOLVES_HOST;
             
@@ -1038,17 +1038,17 @@ nsSocketTransport::BuildSocket(PRFileDes
             PRBool isSSL = (strcmp(mTypes[i], "ssl") == 0);
             if (isSSL || (strcmp(mTypes[i], "starttls") == 0)) {
                 // remember security info and give notification callbacks to PSM...
                 nsCOMPtr<nsIInterfaceRequestor> callbacks;
                 {
                     nsAutoLock lock(mLock);
                     mSecInfo = secinfo;
                     callbacks = mCallbacks;
-                    LOG(("  [secinfo=%x callbacks=%x]\n", mSecInfo.get(), mCallbacks.get()));
+                    SOCKET_LOG(("  [secinfo=%x callbacks=%x]\n", mSecInfo.get(), mCallbacks.get()));
                 }
                 // don't call into PSM while holding mLock!!
                 nsCOMPtr<nsISSLSocketControl> secCtrl(do_QueryInterface(secinfo));
                 if (secCtrl)
                     secCtrl->SetNotificationCallbacks(callbacks);
                 // remember if socket type is SSL so we can ProxyStartSSL if need be.
                 usingSSL = isSSL;
             }
@@ -1058,29 +1058,29 @@ nsSocketTransport::BuildSocket(PRFileDes
                 // it do not have to worry about proxy stuff
                 proxyHost = nsnull;
                 proxyPort = -1;
                 proxyTransparent = PR_TRUE;
             }
         }
 
         if (NS_FAILED(rv)) {
-            LOG(("  error pushing io layer [%u:%s rv=%x]\n", i, mTypes[i], rv));
+            SOCKET_LOG(("  error pushing io layer [%u:%s rv=%x]\n", i, mTypes[i], rv));
             if (fd)
                 PR_Close(fd);
         }
     }
 
     return rv;
 }
 
 nsresult
 nsSocketTransport::InitiateSocket()
 {
-    LOG(("nsSocketTransport::InitiateSocket [this=%x]\n", this));
+    SOCKET_LOG(("nsSocketTransport::InitiateSocket [this=%x]\n", this));
 
     nsresult rv;
 
     //
     // find out if it is going to be ok to attach another socket to the STS.
     // if not then we have to wait for the STS to tell us that it is ok.
     // the notification is asynchronous, which means that when we could be
     // in a race to call AttachSocket once notified.  for this reason, when
@@ -1113,17 +1113,17 @@ nsSocketTransport::InitiateSocket()
     // create new socket fd, push io layers, etc.
     //
     PRFileDesc *fd;
     PRBool proxyTransparent;
     PRBool usingSSL;
 
     rv = BuildSocket(fd, proxyTransparent, usingSSL);
     if (NS_FAILED(rv)) {
-        LOG(("  BuildSocket failed [rv=%x]\n", rv));
+        SOCKET_LOG(("  BuildSocket failed [rv=%x]\n", rv));
         return rv;
     }
 
     PRStatus status;
 
     // Make the socket non-blocking...
     PRSocketOptionData opt;
     opt.option = PR_SockOpt_Nonblocking;
@@ -1160,26 +1160,26 @@ nsSocketTransport::InitiateSocket()
     // established a connection.
     {
         nsAutoLock lock(mLock);
         mFD = fd;
         mFDref = 1;
         mFDconnected = PR_FALSE;
     }
 
-    LOG(("  advancing to STATE_CONNECTING\n"));
+    SOCKET_LOG(("  advancing to STATE_CONNECTING\n"));
     mState = STATE_CONNECTING;
     mPollTimeout = mTimeouts[TIMEOUT_CONNECT];
     SendStatus(STATUS_CONNECTING_TO);
 
 #if defined(PR_LOGGING)
-    if (LOG_ENABLED()) {
+    if (SOCKET_LOG_ENABLED()) {
         char buf[64];
         PR_NetAddrToString(&mNetAddr, buf, sizeof(buf));
-        LOG(("  trying address: %s\n", buf));
+        SOCKET_LOG(("  trying address: %s\n", buf));
     }
 #endif
 
     // 
     // Initiate the connect() to the host...  
     //
     status = PR_Connect(fd, &mNetAddr, NS_SOCKET_CONNECT_TIMEOUT);
     if (status == PR_SUCCESS) {
@@ -1210,17 +1210,17 @@ nsSocketTransport::InitiateSocket()
             if (mSecInfo && !mProxyHost.IsEmpty() && proxyTransparent && usingSSL) {
                 // if the connection phase is finished, and the ssl layer has
                 // been pushed, and we were proxying (transparently; ie. nothing
                 // has to happen in the protocol layer above us), it's time for
                 // the ssl to start doing it's thing.
                 nsCOMPtr<nsISSLSocketControl> secCtrl =
                     do_QueryInterface(mSecInfo);
                 if (secCtrl) {
-                    LOG(("  calling ProxyStartSSL()\n"));
+                    SOCKET_LOG(("  calling ProxyStartSSL()\n"));
                     secCtrl->ProxyStartSSL();
                 }
                 // XXX what if we were forced to poll on the socket for a successful
                 // connection... wouldn't we need to call ProxyStartSSL after a call
                 // to PR_ConnectContinue indicates that we are connected?
                 //
                 // XXX this appears to be what the old socket transport did.  why
                 // isn't this broken?
@@ -1238,17 +1238,17 @@ nsSocketTransport::InitiateSocket()
     return rv;
 }
 
 PRBool
 nsSocketTransport::RecoverFromError()
 {
     NS_ASSERTION(NS_FAILED(mCondition), "there should be something wrong");
 
-    LOG(("nsSocketTransport::RecoverFromError [this=%x state=%x cond=%x]\n",
+    SOCKET_LOG(("nsSocketTransport::RecoverFromError [this=%x state=%x cond=%x]\n",
         this, mState, mCondition));
 
     // can only recover from errors in these states
     if (mState != STATE_RESOLVING && mState != STATE_CONNECTING)
         return PR_FALSE;
 
     // OK to check this outside mLock
     NS_ASSERTION(!mFDconnected, "socket should not be connected");
@@ -1262,17 +1262,17 @@ nsSocketTransport::RecoverFromError()
         return PR_FALSE;
 
     PRBool tryAgain = PR_FALSE;
 
     // try next ip address only if past the resolver stage...
     if (mState == STATE_CONNECTING && mDNSRecord) {
         nsresult rv = mDNSRecord->GetNextAddr(SocketPort(), &mNetAddr);
         if (NS_SUCCEEDED(rv)) {
-            LOG(("  trying again with next ip address\n"));
+            SOCKET_LOG(("  trying again with next ip address\n"));
             tryAgain = PR_TRUE;
         }
     }
 
 #if defined(XP_WIN) || defined(MOZ_PLATFORM_MAEMO)
     // If not trying next address, try to make a connection using dialup. 
     // Retry if that connection is made.
     if (!tryAgain) {
@@ -1306,17 +1306,17 @@ nsSocketTransport::RecoverFromError()
 
     return tryAgain;
 }
 
 // called on the socket thread only
 void
 nsSocketTransport::OnMsgInputClosed(nsresult reason)
 {
-    LOG(("nsSocketTransport::OnMsgInputClosed [this=%x reason=%x]\n",
+    SOCKET_LOG(("nsSocketTransport::OnMsgInputClosed [this=%x reason=%x]\n",
         this, reason));
 
     NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
     mInputClosed = PR_TRUE;
     // check if event should affect entire transport
     if (NS_FAILED(reason) && (reason != NS_BASE_STREAM_CLOSED))
         mCondition = reason;                // XXX except if NS_FAILED(mCondition), right??
@@ -1328,17 +1328,17 @@ nsSocketTransport::OnMsgInputClosed(nsre
         mInput.OnSocketReady(reason);
     }
 }
 
 // called on the socket thread only
 void
 nsSocketTransport::OnMsgOutputClosed(nsresult reason)
 {
-    LOG(("nsSocketTransport::OnMsgOutputClosed [this=%x reason=%x]\n",
+    SOCKET_LOG(("nsSocketTransport::OnMsgOutputClosed [this=%x reason=%x]\n",
         this, reason));
 
     NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
     mOutputClosed = PR_TRUE;
     // check if event should affect entire transport
     if (NS_FAILED(reason) && (reason != NS_BASE_STREAM_CLOSED))
         mCondition = reason;                // XXX except if NS_FAILED(mCondition), right??
@@ -1349,17 +1349,17 @@ nsSocketTransport::OnMsgOutputClosed(nsr
             mPollFlags &= ~PR_POLL_WRITE;
         mOutput.OnSocketReady(reason);
     }
 }
 
 void
 nsSocketTransport::OnSocketConnected()
 {
-    LOG(("  advancing to STATE_TRANSFERRING\n"));
+    SOCKET_LOG(("  advancing to STATE_TRANSFERRING\n"));
 
     mPollFlags = (PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT);
     mPollTimeout = mTimeouts[TIMEOUT_READ_WRITE];
     mState = STATE_TRANSFERRING;
 
     // assign mFD (must do this within the transport lock), but take care not
     // to trample over mFDref if mFD is already set.
     {
@@ -1386,57 +1386,57 @@ nsSocketTransport::GetFD_Locked()
 }
 
 void
 nsSocketTransport::ReleaseFD_Locked(PRFileDesc *fd)
 {
     NS_ASSERTION(mFD == fd, "wrong fd");
 
     if (--mFDref == 0) {
-        LOG(("nsSocketTransport: calling PR_Close [this=%x]\n", this));
+        SOCKET_LOG(("nsSocketTransport: calling PR_Close [this=%x]\n", this));
         PR_Close(mFD);
         mFD = nsnull;
     }
 }
 
 //-----------------------------------------------------------------------------
 // socket event handler impl
 
 void
 nsSocketTransport::OnSocketEvent(PRUint32 type, nsresult status, nsISupports *param)
 {
-    LOG(("nsSocketTransport::OnSocketEvent [this=%p type=%u status=%x param=%p]\n",
+    SOCKET_LOG(("nsSocketTransport::OnSocketEvent [this=%p type=%u status=%x param=%p]\n",
         this, type, status, param));
 
     if (NS_FAILED(mCondition)) {
         // block event since we're apparently already dead.
-        LOG(("  blocking event [condition=%x]\n", mCondition));
+        SOCKET_LOG(("  blocking event [condition=%x]\n", mCondition));
         //
         // notify input/output streams in case either has a pending notify.
         //
         mInput.OnSocketReady(mCondition);
         mOutput.OnSocketReady(mCondition);
         return;
     }
 
     switch (type) {
     case MSG_ENSURE_CONNECT:
-        LOG(("  MSG_ENSURE_CONNECT\n"));
+        SOCKET_LOG(("  MSG_ENSURE_CONNECT\n"));
         //
         // ensure that we have created a socket, attached it, and have a
         // connection.
         //
         if (mState == STATE_CLOSED)
             mCondition = ResolveHost();
         else
-            LOG(("  ignoring redundant event\n"));
+            SOCKET_LOG(("  ignoring redundant event\n"));
         break;
 
     case MSG_DNS_LOOKUP_COMPLETE:
-        LOG(("  MSG_DNS_LOOKUP_COMPLETE\n"));
+        SOCKET_LOG(("  MSG_DNS_LOOKUP_COMPLETE\n"));
         mDNSRequest = 0;
         if (param) {
             mDNSRecord = static_cast<nsIDNSRecord *>(param);
             mDNSRecord->GetNextAddr(SocketPort(), &mNetAddr);
         }
         // status contains DNS lookup status
         if (NS_FAILED(status)) {
             // When using a HTTP proxy, NS_ERROR_UNKNOWN_HOST means the HTTP 
@@ -1454,63 +1454,63 @@ nsSocketTransport::OnSocketEvent(PRUint3
             mCondition = InitiateSocket();
         break;
 
     case MSG_RETRY_INIT_SOCKET:
         mCondition = InitiateSocket();
         break;
 
     case MSG_INPUT_CLOSED:
-        LOG(("  MSG_INPUT_CLOSED\n"));
+        SOCKET_LOG(("  MSG_INPUT_CLOSED\n"));
         OnMsgInputClosed(status);
         break;
 
     case MSG_INPUT_PENDING:
-        LOG(("  MSG_INPUT_PENDING\n"));
+        SOCKET_LOG(("  MSG_INPUT_PENDING\n"));
         OnMsgInputPending();
         break;
 
     case MSG_OUTPUT_CLOSED:
-        LOG(("  MSG_OUTPUT_CLOSED\n"));
+        SOCKET_LOG(("  MSG_OUTPUT_CLOSED\n"));
         OnMsgOutputClosed(status);
         break;
 
     case MSG_OUTPUT_PENDING:
-        LOG(("  MSG_OUTPUT_PENDING\n"));
+        SOCKET_LOG(("  MSG_OUTPUT_PENDING\n"));
         OnMsgOutputPending();
         break;
     case MSG_TIMEOUT_CHANGED:
-        LOG(("  MSG_TIMEOUT_CHANGED\n"));
+        SOCKET_LOG(("  MSG_TIMEOUT_CHANGED\n"));
         mPollTimeout = mTimeouts[(mState == STATE_TRANSFERRING)
           ? TIMEOUT_READ_WRITE : TIMEOUT_CONNECT];
         break;
     default:
-        LOG(("  unhandled event!\n"));
+        SOCKET_LOG(("  unhandled event!\n"));
     }
     
     if (NS_FAILED(mCondition)) {
-        LOG(("  after event [this=%x cond=%x]\n", this, mCondition));
+        SOCKET_LOG(("  after event [this=%x cond=%x]\n", this, mCondition));
         if (!mAttached) // need to process this error ourselves...
             OnSocketDetached(nsnull);
     }
     else if (mPollFlags == PR_POLL_EXCEPT)
         mPollFlags = 0; // make idle
 }
 
 //-----------------------------------------------------------------------------
 // socket handler impl
 
 void
 nsSocketTransport::OnSocketReady(PRFileDesc *fd, PRInt16 outFlags)
 {
-    LOG(("nsSocketTransport::OnSocketReady [this=%x outFlags=%hd]\n",
+    SOCKET_LOG(("nsSocketTransport::OnSocketReady [this=%x outFlags=%hd]\n",
         this, outFlags));
 
     if (outFlags == -1) {
-        LOG(("socket timeout expired\n"));
+        SOCKET_LOG(("socket timeout expired\n"));
         mCondition = NS_ERROR_NET_TIMEOUT;
         return;
     }
 
     if (mState == STATE_TRANSFERRING) {
         // if waiting to write and socket is writable or hit an exception.
         if ((mPollFlags & PR_POLL_WRITE) && (outFlags & ~PR_POLL_READ)) {
             // assume that we won't need to poll any longer (the stream will
@@ -1552,34 +1552,34 @@ nsSocketTransport::OnSocketReady(PRFileD
             } 
             else {
                 //
                 // else, the connection failed...
                 //
                 mCondition = ErrorAccordingToNSPR(code);
                 if ((mCondition == NS_ERROR_CONNECTION_REFUSED) && !mProxyHost.IsEmpty())
                     mCondition = NS_ERROR_PROXY_CONNECTION_REFUSED;
-                LOG(("  connection failed! [reason=%x]\n", mCondition));
+                SOCKET_LOG(("  connection failed! [reason=%x]\n", mCondition));
             }
         }
     }
     else {
         NS_ERROR("unexpected socket state");
         mCondition = NS_ERROR_UNEXPECTED;
     }
 
     if (mPollFlags == PR_POLL_EXCEPT)
         mPollFlags = 0; // make idle
 }
 
 // called on the socket thread only
 void
 nsSocketTransport::OnSocketDetached(PRFileDesc *fd)
 {
-    LOG(("nsSocketTransport::OnSocketDetached [this=%x cond=%x]\n",
+    SOCKET_LOG(("nsSocketTransport::OnSocketDetached [this=%x cond=%x]\n",
         this, mCondition));
 
     NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
     // if we didn't initiate this detach, then be sure to pass an error
     // condition up to our consumers.  (e.g., STS is shutting down.)
     if (NS_SUCCEEDED(mCondition))
         mCondition = NS_ERROR_ABORT;
@@ -1646,17 +1646,17 @@ NS_IMPL_CI_INTERFACE_GETTER3(nsSocketTra
                              nsIDNSListener)
 
 NS_IMETHODIMP
 nsSocketTransport::OpenInputStream(PRUint32 flags,
                                    PRUint32 segsize,
                                    PRUint32 segcount,
                                    nsIInputStream **result)
 {
-    LOG(("nsSocketTransport::OpenInputStream [this=%x flags=%x]\n",
+    SOCKET_LOG(("nsSocketTransport::OpenInputStream [this=%x flags=%x]\n",
         this, flags));
 
     NS_ENSURE_TRUE(!mInput.IsReferenced(), NS_ERROR_UNEXPECTED);
 
     nsresult rv;
     nsCOMPtr<nsIAsyncInputStream> pipeIn;
 
     if (!(flags & OPEN_UNBUFFERED) || (flags & OPEN_BLOCKING)) {
@@ -1694,17 +1694,17 @@ nsSocketTransport::OpenInputStream(PRUin
 }
 
 NS_IMETHODIMP
 nsSocketTransport::OpenOutputStream(PRUint32 flags,
                                     PRUint32 segsize,
                                     PRUint32 segcount,
                                     nsIOutputStream **result)
 {
-    LOG(("nsSocketTransport::OpenOutputStream [this=%x flags=%x]\n",
+    SOCKET_LOG(("nsSocketTransport::OpenOutputStream [this=%x flags=%x]\n",
         this, flags));
 
     NS_ENSURE_TRUE(!mOutput.IsReferenced(), NS_ERROR_UNEXPECTED);
 
     nsresult rv;
     nsCOMPtr<nsIAsyncOutputStream> pipeOut;
     if (!(flags & OPEN_UNBUFFERED) || (flags & OPEN_BLOCKING)) {
         // XXX if the caller wants blocking, then the caller also gets buffered!
--- a/netwerk/base/src/nsSocketTransportService2.cpp
+++ b/netwerk/base/src/nsSocketTransportService2.cpp
@@ -112,17 +112,17 @@ nsSocketTransportService::GetThreadSafel
     nsIThread* result = mThread;
     NS_IF_ADDREF(result);
     return result;
 }
 
 NS_IMETHODIMP
 nsSocketTransportService::Dispatch(nsIRunnable *event, PRUint32 flags)
 {
-    LOG(("STS dispatch [%p]\n", event));
+    SOCKET_LOG(("STS dispatch [%p]\n", event));
 
     nsCOMPtr<nsIThread> thread = GetThreadSafely();
     NS_ENSURE_TRUE(thread, NS_ERROR_NOT_INITIALIZED);
     nsresult rv = thread->Dispatch(event, flags);
     if (rv == NS_ERROR_UNEXPECTED) {
         // Thread is no longer accepting events. We must have just shut it
         // down on the main thread. Pretend we never saw it.
         rv = NS_ERROR_NOT_INITIALIZED;
@@ -139,32 +139,32 @@ nsSocketTransportService::IsOnCurrentThr
 }
 
 //-----------------------------------------------------------------------------
 // socket api (socket thread only)
 
 NS_IMETHODIMP
 nsSocketTransportService::NotifyWhenCanAttachSocket(nsIRunnable *event)
 {
-    LOG(("nsSocketTransportService::NotifyWhenCanAttachSocket\n"));
+    SOCKET_LOG(("nsSocketTransportService::NotifyWhenCanAttachSocket\n"));
 
     NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
     if (CanAttachSocket()) {
         return Dispatch(event, NS_DISPATCH_NORMAL);
     }
 
     mPendingSocketQ.PutEvent(event);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSocketTransportService::AttachSocket(PRFileDesc *fd, nsASocketHandler *handler)
 {
-    LOG(("nsSocketTransportService::AttachSocket [handler=%x]\n", handler));
+    SOCKET_LOG(("nsSocketTransportService::AttachSocket [handler=%x]\n", handler));
 
     NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
     if (!CanAttachSocket()) {
         return NS_ERROR_NOT_AVAILABLE;
     }
 
     SocketContext sock;
@@ -176,17 +176,17 @@ nsSocketTransportService::AttachSocket(P
     if (NS_SUCCEEDED(rv))
         NS_ADDREF(handler);
     return rv;
 }
 
 nsresult
 nsSocketTransportService::DetachSocket(SocketContext *sock)
 {
-    LOG(("nsSocketTransportService::DetachSocket [handler=%x]\n", sock->mHandler));
+    SOCKET_LOG(("nsSocketTransportService::DetachSocket [handler=%x]\n", sock->mHandler));
 
     // inform the handler that this socket is going away
     sock->mHandler->OnSocketDetached(sock->mFD);
 
     // cleanup
     sock->mFD = nsnull;
     NS_RELEASE(sock->mHandler);
 
@@ -208,83 +208,83 @@ nsSocketTransportService::DetachSocket(S
         return Dispatch(event, NS_DISPATCH_NORMAL);
     }
     return NS_OK;
 }
 
 nsresult
 nsSocketTransportService::AddToPollList(SocketContext *sock)
 {
-    LOG(("nsSocketTransportService::AddToPollList [handler=%x]\n", sock->mHandler));
+    SOCKET_LOG(("nsSocketTransportService::AddToPollList [handler=%x]\n", sock->mHandler));
 
     if (mActiveCount == NS_SOCKET_MAX_COUNT) {
         NS_ERROR("too many active sockets");
         return NS_ERROR_UNEXPECTED;
     }
 
     mActiveList[mActiveCount] = *sock;
     mActiveCount++;
 
     mPollList[mActiveCount].fd = sock->mFD;
     mPollList[mActiveCount].in_flags = sock->mHandler->mPollFlags;
     mPollList[mActiveCount].out_flags = 0;
 
-    LOG(("  active=%u idle=%u\n", mActiveCount, mIdleCount));
+    SOCKET_LOG(("  active=%u idle=%u\n", mActiveCount, mIdleCount));
     return NS_OK;
 }
 
 void
 nsSocketTransportService::RemoveFromPollList(SocketContext *sock)
 {
-    LOG(("nsSocketTransportService::RemoveFromPollList [handler=%x]\n", sock->mHandler));
+    SOCKET_LOG(("nsSocketTransportService::RemoveFromPollList [handler=%x]\n", sock->mHandler));
 
     PRUint32 index = sock - mActiveList;
     NS_ASSERTION(index < NS_SOCKET_MAX_COUNT, "invalid index");
 
-    LOG(("  index=%u mActiveCount=%u\n", index, mActiveCount));
+    SOCKET_LOG(("  index=%u mActiveCount=%u\n", index, mActiveCount));
 
     if (index != mActiveCount-1) {
         mActiveList[index] = mActiveList[mActiveCount-1];
         mPollList[index+1] = mPollList[mActiveCount];
     }
     mActiveCount--;
 
-    LOG(("  active=%u idle=%u\n", mActiveCount, mIdleCount));
+    SOCKET_LOG(("  active=%u idle=%u\n", mActiveCount, mIdleCount));
 }
 
 nsresult
 nsSocketTransportService::AddToIdleList(SocketContext *sock)
 {
-    LOG(("nsSocketTransportService::AddToIdleList [handler=%x]\n", sock->mHandler));
+    SOCKET_LOG(("nsSocketTransportService::AddToIdleList [handler=%x]\n", sock->mHandler));
 
     if (mIdleCount == NS_SOCKET_MAX_COUNT) {
         NS_ERROR("too many idle sockets");
         return NS_ERROR_UNEXPECTED;
     }
 
     mIdleList[mIdleCount] = *sock;
     mIdleCount++;
 
-    LOG(("  active=%u idle=%u\n", mActiveCount, mIdleCount));
+    SOCKET_LOG(("  active=%u idle=%u\n", mActiveCount, mIdleCount));
     return NS_OK;
 }
 
 void
 nsSocketTransportService::RemoveFromIdleList(SocketContext *sock)
 {
-    LOG(("nsSocketTransportService::RemoveFromIdleList [handler=%x]\n", sock->mHandler));
+    SOCKET_LOG(("nsSocketTransportService::RemoveFromIdleList [handler=%x]\n", sock->mHandler));
 
     PRUint32 index = sock - &mIdleList[0];
     NS_ASSERTION(index < NS_SOCKET_MAX_COUNT, "invalid index");
 
     if (index != mIdleCount-1)
         mIdleList[index] = mIdleList[mIdleCount-1];
     mIdleCount--;
 
-    LOG(("  active=%u idle=%u\n", mActiveCount, mIdleCount));
+    SOCKET_LOG(("  active=%u idle=%u\n", mActiveCount, mIdleCount));
 }
 
 void
 nsSocketTransportService::MoveToIdleList(SocketContext *sock)
 {
     nsresult rv = AddToIdleList(sock);
     if (NS_FAILED(rv))
         DetachSocket(sock);
@@ -315,17 +315,17 @@ nsSocketTransportService::PollTimeout()
         // mPollTimeout could be less than mElapsedTime if setTimeout
         // was called with a value smaller than mElapsedTime.
         PRUint32 r = (s.mElapsedTime < s.mHandler->mPollTimeout)
           ? s.mHandler->mPollTimeout - s.mElapsedTime
           : 0;
         if (r < minR)
             minR = r;
     }
-    LOG(("poll timeout: %lu\n", minR));
+    SOCKET_LOG(("poll timeout: %lu\n", minR));
     return PR_SecondsToInterval(minR);
 }
 
 PRInt32
 nsSocketTransportService::Poll(PRBool wait, PRUint32 *interval)
 {
     PRPollDesc *pollList;
     PRUint32 pollCount;
@@ -347,23 +347,23 @@ nsSocketTransportService::Poll(PRBool wa
         pollTimeout = PR_MillisecondsToInterval(25);
     }
 
     if (!wait)
         pollTimeout = PR_INTERVAL_NO_WAIT;
 
     PRIntervalTime ts = PR_IntervalNow();
 
-    LOG(("    timeout = %i milliseconds\n",
+    SOCKET_LOG(("    timeout = %i milliseconds\n",
          PR_IntervalToMilliseconds(pollTimeout)));
     PRInt32 rv = PR_Poll(pollList, pollCount, pollTimeout);
 
     PRIntervalTime passedInterval = PR_IntervalNow() - ts;
 
-    LOG(("    ...returned after %i milliseconds\n",
+    SOCKET_LOG(("    ...returned after %i milliseconds\n",
          PR_IntervalToMilliseconds(passedInterval))); 
 
     *interval = PR_IntervalToSeconds(passedInterval);
     return rv;
 }
 
 //-----------------------------------------------------------------------------
 // xpcom api
@@ -404,17 +404,17 @@ nsSocketTransportService::Init()
         // NOTE: per bug 191739, this failure could also be caused by lack
         // of a loopback device on Windows and OS/2 platforms (NSPR creates
         // a loopback socket pair on these platforms to implement a pollable
         // event object).  if we can't create a pollable event, then we'll
         // have to "busy wait" to implement the socket event queue :-(
         //
         if (!mThreadEvent) {
             NS_WARNING("running socket transport thread without a pollable event");
-            LOG(("running socket transport thread without a pollable event"));
+            SOCKET_LOG(("running socket transport thread without a pollable event"));
         }
     }
     
     NS_TIME_FUNCTION_MARK("Created thread");
 
     nsCOMPtr<nsIThread> thread;
     nsresult rv = NS_NewThread(getter_AddRefs(thread), this);
     if (NS_FAILED(rv)) return rv;
@@ -435,17 +435,17 @@ nsSocketTransportService::Init()
     mInitialized = PR_TRUE;
     return NS_OK;
 }
 
 // called from main thread only
 NS_IMETHODIMP
 nsSocketTransportService::Shutdown()
 {
-    LOG(("nsSocketTransportService::Shutdown\n"));
+    SOCKET_LOG(("nsSocketTransportService::Shutdown\n"));
 
     NS_ENSURE_STATE(NS_IsMainThread());
 
     if (!mInitialized)
         return NS_OK;
 
     if (mShuttingDown)
         return NS_ERROR_UNEXPECTED;
@@ -554,17 +554,17 @@ nsSocketTransportService::AfterProcessNe
                                                 PRUint32 depth)
 {
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSocketTransportService::Run()
 {
-    LOG(("STS thread init\n"));
+    SOCKET_LOG(("STS thread init\n"));
 
     gSocketThread = PR_GetCurrentThread();
 
     // add thread event to poll list (mThreadEvent may be NULL)
     mPollList[0].fd = mThreadEvent;
     mPollList[0].in_flags = PR_POLL_READ;
     mPollList[0].out_flags = 0;
 
@@ -584,39 +584,39 @@ nsSocketTransportService::Run()
             if (mShuttingDown)
                 break;
         }
 
         // wait for and process the next pending event
         NS_ProcessNextEvent(thread);
     }
 
-    LOG(("STS shutting down thread\n"));
+    SOCKET_LOG(("STS shutting down thread\n"));
 
     // detach any sockets
     PRInt32 i;
     for (i=mActiveCount-1; i>=0; --i)
         DetachSocket(&mActiveList[i]);
     for (i=mIdleCount-1; i>=0; --i)
         DetachSocket(&mIdleList[i]);
 
     // Final pass over the event queue. This makes sure that events posted by
     // socket detach handlers get processed.
     NS_ProcessPendingEvents(thread);
 
     gSocketThread = nsnull;
 
-    LOG(("STS thread exit\n"));
+    SOCKET_LOG(("STS thread exit\n"));
     return NS_OK;
 }
 
 nsresult
 nsSocketTransportService::DoPollIteration(PRBool wait)
 {
-    LOG(("STS poll iter [%d]\n", wait));
+    SOCKET_LOG(("STS poll iter [%d]\n", wait));
 
     PRInt32 i, count;
 
     //
     // poll loop
     //
     PRBool pollError = PR_FALSE;
 
@@ -624,17 +624,17 @@ nsSocketTransportService::DoPollIteratio
     // walk active list backwards to see if any sockets should actually be
     // idle, then walk the idle list backwards to see if any idle sockets
     // should become active.  take care to check only idle sockets that
     // were idle to begin with ;-)
     //
     count = mIdleCount;
     for (i=mActiveCount-1; i>=0; --i) {
         //---
-        LOG(("  active [%u] { handler=%x condition=%x pollflags=%hu }\n", i,
+        SOCKET_LOG(("  active [%u] { handler=%x condition=%x pollflags=%hu }\n", i,
             mActiveList[i].mHandler,
             mActiveList[i].mHandler->mCondition,
             mActiveList[i].mHandler->mPollFlags));
         //---
         if (NS_FAILED(mActiveList[i].mHandler->mCondition))
             DetachSocket(&mActiveList[i]);
         else {
             PRUint16 in_flags = mActiveList[i].mHandler->mPollFlags;
@@ -644,35 +644,35 @@ nsSocketTransportService::DoPollIteratio
                 // update poll flags
                 mPollList[i+1].in_flags = in_flags;
                 mPollList[i+1].out_flags = 0;
             }
         }
     }
     for (i=count-1; i>=0; --i) {
         //---
-        LOG(("  idle [%u] { handler=%x condition=%x pollflags=%hu }\n", i,
+        SOCKET_LOG(("  idle [%u] { handler=%x condition=%x pollflags=%hu }\n", i,
             mIdleList[i].mHandler,
             mIdleList[i].mHandler->mCondition,
             mIdleList[i].mHandler->mPollFlags));
         //---
         if (NS_FAILED(mIdleList[i].mHandler->mCondition))
             DetachSocket(&mIdleList[i]);
         else if (mIdleList[i].mHandler->mPollFlags != 0)
             MoveToPollList(&mIdleList[i]);
     }
 
-    LOG(("  calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount));
+    SOCKET_LOG(("  calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount));
 
     // Measures seconds spent while blocked on PR_Poll
     PRUint32 pollInterval;
 
     PRInt32 n = Poll(wait, &pollInterval);
     if (n < 0) {
-        LOG(("  PR_Poll error [%d]\n", PR_GetError()));
+        SOCKET_LOG(("  PR_Poll error [%d]\n", PR_GetError()));
         pollError = PR_TRUE;
     }
     else {
         //
         // service "active" sockets...
         //
         for (i=0; i<PRInt32(mActiveCount); ++i) {
             PRPollDesc &desc = mPollList[i+1];
@@ -717,17 +717,17 @@ nsSocketTransportService::DoPollIteratio
                 {
                     nsAutoLock lock(mLock);
                     PR_DestroyPollableEvent(mThreadEvent);
                     mThreadEvent = PR_NewPollableEvent();
                 }
                 if (!mThreadEvent) {
                     NS_WARNING("running socket transport thread without "
                                "a pollable event");
-                    LOG(("running socket transport thread without "
+                    SOCKET_LOG(("running socket transport thread without "
                          "a pollable event"));
                 }
                 mPollList[0].fd = mThreadEvent;
                 // mPollList[0].in_flags was already set to PR_POLL_READ
                 // in Run().
                 mPollList[0].out_flags = 0;
             }
         }
--- a/netwerk/base/src/nsSocketTransportService2.h
+++ b/netwerk/base/src/nsSocketTransportService2.h
@@ -54,18 +54,18 @@
 //-----------------------------------------------------------------------------
 
 #if defined(PR_LOGGING)
 //
 // set NSPR_LOG_MODULES=nsSocketTransport:5
 //
 extern PRLogModuleInfo *gSocketTransportLog;
 #endif
-#define LOG(args)     PR_LOG(gSocketTransportLog, PR_LOG_DEBUG, args)
-#define LOG_ENABLED() PR_LOG_TEST(gSocketTransportLog, PR_LOG_DEBUG)
+#define SOCKET_LOG(args)     PR_LOG(gSocketTransportLog, PR_LOG_DEBUG, args)
+#define SOCKET_LOG_ENABLED() PR_LOG_TEST(gSocketTransportLog, PR_LOG_DEBUG)
 
 //-----------------------------------------------------------------------------
 
 #define NS_SOCKET_MAX_COUNT    50
 #define NS_SOCKET_POLL_TIMEOUT PR_INTERVAL_NO_TIMEOUT
 
 //-----------------------------------------------------------------------------
 
--- a/netwerk/cache/nsCacheService.cpp
+++ b/netwerk/cache/nsCacheService.cpp
@@ -788,24 +788,16 @@ nsCacheService::DispatchToCacheIOThread(
     if (!gService->mCacheIOThread) return NS_ERROR_NOT_AVAILABLE;
     return gService->mCacheIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
 }
 
 
 PRBool
 nsCacheProfilePrefObserver::DiskCacheEnabled()
 {
-#ifdef MOZ_IPC
-    // Bad Things (tm) are likely to happen if child and parent both write to
-    // disk cache.  
-    // - TODO: remove once we turn off caching entirely in child (bug 559714)
-    if (mozilla::net::IsNeckoChild())
-        return PR_FALSE;
-#endif
-
     if ((mDiskCacheCapacity == 0) || (!mDiskCacheParentDirectory))  return PR_FALSE;
     return mDiskCacheEnabled;
 }
 
 
 PRBool
 nsCacheProfilePrefObserver::OfflineCacheEnabled()
 {
@@ -853,23 +845,16 @@ nsCacheProfilePrefObserver::MemoryCacheE
  *  x = log2(K) - 14
  *  C = x^2/3 + x + 2/3 + 0.1 (0.1 for rounding)
  *  if (C > 32) C = 32
  */
 
 PRInt32
 nsCacheProfilePrefObserver::MemoryCacheCapacity()
 {
-#ifdef MOZ_IPC
-    // For now use small memory cache (1 MB) on child, just for FTP/wyciwyg
-    // - TODO: remove once we turn off caching entirely in child (bug 559714)
-    if (mozilla::net::IsNeckoChild())
-        return 1024; 
-#endif
-
     PRInt32 capacity = mMemoryCacheCapacity;
     if (capacity >= 0) {
         CACHE_LOG_DEBUG(("Memory cache capacity forced to %d\n", capacity));
         return capacity;
     }
 
     static PRUint64 bytes = PR_GetPhysicalMemorySize();
     CACHE_LOG_DEBUG(("Physical Memory size is %llu\n", bytes));
--- a/netwerk/protocol/http/HttpChannelParentListener.cpp
+++ b/netwerk/protocol/http/HttpChannelParentListener.cpp
@@ -138,16 +138,22 @@ NS_IMETHODIMP
 HttpChannelParentListener::GetInterface(const nsIID& aIID, void **result)
 {
   if (aIID.Equals(NS_GET_IID(nsIAuthPromptProvider))) {
     if (!mActiveChannel || !mActiveChannel->mTabParent)
       return NS_NOINTERFACE;
     return mActiveChannel->mTabParent->QueryInterface(aIID, result);
   }
 
+  if (aIID.Equals(NS_GET_IID(nsISecureBrowserUI))) {
+    if (!mActiveChannel || !mActiveChannel->mTabParent)
+      return NS_NOINTERFACE;
+    return mActiveChannel->mTabParent->QueryInterface(aIID, result);
+  }
+
   if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
     if (!mActiveChannel)
       return NS_NOINTERFACE;
     return mActiveChannel->QueryInterface(aIID, result);
   }
 
   // TODO: 575494: once we're confident we're handling all needed interfaces,
   // remove all code below and simply "return QueryInterface(aIID, result)"
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -201,16 +201,18 @@ nsHttpConnectionMgr::PruneDeadConnection
     }
 }
 
 void
 nsHttpConnectionMgr::StopPruneDeadConnectionsTimer()
 {
     LOG(("nsHttpConnectionMgr::StopPruneDeadConnectionsTimer\n"));
 
+    // Reset mTimeOfNextWakeUp so that we can find a new shortest value.
+    mTimeOfNextWakeUp = LL_MAXUINT;
     if (mTimer) {
         mTimer->Cancel();
         mTimer = NULL;
     }
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpConnectionMgr::nsIObserver
@@ -407,18 +409,18 @@ nsHttpConnectionMgr::PruneDeadConnection
             } else {
                 timeToNextExpire = PR_MIN(timeToNextExpire, conn->TimeToLive());
             }
         }
     }
 
     // If time to next expire found is shorter than time to next wake-up, we need to
     // change the time for next wake-up.
+    PRUint32 now = NowInSeconds();
     if (0 < ent->mIdleConns.Length()) {
-        PRUint32 now = NowInSeconds();
         PRUint64 timeOfNextExpire = now + timeToNextExpire;
         // If pruning of dead connections is not already scheduled to happen
         // or time found for next connection to expire is is before
         // mTimeOfNextWakeUp, we need to schedule the pruning to happen
         // after timeToNextExpire.
         if (!self->mTimer || timeOfNextExpire < self->mTimeOfNextWakeUp) {
             self->PruneDeadConnectionsAfter(timeToNextExpire);
         }
@@ -551,17 +553,18 @@ nsHttpConnectionMgr::ProcessPendingQForE
 PRBool
 nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 caps)
 {
     nsHttpConnectionInfo *ci = ent->mConnInfo;
 
     LOG(("nsHttpConnectionMgr::AtActiveConnectionLimit [ci=%s caps=%x]\n",
         ci->HashKey().get(), caps));
 
-    // use >= just to be safe
+    // If we have more active connections than the limit, then we're done --
+    // purging idle connections won't get us below it.
     if (mNumActiveConns >= mMaxConns) {
         LOG(("  num active conns == max conns\n"));
         return PR_TRUE;
     }
 
     nsHttpConnection *conn;
     PRInt32 i, totalCount, persistCount = 0;
     
@@ -597,21 +600,16 @@ void
 nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps,
                                    nsHttpConnection **result)
 {
     LOG(("nsHttpConnectionMgr::GetConnection [ci=%s caps=%x]\n",
         ent->mConnInfo->HashKey().get(), PRUint32(caps)));
 
     *result = nsnull;
 
-    if (AtActiveConnectionLimit(ent, caps)) {
-        LOG(("  at active connection limit!\n"));
-        return;
-    }
-
     nsHttpConnection *conn = nsnull;
 
     if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
         // search the idle connection list
         while (!conn && (ent->mIdleConns.Length() > 0)) {
             conn = ent->mIdleConns[0];
             // we check if the connection can be reused before even checking if
             // it is a "matching" connection.
@@ -619,45 +617,52 @@ nsHttpConnectionMgr::GetConnection(nsCon
                 LOG(("   dropping stale connection: [conn=%x]\n", conn));
                 conn->Close(NS_ERROR_ABORT);
                 NS_RELEASE(conn);
             }
             else
                 LOG(("   reusing connection [conn=%x]\n", conn));
             ent->mIdleConns.RemoveElementAt(0);
             mNumIdleConns--;
+
+            // If there are no idle connections left at all, we need to make
+            // sure that we are not pruning dead connections anymore.
+            if (0 == mNumIdleConns)
+                StopPruneDeadConnectionsTimer();
         }
     }
 
     if (!conn) {
-        // No reusable idle connection found for this entry. If there are no
-        // idle connections left at all, we need to make sure that we are not
-        // pruning dead connections anymore.
-        if (0 == mNumIdleConns)
-            StopPruneDeadConnectionsTimer();
+        // Check if we need to purge an idle connection. Note that we may have
+        // removed one above; if so, this will be a no-op. We do this before
+        // checking the active connection limit to catch the case where we do
+        // have an idle connection, but the purge timer hasn't fired yet.
+        // XXX this just purges a random idle connection.  we should instead
+        // enumerate the entire hash table to find the eldest idle connection.
+        if (mNumIdleConns && mNumIdleConns + mNumActiveConns + 1 >= mMaxConns)
+            mCT.Enumerate(PurgeOneIdleConnectionCB, this);
+
+        // Need to make a new TCP connection. First, we check if we've hit
+        // either the maximum connection limit globally or for this particular
+        // host or proxy. If we have, we're done.
+        if (AtActiveConnectionLimit(ent, caps)) {
+            LOG(("  at active connection limit!\n"));
+            return;
+        }
 
         conn = new nsHttpConnection();
         if (!conn)
             return;
         NS_ADDREF(conn);
 
         nsresult rv = conn->Init(ent->mConnInfo, mMaxRequestDelay);
         if (NS_FAILED(rv)) {
             NS_RELEASE(conn);
             return;
         }
-        
-        // We created a new connection that will become active, purge the
-        // oldest idle connection if we've reached the upper limit.
-        // This only needs to be done if there is a idle connection.
-        if (0 < mNumIdleConns && mNumIdleConns + mNumActiveConns + 1 > mMaxConns)
-            mCT.Enumerate(PurgeOneIdleConnectionCB, this);
-
-        // XXX this just purges a random idle connection.  we should instead
-        // enumerate the entire hash table to find the eldest idle connection.
     }
 
     *result = conn;
 }
 
 nsresult
 nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent,
                                          nsAHttpTransaction *trans,
@@ -927,16 +932,18 @@ nsHttpConnectionMgr::OnMsgProcessPending
     NS_RELEASE(ci);
 }
 
 void
 nsHttpConnectionMgr::OnMsgPruneDeadConnections(PRInt32, void *)
 {
     LOG(("nsHttpConnectionMgr::OnMsgPruneDeadConnections\n"));
 
+    // Reset mTimeOfNextWakeUp so that we can find a new shortest value.
+    mTimeOfNextWakeUp = LL_MAXUINT;
     if (mNumIdleConns > 0) 
         mCT.Enumerate(PruneDeadConnectionsCB, this);
 }
 
 void
 nsHttpConnectionMgr::OnMsgReclaimConnection(PRInt32, void *param)
 {
     LOG(("nsHttpConnectionMgr::OnMsgReclaimConnection [conn=%p]\n", param));
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -71,16 +71,17 @@
 #include "nsNetCID.h"
 #include "nsAutoLock.h"
 #include "prprf.h"
 #include "nsReadableUtils.h"
 #include "nsQuickSort.h"
 #include "nsNetUtil.h"
 #include "nsIOService.h"
 #include "nsAsyncRedirectVerifyHelper.h"
+#include "nsSocketTransportService2.h"
 
 #include "nsIXULAppInfo.h"
 
 #ifdef MOZ_IPC
 #include "mozilla/net/NeckoChild.h"
 #endif 
 
 #if defined(XP_UNIX) || defined(XP_BEOS)
@@ -849,17 +850,17 @@ nsHttpHandler::PrefsChanged(nsIPrefBranc
                 mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_REQUEST_DELAY,
                                       mMaxRequestDelay);
         }
     }
 
     if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
         rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val);
         if (NS_SUCCEEDED(rv)) {
-            mMaxConnections = (PRUint16) NS_CLAMP(val, 1, 0xffff);
+            mMaxConnections = (PRUint16) NS_CLAMP(val, 1, NS_SOCKET_MAX_COUNT);
             if (mConnMgr)
                 mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS,
                                       mMaxConnections);
         }
     }
 
     if (PREF_CHANGED(HTTP_PREF("max-connections-per-server"))) {
         rv = prefs->GetIntPref(HTTP_PREF("max-connections-per-server"), &val);
--- a/security/manager/ssl/src/Makefile.in
+++ b/security/manager/ssl/src/Makefile.in
@@ -97,16 +97,17 @@ CPPSRCS = 				\
   nsNTLMAuthModule.cpp \
   nsSmartCardMonitor.cpp \
   nsSmartCardEvent.cpp \
   nsStreamCipher.cpp \
   nsKeyModule.cpp \
   nsIdentityChecking.cpp \
   nsDataSignatureVerifier.cpp \
   nsRandomGenerator.cpp \
+  NSSErrorsService.cpp \
   $(NULL)
 
 ifdef MOZ_XUL
 CPPSRCS += nsCertTree.cpp
 endif
 
 ifdef MOZ_IPC
 CPPSRCS += nsNSSCertificateFakeTransport.cpp
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/src/NSSErrorsService.cpp
@@ -0,0 +1,189 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Personal Security Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Hubbie Shaw
+ *   Doug Turner <dougt@netscape.com>
+ *   Mitch Stoltz <mstoltz@netscape.com>
+ *   Brian Ryner <bryner@brianryner.com>
+ *   Kai Engert <kaie@netscape.com>
+ *   Vipul Gupta <vipul.gupta@sun.com>
+ *   Douglas Stebila <douglas@stebila.ca>
+ *   Kai Engert <kengert@redhat.com>
+ *   honzab.moz@firemni.cz
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "NSSErrorsService.h"
+
+#include "nsNSSComponent.h"
+#include "nsServiceManagerUtils.h"
+#include "secerr.h"
+#include "sslerr.h"
+
+#define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties"
+#define NSSERR_STRBUNDLE_URL "chrome://pipnss/locale/nsserrors.properties"
+
+namespace mozilla {
+namespace psm {
+
+NS_IMPL_ISUPPORTS1(NSSErrorsService, nsINSSErrorsService)
+
+nsresult
+NSSErrorsService::Init()
+{
+  nsresult rv;
+  nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
+  if (NS_FAILED(rv) || !bundleService) 
+    return NS_ERROR_FAILURE;
+  
+  bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL,
+                              getter_AddRefs(mPIPNSSBundle));
+  if (!mPIPNSSBundle)
+    rv = NS_ERROR_FAILURE;
+
+  bundleService->CreateBundle(NSSERR_STRBUNDLE_URL,
+                              getter_AddRefs(mNSSErrorsBundle));
+  if (!mNSSErrorsBundle)
+    rv = NS_ERROR_FAILURE;
+
+  return rv;
+}
+
+#define EXPECTED_SEC_ERROR_BASE (-0x2000)
+#define EXPECTED_SSL_ERROR_BASE (-0x3000)
+
+#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE
+#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code"
+/*
+ * Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000
+ * Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts.
+ * The current code also assumes that NSS library error codes are negative.
+ */
+#endif
+
+NS_IMETHODIMP
+NSSErrorsService::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval)
+{
+  if (!_retval)
+    return NS_ERROR_FAILURE;
+
+  *_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+NSSErrorsService::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode)
+{
+  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
+    return NS_ERROR_FAILURE;
+
+  if (!aXPCOMErrorCode)
+    return NS_ERROR_INVALID_ARG;
+
+  // The error codes within each module may be a 16 bit value.
+  // For simplicity let's use the positive value of the NSS code.
+
+  *aXPCOMErrorCode =
+    NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY,
+                              -1 * aNSPRCode);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+NSSErrorsService::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass)
+{
+  NS_ENSURE_ARG(aErrorClass);
+
+  if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
+      || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
+    return NS_ERROR_FAILURE;
+  
+  PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
+
+  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
+    return NS_ERROR_FAILURE;
+
+  switch (aNSPRCode)
+  {
+    case SEC_ERROR_UNKNOWN_ISSUER:
+    case SEC_ERROR_CA_CERT_INVALID:
+    case SEC_ERROR_UNTRUSTED_ISSUER:
+    case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+    case SEC_ERROR_UNTRUSTED_CERT:
+    case SEC_ERROR_INADEQUATE_KEY_USAGE:
+    case SSL_ERROR_BAD_CERT_DOMAIN:
+    case SEC_ERROR_EXPIRED_CERTIFICATE:
+      *aErrorClass = ERROR_CLASS_BAD_CERT;
+      break;
+    default:
+      *aErrorClass = ERROR_CLASS_SSL_PROTOCOL;
+      break;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+NSSErrorsService::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage)
+{
+  if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
+      || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
+    return NS_ERROR_FAILURE;
+  
+  PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
+
+  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIStringBundle> theBundle = mPIPNSSBundle;
+  const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode);
+
+  if (!id_str) {
+    id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode);
+    theBundle = mNSSErrorsBundle;
+  }
+
+  if (!id_str || !theBundle)
+    return NS_ERROR_FAILURE;
+
+  nsAutoString msg;
+  nsresult rv =
+    theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(),
+                                 getter_Copies(msg));
+  if (NS_SUCCEEDED(rv)) {
+    aErrorMessage = msg;
+  }
+  return rv;
+}
+
+} // psm
+} // mozilla
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/src/NSSErrorsService.h
@@ -0,0 +1,68 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Personal Security Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Hubbie Shaw
+ *   Doug Turner <dougt@netscape.com>
+ *   Brian Ryner <bryner@brianryner.com>
+ *   Kai Engert <kaie@netscape.com>
+ *   Kai Engert <kengert@redhat.com>
+ *   honzab.moz@firemni.cz
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsINSSErrorsService.h"
+
+#include "nsIStringBundle.h"
+#include "nsCOMPtr.h"
+
+namespace mozilla {
+namespace psm {
+
+class NSSErrorsService : public nsINSSErrorsService
+{
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSINSSERRORSSERVICE
+
+public:
+  nsresult Init();
+
+private:
+  nsCOMPtr<nsIStringBundle> mPIPNSSBundle;
+  nsCOMPtr<nsIStringBundle> mNSSErrorsBundle;
+};
+
+} // psm
+} // mozilla
+
+#define NS_NSSERRORSSERVICE_CID \
+  { 0x9ef18451, 0xa157, 0x4d17, { 0x81, 0x32, 0x47, 0xaf, 0xef, 0x21, 0x36, 0x89 } }
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
@@ -1948,24 +1948,23 @@ nsNSSComponent::Init()
   if (bec) {
     bec->ForwardTo(this);
   }
 
   return rv;
 }
 
 /* nsISupports Implementation for the class */
-NS_IMPL_THREADSAFE_ISUPPORTS7(nsNSSComponent,
+NS_IMPL_THREADSAFE_ISUPPORTS6(nsNSSComponent,
                               nsISignatureVerifier,
                               nsIEntropyCollector,
                               nsINSSComponent,
                               nsIObserver,
                               nsISupportsWeakReference,
-                              nsITimerCallback,
-                              nsINSSErrorsService)
+                              nsITimerCallback)
 
 
 /* Callback functions for decoder. For now, use empty/default functions. */
 static void ContentCallback(void *arg, 
                                            const char *buf,
                                            unsigned long len)
 {
 }
@@ -2448,122 +2447,16 @@ nsNSSComponent::RememberCert(CERTCertifi
   
   if (!PL_HashTableAdd(hashTableCerts, (void*)&myDupCert->certKey, myDupCert)) {
     CERT_DestroyCertificate(myDupCert);
   }
   
   return NS_OK;
 }
 
-#define EXPECTED_SEC_ERROR_BASE (-0x2000)
-#define EXPECTED_SSL_ERROR_BASE (-0x3000)
-
-#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE
-#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code"
-/*
- * Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000
- * Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts.
- * The current code also assumes that NSS library error codes are negative.
- */
-#endif
-
-NS_IMETHODIMP
-nsNSSComponent::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval)
-{
-  if (!_retval)
-    return NS_ERROR_FAILURE;
-
-  *_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsNSSComponent::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode)
-{
-  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
-    return NS_ERROR_FAILURE;
-
-  if (!aXPCOMErrorCode)
-    return NS_ERROR_INVALID_ARG;
-
-  // The error codes within each module may be a 16 bit value.
-  // For simplicity let's use the positive value of the NSS code.
-
-  *aXPCOMErrorCode =
-    NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY,
-                              -1 * aNSPRCode);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsNSSComponent::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass)
-{
-  NS_ENSURE_ARG(aErrorClass);
-
-  if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
-      || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
-    return NS_ERROR_FAILURE;
-  
-  PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
-
-  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
-    return NS_ERROR_FAILURE;
-
-  switch (aNSPRCode)
-  {
-    case SEC_ERROR_UNKNOWN_ISSUER:
-    case SEC_ERROR_CA_CERT_INVALID:
-    case SEC_ERROR_UNTRUSTED_ISSUER:
-    case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
-    case SEC_ERROR_UNTRUSTED_CERT:
-    case SEC_ERROR_INADEQUATE_KEY_USAGE:
-    case SSL_ERROR_BAD_CERT_DOMAIN:
-    case SEC_ERROR_EXPIRED_CERTIFICATE:
-      *aErrorClass = ERROR_CLASS_BAD_CERT;
-      break;
-    default:
-      *aErrorClass = ERROR_CLASS_SSL_PROTOCOL;
-      break;
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsNSSComponent::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage)
-{
-  if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
-      || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
-    return NS_ERROR_FAILURE;
-  
-  PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
-
-  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsIStringBundle> theBundle = mPIPNSSBundle;
-  const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode);
-
-  if (!id_str) {
-    id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode);
-    theBundle = mNSSErrorsBundle;
-  }
-
-  if (!id_str || !theBundle)
-    return NS_ERROR_FAILURE;
-
-  nsAutoString msg;
-  nsresult rv =
-    theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(),
-                                 getter_Copies(msg));
-  if (NS_SUCCEEDED(rv)) {
-    aErrorMessage = msg;
-  }
-  return rv;
-}
-
 void
 nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject)
 {
   if (mShutdownObjectList->isUIActive()) {
     ShowAlert(ai_crypto_ui_active);
     nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
     if (status) {
       status->VetoChange();
--- a/security/manager/ssl/src/nsNSSComponent.h
+++ b/security/manager/ssl/src/nsNSSComponent.h
@@ -234,31 +234,29 @@ class nsSSLThread;
 class nsCertVerificationThread;
 
 // Implementation of the PSM component interface.
 class nsNSSComponent : public nsISignatureVerifier,
                        public nsIEntropyCollector,
                        public nsINSSComponent,
                        public nsIObserver,
                        public nsSupportsWeakReference,
-                       public nsITimerCallback,
-                       public nsINSSErrorsService
+                       public nsITimerCallback
 {
 public:
   NS_DEFINE_STATIC_CID_ACCESSOR( NS_NSSCOMPONENT_CID )
 
   nsNSSComponent();
   virtual ~nsNSSComponent();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISIGNATUREVERIFIER
   NS_DECL_NSIENTROPYCOLLECTOR
   NS_DECL_NSIOBSERVER
   NS_DECL_NSITIMERCALLBACK
-  NS_DECL_NSINSSERRORSSERVICE
 
   NS_METHOD Init();
 
   NS_IMETHOD GetPIPNSSBundleString(const char *name,
                                    nsAString &outString);
   NS_IMETHOD PIPBundleFormatStringFromName(const char *name,
                                            const PRUnichar **params,
                                            PRUint32 numParams,
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -374,16 +374,21 @@ nsNSSSocketInfo::EnsureDocShellDependent
   // We'll look at the presence of a security UI object inside docshell.
   // If the docshell wants the lock icon, you'll get the ssl error pages, too.
   // This is helpful to distinguish from all other contexts, like mail windows,
   // or any other SSL connections running in the background.
   // We must query it now and remember, because fatal SSL errors will come 
   // with a socket close, and the socket transport might detach the callbacks 
   // instance prior to our error reporting.
 
+  nsISecureBrowserUI* secureUI = nsnull;
+#ifdef MOZ_IPC
+  CallGetInterface(proxiedCallbacks.get(), &secureUI);
+#endif
+
   nsCOMPtr<nsIDocShell> docshell;
 
   nsCOMPtr<nsIDocShellTreeItem> item(do_GetInterface(proxiedCallbacks));
   if (item)
   {
     nsCOMPtr<nsIDocShellTreeItem> proxiedItem;
     nsCOMPtr<nsIDocShellTreeItem> rootItem;
     NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
@@ -392,46 +397,46 @@ nsNSSSocketInfo::EnsureDocShellDependent
                          NS_PROXY_SYNC,
                          getter_AddRefs(proxiedItem));
 
     proxiedItem->GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
     docshell = do_QueryInterface(rootItem);
     NS_ASSERTION(docshell, "rootItem do_QI is null");
   }
 
-  if (docshell)
+  if (docshell && !secureUI)
   {
     nsCOMPtr<nsIDocShell> proxiedDocShell;
     NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
                          NS_GET_IID(nsIDocShell),
                          docshell.get(),
                          NS_PROXY_SYNC,
                          getter_AddRefs(proxiedDocShell));
-    nsISecureBrowserUI* secureUI = nsnull;
     if (proxiedDocShell)
       proxiedDocShell->GetSecurityUI(&secureUI);
-    if (secureUI)
-    {
-      nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
-      NS_ProxyRelease(mainThread, secureUI, PR_FALSE);
-      mExternalErrorReporting = PR_TRUE;
-
-      // If this socket is associated to a docshell, let's try to remember
-      // the currently used cert. If this socket gets a notification from NSS
-      // having the same raw socket, we can keep the PSM wrapper object
-      // and all the data it has cached (like verification results).
-      nsCOMPtr<nsISSLStatusProvider> statprov = do_QueryInterface(secureUI);
-      if (statprov) {
-        nsCOMPtr<nsISupports> isup_stat;
-        statprov->GetSSLStatus(getter_AddRefs(isup_stat));
-        if (isup_stat) {
-          nsCOMPtr<nsISSLStatus> sslstat = do_QueryInterface(isup_stat);
-          if (sslstat) {
-            sslstat->GetServerCert(getter_AddRefs(mPreviousCert));
-          }
+  }
+
+  if (secureUI)
+  {
+    nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
+    NS_ProxyRelease(mainThread, secureUI, PR_FALSE);
+    mExternalErrorReporting = PR_TRUE;
+
+    // If this socket is associated to a docshell, let's try to remember
+    // the currently used cert. If this socket gets a notification from NSS
+    // having the same raw socket, we can keep the PSM wrapper object
+    // and all the data it has cached (like verification results).
+    nsCOMPtr<nsISSLStatusProvider> statprov = do_QueryInterface(secureUI);
+    if (statprov) {
+      nsCOMPtr<nsISupports> isup_stat;
+      statprov->GetSSLStatus(getter_AddRefs(isup_stat));
+      if (isup_stat) {
+        nsCOMPtr<nsISSLStatus> sslstat = do_QueryInterface(isup_stat);
+        if (sslstat) {
+          sslstat->GetServerCert(getter_AddRefs(mPreviousCert));
         }
       }
     }
   }
 
   return NS_OK;
 }
 
--- a/security/manager/ssl/src/nsNSSModule.cpp
+++ b/security/manager/ssl/src/nsNSSModule.cpp
@@ -73,16 +73,17 @@
 #include "nsStreamCipher.h"
 #include "nsKeyModule.h"
 #include "nsDataSignatureVerifier.h"
 #include "nsCertOverrideService.h"
 #include "nsRandomGenerator.h"
 #include "nsRecentBadCerts.h"
 #include "nsSSLStatus.h"
 #include "nsNSSIOLayer.h"
+#include "NSSErrorsService.h"
 
 #ifdef MOZ_IPC
 #include "nsXULAppAPI.h"
 #define NS_IS_PROCESS_DEFAULT                                                 \
     (GeckoProcessType_Default == XRE_GetProcessType())
 #else
 #define NS_IS_PROCESS_DEFAULT                                                 \
     (true)
@@ -256,16 +257,19 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEn
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsKeyObjectFactory)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsDataSignatureVerifier)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsCertOverrideService, Init)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsRandomGenerator)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsRecentBadCertsService, Init)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsSSLStatus)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsNSSSocketInfo)
 
+typedef mozilla::psm::NSSErrorsService NSSErrorsService;
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NSSErrorsService, Init)
+
 NS_DEFINE_NAMED_CID(NS_NSSCOMPONENT_CID);
 NS_DEFINE_NAMED_CID(NS_SSLSOCKETPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_STARTTLSSOCKETPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_SDR_CID);
 NS_DEFINE_NAMED_CID(NS_PK11TOKENDB_CID);
 NS_DEFINE_NAMED_CID(NS_PKCS11MODULEDB_CID);
 NS_DEFINE_NAMED_CID(NS_PSMCONTENTLISTEN_CID);
 NS_DEFINE_NAMED_CID(NS_X509CERT_CID);
@@ -291,16 +295,17 @@ NS_DEFINE_NAMED_CID(NS_STREAMCIPHER_CID)
 NS_DEFINE_NAMED_CID(NS_KEYMODULEOBJECT_CID);
 NS_DEFINE_NAMED_CID(NS_KEYMODULEOBJECTFACTORY_CID);
 NS_DEFINE_NAMED_CID(NS_DATASIGNATUREVERIFIER_CID);
 NS_DEFINE_NAMED_CID(NS_CERTOVERRIDE_CID);
 NS_DEFINE_NAMED_CID(NS_RANDOMGENERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_RECENTBADCERTS_CID);
 NS_DEFINE_NAMED_CID(NS_SSLSTATUS_CID);
 NS_DEFINE_NAMED_CID(NS_NSSSOCKETINFO_CID);
+NS_DEFINE_NAMED_CID(NS_NSSERRORSSERVICE_CID);
 
 
 static const mozilla::Module::CIDEntry kNSSCIDs[] = {
   { &kNS_NSSCOMPONENT_CID, false, NULL, nsNSSComponentConstructor },
   { &kNS_SSLSOCKETPROVIDER_CID, false, NULL, nsSSLSocketProviderConstructor },
   { &kNS_STARTTLSSOCKETPROVIDER_CID, false, NULL, nsTLSSocketProviderConstructor },
   { &kNS_SDR_CID, false, NULL, nsSecretDecoderRingConstructor },
   { &kNS_PK11TOKENDB_CID, false, NULL, nsPK11TokenDBConstructor },
@@ -329,22 +334,23 @@ static const mozilla::Module::CIDEntry k
   { &kNS_KEYMODULEOBJECT_CID, false, NULL, nsKeyObjectConstructor },
   { &kNS_KEYMODULEOBJECTFACTORY_CID, false, NULL, nsKeyObjectFactoryConstructor },
   { &kNS_DATASIGNATUREVERIFIER_CID, false, NULL, nsDataSignatureVerifierConstructor },
   { &kNS_CERTOVERRIDE_CID, false, NULL, nsCertOverrideServiceConstructor },
   { &kNS_RANDOMGENERATOR_CID, false, NULL, nsRandomGeneratorConstructor },
   { &kNS_RECENTBADCERTS_CID, false, NULL, nsRecentBadCertsServiceConstructor },
   { &kNS_SSLSTATUS_CID, false, NULL, nsSSLStatusConstructor },
   { &kNS_NSSSOCKETINFO_CID, false, NULL, nsNSSSocketInfoConstructor },
+  { &kNS_NSSERRORSSERVICE_CID, false, NULL, NSSErrorsServiceConstructor },
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kNSSContracts[] = {
   { PSM_COMPONENT_CONTRACTID, &kNS_NSSCOMPONENT_CID },
-  { NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSCOMPONENT_CID },
+  { NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSERRORSSERVICE_CID },
   { NS_SSLSOCKETPROVIDER_CONTRACTID, &kNS_SSLSOCKETPROVIDER_CID },
   { NS_STARTTLSSOCKETPROVIDER_CONTRACTID, &kNS_STARTTLSSOCKETPROVIDER_CID },
   { NS_SDR_CONTRACTID, &kNS_SDR_CID },
   { NS_PK11TOKENDB_CONTRACTID, &kNS_PK11TOKENDB_CID },
   { NS_PKCS11MODULEDB_CONTRACTID, &kNS_PKCS11MODULEDB_CID },
   { NS_PSMCONTENTLISTEN_CONTRACTID, &kNS_PSMCONTENTLISTEN_CID },
   { NS_X509CERTDB_CONTRACTID, &kNS_X509CERTDB_CID },
   { NS_NSSCERTCACHE_CONTRACTID, &kNS_NSSCERTCACHE_CID },
--- a/services/crypto/modules/WeaveCrypto.js
+++ b/services/crypto/modules/WeaveCrypto.js
@@ -66,22 +66,16 @@ WeaveCrypto.prototype = {
             let self = this._self;
             self.log("Observed " + topic + " topic.");
             if (topic == "nsPref:changed") {
                 self.debug = self.prefBranch.getBoolPref("cryptoDebug");
             }
         }
     },
 
-    // This is its own method so that it can be overridden.
-    // (Components.Exception isn't thread-safe for instance)
-    makeException : function makeException(message, result) {
-        return Components.Exception(message, result);
-    },
-
     init : function() {
         try {
             // Preferences. Add observer so we get notified of changes.
             this.prefBranch = Services.prefs.getBranch("services.sync.log.");
             this.prefBranch.QueryInterface(Ci.nsIPrefBranch2);
             this.prefBranch.addObserver("cryptoDebug", this.observer, false);
             this.observer._self = this;
             this.debug = this.prefBranch.getBoolPref("cryptoDebug");
@@ -103,44 +97,31 @@ WeaveCrypto.prototype = {
     initNSS : function() {
         // We use NSS for the crypto ops, which needs to be initialized before
         // use. By convention, PSM is required to be the module that
         // initializes NSS. So, make sure PSM is initialized in order to
         // implicitly initialize NSS.
         Cc["@mozilla.org/psm;1"].getService(Ci.nsISupports);
 
         // Open the NSS library.
-        let nssfile = Services.dirsvc.get("GreD", Ci.nsILocalFile);
-        let os = Services.appinfo.OS;
-        switch (os) {
-          case "WINNT":
-          case "WINMO":
-          case "WINCE":
-            nssfile.append("nss3.dll");
-            break;
-          case "Darwin":
-            nssfile.append("libnss3.dylib");
-            break;
-          case "Linux":
-          case "SunOS":
-          case "WebOS": // Palm Pre
-            nssfile.append("libnss3.so");
-            break;
-          case "Android":
-            // Android uses a $GREDIR/lib/ subdir.
-            nssfile.append("lib");
-            nssfile.append("libnss3.so");
-            break;
-          default:
-            throw this.makeException("unsupported platform: " + os, Cr.NS_ERROR_UNEXPECTED);
-        }
-        this.log("Using NSS library " + nssfile.path);
+        let path = ctypes.libraryName("nss3");
 
         // XXX really want to be able to pass specific dlopen flags here.
-        let nsslib = ctypes.open(nssfile.path);
+        var nsslib;
+        try {
+            this.log("Trying NSS library without path");
+            nsslib = ctypes.open(path);
+        } catch(e) {
+            // In case opening the library without a full path fails,
+            // try again with a full path.
+            let file = Services.dirsvc.get("GreD", Ci.nsILocalFile);
+            file.append(path);
+            this.log("Trying again with path " + file.path);
+            nsslib = ctypes.open(file.path);
+        }
 
         this.log("Initializing NSS types and function declarations...");
 
         this.nss = {};
         this.nss_t = {};
 
         // nsprpub/pr/include/prtypes.h#435
         // typedef PRIntn PRBool; --> int
@@ -525,52 +506,52 @@ WeaveCrypto.prototype = {
         let keyItem = this.makeSECItem(symmetricKey, true);
         let ivItem  = this.makeSECItem(iv, true);
 
         // Determine which (padded) PKCS#11 mechanism to use.
         // EG: AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD
         let mechanism = this.nss.PK11_AlgtagToMechanism(this.algorithm);
         mechanism = this.nss.PK11_GetPadMechanism(mechanism);
         if (mechanism == this.nss.CKM_INVALID_MECHANISM)
-            throw this.makeException("invalid algorithm (can't pad)", Cr.NS_ERROR_FAILURE);
+            throw Components.Exception("invalid algorithm (can't pad)", Cr.NS_ERROR_FAILURE);
 
         let ctx, symKey, slot, ivParam;
         try {
             ivParam = this.nss.PK11_ParamFromIV(mechanism, ivItem.address());
             if (ivParam.isNull())
-                throw this.makeException("can't convert IV to param", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("can't convert IV to param", Cr.NS_ERROR_FAILURE);
 
             slot = this.nss.PK11_GetInternalKeySlot();
             if (slot.isNull())
-                throw this.makeException("can't get internal key slot", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("can't get internal key slot", Cr.NS_ERROR_FAILURE);
 
             symKey = this.nss.PK11_ImportSymKey(slot, mechanism, this.nss.PK11_OriginUnwrap, operation, keyItem.address(), null);
             if (symKey.isNull())
-                throw this.makeException("symkey import failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("symkey import failed", Cr.NS_ERROR_FAILURE);
 
             ctx = this.nss.PK11_CreateContextBySymKey(mechanism, operation, symKey, ivParam);
             if (ctx.isNull())
-                throw this.makeException("couldn't create context for symkey", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("couldn't create context for symkey", Cr.NS_ERROR_FAILURE);
 
             let maxOutputSize = output.length;
             let tmpOutputSize = new ctypes.int(); // Note 1: NSS uses a signed int here...
 
             if (this.nss.PK11_CipherOp(ctx, output, tmpOutputSize.address(), maxOutputSize, input, input.length))
-                throw this.makeException("cipher operation failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("cipher operation failed", Cr.NS_ERROR_FAILURE);
 
             let actualOutputSize = tmpOutputSize.value;
             let finalOutput = output.addressOfElement(actualOutputSize);
             maxOutputSize -= actualOutputSize;
 
             // PK11_DigestFinal sure sounds like the last step for *hashing*, but it
             // just seems to be an odd name -- NSS uses this to finish the current
             // cipher operation. You'd think it would be called PK11_CipherOpFinal...
             let tmpOutputSize2 = new ctypes.unsigned_int(); // Note 2: ...but an unsigned here!
             if (this.nss.PK11_DigestFinal(ctx, finalOutput, tmpOutputSize2.address(), maxOutputSize))
-                throw this.makeException("cipher finalize failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("cipher finalize failed", Cr.NS_ERROR_FAILURE);
 
             actualOutputSize += tmpOutputSize2.value;
             let newOutput = ctypes.cast(output, ctypes.unsigned_char.array(actualOutputSize));
             return newOutput;
         } catch (e) {
             this.log("_commonCrypt: failed: " + e);
             throw e;
         } finally {
@@ -599,37 +580,37 @@ WeaveCrypto.prototype = {
             pubKey  = new this.nss_t.SECKEYPublicKey.ptr();
 
             let rsaParams = new this.nss_t.PK11RSAGenParams();
             rsaParams.keySizeInBits = this.keypairBits; // 1024, 2048, etc.
             rsaParams.pe = 65537;                       // public exponent.
 
             slot = this.nss.PK11_GetInternalSlot();
             if (slot.isNull())
-                throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
 
             // Generate the keypair.
             privKey = this.nss.PK11_GenerateKeyPairWithFlags(slot,
                                                              this.nss.CKM_RSA_PKCS_KEY_PAIR_GEN,
                                                              rsaParams.address(),
                                                              pubKey.address(),
                                                              attrFlags, null);
             if (privKey.isNull())
-                throw this.makeException("keypair generation failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("keypair generation failed", Cr.NS_ERROR_FAILURE);
             
             let s = this.nss.PK11_SetPrivateKeyNickname(privKey, "Weave User PrivKey");
             if (s)
-                throw this.makeException("key nickname failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("key nickname failed", Cr.NS_ERROR_FAILURE);
 
             let wrappedPrivateKey = this._wrapPrivateKey(privKey, passphrase, salt, iv);
             out_wrappedPrivateKey.value = wrappedPrivateKey; // outparam
 
             let derKey = this.nss.SECKEY_EncodeDERSubjectPublicKeyInfo(pubKey);
             if (derKey.isNull())
-              throw this.makeException("SECKEY_EncodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
+              throw Components.Exception("SECKEY_EncodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
 
             let encodedPublicKey = this.encodeBase64(derKey.contents.data, derKey.contents.len);
             out_encodedPublicKey.value = encodedPublicKey; // outparam
         } catch (e) {
             this.log("generateKeypair: failed: " + e);
             throw e;
         } finally {
             if (pubKey && !pubKey.isNull())
@@ -659,37 +640,37 @@ WeaveCrypto.prototype = {
             break;
 
           case Ci.IWeaveCrypto.AES_256_CBC:
             keygenMech = this.nss.CKM_AES_KEY_GEN;
             keySize = 32;
             break;
 
           default:
-            throw this.makeException("unknown algorithm", Cr.NS_ERROR_FAILURE);
+            throw Components.Exception("unknown algorithm", Cr.NS_ERROR_FAILURE);
         }
 
         let slot, randKey, keydata;
         try {
             slot = this.nss.PK11_GetInternalSlot();
             if (slot.isNull())
-                throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
 
             randKey = this.nss.PK11_KeyGen(slot, keygenMech, null, keySize, null);
             if (randKey.isNull())
-                throw this.makeException("PK11_KeyGen failed.", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("PK11_KeyGen failed.", Cr.NS_ERROR_FAILURE);
 
             // Slightly odd API, this call just prepares the key value for
             // extraction, we get the actual bits from the call to PK11_GetKeyData().
             if (this.nss.PK11_ExtractKeyValue(randKey))
-                throw this.makeException("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
 
             keydata = this.nss.PK11_GetKeyData(randKey);
             if (keydata.isNull())
-                throw this.makeException("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
 
             return this.encodeBase64(keydata.contents.data, keydata.contents.len);
         } catch (e) {
             this.log("generateRandomKey: failed: " + e);
             throw e;
         } finally {
             if (randKey && !randKey.isNull())
                 this.nss.PK11_FreeSymKey(randKey);
@@ -710,17 +691,17 @@ WeaveCrypto.prototype = {
 
 
     generateRandomBytes : function(byteCount) {
         this.log("generateRandomBytes() called");
 
         // Temporary buffer to hold the generated data.
         let scratch = new ctypes.ArrayType(ctypes.unsigned_char, byteCount)();
         if (this.nss.PK11_GenerateRandom(scratch, byteCount))
-            throw this.makeException("PK11_GenrateRandom failed", Cr.NS_ERROR_FAILURE);
+            throw Components.Exception("PK11_GenrateRandom failed", Cr.NS_ERROR_FAILURE);
 
         return this.encodeBase64(scratch.address(), scratch.length);
     },
 
 
     wrapSymmetricKey : function(symmetricKey, encodedPublicKey) {
         this.log("wrapSymmetricKey() called");
 
@@ -733,46 +714,46 @@ WeaveCrypto.prototype = {
         let keyData = new ctypes.ArrayType(ctypes.unsigned_char, 4096)();
         let wrappedKey = new this.nss_t.SECItem(this.nss.SIBUFFER, keyData, keyData.length);
 
         // Step 2. Put the symmetric key bits into a P11 key object.
         let slot, symKey, pubKeyInfo, pubKey;
         try {
             slot = this.nss.PK11_GetInternalSlot();
             if (slot.isNull())
-                throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
 
             // ImportSymKey wants a mechanism, from which it derives the key type.
             let keyMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
 
             // This imports a key with the usage set for encryption, but that doesn't
             // really matter because we're just going to wrap it up and not use it.
             symKey = this.nss.PK11_ImportSymKey(slot, keyMech, this.nss.PK11_OriginUnwrap, this.nss.CKA_ENCRYPT, symKeyData.address(), null);
             if (symKey.isNull())
-                throw this.makeException("symkey import failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("symkey import failed", Cr.NS_ERROR_FAILURE);
 
             // Step 3. Put the public key bits into a P11 key object.
 
             // Can't just do this directly, it's expecting a minimal ASN1 blob
             // pubKey = SECKEY_ImportDERPublicKey(&pubKeyData, CKK_RSA);
             pubKeyInfo = this.nss.SECKEY_DecodeDERSubjectPublicKeyInfo(pubKeyData.address());
             if (pubKeyInfo.isNull())
-                throw this.makeException("SECKEY_DecodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("SECKEY_DecodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
 
             pubKey = this.nss.SECKEY_ExtractPublicKey(pubKeyInfo);
             if (pubKey.isNull())
-                throw this.makeException("SECKEY_ExtractPublicKey failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("SECKEY_ExtractPublicKey failed", Cr.NS_ERROR_FAILURE);
 
             // Step 4. Wrap the symmetric key with the public key.
 
             let wrapMech = this.nss.PK11_AlgtagToMechanism(this.nss.SEC_OID_PKCS1_RSA_ENCRYPTION);
 
             let s = this.nss.PK11_PubWrapSymKey(wrapMech, pubKey, symKey, wrappedKey.address());
             if (s)
-                throw this.makeException("PK11_PubWrapSymKey failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("PK11_PubWrapSymKey failed", Cr.NS_ERROR_FAILURE);
 
             // Step 5. Base64 encode the wrapped key, cleanup, and return to caller.
             return this.encodeBase64(wrappedKey.data, wrappedKey.len);
         } catch (e) {
             this.log("wrapSymmetricKey: failed: " + e);
             throw e;
         } finally {
             if (pubKey && !pubKey.isNull())
@@ -802,26 +783,26 @@ WeaveCrypto.prototype = {
             // Step 2. Convert the passphrase to a symmetric key and get the IV in the proper form.
             pbeKey = this._deriveKeyFromPassphrase(passphrase, salt);
             let ivItem = this.makeSECItem(iv, true);
 
             // AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD
             let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
             wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
             if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
-                throw this.makeException("unwrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("unwrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
 
             ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
             if (ivParam.isNull())
-                throw this.makeException("unwrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("unwrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
 
             // Step 3. Unwrap the private key with the key from the passphrase.
             slot = this.nss.PK11_GetInternalSlot();
             if (slot.isNull())
-                throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
 
             // Normally, one wants to associate a private key with a public key.
             // P11_UnwrapPrivKey() passes its keyID arg to PK11_MakeIDFromPubKey(),
             // which hashes the public key to create an ID (or, for small inputs,
             // assumes it's already hashed and does nothing).
             // We don't really care about this, because our unwrapped private key will
             // just live long enough to unwrap the bulk data key. So, we'll just jam in
             // a random value... We have an IV handy, so that will suffice.
@@ -832,34 +813,34 @@ WeaveCrypto.prototype = {
                                                   null,   // label
                                                   keyID,
                                                   false, // isPerm (token object)
                                                   true,  // isSensitive
                                                   this.nss.CKK_RSA,
                                                   privKeyUsage.addressOfElement(0), privKeyUsageLength,
                                                   null);  // wincx
             if (privKey.isNull())
-                throw this.makeException("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
 
             // Step 4. Unwrap the symmetric key with the user's private key.
 
             // XXX also have PK11_PubUnwrapSymKeyWithFlags() if more control is needed.
             // (last arg is keySize, 0 seems to work)
             symKey = this.nss.PK11_PubUnwrapSymKey(privKey, wrappedSymKey.address(), wrapMech,
                                                    this.nss.CKA_DECRYPT, 0);
             if (symKey.isNull())
-                throw this.makeException("PK11_PubUnwrapSymKey failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("PK11_PubUnwrapSymKey failed", Cr.NS_ERROR_FAILURE);
 
             // Step 5. Base64 encode the unwrapped key, cleanup, and return to caller.
             if (this.nss.PK11_ExtractKeyValue(symKey))
-                throw this.makeException("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
 
             symKeyData = this.nss.PK11_GetKeyData(symKey);
             if (symKeyData.isNull())
-                throw this.makeException("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
 
             return this.encodeBase64(symKeyData.contents.data, symKeyData.contents.len);
         } catch (e) {
             this.log("unwrapSymmetricKey: failed: " + e);
             throw e;
         } finally {
             if (privKey && !privKey.isNull())
                 this.nss.SECKEY_DestroyPrivateKey(privKey);
@@ -889,40 +870,40 @@ WeaveCrypto.prototype = {
             // Step 2. Convert the passphrase to a symmetric key and get the IV in the proper form.
             let pbeKey = this._deriveKeyFromPassphrase(oldPassphrase, salt);
             let ivItem = this.makeSECItem(iv, true);
 
             // AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD
             let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
             wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
             if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
-                throw this.makeException("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
 
             ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
             if (ivParam.isNull())
-                throw this.makeException("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
 
             // Step 3. Unwrap the private key with the key from the passphrase.
             slot = this.nss.PK11_GetInternalSlot();
             if (slot.isNull())
-                throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
 
             let keyID = ivItem.address();
 
             privKey = this.nss.PK11_UnwrapPrivKey(slot,
                                                   pbeKey, wrapMech, ivParam, wrappedPrivKey.address(),
                                                   null,   // label
                                                   keyID,
                                                   false, // isPerm (token object)
                                                   true,  // isSensitive
                                                   this.nss.CKK_RSA,
                                                   privKeyUsage.addressOfElement(0), privKeyUsageLength,
                                                   null);  // wincx
             if (privKey.isNull())
-                throw this.makeException("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
 
             // Step 4. Rewrap the private key with the new passphrase.
             return this._wrapPrivateKey(privKey, newPassphrase, salt, iv);
         } catch (e) {
             this.log("rewrapPrivateKey: failed: " + e);
             throw e;
         } finally {
             if (privKey && !privKey.isNull())
@@ -951,26 +932,26 @@ WeaveCrypto.prototype = {
             // Step 2. Convert the passphrase to a symmetric key and get the IV in the proper form.
             pbeKey = this._deriveKeyFromPassphrase(passphrase, salt);
             let ivItem = this.makeSECItem(iv, true);
 
             // AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD
             let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
             wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
             if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
-                throw this.makeException("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
 
             ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
             if (ivParam.isNull())
-                throw this.makeException("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
 
             // Step 3. Unwrap the private key with the key from the passphrase.
             slot = this.nss.PK11_GetInternalSlot();
             if (slot.isNull())
-                throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
 
             let keyID = ivItem.address();
 
             privKey = this.nss.PK11_UnwrapPrivKey(slot,
                                                   pbeKey, wrapMech, ivParam, wrappedPrivKey.address(),
                                                   null,   // label
                                                   keyID,
                                                   false, // isPerm (token object)
@@ -1054,25 +1035,25 @@ WeaveCrypto.prototype = {
         let keyLength  = 0;    // Callee will pick.
         let iterations = 4096; // PKCS#5 recommends at least 1000.
 
         let algid, slot, symKey;
         try {
             algid = this.nss.PK11_CreatePBEV2AlgorithmID(pbeAlg, cipherAlg, prfAlg,
                                                         keyLength, iterations, saltItem.address());
             if (algid.isNull())
-                throw this.makeException("PK11_CreatePBEV2AlgorithmID failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("PK11_CreatePBEV2AlgorithmID failed", Cr.NS_ERROR_FAILURE);
 
             slot = this.nss.PK11_GetInternalSlot();
             if (slot.isNull())
-                throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
 
             symKey = this.nss.PK11_PBEKeyGen(slot, algid, passItem.address(), false, null);
             if (symKey.isNull())
-                throw this.makeException("PK11_PBEKeyGen failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("PK11_PBEKeyGen failed", Cr.NS_ERROR_FAILURE);
         } catch (e) {
             this.log("_deriveKeyFromPassphrase: failed: " + e);
             throw e;
         } finally {
             if (algid && !algid.isNull())
                 this.nss.SECOID_DestroyAlgorithmID(algid, true);
             if (slot && !slot.isNull())
                 this.nss.PK11_FreeSlot(slot);
@@ -1090,33 +1071,33 @@ WeaveCrypto.prototype = {
             pbeKey = this._deriveKeyFromPassphrase(passphrase, salt);
 
             let ivItem = this.makeSECItem(iv, true);
 
             // AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD
             let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
             wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
             if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
-                throw this.makeException("wrapPrivKey: unknown key mech", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("wrapPrivKey: unknown key mech", Cr.NS_ERROR_FAILURE);
 
             let ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
             if (ivParam.isNull())
-                throw this.makeException("wrapPrivKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("wrapPrivKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
 
             // Use a buffer to hold the wrapped key. NSS says about 1200 bytes for
             // a 2048-bit RSA key, so a 4096 byte buffer should be plenty.
             let keyData = new ctypes.ArrayType(ctypes.unsigned_char, 4096)();
             wrappedKey = new this.nss_t.SECItem(this.nss.SIBUFFER, keyData, keyData.length);
 
             let s = this.nss.PK11_WrapPrivKey(privKey.contents.pkcs11Slot,
                                               pbeKey, privKey,
                                               wrapMech, ivParam,
                                               wrappedKey.address(), null);
             if (s)
-                throw this.makeException("wrapPrivKey: PK11_WrapPrivKey failed", Cr.NS_ERROR_FAILURE);
+                throw Components.Exception("wrapPrivKey: PK11_WrapPrivKey failed", Cr.NS_ERROR_FAILURE);
 
             return this.encodeBase64(wrappedKey.data, wrappedKey.len);
         } catch (e) {
             this.log("_wrapPrivateKey: failed: " + e);
             throw e;
         } finally {
             if (ivParam && !ivParam.isNull())
                 this.nss.SECITEM_FreeItem(ivParam, true);
deleted file mode 100644
--- a/services/crypto/modules/threaded.js
+++ /dev/null
@@ -1,150 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Firefox Sync.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Philipp von Weitershausen <philipp@weitershausen>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-const EXPORTED_SYMBOLS = ["ThreadedCrypto"];
-
-const Cu = Components.utils;
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://services-sync/ext/Sync.js");
-Cu.import("resource://services-crypto/WeaveCrypto.js");
-
-/*
- * Execute a function in a thread.
- */
-function Runner(func, thisObj, returnval, error) {
-  this.func = func;
-  this.thisObj = thisObj;
-  this.returnval = returnval;
-  this.error = error;
-}
-Runner.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIRunnable]),
-
-  run: function run() {
-    let ex = this.error;
-    if (ex) {
-      this.func.throw(ex);
-    } else {
-      this.func.call(this.thisObj, this.returnval);
-    }
-  }
-};
-
-/*
- * Execute a function in a thread and notify a callback on another thread
- * afterward.
- */
-function CallbackRunner(func, thisObj, args, callback, cbThread) {
-  this.func = func;
-  this.thisObj = thisObj;
-  this.args = args;
-  this.callback = callback;
-  this.cbThread = cbThread;
-}
-CallbackRunner.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIRunnable]),
-
-  run: function run() {
-    let returnval, error;
-    try {
-      returnval = this.func.apply(this.thisObj, this.args);
-    } catch(ex) {
-      error = ex;
-    }
-    this.cbThread.dispatch(new Runner(this.callback, this.thisObj,
-                                      returnval, error),
-                           Ci.nsIThread.DISPATCH_NORMAL);
-  }
-};
-
-/*
- * Implementation of IWeaveCrypto that defers method calls to another thread
- * but keeps the synchronous API. (Don't ask...)
- */
-function ThreadedCrypto() {
-  this.backgroundThread = Services.tm.newThread(0);
-  this.crypto = new WeaveCrypto();
-
-  // Components.Exception isn't thread-safe.
-  this.crypto.makeException = function makeException(message, result) {
-    return result;
-  };
-
-  // Make sure to kill the thread before XPCOM shuts down.
-  Services.obs.addObserver(this, "profile-before-change", true);
-}
-ThreadedCrypto.deferToThread = function deferToThread(methodname) {
-  return function threadMethod() {
-    // Dispatch method call to background thread.
-    let args = Array.slice(arguments);
-    return Sync(function(callback) {
-      let runner = new CallbackRunner(this.crypto[methodname], this.crypto,
-                                      args, callback, Services.tm.mainThread);
-      this.backgroundThread.dispatch(runner, Ci.nsIThread.DISPATCH_NORMAL);
-    }, this)();
-  };
-};
-ThreadedCrypto.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.IWeaveCrypto,
-                                         Ci.nsISupportsWeakReference]),
-
-  observe: function observe() {
-    this.backgroundThread.shutdown();
-  },
-
-  get algorithm() this.crypto.algorithm,
-  set algorithm(value) this.crypto.algorithm = value,
-
-  get keypairBits() this.crypto.keypairBits,
-  set keypairBits(value) this.crypto.keypairBits = value,
-
-  encrypt: ThreadedCrypto.deferToThread("encrypt"),
-  decrypt: ThreadedCrypto.deferToThread("decrypt"),
-  generateKeypair: ThreadedCrypto.deferToThread("generateKeypair"),
-  generateRandomKey: ThreadedCrypto.deferToThread("generateRandomKey"),
-  generateRandomIV: ThreadedCrypto.deferToThread("generateRandomIV"),
-  generateRandomBytes: ThreadedCrypto.deferToThread("generateRandomBytes"),
-  wrapSymmetricKey: ThreadedCrypto.deferToThread("wrapSymmetricKey"),
-  unwrapSymmetricKey: ThreadedCrypto.deferToThread("unwrapSymmetricKey"),
-  rewrapPrivateKey: ThreadedCrypto.deferToThread("rewrapPrivateKey"),
-  verifyPassphrase: ThreadedCrypto.deferToThread("verifyPassphrase")
-};
--- a/services/crypto/tests/unit/head_helpers.js
+++ b/services/crypto/tests/unit/head_helpers.js
@@ -6,18 +6,16 @@ const Cu = Components.utils;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 try {
   // In the context of xpcshell tests, there won't be a default AppInfo
   Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
 }
 catch(ex) {
 
-do_get_profile();
-
 // Make sure to provide the right OS so crypto loads the right binaries
 let OS = "XPCShell";
 if ("@mozilla.org/windows-registry-key;1" in Cc)
   OS = "WINNT";
 else if ("nsILocalFileMac" in Ci)
   OS = "Darwin";
 else
   OS = "Linux";
--- a/services/crypto/tests/unit/test_crypto_crypt.js
+++ b/services/crypto/tests/unit/test_crypto_crypt.js
@@ -1,12 +1,12 @@
 let cryptoSvc;
 try {
-  Components.utils.import("resource://services-crypto/threaded.js");
-  cryptoSvc = new ThreadedCrypto();
+  Components.utils.import("resource://services-crypto/WeaveCrypto.js");
+  cryptoSvc = new WeaveCrypto();
 } catch (ex) {
   // Fallback to binary WeaveCrypto
   cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]
                 .getService(Ci.IWeaveCrypto);
 }
 
 function run_test() {
   // First, do a normal run with expected usage... Generate a random key and
--- a/services/crypto/tests/unit/test_crypto_keypair.js
+++ b/services/crypto/tests/unit/test_crypto_keypair.js
@@ -1,12 +1,12 @@
 let cryptoSvc;
 try {
-  Components.utils.import("resource://services-crypto/threaded.js");
-  cryptoSvc = new ThreadedCrypto();
+  Components.utils.import("resource://services-crypto/WeaveCrypto.js");
+  cryptoSvc = new WeaveCrypto();
 } catch (ex) {
   // Fallback to binary WeaveCrypto
   cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]
                 .getService(Ci.IWeaveCrypto);
 }
 
 function run_test() {
   var salt = cryptoSvc.generateRandomBytes(16);
--- a/services/crypto/tests/unit/test_crypto_random.js
+++ b/services/crypto/tests/unit/test_crypto_random.js
@@ -1,12 +1,12 @@
 let cryptoSvc;
 try {
-  Components.utils.import("resource://services-crypto/threaded.js");
-  cryptoSvc = new ThreadedCrypto();
+  Components.utils.import("resource://services-crypto/WeaveCrypto.js");
+  cryptoSvc = new WeaveCrypto();
 } catch (ex) {
   // Fallback to binary WeaveCrypto
   cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]
                 .getService(Ci.IWeaveCrypto);
 }
 
 function run_test() {
   // Test salt generation.
--- a/services/crypto/tests/unit/test_crypto_rewrap.js
+++ b/services/crypto/tests/unit/test_crypto_rewrap.js
@@ -1,12 +1,12 @@
 let cryptoSvc;
 try {
-  Components.utils.import("resource://services-crypto/threaded.js");
-  cryptoSvc = new ThreadedCrypto();
+  Components.utils.import("resource://services-crypto/WeaveCrypto.js");
+  cryptoSvc = new WeaveCrypto();
 } catch (ex) {
   // Fallback to binary WeaveCrypto
   cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]
                 .getService(Ci.IWeaveCrypto);
 }
 
 function run_test() {
   var salt = cryptoSvc.generateRandomBytes(16);
--- a/services/crypto/tests/unit/test_crypto_verify.js
+++ b/services/crypto/tests/unit/test_crypto_verify.js
@@ -1,12 +1,12 @@
 let cryptoSvc;
 try {
-  Components.utils.import("resource://services-crypto/threaded.js");
-  cryptoSvc = new ThreadedCrypto();
+  Components.utils.import("resource://services-crypto/WeaveCrypto.js");
+  cryptoSvc = new WeaveCrypto();
 } catch (ex) {
   // Fallback to binary WeaveCrypto
   cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]
                 .getService(Ci.IWeaveCrypto);
 }
 
 function run_test() {
   var salt = cryptoSvc.generateRandomBytes(16);
--- a/services/sync/modules/util.js
+++ b/services/sync/modules/util.js
@@ -1034,18 +1034,18 @@ this.__defineGetter__("_sessionCID", fun
  ["WinWatcher", "@mozilla.org/embedcomp/window-watcher;1", "nsIWindowWatcher"],
  ["Session", this._sessionCID, "nsISessionStore"],
 ].forEach(function(lazy) Utils.lazySvc(Svc, lazy[0], lazy[1], lazy[2]));
 
 Svc.__defineGetter__("Crypto", function() {
   let cryptoSvc;
   try {
     let ns = {};
-    Cu.import("resource://services-crypto/threaded.js", ns);
-    cryptoSvc = new ns.ThreadedCrypto();
+    Cu.import("resource://services-crypto/WeaveCrypto.js", ns);
+    cryptoSvc = new ns.WeaveCrypto();
   } catch (ex) {
     // Fallback to binary WeaveCrypto
     cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"].
                 getService(Ci.IWeaveCrypto);
   }
   delete Svc.Crypto;
   return Svc.Crypto = cryptoSvc;
 });
--- a/services/sync/tests/unit/test_service_sync_remoteSetup.js
+++ b/services/sync/tests/unit/test_service_sync_remoteSetup.js
@@ -1,13 +1,16 @@
 Cu.import("resource://services-sync/main.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://services-sync/log4moz.js");
 
 function run_test() {
+  if (DISABLE_TESTS_BUG_604565)
+    return;
+
   let logger = Log4Moz.repository.rootLogger;
   Log4Moz.repository.rootLogger.addAppender(new Log4Moz.DumpAppender());
 
   let guidSvc = new FakeGUIDService();
   let cryptoSvc = new FakeCryptoService();
 
   let keys = new ServerCollection({privkey: new ServerWBO('privkey'),
                                    pubkey: new ServerWBO('pubkey')});
--- a/toolkit/components/console/hudservice/HUDService.jsm
+++ b/toolkit/components/console/hudservice/HUDService.jsm
@@ -3902,169 +3902,162 @@ function JSPropertyProvider(aScope, aInp
  *
  * Defines a set of functions ("helper functions") that are available from the
  * WebConsole but not from the webpage.
  * A list of helper functions used by Firebug can be found here:
  *   http://getfirebug.com/wiki/index.php/Command_Line_API
  */
 function JSTermHelper(aJSTerm)
 {
-  return {
-    /**
-     * Returns the result of document.getElementById(aId).
-     *
-     * @param string aId
-     *        A string that is passed to window.document.getElementById.
-     * @returns nsIDOMNode or null
-     */
-    $: function JSTH_$(aId)
-    {
-      try {
-        return aJSTerm._window.document.getElementById(aId);
-      }
-      catch (ex) {
-        aJSTerm.console.error(ex.message);
-      }
-    },
-
-    /**
-     * Returns the result of document.querySelectorAll(aSelector).
-     *
-     * @param string aSelector
-     *        A string that is passed to window.document.querySelectorAll.
-     * @returns array of nsIDOMNode
-     */
-    $$: function JSTH_$$(aSelector)
-    {
-      try {
-        return aJSTerm._window.document.querySelectorAll(aSelector);
-      }
-      catch (ex) {
-        aJSTerm.console.error(ex.message);
-      }
-    },
-
-    /**
-     * Runs a xPath query and returns all matched nodes.
-     *
-     * @param string aXPath
-     *        xPath search query to execute.
-     * @param [optional] nsIDOMNode aContext
-     *        Context to run the xPath query on. Uses window.document if not set.
-     * @returns array of nsIDOMNode
-     */
-    $x: function JSTH_$x(aXPath, aContext)
-    {
-      let nodes = [];
-      let doc = aJSTerm._window.wrappedJSObject.document;
-      let aContext = aContext || doc;
-
-      try {
-        let results = doc.evaluate(aXPath, aContext, null,
-                                    Ci.nsIDOMXPathResult.ANY_TYPE, null);
-
-        let node;
-        while (node = results.iterateNext()) {
-          nodes.push(node);
-        }
-      }
-      catch (ex) {
-        aJSTerm.console.error(ex.message);
+  /**
+   * Returns the result of document.getElementById(aId).
+   *
+   * @param string aId
+   *        A string that is passed to window.document.getElementById.
+   * @returns nsIDOMNode or null
+   */
+  aJSTerm.sandbox.$ = function JSTH_$(aId)
+  {
+    try {
+      return aJSTerm._window.document.getElementById(aId);
+    }
+    catch (ex) {
+      aJSTerm.console.error(ex.message);
+    }
+  };
+
+  /**
+   * Returns the result of document.querySelectorAll(aSelector).
+   *
+   * @param string aSelector
+   *        A string that is passed to window.document.querySelectorAll.
+   * @returns array of nsIDOMNode
+   */
+  aJSTerm.sandbox.$$ = function JSTH_$$(aSelector)
+  {
+    try {
+      return aJSTerm._window.document.querySelectorAll(aSelector);
+    }
+    catch (ex) {
+      aJSTerm.console.error(ex.message);
+    }
+  };
+
+  /**
+   * Runs a xPath query and returns all matched nodes.
+   *
+   * @param string aXPath
+   *        xPath search query to execute.
+   * @param [optional] nsIDOMNode aContext
+   *        Context to run the xPath query on. Uses window.document if not set.
+   * @returns array of nsIDOMNode
+   */
+  aJSTerm.sandbox.$x = function JSTH_$x(aXPath, aContext)
+  {
+    let nodes = [];
+    let doc = aJSTerm._window.document;
+    let aContext = aContext || doc;
+
+    try {
+      let results = doc.evaluate(aXPath, aContext, null,
+                                  Ci.nsIDOMXPathResult.ANY_TYPE, null);
+
+      let node;
+      while (node = results.iterateNext()) {
+        nodes.push(node);
       }
-
-      return nodes;
-    },
-
-    /**
-     * Clears the output of the JSTerm.
-     */
-    clear: function JSTH_clear()
-    {
-      aJSTerm.clearOutput();
-    },
-
-    /**
-     * Returns the result of Object.keys(aObject).
-     *
-     * @param object aObject
-     *        Object to return the property names from.
-     * @returns array of string
-     */
-    keys: function JSTH_keys(aObject)
-    {
-      try {
-        return Object.keys(XPCNativeWrapper.unwrap(aObject));
-      }
-      catch (ex) {
-        aJSTerm.console.error(ex.message);
-      }
-    },
-
-    /**
-     * Returns the values of all properties on aObject.
-     *
-     * @param object aObject
-     *        Object to display the values from.
-     * @returns array of string
-     */
-    values: function JSTH_values(aObject)
-    {
-      let arrValues = [];
-      let obj = XPCNativeWrapper.unwrap(aObject);
-
-      try {
-        for (let prop in obj) {
-          arrValues.push(obj[prop]);
-        }
+    }
+    catch (ex) {
+      aJSTerm.console.error(ex.message);
+    }
+
+    return nodes;
+  };
+
+  /**
+   * Clears the output of the JSTerm.
+   */
+  aJSTerm.sandbox.clear = function JSTH_clear()
+  {
+    aJSTerm.clearOutput();
+  };
+
+  /**
+   * Returns the result of Object.keys(aObject).
+   *
+   * @param object aObject
+   *        Object to return the property names from.
+   * @returns array of string
+   */
+  aJSTerm.sandbox.keys = function JSTH_keys(aObject)
+  {
+    try {
+      return Object.keys(aObject);
+    }
+    catch (ex) {
+      aJSTerm.console.error(ex.message);
+    }
+  };
+
+  /**
+   * Returns the values of all properties on aObject.
+   *
+   * @param object aObject
+   *        Object to display the values from.
+   * @returns array of string
+   */
+  aJSTerm.sandbox.values = function JSTH_values(aObject)
+  {
+    let arrValues = [];
+
+    try {
+      for (let prop in aObject) {
+        arrValues.push(aObject[prop]);
       }
-      catch (ex) {
-        aJSTerm.console.error(ex.message);
-      }
-      return arrValues;
-    },
-
-    /**
-     * Inspects the passed aObject. This is done by opening the PropertyPanel.
-     *
-     * @param object aObject
-     *        Object to inspect.
-     * @returns void
-     */
-    inspect: function JSTH_inspect(aObject)
-    {
-      let obj = XPCNativeWrapper.unwrap(aObject);
-      aJSTerm.openPropertyPanel(null, obj);
-    },
-
-    /**
-     * Prints aObject to the output.
-     *
-     * @param object aObject
-     *        Object to print to the output.
-     * @returns void
-     */
-    pprint: function JSTH_pprint(aObject)
-    {
-      if (aObject === null || aObject === undefined || aObject === true || aObject === false) {
-        aJSTerm.console.error(HUDService.getStr("helperFuncUnsupportedTypeError"));
-        return;
-      }
-      let output = [];
-      if (typeof aObject != "string") {
-        aObject = XPCNativeWrapper.unwrap(aObject);
-      }
-      let pairs = namesAndValuesOf(aObject);
-
-      pairs.forEach(function(pair) {
-        output.push("  " + pair.display);
-      });
-
-      aJSTerm.writeOutput(output.join("\n"));
+    }
+    catch (ex) {
+      aJSTerm.console.error(ex.message);
     }
-  }
+    return arrValues;
+  };
+
+  /**
+   * Inspects the passed aObject. This is done by opening the PropertyPanel.
+   *
+   * @param object aObject
+   *        Object to inspect.
+   * @returns void
+   */
+  aJSTerm.sandbox.inspect = function JSTH_inspect(aObject)
+  {
+    aJSTerm.openPropertyPanel(null, aObject);
+  };
+
+  /**
+   * Prints aObject to the output.
+   *
+   * @param object aObject
+   *        Object to print to the output.
+   * @returns void
+   */
+  aJSTerm.sandbox.pprint = function JSTH_pprint(aObject)
+  {
+    if (aObject === null || aObject === undefined || aObject === true || aObject === false) {
+      aJSTerm.console.error(HUDService.getStr("helperFuncUnsupportedTypeError"));
+      return;
+    }
+    let output = [];
+    let pairs = namesAndValuesOf(aObject);
+
+    pairs.forEach(function(pair) {
+      output.push("  " + pair.display);
+    });
+
+    aJSTerm.writeOutput(output.join("\n"));
+  };
 }
 
 /**
  * JSTerm
  *
  * JavaScript Terminal: creates input nodes for console code interpretation
  * and 'JS Workspaces'
  */
@@ -4141,21 +4134,20 @@ JSTerm.prototype = {
   attachUI: function JST_attachUI()
   {
     this.mixins.attachUI();
   },
 
   createSandbox: function JST_setupSandbox()
   {
     // create a JS Sandbox out of this.context
-    this.sandbox = new Cu.Sandbox(this._window);
-    this.sandbox.window = this._window;
+    this.sandbox = new Cu.Sandbox(this._window,
+      { sandboxPrototype: this._window, wantXrays: false });
     this.sandbox.console = this.console;
-    this.sandbox.__helperFunctions__ = JSTermHelper(this);
-    this.sandbox.__proto__ = this._window.wrappedJSObject;
+    JSTermHelper(this);
   },
 
   get _window()
   {
     return this.context.get().QueryInterface(Ci.nsIDOMWindowInternal);
   },
   /**
    * Evaluates a string in the sandbox. The string is currently wrapped by a
@@ -4163,18 +4155,17 @@ JSTerm.prototype = {
    *
    * @param string aString
    *        String to evaluate in the sandbox.
    * @returns something
    *          The result of the evaluation.
    */
   evalInSandbox: function JST_evalInSandbox(aString)
   {
-    let execStr = "with(__helperFunctions__) { with(window) {" + aString + "} }";
-    return Cu.evalInSandbox(execStr,  this.sandbox, "default", "HUD Console", 1);
+    return Cu.evalInSandbox(aString, this.sandbox, "1.8", "HUD Console", 1);
   },
 
 
   execute: function JST_execute(aExecuteString)
   {
     // attempt to execute the content of the inputNode
     aExecuteString = aExecuteString || this.inputNode.value;
     if (!aExecuteString) {
--- a/toolkit/components/console/hudservice/tests/browser/Makefile.in
+++ b/toolkit/components/console/hudservice/tests/browser/Makefile.in
@@ -93,16 +93,17 @@ include $(topsrcdir)/config/rules.mk
 	browser_webconsole_bug_583816_tab_focus.js \
 	browser_webconsole_bug_594477_clickable_output.js \
 	browser_webconsole_bug_589162_css_filter.js \
 	browser_webconsole_bug_597103_deactivateHUDForContext_unfocused_window.js \
 	browser_webconsole_bug_595350_multiple_windows_and_tabs.js \
 	browser_webconsole_bug_594497_history_arrow_keys.js \
 	browser_webconsole_bug_588342_document_focus.js \
 	browser_webconsole_bug_595934_message_categories.js \
+	browser_webconsole_bug_601352_scroll.js \
 	head.js \
 	$(NULL)
 
 # compartment-disabled
 #	browser_webconsole_bug_593003_iframe_wrong_hud.js \
 
 _BROWSER_TEST_PAGES = \
 	test-console.html \
new file mode 100644
--- /dev/null
+++ b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_601352_scroll.js
@@ -0,0 +1,62 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Contributor(s):
+ *  Mihai Șucan <mihai.sucan@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function tabLoad(aEvent) {
+  browser.removeEventListener(aEvent.type, arguments.callee, true);
+
+  openConsole();
+
+  let hudId = HUDService.getHudIdByWindow(content);
+  let HUD = HUDService.hudWeakReferences[hudId].get();
+
+  let longMessage = "";
+  for (let i = 0; i < 20; i++) {
+    longMessage += "LongNonwrappingMessage";
+  }
+
+  for (let i = 0; i < 100; i++) {
+    HUD.console.log("test message " + i);
+  }
+
+  HUD.console.log(longMessage);
+
+  for (let i = 0; i < 100; i++) {
+    HUD.console.log("test message " + i);
+  }
+
+  HUD.jsterm.execute("1+1");
+
+  executeSoon(function() {
+    isnot(HUD.outputNode.scrollTop, 0, "scroll location is not at the top");
+
+    let node = HUD.outputNode.querySelector(".hud-group > *:last-child");
+    let rectNode = node.getBoundingClientRect();
+    let rectOutput = HUD.outputNode.getBoundingClientRect();
+
+    // Visible scroll viewport.
+    let height = HUD.outputNode.scrollHeight - HUD.outputNode.scrollTop;
+
+    // Top position of the last message node, relative to the outputNode.
+    let top = rectNode.top - rectOutput.top;
+
+    // Bottom position of the last message node, relative to the outputNode.
+    let bottom = rectNode.bottom - rectOutput.top;
+
+    ok(top >= 0 && bottom <= height, "last message is visible");
+
+    finishTest();
+  });
+}
+
+function test() {
+  addTab("data:text/html,Web Console test for bug 601352");
+  browser.addEventListener("load", tabLoad, true);
+}
+
--- a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_jsterm.js
+++ b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_jsterm.js
@@ -93,10 +93,26 @@ function testJSTerm()
   checkResult("valuesResult=true", "values() worked", 1);
 
   jsterm.clearOutput();
   jsterm.execute("pprint({b:2, a:1})");
   // Doesn't conform to checkResult format
   let label = jsterm.outputNode.querySelector(".jsterm-output-line");
   is(label.textContent.trim(), "a: 1\n  b: 2", "pprint() worked");
 
+  // check instanceof correctness, bug 599940
+  jsterm.clearOutput();
+  jsterm.execute("[] instanceof Array");
+  checkResult("true", "[] instanceof Array == true", 1);
+
+  jsterm.clearOutput();
+  jsterm.execute("({}) instanceof Object");
+  checkResult("true", "({}) instanceof Object == true", 1);
+
+  // check for occurrences of Object XRayWrapper, bug 604430
+  jsterm.clearOutput();
+  jsterm.execute("document");
+  let label = jsterm.outputNode.querySelector(".jsterm-output-line");
+  is(label.textContent.trim().search(/\[object XrayWrapper/), -1,
+    "check for non-existence of [object XrayWrapper ");
+
   finishTest();
 }
--- a/toolkit/components/passwordmgr/test/test_prompt.html
+++ b/toolkit/components/passwordmgr/test/test_prompt.html
@@ -119,16 +119,43 @@ ok(true, "removing login 4...");
   pwmgr.removeLogin(login4);
 ok(true, "removing proxyLogin...");
   pwmgr.removeLogin(proxyLogin);
 ok(true, "whee, done!");
 
   SimpleTest.finish();
 }
 
+function addNotificationCallback(cb)
+{
+  storageObserver.notificationCallbacks.push(cb);
+}
+
+var storageObserver = {
+  notificationCallbacks: [],
+
+  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) {
+   if (this.notificationCallbacks.length)
+      this.notificationCallbacks.splice(0, 1)[0]();
+  }
+};
+
+var observerService = Cc["@mozilla.org/observer-service;1"]
+                      .getService(Ci.nsIObserverService);
+observerService.addObserver(storageObserver, "passwordmgr-storage-changed", false);
+
 /*
  * handleDialog
  *
  * Invoked a short period of time after calling startCallbackTimer(), and
  * allows testing the actual auth dialog while it's being displayed. Tests
  * should call startCallbackTimer() each time the auth dialog is expected (the
  * timer is a one-shot).
  */
@@ -412,87 +439,87 @@ function handleLoad() {
         break;
 
     case 1003:
         testNum++;
         is(authok, "PASS", "Checking for successful authentication");
         is(username, "mochiuser1", "Checking for echoed username");
         is(password, "mochipass1-new", "Checking for echoed password");
 
-        // Check for the popup notification, and change the password.
-        popup = getPopup(popupNotifications, "password-change");
-        ok(popup, "got popup notification");
-        clickPopupButton(popup, kChangeButton);
-        popup.remove();
-
         // Housekeeping: change it back
         function resetIt() {
           netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
           tmpLogin.init("http://mochi.test:8888", null, "mochitest",
                         "mochiuser1", "mochipass1-new", "", "");
           pwmgr.modifyLogin(tmpLogin, login3A);
         }
-        setTimeout(resetIt, 0);
+        addNotificationCallback(resetIt);
+
+        // Check for the popup notification, and change the password.
+        popup = getPopup(popupNotifications, "password-change");
+        ok(popup, "got popup notification");
+        clickPopupButton(popup, kChangeButton);
+        popup.remove();
 
         // Same as last test, but for a realm we haven't already authenticated
         // to (but have an existing saved login for, so that we'll trigger
         // a change-password popup notification.
         startCallbackTimer();
         iframe.src = "authenticate.sjs?user=mochiuser3&pass=mochipass3-new&realm=mochitest3";
         break;
 
     case 1004:
         testNum++;
         is(authok, "PASS", "Checking for successful authentication");
         is(username, "mochiuser3", "Checking for echoed username");
         is(password, "mochipass3-new", "Checking for echoed password");
 
+        // Housekeeping: change it back to the original login4. Actually,
+        // just delete it and we'll re-add it as the next test.
+        function clearIt() {
+          netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+          tmpLogin.init("http://mochi.test:8888", null, "mochitest3",
+                        "mochiuser3", "mochipass3-new", "", "");
+          pwmgr.removeLogin(tmpLogin);
+
+          // Trigger a new prompt, so we can test adding a new login.
+          startCallbackTimer();
+          iframe.src = "authenticate.sjs?user=mochiuser3&pass=mochipass3-old&realm=mochitest3";
+        }
+        addNotificationCallback(clearIt);
+
         // Check for the popup notification, and change the password.
         popup = getPopup(popupNotifications, "password-change");
         ok(popup, "got popup notification");
         clickPopupButton(popup, kChangeButton);
         popup.remove();
 
-        // Housekeeping: change it back to the original login4. Actually,
-        // just delete it and we'll re-add it as the next test.
-        function clearIt() {
-            netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-            tmpLogin.init("http://mochi.test:8888", null, "mochitest3",
-                          "mochiuser3", "mochipass3-new", "", "");
-            pwmgr.removeLogin(tmpLogin);
-        }
-        setTimeout(clearIt, 0);
-
         // Clear cached auth from this subtest, and avoid leaking due to bug 459620.
         var authMgr = Cc['@mozilla.org/network/http-auth-manager;1'].
                       getService(Ci.nsIHttpAuthManager);
         authMgr.clearAll();
-
-        // Trigger a new prompt, so we can test adding a new login.
-        startCallbackTimer();
-        iframe.src = "authenticate.sjs?user=mochiuser3&pass=mochipass3-old&realm=mochitest3";
         break;
 
     case 1005:
         testNum++;
         is(authok, "PASS", "Checking for successful authentication");
         is(username, "mochiuser3", "Checking for echoed username");
         is(password, "mochipass3-old", "Checking for echoed password");
 
+        function finishIt() {
+          netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+          finishTest();
+        }
+        addNotificationCallback(finishIt);
+
         // Check for the popup notification, and change the password.
         popup = getPopup(popupNotifications, "password-save");
         ok(popup, "got popup notification");
         clickPopupButton(popup, kRememberButton);
         popup.remove();
-        
-        function finishIt() {
-            netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-            finishTest();
-        }
-        setTimeout(finishIt, 0);
         break;
 
     default:
         ok(false, "Uhh, unhandled switch for testNum #" + testNum);
         break;
   }
 
 }
--- a/toolkit/components/places/src/History.cpp
+++ b/toolkit/components/places/src/History.cpp
@@ -1176,22 +1176,37 @@ History::RegisterVisitedCallback(nsIURI*
   if (observers.IsEmpty()) {
     NS_ASSERTION(!keyAlreadyExists,
                  "An empty key was kept around in our hashtable!");
 
     // We are the first Link node to ask about this URI, or there are no pending
     // Links wanting to know about this URI.  Therefore, we should query the
     // database now.
     nsresult rv = VisitedQuery::Start(aURI);
+
+    // In IPC builds, we are passed a NULL Link from
+    // ContentParent::RecvStartVisitedQuery.  Since we won't be adding a NULL
+    // entry to our list of observers, and the code after this point assumes
+    // that aLink is non-NULL, we will need to return now.
     if (NS_FAILED(rv) || !aLink) {
       // Remove our array from the hashtable so we don't keep it around.
       mObservers.RemoveEntry(aURI);
       return rv;
     }
   }
+#ifdef MOZ_IPC
+  // In IPC builds, we are passed a NULL Link from
+  // ContentParent::RecvStartVisitedQuery.  All of our code after this point
+  // assumes aLink is non-NULL, so we have to return now.
+  else if (!aLink) {
+    NS_ASSERTION(XRE_GetProcessType() == GeckoProcessType_Default,
+                 "We should only ever get a null Link in the default process!");
+    return NS_OK;
+  }
+#endif
 
   // Sanity check that Links are not registered more than once for a given URI.
   // This will not catch a case where it is registered for two different URIs.
   NS_ASSERTION(!observers.Contains(aLink),
                "Already tracking this Link object!");
 
   // Start tracking our Link.
   if (!observers.AppendElement(aLink)) {
--- a/toolkit/components/places/tests/cpp/test_IHistory.cpp
+++ b/toolkit/components/places/tests/cpp/test_IHistory.cpp
@@ -546,16 +546,44 @@ test_visituri_transition_embed()
   do_get_lastVisit(place.id, visit);
 
   do_check_true(visit.transitionType == nsINavHistoryService::TRANSITION_EMBED);
 
   run_next_test();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+//// IPC-only Tests
+
+#ifdef MOZ_IPC
+void
+test_two_null_links_same_uri()
+{
+  // Tests that we do not crash when we have had two NULL Links passed to
+  // RegisterVisitedCallback and then the visit occurs (bug 607469).  This only
+  // happens in IPC builds.
+  nsCOMPtr<nsIURI> testURI(new_test_uri());
+
+  nsCOMPtr<IHistory> history(do_get_IHistory());
+  nsresult rv = history->RegisterVisitedCallback(testURI, NULL);
+  do_check_success(rv);
+  rv = history->RegisterVisitedCallback(testURI, NULL);
+  do_check_success(rv);
+
+  rv = history->VisitURI(testURI, NULL, mozilla::IHistory::TOP_LEVEL);
+  do_check_success(rv);
+
+  nsCOMPtr<VisitURIObserver> finisher = new VisitURIObserver();
+  finisher->WaitForNotification();
+
+  run_next_test();
+}
+#endif // MOZ_IPC
+
+////////////////////////////////////////////////////////////////////////////////
 //// Test Harness
 
 /**
  * Note: for tests marked "Order Important!", please see the test for details.
  */
 Test gTests[] = {
   TEST(test_unvisted_does_not_notify_part1), // Order Important!
   TEST(test_visited_notifies),
@@ -566,14 +594,19 @@ Test gTests[] = {
   TEST(test_RegisterVisitedCallback_returns_before_notifying),
   TEST(test_observer_topic_dispatched),
   TEST(test_visituri_inserts),
   TEST(test_visituri_updates),
   TEST(test_visituri_preserves_shown_and_typed),
   TEST(test_visituri_creates_visit),
   TEST(test_visituri_transition_typed),
   TEST(test_visituri_transition_embed),
+
+  // The rest of these tests are tests that are only run in IPC builds.
+#ifdef MOZ_IPC
+  TEST(test_two_null_links_same_uri),
+#endif // MOZ_IPC
 };
 
 const char* file = __FILE__;
 #define TEST_NAME "IHistory"
 #define TEST_FILE file
 #include "places_test_harness_tail.h"
--- a/toolkit/components/prompts/content/commonDialog.js
+++ b/toolkit/components/prompts/content/commonDialog.js
@@ -40,328 +40,70 @@
  * ***** END LICENSE BLOCK ***** */
 
 const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cc = Components.classes;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/CommonDialog.jsm");
 
-let gArgs = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
-                               .QueryInterface(Ci.nsIWritablePropertyBag);
-
-let promptType, numButtons, iconClass, soundID, hasInputField = true;
-
+let propBag, args, Dialog;
 
-function earlyInit() {
-    // This is called before onload fires, so we can't be certain that any elements
-    // in the document have their bindings ready, so don't call any methods/properties
-    // here on xul elements that come from xbl bindings.
+function commonDialogOnLoad() {
+    propBag = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
+                                 .QueryInterface(Ci.nsIWritablePropertyBag);
+    // Convert to a JS object
+    args = {};
+    let propEnum = propBag.enumerator;
+    while (propEnum.hasMoreElements()) {
+        let prop = propEnum.getNext().QueryInterface(Ci.nsIProperty);
+        args[prop.name] = prop.value;
+    }
 
-    promptType = gArgs.getProperty("promptType");
+    let dialog = document.documentElement;
 
-    switch (promptType) {
-      case "alert":
-      case "alertCheck":
-        hasInputField = false;
-        numButtons    = 1;
-        iconClass     = "alert-icon";
-        soundID       = Ci.nsISound.EVENT_ALERT_DIALOG_OPEN;
-        break;
-      case "confirmCheck":
-      case "confirm":
-        hasInputField = false;
-        numButtons    = 2;
-        iconClass     = "question-icon";
-        soundID       = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
-        break;
-      case "confirmEx":
-        numButtons = 0;
-        if (gArgs.hasKey("button0Label"))
-            numButtons++;
-        if (gArgs.hasKey("button1Label"))
-            numButtons++;
-        if (gArgs.hasKey("button2Label"))
-            numButtons++;
-        if (gArgs.hasKey("button3Label"))
-            numButtons++;
-        if (numButtons == 0)
-            throw "A dialog with no buttons? Can not haz.";
-        hasInputField = false;
-        iconClass     = "question-icon";
-        soundID       = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
-        break;
-      case "prompt":
-        numButtons = 2;
-        iconClass  = "question-icon";
-        soundID    = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
-        initTextbox("login", gArgs.getProperty("value"));
-        // Clear the label, since this isn't really a username prompt.
-        document.getElementById("loginLabel").setAttribute("value", "");
-        break;
-      case "promptUserAndPass":
-        numButtons = 2;
-        iconClass  = "authentication-icon question-icon";
-        soundID    = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
-        initTextbox("login",     gArgs.getProperty("user"));
-        initTextbox("password1", gArgs.getProperty("pass"));
-        break;
-      case "promptPassword":
-        numButtons = 2;
-        iconClass  = "authentication-icon question-icon";
-        soundID    = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
-        initTextbox("password1", gArgs.getProperty("pass"));
-        // Clear the label, since the message presumably indicates its purpose.
-        document.getElementById("password1Label").setAttribute("value", "");
-        break;
-      default:
-        Cu.reportError("commonDialog opened for unknown type: " + promptType);
-        window.close();
-    }
+    let ui = {
+        loginContainer     : document.getElementById("loginContainer"),
+        loginTextbox       : document.getElementById("loginTextbox"),
+        loginLabel         : document.getElementById("loginLabel"),
+        password1Container : document.getElementById("password1Container"),
+        password1Textbox   : document.getElementById("password1Textbox"),
+        password1Label     : document.getElementById("password1Label"),
+        infoBody           : document.getElementById("info.body"),
+        infoTitle          : document.getElementById("info.title"),
+        infoIcon           : document.getElementById("info.icon"),
+        checkbox           : document.getElementById("checkbox"),
+        checkboxContainer  : document.getElementById("checkboxContainer"),
+        button3            : dialog.getButton("extra2"),
+        button2            : dialog.getButton("extra1"),
+        button1            : dialog.getButton("cancel"),
+        button0            : dialog.getButton("accept"),
+        focusTarget        : window,
+    };
+
+    // limit the dialog to the screen width
+    document.getElementById("filler").maxWidth = screen.availWidth;
+    Services.obs.addObserver(softkbObserver, "softkb-change", false);
+
+    Dialog = new CommonDialog(args, ui);
+    Dialog.onLoad(dialog);
+    window.getAttention();
 }
 
-function initTextbox(aName, aValue) {
-    document.getElementById(aName + "Container").hidden = false;
-    document.getElementById(aName + "Textbox").setAttribute("value", aValue);
-}
-
-function setLabelForNode(aNode, aLabel, aIsLabelFlag) {
-    // This is for labels which may contain embedded access keys.
-    // If we end in (&X) where X represents the access key, optionally preceded
-    // by spaces and/or followed by the ':' character, store the access key and
-    // remove the access key placeholder + leading spaces from the label.
-    // Otherwise a character preceded by one but not two &s is the access key.
-    // Store it and remove the &.
-
-    // Note that if you change the following code, see the comment of
-    // nsTextBoxFrame::UpdateAccessTitle.
-    var accessKey = null;
-    if (/ *\(\&([^&])\)(:)?$/.test(aLabel)) {
-        aLabel = RegExp.leftContext + RegExp.$2;
-        accessKey = RegExp.$1;
-    } else if (/^(.*[^&])?\&(([^&]).*$)/.test(aLabel)) {
-        aLabel = RegExp.$1 + RegExp.$2;
-        accessKey = RegExp.$3;
-    }
-
-    // && is the magic sequence to embed an & in your label.
-    aLabel = aLabel.replace(/\&\&/g, "&");
-    if (aIsLabelFlag) {    // Set text for <label> element
-        aNode.setAttribute("value", aLabel);
-    } else {    // Set text for other xul elements
-        aNode.label = aLabel;
-    }
-
-    // XXXjag bug 325251
-    // Need to set this after aNode.setAttribute("value", aLabel);
-    if (accessKey)
-        aNode.accessKey = accessKey;
+function commonDialogOnUnload() {
+    Services.obs.removeObserver(softkbObserver, "softkb-change");
+    // Convert args back into property bag
+    for (let propName in args)
+        propBag.setProperty(propName, args[propName]);
 }
 
 function softkbObserver(subject, topic, data) {
     let rect = JSON.parse(data);
     if (rect) {
         let height = rect.bottom - rect.top;
         let width  = rect.right - rect.left;
         let top    = (rect.top + (height - window.innerHeight) / 2);
         let left   = (rect.left + (width - window.innerWidth) / 2);
         window.moveTo(left, top);
     }
 }
-
-function commonDialogOnLoad() {
-    // limit the dialog to the screen width
-    document.getElementById("filler").maxWidth = screen.availWidth;
-
-    // set the document title
-    let title = gArgs.getProperty("title");
-#ifdef XP_MACOSX
-    document.getElementById("info.title").appendChild(document.createTextNode(title));
-#else
-    document.title = title;
-#endif
-
-    Services.obs.addObserver(softkbObserver, "softkb-change", false);
-
-    // Set button visibility
-    let dialog = document.documentElement;
-    switch (numButtons) {
-      case 1:
-        dialog.getButton("cancel").hidden = true;
-        break;
-      case 4:
-        dialog.getButton("extra2").hidden = false;
-      case 3:
-        dialog.getButton("extra1").hidden = false;
-    }
-
-    // Set button labels
-    switch (numButtons) {
-      case 4:
-        setLabelForNode(document.documentElement.getButton("extra2"), gArgs.getProperty("button3Label"));
-        // fall through
-      case 3:
-        setLabelForNode(document.documentElement.getButton("extra1"), gArgs.getProperty("button2Label"));
-        // fall through
-      default:
-      case 2:
-        if (gArgs.hasKey("button1Label"))
-            setLabelForNode(document.documentElement.getButton("cancel"), gArgs.getProperty("button1Label"));
-        // fall through
-      case 1:
-        if (gArgs.hasKey("button0Label"))
-            setLabelForNode(document.documentElement.getButton("accept"), gArgs.getProperty("button0Label"));
-        break;
-    }
-
-    // display the main text
-    // Bug 317334 - crop string length as a workaround.
-    let croppedMessage = gArgs.getProperty("text").substr(0, 10000);
-    document.getElementById("info.body").appendChild(document.createTextNode(croppedMessage));
-
-    if (gArgs.hasKey("checkLabel")) {
-        let label = gArgs.getProperty("checkLabel")
-        // Only show the checkbox if label has a value.
-        if (label) {
-            document.getElementById("checkboxContainer").hidden = false;
-            let checkboxElement = document.getElementById("checkbox");
-            setLabelForNode(checkboxElement, label);
-            checkboxElement.checked = gArgs.getProperty("checked");
-        }
-    }
-
-    // set the icon
-    document.getElementById("info.icon").className += " " + iconClass;
-
-    // set default result to cancelled
-    gArgs.setProperty("ok", false);
-    gArgs.setProperty("buttonNumClicked", 1);
-
-
-    // If there are no input fields on the dialog, select the default button.
-    // Otherwise, select the appropriate input field.
-    if (!hasInputField) {
-        let dlgButtons = ['accept', 'cancel', 'extra1', 'extra2'];
-
-        // Set the default button and focus it on non-OS X systems
-        let b = 0;
-        if (gArgs.hasKey("defaultButtonNum"))
-            b = gArgs.getProperty("defaultButtonNum");
-        let dButton = dlgButtons[b];
-        // XXX shouldn't we set the default even when a textbox is focused?
-        document.documentElement.defaultButton = dButton;
-#ifndef XP_MACOSX
-        document.documentElement.getButton(dButton).focus();
-#endif
-    } else {
-        if (promptType == "promptPassword")
-            document.getElementById("password1Textbox").select();
-        else
-            document.getElementById("loginTextbox").select();
-    }
-
-    if (gArgs.hasKey("enableDelay") && gArgs.getProperty("enableDelay")) {
-        let delayInterval = Services.prefs.getIntPref("security.dialog_enable_delay");
-
-        document.documentElement.getButton("accept").disabled = true;
-        document.documentElement.getButton("extra1").disabled = true;
-        document.documentElement.getButton("extra2").disabled = true;
-
-        setTimeout(commonDialogReenableButtons, delayInterval);
-
-        addEventListener("blur", commonDialogBlur, false);
-        addEventListener("focus", commonDialogFocus, false);
-    }
-
-    window.getAttention();
-
-    // play sound
-    try {
-        if (soundID) {
-            Cc["@mozilla.org/sound;1"].
-            createInstance(Ci.nsISound).
-            playEventSound(soundID);
-        }
-    } catch (e) { }
-
-    Services.obs.notifyObservers(window, "common-dialog-loaded", null);
-}
-
-function commonDialogOnUnload() {
-    Services.obs.removeObserver(softkbObserver, "softkb-change");
-}
-
-
-var gDelayExpired = false;
-var gBlurred = false;
-
-function commonDialogBlur(aEvent) {
-    if (aEvent.target != document)
-        return;
-    gBlurred = true;
-    document.documentElement.getButton("accept").disabled = true;
-    document.documentElement.getButton("extra1").disabled = true;
-    document.documentElement.getButton("extra2").disabled = true;
-}
-
-function commonDialogFocus(aEvent) {
-    if (aEvent.target != document)
-        return;
-    gBlurred = false;
-    // When refocusing the window, don't enable the buttons unless the countdown
-    // delay has expired.
-    if (gDelayExpired) {
-        let script;
-        script  = "document.documentElement.getButton('accept').disabled = false; ";
-        script += "document.documentElement.getButton('extra1').disabled = false; ";
-        script += "document.documentElement.getButton('extra2').disabled = false;";
-        setTimeout(script, 250);
-    }
-}
-
-function commonDialogReenableButtons() {
-    // Don't automatically enable the buttons if we're not in the foreground
-    if (!gBlurred) {
-        document.documentElement.getButton("accept").disabled = false;
-        document.documentElement.getButton("extra1").disabled = false;
-        document.documentElement.getButton("extra2").disabled = false;
-    }
-    gDelayExpired = true;
-}
-
-function onCheckboxClick(aCheckboxElement) {
-    gArgs.setProperty("checked", aCheckboxElement.checked);
-}
-
-function commonDialogOnAccept() {
-    gArgs.setProperty("ok", true);
-    gArgs.setProperty("buttonNumClicked", 0);
-
-    let username = document.getElementById("loginTextbox").value;
-    let password = document.getElementById("password1Textbox").value;
-
-    // Return textfield values
-    switch (promptType) {
-      case "prompt":
-        gArgs.setProperty("value", username);
-        break;
-      case "promptUserAndPass":
-        gArgs.setProperty("user", username);
-        gArgs.setProperty("pass", password);
-        break;
-      case "promptPassword":
-        gArgs.setProperty("pass", password);
-        break;
-    }
-}
-
-function commonDialogOnExtra1() {
-    // .setProperty("ok", true)?
-    gArgs.setProperty("buttonNumClicked", 2);
-    window.close();
-}
-
-function commonDialogOnExtra2() {
-    // .setProperty("ok", true)?
-    gArgs.setProperty("buttonNumClicked", 3);
-    window.close();
-}
--- a/toolkit/components/prompts/content/commonDialog.xul
+++ b/toolkit/components/prompts/content/commonDialog.xul
@@ -1,26 +1,27 @@
-<?xml version="1.0"?> 
+<?xml version="1.0"?>
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 <?xml-stylesheet href="chrome://global/content/commonDialog.css" type="text/css"?>
 <?xml-stylesheet href="chrome://global/skin/commonDialog.css" type="text/css"?>
 
 <!DOCTYPE dialog SYSTEM "chrome://global/locale/commonDialog.dtd">
 
 <dialog id="commonDialog"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         aria-describedby="info.body"
         onload="commonDialogOnLoad();"
         onunload="commonDialogOnUnload();"
-        ondialogaccept="return commonDialogOnAccept();"
-        ondialogextra1="return commonDialogOnExtra1();"
-        ondialogextra2="return commonDialogOnExtra2();"
+        ondialogaccept="Dialog.onButton0(); return true;"
+        ondialogcancel="Dialog.onButton1(); return true;"
+        ondialogextra1="Dialog.onButton2(); window.close();"
+        ondialogextra2="Dialog.onButton3(); window.close();"
         buttonpack="center">
-    
+
   <script type="application/javascript" src="chrome://global/content/commonDialog.js"/>
   <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
 
   <commandset id="selectEditMenuItems">
     <command id="cmd_copy" oncommand="goDoCommand('cmd_copy')" disabled="true"/>
     <command id="cmd_selectAll" oncommand="goDoCommand('cmd_selectAll')"/>
   </commandset>
 
@@ -50,39 +51,34 @@
     </columns>
 
     <rows>
       <row>
         <hbox id="iconContainer" align="start">
           <image id="info.icon" class="spaced"/>
         </hbox>
         <vbox id="infoContainer">
-#ifdef XP_MACOSX
-          <!-- Dialog title is inside dialog for OS X -->
-          <description id="info.title"/>
+          <!-- Only shown on OS X, since it has no dialog title -->
+          <description id="info.title"
+#ifndef XP_MACOSX
+            style="display: none"
 #endif
+          />
           <spacer style="height: 1em"/>
           <description id="info.body" context="contentAreaContextMenu" noinitialfocus="true"/>
         </vbox>
       </row>
       <row id="loginContainer" hidden="true" align="center">
         <label id="loginLabel" value="&editfield0.label;" control="loginTextbox"/>
         <textbox id="loginTextbox"/>
       </row>
       <row id ="password1Container" hidden="true" align="center">
         <label id="password1Label" value="&editfield1.label;" control="password1Textbox"/>
         <textbox type="password" id="password1Textbox"/>
       </row>
       <row id="checkboxContainer" hidden="true">
         <spacer/>
-        <checkbox id="checkbox" oncommand="onCheckboxClick(this);"/>
+        <checkbox id="checkbox" oncommand="Dialog.onCheckbox()"/>
       </row>
     </rows>
   </grid>
 
-
-  <!-- This method is called inline because it may unset hidden="true" on the
-       above boxes, causing their frames to be build and bindings to load.  
-       So, by calling this inline, we guarantee the textboxes and checkboxes 
-       above will have their bindings before initButtons is called, and the
-       dialog will be intrinsically sized correctly. -->
-  <script type="application/javascript">earlyInit();</script>
 </dialog>
--- a/toolkit/components/prompts/content/selectDialog.js
+++ b/toolkit/components/prompts/content/selectDialog.js
@@ -36,22 +36,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cc = Components.classes;
 const Cu = Components.utils;
 
-let gArgs = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
+let gArgs, listBox;
+
+function dialogOnLoad() {
+    gArgs = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
                                .QueryInterface(Ci.nsIWritablePropertyBag);
 
-let listBox;
-
-function dialogOnLoad() {
     let promptType = gArgs.getProperty("promptType");
     if (promptType != "select") {
         Cu.reportError("selectDialog opened for unknown type: " + promptType);
         window.close();
     }
 
     // Default to canceled.
     gArgs.setProperty("ok", false);
--- a/toolkit/components/prompts/content/selectDialog.xul
+++ b/toolkit/components/prompts/content/selectDialog.xul
@@ -1,9 +1,9 @@
-<?xml version="1.0"?> 
+<?xml version="1.0"?>
 
 <!-- ***** BEGIN LICENSE BLOCK *****
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at
  http://www.mozilla.org/MPL/
@@ -32,20 +32,20 @@
  use your version of this file under the terms of the MPL, indicate your
  decision by deleting the provisions above and replace them with the notice
  and other provisions required by the GPL or the LGPL. If you do not delete
  the provisions above, a recipient may use your version of this file under
  the terms of any one of the MPL, the GPL or the LGPL.
 
  ***** END LICENSE BLOCK ***** -->
 
-<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?> 
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
 <!DOCTYPE dialog SYSTEM "chrome://global/locale/commonDialog.dtd">
- 
-<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 
+
+<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
       onload="dialogOnLoad()"
       ondialogaccept="return dialogOK();">
 
   <script type="application/javascript" src="chrome://global/content/selectDialog.js" />
   <keyset id="dialogKeys"/>
   <vbox style="width: 24em;margin: 5px;">
     <label id="info.txt"/>
     <vbox>
new file mode 100644
--- /dev/null
+++ b/toolkit/components/prompts/src/CommonDialog.jsm
@@ -0,0 +1,350 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is CommonDialog.jsm code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Justin Dolske <dolske@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var EXPORTED_SYMBOLS = ["CommonDialog"];
+
+const Ci = Components.interfaces;
+const Cr = Components.results;
+const Cc = Components.classes;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+
+function CommonDialog(args, ui) {
+    this.args = args;
+    this.ui   = ui;
+}
+
+CommonDialog.prototype = {
+    args : null,
+    ui   : null,
+
+    hasInputField : true,
+    numButtons    : undefined,
+    iconClass     : undefined,
+    soundID       : undefined,
+    focusTimer    : null,
+
+    onLoad : function(xulDialog) {
+        switch (this.args.promptType) {
+          case "alert":
+          case "alertCheck":
+            this.hasInputField = false;
+            this.numButtons    = 1;
+            this.iconClass     = ["alert-icon"];
+            this.soundID       = Ci.nsISound.EVENT_ALERT_DIALOG_OPEN;
+            break;
+          case "confirmCheck":
+          case "confirm":
+            this.hasInputField = false;
+            this.numButtons    = 2;
+            this.iconClass     = ["question-icon"];
+            this.soundID       = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
+            break;
+          case "confirmEx":
+            var numButtons = 0;
+            if (this.args.button0Label)
+                numButtons++;
+            if (this.args.button1Label)
+                numButtons++;
+            if (this.args.button2Label)
+                numButtons++;
+            if (this.args.button3Label)
+                numButtons++;
+            if (numButtons == 0)
+                throw "A dialog with no buttons? Can not haz.";
+            this.numButtons    = numButtons;
+            this.hasInputField = false;
+            this.iconClass     = ["question-icon"];
+            this.soundID       = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
+            break;
+          case "prompt":
+            this.numButtons = 2;
+            this.iconClass  = ["question-icon"];
+            this.soundID    = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
+            this.initTextbox("login", this.args.value);
+            // Clear the label, since this isn't really a username prompt.
+            this.ui.loginLabel.setAttribute("value", "");
+            break;
+          case "promptUserAndPass":
+            this.numButtons = 2;
+            this.iconClass  = ["authentication-icon", "question-icon"];
+            this.soundID    = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
+            this.initTextbox("login",     this.args.user);
+            this.initTextbox("password1", this.args.pass);
+            break;
+          case "promptPassword":
+            this.numButtons = 2;
+            this.iconClass  = ["authentication-icon", "question-icon"];
+            this.soundID    = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
+            this.initTextbox("password1", this.args.pass);
+            // Clear the label, since the message presumably indicates its purpose.
+            this.ui.password1Label.setAttribute("value", "");
+            break;
+          default:
+            Cu.reportError("commonDialog opened for unknown type: " + this.args.promptType);
+            throw "unknown dialog type";
+        }
+
+        // set the document title
+        let title = this.args.title;
+        // OS X doesn't have a title on modal dialogs, this is hidden on other platforms.
+        let infoTitle = this.ui.infoTitle;
+        infoTitle.appendChild(infoTitle.ownerDocument.createTextNode(title));
+        if (xulDialog)
+            xulDialog.ownerDocument.title = title;
+
+        // Set button labels and visibility
+        //
+        // This assumes that button0 defaults to a visible "ok" button, and
+        // button1 defaults to a visible "cancel" button. The other 2 buttons
+        // have no default labels (and are hidden).
+        switch (this.numButtons) {
+          case 4:
+            this.setLabelForNode(this.ui.button3, this.args.button3Label);
+            this.ui.button3.hidden = false;
+            // fall through
+          case 3:
+            this.setLabelForNode(this.ui.button2, this.args.button2Label);
+            this.ui.button2.hidden = false;
+            // fall through
+          case 2:
+            // Defaults to a visible "cancel" button
+            if (this.args.button1Label)
+                this.setLabelForNode(this.ui.button1, this.args.button1Label);
+            break;
+
+          case 1:
+            this.ui.button1.hidden = true;
+            break;
+        }
+        // Defaults to a visible "ok" button
+        if (this.args.button0Label)
+            this.setLabelForNode(this.ui.button0, this.args.button0Label);
+
+        // display the main text
+        // Bug 317334 - crop string length as a workaround.
+        let croppedMessage = this.args.text.substr(0, 10000);
+        let infoBody = this.ui.infoBody;
+        infoBody.appendChild(infoBody.ownerDocument.createTextNode(croppedMessage));
+
+        let label = this.args.checkLabel;
+        if (label) {
+            // Only show the checkbox if label has a value.
+            this.ui.checkboxContainer.hidden = false;
+            this.setLabelForNode(this.ui.checkbox, label);
+            this.ui.checkbox.checked = this.args.checked;
+        }
+
+        // set the icon
+        let icon = this.ui.infoIcon;
+        this.iconClass.forEach(function(el,idx,arr) icon.classList.add(el));
+
+        // set default result to cancelled
+        this.args.ok = false;
+        this.args.buttonNumClicked = 1;
+
+
+        // If there are no input fields on the dialog, select the default button.
+        // Otherwise, select the appropriate input field.
+        // XXX shouldn't we set an unfocused default even when a textbox is focused?
+        if (!this.hasInputField) {
+            // Set the default button (and focus it on non-OS X systems)
+            let b = 0;
+            if (this.args.defaultButtonNum)
+                b = this.args.defaultButtonNum;
+            let button = this.ui["button" + b];
+            if (xulDialog) {
+                xulDialog.defaultButton = ['accept', 'cancel', 'extra1', 'extra2'][b];
+                let isOSX = ("nsILocalFileMac" in Components.interfaces);
+                if (!isOSX)
+                    button.focus();
+            }
+            // TODO:
+            // else
+            //     (tabmodal prompts need to set a default button for Enter to act upon)
+        } else {
+            if (this.args.promptType == "promptPassword")
+                this.ui.password1Textbox.select();
+            else
+                this.ui.loginTextbox.select();
+        }
+
+        if (this.args.enableDelay) {
+            this.setButtonsEnabledState(false);
+            // Use a longer, pref-controlled delay when the dialog is first opened.
+            let delayTime = Services.prefs.getIntPref("security.dialog_enable_delay");
+            this.startOnFocusDelay(delayTime);
+            let self = this;
+            this.ui.focusTarget.addEventListener("blur",  function(e) { self.onBlur(e);  }, false);
+            this.ui.focusTarget.addEventListener("focus", function(e) { self.onFocus(e); }, false);
+        }
+
+        // play sound
+        try {
+            if (this.soundID) {
+                Cc["@mozilla.org/sound;1"].
+                createInstance(Ci.nsISound).
+                playEventSound(soundID);
+            }
+        } catch (e) { }
+
+        if (xulDialog)
+            Services.obs.notifyObservers(xulDialog.ownerDocument.defaultView, "common-dialog-loaded", null);
+        // TODO:
+        // else
+        //    (notify using what as the subject?)
+    },
+
+    setLabelForNode: function(aNode, aLabel) {
+        // This is for labels which may contain embedded access keys.
+        // If we end in (&X) where X represents the access key, optionally preceded
+        // by spaces and/or followed by the ':' character, store the access key and
+        // remove the access key placeholder + leading spaces from the label.
+        // Otherwise a character preceded by one but not two &s is the access key.
+        // Store it and remove the &.
+
+        // Note that if you change the following code, see the comment of
+        // nsTextBoxFrame::UpdateAccessTitle.
+        var accessKey = null;
+        if (/ *\(\&([^&])\)(:)?$/.test(aLabel)) {
+            aLabel = RegExp.leftContext + RegExp.$2;
+            accessKey = RegExp.$1;
+        } else if (/^(.*[^&])?\&(([^&]).*$)/.test(aLabel)) {
+            aLabel = RegExp.$1 + RegExp.$2;
+            accessKey = RegExp.$3;
+        }
+
+        // && is the magic sequence to embed an & in your label.
+        aLabel = aLabel.replace(/\&\&/g, "&");
+        aNode.label = aLabel;
+
+        // XXXjag bug 325251
+        // Need to set this after aNode.setAttribute("value", aLabel);
+        if (accessKey)
+            aNode.accessKey = accessKey;
+    },
+
+
+    initTextbox : function (aName, aValue) {
+        this.ui[aName + "Container"].hidden = false;
+        this.ui[aName + "Textbox"].setAttribute("value", aValue);
+    },
+
+    setButtonsEnabledState : function(enabled) {
+        this.ui.button0.disabled = !enabled;
+        // button1 (cancel) remains enabled.
+        this.ui.button2.disabled = !enabled;
+        this.ui.button3.disabled = !enabled;
+    },
+
+    onBlur : function (aEvent) {
+        if (aEvent.target != this.ui.focusTarget)
+            return;
+        this.setButtonsEnabledState(false);
+
+        // If we blur while waiting to enable the buttons, just cancel the
+        // timer to ensure the delay doesn't fire while not focused.
+        if (this.focusTimer) {
+            this.focusTimer.cancel();
+            this.focusTimer = null;
+        }
+    },
+
+    onFocus : function (aEvent) {
+        if (aEvent.target != this.ui.focusTarget)
+            return;
+        this.startOnFocusDelay();
+    },
+
+    startOnFocusDelay : function(delayTime) {
+        // Shouldn't already have a timer, but just in case...
+        if (this.focusTimer)
+            return;
+        // If no delay specified, use 250ms. (This is the normal case for when
+        // after the dialog has been opened and focus shifts.)
+        if (!delayTime)
+            delayTime = 250;
+        let self = this;
+        this.focusTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+        this.focusTimer.initWithCallback(function() { self.onFocusTimeout(); },
+                                         delayTime, Ci.nsITimer.TYPE_ONE_SHOT);
+    },
+
+    onFocusTimeout : function() {
+        this.focusTimer = null;
+        this.setButtonsEnabledState(true);
+    },
+
+    onCheckbox : function() {
+        this.args.checked = this.ui.checkbox.checked;
+    },
+
+    onButton0 : function() {
+        this.args.ok = true;
+        this.args.buttonNumClicked = 0;
+
+        let username = this.ui.loginTextbox.value;
+        let password = this.ui.password1Textbox.value;
+
+        // Return textfield values
+        switch (this.args.promptType) {
+          case "prompt":
+            this.args.value = username;
+            break;
+          case "promptUserAndPass":
+            this.args.user = username;
+            this.args.pass = password;
+            break;
+          case "promptPassword":
+            this.args.pass = password;
+            break;
+        }
+    },
+
+    onButton1 : function() {
+        this.args.buttonNumClicked = 1;
+    },
+
+    onButton2 : function() {
+        this.args.buttonNumClicked = 2;
+    },
+
+    onButton3 : function() {
+        this.args.buttonNumClicked = 3;
+    },
+};
--- a/toolkit/components/prompts/src/Makefile.in
+++ b/toolkit/components/prompts/src/Makefile.in
@@ -43,9 +43,13 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE = prompter
 
 EXTRA_COMPONENTS = \
     nsPrompter.js \
     nsPrompter.manifest \
     $(NULL)
 
+EXTRA_JS_MODULES = \
+    CommonDialog.jsm \
+    $(NULL)
+
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/components/prompts/src/nsPrompter.js
+++ b/toolkit/components/prompts/src/nsPrompter.js
@@ -317,16 +317,35 @@ let PromptUtils = {
         else if (!realm)
             text = PromptUtils.getLocalizedString("EnterUserPasswordFor", [displayHost]);
         else
             text = PromptUtils.getLocalizedString("EnterLoginForRealm", [realm, displayHost]);
 
         return text;
     },
 
+    objectToPropBag : function (obj) {
+        let bag = Cc["@mozilla.org/hash-property-bag;1"].
+                  createInstance(Ci.nsIWritablePropertyBag2);
+        bag.QueryInterface(Ci.nsIWritablePropertyBag);
+
+        for (let propName in obj)
+            bag.setProperty(propName, obj[propName]);
+
+        return bag;
+    },
+
+    propBagToObject : function (propBag, obj) {
+        // Here we iterate over the object's original properties, not the bag
+        // (ie, the prompt can't return more/different properties than were
+        // passed in). This just helps ensure that the caller provides default
+        // values, lest the prompt forget to set them.
+        for (let propName in obj)
+            obj[propName] = propBag.getProperty(propName);
+    },
 };
 
 XPCOMUtils.defineLazyGetter(PromptUtils, "strBundle", function () {
     let bunService = Cc["@mozilla.org/intl/stringbundle;1"].
                      getService(Ci.nsIStringBundleService);
     let bundle = bunService.createBundle("chrome://global/locale/commonDialogs.properties");
     if (!bundle)
         throw "String bundle for Prompter not present!";
@@ -338,50 +357,51 @@ XPCOMUtils.defineLazyGetter(PromptUtils,
     try {
         ellipsis = Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
     } catch (e) { }
     return ellipsis;
 });
 
 
 
-const COMMON_DIALOG = "chrome://global/content/commonDialog.xul";
-const SELECT_DIALOG = "chrome://global/content/selectDialog.xul";
+function openModalWindow(domWin, uri, args) {
+    // XXX do we want to do modal state if we fall back to .activeWindow?
+    if (!domWin)
+        domWin = Services.ww.activeWindow;
+
+    // XXX domWin may still be null here if there are _no_ windows open.
+
+    // Note that we don't need to fire DOMWillOpenModalDialog and
+    // DOMModalDialogClosed events here, wwatcher's OpenWindowJSInternal
+    // will do that. Similarly for enterModalState / leaveModalState.
+
+    Services.ww.openWindow(domWin, uri, "_blank", "centerscreen,chrome,modal,titlebar", args);
+}
 
 function ModalPrompter(domWin) {
     this.domWin = domWin;
 }
 ModalPrompter.prototype = {
     domWin : null,
 
     QueryInterface : XPCOMUtils.generateQI([Ci.nsIPrompt, Ci.nsIAuthPrompt, Ci.nsIAuthPrompt2]),
 
 
     /* ---------- internal methods ---------- */
 
 
-    newPropBag : function () {
-        let bag = Cc["@mozilla.org/hash-property-bag;1"].
-                  createInstance(Ci.nsIWritablePropertyBag2);
-        return bag.QueryInterface(Ci.nsIWritablePropertyBag);
-    },
+    openPrompt : function (args) {
+        const COMMON_DIALOG = "chrome://global/content/commonDialog.xul";
+        const SELECT_DIALOG = "chrome://global/content/selectDialog.xul";
 
-    openPrompt : function (uri, args) {
-        // XXX do we want to do modal state if we fall back to .activeWindow?
-        let domWin = this.domWin;
-        if (!domWin)
-            domWin = Services.ww.activeWindow;
+        let uri = (args.promptType == "select") ? SELECT_DIALOG : COMMON_DIALOG;
 
-        // XXX domWin may still be null here if there are _no_ windows open.
-
-        // Note that we don't need to fire DOMWillOpenModalDialog and
-        // DOMModalDialogClosed events here, wwatcher's OpenWindowJSInternal
-        // will do that. Similarly for enterModalState / leaveModalState.
-
-        Services.ww.openWindow(domWin, uri, "_blank", "centerscreen,chrome,modal,titlebar", args);
+        let propBag = PromptUtils.objectToPropBag(args);
+        openModalWindow(this.domWin, uri, propBag);
+        PromptUtils.propBagToObject(propBag, args);
     },
 
 
 
     /*
      * ---------- interface disambiguation ----------
      *
      * nsIPrompt and nsIAuthPrompt share 3 method names with slightly
@@ -416,212 +436,222 @@ ModalPrompter.prototype = {
 
     /* ----------  nsIPrompt  ---------- */
 
 
     alert : function (title, text) {
         if (!title)
             title = PromptUtils.getLocalizedString("Alert");
 
-        let args = this.newPropBag();
-        args.setProperty("promptType", "alert");
-        args.setProperty("title", title);
-        args.setProperty("text",  text);
+        let args = {
+            promptType: "alert",
+            title:      title,
+            text:       text,
+        };
 
-        this.openPrompt(COMMON_DIALOG, args);
+        this.openPrompt(args);
     },
 
     alertCheck : function (title, text, checkLabel, checkValue) {
         if (!title)
             title = PromptUtils.getLocalizedString("Alert");
 
-        let args = this.newPropBag();
-        args.setProperty("promptType", "alertCheck");
-        args.setProperty("title",      title);
-        args.setProperty("text",       text);
-        args.setProperty("checkLabel", checkLabel);
-        args.setProperty("checked",    checkValue.value);
+        let args = {
+            promptType: "alertCheck",
+            title:      title,
+            text:       text,
+            checkLabel: checkLabel,
+            checked:    checkValue.value,
+        };
 
-        this.openPrompt(COMMON_DIALOG, args);
+        this.openPrompt(args);
 
         // Checkbox state always returned, even if cancel clicked.
-        checkValue.value = args.getProperty("checked");
+        checkValue.value = args.checked;
     },
 
     confirm : function (title, text) {
         if (!title)
             title = PromptUtils.getLocalizedString("Confirm");
 
-        let args = this.newPropBag();
-        args.setProperty("promptType", "confirm");
-        args.setProperty("title",      title);
-        args.setProperty("text",       text);
-        args.setProperty("ok",         false);
+        let args = {
+            promptType: "confirm",
+            title:      title,
+            text:       text,
+            ok:         false,
+        };
 
-        this.openPrompt(COMMON_DIALOG, args);
+        this.openPrompt(args);
 
         // Did user click Ok or Cancel?
-        return args.getProperty("ok");
+        return args.ok;
     },
 
     confirmCheck : function (title, text, checkLabel, checkValue) {
         if (!title)
             title = PromptUtils.getLocalizedString("ConfirmCheck");
 
-        let args = this.newPropBag();
-        args.setProperty("promptType", "confirmCheck");
-        args.setProperty("title",      title);
-        args.setProperty("text",       text);
-        args.setProperty("checkLabel", checkLabel);
-        args.setProperty("checked",    checkValue.value);
-        args.setProperty("ok",         false);
+        let args = {
+            promptType: "confirmCheck",
+            title:      title,
+            text:       text,
+            checkLabel: checkLabel,
+            checked:    checkValue.value,
+            ok:         false,
+        };
 
-        this.openPrompt(COMMON_DIALOG, args);
+        this.openPrompt(args);
 
         // Checkbox state always returned, even if cancel clicked.
-        checkValue.value = args.getProperty("checked");
+        checkValue.value = args.checked;
 
         // Did user click Ok or Cancel?
-        return args.getProperty("ok");
+        return args.ok;
     },
 
     confirmEx : function (title, text, flags, button0, button1, button2,
                           checkLabel, checkValue) {
 
         if (!title)
             title = PromptUtils.getLocalizedString("Confirm");
 
-        let args = this.newPropBag();
-        args.setProperty("promptType", "confirmEx");
-        args.setProperty("title",      title);
-        args.setProperty("text",       text);
-        args.setProperty("checkLabel", checkLabel);
-        args.setProperty("checked",    checkValue.value);
-        args.setProperty("ok",         false);
-        args.setProperty("buttonNumClicked", 1);
+        let args = {
+            promptType:  "confirmEx",
+            title:       title,
+            text:        text,
+            checkLabel:  checkLabel,
+            checked:     checkValue.value,
+            ok:          false,
+            buttonNumClicked: 1,
+        };
 
         let [label0, label1, label2, defaultButtonNum, isDelayEnabled] =
             PromptUtils.confirmExHelper(flags, button0, button1, button2);
 
-        args.setProperty("defaultButtonNum", defaultButtonNum);
-        args.setProperty("enableDelay", isDelayEnabled);
+        args.defaultButtonNum = defaultButtonNum;
+        args.enableDelay = isDelayEnabled;
 
         if (label0) {
-            args.setProperty("button0Label", label0);
+            args.button0Label = label0;
             if (label1) {
-                args.setProperty("button1Label", label1);
+                args.button1Label = label1;
                 if (label2) {
-                    args.setProperty("button2Label", label2);
+                    args.button2Label = label2;
                 }
             }
         }
 
-        this.openPrompt(COMMON_DIALOG, args);
+        this.openPrompt(args);
 
         // Checkbox state always returned, even if cancel clicked.
-        checkValue.value = args.getProperty("checked");
+        checkValue.value = args.checked;
 
         // Get the number of the button the user clicked.
-        return args.getProperty("buttonNumClicked");
+        return args.buttonNumClicked;
     },
 
     nsIPrompt_prompt : function (title, text, value, checkLabel, checkValue) {
         if (!title)
             title = PromptUtils.getLocalizedString("Prompt");
 
-        let args = this.newPropBag();
-        args.setProperty("promptType", "prompt");
-        args.setProperty("title",      title);
-        args.setProperty("text",       text);
-        args.setProperty("value",      value.value);
-        args.setProperty("checkLabel", checkLabel);
-        args.setProperty("checked",    checkValue.value);
-        args.setProperty("ok",         false);
+        let args = {
+            promptType: "prompt",
+            title:      title,
+            text:       text,
+            value:      value.value,
+            checkLabel: checkLabel,
+            checked:    checkValue.value,
+            ok:         false,
+        };
 
-        this.openPrompt(COMMON_DIALOG, args);
+        this.openPrompt(args);
 
         // Did user click Ok or Cancel?
-        let ok  = args.getProperty("ok");
+        let ok  = args.ok;
         if (ok) {
-            checkValue.value = args.getProperty("checked");
-            value.value      = args.getProperty("value");
+            checkValue.value = args.checked;
+            value.value      = args.value;
         }
 
         return ok;
     },
 
     nsIPrompt_promptUsernameAndPassword : function (title, text, user, pass, checkLabel, checkValue) {
         if (!title)
             title = PromptUtils.getLocalizedString("PromptUsernameAndPassword2");
 
-        let args = this.newPropBag();
-        args.setProperty("promptType", "promptUserAndPass");
-        args.setProperty("title",      title);
-        args.setProperty("text",       text);
-        args.setProperty("user",       user.value);
-        args.setProperty("pass",       pass.value);
-        args.setProperty("checkLabel", checkLabel);
-        args.setProperty("checked",    checkValue.value);
-        args.setProperty("ok",         false);
+        let args = {
+            promptType: "promptUserAndPass",
+            title:      title,
+            text:       text,
+            user:       user.value,
+            pass:       pass.value,
+            checkLabel: checkLabel,
+            checked:    checkValue.value,
+            ok:         false,
+        };
 
-        this.openPrompt(COMMON_DIALOG, args);
+        this.openPrompt(args);
 
         // Did user click Ok or Cancel?
-        let ok  = args.getProperty("ok");
+        let ok  = args.ok;
         if (ok) {
-            checkValue.value = args.getProperty("checked");
-            user.value       = args.getProperty("user");
-            pass.value       = args.getProperty("pass");
+            checkValue.value = args.checked;
+            user.value       = args.user;
+            pass.value       = args.pass;
         }
 
         return ok;
     },
 
     nsIPrompt_promptPassword : function (title, text, pass, checkLabel, checkValue) {
         if (!title)
             title = PromptUtils.getLocalizedString("PromptPassword2");
 
-        let args = this.newPropBag();
-        args.setProperty("promptType", "promptPassword");
-        args.setProperty("title",      title);
-        args.setProperty("text",       text);
-        args.setProperty("pass",       pass.value);
-        args.setProperty("checkLabel", checkLabel);
-        args.setProperty("checked",    checkValue.value);
-        args.setProperty("ok",         false);
+        let args = {
+            promptType: "promptPassword",
+            title:      title,
+            text:       text,
+            pass:       pass.value,
+            checkLabel: checkLabel,
+            checked:    checkValue.value,
+            ok:         false,
+        }
 
-        this.openPrompt(COMMON_DIALOG, args);
+        this.openPrompt(args);
 
         // Did user click Ok or Cancel?
-        let ok  = args.getProperty("ok");
+        let ok  = args.ok;
         if (ok) {
-            checkValue.value = args.getProperty("checked");
-            pass.value       = args.getProperty("pass");
+            checkValue.value = args.checked;
+            pass.value       = args.pass;
         }
 
         return ok;
     },
 
     select : function (title, text, count, list, selected) {
         if (!title)
             title = PromptUtils.getLocalizedString("Select");
 
-        let args = this.newPropBag();
-        args.setProperty("promptType", "select");
-        args.setProperty("title",      title);
-        args.setProperty("text",       text);
-        args.setProperty("list",       list);
-        args.setProperty("ok",         false);
+        let args = {
+            promptType: "select",
+            title:      title,
+            text:       text,
+            list:       list,
+            selected:   -1,
+            ok:         false,
+        };
 
-        this.openPrompt(SELECT_DIALOG, args);
+        this.openPrompt(args);
 
         // Did user click Ok or Cancel?
-        let ok  = args.getProperty("ok");
+        let ok  = args.ok;
         if (ok)
-            selected.value = args.getProperty("selected");
+            selected.value = args.selected;
 
         return ok;
     },
 
 
     /* ----------  nsIAuthPrompt  ---------- */
 
 
--- a/toolkit/components/prompts/test/test_modal_prompts.html
+++ b/toolkit/components/prompts/test/test_modal_prompts.html
@@ -19,16 +19,30 @@ Prompter tests: modal prompts
 <script class="testbody" type="text/javascript;version=1.8">
 
 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
 
 let prompter = Cc["@mozilla.org/embedcomp/prompt-service;1"].
                getService(Ci.nsIPromptService2);
 let ioService = Cc["@mozilla.org/network/io-service;1"].
                 getService(Ci.nsIIOService);
+let pollTimer;
+
+function pollDialog(dialog) {
+    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+    if (dialog.getButton("accept").disabled)
+        return;
+
+    ok(true, "dialog button is enabled now");
+    pollTimer.cancel();
+    pollTimer = null;
+    dialog.acceptDialog();
+    didDialog = true;
+}
 
 function checkExpectedState(doc, state) {
     let msg        = doc.getElementById("info.body").textContent;
     let icon       = doc.getElementById("info.icon");
     let textOuter  = doc.getElementById("loginContainer");
     let passOuter  = doc.getElementById("password1Container");
     let checkOuter = doc.getElementById("checkboxContainer");
     let textField  = doc.getElementById("loginTextbox");
@@ -649,16 +663,37 @@ function handleDialog(doc, testNum) {
             textValue   : "",
             passValue   : "",
             checkMsg    : "",
             checked     : false,
         };
         checkExpectedState(doc, state);
         break;
 
+      case 30:
+        // ConfirmEx (with delay, ok)
+        state = {
+            msg   : "This is the confirmEx delay text.",
+            title : "TestTitle",
+            iconClass   : "question-icon",
+            textHidden  : true,
+            passHidden  : true,
+            checkHidden : true,
+            textValue   : "",
+            passValue   : "",
+            checkMsg    : "",
+            checked     : false,
+        };
+        is(dialog.getButton("accept").label, "OK",     "Checking accept-button label");
+        is(dialog.getButton("cancel").label, "Cancel", "Checking cancel-button label");
+        is(dialog.getButton("accept").disabled, true,  "Checking accept-button is disabled");
+        is(dialog.getButton("cancel").disabled, false, "Checking cancel-button isn't disabled ");
+        checkExpectedState(doc, state);
+        break;
+
 
       case 100:
         // PromptAuth (no realm, ok, with checkbox)
         state = {
             msg : 'Enter username and password for http://example.com',
             title : "TestTitle",
             iconClass   : "authentication-icon question-icon",
             textHidden  : false,
@@ -706,16 +741,24 @@ function handleDialog(doc, testNum) {
 
       default:
         ok(false, "Uhh, unhandled switch for testNum #" + testNum);
         break;
     }
 
     if (testNum == 28) {
         dialog._doButtonCommand("extra1");
+    } else if (testNum == 30) {
+        // Buttons are disabled at the moment, poll until they're reenabled.
+        // Can't use setInterval here, because the window's in a modal state
+        // and thus DOM events are suppressed.
+        pollTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+        pollTimer.initWithCallback(function() { pollDialog(dialog); },
+                                   100, Ci.nsITimer.TYPE_REPEATING_SLACK);
+        return;
     } else {
         if (clickOK)
             dialog.acceptDialog();
         else
             dialog.cancelDialog();
     }
 
     ok(true, "handleDialog done");
@@ -1044,16 +1087,25 @@ ok(didDialog, "handleDialog was invoked"
 // ===== test 29  =====
 // Alert, no window
 testNum++;
 startCallbackTimer();
 prompter.alert(null, "TestTitle", "This is the alert text.");
 ok(didDialog, "handleDialog was invoked");
 
 
+// ===== test 30 =====
+// ConfirmEx (delay, ok)
+testNum++;
+startCallbackTimer();
+flags = (Ci.nsIPromptService.STD_OK_CANCEL_BUTTONS | Ci.nsIPromptService.BUTTON_DELAY_ENABLE);
+clickedButton = prompter.confirmEx(window, "TestTitle", "This is the confirmEx delay text.", flags, null, null, null, null, {});
+is(clickedButton, 0, "checked expected button num click");
+ok(didDialog, "handleDialog was invoked");
+
 // promptAuth already tested via password manager but do a few specific things here.
 
 
 var channel = ioService.newChannel("http://example.com", null, null);
 var level = Ci.nsIAuthPrompt2.LEVEL_NONE;
 var authinfo = {
     username : "",
     password : "",
--- a/toolkit/components/satchel/src/nsFormFillController.cpp
+++ b/toolkit/components/satchel/src/nsFormFillController.cpp
@@ -289,17 +289,18 @@ nsFormFillController::SetPopupOpen(PRBoo
       NS_ENSURE_STATE(content);
       nsCOMPtr<nsIDocShell> docShell = GetDocShellForInput(mFocusedInput);
       NS_ENSURE_STATE(docShell);
       nsCOMPtr<nsIPresShell> presShell;
       docShell->GetPresShell(getter_AddRefs(presShell));
       NS_ENSURE_STATE(presShell);
       presShell->ScrollContentIntoView(content,
                                        NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
-                                       NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
+                                       NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
+                                       nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
       // mFocusedPopup can be destroyed after ScrollContentIntoView, see bug 420089
       if (mFocusedPopup)
         mFocusedPopup->OpenAutocompletePopup(this, mFocusedInput);
     } else
       mFocusedPopup->ClosePopup();
   }
 
   return NS_OK;
--- a/toolkit/content/widgets/toolbar.xml
+++ b/toolkit/content/widgets/toolbar.xml
@@ -254,31 +254,35 @@
               }
             }
 
             return val;
           ]]>
         </setter>
       </property>
 
+      <field name="_newElementCount">0</field>
       <method name="_getToolbarItem">
         <parameter name="aId"/>
         <body>
           <![CDATA[
             const XUL_NS = "http://www.mozilla.org/keymaster/" +
                            "gatekeeper/there.is.only.xul";
 
             var newItem = null;
             switch (aId) {
               // Handle special cases
               case "separator":
               case "spring":
               case "spacer":
                 newItem = document.createElementNS(XUL_NS, "toolbar" + aId);
-                newItem.id = aId + Date.now() + this.childNodes.length;
+                // Due to timers resolution Date.now() can be the same for
+                // elements created in small timeframes.  So ids are
+                // differentiated through a unique count suffix.
+                newItem.id = aId + Date.now() + (++this._newElementCount);
                 if (aId == "spring")
                   newItem.flex = 1;
                 break;
               default:
                 var toolbox = this.toolbox;
                 if (!toolbox)
                   break;
 
--- a/toolkit/locales/en-US/chrome/global/headsUpDisplay.properties
+++ b/toolkit/locales/en-US/chrome/global/headsUpDisplay.properties
@@ -17,29 +17,47 @@ categoryConsole=Console:
 btnMutation=DOM Mutation
 tipMutation=Toggle DOM Mutation event logging
 btnPageNet=Net
 tipPageNet=Log network access
 btnPageCSS=CSS
 tipPageCSS=Log CSS parsing errors
 btnPageJS=JS
 tipPageJS=Log JavaScript exceptions
+# LOCALIZATION NOTE (btnPageWebDeveloper):
+#
+# This is used as the text of the "Web Developer" button on the toolbar. It
+# shows or hides messages that the web developer inserted on the page for
+# debugging purposes, using calls such console.log() and console.error(). You
+# may wish to localize this as "Page" if that is clearer in your locale. See
+# bug 601667 for more information.
+btnPageWebDeveloper=Web Developer
+# LOCALIZATION NOTE (tipPageWebDeveloper):
+#
+# This is used as the text of the tool tip for the "Web Developer" button on
+# the toolbar.
+tipPageWebDeveloper=Log messages sent to the "console" object
 btnConsoleErrors=Errors
 tipConsoleErrors=Log calls to console.error()
 btnConsoleInfo=Info
 tipConsoleInfo=Log calls to console.info()
 btnConsoleWarnings=Warnings
 tipConsoleWarnings=Log calls to console.warn()
 btnConsoleLog=Log
 tipConsoleLog=Log calls to console.log()
 btnGlobal=Global Messages
 tipGlobal=Toggle Global Message logging
 localConsole=Local Console
 clearConsoleCmd.label=Clear Console
 clearConsoleCmd.accesskey=e
+# LOCALIZATION NOTE (btnClear):
+#
+# This is used as the text of the "Clear" button for the toolbar. It clears the
+# contents of the console.
+btnClear=Clear
 stringFilter=Filter
 close.button=Close
 close.accesskey=C
 update.button=Update
 update.accesskey=U
 # LOCALIZATION NOTE FOR `jsPropertyTitle` AND `jsPropertyInspectTitle`:
 #
 # The "PropertyPanel" is used to display a JS object to the user.
--- a/toolkit/mozapps/extensions/test/browser/addon_prefs.xul
+++ b/toolkit/mozapps/extensions/test/browser/addon_prefs.xul
@@ -1,5 +1,5 @@
-<?xml version="1.0"?>
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        id="addon-test-pref-window">
-  <label value="Oh hai!"/>
-</window>
+<?xml version="1.0"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        id="addon-test-pref-window">
+  <label value="Oh hai!"/>
+</window>
--- a/toolkit/mozapps/extensions/test/browser/browser_bug557943.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug557943.js
@@ -1,77 +1,78 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// Bug 557943 - Searching for addons can result in wrong results
-
-var gManagerWindow;
-
-function test() {
-  waitForExplicitFinish();
-
-  gProvider = new MockProvider();
-
-  gProvider.createAddons([{
-    id: "addon1@tests.mozilla.org",
-    name: "Microsoft .NET Framework Assistant",
-    description: "",
-    version: "6.66"
-  }, {
-    id: "addon2@tests.mozilla.org",
-    name: "AwesomeNet Addon",
-    description: ""
-  }, {
-    id: "addon3@tests.mozilla.org",
-    name: "Dictionnaire MySpell en Francais (réforme 1990)",
-    description: ""
-  }]);
-
-  open_manager("addons://list/extension", function(aWindow) {
-    gManagerWindow = aWindow;
-    run_next_test();
-  });
-}
-
-function end_test() {
-  close_manager(gManagerWindow, function() {
-    finish();
-  });
-}
-
-
-function perform_search(aQuery, aCallback) {
-  var searchBox = gManagerWindow.document.getElementById("header-search");
-  searchBox.value = aQuery;
-
-  EventUtils.synthesizeMouse(searchBox, 2, 2, { }, gManagerWindow);
-  EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
-  wait_for_view_load(gManagerWindow, function() {
-    var list = gManagerWindow.document.getElementById("search-list");
-    var rows = list.getElementsByTagName("richlistitem");
-    aCallback(rows);
-  });
-}
-
-
-add_test(function() {
-  perform_search(".net", function(aRows) {
-    is(aRows.length, 1, "Should only get one result");
-    is(aRows[0].mAddon.id, "addon1@tests.mozilla.org", "Should get expected addon as only result");
-    run_next_test();
-  });
-});
-
-add_test(function() {
-  perform_search("réf", function(aRows) {
-    is(aRows.length, 1, "Should only get one result");
-    is(aRows[0].mAddon.id, "addon3@tests.mozilla.org", "Should get expected addon as only result");
-    run_next_test();
-  });
-});
-
-add_test(function() {
-  perform_search("javascript:void()", function(aRows) {
-    is(aRows.length, 0, "Should not get any results");
-    run_next_test();
-  });
-});
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Bug 557943 - Searching for addons can result in wrong results
+
+var gManagerWindow;
+var gProvider;
+
+function test() {
+  waitForExplicitFinish();
+
+  gProvider = new MockProvider();
+
+  gProvider.createAddons([{
+    id: "addon1@tests.mozilla.org",
+    name: "Microsoft .NET Framework Assistant",
+    description: "",
+    version: "6.66"
+  }, {
+    id: "addon2@tests.mozilla.org",
+    name: "AwesomeNet Addon",
+    description: ""
+  }, {
+    id: "addon3@tests.mozilla.org",
+    name: "Dictionnaire MySpell en Francais (réforme 1990)",
+    description: ""
+  }]);
+
+  open_manager("addons://list/extension", function(aWindow) {
+    gManagerWindow = aWindow;
+    run_next_test();
+  });
+}
+
+function end_test() {
+  close_manager(gManagerWindow, function() {
+    finish();
+  });
+}
+
+
+function perform_search(aQuery, aCallback) {
+  var searchBox = gManagerWindow.document.getElementById("header-search");
+  searchBox.value = aQuery;
+
+  EventUtils.synthesizeMouse(searchBox, 2, 2, { }, gManagerWindow);
+  EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
+  wait_for_view_load(gManagerWindow, function() {
+    var list = gManagerWindow.document.getElementById("search-list");
+    var rows = list.getElementsByTagName("richlistitem");
+    aCallback(rows);
+  });
+}
+
+
+add_test(function() {
+  perform_search(".net", function(aRows) {
+    is(aRows.length, 1, "Should only get one result");
+    is(aRows[0].mAddon.id, "addon1@tests.mozilla.org", "Should get expected addon as only result");
+    run_next_test();
+  });
+});
+
+add_test(function() {
+  perform_search("réf", function(aRows) {
+    is(aRows.length, 1, "Should only get one result");
+    is(aRows[0].mAddon.id, "addon3@tests.mozilla.org", "Should get expected addon as only result");
+    run_next_test();
+  });
+});
+
+add_test(function() {
+  perform_search("javascript:void()", function(aRows) {
+    is(aRows.length, 0, "Should not get any results");
+    run_next_test();
+  });
+});
--- a/toolkit/mozapps/extensions/test/browser/browser_bug557956.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js
@@ -114,17 +114,18 @@ function open_compatibility_window(aInac
   var win = ww.openWindow(null, URI_EXTENSION_UPDATE_DIALOG, "", features, variant);
 
   win.addEventListener("load", function() {
     win.removeEventListener("load", arguments.callee, false);
 
     info("Compatibility dialog opened");
 
     function page_shown(aEvent) {
-      info("Page " + aEvent.target.id + " shown");
+      if (aEvent.target.pageid)
+        info("Page " + aEvent.target.pageid + " shown");
     }
 
     win.addEventListener("pageshow", page_shown, false);
     win.addEventListener("unload", function() {
       win.removeEventListener("unload", arguments.callee, false);
       win.removeEventListener("pageshow", page_shown, false);
       info("Compatibility dialog closed");
     }, false);
--- a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js
@@ -2,17 +2,19 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 /**
  * Tests that history navigation works for the add-ons manager.
  */
 
 function test() {
-  requestLongerTimeout(2);
+  // Set the timeout to 300 seconds since this test can easily take 220 seconds
+  // to run on a Windows debug build when it runs in a tab.
+  requestLongerTimeout(10);
 
   waitForExplicitFinish();
 
   var gProvider = new MockProvider();
   gProvider.createAddons([{
     id: "test1@tests.mozilla.org",
     name: "Test add-on 1",
     description: "foo"
--- a/toolkit/mozapps/extensions/test/browser/browser_bug567127.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug567127.js
@@ -1,159 +1,159 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// Tests bug 567127 - Add install button to the add-ons manager
-
-
-var gFilePickerFiles = [];
-var gMockFilePickerFactory;
-var gMockFilePickerFactoryCID;
-var gManagerWindow;
-
-function MockFilePicker() { }
-
-MockFilePicker.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIFilePicker]),
-  init: function(aParent, aTitle, aMode) { },
-  appendFilters: function(aFilterMask) { },
-  appendFilter: function(aTitle, aFilter) { },
-  defaultString: "",
-  defaultExtension: "",
-  filterIndex: 0,
-  displayDirectory: null,
-  file: null,
-  fileURL: null,
-  get files() {
-    var i = 0;
-    return {
-      getNext: function() gFilePickerFiles[i++],
-      hasMoreElements: function() gFilePickerFiles.length > i
-    };
-  },
-  show: function() {
-    return gFilePickerFiles.length == 0 ?
-           Components.interfaces.nsIFilePicker.returnCancel :
-           Components.interfaces.nsIFilePicker.returnOK;
-  }
-};
-
-// This listens for the next opened window and checks it is of the right url.
-// opencallback is called when the new window is fully loaded
-// closecallback is called when the window is closed
-function WindowOpenListener(url, opencallback, closecallback) {
-  this.url = url;
-  this.opencallback = opencallback;
-  this.closecallback = closecallback;
-
-  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
-                     .getService(Components.interfaces.nsIWindowMediator);
-  wm.addListener(this);
-}
-
-WindowOpenListener.prototype = {
-  url: null,
-  opencallback: null,
-  closecallback: null,
-  window: null,
-  domwindow: null,
-
-  handleEvent: function(event) {
-    is(this.domwindow.document.location.href, this.url, "Should have opened the correct window");
-
-    this.domwindow.removeEventListener("load", this, false);
-    // Allow any other load handlers to execute
-    var self = this;
-    executeSoon(function() { self.opencallback(self.domwindow); } );
-  },
-
-  onWindowTitleChange: function(window, title) {
-  },
-
-  onOpenWindow: function(window) {
-    if (this.window)
-      return;
-
-    this.window = window;
-    this.domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                           .getInterface(Components.interfaces.nsIDOMWindowInternal);
-    this.domwindow.addEventListener("load", this, false);
-  },
-
-  onCloseWindow: function(window) {
-    if (this.window != window)
-      return;
-
-    var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
-                       .getService(Components.interfaces.nsIWindowMediator);
-    wm.removeListener(this);
-    this.opencallback = null;
-    this.window = null;
-    this.domwindow = null;
-
-    // Let the window close complete
-    executeSoon(this.closecallback);
-    this.closecallback = null;
-  }
-};
-
-
-function test_confirmation(aWindow, aExpectedURLs) {
-  var list = aWindow.document.getElementById("itemList");
-  is(list.childNodes.length, aExpectedURLs.length, "Should be the right number of installs");
-
-  aExpectedURLs.forEach(function(aURL) {
-    var node = list.firstChild;
-    while (node) {
-      if (node.url == aURL) {
-        ok(true, "Should have seen " + aURL + " in the list");
-        return;
-      }
-      node = node.nextSibling;
-    }
-    ok(false, "Should have seen " + aURL + " in the list");
-  });
-
-  aWindow.document.documentElement.cancelDialog();
-}
-
-
-function test() {
-  waitForExplicitFinish();
-  
-  gMockFilePickerFactoryCID = Components.ID("{4f595df2-9108-42c6-9910-0dc392a310c9}");
-  gMockFilePickerFactory = XPCOMUtils._getFactory(MockFilePicker);
-  var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
-  compReg.registerFactory(gMockFilePickerFactoryCID,
-                          "Mock FilePicker",
-                          "@mozilla.org/filepicker;1",
-                          gMockFilePickerFactory);
-
-  open_manager("addons://list/extension", function(aWindow) {
-    gManagerWindow = aWindow;
-    run_next_test();
-  });
-}
-
-function end_test() {
-  var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
-  compReg.unregisterFactory(gMockFilePickerFactoryCID,
-                            gMockFilePickerFactory);
-  close_manager(gManagerWindow, function() {
-    finish();
-  });
-}
-
-
-add_test(function() {
-  var filePaths = [
-                   get_addon_file_url("browser_bug567127_1.xpi"),
-                   get_addon_file_url("browser_bug567127_2.xpi")
-                  ];
-  gFilePickerFiles = filePaths.map(function(aPath) aPath.file);
-  
-  new WindowOpenListener(INSTALL_URI, function(aWindow) {
-    test_confirmation(aWindow, filePaths.map(function(aPath) aPath.spec));
-  }, run_next_test);
-  
-  gManagerWindow.gViewController.doCommand("cmd_installFromFile");
-});
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests bug 567127 - Add install button to the add-ons manager
+
+
+var gFilePickerFiles = [];
+var gMockFilePickerFactory;
+var gMockFilePickerFactoryCID;
+var gManagerWindow;
+
+function MockFilePicker() { }
+
+MockFilePicker.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIFilePicker]),
+  init: function(aParent, aTitle, aMode) { },
+  appendFilters: function(aFilterMask) { },
+  appendFilter: function(aTitle, aFilter) { },
+  defaultString: "",
+  defaultExtension: "",
+  filterIndex: 0,
+  displayDirectory: null,
+  file: null,
+  fileURL: null,
+  get files() {
+    var i = 0;
+    return {
+      getNext: function() gFilePickerFiles[i++],
+      hasMoreElements: function() gFilePickerFiles.length > i
+    };
+  },
+  show: function() {
+    return gFilePickerFiles.length == 0 ?
+           Components.interfaces.nsIFilePicker.returnCancel :
+           Components.interfaces.nsIFilePicker.returnOK;
+  }
+};
+
+// This listens for the next opened window and checks it is of the right url.
+// opencallback is called when the new window is fully loaded
+// closecallback is called when the window is closed
+function WindowOpenListener(url, opencallback, closecallback) {
+  this.url = url;
+  this.opencallback = opencallback;
+  this.closecallback = closecallback;
+
+  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                     .getService(Components.interfaces.nsIWindowMediator);
+  wm.addListener(this);
+}
+
+WindowOpenListener.prototype = {
+  url: null,
+  opencallback: null,
+  closecallback: null,
+  window: null,
+  domwindow: null,
+
+  handleEvent: function(event) {
+    is(this.domwindow.document.location.href, this.url, "Should have opened the correct window");
+
+    this.domwindow.removeEventListener("load", this, false);
+    // Allow any other load handlers to execute
+    var self = this;
+    executeSoon(function() { self.opencallback(self.domwindow); } );
+  },
+
+  onWindowTitleChange: function(window, title) {
+  },
+
+  onOpenWindow: function(window) {
+    if (this.window)
+      return;
+
+    this.window = window;
+    this.domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                           .getInterface(Components.interfaces.nsIDOMWindowInternal);
+    this.domwindow.addEventListener("load", this, false);
+  },
+
+  onCloseWindow: function(window) {
+    if (this.window != window)
+      return;
+
+    var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                       .getService(Components.interfaces.nsIWindowMediator);
+    wm.removeListener(this);
+    this.opencallback = null;
+    this.window = null;
+    this.domwindow = null;
+
+    // Let the window close complete
+    executeSoon(this.closecallback);
+    this.closecallback = null;
+  }
+};
+
+
+function test_confirmation(aWindow, aExpectedURLs) {
+  var list = aWindow.document.getElementById("itemList");
+  is(list.childNodes.length, aExpectedURLs.length, "Should be the right number of installs");
+
+  aExpectedURLs.forEach(function(aURL) {
+    var node = list.firstChild;
+    while (node) {
+      if (node.url == aURL) {
+        ok(true, "Should have seen " + aURL + " in the list");
+        return;
+      }
+      node = node.nextSibling;
+    }
+    ok(false, "Should have seen " + aURL + " in the list");
+  });
+
+  aWindow.document.documentElement.cancelDialog();
+}
+
+
+function test() {
+  waitForExplicitFinish();
+  
+  gMockFilePickerFactoryCID = Components.ID("{4f595df2-9108-42c6-9910-0dc392a310c9}");
+  gMockFilePickerFactory = XPCOMUtils._getFactory(MockFilePicker);
+  var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
+  compReg.registerFactory(gMockFilePickerFactoryCID,
+                          "Mock FilePicker",
+                          "@mozilla.org/filepicker;1",
+                          gMockFilePickerFactory);
+
+  open_manager("addons://list/extension", function(aWindow) {
+    gManagerWindow = aWindow;
+    run_next_test();
+  });
+}
+
+function end_test() {
+  var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
+  compReg.unregisterFactory(gMockFilePickerFactoryCID,
+                            gMockFilePickerFactory);
+  close_manager(gManagerWindow, function() {
+    finish();
+  });
+}
+
+
+add_test(function() {
+  var filePaths = [
+                   get_addon_file_url("browser_bug567127_1.xpi"),
+                   get_addon_file_url("browser_bug567127_2.xpi")
+                  ];
+  gFilePickerFiles = filePaths.map(function(aPath) aPath.file);
+  
+  new WindowOpenListener(INSTALL_URI, function(aWindow) {
+    test_confirmation(aWindow, filePaths.map(function(aPath) aPath.spec));
+  }, run_next_test);
+  
+  gManagerWindow.gViewController.doCommand("cmd_installFromFile");
+});
--- a/toolkit/mozapps/extensions/test/browser/browser_bug581076.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug581076.js
@@ -1,129 +1,129 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// Bug 581076 - No "See all results" link present when searching for add-ons and not all are displayed (extensions.getAddons.maxResults)
-
-const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL";
-const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
-const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults";
-const SEARCH_URL = TESTROOT + "browser_searching.xml";
-const SEARCH_EXPECTED_TOTAL = 100;
-const SEARCH_QUERY = "search";
-
-var gManagerWindow;
-
-
-function test() {
-  Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL);
-  Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
-
-  waitForExplicitFinish();
-
-  open_manager("addons://list/extension", function(aWindow) {
-    gManagerWindow = aWindow;
-    run_next_test();
-  });
-}
-
-function end_test() {
-  Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS);
-
-  // Test generates a lot of available installs so just cancel them all
-  AddonManager.getAllInstalls(function(aInstalls) {
-    aInstalls.forEach(function(aInstall) {
-      aInstall.cancel();
-    });
-
-    close_manager(gManagerWindow, finish);
-  });
-}
-
-function search(aRemoteSearch, aCallback) {
-  var searchBox = gManagerWindow.document.getElementById("header-search");
-  searchBox.value = SEARCH_QUERY;
-
-  EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow);
-  EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
-
-  wait_for_view_load(gManagerWindow, function() {
-    if (aRemoteSearch)
-      var filter = gManagerWindow.document.getElementById("search-filter-remote");
-    else
-      var filter = gManagerWindow.document.getElementById("search-filter-local");
-    EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow);
-
-    executeSoon(aCallback);
-  });
-}
-
-function check_allresultslink(aShouldShow) {
-  var list = gManagerWindow.document.getElementById("search-list");
-  var link = gManagerWindow.document.getElementById("search-allresults-link");
-  is(link.parentNode, list.lastChild, "Footer should be at the end of the richlistbox");
-  if (aShouldShow) {
-    is_element_visible(link, "All Results link should be visible");
-    is(link.value, "See all " + SEARCH_EXPECTED_TOTAL + " results", "All Results link should show the correct message");
-    var scope = {};
-    Components.utils.import("resource://gre/modules/AddonRepository.jsm", scope);
-    is(link.href, scope.AddonRepository.getSearchURL(SEARCH_QUERY), "All Results link should have the correct href");
-  } else {
-    is_element_hidden(link, "All Results link should be hidden");
-  }
-}
-
-add_test(function() {
-  info("Searching locally");
-  search(false, function() {
-    check_allresultslink(false);
-    restart_manager(gManagerWindow, null, function(aManager) {
-      gManagerWindow = aManager;
-      run_next_test();
-    });
-  });
-});
-
-add_test(function() {
-  info("Searching remotely - more results than cap");
-  Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3);
-  search(true, function() {
-    check_allresultslink(true);
-    restart_manager(gManagerWindow, null, function(aManager) {
-      gManagerWindow = aManager;
-      run_next_test();
-    });
-  });
-});
-
-add_test(function() {
-  info("Searching remotely - less results than cap");
-  Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 200);
-  search(true, function() {
-    check_allresultslink(false);
-    restart_manager(gManagerWindow, null, function(aManager) {
-      gManagerWindow = aManager;
-      run_next_test();
-    });
-  });
-});
-
-add_test(function() {
-  info("Searching remotely - more results than cap");
-  Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3);
-  search(true, function() {
-    check_allresultslink(true);
-    run_next_test();
-  });
-});
-
-add_test(function() {
-  info("Switching views");
-  gManagerWindow.loadView("addons://list/extension");
-  wait_for_view_load(gManagerWindow, function() {
-    info("Re-loading previous search");
-    search(true, function() {
-      check_allresultslink(true);
-      run_next_test();
-    });
-  });
-});
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Bug 581076 - No "See all results" link present when searching for add-ons and not all are displayed (extensions.getAddons.maxResults)
+
+const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL";
+const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
+const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults";
+const SEARCH_URL = TESTROOT + "browser_searching.xml";
+const SEARCH_EXPECTED_TOTAL = 100;
+const SEARCH_QUERY = "search";
+
+var gManagerWindow;
+
+
+function test() {
+  Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL);
+  Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
+
+  waitForExplicitFinish();
+
+  open_manager("addons://list/extension", function(aWindow) {
+    gManagerWindow = aWindow;
+    run_next_test();
+  });
+}
+
+function end_test() {
+  Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS);
+
+  // Test generates a lot of available installs so just cancel them all
+  AddonManager.getAllInstalls(function(aInstalls) {
+    aInstalls.forEach(function(aInstall) {
+      aInstall.cancel();
+    });
+
+    close_manager(gManagerWindow, finish);
+  });
+}
+
+function search(aRemoteSearch, aCallback) {
+  var searchBox = gManagerWindow.document.getElementById("header-search");
+  searchBox.value = SEARCH_QUERY;
+
+  EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow);
+  EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
+
+  wait_for_view_load(gManagerWindow, function() {
+    if (aRemoteSearch)
+      var filter = gManagerWindow.document.getElementById("search-filter-remote");
+    else
+      var filter = gManagerWindow.document.getElementById("search-filter-local");
+    EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow);
+
+    executeSoon(aCallback);
+  });
+}
+
+function check_allresultslink(aShouldShow) {
+  var list = gManagerWindow.document.getElementById("search-list");
+  var link = gManagerWindow.document.getElementById("search-allresults-link");
+  is(link.parentNode, list.lastChild, "Footer should be at the end of the richlistbox");
+  if (aShouldShow) {
+    is_element_visible(link, "All Results link should be visible");
+    is(link.value, "See all " + SEARCH_EXPECTED_TOTAL + " results", "All Results link should show the correct message");
+    var scope = {};
+    Components.utils.import("resource://gre/modules/AddonRepository.jsm", scope);
+    is(link.href, scope.AddonRepository.getSearchURL(SEARCH_QUERY), "All Results link should have the correct href");
+  } else {
+    is_element_hidden(link, "All Results link should be hidden");
+  }
+}
+
+add_test(function() {
+  info("Searching locally");
+  search(false, function() {
+    check_allresultslink(false);
+    restart_manager(gManagerWindow, null, function(aManager) {
+      gManagerWindow = aManager;
+      run_next_test();
+    });
+  });
+});
+
+add_test(function() {
+  info("Searching remotely - more results than cap");
+  Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3);
+  search(true, function() {
+    check_allresultslink(true);
+    restart_manager(gManagerWindow, null, function(aManager) {
+      gManagerWindow = aManager;
+      run_next_test();
+    });
+  });
+});
+
+add_test(function() {
+  info("Searching remotely - less results than cap");
+  Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 200);
+  search(true, function() {
+    check_allresultslink(false);
+    restart_manager(gManagerWindow, null, function(aManager) {
+      gManagerWindow = aManager;
+      run_next_test();
+    });
+  });
+});
+
+add_test(function() {
+  info("Searching remotely - more results than cap");
+  Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3);
+  search(true, function() {
+    check_allresultslink(true);
+    run_next_test();
+  });
+});
+
+add_test(function() {
+  info("Switching views");
+  gManagerWindow.loadView("addons://list/extension");
+  wait_for_view_load(gManagerWindow, function() {
+    info("Re-loading previous search");
+    search(true, function() {
+      check_allresultslink(true);
+      run_next_test();
+    });
+  });
+});
--- a/toolkit/mozapps/extensions/test/browser/browser_bug587970.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug587970.js
@@ -1,152 +1,152 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// Bug 587970 - Provide ability "Update all now" within 'Available Updates' screen
-
-var gManagerWindow;
-var gProvider;
-
-function test() {
-  waitForExplicitFinish();
-  
-  gProvider = new MockProvider();
-
-  gProvider.createAddons([{
-    id: "addon1@tests.mozilla.org",
-    name: "addon 1",
-    version: "1.0",
-    applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE
-  }, {
-    id: "addon2@tests.mozilla.org",
-    name: "addon 2",
-    version: "2.0",
-    applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE
-  }]);
-  
-
-  open_manager("addons://updates/available", function(aWindow) {
-    gManagerWindow = aWindow;
-    run_next_test();
-  });
-}
-
-
-function end_test() {
-  close_manager(gManagerWindow, finish);
-}
-
-
-add_test(function() {
-  var list = gManagerWindow.document.getElementById("updates-list");
-  is(list.childNodes.length, 0, "Available updates list should be empty");
-
-  var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg");
-  is_element_visible(emptyNotice, "Empty notice should be visible");
-  
-  var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
-  is_element_hidden(updateSelected, "Update Selected button should be hidden");
-
-  info("Adding updates");
-  gProvider.createInstalls([{
-    name: "addon 1",
-    version: "1.1",
-    existingAddon: gProvider.addons[0]
-  }, {
-    name: "addon 2",
-    version: "2.1",
-    existingAddon: gProvider.addons[1]
-  }]);
-
-  function wait_for_refresh() {
-    if (list.childNodes.length == 2 &&
-        list.childNodes[0].mManualUpdate &&
-        list.childNodes[1].mManualUpdate) {
-      run_next_test();
-    } else {
-      info("Waiting for pane to refresh");
-      setTimeout(wait_for_refresh, 10);
-    }
-  }
-  info("Waiting for pane to refresh");
-  setTimeout(wait_for_refresh, 10);
-});
-
-
-add_test(function() {
-  var list = gManagerWindow.document.getElementById("updates-list");
-  is(list.childNodes.length, 2, "Available updates list should have 2 items");
-  
-  var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
-  isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list");
-  var item2 = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org");
-  isnot(item2, null, "Item for addon2@tests.mozilla.org should be in list");
-
-  var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg");
-  is_element_hidden(emptyNotice, "Empty notice should be hidden");
-
-  var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
-  is_element_visible(updateSelected, "Update Selected button should be visible");
-  is(updateSelected.disabled, false, "Update Selected button should be enabled by default");
-
-  is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1");
-  is(item2._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon2");
-  
-  info("Unchecking Include Update checkbox for addon1");
-  EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow);
-  is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1");
-  is(updateSelected.disabled, false, "Update Selected button should still be enabled");
-
-  info("Unchecking Include Update checkbox for addon2");
-  EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow);
-  is(item2._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon2");
-  is(updateSelected.disabled, true, "Update Selected button should now be disabled");
-
-  info("Checking Include Update checkbox for addon2");
-  EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow);
-  is(item2._includeUpdate.checked, true, "Include Update checkbox should now be be checked for addon2");
-  is(updateSelected.disabled, false, "Update Selected button should now be enabled");
-
-  var listener = {
-    onInstallEnded: function() {
-      gProvider.installs[1].removeTestListener(listener);
-
-      is(gProvider.installs[0].state, AddonManager.STATE_AVAILABLE, "addon1 should not have been upgraded");
-      is(gProvider.installs[1].state, AddonManager.STATE_INSTALLED, "addon2 should have been upgraded");
-    }
-  }
-  gProvider.installs[1].addTestListener(listener);
-  info("Clicking Update Selected button");
-  EventUtils.synthesizeMouse(updateSelected, 2, 2, { }, gManagerWindow);
-
-  wait_for_view_load(gManagerWindow, function() {
-    function wait_for_refresh() {
-      var item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
-      if (item.mManualUpdate) {
-        run_next_test();
-      } else {
-        info("Waiting for pane to refresh");
-        setTimeout(wait_for_refresh, 10);
-      }
-    }
-    info("Waiting for pane to refresh");
-    setTimeout(wait_for_refresh, 10);
-  }, true);
-});
-
-
-add_test(function() {
-  var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
-  is(updateSelected.disabled, false, "Update Selected button should now be enabled");
-
-  var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
-  isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list");
-  is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1");
-
-  info("Unchecking Include Update checkbox for addon1");
-  EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow);
-  is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1");
-  is(updateSelected.disabled, true, "Update Selected button should now be disabled");
-
-  run_next_test();
-});
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Bug 587970 - Provide ability "Update all now" within 'Available Updates' screen
+
+var gManagerWindow;
+var gProvider;
+
+function test() {
+  waitForExplicitFinish();
+  
+  gProvider = new MockProvider();
+
+  gProvider.createAddons([{
+    id: "addon1@tests.mozilla.org",
+    name: "addon 1",
+    version: "1.0",
+    applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE
+  }, {
+    id: "addon2@tests.mozilla.org",
+    name: "addon 2",
+    version: "2.0",
+    applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE
+  }]);
+  
+
+  open_manager("addons://updates/available", function(aWindow) {
+    gManagerWindow = aWindow;
+    run_next_test();
+  });
+}
+
+
+function end_test() {
+  close_manager(gManagerWindow, finish);
+}
+
+
+add_test(function() {
+  var list = gManagerWindow.document.getElementById("updates-list");
+  is(list.childNodes.length, 0, "Available updates list should be empty");
+
+  var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg");
+  is_element_visible(emptyNotice, "Empty notice should be visible");
+  
+  var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
+  is_element_hidden(updateSelected, "Update Selected button should be hidden");
+
+  info("Adding updates");
+  gProvider.createInstalls([{
+    name: "addon 1",
+    version: "1.1",
+    existingAddon: gProvider.addons[0]
+  }, {
+    name: "addon 2",
+    version: "2.1",
+    existingAddon: gProvider.addons[1]
+  }]);
+
+  function wait_for_refresh() {
+    if (list.childNodes.length == 2 &&
+        list.childNodes[0].mManualUpdate &&
+        list.childNodes[1].mManualUpdate) {
+      run_next_test();
+    } else {
+      info("Waiting for pane to refresh");
+      setTimeout(wait_for_refresh, 10);
+    }
+  }
+  info("Waiting for pane to refresh");
+  setTimeout(wait_for_refresh, 10);
+});
+
+
+add_test(function() {
+  var list = gManagerWindow.document.getElementById("updates-list");
+  is(list.childNodes.length, 2, "Available updates list should have 2 items");
+  
+  var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
+  isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list");
+  var item2 = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org");
+  isnot(item2, null, "Item for addon2@tests.mozilla.org should be in list");
+
+  var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg");
+  is_element_hidden(emptyNotice, "Empty notice should be hidden");
+
+  var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
+  is_element_visible(updateSelected, "Update Selected button should be visible");
+  is(updateSelected.disabled, false, "Update Selected button should be enabled by default");
+
+  is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1");
+  is(item2._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon2");
+  
+  info("Unchecking Include Update checkbox for addon1");
+  EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow);
+  is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1");
+  is(updateSelected.disabled, false, "Update Selected button should still be enabled");
+
+  info("Unchecking Include Update checkbox for addon2");
+  EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow);
+  is(item2._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon2");
+  is(updateSelected.disabled, true, "Update Selected button should now be disabled");
+
+  info("Checking Include Update checkbox for addon2");
+  EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow);
+  is(item2._includeUpdate.checked, true, "Include Update checkbox should now be be checked for addon2");
+  is(updateSelected.disabled, false, "Update Selected button should now be enabled");
+
+  var listener = {
+    onInstallEnded: function() {
+      gProvider.installs[1].removeTestListener(listener);
+
+      is(gProvider.installs[0].state, AddonManager.STATE_AVAILABLE, "addon1 should not have been upgraded");
+      is(gProvider.installs[1].state, AddonManager.STATE_INSTALLED, "addon2 should have been upgraded");
+    }
+  }
+  gProvider.installs[1].addTestListener(listener);
+  info("Clicking Update Selected button");
+  EventUtils.synthesizeMouse(updateSelected, 2, 2, { }, gManagerWindow);
+
+  wait_for_view_load(gManagerWindow, function() {
+    function wait_for_refresh() {
+      var item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
+      if (item.mManualUpdate) {
+        run_next_test();
+      } else {
+        info("Waiting for pane to refresh");
+        setTimeout(wait_for_refresh, 10);
+      }
+    }
+    info("Waiting for pane to refresh");
+    setTimeout(wait_for_refresh, 10);
+  }, true);
+});
+
+
+add_test(function() {
+  var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
+  is(updateSelected.disabled, false, "Update Selected button should now be enabled");
+
+  var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
+  isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list");
+  is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1");
+
+  info("Unchecking Include Update checkbox for addon1");
+  EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow);
+  is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1");
+  is(updateSelected.disabled, true, "Update Selected button should now be disabled");
+
+  run_next_test();
+});
--- a/toolkit/mozapps/extensions/test/browser/browser_bug591465.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug591465.js
@@ -1,351 +1,351 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// Bug 591465 - Context menu of add-ons miss context related state change entries
-
-const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults";
-const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
-const SEARCH_URL = TESTROOT + "browser_bug591465.xml";
-const SEARCH_QUERY = "SEARCH";
-
-var gManagerWindow;
-var gProvider;
-var gContextMenu;
-
-
-function test() {
-  waitForExplicitFinish();
-  
-  gProvider = new MockProvider();
-
-  gProvider.createAddons([{
-    id: "addon1@tests.mozilla.org",
-    name: "addon 1",
-    version: "1.0"
-  }, {
-    id: "addon2@tests.mozilla.org",
-    name: "addon 2",
-    version: "1.0",
-    _userDisabled: true
-  }, {
-    id: "theme1@tests.mozilla.org",
-    name: "theme 1",
-    version: "1.0",
-    type: "theme"
-  }, {
-    id: "theme2@tests.mozilla.org",
-    name: "theme 2",
-    version: "1.0",
-    type: "theme",
-    _userDisabled: true
-   }, {
-    id: "theme3@tests.mozilla.org",
-    name: "theme 3",
-    version: "1.0",
-    type: "theme",
-    permissions: 0
-  }]);
-
-  open_manager("addons://list/extension", function(aWindow) {
-    gManagerWindow = aWindow;
-    gContextMenu = aWindow.document.getElementById("addonitem-popup");
-    run_next_test();
-  });
-}
-
-
-function end_test() {
-  Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS);
-  close_manager(gManagerWindow, finish);
-}
-
-
-function check_contextmenu(aIsTheme, aIsEnabled, aIsRemote, aIsDetails, aIsSingleItemCase) {
-  if (aIsTheme || aIsEnabled || aIsRemote)
-    is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableItem"),
-                       "'Enable' should be hidden");
-  else
-    is_element_visible(gManagerWindow.document.getElementById("menuitem_enableItem"),
-                       "'Enable' should be visible");
-  
-  if (aIsTheme || !aIsEnabled || aIsRemote)
-    is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableItem"),
-                       "'Disable' should be hidden");
-  else
-    is_element_visible(gManagerWindow.document.getElementById("menuitem_disableItem"),
-                       "'Disable' should be visible");
-
-  if (!aIsTheme || aIsEnabled || aIsRemote || aIsSingleItemCase)
-    is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableTheme"),
-                       "'Wear Theme' should be hidden");
-  else
-    is_element_visible(gManagerWindow.document.getElementById("menuitem_enableTheme"),
-                       "'Wear Theme' should be visible");
-  
-  if (!aIsTheme || !aIsEnabled || aIsRemote || aIsSingleItemCase)
-    is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableTheme"),
-                       "'Stop Wearing Theme' should be hidden");
-  else
-    is_element_visible(gManagerWindow.document.getElementById("menuitem_disableTheme"),
-                       "'Stop Wearing Theme' should be visible");
-
-  if (aIsRemote)
-    is_element_visible(gManagerWindow.document.getElementById("menuitem_installItem"),
-                       "'Install' should be visible");
-  else
-    is_element_hidden(gManagerWindow.document.getElementById("menuitem_installItem"),
-                       "'Install' should be hidden");
-                       
-  if (aIsDetails)
-    is_element_hidden(gManagerWindow.document.getElementById("menuitem_showDetails"), 
-                       "'Show More Information' should be hidden in details view");
-  else
-    is_element_visible(gManagerWindow.document.getElementById("menuitem_showDetails"), 
-                       "'Show More Information' should be visible in list view");
-                       
-  if (aIsSingleItemCase)
-    is_element_hidden(gManagerWindow.document.getElementById("addonitem-menuseparator"), 
-                       "Menu separator should be hidden with only one menu item");
-  else
-    is_element_visible(gManagerWindow.document.getElementById("addonitem-menuseparator"), 
-                       "Menu separator should be visible with multiple menu items");
-
-}
-
-
-add_test(function() {
-  var el = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
-  isnot(el, null, "Should have found addon element");
-
-  gContextMenu.addEventListener("popupshown", function() {
-    gContextMenu.removeEventListener("popupshown", arguments.callee, false);
-
-    check_contextmenu(false, true, false, false, false);
-
-    gContextMenu.hidePopup();
-    run_next_test();
-  }, false);
-
-  info("Opening context menu on enabled extension item");
-  EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
-  EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
-});
-
-
-add_test(function() {
-  var el = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org");
-
-  gContextMenu.addEventListener("popupshown", function() {
-    gContextMenu.removeEventListener("popupshown", arguments.callee, false);
-
-    check_contextmenu(false, false, false, false, false);
-
-    gContextMenu.hidePopup();
-    run_next_test();
-  }, false);
-
-  info("Opening context menu on disabled extension item");
-  EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
-  EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
-});
-
-
-add_test(function() {
-  gManagerWindow.loadView("addons://list/theme");
-  wait_for_view_load(gManagerWindow, function() {
-    var el = get_addon_element(gManagerWindow, "theme1@tests.mozilla.org");
-  
-    gContextMenu.addEventListener("popupshown", function() {
-      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
-  
-    check_contextmenu(true, true, false, false, false);
-  
-      gContextMenu.hidePopup();
-      run_next_test();
-    }, false);
-  
-    info("Opening context menu on enabled theme item");
-    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
-    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
-  });
-});
-
-
-add_test(function() {
-  var el = get_addon_element(gManagerWindow, "theme2@tests.mozilla.org");
-
-  gContextMenu.addEventListener("popupshown", function() {
-    gContextMenu.removeEventListener("popupshown", arguments.callee, false);
-
-    check_contextmenu(true, false, false, false, false);
-
-    gContextMenu.hidePopup();
-    run_next_test();
-  }, false);
-
-  info("Opening context menu on disabled theme item");
-  EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
-  EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
-});
-
-
-add_test(function() {
-  gManagerWindow.loadView("addons://detail/addon1@tests.mozilla.org");
-  wait_for_view_load(gManagerWindow, function() {
-    
-    gContextMenu.addEventListener("popupshown", function() {
-      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
-  
-      check_contextmenu(false, true, false, true, false);
-  
-      gContextMenu.hidePopup();
-      run_next_test();
-    }, false);
-
-    info("Opening context menu on enabled extension, in detail view");
-    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
-    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
-    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
-  });
-});
-
-
-add_test(function() {
-  gManagerWindow.loadView("addons://detail/addon2@tests.mozilla.org");
-  wait_for_view_load(gManagerWindow, function() {
-    
-    gContextMenu.addEventListener("popupshown", function() {
-      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
-  
-      check_contextmenu(false, false, false, true, false);
-  
-      gContextMenu.hidePopup();
-      run_next_test();
-    }, false);
-
-    info("Opening context menu on disabled extension, in detail view");
-    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
-    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
-    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
-  });
-});
-
-
-add_test(function() {
-  gManagerWindow.loadView("addons://detail/theme1@tests.mozilla.org");
-  wait_for_view_load(gManagerWindow, function() {
-    
-    gContextMenu.addEventListener("popupshown", function() {
-      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
-  
-      check_contextmenu(true, true, false, true, false);
-  
-      gContextMenu.hidePopup();
-      run_next_test();
-    }, false);
-
-    info("Opening context menu on enabled theme, in detail view");
-    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
-    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
-    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
-  });
-});
-
-
-add_test(function() {
-  gManagerWindow.loadView("addons://detail/theme2@tests.mozilla.org");
-  wait_for_view_load(gManagerWindow, function() {
-    
-    gContextMenu.addEventListener("popupshown", function() {
-      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
-  
-      check_contextmenu(true, false, false, true, false);
-  
-      gContextMenu.hidePopup();
-      run_next_test();
-    }, false);
-
-    info("Opening context menu on disabled theme, in detail view");
-    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
-    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
-    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
-  });
-});
-
-add_test(function() {
-  gManagerWindow.loadView("addons://detail/theme3@tests.mozilla.org");
-  wait_for_view_load(gManagerWindow, function() {
-    
-    gContextMenu.addEventListener("popupshown", function() {
-      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
-  
-      check_contextmenu(true, true, false, true, true);
-  
-      gContextMenu.hidePopup();
-      run_next_test();
-    }, false);
-
-    info("Opening context menu with single menu item on enabled theme, in detail view");
-    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
-    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
-    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
-  });
-});
-
-add_test(function() {
-  info("Searching for remote addons");
-
-  Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL);
-  Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
-
-  var searchBox = gManagerWindow.document.getElementById("header-search");
-  searchBox.value = SEARCH_QUERY;
-
-  EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow);
-  EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
-
-  wait_for_view_load(gManagerWindow, function() {
-    var filter = gManagerWindow.document.getElementById("search-filter-remote");
-    EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow);
-    executeSoon(function() {
-      
-      var el = get_addon_element(gManagerWindow, "remote1@tests.mozilla.org");
-    
-      gContextMenu.addEventListener("popupshown", function() {
-        gContextMenu.removeEventListener("popupshown", arguments.callee, false);
-    
-        check_contextmenu(false, false, true, false, false);
-    
-        gContextMenu.hidePopup();
-        run_next_test();
-      }, false);
-    
-      info("Opening context menu on remote extension item");
-      EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
-      EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
-      
-    });
-  });
-});
-
-
-add_test(function() {
-  gManagerWindow.loadView("addons://detail/remote1@tests.mozilla.org");
-  wait_for_view_load(gManagerWindow, function() {
-    
-    gContextMenu.addEventListener("popupshown", function() {
-      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
-  
-      check_contextmenu(false, false, true, true, false);
-  
-      gContextMenu.hidePopup();
-      run_next_test();
-    }, false);
-
-    info("Opening context menu on remote extension, in detail view");
-    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
-    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
-    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
-  });
-});
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Bug 591465 - Context menu of add-ons miss context related state change entries
+
+const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults";
+const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
+const SEARCH_URL = TESTROOT + "browser_bug591465.xml";
+const SEARCH_QUERY = "SEARCH";
+
+var gManagerWindow;
+var gProvider;
+var gContextMenu;
+
+
+function test() {
+  waitForExplicitFinish();
+  
+  gProvider = new MockProvider();
+
+  gProvider.createAddons([{
+    id: "addon1@tests.mozilla.org",
+    name: "addon 1",
+    version: "1.0"
+  }, {
+    id: "addon2@tests.mozilla.org",
+    name: "addon 2",
+    version: "1.0",
+    _userDisabled: true
+  }, {
+    id: "theme1@tests.mozilla.org",
+    name: "theme 1",
+    version: "1.0",
+    type: "theme"
+  }, {
+    id: "theme2@tests.mozilla.org",
+    name: "theme 2",
+    version: "1.0",
+    type: "theme",
+    _userDisabled: true
+   }, {
+    id: "theme3@tests.mozilla.org",
+    name: "theme 3",
+    version: "1.0",
+    type: "theme",
+    permissions: 0
+  }]);
+
+  open_manager("addons://list/extension", function(aWindow) {
+    gManagerWindow = aWindow;
+    gContextMenu = aWindow.document.getElementById("addonitem-popup");
+    run_next_test();
+  });
+}
+
+
+function end_test() {
+  Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS);
+  close_manager(gManagerWindow, finish);
+}
+
+
+function check_contextmenu(aIsTheme, aIsEnabled, aIsRemote, aIsDetails, aIsSingleItemCase) {
+  if (aIsTheme || aIsEnabled || aIsRemote)
+    is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableItem"),
+                       "'Enable' should be hidden");
+  else
+    is_element_visible(gManagerWindow.document.getElementById("menuitem_enableItem"),
+                       "'Enable' should be visible");
+  
+  if (aIsTheme || !aIsEnabled || aIsRemote)
+    is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableItem"),
+                       "'Disable' should be hidden");
+  else
+    is_element_visible(gManagerWindow.document.getElementById("menuitem_disableItem"),
+                       "'Disable' should be visible");
+
+  if (!aIsTheme || aIsEnabled || aIsRemote || aIsSingleItemCase)
+    is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableTheme"),
+                       "'Wear Theme' should be hidden");
+  else
+    is_element_visible(gManagerWindow.document.getElementById("menuitem_enableTheme"),
+                       "'Wear Theme' should be visible");
+  
+  if (!aIsTheme || !aIsEnabled || aIsRemote || aIsSingleItemCase)
+    is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableTheme"),
+                       "'Stop Wearing Theme' should be hidden");
+  else
+    is_element_visible(gManagerWindow.document.getElementById("menuitem_disableTheme"),
+                       "'Stop Wearing Theme' should be visible");
+
+  if (aIsRemote)
+    is_element_visible(gManagerWindow.document.getElementById("menuitem_installItem"),
+                       "'Install' should be visible");
+  else
+    is_element_hidden(gManagerWindow.document.getElementById("menuitem_installItem"),
+                       "'Install' should be hidden");
+                       
+  if (aIsDetails)
+    is_element_hidden(gManagerWindow.document.getElementById("menuitem_showDetails"), 
+                       "'Show More Information' should be hidden in details view");
+  else
+    is_element_visible(gManagerWindow.document.getElementById("menuitem_showDetails"), 
+                       "'Show More Information' should be visible in list view");
+                       
+  if (aIsSingleItemCase)
+    is_element_hidden(gManagerWindow.document.getElementById("addonitem-menuseparator"), 
+                       "Menu separator should be hidden with only one menu item");
+  else
+    is_element_visible(gManagerWindow.document.getElementById("addonitem-menuseparator"), 
+                       "Menu separator should be visible with multiple menu items");
+
+}
+
+
+add_test(function() {
+  var el = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
+  isnot(el, null, "Should have found addon element");
+
+  gContextMenu.addEventListener("popupshown", function() {
+    gContextMenu.removeEventListener("popupshown", arguments.callee, false);
+
+    check_contextmenu(false, true, false, false, false);
+
+    gContextMenu.hidePopup();
+    run_next_test();
+  }, false);
+
+  info("Opening context menu on enabled extension item");
+  EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
+  EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
+});
+
+
+add_test(function() {
+  var el = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org");
+
+  gContextMenu.addEventListener("popupshown", function() {
+    gContextMenu.removeEventListener("popupshown", arguments.callee, false);
+
+    check_contextmenu(false, false, false, false, false);
+
+    gContextMenu.hidePopup();
+    run_next_test();
+  }, false);
+
+  info("Opening context menu on disabled extension item");
+  EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
+  EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
+});
+
+
+add_test(function() {
+  gManagerWindow.loadView("addons://list/theme");
+  wait_for_view_load(gManagerWindow, function() {
+    var el = get_addon_element(gManagerWindow, "theme1@tests.mozilla.org");
+  
+    gContextMenu.addEventListener("popupshown", function() {
+      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
+  
+    check_contextmenu(true, true, false, false, false);
+  
+      gContextMenu.hidePopup();
+      run_next_test();
+    }, false);
+  
+    info("Opening context menu on enabled theme item");
+    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
+    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
+  });
+});
+
+
+add_test(function() {
+  var el = get_addon_element(gManagerWindow, "theme2@tests.mozilla.org");
+
+  gContextMenu.addEventListener("popupshown", function() {
+    gContextMenu.removeEventListener("popupshown", arguments.callee, false);
+
+    check_contextmenu(true, false, false, false, false);
+
+    gContextMenu.hidePopup();
+    run_next_test();
+  }, false);
+
+  info("Opening context menu on disabled theme item");
+  EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
+  EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
+});
+
+
+add_test(function() {
+  gManagerWindow.loadView("addons://detail/addon1@tests.mozilla.org");
+  wait_for_view_load(gManagerWindow, function() {
+    
+    gContextMenu.addEventListener("popupshown", function() {
+      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
+  
+      check_contextmenu(false, true, false, true, false);
+  
+      gContextMenu.hidePopup();
+      run_next_test();
+    }, false);
+
+    info("Opening context menu on enabled extension, in detail view");
+    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
+    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
+    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
+  });
+});
+
+
+add_test(function() {
+  gManagerWindow.loadView("addons://detail/addon2@tests.mozilla.org");
+  wait_for_view_load(gManagerWindow, function() {
+    
+    gContextMenu.addEventListener("popupshown", function() {
+      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
+  
+      check_contextmenu(false, false, false, true, false);
+  
+      gContextMenu.hidePopup();
+      run_next_test();
+    }, false);
+
+    info("Opening context menu on disabled extension, in detail view");
+    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
+    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
+    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
+  });
+});
+
+
+add_test(function() {
+  gManagerWindow.loadView("addons://detail/theme1@tests.mozilla.org");
+  wait_for_view_load(gManagerWindow, function() {
+    
+    gContextMenu.addEventListener("popupshown", function() {
+      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
+  
+      check_contextmenu(true, true, false, true, false);
+  
+      gContextMenu.hidePopup();
+      run_next_test();
+    }, false);
+
+    info("Opening context menu on enabled theme, in detail view");
+    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
+    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
+    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
+  });
+});
+
+
+add_test(function() {
+  gManagerWindow.loadView("addons://detail/theme2@tests.mozilla.org");
+  wait_for_view_load(gManagerWindow, function() {
+    
+    gContextMenu.addEventListener("popupshown", function() {
+      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
+  
+      check_contextmenu(true, false, false, true, false);
+  
+      gContextMenu.hidePopup();
+      run_next_test();
+    }, false);
+
+    info("Opening context menu on disabled theme, in detail view");
+    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
+    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
+    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
+  });
+});
+
+add_test(function() {
+  gManagerWindow.loadView("addons://detail/theme3@tests.mozilla.org");
+  wait_for_view_load(gManagerWindow, function() {
+    
+    gContextMenu.addEventListener("popupshown", function() {
+      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
+  
+      check_contextmenu(true, true, false, true, true);
+  
+      gContextMenu.hidePopup();
+      run_next_test();
+    }, false);
+
+    info("Opening context menu with single menu item on enabled theme, in detail view");
+    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
+    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
+    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
+  });
+});
+
+add_test(function() {
+  info("Searching for remote addons");
+
+  Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL);
+  Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
+
+  var searchBox = gManagerWindow.document.getElementById("header-search");
+  searchBox.value = SEARCH_QUERY;
+
+  EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow);
+  EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
+
+  wait_for_view_load(gManagerWindow, function() {
+    var filter = gManagerWindow.document.getElementById("search-filter-remote");
+    EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow);
+    executeSoon(function() {
+      
+      var el = get_addon_element(gManagerWindow, "remote1@tests.mozilla.org");
+    
+      gContextMenu.addEventListener("popupshown", function() {
+        gContextMenu.removeEventListener("popupshown", arguments.callee, false);
+    
+        check_contextmenu(false, false, true, false, false);
+    
+        gContextMenu.hidePopup();
+        run_next_test();
+      }, false);
+    
+      info("Opening context menu on remote extension item");
+      EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
+      EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
+      
+    });
+  });
+});
+
+
+add_test(function() {
+  gManagerWindow.loadView("addons://detail/remote1@tests.mozilla.org");
+  wait_for_view_load(gManagerWindow, function() {
+    
+    gContextMenu.addEventListener("popupshown", function() {
+      gContextMenu.removeEventListener("popupshown", arguments.callee, false);
+  
+      check_contextmenu(false, false, true, true, false);
+  
+      gContextMenu.hidePopup();
+      run_next_test();
+    }, false);
+
+    info("Opening context menu on remote extension, in detail view");
+    var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
+    EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
+    EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
+  });
+});
--- a/toolkit/mozapps/extensions/test/browser/browser_details.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_details.js
@@ -5,16 +5,17 @@
 // Tests various aspects of the details view
 
 const PREF_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault"
 const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
 const SEARCH_URL = TESTROOT + "browser_details.xml";
 
 var gManagerWindow;
 var gCategoryUtilities;
+var gProvider;
 
 var gApp = document.getElementById("bundle_brand").getString("brandShortName");
 var gVersion = Services.appinfo.version;
 var gBlocklistURL = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL");
 var gPluginURL = Services.urlFormatter.formatURLPref("plugins.update.url");
 var gDate = new Date(2010, 7, 1);
 
 function open_details(aId, aType, aCallback) {
--- a/toolkit/mozapps/extensions/test/browser/browser_globalwarnings.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_globalwarnings.js
@@ -1,65 +1,65 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// Bug 566194 - safe mode / security & compatibility check status are not exposed in new addon manager UI
-
-function test() {
-  waitForExplicitFinish();
-  run_next_test();
-}
-
-function end_test() {
-  finish();
-}
-
-add_test(function() {
-  info("Testing compatibility checking warning");
-
-  var version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
-  var pref = "extensions.checkCompatibility." + version;
-  info("Setting " + pref + " pref to false")
-  Services.prefs.setBoolPref(pref, false);
-
-  open_manager("addons://list/extension", function(aWindow) {
-    var label = aWindow.document.querySelector("#list-view label.global-warning-checkcompatibility");
-    is_element_visible(label, "Check Compatibility warning label should be visible");
-    var button = aWindow.document.querySelector("#list-view button.global-warning-checkcompatibility");
-    is_element_visible(button, "Check Compatibility warning button should be visible");
-
-    info("Clicking 'Enable' button");
-    EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow);
-    is(Services.prefs.prefHasUserValue(pref), false, "Check Compatability pref should be cleared");
-    is_element_hidden(label, "Check Compatibility warning label should be hidden");
-    is_element_hidden(button, "Check Compatibility warning button should be hidden");
-
-    close_manager(aWindow, function() {
-      run_next_test();
-    });
-  });
-});
-
-add_test(function() {
-  info("Testing update security checking warning");
-
-  var pref = "extensions.checkUpdateSecurity";
-  info("Setting " + pref + " pref to false")
-  Services.prefs.setBoolPref(pref, false);
-
-  open_manager(null, function(aWindow) {
-    var label = aWindow.document.querySelector("#list-view label.global-warning-updatesecurity");
-    is_element_visible(label, "Check Update Security warning label should be visible");
-    var button = aWindow.document.querySelector("#list-view button.global-warning-updatesecurity");
-    is_element_visible(button, "Check Update Security warning button should be visible");
-
-    info("Clicking 'Enable' button");
-    EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow);
-    is(Services.prefs.prefHasUserValue(pref), false, "Check Update Security pref should be cleared");
-    is_element_hidden(label, "Check Update Security warning label should be hidden");
-    is_element_hidden(button, "Check Update Security warning button should be hidden");
-
-    close_manager(aWindow, function() {
-      run_next_test();
-    });
-  });
-});
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Bug 566194 - safe mode / security & compatibility check status are not exposed in new addon manager UI
+
+function test() {
+  waitForExplicitFinish();
+  run_next_test();
+}
+
+function end_test() {
+  finish();
+}
+
+add_test(function() {
+  info("Testing compatibility checking warning");
+
+  var version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
+  var pref = "extensions.checkCompatibility." + version;
+  info("Setting " + pref + " pref to false")
+  Services.prefs.setBoolPref(pref, false);
+
+  open_manager("addons://list/extension", function(aWindow) {
+    var label = aWindow.document.querySelector("#list-view label.global-warning-checkcompatibility");
+    is_element_visible(label, "Check Compatibility warning label should be visible");
+    var button = aWindow.document.querySelector("#list-view button.global-warning-checkcompatibility");
+    is_element_visible(button, "Check Compatibility warning button should be visible");
+
+    info("Clicking 'Enable' button");
+    EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow);
+    is(Services.prefs.prefHasUserValue(pref), false, "Check Compatability pref should be cleared");
+    is_element_hidden(label, "Check Compatibility warning label should be hidden");
+    is_element_hidden(button, "Check Compatibility warning button should be hidden");
+
+    close_manager(aWindow, function() {
+      run_next_test();
+    });
+  });
+});
+
+add_test(function() {
+  info("Testing update security checking warning");
+
+  var pref = "extensions.checkUpdateSecurity";
+  info("Setting " + pref + " pref to false")
+  Services.prefs.setBoolPref(pref, false);
+
+  open_manager(null, function(aWindow) {
+    var label = aWindow.document.querySelector("#list-view label.global-warning-updatesecurity");
+    is_element_visible(label, "Check Update Security warning label should be visible");
+    var button = aWindow.document.querySelector("#list-view button.global-warning-updatesecurity");
+    is_element_visible(button, "Check Update Security warning button should be visible");
+
+    info("Clicking 'Enable' button");
+    EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow);
+    is(Services.prefs.prefHasUserValue(pref), false, "Check Update Security pref should be cleared");
+    is_element_hidden(label, "Check Update Security warning label should be hidden");
+    is_element_hidden(button, "Check Update Security warning button should be hidden");
+
+    close_manager(aWindow, function() {
+      run_next_test();
+    });
+  });
+});
--- a/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js
@@ -1,188 +1,188 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// Tests manual updates, including the Available Updates pane
-
-var gProvider;
-var gManagerWindow;
-var gCategoryUtilities;
-var gAvailableCategory;
-
-function test() {
-  waitForExplicitFinish();
-
-  gProvider = new MockProvider();
-
-  gProvider.createAddons([{
-    id: "addon1@tests.mozilla.org",
-    name: "auto updating addon",
-    version: "1.0",
-    applyBackgroundUpdates: AddonManager.AUTOUPDATE_ENABLE
-  }]);
-
-  open_manager("addons://list/extension", function(aWindow) {
-    gManagerWindow = aWindow;
-    gCategoryUtilities = new CategoryUtilities(gManagerWindow);
-    run_next_test();
-  });
-}
-
-function end_test() {
-  close_manager(gManagerWindow, function() {
-    finish();
-  });
-}
-
-
-add_test(function() {
-  gAvailableCategory = gManagerWindow.gCategories.get("addons://updates/available");
-  is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should initially be hidden");
-  
-  gProvider.createAddons([{
-    id: "addon2@tests.mozilla.org",
-    name: "manually updating addon",
-    version: "1.0",
-    isCompatible: false,
-    blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED,
-    applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE
-  }]);
-  
-  is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should now be visible");
-  
-  gAvailableCategory.addEventListener("CategoryVisible", function() {
-    gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false);
-    is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should not be visible");
-    gAvailableCategory.addEventListener("CategoryVisible", function() {
-      gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false);
-      is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should be visible");
-      run_next_test();
-    }, false);
-    gProvider.addons[1].applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE;
-  }, false);
-  gProvider.addons[1].applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE;
-});
-
-
-add_test(function() {
-  gAvailableCategory.addEventListener("CategoryBadgeUpdated", function() {
-    gAvailableCategory.removeEventListener("CategoryBadgeUpdated", arguments.callee, false);
-    is(gAvailableCategory.badgeCount, 1, "Badge for Available Updates should now be 1");
-    run_next_test();
-  }, false);
-
-  gCategoryUtilities.openType("extension", function() {
-    gProvider.createInstalls([{
-      name: "manually updating addon (new and improved!)",
-      existingAddon: gProvider.addons[1],
-      version: "1.1",
-      releaseNotesURI: Services.io.newURI(TESTROOT + "thereIsNoFileHere.xhtml", null, null)
-    }]);
-
-    var item = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org");
-    is(item._version.value, "1.0", "Should still show the old version in the normal list");
-  });
-});
-
-
-add_test(function() {
-  wait_for_view_load(gManagerWindow, function() {
-    is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/available", "Available Updates category should now be selected");
-    is(gManagerWindow.gViewController.currentViewId, "addons://updates/available", "Available Updates view should be the current view");
-    run_next_test();
-  }, true);
-  EventUtils.synthesizeMouseAtCenter(gAvailableCategory, { }, gManagerWindow);
-});
-
-
-add_test(function() {
-  var list = gManagerWindow.document.getElementById("updates-list");
-  is(list.itemCount, 1, "Should be 1 available update listed");
-  var item = list.firstChild;
-  is(item.mAddon.id, "addon2@tests.mozilla.org", "Update item should be for the manually updating addon");
-  
-  // for manual update items, update-related properties are updated asynchronously,
-  // so we poll for one of the expected changes to know when its done
-  function waitForAsyncInit() {
-    if (item._version.value == "1.1") {
-      run_next_test();
-      return;