Merge from mozilla-central.
authorBenjamin Smedberg <benjamin@smedbergs.us>
Fri, 06 Nov 2009 09:54:28 -0500
changeset 36052 e8d11cef633f1dceab50393611d06df4cbd7166e
parent 36051 4d9d74b3da6a08d05654472c1c1276bffff4c579 (current diff)
parent 34630 f1c0c5a52b298a4d75570dbd5b5e227736e4f7ae (diff)
child 36053 c6c2026ba4cf6f2856fbe2ec570c8fd2679014d4
push id10694
push userbsmedberg@mozilla.com
push dateMon, 14 Dec 2009 15:23:10 +0000
treeherdermozilla-central@683dfdc4adf0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.3a1pre
Merge from mozilla-central.
browser/app/profile/firefox.js
browser/installer/package-manifest.in
build/automation.py.in
configure.in
content/base/src/Makefile.in
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.h
content/canvas/src/nsCanvasRenderingContext2D.cpp
docshell/base/nsDocShell.cpp
js/src/tests/template.js
layout/reftests/css-gradients/nostops-ref.html
layout/reftests/css-gradients/onestop-ref.html
layout/reftests/css-gradients/radial-ref.html
layout/reftests/css-gradients/radial.html
layout/reftests/css-gradients/twostops-ref.html
layout/reftests/css-gradients/twostops.html
modules/plugin/base/src/nsNPAPIPlugin.cpp
modules/plugin/base/src/nsPluginHost.cpp
modules/plugin/test/mochitest/Makefile.in
modules/plugin/test/testplugin/nptest.cpp
modules/plugin/test/testplugin/nptest_gtk2.cpp
modules/plugin/test/testplugin/nptest_windows.cpp
netwerk/protocol/http/src/nsHttpHandler.cpp
testing/testsuite-targets.mk
toolkit/library/libxul-config.mk
toolkit/profile/skin/Makefile.in
toolkit/profile/skin/jar.mn
toolkit/profile/skin/profileSelection.css
toolkit/profile/skin/profileicon.png
toolkit/themes/gnomestripe/global/icons/Search-glass.png
toolkit/toolkit-makefiles.sh
toolkit/xre/nsAppRunner.cpp
widget/src/gtk2/nsWindow.cpp
xpcom/build/Makefile.in
--- a/Makefile.in
+++ b/Makefile.in
@@ -192,22 +192,22 @@ ifdef MOZ_CRASHREPORTER
 	  $(MAKE_SYM_STORE_ARGS)                                          \
 	  $(foreach dir,$(SYM_STORE_SOURCE_DIRS),-s $(dir))               \
 	  $(DUMP_SYMS_BIN)                                                \
 	  $(DIST)/crashreporter-symbols                                   \
 	  $(MAKE_SYM_STORE_PATH) >                                        \
 	  $(DIST)/crashreporter-symbols/$(SYMBOL_INDEX_NAME)
 	echo packing symbols
 	cd $(DIST)/crashreporter-symbols && \
-          zip -r9D ../"$(SYMBOL_ARCHIVE_BASENAME).zip" .
+          zip -r9D "../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip" .
 endif # MOZ_CRASHREPORTER
 
 uploadsymbols:
 ifdef MOZ_CRASHREPORTER
-	$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh "$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip"
+	$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh "$(DIST)/$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip"
 endif
 
 ifeq ($(OS_ARCH),WINNT)
 signnss:
 ifdef MOZILLA_OFFICIAL
 	echo signing NSS libs
 	cd $(DIST)/bin; ./shlibsign.exe -v -i softokn3.dll
 	cd $(DIST)/bin; ./shlibsign.exe -v -i freebl3.dll
--- a/accessible/public/nsIAccessibilityService.idl
+++ b/accessible/public/nsIAccessibilityService.idl
@@ -41,17 +41,17 @@
 
 interface nsIAccessibleEventListener;
 interface nsIDocument;
 interface nsIFrame;
 interface nsObjectFrame;
 interface nsIContent;
 interface nsITimer;
 
-[uuid(6a58f7e8-587c-40dd-b684-dc3e54f1342a)]
+[uuid(29384ba1-f9ce-425d-afb5-54e2ee949d87)]
 interface nsIAccessibilityService : nsIAccessibleRetrieval
 {
   nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode);
   nsIAccessible createRootAccessible(in nsIPresShell aShell, in nsIDocument aDocument);
 
   nsIAccessible createHTML4ButtonAccessible(in nsIFrame aFrame);
   nsIAccessible createHyperTextAccessible(in nsIFrame aFrame);
   nsIAccessible createHTMLBRAccessible(in nsIFrame aFrame);
@@ -110,16 +110,22 @@ interface nsIAccessibilityService : nsIA
    *  @param aClosure    The nsIWebProgress* for the load event
    *  @param aEventType  The type of load event, one of: nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START,
    *                                                     nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE or
    *                                                     nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED
    */
   void processDocLoadEvent(in nsITimer aTimer, in voidPtr aClosure, in PRUint32 aEventType);
 
   /**
+   * Notify accessibility that anchor jump has been accomplished to the given
+   * target. Used by layout.
+   */
+  void notifyOfAnchorJumpTo(in nsIContent aTarget);
+
+  /**
    * Fire accessible event of the given type for the given target.
    *
    * @param aEvent   [in] accessible event type
    * @param aTarget  [in] target of accessible event
    */
   void fireAccessibleEvent(in unsigned long aEvent, in nsIAccessible aTarget);
 };
 
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -122,18 +122,17 @@ nsAccessibilityService::nsAccessibilityS
     do_GetService("@mozilla.org/observer-service;1");
   if (!observerService)
     return;
 
   observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
   nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID));
   if (progress) {
     progress->AddProgressListener(static_cast<nsIWebProgressListener*>(this),
-                                  nsIWebProgress::NOTIFY_STATE_DOCUMENT |
-                                  nsIWebProgress::NOTIFY_LOCATION);
+                                  nsIWebProgress::NOTIFY_STATE_DOCUMENT);
   }
 
   // Initialize accessibility.
   nsAccessNodeWrap::InitAccessibility();
 }
 
 nsAccessibilityService::~nsAccessibilityService()
 {
@@ -261,16 +260,45 @@ NS_IMETHODIMP nsAccessibilityService::Pr
   NS_ENSURE_STATE(docAcc);
 
   docAcc->FireDocLoadEvents(aEventType);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsAccessibilityService::NotifyOfAnchorJumpTo(nsIContent *aTarget)
+{
+  nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(aTarget));
+
+  nsCOMPtr<nsIAccessible> targetAcc;
+  GetAccessibleFor(targetNode, getter_AddRefs(targetAcc));
+
+  // If the jump target is not accessible then fire an event for nearest
+  // accessible in parent chain.
+  if (!targetAcc) {
+    nsIDocument *document = aTarget->GetCurrentDoc();
+    nsCOMPtr<nsIDOMNode> documentNode(do_QueryInterface(document));
+    if (documentNode) {
+      nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
+        nsAccessNode::GetDocAccessibleFor(documentNode);
+      if (accessibleDoc)
+        accessibleDoc->GetAccessibleInParentChain(targetNode, PR_TRUE,
+                                                  getter_AddRefs(targetAcc));
+    }
+  }
+
+  if (targetAcc)
+    return nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_SCROLLING_START,
+                                    targetAcc);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsAccessibilityService::FireAccessibleEvent(PRUint32 aEvent,
                                             nsIAccessible *aTarget)
 {
   return nsAccUtils::FireAccEvent(aEvent, aTarget);
 }
 
 void nsAccessibilityService::StartLoadCallback(nsITimer *aTimer, void *aClosure)
 {
@@ -304,38 +332,17 @@ NS_IMETHODIMP nsAccessibilityService::On
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
 
 /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
 NS_IMETHODIMP nsAccessibilityService::OnLocationChange(nsIWebProgress *aWebProgress,
   nsIRequest *aRequest, nsIURI *location)
 {
-  // If the document is already loaded, this will just check to see
-  // if an anchor jump event needs to be fired.
-  // If there is no accessible for the document, we will ignore
-  // this and the anchor jump event will be fired via OnStateChange
-  // and nsIAccessibleStates::STATE_STOP
-  nsCOMPtr<nsIDOMWindow> domWindow;
-  aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
-  NS_ASSERTION(domWindow, "DOM Window for state change is null");
-  NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsIDOMDocument> domDoc;
-  domWindow->GetDocument(getter_AddRefs(domDoc));
-  nsCOMPtr<nsIDOMNode> domDocRootNode(do_QueryInterface(domDoc));
-  NS_ENSURE_TRUE(domDocRootNode, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
-    nsAccessNode::GetDocAccessibleFor(domDocRootNode);
-  nsRefPtr<nsDocAccessible> docAcc =
-    nsAccUtils::QueryAccessibleDocument(accessibleDoc);
-  if (docAcc)
-    docAcc->FireAnchorJumpEvent();
-
+  NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP nsAccessibilityService::OnStatusChange(nsIWebProgress *aWebProgress,
   nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -3112,30 +3112,28 @@ nsAccessible::GetNameInternal(nsAString&
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible private methods
 
 already_AddRefed<nsIAccessible>
-nsAccessible::GetFirstAvailableAccessible(nsIDOMNode *aStartNode, PRBool aRequireLeaf)
+nsAccessible::GetFirstAvailableAccessible(nsIDOMNode *aStartNode)
 {
   nsIAccessibilityService *accService = GetAccService();
   nsCOMPtr<nsIAccessible> accessible;
   nsCOMPtr<nsIDOMTreeWalker> walker; 
   nsCOMPtr<nsIDOMNode> currentNode(aStartNode);
 
   while (currentNode) {
     accService->GetAccessibleInWeakShell(currentNode, mWeakShell, getter_AddRefs(accessible)); // AddRef'd
-    if (accessible && (!aRequireLeaf || nsAccUtils::IsLeaf(accessible))) {
-      nsIAccessible *retAccessible = accessible;
-      NS_ADDREF(retAccessible);
-      return retAccessible;
-    }
+    if (accessible)
+      return accessible.forget();
+
     if (!walker) {
       // Instantiate walker lazily since we won't need it in 90% of the cases
       // where the first DOM node we're given provides an accessible
       nsCOMPtr<nsIDOMDocument> document;
       currentNode->GetOwnerDocument(getter_AddRefs(document));
       nsCOMPtr<nsIDOMDocumentTraversal> trav = do_QueryInterface(document);
       NS_ASSERTION(trav, "No DOM document traversal for document");
       NS_ENSURE_TRUE(trav, nsnull);
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -321,23 +321,25 @@ protected:
   
   // nsCOMPtr<>& is useful here, because getter_AddRefs() nulls the comptr's value, and NextChild
   // depends on the passed-in comptr being null or already set to a child (finding the next sibling).
   nsIAccessible *NextChild(nsCOMPtr<nsIAccessible>& aAccessible);
     
   already_AddRefed<nsIAccessible> GetNextWithState(nsIAccessible *aStart, PRUint32 matchState);
 
   /**
-   * Return an accessible for the given DOM node, or if that node isn't accessible, return the
-   * accessible for the next DOM node which has one (based on forward depth first search)
-   * @param aStartNode, the DOM node to start from
-   * @param aRequireLeaf, only accept leaf accessible nodes
-   * @return the resulting accessible
+   * Return an accessible for the given DOM node, or if that node isn't
+   * accessible, return the accessible for the next DOM node which has one
+   * (based on forward depth first search).
+   *
+   * @param  aStartNode  [in] the DOM node to start from
+   * @return              the resulting accessible
    */   
-  already_AddRefed<nsIAccessible> GetFirstAvailableAccessible(nsIDOMNode *aStartNode, PRBool aRequireLeaf = PR_FALSE);
+  already_AddRefed<nsIAccessible>
+    GetFirstAvailableAccessible(nsIDOMNode *aStartNode);
 
   // Hyperlink helpers
   virtual nsresult GetLinkOffset(PRInt32* aStartOffset, PRInt32* aEndOffset);
 
   //////////////////////////////////////////////////////////////////////////////
   // Action helpers
 
   /**
--- a/accessible/src/base/nsAccessibleEventData.cpp
+++ b/accessible/src/base/nsAccessibleEventData.cpp
@@ -302,27 +302,27 @@ nsAccEvent::GetAccessibleByNode()
   }
 #endif
 
   return accessible.forget();
 }
 
 /* static */
 void
-nsAccEvent::ApplyEventRules(nsTArray<nsCOMPtr<nsIAccessibleEvent> > &aEventsToFire)
+nsAccEvent::ApplyEventRules(nsTArray<nsRefPtr<nsAccEvent> > &aEventsToFire)
 {
   PRUint32 numQueuedEvents = aEventsToFire.Length();
   PRInt32 tail = numQueuedEvents - 1;
 
-  nsRefPtr<nsAccEvent> tailEvent = GetAccEventPtr(aEventsToFire[tail]);
+  nsAccEvent* tailEvent = aEventsToFire[tail];
   switch(tailEvent->mEventRule) {
     case nsAccEvent::eCoalesceFromSameSubtree:
     {
       for (PRInt32 index = 0; index < tail; index ++) {
-        nsRefPtr<nsAccEvent> thisEvent = GetAccEventPtr(aEventsToFire[index]);
+        nsAccEvent* thisEvent = aEventsToFire[index];
         if (thisEvent->mEventType != tailEvent->mEventType)
           continue; // Different type
 
         if (thisEvent->mEventRule == nsAccEvent::eAllowDupes ||
             thisEvent->mEventRule == nsAccEvent::eDoNotEmit)
           continue; //  Do not need to check
 
         if (thisEvent->mDOMNode == tailEvent->mDOMNode) {
@@ -376,39 +376,39 @@ nsAccEvent::ApplyEventRules(nsTArray<nsC
                         tailEvent->mDOMNode, nsAccEvent::eAllowDupes);
       }
     } break; // case eCoalesceFromSameSubtree
 
     case nsAccEvent::eRemoveDupes:
     {
       // Check for repeat events.
       for (PRInt32 index = 0; index < tail; index ++) {
-        nsRefPtr<nsAccEvent> accEvent = GetAccEventPtr(aEventsToFire[index]);
+        nsAccEvent* accEvent = aEventsToFire[index];
         if (accEvent->mEventType == tailEvent->mEventType &&
             accEvent->mEventRule == tailEvent->mEventRule &&
             accEvent->mDOMNode == tailEvent->mDOMNode) {
           accEvent->mEventRule = nsAccEvent::eDoNotEmit;
         }
       }
     } break; // case eRemoveDupes
 
     default:
       break; // case eAllowDupes, eDoNotEmit
   } // switch
 }
 
 /* static */
 void
-nsAccEvent::ApplyToSiblings(nsTArray<nsCOMPtr<nsIAccessibleEvent> > &aEventsToFire,
+nsAccEvent::ApplyToSiblings(nsTArray<nsRefPtr<nsAccEvent> > &aEventsToFire,
                             PRUint32 aStart, PRUint32 aEnd,
-                             PRUint32 aEventType, nsIDOMNode* aDOMNode,
-                             EEventRule aEventRule)
+                            PRUint32 aEventType, nsIDOMNode* aDOMNode,
+                            EEventRule aEventRule)
 {
   for (PRUint32 index = aStart; index < aEnd; index ++) {
-    nsRefPtr<nsAccEvent> accEvent = GetAccEventPtr(aEventsToFire[index]);
+    nsAccEvent* accEvent = aEventsToFire[index];
     if (accEvent->mEventType == aEventType &&
         accEvent->mEventRule != nsAccEvent::eDoNotEmit &&
         nsCoreUtils::AreSiblings(accEvent->mDOMNode, aDOMNode)) {
       accEvent->mEventRule = aEventRule;
     }
   }
 }
 
--- a/accessible/src/base/nsAccessibleEventData.h
+++ b/accessible/src/base/nsAccessibleEventData.h
@@ -45,16 +45,17 @@
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsIAccessibleEvent.h"
 #include "nsIAccessible.h"
 #include "nsIAccessibleDocument.h"
 #include "nsIDOMNode.h"
 #include "nsString.h"
 #include "nsCycleCollectionParticipant.h"
+#include "nsAccUtils.h"
 
 class nsIPresShell;
 
 #define NS_ACCEVENT_IMPL_CID                            \
 {  /* 55b89892-a83d-4252-ba78-cbdf53a86936 */           \
   0x55b89892,                                           \
   0xa83d,                                               \
   0x4252,                                               \
@@ -121,21 +122,23 @@ private:
 
 public:
   static PRUint32 EventType(nsIAccessibleEvent *aAccEvent) {
     PRUint32 eventType;
     aAccEvent->GetEventType(&eventType);
     return eventType;
   }
   static EEventRule EventRule(nsIAccessibleEvent *aAccEvent) {
-    nsRefPtr<nsAccEvent> accEvent = GetAccEventPtr(aAccEvent);
+    nsRefPtr<nsAccEvent> accEvent =
+      nsAccUtils::QueryObject<nsAccEvent>(aAccEvent);
     return accEvent->mEventRule;
   }
   static PRBool IsAsyncEvent(nsIAccessibleEvent *aAccEvent) {
-    nsRefPtr<nsAccEvent> accEvent = GetAccEventPtr(aAccEvent);
+    nsRefPtr<nsAccEvent> accEvent =
+      nsAccUtils::QueryObject<nsAccEvent>(aAccEvent);
     return accEvent->mIsAsync;
   }
   static PRBool IsFromUserInput(nsIAccessibleEvent *aAccEvent) {
     PRBool isFromUserInput;
     aAccEvent->GetIsFromUserInput(&isFromUserInput);
     return isFromUserInput;
   }
 
@@ -164,36 +167,30 @@ public:
 
   /**
    * Apply event rules to pending events, this method is called in
    * FlushingPendingEvents().
    * Result of this method:
    *   Event rule of filtered events will be set to eDoNotEmit.
    *   Events with other event rule are good to emit.
    */
-  static void ApplyEventRules(nsTArray<nsCOMPtr<nsIAccessibleEvent> > &aEventsToFire);
+  static void ApplyEventRules(nsTArray<nsRefPtr<nsAccEvent> > &aEventsToFire);
 
 private:
-  static already_AddRefed<nsAccEvent> GetAccEventPtr(nsIAccessibleEvent *aAccEvent) {
-    nsAccEvent* accEvent = nsnull;
-    aAccEvent->QueryInterface(NS_GET_IID(nsAccEvent), (void**)&accEvent);
-    return accEvent;
-  }
-
   /**
    * Apply aEventRule to same type event that from sibling nodes of aDOMNode.
    * @param aEventsToFire    array of pending events
    * @param aStart           start index of pending events to be scanned
    * @param aEnd             end index to be scanned (not included)
    * @param aEventType       target event type
    * @param aDOMNode         target are siblings of this node
    * @param aEventRule       the event rule to be applied
    *                         (should be eDoNotEmit or eAllowDupes)
    */
-  static void ApplyToSiblings(nsTArray<nsCOMPtr<nsIAccessibleEvent> > &aEventsToFire,
+  static void ApplyToSiblings(nsTArray<nsRefPtr<nsAccEvent> > &aEventsToFire,
                               PRUint32 aStart, PRUint32 aEnd,
                               PRUint32 aEventType, nsIDOMNode* aDOMNode,
                               EEventRule aEventRule);
 
   /**
    * Do not emit one of two given reorder events fired for the same DOM node.
    */
   static void CoalesceReorderEventsFromSameSource(nsAccEvent *aAccEvent1,
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -856,51 +856,16 @@ nsresult nsDocAccessible::RemoveEventLis
       caretAccessible->RemoveDocSelectionListener(presShell);
     }
   }
 
   return NS_OK;
 }
 
 void
-nsDocAccessible::FireAnchorJumpEvent()
-{
-  if (!mIsContentLoaded || !mDocument)
-    return;
-
-  nsCOMPtr<nsISupports> container = mDocument->GetContainer();
-  nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(container));
-  nsCAutoString theURL;
-  if (webNav) {
-    nsCOMPtr<nsIURI> pURI;
-    webNav->GetCurrentURI(getter_AddRefs(pURI));
-    if (pURI) {
-      pURI->GetSpec(theURL);
-    }
-  }
-  static nsCAutoString lastAnchor;
-  const char kHash = '#';
-  nsCAutoString currentAnchor;
-  PRInt32 hasPosition = theURL.FindChar(kHash);
-  if (hasPosition > 0 && hasPosition < (PRInt32)theURL.Length() - 1) {
-    mIsAnchor = PR_TRUE;
-    currentAnchor.Assign(Substring(theURL,
-                                   hasPosition+1, 
-                                   (PRInt32)theURL.Length()-hasPosition-1));
-  }
-
-  if (currentAnchor.Equals(lastAnchor)) {
-    mIsAnchorJumped = PR_FALSE;
-  } else {
-    mIsAnchorJumped = PR_TRUE;
-    lastAnchor.Assign(currentAnchor);
-  }
-}
-
-void
 nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
 {
   if (IsDefunct())
     return;
 
   PRBool isFinished = 
              (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE ||
               aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
@@ -943,17 +908,16 @@ nsDocAccessible::FireDocLoadEvents(PRUin
         nsCoreUtils::GetDocShellTreeItemFor(gLastFocusedNode);
       if (focusedTreeItem) {
         nsCOMPtr<nsIDocShellTreeItem> sameTypeRootOfFocus;
         focusedTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRootOfFocus));
         if (sameTypeRoot == sameTypeRootOfFocus) {
           nsCOMPtr<nsIAccessibleEvent> accEvent =
             new nsAccStateChangeEvent(this, nsIAccessibleStates::STATE_BUSY, PR_FALSE, PR_FALSE);
           FireAccessibleEvent(accEvent);
-          FireAnchorJumpEvent();
         }
       }
     }
   }
 
   if (sameTypeRoot == treeItem) {
     // Not a frame or iframe
     if (!isFinished) {
@@ -1621,17 +1585,18 @@ nsDocAccessible::FireDelayedAccessibleEv
   return FireDelayedAccessibleEvent(event);
 }
 
 nsresult
 nsDocAccessible::FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent)
 {
   NS_ENSURE_ARG(aEvent);
 
-  mEventsToFire.AppendElement(aEvent);
+  nsRefPtr<nsAccEvent> accEvent = nsAccUtils::QueryObject<nsAccEvent>(aEvent);
+  mEventsToFire.AppendElement(accEvent);
 
   // Filter events.
   nsAccEvent::ApplyEventRules(mEventsToFire);
 
   // Process events.
   return PreparePendingEventsFlush();
 }
 
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -51,21 +51,21 @@
 #include "nsCOMArray.h"
 #include "nsIDocShellTreeNode.h"
 
 class nsIScrollableView;
 
 const PRUint32 kDefaultCacheSize = 256;
 
 #define NS_DOCACCESSIBLE_IMPL_CID                       \
-{  /* 9735bc5f-a4b6-4668-ab73-6f8434c8e750 */           \
-  0x9735bc5f,                                           \
-  0xa4b6,                                               \
-  0x4668,                                               \
-  { 0xab, 0x73, 0x6f, 0x84, 0x34, 0xc8, 0xe7, 0x50 }    \
+{  /* 9e97d7af-b20a-4a5a-a8d9-bcae0de0b7a2 */           \
+  0x9e97d7af,                                           \
+  0xb20a,                                               \
+  0x4a5a,                                               \
+  { 0xa8, 0xd9, 0xbc, 0xae, 0x0d, 0xe0, 0xb7, 0xa2 }    \
 }
 
 class nsDocAccessible : public nsHyperTextAccessibleWrap,
                         public nsIAccessibleDocument,
                         public nsIDocumentObserver,
                         public nsIObserver,
                         public nsIScrollPositionListener,
                         public nsSupportsWeakReference
@@ -168,21 +168,16 @@ public:
   /**
    * Fire document load events.
    *
    * @param  aEventType  [in] nsIAccessibleEvent constant
    */
   virtual void FireDocLoadEvents(PRUint32 aEventType);
 
   /**
-   * Process the case when anchor was clicked.
-   */
-  virtual void FireAnchorJumpEvent();
-
-  /**
    * Used to flush pending events, called after timeout. See FlushPendingEvents.
    */
   static void FlushEventsCallback(nsITimer *aTimer, void *aClosure);
 
 protected:
   /**
    * Iterates through sub documents and shut them down.
    */
@@ -293,22 +288,20 @@ protected:
     nsCOMPtr<nsIDocument> mDocument;
     nsCOMPtr<nsITimer> mScrollWatchTimer;
     nsCOMPtr<nsITimer> mFireEventTimer;
     PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
     PRPackedBool mIsContentLoaded;
     PRPackedBool mIsLoadCompleteFired;
 
 protected:
-    PRBool mIsAnchor;
-    PRBool mIsAnchorJumped;
 
   PRBool mInFlushPendingEvents;
   PRBool mFireEventTimerStarted;
-  nsTArray<nsCOMPtr<nsIAccessibleEvent> > mEventsToFire;
+  nsTArray<nsRefPtr<nsAccEvent> > mEventsToFire;
 
     static PRUint32 gLastFocusedAccessiblesState;
     static nsIAtom *gLastFocusedFrameType;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsDocAccessible,
                               NS_DOCACCESSIBLE_IMPL_CID)
 
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -56,24 +56,18 @@
   *  all of the widgets for both of the Selects, for HTML only.
   *
   *  Listbox:
   *     - nsHTMLSelectListAccessible
   *       - nsHTMLSelectOptionAccessible
   *
   *  Comboboxes:
   *     - nsHTMLComboboxAccessible
-  *        - nsHTMLComboboxTextFieldAccessible  (#ifdef COMBO_BOX_WITH_THREE_CHILDREN)
-  *        - nsHTMLComboboxButtonAccessible     (#ifdef COMBO_BOX_WITH_THREE_CHILDREN)
   *        - nsHTMLComboboxListAccessible        [ inserted in accessible tree ]
   *           - nsHTMLSelectOptionAccessible(s)
-  *
-  * XXX COMBO_BOX_WITH_THREE_CHILDREN is not currently defined.
-  *     If we start using it again, we should pass the correct frame into those accessibles.
-  *     They share a DOM node with the parent combobox.
   */
 
 
 /** ------------------------------------------------------ */
 /**  Impl. of nsHTMLSelectableAccessible                   */
 /** ------------------------------------------------------ */
 
 // Helper class
@@ -977,40 +971,16 @@ void nsHTMLComboboxAccessible::CacheChil
   if (!mWeakShell) {
     // This node has been shut down
     mAccChildCount = eChildCountUninitialized;
     return;
   }
 
   if (mAccChildCount == eChildCountUninitialized) {
     mAccChildCount = 0;
-#ifdef COMBO_BOX_WITH_THREE_CHILDREN
-    // We no longer create textfield and button accessible, in order to have
-    // harmonization between IAccessible2, ATK/AT-SPI and OS X
-    nsHTMLComboboxTextFieldAccessible* textFieldAccessible = 
-      new nsHTMLComboboxTextFieldAccessible(this, mDOMNode, mWeakShell);
-    SetFirstChild(textFieldAccessible);
-    if (!textFieldAccessible) {
-      return;
-    }
-    textFieldAccessible->SetParent(this);
-    textFieldAccessible->Init();
-    mAccChildCount = 1;  // Textfield accessible child successfully added
-
-    nsHTMLComboboxButtonAccessible* buttonAccessible =
-      new nsHTMLComboboxButtonAccessible(mParent, mDOMNode, mWeakShell);
-    textFieldAccessible->SetNextSibling(buttonAccessible);
-    if (!buttonAccessible) {
-      return;
-    }
-
-    buttonAccessible->SetParent(this);
-    buttonAccessible->Init();
-    mAccChildCount = 2; // Button accessible child successfully added
-#endif
 
     nsIFrame *frame = GetFrame();
     if (!frame) {
       return;
     }
     nsIComboboxControlFrame *comboFrame = do_QueryFrame(frame);
     if (!comboFrame) {
       return;
@@ -1024,21 +994,17 @@ void nsHTMLComboboxAccessible::CacheChil
       mListAccessible = 
         new nsHTMLComboboxListAccessible(mParent, mDOMNode, mWeakShell);
       if (!mListAccessible)
         return;
 
       mListAccessible->Init();
     }
 
-#ifdef COMBO_BOX_WITH_THREE_CHILDREN
-    buttonAccessible->SetNextSibling(mListAccessible);
-#else
     SetFirstChild(mListAccessible);
-#endif
 
     mListAccessible->SetParent(this);
     mListAccessible->SetNextSibling(nsnull);
 
     ++ mAccChildCount;  // List accessible child successfully added
   }
 }
 
@@ -1183,232 +1149,19 @@ NS_IMETHODIMP nsHTMLComboboxAccessible::
   if (comboFrame->IsDroppedDown())
     aName.AssignLiteral("close"); 
   else
     aName.AssignLiteral("open"); 
 
   return NS_OK;
 }
 
-
-#ifdef COMBO_BOX_WITH_THREE_CHILDREN
-/** ----- nsHTMLComboboxTextFieldAccessible ----- */
-
-/** Constructor */
-nsHTMLComboboxTextFieldAccessible::nsHTMLComboboxTextFieldAccessible(nsIAccessible* aParent, 
-                                                                     nsIDOMNode* aDOMNode, 
-                                                                     nsIWeakReference* aShell):
-nsHTMLTextFieldAccessible(aDOMNode, aShell)
-{
-}
-
-NS_IMETHODIMP nsHTMLComboboxTextFieldAccessible::GetUniqueID(void **aUniqueID)
-{
-  // Since mDOMNode is same as for our parent, use |this| pointer as the unique Id
-  *aUniqueID = static_cast<void*>(this);
-  return NS_OK;
-}
-
-/**
-  * Gets the bounds for the BlockFrame.
-  *     Walks the Frame tree and checks for proper frames.
-  */
-void nsHTMLComboboxTextFieldAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame)
-{
-  // get our first child's frame
-  nsIFrame* frame = nsAccessible::GetBoundsFrame();
-  if (!frame)
-    return;
-
-  frame = frame->GetFirstChild(nsnull);
-  *aBoundingFrame = frame;
-
-  aBounds = frame->GetRect();
-}
-
-void nsHTMLComboboxTextFieldAccessible::CacheChildren()
-{
-  // Allow single text anonymous child, so that nsHyperTextAccessible can operate correctly
-  // We must override this otherwise we get the dropdown button as a child of the textfield,
-  // and at least for now we want to keep it as a sibling
-  if (!mWeakShell) {
-    // This node has been shut down
-    mAccChildCount = eChildCountUninitialized;
-    return;
-  }
-
-  // Allows only 1 child
-  if (mAccChildCount == eChildCountUninitialized) {
-    mAccChildCount = 0; // Prevent reentry
-    nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
-    // Seed the frame hint early while we're still on a container node.
-    // This is better than doing the GetPrimaryFrameFor() later on
-    // a text node, because text nodes aren't in the frame map.
-    walker.mState.frame = GetFrame();
-
-    walker.GetFirstChild();
-    SetFirstChild(walker.mState.accessible);
-    nsRefPtr<nsAccessible> child =
-      nsAccUtils::QueryAccessible(walker.mState.accessible);
-    child->SetParent(this);
-    child->SetNextSibling(nsnull);
-    mAccChildCount = 1;
-  }
-}
-
-/** -----ComboboxButtonAccessible ----- */
-
-/** Constructor -- cache our parent */
-nsHTMLComboboxButtonAccessible::nsHTMLComboboxButtonAccessible(nsIAccessible* aParent, 
-                                                           nsIDOMNode* aDOMNode, 
-                                                           nsIWeakReference* aShell):
-nsLeafAccessible(aDOMNode, aShell)
-{
-}
-
-/** Just one action ( click ). */
-NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetNumActions(PRUint8 *aNumActions)
-{
-  *aNumActions = 1;
-  return NS_OK;
-}
-
-/**
-  * Programmaticaly click on the button, causing either the display or
-  *     the hiding of the drop down box ( window ).
-  *     Walks the Frame tree and checks for proper frames.
-  */
-NS_IMETHODIMP nsHTMLComboboxButtonAccessible::DoAction(PRUint8 aIndex)
-{
-  nsIFrame* frame = nsAccessible::GetBoundsFrame();
-  nsPresContext *context = GetPresContext();
-  if (!frame || !context)
-    return NS_ERROR_FAILURE;
-
-  frame = frame->GetFirstChild(nsnull)->GetNextSibling();
-
-  // We only have one action, click. Any other index is meaningless(wrong)
-  if (aIndex == eAction_Click) {
-    nsCOMPtr<nsIDOMHTMLInputElement>
-      element(do_QueryInterface(frame->GetContent()));
-    if (element)
-    {
-       element->Click();
-       return NS_OK;
-    }
-    return NS_ERROR_FAILURE;
-  }
-  return NS_ERROR_INVALID_ARG;
-}
-
-/**
-  * Our action name is the reverse of our state: 
-  *     if we are closed -> open is our name.
-  *     if we are open -> closed is our name.
-  * Uses the frame to get the state, updated on every click
-  */
-NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
-{
-  nsIFrame *boundsFrame = GetBoundsFrame();
-  nsIComboboxControlFrame* comboFrame;
-  boundsFrame->QueryInterface(NS_GET_IID(nsIComboboxControlFrame), (void**)&comboFrame);
-  if (!comboFrame)
-    return NS_ERROR_FAILURE;
-
-  if (comboFrame->IsDroppedDown())
-    aName.AssignLiteral("close"); 
-  else
-    aName.AssignLiteral("open");
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetUniqueID(void **aUniqueID)
-{
-  // Since mDOMNode is same for all tree item, use |this| pointer as the unique Id
-  *aUniqueID = static_cast<void*>(this);
-  return NS_OK;
-}
-
-/**
-  * Gets the bounds for the gfxButtonControlFrame.
-  *     Walks the Frame tree and checks for proper frames.
-  */
-void nsHTMLComboboxButtonAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame)
-{
-  // get our second child's frame
-  // bounding frame is the ComboboxControlFrame
-  nsIFrame *frame = nsAccessible::GetBoundsFrame();
-  *aBoundingFrame = frame;
-  nsPresContext *context = GetPresContext();
-  if (!frame || !context)
-    return;
-
-  aBounds = frame->GetFirstChild(nsnull)->GetNextSibling()->GetRect();
-    // sibling frame is for the button
-}
-
-/** We are a button. */
-nsresult
-nsHTMLComboboxButtonAccessible::GetRoleInternal(PRUint32 *aRole)
-{
-  *aRole = nsIAccessibleRole::ROLE_PUSHBUTTON;
-  return NS_OK;
-}
-
-/** Return our cached parent */
-NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetParent(nsIAccessible **aParent)
-{   
-  NS_IF_ADDREF(*aParent = mParent);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHTMLComboboxButtonAccessible::GetName(nsAString& aName)
-{
-  // Native anonymous content, no way to use ARIA here.
-  aName.Truncate();
-  return GetActionName(eAction_Click, aName);
-}
-
-/**
-  * As a nsHTMLComboboxButtonAccessible we can have the following states:
-  *     STATE_PRESSED
-  *     STATE_FOCUSED
-  *     STATE_FOCUSABLE
-  *     STATE_INVISIBLE
-  */
-nsresult
-nsHTMLComboboxButtonAccessible::GetStateInternal(PRUint32 *aState,
-                                                 PRUint32 *aExtraState)
-{
-  // Get focus status from base class
-  nsresult rv = nsAccessible::GetStateInternal(aState, aExtraState);
-  NS_ENSURE_A11Y_SUCCESS(rv, rv);
-
-  nsIFrame *boundsFrame = GetBoundsFrame();
-  nsIComboboxControlFrame* comboFrame = nsnull;
-  if (boundsFrame)
-    boundsFrame->QueryInterface(NS_GET_IID(nsIComboboxControlFrame), (void**)&comboFrame);
-
-  if (!comboFrame) {
-    *aState |= nsIAccessibleStates::STATE_INVISIBLE;
-  }
-  else {
-    *aState |= nsIAccessibleStates::STATE_FOCUSABLE;
-    if (comboFrame->IsDroppedDown()) {
-      *aState |= nsIAccessibleStates::STATE_PRESSED;
-    }
-  }
- 
-  return NS_OK;
-}
-#endif
-
-/** ----- nsHTMLComboboxListAccessible ----- */
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLComboboxListAccessible
+////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLComboboxListAccessible::nsHTMLComboboxListAccessible(nsIAccessible *aParent,
                                                            nsIDOMNode* aDOMNode,
                                                            nsIWeakReference* aShell):
 nsHTMLSelectListAccessible(aDOMNode, aShell)
 {
 }
 
--- a/accessible/src/html/nsHTMLSelectAccessible.h
+++ b/accessible/src/html/nsHTMLSelectAccessible.h
@@ -239,69 +239,16 @@ protected:
   void CacheChildren();
 
   already_AddRefed<nsIAccessible> GetFocusedOptionAccessible();
 
 private:
   nsRefPtr<nsHTMLComboboxListAccessible> mListAccessible;
 };
 
-#ifdef COMBO_BOX_WITH_THREE_CHILDREN
-/*
- * A class the represents the text field in the Select to the left
- *     of the drop down button
- */
-class nsHTMLComboboxTextFieldAccessible  : public nsHTMLTextFieldAccessible
-{
-public:
-  
-  nsHTMLComboboxTextFieldAccessible(nsIAccessible* aParent, nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
-  virtual ~nsHTMLComboboxTextFieldAccessible() {}
-
-  /* ----- nsIAccessible ----- */
-  NS_IMETHOD GetUniqueID(void **aUniqueID);
-
-  virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame);
-
-protected:
-  void CacheChildren();
-};
-
-/**
-  * A class that represents the button inside the Select to the
-  *     right of the text field
-  */
-class nsHTMLComboboxButtonAccessible  : public nsLeafAccessible
-{
-public:
-  enum { eAction_Click = 0 };
-
-  nsHTMLComboboxButtonAccessible(nsIAccessible* aParent, nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
-  virtual ~nsHTMLComboboxButtonAccessible() {}
-
-  // nsIAccessible
-  NS_IMETHOD DoAction(PRUint8 index);
-  NS_IMETHOD GetNumActions(PRUint8 *_retval);
-  NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
-  NS_IMETHOD GetParent(nsIAccessible **_retval);
-  NS_IMETHOD GetName(nsAString& aName);
-
-  // nsIAccessNode
-  NS_IMETHOD GetUniqueID(void **aUniqueID);
-
-  // nsAccessible
-  virtual nsresult GetRoleInternal(PRUint32 *aRole);
-  virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
-  
-protected:
-  virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame);
-};
-
-#endif
-
 /*
  * A class that represents the window that lives to the right
  * of the drop down button inside the Select. This is the window
  * that is made visible when the button is pressed.
  */
 class nsHTMLComboboxListAccessible : public nsHTMLSelectListAccessible
 {
 public:
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -137,51 +137,16 @@ nsDocAccessibleWrap::get_accChild(VARIAN
   }
 
   // Otherwise, the normal get_accChild() will do
   return nsAccessibleWrap::get_accChild(varChild, ppdispChild);
 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
-void
-nsDocAccessibleWrap::FireAnchorJumpEvent()
-{
-  // Staying on the same page, jumping to a named anchor
-  // Fire EVENT_SCROLLING_START on first leaf accessible -- because some
-  // assistive technologies only cache the child numbers for leaf accessibles
-  // the can only relate events back to their internal model if it's a leaf.
-  // There is usually an accessible for the focus node, but if it's an empty text node
-  // we have to move forward in the document to get one
-  nsDocAccessible::FireAnchorJumpEvent();
-  if (!mIsAnchorJumped)
-    return;
-
-  nsCOMPtr<nsIDOMNode> focusNode;
-  if (mIsAnchor) {
-    nsCOMPtr<nsISelectionController> selCon(do_QueryReferent(mWeakShell));
-    if (!selCon)
-      return;
-
-    nsCOMPtr<nsISelection> domSel;
-    selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
-    if (!domSel)
-      return;
-
-    domSel->GetFocusNode(getter_AddRefs(focusNode));
-  }
-  else {
-    focusNode = mDOMNode; // Moved to top, so event is for 1st leaf after root
-  }
-
-  nsCOMPtr<nsIAccessible> accessible = GetFirstAvailableAccessible(focusNode, PR_TRUE);
-  nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_SCROLLING_START,
-                           accessible);
-}
-
 STDMETHODIMP nsDocAccessibleWrap::get_URL(/* [out] */ BSTR __RPC_FAR *aURL)
 {
 __try {
   *aURL = NULL;
 
   nsAutoString URL;
   nsresult rv = GetURL(URL);
   if (NS_FAILED(rv))
--- a/accessible/src/msaa/nsDocAccessibleWrap.h
+++ b/accessible/src/msaa/nsDocAccessibleWrap.h
@@ -87,18 +87,16 @@ public:
         /* [in] */ VARIANT varChild,
         /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild);
 
     // Override get_accValue to provide URL when no other value is available
     virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accValue( 
         /* [optional][in] */ VARIANT varChild,
         /* [retval][out] */ BSTR __RPC_FAR *pszValue);
 
-    virtual void FireAnchorJumpEvent();
-
   // nsDocAccessibleWrap
 
   /**
    * Find an accessible by the given child ID in cached documents.
    *
    * @param  aVarChild    [in] variant pointing to the child ID
    * @param  aAccessible  [out] the found accessible
    */
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -49,16 +49,17 @@ include $(topsrcdir)/config/rules.mk
 		letters.gif \
 		moz.png \
 		$(topsrcdir)/content/media/test/bug461281.ogg \
 		longdesc_src.html \
 		actions.js \
 		attributes.js \
 		common.js \
 		events.js \
+		events_scroll.html \
 		grid.js \
 		layout.js \
 		name.css \
 		name.js \
 		name.xbl \
 		name_nsRootAcc_wnd.xul \
 		namerules.xml \
  		nsIAccessible_selects.js \
@@ -86,26 +87,28 @@ include $(topsrcdir)/config/rules.mk
 	$(warning   test_childAtPoint.html temporarily disabled) \
 	$(warning	test_childAtPoint.xul temporarily disabled) \
 		test_cssattrs.html \
 		test_descr.html \
 		test_elm_filectrl.html \
 		test_elm_listbox.xul \
 	$(warning   test_elm_media.html temporarily disabled) \
 		test_elm_plugin.html \
+		test_elm_select.html \
 		test_elm_tree.xul \
 		test_elm_txtcntnr.html \
 		test_events_caretmove.html \
 		test_events_coalescence.html \
 		test_events_doc.html \
 		test_events_draganddrop.html \
 		test_events_flush.html \
 		test_events_focus.html \
 		test_events_focus.xul \
 		test_events_mutation.html \
+		test_events_scroll.xul \
 		test_events_tree.xul \
 		test_events_valuechange.html \
 		test_groupattrs.xul \
 		test_groupattrs.html \
 		test_invalidate_accessnode.html \
 		test_invalidate_elmli.html \
 		test_name.html \
 		test_name.xul \
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/events_scroll.html
@@ -0,0 +1,123 @@
+<html>
+
+<head>
+  <title>nsIAccessible actions testing for anchors</title>
+</head>
+
+<body>
+  <p>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+  </p>
+  <a name="link1">link1</a>
+
+  <p style="color: blue">
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+    text text text text text text text text text text text text text text <br>
+  </p>
+</body>
+<html>
--- a/accessible/tests/mochitest/name_nsRootAcc_wnd.xul
+++ b/accessible/tests/mochitest/name_nsRootAcc_wnd.xul
@@ -16,17 +16,20 @@
       gOpenerWnd.SimpleTest.is(aExpected, aActual, aMsg);
     }
 
     // Hack to make xul:tabbrowser work.
     var XULBrowserWindow = {
       isBusy: false,
       setOverLink: function (link, b) {
       }
-    }
+    };
+    var gFindBar = {
+      hidden: true
+    };
 
     ////////////////////////////////////////////////////////////////////////////
     // Invoker implementation.
 
     function switchTabSelectChecker(aInvoker)
     {
       this.type = "select";
       this.target getter = function() { return aInvoker.getTabsElm(); }
@@ -69,27 +72,29 @@
 
     ////////////////////////////////////////////////////////////////////////////
     // Tests
 
     var gQueue = null;
 
     const Ci = Components.interfaces;
 
-    function onload()
+    function doTest()
     {
       var tabBrowser = document.getElementById("content");
       tabBrowser.loadURI("about:");
       tabBrowser.addTab("about:mozilla");
 
       gQueue = new gOpenerWnd.eventQueue();
       gQueue.push(new switchTabInvoker(tabBrowser));
       gQueue.onFinish = function() { window.close(); }
       gQueue.invoke();
     }
+
+    gOpenerWnd.addA11yLoadEvent(doTest);
   ]]>
   </script>
 
   <!-- Hack to make xul:tabbrowser work -->
   <menubar>
     <menu label="menu">
       <menupopup>
         <menuitem label="close window hook" id="menu_closeWindow"/>
--- a/accessible/tests/mochitest/test_actions_anchors.html
+++ b/accessible/tests/mochitest/test_actions_anchors.html
@@ -34,41 +34,33 @@
 
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
     // gA11yEventDumpID = "debug"; // debug stuff
 
     function doTest()
     {
-      if (!WIN) {
-        ok(true,
-           "Nothing to test because scolling events are fired on Windows only");
-
-        SimpleTest.finish();
-        return;
-      }
-
       var actionsArray = [
         {
           ID: "anchor1",
           actionName: "jump",
           actionIndex: 0,
           events: CLICK_EVENTS,
           eventSeq: [
             new scrollingChecker(getAccessible("bottom1"))
           ]
         },
         {
           ID: "anchor2",
           actionName: "jump",
           actionIndex: 0,
           events: CLICK_EVENTS,
           eventSeq: [
-            new scrollingChecker(getAccessible("bottom2").firstChild)
+            new scrollingChecker(getAccessible("bottom2"))
           ]
         }
       ];
 
       testActions(actionsArray);
     }
 
     SimpleTest.waitForExplicitFinish();
@@ -77,17 +69,28 @@
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=506389"
      title="Some same page links do not fire EVENT_SYSTEM_SCROLLINGSTART">
     Mozilla Bug 506389
+  </a><br>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=437607"
+     title="Clicking the 'Skip to main content' link once works, second time fails to initiate a V cursor jump">
+    Mozilla Bug 437607
+  </a><br>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=519303"
+     title="Same page links to targets with content fires scrolling start accessible event on leaf text node">
+    Mozilla Bug 519303
   </a>
+
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="debug"></div>
 
   <h1>This is a test page for anchors</h1>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_elm_select.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>HTML select control tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      var accTree = {
+        role: ROLE_LISTBOX,
+        children: [
+          {
+            role: ROLE_HEADING
+          },
+          {
+            role: ROLE_OPTION,
+            children: [
+              {
+                role: ROLE_TEXT_LEAF
+              }
+            ]
+          },
+          {
+            role: ROLE_OPTION,
+            children: [
+              {
+                role: ROLE_TEXT_LEAF
+              }
+            ]
+          },
+          {
+            role: ROLE_OPTION,
+            children: [
+              {
+                role: ROLE_TEXT_LEAF
+              }
+            ]
+          }
+        ]
+      };
+      testAccessibleTree("listbox", accTree);
+
+      accTree = {
+        role: ROLE_COMBOBOX,
+        children: [
+          {
+            role: ROLE_COMBOBOX_LIST,
+            children: [
+              {
+                role: ROLE_HEADING
+              },
+              {
+                role: ROLE_COMBOBOX_OPTION,
+                children: [
+                  {
+                    role: ROLE_TEXT_LEAF
+                  }
+                ]
+              },
+              {
+                role: ROLE_COMBOBOX_OPTION,
+                children: [
+                  {
+                    role: ROLE_TEXT_LEAF
+                  }
+                ]
+              },
+              {
+                role: ROLE_COMBOBOX_OPTION,
+                children: [
+                  {
+                    role: ROLE_TEXT_LEAF
+                  }
+                ]
+              }
+            ]
+          }
+        ]
+      };
+      testAccessibleTree("combobox", accTree);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="remove all the code in #ifdef COMBO_BOX_WITH_THREE_CHILDREN"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=506616">
+    Mozilla Bug 506616
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <select id="listbox" size="4">
+    <optgroup label="Colors">
+      <option>Red</option>
+      <option>Blue</option>
+    </optgroup>
+    <option>Animal</option>
+  </select>
+
+  <select id="combobox">
+    <optgroup label="Colors">
+      <option>Red</option>
+      <option>Blue</option>
+    </optgroup>
+    <option>Animal</option>
+  </select>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_events_scroll.xul
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
+
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/treeview.js" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/events.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Hack to make xul:tabbrowser work
+
+    const Ci = Components.interfaces;
+
+    var XULBrowserWindow = {
+      isBusy: false,
+      setOverLink: function (link, b) {
+      }
+    };
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Tests
+
+    var gScrollHandler = {
+      handleEvent: function gScrollHandler_handleEvent(aEvent) {
+        if (aEvent.DOMNode.getAttribute("name") == "link1") {
+          unregisterA11yEventListener(EVENT_SCROLLING_START, this);
+          SimpleTest.finish();
+        }
+      }
+    };
+
+    function doTest()
+    {
+      registerA11yEventListener(EVENT_SCROLLING_START, gScrollHandler);
+
+      var url =
+        "chrome://mochikit/content/a11y/accessible/events_scroll.html#link1";
+
+      var tabBrowser = document.getElementById("tabBrowser");
+      tabBrowser.loadURI(url);
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=437607"
+         title="Clicking the 'Skip to main content' link once works, second time fails to initiate a V cursor jump">
+        Mozilla Bug 437607
+      </a><br/>
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=519303"
+         title="Same page links to targets with content fires scrolling start accessible event on leaf text node">
+        Mozilla Bug 519303
+      </a>
+
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <!-- Hack to make xul:tabbrowser work -->
+      <menubar>
+        <menu label="menu">
+          <menupopup>
+            <menuitem label="close window hook" id="menu_closeWindow"/>
+            <menuitem label="close hook" id="menu_close"/>
+          </menupopup>
+        </menu>
+      </menubar>
+
+      <tabbrowser type="content-primary" flex="1" id="tabBrowser"/>
+    </vbox>
+  </hbox>
+
+</window>
--- a/allmakefiles.sh
+++ b/allmakefiles.sh
@@ -58,16 +58,17 @@ fi
 add_makefiles "
 Makefile
 build/Makefile
 build/pgo/Makefile
 build/pgo/blueprint/Makefile
 build/pgo/js-input/Makefile
 build/unix/Makefile
 build/win32/Makefile
+build/win32/crashinjectdll/Makefile
 config/Makefile
 config/autoconf.mk
 config/mkdepend/Makefile
 config/nspr/Makefile
 config/doxygen.cfg
 config/tests/src-simple/Makefile
 probes/Makefile
 extensions/Makefile
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -16,16 +16,24 @@
         <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
            <versionRange minVersion="3.0a1" maxVersion="*"/>
         </targetApplication>
       </versionRange>
     </emItem>
     <emItem id="support@daemon-tools.cc">
       <versionRange minVersion=" " maxVersion="1.0.0.5"/>
     </emItem>
+    <emItem id="{2224e955-00e9-4613-a844-ce69fccaae91}"/>
+    <emItem id="{3f963a5b-e555-4543-90e2-c3908898db71}">
+      <versionRange minVersion=" " maxVersion="8.0">
+        <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+           <versionRange minVersion="3.1a1" maxVersion="*"/>
+        </targetApplication>
+      </versionRange>
+    </emItem>
     <emItem id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}">
       <versionRange minVersion="1.2" maxVersion="1.2">
         <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
            <versionRange minVersion="3.0a1" maxVersion="*"/>
         </targetApplication>
       </versionRange>
     </emItem>
   </emItems>
@@ -44,10 +52,15 @@
     <match name="name" exp="QuickTime Plug-in 7[.]1[.]"/>
     <match name="filename" exp="npqtplugin.?[.]dll"/>
     <versionRange>
       <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
         <versionRange minVersion="3.0a1" maxVersion="3.*"/>
       </targetApplication>
     </versionRange>
   </pluginItem>
+  <pluginItem>
+    <match name="filename" exp="NPFFAddOn.dll"/>
+    <versionRange>
+    </versionRange>
+  </pluginItem>
 </pluginItems>
 </blocklist>
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -49,16 +49,18 @@
 #include "prprf.h"
 #include "prenv.h"
 
 #include "nsCOMPtr.h"
 #include "nsILocalFile.h"
 #include "nsStringGlue.h"
 
 #ifdef XP_WIN
+// we want to use the DLL blocklist if possible
+#define XRE_WANT_DLL_BLOCKLIST
 // we want a wmain entry point
 #include "nsWindowsWMain.cpp"
 #endif
 
 static void Output(const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -257,18 +257,17 @@ pref("browser.urlbar.default.behavior", 
 // picking a filename without that info in hand so that the user sees some
 // feedback from their action.
 pref("browser.download.saveLinkAsFilenameTimeout", 1000);
 
 pref("browser.download.useDownloadDir", true);
 
 #ifdef WINCE
 pref("browser.download.folderList", 2);
-// Bug 499807: use Hard Disk filesystem because Desktop is short on space.
-pref("browser.download.dir", "\\Hard Disk");
+pref("browser.download.dir", "\\Storage Card");
 #else
 pref("browser.download.folderList", 1);
 #endif
 pref("browser.download.manager.showAlertOnComplete", true);
 pref("browser.download.manager.showAlertInterval", 2000);
 pref("browser.download.manager.retention", 2);
 pref("browser.download.manager.showWhenStarting", true);
 pref("browser.download.manager.closeWhenDone", false);
@@ -306,17 +305,16 @@ pref("browser.search.updateinterval", 6)
 
 // Whether or not microsummary and generator updates are enabled
 pref("browser.microsummary.enabled", true);
 pref("browser.microsummary.updateGenerators", true);
 
 // enable search suggestions by default
 pref("browser.search.suggest.enabled", true);
 
-pref("browser.history.showSessions", false);
 pref("browser.sessionhistory.max_entries", 50);
 pref("browser.history_expire_days", 180);
 pref("browser.history_expire_days_min", 90);
 pref("browser.history_expire_sites", 40000);
 
 // handle links targeting new windows
 // 0=default window, 1=current window/tab, 2=new window, 3=new tab in most recent window
 pref("browser.link.open_newwindow", 3);
@@ -358,30 +356,26 @@ pref("browser.tabs.closeButtons", 1);
 // true   return to the tab that opened this tab (its owner)
 // false  return to the adjacent tab (old default)
 pref("browser.tabs.selectOwnerOnClose", true);
 
 pref("browser.allTabs.previews", false);
 pref("browser.ctrlTab.previews", false);
 pref("browser.ctrlTab.recentlyUsedLimit", 7);
 
-// Default bookmark sorting
-pref("browser.bookmarks.sort.direction", "descending");
-pref("browser.bookmarks.sort.resource", "rdf:http://home.netscape.com/NC-rdf#Name");
-
 // By default, do not export HTML at shutdown.
 // If true, at shutdown the bookmarks in your menu and toolbar will
 // be exported as HTML to the bookmarks.html file.
 pref("browser.bookmarks.autoExportHTML",          false);
 
 // The maximum number of daily bookmark backups to 
 // keep in {PROFILEDIR}/bookmarkbackups. Special values:
 // -1: unlimited
 //  0: no backups created (and deletes all existing backups)
-pref("browser.bookmarks.max_backups",             5);
+pref("browser.bookmarks.max_backups",             10);
 
 // Scripts & Windows prefs
 pref("dom.disable_open_during_load",              true);
 #ifdef DEBUG
 pref("javascript.options.showInConsole",          true);
 pref("general.warnOnAboutConfig",                 false);
 #else
 pref("javascript.options.showInConsole",          false);
@@ -753,17 +747,21 @@ pref("browser.EULA.version", 3);
 pref("browser.rights.version", 3);
 pref("browser.rights.3.shown", false);
 
 #ifdef DEBUG
 // Don't show the about:rights notification in debug builds.
 pref("browser.rights.override", true);
 #endif
 
+#ifdef WINCE
+pref("browser.sessionstore.resume_from_crash", false);
+#else
 pref("browser.sessionstore.resume_from_crash", true);
+#endif
 pref("browser.sessionstore.resume_session_once", false);
 
 // minimal interval between two save operations in milliseconds
 pref("browser.sessionstore.interval", 10000);
 // maximum amount of POSTDATA to be saved in bytes per history entry (-1 = all of it)
 // (NB: POSTDATA will be saved either entirely or not at all)
 pref("browser.sessionstore.postdata", 0);
 // on which sites to save text data, POSTDATA and cookies
--- a/browser/base/Makefile.in
+++ b/browser/base/Makefile.in
@@ -50,16 +50,17 @@ abs_srcdir = $(call core_abspath,$(srcdi
 CHROME_DEPS += $(abs_srcdir)/content/overrides/app-license.html
 
 ifdef ENABLE_TESTS
 DIRS += content/test
 endif
 
 EXTRA_JS_MODULES = \
 	content/openLocationLastURL.jsm \
+	content/NetworkPrioritizer.jsm \
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 PRE_RELEASE_SUFFIX := $(shell $(PYTHON) $(topsrcdir)/config/printprereleasesuffix.py \
                         $(shell cat $(srcdir)/../config/version.txt))
 
 DEFINES += \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/NetworkPrioritizer.jsm
@@ -0,0 +1,217 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Paul O’Shannessy <paul@oshannessy.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * This module adjusts network priority for tabs in a way that gives 'important'
+ * tabs a higher priority. There are 3 levels of priority. Each is listed below
+ * with the priority adjustment used.
+ *
+ * Highest (-10): Selected tab in the focused window.
+ * Medium (0):    Background tabs in the focused window.
+ *                Selected tab in background windows.
+ * Lowest (+10):  Background tabs in background windows.
+ */
+
+let EXPORTED_SYMBOLS = ["trackBrowserWindow"];
+
+const Ci = Components.interfaces;
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+
+// Lazy getters
+XPCOMUtils.defineLazyServiceGetter(this, "_focusManager",
+                                   "@mozilla.org/focus-manager;1",
+                                   "nsIFocusManager");
+
+
+// Constants
+const TAB_EVENTS = ["TabOpen", "TabSelect"];
+const WINDOW_EVENTS = ["activate", "unload"];
+// PRIORITY DELTA is -10 because lower priority value is actually a higher priority
+const PRIORITY_DELTA = -10;
+
+
+// Variables
+let _lastFocusedWindow = null;
+let _windows = [];
+
+
+// Exported symbol
+function trackBrowserWindow(aWindow) {
+  WindowHelper.addWindow(aWindow);
+}
+
+
+// Global methods
+function _handleEvent(aEvent) {
+  switch (aEvent.type) {
+    case "TabOpen":
+      BrowserHelper.onOpen(aEvent.target.linkedBrowser);
+      break;
+    case "TabSelect":
+      BrowserHelper.onSelect(aEvent.target.linkedBrowser);
+      break;
+    case "activate":
+      WindowHelper.onActivate(aEvent.target);
+      break;
+    case "unload":
+      WindowHelper.removeWindow(aEvent.currentTarget);
+      break;
+  }
+}
+
+
+// Methods that impact a browser. Put into single object for organization.
+let BrowserHelper = {
+  onOpen: function(aBrowser) {
+    // If the tab is in the focused window, leave priority as it is
+    if (aBrowser.ownerDocument.defaultView != _lastFocusedWindow)
+      this.decreasePriority(aBrowser);
+  },
+
+  onSelect: function(aBrowser) {
+    let windowEntry = WindowHelper.getEntry(aBrowser.ownerDocument.defaultView);
+    if (windowEntry.lastSelectedBrowser)
+      this.decreasePriority(windowEntry.lastSelectedBrowser);
+    this.increasePriority(aBrowser);
+
+    windowEntry.lastSelectedBrowser = aBrowser;
+  },
+
+  // Auxiliary methods
+  getLoadgroup: function(aBrowser) {
+    return aBrowser.webNavigation.QueryInterface(Ci.nsIDocumentLoader)
+                   .loadGroup.QueryInterface(Ci.nsISupportsPriority);
+  },
+
+  increasePriority: function(aBrowser) {
+    this.getLoadgroup(aBrowser).adjustPriority(PRIORITY_DELTA);
+  },
+
+  decreasePriority: function(aBrowser) {
+    this.getLoadgroup(aBrowser).adjustPriority(PRIORITY_DELTA * -1);
+  }
+};
+
+
+// Methods that impact a window. Put into single object for organization.
+let WindowHelper = {
+  addWindow: function(aWindow) {
+    // Build internal data object
+    _windows.push({ window: aWindow, lastSelectedBrowser: null });
+
+    // Add event listeners
+    TAB_EVENTS.forEach(function(event) {
+      aWindow.gBrowser.tabContainer.addEventListener(event, _handleEvent, false);
+    });
+    WINDOW_EVENTS.forEach(function(event) {
+      aWindow.addEventListener(event, _handleEvent, false);
+    });
+
+    // This gets called AFTER activate event, so if this is the focused window
+    // we want to activate it. Otherwise, deprioritize it.
+    if (aWindow == _focusManager.activeWindow)
+      this.handleFocusedWindow(aWindow);
+    else
+      this.decreasePriority(aWindow);
+
+    // Select the selected tab
+    BrowserHelper.onSelect(aWindow.gBrowser.selectedBrowser);
+  },
+
+  removeWindow: function(aWindow) {
+    if (aWindow == _lastFocusedWindow)
+      _lastFocusedWindow = null;
+
+    // Delete this window from our tracking
+    _windows.splice(this.getEntryIndex(aWindow), 1);
+
+    // Remove the event listeners
+    TAB_EVENTS.forEach(function(event) {
+      aWindow.gBrowser.tabContainer.removeEventListener(event, _handleEvent, false);
+    });
+    WINDOW_EVENTS.forEach(function(event) {
+      aWindow.removeEventListener(event, _handleEvent, false);
+    });
+  },
+
+  onActivate: function(aWindow, aHasFocus) {
+    // If this window was the last focused window, we don't need to do anything
+    if (aWindow == _lastFocusedWindow)
+      return;
+
+    // handleFocusedWindow will deprioritize the current window
+    this.handleFocusedWindow(aWindow);
+
+    // Lastly we should increase priority for this window
+    this.increasePriority(aWindow);
+  },
+
+  handleFocusedWindow: function(aWindow) {
+    // If we have a last focused window, we need to deprioritize it first
+    if (_lastFocusedWindow)
+      this.decreasePriority(_lastFocusedWindow);
+
+    // aWindow is now focused
+    _lastFocusedWindow = aWindow;
+  },
+
+  // Auxiliary methods
+  increasePriority: function(aWindow) {
+    aWindow.gBrowser.browsers.forEach(function(aBrowser) {
+      BrowserHelper.increasePriority(aBrowser);
+    });
+  },
+
+  decreasePriority: function(aWindow) {
+    aWindow.gBrowser.browsers.forEach(function(aBrowser) {
+      BrowserHelper.decreasePriority(aBrowser);
+    });
+  },
+
+  getEntry: function(aWindow) {
+    return _windows[this.getEntryIndex(aWindow)];
+  },
+
+  getEntryIndex: function(aWindow) {
+    // Assumes that every object has a unique window & it's in the array
+    for (let i = 0; i < _windows.length; i++)
+      if (_windows[i].window == aWindow)
+        return i;
+  }
+};
+
--- a/browser/base/content/aboutDialog.xul
+++ b/browser/base/content/aboutDialog.xul
@@ -71,17 +71,17 @@
 #ifdef XP_UNIX
         creditsaccesskey="&copyrightGNOME.accesskey;"
 #else
         creditsaccesskey="&copyright.accesskey;"
 #endif
         aboutlabel="&aboutLink;"
         aboutaccesskey="&aboutLink.accesskey;">
     
-  <script type="application/x-javascript" src="chrome://browser/content/aboutDialog.js"/>
+  <script type="application/javascript" src="chrome://browser/content/aboutDialog.js"/>
 
   <deck id="modes" flex="1">
     <vbox flex="1" id="clientBox">
 #expand <label id="version" value="&aboutVersion; __MOZ_APP_VERSION__"/>
       <label id="distribution"/>
       <label id="distributionId"/>
       <description id="copyright">
         &copyrightInfo1;<label 
--- a/browser/base/content/aboutRobots.xhtml
+++ b/browser/base/content/aboutRobots.xhtml
@@ -62,17 +62,17 @@
 ]>
 
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>&robots.pagetitle;</title>
     <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all" />
     <link rel="icon" type="image/png" id="favicon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAACGFjVEwAAAASAAAAAJNtBPIAAAAaZmNUTAAAAAAAAAAQAAAAEAAAAAAAAAAALuAD6AABhIDeugAAALhJREFUOI2Nk8sNxCAMRDlGohauXFOMpfTiAlxICqAELltHLqlgctg1InzMRhpFAc%2BLGWTnmoeZYamt78zXdZmaQtQMADlnU0OIAlbmJUBEcO4bRKQY2rUXIPmAGnDuG%2FBx3%2FfvOPVaDUg%2BoAPUf1PArIMCSD5glMEsUGaG%2BkyAFWIBaCsKuA%2BHGCNijLgP133XgOEtaPFMy2vUolEGJoCIzBmoRUR9%2B7rxj16DZaW%2FmgtmxnJ8V3oAnApQwNS5zpcAAAAaZmNUTAAAAAEAAAAQAAAAEAAAAAAAAAAAAB4D6AIB52fclgAAACpmZEFUAAAAAjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9WF%2Bu8QAAABpmY1RMAAAAAwAAABAAAAAQAAAAAAAAAAAAHgPoAgEK8Q9%2FAAAAFmZkQVQAAAAEOI1jYBgFo2AUjAIIAAAEEAAB0xIn4wAAABpmY1RMAAAABQAAABAAAAAQAAAAAAAAAAAAHgPoAgHnO30FAAAAQGZkQVQAAAAGOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVfozYcAAAABpmY1RMAAAABwAAABAAAAAQAAAAAAAAAAAAHgPoAgEKra7sAAAAFmZkQVQAAAAIOI1jYBgFo2AUjAIIAAAEEAABM9s3hAAAABpmY1RMAAAACQAAABAAAAAQAAAAAAAAAAAAHgPoAgHn3p%2BwAAAAKmZkQVQAAAAKOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F1BhPl6AAAAGmZjVEwAAAALAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQpITFkAAAAWZmRBVAAAAAw4jWNgGAWjYBSMAggAAAQQAAHaszpmAAAAGmZjVEwAAAANAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeeCPiMAAABAZmRBVAAAAA44jWNgGJ5gpxrDf2LEcIL%2FpzAVYxPDavP%2FUwz%2FpW79%2F%2F%2F%2FFMP%2FnWoQjC5GOxcgu4QYsVEwCmAAAOE0KxUmBL0KAAAAGmZjVEwAAAAPAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQoU7coAAAAWZmRBVAAAABA4jWNgGAWjYBSMAggAAAQQAAEpOBELAAAAGmZjVEwAAAARAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeYVWtoAAAAqZmRBVAAAABI4jWNgGAVYQXNz839ixHBq3qnG8B9ZAzYx2rlgFIwCcgAA8psX%2FWvpAecAAAAaZmNUTAAAABMAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC4OJMwAAABZmZEFUAAAAFDiNY2AYBaNgFIwCCAAABBAAAcBQHOkAAAAaZmNUTAAAABUAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5kn7SQAAAEBmZEFUAAAAFjiNY2AYnmCnGsN%2FYsRwgv%2BnMBVjE8Nq8%2F9TDP%2Blbv3%2F%2F%2F8Uw%2F%2BdahCMLkY7FyC7hBixUTAKYAAA4TQrFc%2BcEoQAAAAaZmNUTAAAABcAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC98ooAAAABZmZEFUAAAAGDiNY2AYBaNgFIwCCAAABBAAASCZDI4AAAAaZmNUTAAAABkAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5qwZ%2FAAAACpmZEFUAAAAGjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9cjJWbAAAABpmY1RMAAAAGwAAABAAAAAQAAAAAAAAAAAAHgPoAgELOsoVAAAAFmZkQVQAAAAcOI1jYBgFo2AUjAIIAAAEEAAByfEBbAAAABpmY1RMAAAAHQAAABAAAAAQAAAAAAAAAAAAHgPoAgHm8LhvAAAAQGZkQVQAAAAeOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVlxR3%2FgAAABpmY1RMAAAAHwAAABAAAAAQAAAAAAAAAAAAHgPoAgELZmuGAAAAFmZkQVQAAAAgOI1jYBgFo2AUjAIIAAAEEAABHP5cFQAAABpmY1RMAAAAIQAAABAAAAAQAAAAAAAAAAAAHgPoAgHlgtAOAAAAKmZkQVQAAAAiOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F0%2FMvDdAAAAAElFTkSuQmCC"/>
 
-    <script type="application/x-javascript"><![CDATA[
+    <script type="application/javascript"><![CDATA[
       var buttonClicked = false;
       function robotButton()
       {
         var button = document.getElementById('errorTryAgain');
         if (buttonClicked) {
           button.style.visibility = "hidden";
         } else {
           var newLabel = button.getAttribute("label2");
--- a/browser/base/content/aboutSupport.xhtml
+++ b/browser/base/content/aboutSupport.xhtml
@@ -371,17 +371,17 @@ function generateTextForTextNode(node, i
   // If the text node is the first of a run of text nodes, then start
   // a new line and add the initial indentation.
   let prevNode = node.previousSibling;
   if (!prevNode || prevNode.nodeType == Node.TEXT_NODE)
     textFragmentAccumulator.push("\n" + indent);
 
   // Trim the text node's text content and add proper indentation after 
   // any internal line breaks.  
-  let text = node.textContent.trim().replace("\n[ \t]*", "\n" + indent);
+  let text = node.textContent.trim().replace("\n", "\n" + indent, "g");
   textFragmentAccumulator.push(text);
 }
 
 function openProfileDirectory() {
   // Get the profile directory.
   let propertiesService = Cc["@mozilla.org/file/directory_service;1"]
                             .getService(Ci.nsIProperties);
   let currProfD = propertiesService.get("ProfD", Ci.nsIFile);
--- a/browser/base/content/baseMenuOverlay.xul
+++ b/browser/base/content/baseMenuOverlay.xul
@@ -43,17 +43,17 @@
 %brandDTD;
 <!ENTITY % baseMenuOverlayDTD SYSTEM "chrome://browser/locale/baseMenuOverlay.dtd">
 %baseMenuOverlayDTD;
 ]>
 <overlay id="baseMenuOverlay"
          xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
-<script type="application/x-javascript" src="chrome://browser/content/utilityOverlay.js"/>
+<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
 
 #ifdef XP_MACOSX
 <!-- nsMenuBarX hides these and uses them to build the Application menu.
      When using Carbon widgets for Mac OS X widgets, some of these are not
      used as they only apply to Cocoa widget builds. All version of Firefox
      through Firefox 2 will use Carbon widgets. -->
     <menupopup id="menu_ToolsPopup">
         <menuitem id="menu_preferences" label="&preferencesCmdMac.label;" key="key_preferencesCmdMac" oncommand="openPreferences();"/>
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -17,16 +17,22 @@ toolbarpaletteitem[place="palette"] > to
   display: none;
 }
 
 #main-window:-moz-lwtheme {
   background-repeat: no-repeat;
   background-position: top right;
 }
 
+%ifdef XP_MACOSX
+#main-window[inFullscreen="true"] {
+  padding-top: 0; /* override drawintitlebar="true" */
+}
+%endif
+
 #browser-bottombox[lwthemefooter="true"] {
   background-repeat: no-repeat;
   background-position: bottom left;
 }
 
 /* ::::: location bar ::::: */
 #urlbar {
   -moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -677,18 +677,18 @@ let gGestureSupport = {
     const gestureEvents = ["SwipeGesture",
       "MagnifyGestureStart", "MagnifyGestureUpdate", "MagnifyGesture",
       "RotateGestureStart", "RotateGestureUpdate", "RotateGesture",
       "TapGesture", "PressTapGesture"];
 
     let addRemove = aAddListener ? window.addEventListener :
       window.removeEventListener;
 
-    for each (let event in gestureEvents)
-      addRemove("Moz" + event, this, true);
+    gestureEvents.forEach(function (event) addRemove("Moz" + event, this, true),
+                          this);
   },
 
   /**
    * Dispatch events based on the type of mouse gesture event. For now, make
    * sure to stop propagation of every gesture event so that web content cannot
    * receive gesture events.
    *
    * @param aEvent
@@ -866,19 +866,20 @@ let gGestureSupport = {
   /**
    * Convert the swipe gesture into a browser action based on the direction
    *
    * @param aEvent
    *        The swipe event to handle
    */
   onSwipe: function GS_onSwipe(aEvent) {
     // Figure out which one (and only one) direction was triggered 
-    for each (let dir in ["UP", "RIGHT", "DOWN", "LEFT"])
+    ["UP", "RIGHT", "DOWN", "LEFT"].forEach(function (dir) {
       if (aEvent.direction == aEvent["DIRECTION_" + dir])
         return this._doAction(aEvent, ["swipe", dir.toLowerCase()]);
+    }, this);
   },
 
   /**
    * Get a gesture preference or use a default if it doesn't exist
    *
    * @param aPref
    *        Name of the preference to load under the gesture branch
    * @param aDef
@@ -1281,16 +1282,20 @@ function delayedStartup(isLoadingBlank, 
   // apply full zoom settings to tabs restored by the session restore service.
   try {
     FullZoom.init();
   }
   catch(ex) {
     Components.utils.reportError("Failed to init content pref service:\n" + ex);
   }
 
+  let NP = {};
+  Cu.import("resource://gre/modules/NetworkPrioritizer.jsm", NP);
+  NP.trackBrowserWindow(window);
+
   // initialize the session-restore service (in case it's not already running)
   if (document.documentElement.getAttribute("windowtype") == "navigator:browser") {
     try {
       var ss = Cc["@mozilla.org/browser/sessionstore;1"].
                getService(Ci.nsISessionStore);
       ss.init(window);
     } catch(ex) {
       dump("nsSessionStore could not be initialized: " + ex + "\n");
@@ -2079,25 +2084,38 @@ function BrowserViewSourceOfDocument(aDo
     // If no page descriptor is available, just use the view-source URL...
   }
 
   top.gViewSourceUtils.viewSource(webNav.currentURI.spec, pageCookie, aDocument);
 }
 
 // doc - document to use for source, or null for this window's document
 // initialTab - name of the initial tab to display, or null for the first tab
-// imageUrl - url of an image to load in the Media Tab of the Page Info window; can be null/omitted
-function BrowserPageInfo(doc, initialTab, imageUrl)
-{
-  var args = {doc: doc, initialTab: initialTab, imageUrl: imageUrl};
-  return toOpenDialogByTypeAndUrl("Browser:page-info",
-                                  doc ? doc.location : window.content.document.location,
-                                  "chrome://browser/content/pageinfo/pageInfo.xul",
-                                  "chrome,toolbar,dialog=no,resizable",
-                                  args);
+// imageElement - image to load in the Media Tab of the Page Info window; can be null/omitted
+function BrowserPageInfo(doc, initialTab, imageElement) {
+  var args = {doc: doc, initialTab: initialTab, imageElement: imageElement};
+  var windows = Cc['@mozilla.org/appshell/window-mediator;1']
+                  .getService(Ci.nsIWindowMediator)
+                  .getEnumerator("Browser:page-info");
+
+  var documentURL = doc ? doc.location : window.content.document.location;
+
+  // Check for windows matching the url
+  while (windows.hasMoreElements()) {
+    var currentWindow = windows.getNext();
+    if (currentWindow.document.documentElement.getAttribute("relatedUrl") == documentURL) {
+      currentWindow.focus();
+      currentWindow.resetPageInfo(args);
+      return currentWindow;
+    }
+  }
+
+  // We didn't find a matching window, so open a new one.
+  return openDialog("chrome://browser/content/pageinfo/pageInfo.xul", "",
+                    "chrome,toolbar,dialog=no,resizable", args);
 }
 
 #ifdef DEBUG
 // Initialize the LeakDetector class.
 function LeakDetector(verbose)
 {
   this.verbose = verbose;
 }
@@ -2625,31 +2643,31 @@ function FillInHTMLTooltip(tipElement)
         .getPropertyValue("direction");
     }
     tipElement = tipElement.parentNode;
   }
 
   var tipNode = document.getElementById("aHTMLTooltip");
   tipNode.style.direction = direction;
   
-  for each (var t in [titleText, XLinkTitleText]) {
+  [titleText, XLinkTitleText].forEach(function (t) {
     if (t && /\S/.test(t)) {
 
       // Per HTML 4.01 6.2 (CDATA section), literal CRs and tabs should be
       // replaced with spaces, and LFs should be removed entirely.
       // XXX Bug 322270: We don't preserve the result of entities like &#13;,
       // which should result in a line break in the tooltip, because we can't
       // distinguish that from a literal character in the source by this point.
       t = t.replace(/[\r\t]/g, ' ');
       t = t.replace(/\n/g, '');
 
       tipNode.setAttribute("label", t);
       retVal = true;
     }
-  }
+  });
 
   return retVal;
 }
 
 var browserDragAndDrop = {
   getDragURLFromDataTransfer : function (dt)
   {
     var types = dt.types;
@@ -3244,38 +3262,16 @@ function toOpenWindowByType(inType, uri,
   if (topWindow)
     topWindow.focus();
   else if (features)
     window.open(uri, "_blank", features);
   else
     window.open(uri, "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar");
 }
 
-function toOpenDialogByTypeAndUrl(inType, relatedUrl, windowUri, features, extraArgument)
-{
-  var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
-  var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
-  var windows = windowManagerInterface.getEnumerator(inType);
-
-  // Check for windows matching the url
-  while (windows.hasMoreElements()) {
-    var currentWindow = windows.getNext();
-    if (currentWindow.document.documentElement.getAttribute("relatedUrl") == relatedUrl) {
-    	currentWindow.focus();
-    	return;
-    }
-  }
-
-  // We didn't find a matching window, so open a new one.
-  if (features)
-    return window.openDialog(windowUri, "_blank", features, extraArgument);
-
-  return window.openDialog(windowUri, "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar", extraArgument);
-}
-
 function OpenBrowserWindow()
 {
   var charsetArg = new String();
   var handler = Components.classes["@mozilla.org/browser/clh;1"]
                           .getService(Components.interfaces.nsIBrowserHandler);
   var defaultArgs = handler.defaultArgs;
   var wintype = document.documentElement.getAttribute('windowtype');
 
@@ -3765,20 +3761,23 @@ var FullScreen =
         // so that new windows don't have missing toolbars
         if (aShow)
           els[i].removeAttribute("moz-collapsed");
         else
           els[i].setAttribute("moz-collapsed", "true");
       }
     }
 
-    if (aShow)
+    if (aShow) {
       gNavToolbox.removeAttribute("inFullscreen");
-    else
+      document.documentElement.removeAttribute("inFullscreen");
+    } else {
       gNavToolbox.setAttribute("inFullscreen", true);
+      document.documentElement.setAttribute("inFullscreen", true);
+    }
 
     var controls = document.getElementsByAttribute("fullscreencontrol", "true");
     for (var i = 0; i < controls.length; ++i)
       controls[i].hidden = aShow;
   }
 };
 
 /**
@@ -5456,19 +5455,19 @@ var OfflineApps = {
            Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN);
   },
 
   // XXX: duplicated in preferences/advanced.js
   _getOfflineAppUsage: function (host, groups)
   {
     var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
                        getService(Components.interfaces.nsIApplicationCacheService);
-    if (!groups) {
-      groups = cacheService.getGroups({});
-    }
+    if (!groups)
+      groups = cacheService.getGroups();
+
     var ios = Components.classes["@mozilla.org/network/io-service;1"].
               getService(Components.interfaces.nsIIOService);
 
     var usage = 0;
     for (var i = 0; i < groups.length; i++) {
       var uri = ios.newURI(groups[i], null, null);
       if (uri.asciiHost == host) {
         var cache = cacheService.getActiveCache(groups[i]);
@@ -5933,16 +5932,17 @@ var gMissingPluginInstaller = {
 
     function showBlocklistInfo() {
       var url = formatURL("extensions.blocklist.detailsURL", true);
       gBrowser.loadOneTab(url, {inBackground: false});
       return true;
     }
 
     function showOutdatedPluginsInfo() {
+      gPrefService.setBoolPref("plugins.update.notifyUser", false);
       var url = formatURL("plugins.update.url", true);
       gBrowser.loadOneTab(url, {inBackground: false});
       return true;
     }
 
     function showPluginsMissing() {
       // get the urls of missing plugins
       var missingPluginsArray = gBrowser.selectedBrowser.missingPlugins;
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -87,22 +87,22 @@
         browsingmode="normal"
         toggletoolbar="true"
         persist="screenX screenY width height sizemode"> 
 
 # All JS files which are not content (only) dependent that browser.xul
 # wishes to include *must* go into the global-scripts.inc file
 # so that they can be shared by macBrowserOverlay.xul.
 #include global-scripts.inc
-<script type="application/x-javascript" src="chrome://browser/content/nsContextMenu.js"/>
+<script type="application/javascript" src="chrome://browser/content/nsContextMenu.js"/>
 
 #ifdef MOZ_SAFE_BROWSING
-<script type="application/x-javascript" src="chrome://browser/content/safebrowsing/sb-loader.js"/>
+<script type="application/javascript" src="chrome://browser/content/safebrowsing/sb-loader.js"/>
 #endif
-<script type="application/x-javascript" src="chrome://global/content/contentAreaUtils.js"/>
+<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
 
 <script type="application/javascript" src="chrome://browser/content/places/editBookmarkOverlay.js"/>
 
 # All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the 
 # browser-sets.inc file for sharing with hiddenWindow.xul.
 #include browser-sets.inc
 
   <popupset id="mainPopupSet">
--- a/browser/base/content/credits.xhtml
+++ b/browser/base/content/credits.xhtml
@@ -159,18 +159,18 @@
         list-style-type: none;
       }
 
       .center {
         text-align: center;
       }
     </style>
 
-    <script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"></script>
-    <script type="application/x-javascript">
+    <script type="application/javascript" src="chrome://global/content/globalOverlay.js"></script>
+    <script type="application/javascript">
     <![CDATA[
 
       var gCreditsInterval = -1;
 
       function uninit()
       {
         if (gCreditsInterval > -1)
           clearInterval(gCreditsInterval);
--- a/browser/base/content/global-scripts.inc
+++ b/browser/base/content/global-scripts.inc
@@ -32,13 +32,13 @@
 # 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 *****
 
-<script type="application/x-javascript" src="chrome://global/content/printUtils.js"/>
-<script type="application/x-javascript" src="chrome://global/content/viewZoomOverlay.js"/>
-<script type="application/x-javascript" src="chrome://browser/content/browser.js"/>
-<script type="application/x-javascript" src="chrome://global/content/inlineSpellCheckUI.js"/>
-<script type="application/x-javascript" src="chrome://global/content/viewSourceUtils.js"/>
+<script type="application/javascript" src="chrome://global/content/printUtils.js"/>
+<script type="application/javascript" src="chrome://global/content/viewZoomOverlay.js"/>
+<script type="application/javascript" src="chrome://browser/content/browser.js"/>
+<script type="application/javascript" src="chrome://global/content/inlineSpellCheckUI.js"/>
+<script type="application/javascript" src="chrome://global/content/viewSourceUtils.js"/>
--- a/browser/base/content/macBrowserOverlay.xul
+++ b/browser/base/content/macBrowserOverlay.xul
@@ -55,17 +55,17 @@
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
 # All JS files which are not content (only) dependent that browser.xul
 # wishes to include *must* go into the global-scripts.inc file
 # so that they can be shared by this overlay.
 #include global-scripts.inc
 
-<script type="application/x-javascript">
+<script type="application/javascript">
   addEventListener("load", nonBrowserWindowStartup, false);
   addEventListener("unload", nonBrowserWindowShutdown, false);
 </script>
 
 # All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the 
 # browser-sets.inc file for sharing with hiddenWindow.xul.
 #include browser-sets.inc
 
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -139,28 +139,74 @@ nsContextMenu.prototype = {
       var mailtoHandler = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
                           getService(Ci.nsIExternalProtocolService).
                           getProtocolHandlerInfo("mailto");
       isMailtoInternal = (!mailtoHandler.alwaysAskBeforeHandling &&
                           mailtoHandler.preferredAction == Ci.nsIHandlerInfo.useHelperApp &&
                           (mailtoHandler.preferredApplicationHandler instanceof Ci.nsIWebHandlerApp));
     }
 
-    // time to do some bad things and see if we've highlighted a URL that isn't actually linked
+    // Time to do some bad things and see if we've highlighted a URL that
+    // isn't actually linked.
+    var onPlainTextLink = false;
     if (this.isTextSelected) {
-      // ok, we have some text, let's figure out if it looks like a URL
-      var someText = document.commandDispatcher.focusedWindow
-                             .getSelection().toString();
-      try {
-       var uri = makeURI(someText);
+      // Ok, we have some text, let's figure out if it looks like a URL.
+      let selection =  document.commandDispatcher.focusedWindow
+                               .getSelection();
+      let linkText = selection.toString().trim();
+      let uri;
+      if (/^(?:https?|ftp):/i.test(linkText)) {
+        try {
+          uri = makeURI(linkText);
+        } catch (ex) {}
       }
-      catch (ex) { }
- 
-      var onPlainTextLink = false;
-      if (uri && /^(https?|ftp)$/i.test(uri.scheme) && uri.host) {
+      // Check if this could be a valid url, just missing the protocol.
+      else if (/^(?:\w+\.)+\D\S*$/.test(linkText)) {
+        // Now let's see if this is an intentional link selection. Our guess is
+        // based on whether the selection begins/ends with whitespace or is
+        // preceded/followed by a non-word character.
+
+        // selection.toString() trims trailing whitespace, so we look for
+        // that explicitly in the first and last ranges.
+        let beginRange = selection.getRangeAt(0);
+        let delimitedAtStart = /^\s/.test(beginRange);
+        if (!delimitedAtStart) {
+          let container = beginRange.startContainer;
+          let offset = beginRange.startOffset;
+          if (container.nodeType == Node.TEXT_NODE && offset > 0)
+            delimitedAtStart = /\W/.test(container.textContent[offset - 1]);
+          else
+            delimitedAtStart = true;
+        }
+
+        let delimitedAtEnd = false;
+        if (delimitedAtStart) {
+          let endRange = selection.getRangeAt(selection.rangeCount - 1);
+          delimitedAtEnd = /\s$/.test(endRange);
+          if (!delimitedAtEnd) {
+            let container = endRange.endContainer;
+            let offset = endRange.endOffset;
+            if (container.nodeType == Node.TEXT_NODE &&
+                offset < container.textContent.length)
+              delimitedAtEnd = /\W/.test(container.textContent[offset]);
+            else
+              delimitedAtEnd = true;
+          }
+        }
+
+        if (delimitedAtStart && delimitedAtEnd) {
+          let uriFixup = Cc["@mozilla.org/docshell/urifixup;1"]
+                           .getService(Ci.nsIURIFixup);
+          try {
+            uri = uriFixup.createFixupURI(linkText, uriFixup.FIXUP_FLAG_NONE);
+          } catch (ex) {}
+        }
+      }
+
+      if (uri && uri.host) {
         this.linkURI = uri;
         this.linkURL = this.linkURI.spec;
         onPlainTextLink = true;
       }
     }
  
     var shouldShow = this.onSaveableLink || isMailtoInternal || onPlainTextLink;
     this.showItem("context-openlink", shouldShow);
@@ -253,17 +299,17 @@ nsContextMenu.prototype = {
     this.setItemAttr("context-viewvideo",  "disabled", !this.mediaURL);
 
     // View background image depends on whether there is one.
     this.showItem("context-viewbgimage", shouldShow && !this._hasMultipleBGImages);
     this.showItem("context-sep-viewbgimage", shouldShow && !this._hasMultipleBGImages);
     document.getElementById("context-viewbgimage")
             .disabled = !this.hasBGImage;
 
-    this.showItem("context-viewimageinfo", (this.onImage));
+    this.showItem("context-viewimageinfo", this.onImage);
   },
 
   initMiscItems: function CM_initMiscItems() {
     var isTextSelected = this.isTextSelected;
     
     // Use "Bookmark This Link" if on a link.
     this.showItem("context-bookmarkpage",
                   !(this.isContentSelected || this.onTextInput || this.onLink ||
@@ -774,17 +820,18 @@ nsContextMenu.prototype = {
     BrowserViewSourceOfDocument(this.target.ownerDocument);
   },
 
   viewInfo: function() {
     BrowserPageInfo(this.target.ownerDocument.defaultView.top.document);
   },
 
   viewImageInfo: function() {
-    BrowserPageInfo(this.target.ownerDocument.defaultView.top.document,"mediaTab",this.mediaURL);
+    BrowserPageInfo(this.target.ownerDocument.defaultView.top.document,
+                    "mediaTab", this.target);
   },
 
   viewFrameInfo: function() {
     BrowserPageInfo(this.target.ownerDocument);
   },
 
   reloadImage: function(e) {
     urlSecurityCheck(this.mediaURL,
--- a/browser/base/content/openLocation.xul
+++ b/browser/base/content/openLocation.xul
@@ -49,19 +49,19 @@
         onload="onLoad()"
         buttonlabelaccept="&openBtn.label;"
         buttoniconaccept="open"
         ondialogaccept="open()"
         style="width: 40em;"
         persist="screenX screenY"
         screenX="24" screenY="24">
               
-  <script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"/> 
-  <script type="application/x-javascript" src="chrome://browser/content/openLocation.js"/>
-  <script type="application/x-javascript" src="chrome://browser/content/utilityOverlay.js"/>
+  <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/> 
+  <script type="application/javascript" src="chrome://browser/content/openLocation.js"/>
+  <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
   
   <stringbundle id="openLocationBundle" src="chrome://browser/locale/openLocation.properties"/>
 
   <hbox>
     <separator orient="vertical" class="thin"/>
     <vbox flex="1">
       <description>&enter.label;</description>
       <separator class="thin"/>
--- a/browser/base/content/openLocationLastURL.jsm
+++ b/browser/base/content/openLocationLastURL.jsm
@@ -83,12 +83,13 @@ let gOpenLocationLastURL = {
     else {
       let str = Components.classes["@mozilla.org/supports-string;1"]
                           .createInstance(Components.interfaces.nsISupportsString);
       str.data = val;
       prefSvc.setComplexValue(LAST_URL_PREF, nsISupportsString, str);
     }
   },
   reset: function() {
-    prefSvc.clearUserPref(LAST_URL_PREF);
+    if (prefSvc.prefHasUserValue(LAST_URL_PREF))
+        prefSvc.clearUserPref(LAST_URL_PREF);
     gOpenLocationLastURLData = "";
   }
 };
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -143,17 +143,17 @@ pageInfoTreeView.prototype = {
   isSelectable: function(row, column) { return false; },
   performAction: function(action) { },
   performActionOnCell: function(action, row, column) { }
 };
 
 // mmm, yummy. global variables.
 var gWindow = null;
 var gDocument = null;
-var gImageUrl = null;
+var gImageElement = null;
 
 // column number to help using the data array
 const COL_IMAGE_ADDRESS = 0;
 const COL_IMAGE_TYPE    = 1;
 const COL_IMAGE_SIZE    = 2;
 const COL_IMAGE_ALT     = 3;
 const COL_IMAGE_COUNT   = 4;
 const COL_IMAGE_NODE    = 5;
@@ -274,51 +274,26 @@ function onLoadPageInfo()
   gStrings.notSet = gBundle.getString("notset");
   gStrings.mediaImg = gBundle.getString("mediaImg");
   gStrings.mediaBGImg = gBundle.getString("mediaBGImg");
   gStrings.mediaObject = gBundle.getString("mediaObject");
   gStrings.mediaEmbed = gBundle.getString("mediaEmbed");
   gStrings.mediaLink = gBundle.getString("mediaLink");
   gStrings.mediaInput = gBundle.getString("mediaInput");
 
-  if ("arguments" in window && window.arguments.length >= 1 &&
-       window.arguments[0] && window.arguments[0].doc) {
-    gDocument = window.arguments[0].doc;
-    gWindow = gDocument.defaultView;
-  }
-  else {
-    if ("gBrowser" in window.opener)
-      gWindow = window.opener.gBrowser.contentWindow;
-    else
-      gWindow = window.opener.frames[0];
-    gDocument = gWindow.document;
-  }
+  var args = "arguments" in window &&
+             window.arguments.length >= 1 &&
+             window.arguments[0];
 
   // init media view
   var imageTree = document.getElementById("imagetree");
   imageTree.view = gImageView;
 
-  // set gImageUrl if present
-  if ("arguments" in window && window.arguments.length >= 1 &&
-       window.arguments[0] && window.arguments[0].imageUrl)
-    gImageUrl = window.arguments[0].imageUrl;
-
-  // build the content
-  loadPageInfo();
-
   /* Select the requested tab, if the name is specified */
-  var initialTab = "generalTab";
-  if ("arguments" in window && window.arguments.length >= 1 &&
-       window.arguments[0] && window.arguments[0].initialTab)
-    initialTab = window.arguments[0].initialTab;
-  var radioGroup = document.getElementById("viewGroup");
-  initialTab = document.getElementById(initialTab) || document.getElementById("generalTab");
-  radioGroup.selectedItem = initialTab;
-  radioGroup.selectedItem.doCommand();
-  radioGroup.focus();
+  loadTab(args);
   Components.classes["@mozilla.org/observer-service;1"]
             .getService(Components.interfaces.nsIObserverService)
             .notifyObservers(window, "page-info-dialog-loaded", null);
 }
 
 function loadPageInfo()
 {
   var titleFormat = gWindow != gWindow.top ? "pageInfo.frame.title"
@@ -335,17 +310,17 @@ function loadPageInfo()
 
   initFeedTab();
   onLoadPermission();
 
   /* Call registered overlay init functions */
   onLoadRegistry.forEach(function(func) { func(); });
 }
 
-function resetPageInfo()
+function resetPageInfo(args)
 {
   /* Reset Meta tags part */
   gMetaView.clear();
 
   /* Reset Media tab */
   var mediaTab = document.getElementById("mediaTab");
   if (!mediaTab.hidden) {
     Components.classes["@mozilla.org/observer-service;1"]
@@ -359,18 +334,17 @@ function resetPageInfo()
   /* Reset Feeds Tab */
   var feedListbox = document.getElementById("feedListbox");
   while (feedListbox.firstChild)
     feedListbox.removeChild(feedListbox.firstChild);
 
   /* Call registered overlay reset functions */
   onResetRegistry.forEach(function(func) { func(); });
 
-  /* And let's rebuild the data */
-  loadPageInfo();
+  loadTab(args);
 }
 
 function onUnloadPageInfo()
 {
   // Remove the observer, only if there is at least 1 image.
   if (!document.getElementById("mediaTab").hidden) {
     Components.classes["@mozilla.org/observer-service;1"]
               .getService(Components.interfaces.nsIObserverService)
@@ -398,16 +372,47 @@ function doHelpButton()
 
 function showTab(id)
 {
   var deck  = document.getElementById("mainDeck");
   var pagel = document.getElementById(id + "Panel");
   deck.selectedPanel = pagel;
 }
 
+function loadTab(args)
+{
+  if (args && args.doc) {
+    gDocument = args.doc;
+    gWindow = gDocument.defaultView;
+  }
+  else {
+    if ("gBrowser" in window.opener)
+      gWindow = window.opener.gBrowser.contentWindow;
+    else
+      gWindow = window.opener.frames[0];
+    gDocument = gWindow.document;
+  }
+
+  if (args && args.imageElement)
+    gImageElement = args.imageElement;
+
+  /* Rebuild the data */
+  gImageElement = args && args.imageElement;
+
+  /* Load the page info */
+  loadPageInfo();
+
+  var initialTab = (args && args.initialTab) || "generalTab";
+  var radioGroup = document.getElementById("viewGroup");
+  initialTab = document.getElementById(initialTab) || document.getElementById("generalTab");
+  radioGroup.selectedItem = initialTab;
+  radioGroup.selectedItem.doCommand();
+  radioGroup.focus();
+}
+
 function onClickMore()
 {
   var radioGrp = document.getElementById("viewGroup");
   var radioElt = document.getElementById("securityTab");
   radioGrp.selectedItem = radioElt;
   showTab('security');
 }
 
@@ -526,17 +531,17 @@ function goThroughFrames(aDocument, aWin
 function processFrames()
 {
   if (gFrameList.length) {
     var doc = gFrameList[0];
     onProcessFrame.forEach(function(func) { func(doc); });
     var iterator = doc.createTreeWalker(doc, NodeFilter.SHOW_ELEMENT, grabAll, true);
     gFrameList.shift();
     setTimeout(doGrab, 16, iterator);
-    onFinished.push(selectImgUrl);
+    onFinished.push(selectImage);
   }
   else
     onFinished.forEach(function(func) { func(); });
 }
 
 function doGrab(iterator)
 {
   for (var i = 0; i < 50; ++i)
@@ -1166,21 +1171,20 @@ function doCopy()
 function doSelectAll()
 {
   var elem = document.commandDispatcher.focusedElement;
 
   if (elem && "treeBoxObject" in elem)
     elem.view.selection.selectAll();
 }
 
-function selectImgUrl ()
-{
-  if (gImageUrl) {
-    var tree = document.getElementById("imagetree");
-    for (var c = 0; c < tree.view.rowCount; c++)
-    {
-      if (gImageUrl == gImageView.data[c][COL_IMAGE_ADDRESS]) {
-        tree.view.selection.select(c);
-        return;
-      }
+function selectImage() {
+  if (!gImageElement)
+    return;
+
+  var tree = document.getElementById("imagetree");
+  for (var i = 0; i < tree.view.rowCount; i++) {
+    if (gImageElement == gImageView.data[i][COL_IMAGE_NODE]) {
+      tree.view.selection.select(i);
+      return;
     }
   }
 }
--- a/browser/base/content/pageinfo/pageInfo.xul
+++ b/browser/base/content/pageinfo/pageInfo.xul
@@ -59,23 +59,23 @@
   windowtype="Browser:page-info"
   onload="onLoadPageInfo()"
   onunload="onUnloadPageInfo()"
   align="stretch"
   screenX="10" screenY="10"
   width="&pageInfoWindow.width;" height="&pageInfoWindow.height;"
   persist="screenX screenY width height sizemode">
 
-  <script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"/>
-  <script type="application/x-javascript" src="chrome://global/content/contentAreaUtils.js"/>
-  <script type="application/x-javascript" src="chrome://browser/content/pageinfo/pageInfo.js"/>
-  <script type="application/x-javascript" src="chrome://browser/content/pageinfo/feeds.js"/>
-  <script type="application/x-javascript" src="chrome://browser/content/pageinfo/permissions.js"/>
-  <script type="application/x-javascript" src="chrome://browser/content/pageinfo/security.js"/>
-  <script type="application/x-javascript" src="chrome://browser/content/utilityOverlay.js"/>
+  <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
+  <script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
+  <script type="application/javascript" src="chrome://browser/content/pageinfo/pageInfo.js"/>
+  <script type="application/javascript" src="chrome://browser/content/pageinfo/feeds.js"/>
+  <script type="application/javascript" src="chrome://browser/content/pageinfo/permissions.js"/>
+  <script type="application/javascript" src="chrome://browser/content/pageinfo/security.js"/>
+  <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
 
   <stringbundleset id="pageinfobundleset">
     <stringbundle id="pageinfobundle" src="chrome://browser/locale/pageInfo.properties"/>
     <stringbundle id="pkiBundle" src="chrome://pippki/locale/pippki.properties"/>
   </stringbundleset>
 
   <commandset id="pageInfoCommandSet">
     <command id="cmd_close"     oncommand="window.close();"/>
--- a/browser/base/content/safeMode.js
+++ b/browser/base/content/safeMode.js
@@ -85,17 +85,18 @@ function disableAddons() {
   var type = nsIUpdateItem.TYPE_EXTENSION + nsIUpdateItem.TYPE_LOCALE;
   var items = em.getItemList(type, { });
   for (var i = 0; i < items.length; ++i)
     em.disableItem(items[i].id);
 
   // Select the default theme
   var prefB = Components.classes["@mozilla.org/preferences-service;1"]
                         .getService(Components.interfaces.nsIPrefBranch);
-  prefB.clearUserPref("general.skins.selectedSkin");
+  if (prefB.prefHasUserValue("general.skins.selectedSkin"))
+    prefB.clearUserPref("general.skins.selectedSkin");
 
   // Disable plugins
   var phs = Components.classes["@mozilla.org/plugin/host;1"]
                       .getService(Components.interfaces.nsIPluginHost);
   var plugins = phs.getPluginTags({ });
   for (i = 0; i < plugins.length; ++i)
     plugins[i].disabled = true;
 }
--- a/browser/base/content/safeMode.xul
+++ b/browser/base/content/safeMode.xul
@@ -62,17 +62,17 @@
             buttonlabelextra1="&continueButton.label;"
             width="&window.width;"
             ondialogaccept="onOK()"
             ondialogcancel="onCancel()"
             ondialogextra1="window.close()"
             onload="onLoad();"
             buttondisabledaccept="true">
 
-  <script type="application/x-javascript" src="chrome://browser/content/safeMode.js"/>
+  <script type="application/javascript" src="chrome://browser/content/safeMode.js"/>
 
   <stringbundle id="preferencesBundle" src="chrome://browser/locale/preferences/preferences.properties"/>
 
   <description>&safeModeDescription.label;</description>
 
   <separator class="thin"/>
 
   <label value="&safeModeDescription2.label;"/>
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -867,20 +867,16 @@
               return;
 
             // Preview mode should not reset the owner
             if (!this._previewMode && this.mCurrentTab != this.selectedTab)
               this.mCurrentTab.owner = null;
 
             this._lastRelatedTab = null;
 
-            var fm = Components.classes["@mozilla.org/focus-manager;1"].
-                       getService(Components.interfaces.nsIFocusManager);
-            var focusedChromeElement = fm.getFocusedElementForWindow(window, false, {});
-
             var oldBrowser = this.mCurrentBrowser;
             if (oldBrowser)
               oldBrowser.setAttribute("type", "content-targetable");
 
             var updatePageReport = false;
             if (!oldBrowser ||
                 (oldBrowser.pageReport && !newBrowser.pageReport) ||
                 (!oldBrowser.pageReport && newBrowser.pageReport))
@@ -965,23 +961,20 @@
             // that might rely upon the other changes suppressed.
             // Focus is suppressed in the event that the main browser window is minimized - focusing a tab would restore the window
             if (!this._previewMode) {
               // We've selected the new tab, so go ahead and notify listeners.
               var event = document.createEvent("Events");
               event.initEvent("TabSelect", true, false);
               this.mCurrentTab.dispatchEvent(event);
 
-              // change focus to the new tab if nothing is focused, the old tab
-              // is focused or there is something in the new tab to focus. One
-              // specific case where focus is not changed is when the new tab
-              // has no focused element and a chrome element is focused.
-              if ((!focusedChromeElement || focusedChromeElement == oldBrowser ||
-                  fm.getFocusedElementForWindow(window.content, true, {})))
-                fm.setFocus(newBrowser, fm.FLAG_NOSCROLL);
+              // Change focus to the new browser unless the findbar is focused.
+              if (gFindBar.hidden ||
+                  gFindBar.getElement("findbar-textbox").getAttribute("focused") != "true")
+                newBrowser.focus();
             }
           ]]>
         </body>
       </method>
 
       <method name="onTabClick">
         <parameter name="event"/>
         <body>
@@ -2925,17 +2918,17 @@
             <xul:menupopup class="tabs-alltabs-popup" anonid="alltabs-popup"
                            position="after_end"/>
           </xul:toolbarbutton>
           <xul:toolbarbutton anonid="tabs-closebutton"
                              class="close-button tabs-closebutton"/>
         </xul:hbox>
       </xul:stack>
     </content>
-    <implementation implements="nsITimerCallback, nsIDOMEventListener">
+    <implementation implements="nsIDOMEventListener">
       <constructor>
         <![CDATA[
           var pb2 =
               Components.classes['@mozilla.org/preferences-service;1'].
               getService(Components.interfaces.nsIPrefBranch2);
 
           try {
             this.mTabMinWidth = pb2.getIntPref("browser.tabs.tabMinWidth");
@@ -2966,22 +2959,16 @@
       </constructor>
 
       <destructor>
         <![CDATA[
           var pb2 =
               Components.classes['@mozilla.org/preferences-service;1'].
               getService(Components.interfaces.nsIPrefBranch2);
           pb2.removeObserver("browser.tabs.closeButtons", this._prefObserver);
-
-          // Release timer to avoid reference cycles.
-          if (this._animateTimer) {
-            this._animateTimer.cancel();
-            this._animateTimer = null;
-          }
         ]]>
       </destructor>
 
       <field name="mTabstripWidth">0</field>
 
       <field name="mTabstrip">
         document.getAnonymousElementByAttribute(this, "anonid", "arrowscrollbox");
       </field>
@@ -3101,43 +3088,16 @@
       <field name="mAllTabsPopup">
         document.getAnonymousElementByAttribute(this, 
                                                 "anonid", "alltabs-popup");
       </field>
 
       <field name="_animateElement">
         this.mTabstrip._scrollButtonDown;
       </field>
-
-      <field name="_animateTimer">null</field>
-      <field name="_animateBaseOpacity">null</field>
-      <field name="_animateBaseColor">null</field>
-      <field name="_animateStep">-1</field>
-      <field name="_animateDelay">25</field>
-      <field name="_animatePercents">
-       [1.00, 0.85, 0.80, 0.75, 0.71, 0.68, 0.65, 0.62, 0.59, 0.57,
-        0.54, 0.52, 0.50, 0.47, 0.45, 0.44, 0.42, 0.40, 0.38, 0.37,
-        0.35, 0.34, 0.32, 0.31, 0.30, 0.29, 0.28, 0.27, 0.26, 0.25,
-        0.24, 0.23, 0.23, 0.22, 0.22, 0.21, 0.21, 0.21, 0.20, 0.20,
-        0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.19, 0.19, 0.19, 0.18,
-        0.18, 0.17, 0.17, 0.16, 0.15, 0.14, 0.13, 0.11, 0.09, 0.06]
-      </field>
-
-      <method name="_stopAnimation">
-        <body><![CDATA[
-          if (this._animateStep != -1) {
-            if (this._animateTimer)
-              this._animateTimer.cancel();
-
-            this._animateStep = -1;
-            this._animateElement.style.outlineColor = "";
-            this._animateElement.style.outlineStyle = "";
-          }
-        ]]></body>
-      </method>
       
       <method name="_notifyBackgroundTab">
         <parameter name="aTab"/>
         <body><![CDATA[
           var scrollRect = this.mTabstrip.scrollClientRect;
           var tab = aTab.getBoundingClientRect();
 
           // Is the new tab already completely visible?
@@ -3154,64 +3114,22 @@
               return;
             }
 
             this.mTabstrip._smoothScrollByPixels(this.mTabstrip._isRTLScrollbox ?
                                                  selected.right - scrollRect.right :
                                                  selected.left - scrollRect.left);
           }
 
-          this._stopAnimation();
-
-          const DEFAULT_OPACITY = .7;
-          var self = this;
-          this._animateBaseColor =
-            window.getComputedStyle(this._animateElement, null)
-                  .outlineColor
-                  .replace(/^rgb\((.*)\)$/, "rgba($1, " + DEFAULT_OPACITY + ")")
-                  .replace(/([^, ]*)\)/, function (m0, m1) {
-                    self._animateBaseOpacity = parseFloat(m1);
-                    return "$opacity)";
-                  });
-
-          // start the flash timer
-          this._animateStep = 0;
-
-          var outlineWidth =
-            Math.ceil(Math.min(this._animateElement.clientHeight,
-                               this._animateElement.clientWidth) * .6) + "px";
-          this._animateElement.style.outlineWidth = outlineWidth;
-          this._animateElement.style.outlineOffset = "-" + outlineWidth;
-          this._animateElement.style.outlineColor = "rgba(0,0,0,0)";
-          this._animateElement.style.outlineStyle = "solid";
-
-          if (!this._animateTimer) 
-            this._animateTimer =
-              Components.classes["@mozilla.org/timer;1"]
-                        .createInstance(Components.interfaces.nsITimer);
-
-          this._animateTimer.initWithCallback(this, this._animateDelay,
-                                              this._animateTimer.TYPE_REPEATING_SLACK);
-        ]]></body>
-      </method>
-
-      <method name="notify">
-        <parameter name="aTimer"/>
-        <body><![CDATA[
-          if (!document)
-            aTimer.cancel();
-
-          var opacity = this._animateBaseOpacity * this._animatePercents[this._animateStep];
-          this._animateElement.style.outlineColor =
-            this._animateBaseColor.replace("$opacity", opacity);
-
-          if (this._animateStep < (this._animatePercents.length - 1))
-            this._animateStep++;
-          else
-            this._stopAnimation();
+          if (!this._animateElement.hasAttribute("notifybgtab")) {
+            this._animateElement.setAttribute("notifybgtab", "true");
+            setTimeout(function (ele) {
+              ele.removeAttribute("notifybgtab");
+            }, 150, this._animateElement);
+          }
         ]]></body>
       </method>
     </implementation>
     <handlers>
       <handler event="TabSelect" action="this._handleTabSelect();"/>
     </handlers>
   </binding>
 
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -94,16 +94,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_bug432599.js \
                  browser_bug435035.js \
                  browser_bug441778.js \
                  browser_bug455852.js \
                  browser_bug462673.js \
                  browser_bug481560.js \
                  browser_bug477014.js \
                  browser_bug495058.js \
+                 browser_bug517902.js \
                  browser_bug521216.js \
                  browser_discovery.js \
                  browser_tabfocus.js \
                  discovery.html \
                  moz.png \
                  test_bug435035.html \
                  test_bug462673.html \
                  browser_getshortcutoruri.js \
@@ -134,17 +135,19 @@ include $(topsrcdir)/config/rules.mk
                  browser_scope.js \
                  browser_overflowScroll.js \
                  browser_sanitizeDialog.js \
                  browser_tabs_owner.js \
                  browser_bug491431.js \
                  browser_bug304198.js \
                  browser_drag.js \
                  browser_relatedTabs.js \
+                 browser_plainTextLinks.js \
                  browser_contextSearchTabPosition.js \
+                 browser_NetworkPrioritizer.js \
     $(NULL)
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += browser_bug462289.js
 else
 _BROWSER_FILES += browser_customize.js
 endif
 
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_NetworkPrioritizer.js
@@ -0,0 +1,187 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Paul O’Shannessy <paul@oshannessy.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function test() {
+  /** Tests for NetworkPrioritizer.jsm (Bug 514490) **/
+
+  waitForExplicitFinish();
+
+  const PRIORITY_DELTA = -10; // same as in NetworkPrioritizer
+
+  // Test helper functions.
+  // getPriority and setPriority can take a Tab or a Browser
+  function getPriority(aBrowser) {
+    // Assume we were passed a tab if it's not a browser
+    if (!aBrowser.webNavigation)
+      aBrowser = aBrowser.linkedBrowser;
+    return aBrowser.webNavigation.QueryInterface(Ci.nsIDocumentLoader)
+                   .loadGroup.QueryInterface(Ci.nsISupportsPriority).priority;
+  }
+  function setPriority(aBrowser, aPriority) {
+    if (!aBrowser.webNavigation)
+      aBrowser = aBrowser.linkedBrowser;
+    aBrowser.webNavigation.QueryInterface(Ci.nsIDocumentLoader)
+            .loadGroup.QueryInterface(Ci.nsISupportsPriority).priority = aPriority;
+  }
+
+  function isWindowState(aWindow, aTabPriorities) {
+    let browsers = aWindow.gBrowser.browsers;
+    // Make sure we have the right number of tabs & priorities
+    is(browsers.length, aTabPriorities.length,
+       "Window has expected number of tabs");
+    // aState should be in format [ priority, priority, priority ]
+    for (let i = 0; i < browsers.length; i++) {
+      is(getPriority(browsers[i]), aTabPriorities[i],
+         "Tab had expected priority");
+    }
+  }
+
+
+  // This is the real test. It creates multiple tabs & windows, changes focus,
+  // closes windows/tabs to make sure we behave correctly.
+  // This test assumes that no priorities have been adjusted and the loadgroup
+  // priority starts at 0.
+  function test_behavior() {
+
+    // Call window "window_A" to make the test easier to follow
+    let window_A = window;
+
+    // Test 1 window, 1 tab case.
+    isWindowState(window_A, [-10]);
+
+    // Exising tab is tab_A1
+    let tab_A2 = window_A.gBrowser.addTab("http://example.com");
+    let tab_A3 = window_A.gBrowser.addTab("about:config");
+    tab_A3.linkedBrowser.addEventListener("load", function(aEvent) {
+      tab_A3.removeEventListener("load", arguments.callee, true);
+
+      // tab_A2 isn't focused yet
+      isWindowState(window_A, [-10, 0, 0]);
+
+      // focus tab_A2 & make sure priority got updated
+      window_A.gBrowser.selectedTab = tab_A2;
+      isWindowState(window_A, [0, -10, 0]);
+
+      window_A.gBrowser.removeTab(tab_A2);
+      // Next tab is auto selected
+      isWindowState(window_A, [0, -10]);
+
+      // Open another window then play with focus
+      let window_B = openDialog(location, "_blank", "chrome,all,dialog=no", "http://example.com");
+      window_B.addEventListener("load", function(aEvent) {
+        window_B.removeEventListener("load", arguments.callee, false);
+        window_B.gBrowser.addEventListener("load", function(aEvent) {
+          window_B.gBrowser.removeEventListener("load", arguments.callee, true);
+
+          // On Linux, waitForFocus doesn't work if the window is already focused,
+          // so focus window_A first.
+          waitForFocus(function() {
+            waitForFocus(function() {
+              isWindowState(window_A, [10, 0]);
+              isWindowState(window_B, [-10]);
+
+              waitForFocus(function() {
+                isWindowState(window_A, [0, -10]);
+                isWindowState(window_B, [0]);
+
+                waitForFocus(function() {
+                  isWindowState(window_A, [10, 0]);
+                  isWindowState(window_B, [-10]);
+
+                  // And we're done. Cleanup & run the next test
+                  window_B.close();
+                  window_A.gBrowser.removeTab(tab_A3);
+                  executeSoon(runNextTest);
+                }, window_B);
+              }, window_A);
+            }, window_B);
+          }, window_A);
+
+        }, true);
+      }, false);
+    }, true);
+
+  }
+
+
+  // This is more a test of nsLoadGroup and how it handles priorities. But since
+  // we depend on its behavior, it's good to test it. This is testing that there
+  // are no errors if we adjust beyond nsISupportsPriority's bounds.
+  function test_extremePriorities() {
+    let tab_A1 = gBrowser.tabContainer.getItemAtIndex(0);
+    let oldPriority = getPriority(tab_A1);
+
+    // Set the priority of tab_A1 to the lowest possible. Selecting the other tab
+    // will try to lower it
+    setPriority(tab_A1, Ci.nsISupportsPriority.PRIORITY_LOWEST);
+
+    let tab_A2 = gBrowser.addTab("http://example.com");
+    tab_A2.linkedBrowser.addEventListener("load", function(aEvent) {
+      tab_A2.removeEventListener("load", arguments.callee, true);
+      gBrowser.selectedTab = tab_A2;
+      is(getPriority(tab_A1), Ci.nsISupportsPriority.PRIORITY_LOWEST - PRIORITY_DELTA,
+         "Can adjust priority beyond 'lowest'");
+
+      // Now set priority to "highest" and make sure that no errors occur.
+      setPriority(tab_A1, Ci.nsISupportsPriority.PRIORITY_HIGHEST);
+      gBrowser.selectedTab = tab_A1;
+
+      is(getPriority(tab_A1), Ci.nsISupportsPriority.PRIORITY_HIGHEST + PRIORITY_DELTA,
+         "Can adjust priority beyond 'highest'");
+
+      // Cleanup, run next test
+      gBrowser.removeTab(tab_A2);
+      executeSoon(function() {
+        setPriority(tab_A1, oldPriority);
+        runNextTest();
+      });
+
+    }, true);
+  }
+
+
+  let tests = [test_behavior, test_extremePriorities];
+  function runNextTest() {
+    if (tests.length) {
+      // Linux has problems if window isn't focused. Should help prevent [orange].
+      waitForFocus(tests.shift());
+    } else {
+      finish();
+    }
+  }
+
+  runNextTest();
+}
--- a/browser/base/content/test/browser_bug304198.js
+++ b/browser/base/content/test/browser_bug304198.js
@@ -33,23 +33,20 @@
  * 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 ***** */
 
 function test() {
   waitForExplicitFinish();
 
-  if (Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager).activeWindow !=
-      window) {
-    setTimeout(test, 0);
-    window.focus();
-    return;
-  }
+  waitForFocus(continue_test);
+}
 
+function continue_test() {
   let charsToDelete, deletedURLTab, fullURLTab, partialURLTab, testPartialURL, testURL;
 
   charsToDelete = 5;
   deletedURLTab = gBrowser.addTab();
   fullURLTab = gBrowser.addTab();
   partialURLTab = gBrowser.addTab();
   testURL = "http://example.org/browser/browser/base/content/test/dummy_page.html";
 
@@ -103,17 +100,18 @@ function test() {
     gBrowser.selectedTab = deletedURLTab;
     is(gURLBar.value, testURL, 'gURLBar.value should be testURL after initial switch to deletedURLTab');
 
     // simulate the user removing the whole url from the location bar
     gPrefService.setBoolPref("browser.urlbar.clickSelectsAll", true);
 
     urlbarBackspace(function () {
       is(gURLBar.value, "", 'gURLBar.value should be "" (just set)');
-      gPrefService.clearUserPref("browser.urlbar.clickSelectsAll");
+      if (gPrefService.prefHasUserValue("browser.urlbar.clickSelectsAll"))
+        gPrefService.clearUserPref("browser.urlbar.clickSelectsAll");
       cb();
     });
   }
 
   function prepareFullURLTab(cb) {
     gBrowser.selectedTab = fullURLTab;
     is(gURLBar.value, testURL, 'gURLBar.value should be testURL after initial switch to fullURLTab');
     cb();
@@ -128,17 +126,18 @@ function test() {
 
     var deleted = 0;
     urlbarBackspace(function () {
       deleted++;
       if (deleted < charsToDelete) {
         urlbarBackspace(arguments.callee);
       } else {
         is(gURLBar.value, testPartialURL, "gURLBar.value should be testPartialURL (just set)");
-        gPrefService.clearUserPref("browser.urlbar.clickSelectsAll");
+        if (gPrefService.prefHasUserValue("browser.urlbar.clickSelectsAll"))
+          gPrefService.clearUserPref("browser.urlbar.clickSelectsAll");
         cb();
       }
     });
   }
 
   function runTests() {
     // prepare the three tabs required by this test
     prepareFullURLTab(function () {
--- a/browser/base/content/test/browser_bug386835.js
+++ b/browser/base/content/test/browser_bug386835.js
@@ -80,17 +80,18 @@ function runPrintPreviewTests() {
   testPrintPreview(gTab1, function() {
     // test print preview on HTML document
     testPrintPreview(gTab2, function() {
       // test print preview on image document with siteSpecific set to false
       gPrefService.setBoolPref("browser.zoom.siteSpecific", false);
       testPrintPreview(gTab1, function() {
         // test print preview of HTML document with siteSpecific set to false
         testPrintPreview(gTab2, function() {
-          gPrefService.clearUserPref("browser.zoom.siteSpecific");
+          if (gPrefService.prefHasUserValue("browser.zoom.siteSpecific"))
+            gPrefService.clearUserPref("browser.zoom.siteSpecific");
           finishTest();
         });
       });
     });
   });
 }
 
 function testPrintPreview(aTab, aCallback) {
--- a/browser/base/content/test/browser_bug419612.js
+++ b/browser/base/content/test/browser_bug419612.js
@@ -18,17 +18,18 @@ function test() {
 
       gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", false);
       FullZoom.reset();
       gBrowser.selectedTab = tab1;
       tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser);
       tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser);
       isnot(tab1Zoom, tab2Zoom, "Zoom should not affect background tabs");
 
-      gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs");
+      if (gPrefService.prefHasUserValue("browser.zoom.updateBackgroundTabs"))
+        gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs");
       gBrowser.removeTab(tab1);
       gBrowser.removeTab(tab2);
       finish();
     }), true);
     tab2.linkedBrowser.loadURI(testPage);
   }), true);
   content.location = testPage;
 }
--- a/browser/base/content/test/browser_bug455852.js
+++ b/browser/base/content/test/browser_bug455852.js
@@ -6,10 +6,11 @@ function test() {
 
   var tab = gBrowser.selectedTab;
   gPrefService.setBoolPref("browser.tabs.closeWindowWithLastTab", false);
   EventUtils.synthesizeKey("w", { accelKey: true });
   is(tab.parentNode, null, "ctrl+w removes the tab");
   is(gBrowser.mTabs.length, 1, "a new tab has been opened");
   is(document.activeElement, gURLBar.inputField, "location bar is focused for the new tab");
 
-  gPrefService.clearUserPref("browser.tabs.closeWindowWithLastTab");
+  if (gPrefService.prefHasUserValue("browser.tabs.closeWindowWithLastTab"))
+    gPrefService.clearUserPref("browser.tabs.closeWindowWithLastTab");
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug517902.js
@@ -0,0 +1,37 @@
+/* Make sure that "View Image Info" loads the correct image data */
+
+function test() {
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  
+  gBrowser.selectedBrowser.addEventListener("load", function () {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+
+    var doc = gBrowser.contentDocument;
+    var testImg = doc.getElementById("test-image");
+    var pageInfo = BrowserPageInfo(doc, "mediaTab", testImg);
+
+    pageInfo.addEventListener("load", function () {
+      pageInfo.onFinished.push(function () {
+        executeSoon(function () {
+          var pageInfoImg = pageInfo.document.getElementById("thepreviewimage");
+
+          is(pageInfoImg.src, testImg.src, "selected image has the correct source");
+          is(pageInfoImg.width, testImg.width, "selected image has the correct width");
+          is(pageInfoImg.height, testImg.height, "selected image has the correct height");
+
+          pageInfo.close();
+          gBrowser.removeCurrentTab();
+          finish();
+        });
+      });
+    }, true);
+  }, true);
+
+  content.location =
+    "data:text/html," +
+    "<img src='about:logo?a' height=200 width=250>" +
+    "<img src='about:logo?b' height=200 width=250 alt=1>" +
+    "<img src='about:logo?b' height=100 width=150 alt=2 id='test-image'>";
+}
--- a/browser/base/content/test/browser_ctrlTab.js
+++ b/browser/base/content/test/browser_ctrlTab.js
@@ -79,17 +79,18 @@ function test() {
     pressCtrlTab();
     document.removeEventListener("keypress", detectKeyEvent, false);
     ok(eventConsumed, "Ctrl+Tab consumed by the tabbed browser if one tab is open");
     is(focusedWindow, document.commandDispatcher.focusedWindow,
        "Ctrl+Tab doesn't change focus if one tab is open");
   }
 
   // cleanup
-  gPrefService.clearUserPref("browser.ctrlTab.previews");
+  if (gPrefService.prefHasUserValue("browser.ctrlTab.previews"))
+    gPrefService.clearUserPref("browser.ctrlTab.previews");
 
   finish();
 
   /* private utility functions */
 
   function pressCtrlTab(aShiftKey)
     EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: !!aShiftKey });
 
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_plainTextLinks.js
@@ -0,0 +1,95 @@
+let doc, range, selection;
+function setSelection(el1, el2, index1, index2) {
+  selection.removeAllRanges();
+  range.setStart(el1, index1);
+  range.setEnd(el2, index2);
+  selection.addRange(range);
+}
+
+function initContextMenu() {
+  document.popupNode = doc.getElementsByTagName("DIV")[0];
+  let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
+  let contextMenu = new nsContextMenu(contentAreaContextMenu, gBrowser);
+  return contextMenu;
+}
+
+function testExpected(expected, msg) {
+  initContextMenu();
+  let linkMenuItem = document.getElementById("context-openlinkincurrent");
+  is(linkMenuItem.hidden, expected, msg);
+}
+
+function testLinkExpected(expected, msg) {
+  let contextMenu = initContextMenu();
+  is(contextMenu.linkURL, expected, msg);
+}
+
+function runSelectionTests() {
+  let mainDiv = doc.createElement("div");
+  let div = doc.createElement("div");
+  let div2 = doc.createElement("div");
+  let span1 = doc.createElement("span");
+  let span2 = doc.createElement("span");
+  let span3 = doc.createElement("span");
+  let p1 = doc.createElement("p");
+  let p2 = doc.createElement("p");
+  span1.textContent = "http://index.";
+  span2.textContent = "example.com example.com";
+  span3.textContent = " - Test";
+  p1.textContent = "mailto:test.com ftp.example.com";
+  p2.textContent = "example.com   -";
+  div.appendChild(span1);
+  div.appendChild(span2);
+  div.appendChild(span3);
+  div.appendChild(p1);
+  div.appendChild(p2);
+  let p3 = doc.createElement("p");
+  p3.textContent = "main.example.com";
+  div2.appendChild(p3);
+  mainDiv.appendChild(div);
+  mainDiv.appendChild(div2);
+  doc.body.appendChild(mainDiv);
+  setSelection(span1.firstChild, span2.firstChild, 0, 11);
+  testExpected(false, "The link context menu should show for http://www.example.com");
+  setSelection(span1.firstChild, span2.firstChild, 7, 11);
+  testExpected(false, "The link context menu should show for www.example.com");
+  setSelection(span1.firstChild, span2.firstChild, 8, 11);
+  testExpected(true, "The link context menu should not show for ww.example.com");
+  setSelection(span2.firstChild, span2.firstChild, 0, 11);
+  testExpected(false, "The link context menu should show for example.com");
+  testLinkExpected("http://example.com/", "url for example.com selection should not prepend www");
+  setSelection(span2.firstChild, span2.firstChild, 11, 23);
+  testExpected(false, "The link context menu should show for example.com");
+  setSelection(span2.firstChild, span2.firstChild, 0, 10);
+  testExpected(true, "Link options should not show for selection that's not at a word boundary");
+  setSelection(span2.firstChild, span3.firstChild, 12, 7);
+  testExpected(true, "Link options should not show for selection that has whitespace");
+  setSelection(span2.firstChild, span2.firstChild, 12, 19);
+  testExpected(true, "Link options should not show unless a url is selected");
+  setSelection(p1.firstChild, p1.firstChild, 0, 15);
+  testExpected(true, "Link options should not show for mailto: links");
+  setSelection(p1.firstChild, p1.firstChild, 16, 31);
+  testExpected(false, "Link options should show for ftp.example.com");
+  testLinkExpected("ftp://ftp.example.com/", "ftp.example.com should be preceeded with ftp://");
+  setSelection(p2.firstChild, p2.firstChild, 0, 14);
+  testExpected(false, "Link options should show for www.example.com  ");
+  selection.selectAllChildren(div2);
+  testExpected(false, "Link options should show for triple-click selections");
+  gBrowser.removeCurrentTab();
+  finish();
+}
+
+function test() {
+  waitForExplicitFinish();
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function() {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+    doc = content.document;
+    range = doc.createRange();
+    selection = content.getSelection();
+    waitForFocus(runSelectionTests, content);
+  }, true);
+
+  content.location =
+    "data:text/html,Test For Non-Hyperlinked url selection";
+}
--- a/browser/base/content/test/browser_tabfocus.js
+++ b/browser/base/content/test/browser_tabfocus.js
@@ -1,23 +1,21 @@
 /*
  * This test checks that focus is adjusted properly when switching tabs.
  */
 
 let testPage1 = "data:text/html,<html id='tab1'><body><button id='button1'>Tab 1</button></body></html>";
 let testPage2 = "data:text/html,<html id='tab2'><body><button id='button2'>Tab 2</button></body></html>";
 let testPage3 = "data:text/html,<html id='tab3'><body><button id='button3'>Tab 3</button></body></html>";
 
-var browser1;
-
 function test() {
   waitForExplicitFinish();
 
   var tab1 = gBrowser.addTab();
-  browser1 = gBrowser.getBrowserForTab(tab1);
+  var browser1 = gBrowser.getBrowserForTab(tab1);
 
   var tab2 = gBrowser.addTab();
   var browser2 = gBrowser.getBrowserForTab(tab2);
 
   gURLBar.focus();
 
   var loadCount = 0;
   function check()
@@ -29,35 +27,36 @@ function test() {
     window.focus();
 
     _browser_tabfocus_test_lastfocus = gURLBar;
     _browser_tabfocus_test_lastfocuswindow = window;
 
     window.addEventListener("focus", _browser_tabfocus_test_eventOccured, true);
     window.addEventListener("blur", _browser_tabfocus_test_eventOccured, true);
 
-    gBrowser.selectedTab = tab2;
-
-    var fm = Components.classes["@mozilla.org/focus-manager;1"].
-               getService(Components.interfaces.nsIFocusManager);
-    is(fm.focusedWindow, window, "focusedWindow after tab load");
-    is(fm.focusedElement, gURLBar.inputField, "focusedElement after tab load");
-
     // make sure that the focus initially starts out blank
+    var fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
     var focusedWindow = {};
     is(fm.getFocusedElementForWindow(browser1.contentWindow, false, focusedWindow), null, "initial focus in tab 1");
     is(focusedWindow.value, browser1.contentWindow, "initial frame focus in tab 1");
     is(fm.getFocusedElementForWindow(browser2.contentWindow, false, focusedWindow), null, "initial focus in tab 2");
     is(focusedWindow.value, browser2.contentWindow, "initial frame focus in tab 2");
 
+    expectFocusShift(function () gBrowser.selectedTab = tab2,
+                     browser2.contentWindow, null, true,
+                     "focusedElement after tab change, focus in new tab");
+
     // switching tabs when the urlbar is focused and nothing in the new tab is focused
-    // should keep focus in the urlbar
+    // should focus the browser
+    expectFocusShift(function () gURLBar.focus(),
+                     window, gURLBar.inputField, true,
+                     "url field focused");
     expectFocusShift(function () gBrowser.selectedTab = tab1,
-                     window, gURLBar.inputField, false,
-                     "focusedElement after tab change, focus in url field, no focus in new tab");
+                     browser1.contentWindow, null, true,
+                     "focusedElement after tab change, focus in new tab");
 
     // focusing a button in the current tab should focus it
     var button1 = browser1.contentDocument.getElementById("button1");
     expectFocusShift(function () button1.focus(),
                      browser1.contentWindow, button1, true,
                      "focusedWindow after focus in focused tab");
 
     // focusing a button in a background tab should not change the actual
@@ -218,18 +217,17 @@ function expectFocusShift(callback, expe
     _browser_tabfocus_test_lastfocuswindow = expectedWindow;
   }
 
   callback();
 
   is(_browser_tabfocus_test_events, expectedEvents, testid + " events");
   _browser_tabfocus_test_events = "";
 
-  var fm = Components.classes["@mozilla.org/focus-manager;1"].
-             getService(Components.interfaces.nsIFocusManager);
+  var fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
 
   var focusedElement = fm.focusedElement;
   is(focusedElement ? getId(focusedElement) : "none",
      expectedElement ? getId(expectedElement) : "none", testid + " focusedElement");
   is(fm.focusedWindow, expectedWindow, testid + " focusedWindow");
   var focusedWindow = {};
   is(fm.getFocusedElementForWindow(expectedWindow, false, focusedWindow),
      expectedElement, testid + " getFocusedElementForWindow");
--- a/browser/base/content/web-panels.xul
+++ b/browser/base/content/web-panels.xul
@@ -48,21 +48,21 @@
 <!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd">
 %textcontextDTD;
 ]>
 
 <page id="webpanels-window"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         onload="load()" onunload="unload()">
-  <script type="application/x-javascript" src="chrome://global/content/contentAreaUtils.js"/>
-  <script type="application/x-javascript" src="chrome://browser/content/browser.js"/>
-  <script type="application/x-javascript" src="chrome://global/content/inlineSpellCheckUI.js"/>
-  <script type="application/x-javascript" src="chrome://browser/content/nsContextMenu.js"/>
-  <script type="application/x-javascript" src="chrome://browser/content/web-panels.js"/>
+  <script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
+  <script type="application/javascript" src="chrome://browser/content/browser.js"/>
+  <script type="application/javascript" src="chrome://global/content/inlineSpellCheckUI.js"/>
+  <script type="application/javascript" src="chrome://browser/content/nsContextMenu.js"/>
+  <script type="application/javascript" src="chrome://browser/content/web-panels.js"/>
 
   <stringbundleset id="stringbundleset"> 
     <stringbundle id="bundle_browser" src="chrome://browser/locale/browser.properties"/>
   </stringbundleset>
 
   <broadcasterset id="mainBroadcasterSet">
     <broadcaster id="isFrameImage"/>
   </broadcasterset>
--- a/browser/components/certerror/content/aboutCertError.xhtml
+++ b/browser/components/certerror/content/aboutCertError.xhtml
@@ -62,17 +62,17 @@
     <!-- This page currently uses the same favicon as neterror.xhtml.
          If the location of the favicon is changed for both pages, the
          FAVICON_ERRORPAGE_URL symbol in toolkit/components/places/src/nsFaviconService.h
          should be updated. If this page starts using a different favicon
          than neterrorm nsFaviconService->DoSetAndLoadFaviconForPage
          should be updated to ignore this one as well. -->
     <link rel="icon" type="image/png" id="favicon" href="chrome://global/skin/icons/warning-16.png"/>
 
-    <script type="application/x-javascript"><![CDATA[
+    <script type="application/javascript"><![CDATA[
       // Error url MUST be formatted like this:
       //   about:certerror?e=error&u=url&d=desc
 
       // Note that this file uses document.documentURI to get
       // the URL (with the format from above). This is because
       // document.location.href gets the current URI off the docshell,
       // which is the URL displayed in the location bar, i.e.
       // the URI that the user attempted to load.
@@ -268,12 +268,12 @@
       </div>
     </div>
 
     <!--
     - Note: It is important to run the script this way, instead of using
     - an onload handler. This is because error pages are loaded as
     - LOAD_BACKGROUND, which means that onload handlers will not be executed.
     -->
-    <script type="application/x-javascript">initPage();</script>
+    <script type="application/javascript">initPage();</script>
 
   </body>
 </html>
--- a/browser/components/certerror/test/browser_bug431826.js
+++ b/browser/components/certerror/test/browser_bug431826.js
@@ -30,11 +30,12 @@ function testExpertPref() {
   window.removeEventListener("DOMContentLoaded", testExpertPref, true);
   var expertDiv = gBrowser.contentDocument.getElementById("expertContent");
   var technicalDiv = gBrowser.contentDocument.getElementById("technicalContent");
   ok(!expertDiv.hasAttribute("collapsed"), "Expert content should not be collapsed with the expert mode pref set");
   ok(!technicalDiv.hasAttribute("collapsed"), "Technical content should not be collapsed with the expert mode pref set");
 
   // Clean up
   gBrowser.removeCurrentTab();
-  gPrefService.clearUserPref("browser.xul.error_pages.expert_bad_cert");
+  if (gPrefService.prefHasUserValue("browser.xul.error_pages.expert_bad_cert"))
+    gPrefService.clearUserPref("browser.xul.error_pages.expert_bad_cert");
   finish();
 }
--- a/browser/components/distribution.js
+++ b/browser/components/distribution.js
@@ -239,17 +239,17 @@ DistributionCustomizer.prototype = {
     // nsPrefService loads very early.  Reload prefs so we can set
     // distribution defaults during the prefservice:after-app-defaults
     // notification (see applyPrefDefaults below)
     this._prefSvc.QueryInterface(Ci.nsIObserver);
     this._prefSvc.observe(null, "reload-default-prefs", null);
   },
 
   _bookmarksApplied: false,
-  applyBookmarks: function DIST_applyBookarks() {
+  applyBookmarks: function DIST_applyBookmarks() {
     this._bookmarksApplied = true;
     if (!this._iniFile)
       return this._checkCustomizationComplete();
 
     let sections = enumToObject(this._ini.getSections());
 
     // The global section, and several of its fields, is required
     // (we also check here to be consistent with applyPrefDefaults below)
--- a/browser/components/feeds/content/subscribe.xhtml
+++ b/browser/components/feeds/content/subscribe.xhtml
@@ -19,17 +19,17 @@
       xmlns="http://www.w3.org/1999/xhtml"
       xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <head>
     <title>&feedPage.title;</title>
     <link rel="stylesheet"
           href="chrome://browser/skin/feeds/subscribe.css"
           type="text/css"
           media="all"/>
-    <script type="application/x-javascript"
+    <script type="application/javascript"
             src="chrome://browser/content/feeds/subscribe.js"/>
   </head>
   <body onload="SubscribeHandler.writeContent();" onunload="SubscribeHandler.uninit();">
     <div id="feedHeaderContainer">
       <div id="feedHeader" dir="&locale.dir;">
         <div id="feedIntroText">
           <p id="feedSubscriptionInfo1" />
           <p id="feedSubscriptionInfo2" />
@@ -55,17 +55,17 @@
               ><xul:spacer flex="1"
               /><xul:button label="&feedSubscribeNow;" id="subscribeButton"
             /></xul:hbox
           ></xul:vbox
         ></div
       ></div>
     </div>
 
-    <script type="application/x-javascript">
+    <script type="application/javascript">
       SubscribeHandler.init();
     </script>
 
     <div id="feedBody">
       <div id="feedTitle">
         <a id="feedTitleLink">
           <img id="feedTitleImage"/>
         </a>
--- a/browser/components/microsummaries/src/nsMicrosummaryService.js
+++ b/browser/components/microsummaries/src/nsMicrosummaryService.js
@@ -547,17 +547,17 @@ MicrosummaryService.prototype = {
    * This caches the list of microsummarized bookmarks. The cache is
    * managed by observing the annotation service, and updating 
    * when a microsummary annotation is added or removed.
    *
    * @returns an array of item ids for microsummarized bookmarks
    *
    */
   get _bookmarks() {
-    var bookmarks = this._ans.getItemsWithAnnotation(ANNO_MICSUM_GEN_URI, {});
+    var bookmarks = this._ans.getItemsWithAnnotation(ANNO_MICSUM_GEN_URI);
     this.__defineGetter__("_bookmarks", function() bookmarks);
     return this._bookmarks;
   },
 
   _setAnnotation: function MSS__setAnnotation(aBookmarkId, aFieldName, aFieldValue) {
     this._ans.setItemAnnotation(aBookmarkId,
                                 aFieldName,
                                 aFieldValue,
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -448,17 +448,20 @@ var MigrationWizard = {
         if (this._newHomePage) {
           try {
             // set homepage properly
             var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
                                     .getService(Components.interfaces.nsIPrefService);
             var prefBranch = prefSvc.getBranch(null);
 
             if (this._newHomePage == "DEFAULT") {
-              prefBranch.clearUserPref("browser.startup.homepage");
+              try {
+                prefBranch.clearUserPref("browser.startup.homepage");
+              }
+              catch (e) { }
             }
             else {
               var str = Components.classes["@mozilla.org/supports-string;1"]
                                 .createInstance(Components.interfaces.nsISupportsString);
               str.data = this._newHomePage;
               prefBranch.setComplexValue("browser.startup.homepage",
                                          Components.interfaces.nsISupportsString,
                                          str);
--- a/browser/components/migration/content/migration.xul
+++ b/browser/components/migration/content/migration.xul
@@ -44,17 +44,17 @@
         windowtype="Browser:MigrationWizard"
         title="&migrationWizard.title;"
         onload="MigrationWizard.init()"
         onunload="MigrationWizard.uninit()"
         style="width: 40em;"
         buttons="accept,cancel"
         branded="true">
 
-  <script type="application/x-javascript" src="chrome://browser/content/migration/migration.js"/>
+  <script type="application/javascript" src="chrome://browser/content/migration/migration.js"/>
 
   <stringbundle id="bundle" src="chrome://browser/locale/migration/migration.properties"/>
   <stringbundle id="brandBundle" src="chrome://branding/locale/brand.properties"/>
 
   <wizardpage id="importSource" pageid="importSource" next="selectProfile"
               label="&importSource.title;"
               onpageadvanced="return MigrationWizard.onImportSourcePageAdvanced();">
 #ifdef XP_WIN
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -997,17 +997,17 @@ BrowserGlue.prototype = {
                     "&sort=" +
                     Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
                     "&maxResults=" + MAX_RESULTS),
                  parent: bmsvc.bookmarksMenuFolder,
                  position: bookmarksMenuIndex++,
                  newInVersion: 1 };
         smartBookmarks.push(smart);
 
-        var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, {});
+        var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
         // Set current itemId, parent and position if Smart Bookmark exists,
         // we will use these informations to create the new version at the same
         // position.
         for each(var itemId in smartBookmarkItemIds) {
           var queryId = annosvc.getItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
           for (var i = 0; i < smartBookmarks.length; i++){
             if (smartBookmarks[i].queryId == queryId) {
               smartBookmarks[i].found = true;
--- a/browser/components/places/content/bookmarksPanel.xul
+++ b/browser/components/places/content/bookmarksPanel.xul
@@ -47,19 +47,19 @@
 <!DOCTYPE page SYSTEM "chrome://browser/locale/places/places.dtd">
 
 <page id="bookmarksPanel"
       xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
       onload="init();"
       onunload="SidebarUtils.clearURLFromStatusBar();">
 
-  <script type="application/x-javascript" 
+  <script type="application/javascript" 
           src="chrome://browser/content/bookmarks/sidebarUtils.js"/>
-  <script type="application/x-javascript" 
+  <script type="application/javascript" 
           src="chrome://browser/content/bookmarks/bookmarksPanel.js"/>
 
   <commandset id="placesCommands"/>
   <commandset id="editMenuCommands"/>
   <popup id="placesContext"/>
 
   <!-- Bookmarks and history tooltip -->
   <tooltip id="bhTooltip"/>
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -243,17 +243,17 @@ PlacesController.prototype = {
       break;
     case "cmd_delete":
     case "placesCmd_delete":
       this.remove("Remove Selection");
       break;
     case "placesCmd_deleteDataHost":
       var host;
       if (PlacesUtils.nodeIsHost(this._view.selectedNode)) {
-        var queries = this._view.selectedNode.getQueries({});
+        var queries = this._view.selectedNode.getQueries();
         host = queries[0].domain;
       }
       else
         host = PlacesUtils._uri(this._view.selectedNode.uri).host;
       PlacesUIUtils.privateBrowsing.removeDataFromDomain(host);
       break;
     case "cmd_selectAll":
       this.selectAll();
@@ -504,25 +504,25 @@ PlacesController.prototype = {
                 nodeData["livemarkChild"] = true;
             }
           }
           break;
       }
 
       // annotations
       if (uri) {
-        var names = PlacesUtils.annotations.getPageAnnotationNames(uri, {});
+        var names = PlacesUtils.annotations.getPageAnnotationNames(uri);
         for (var j = 0; j < names.length; ++j)
           nodeData[names[j]] = true;
       }
 
       // For items also include the item-specific annotations
       if (node.itemId != -1) {
         names = PlacesUtils.annotations
-                           .getItemAnnotationNames(node.itemId, {});
+                           .getItemAnnotationNames(node.itemId);
         for (j = 0; j < names.length; ++j)
           nodeData[names[j]] = true;
       }
       metadata.push(nodeData);
     }
 
     return metadata;
   },
@@ -1053,17 +1053,17 @@ PlacesController.prototype = {
   _removeHistoryContainer: function PC_removeHistoryContainer(aContainerNode) {
     var bhist = PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory);
     if (PlacesUtils.nodeIsHost(aContainerNode)) {
       // Site container.
       bhist.removePagesFromHost(aContainerNode.title, true);
     }
     else if (PlacesUtils.nodeIsDay(aContainerNode)) {
       // Day container.
-      var query = aContainerNode.getQueries({})[0];
+      var query = aContainerNode.getQueries()[0];
       var beginTime = query.beginTime;
       var endTime = query.endTime;
       NS_ASSERT(query && beginTime && endTime,
                 "A valid date container query should exist!");
       // We want to exclude beginTime from the removal because
       // removePagesByTimeframe includes both extremes, while date containers
       // exclude the lower extreme.  So, if we would not exclude it, we would
       // end up removing more history than requested.
--- a/browser/components/places/content/editBookmarkOverlay.js
+++ b/browser/components/places/content/editBookmarkOverlay.js
@@ -199,32 +199,32 @@ var gEditItemOverlay = {
     }
 
     if (this._itemId == -1 ||
         this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {
       this._isLivemark = false;
 
       this._initTextField("locationField", this._uri.spec);
       if (!aItemIdList) {
-        var tags = PlacesUtils.tagging.getTagsForURI(this._uri, {}).join(", ");
+        var tags = PlacesUtils.tagging.getTagsForURI(this._uri).join(", ");
         this._initTextField("tagsField", tags, false);
       }
       else {
         this._multiEdit = true;
         this._allTags = [];
         this._itemIds = aItemIdList;
         var nodeToCheck = 0;
         for (var i = 0; i < aItemIdList.length; i++) {
           if (aItemIdList[i] instanceof Ci.nsIURI) {
             this._uris[i] = aItemIdList[i];
             this._itemIds[i] = -1;
           }
           else
-            this._uris[i] = PlacesUtils.bookmarks.getBookmarkURI(this._itemIds[i], {});
-          this._tags[i] = PlacesUtils.tagging.getTagsForURI(this._uris[i], {});
+            this._uris[i] = PlacesUtils.bookmarks.getBookmarkURI(this._itemIds[i]);
+          this._tags[i] = PlacesUtils.tagging.getTagsForURI(this._uris[i]);
           if (this._tags[i].length < this._tags[nodeToCheck].length)
             nodeToCheck =  i;
         }
         this._getCommonTags(nodeToCheck);
         this._initTextField("tagsField", this._allTags.join(", "), false);
         this._element("itemsCountText").value =
           PlacesUIUtils.getFormattedString("detailsPane.multipleItems",
                                            [this._itemIds.length]);
@@ -323,17 +323,17 @@ var gEditItemOverlay = {
       bmMenuItem.folderId = PlacesUtils.bookmarksMenuFolderId;
       var toolbarItem = this._element("toolbarFolderItem");
       toolbarItem.label = bms.getItemTitle(PlacesUtils.toolbarFolderId);
       toolbarItem.folderId = PlacesUtils.toolbarFolderId;
       this._staticFoldersListBuilt = true;
     }
 
     // List of recently used folders:
-    var folderIds = annos.getItemsWithAnnotation(LAST_USED_ANNO, { });
+    var folderIds = annos.getItemsWithAnnotation(LAST_USED_ANNO);
 
     /**
      * The value of the LAST_USED_ANNO annotation is the time (in the form of
      * Date.getTime) at which the folder has been last used.
      *
      * First we build the annotated folders array, each item has both the
      * folder identifier and the time at which it was last-used by this dialog
      * set. Then we sort it descendingly based on the time field.
@@ -568,17 +568,17 @@ var gEditItemOverlay = {
 
   _updateTags: function EIO__updateTags() {
     if (this._multiEdit)
       return this._updateMultipleTagsForItems();
     return this._updateSingleTagForItem();
   },
 
   _updateSingleTagForItem: function EIO__updateSingleTagForItem() {
-    var currentTags = PlacesUtils.tagging.getTagsForURI(this._uri, { });
+    var currentTags = PlacesUtils.tagging.getTagsForURI(this._uri);
     var tags = this._getTagsArrayFromTagField();
     if (tags.length > 0 || currentTags.length > 0) {
       var tagsToRemove = [];
       var tagsToAdd = [];
       var txns = []; 
       for (var i = 0; i < currentTags.length; i++) {
         if (tags.indexOf(currentTags[i]) == -1)
           tagsToRemove.push(currentTags[i]);
@@ -594,17 +594,17 @@ var gEditItemOverlay = {
         txns.push(PlacesUIUtils.ptm.tagURI(this._uri, tagsToAdd));
 
       if (txns.length > 0) {
         var aggregate = PlacesUIUtils.ptm.aggregateTransactions("Update tags",
                                                                 txns);
         PlacesUIUtils.ptm.doTransaction(aggregate);
 
         // Ensure the tagsField is in sync, clean it up from empty tags
-        var tags = PlacesUtils.tagging.getTagsForURI(this._uri, {}).join(", ");
+        var tags = PlacesUtils.tagging.getTagsForURI(this._uri).join(", ");
         this._initTextField("tagsField", tags, false);
         return true;
       }
     }
     return false;
   },
 
    /**
@@ -661,17 +661,17 @@ var gEditItemOverlay = {
       if (txns.length > 0) {
         var aggregate = PlacesUIUtils.ptm.aggregateTransactions("Update tags",
                                                                 txns);
         PlacesUIUtils.ptm.doTransaction(aggregate);
 
         this._allTags = tags;
         this._tags = [];
         for (i = 0; i < this._uris.length; i++)
-          this._tags[i] = PlacesUtils.tagging.getTagsForURI(this._uris[i], {});
+          this._tags[i] = PlacesUtils.tagging.getTagsForURI(this._uris[i]);
 
         // Ensure the tagsField is in sync, clean it up from empty tags
         this._initTextField("tagsField", tags, false);
         return true;
       }
     }
     return false;
   },
@@ -1107,17 +1107,17 @@ var gEditItemOverlay = {
       if (locationField.value != aValue) {
         this._uri = Cc["@mozilla.org/network/io-service;1"].
                     getService(Ci.nsIIOService).
                     newURI(aValue, null, null);
         this._initTextField("locationField", this._uri.spec);
         this._initNamePicker(); // for microsummaries
         this._initTextField("tagsField",
                              PlacesUtils.tagging
-                                        .getTagsForURI(this._uri, { }).join(", "),
+                                        .getTagsForURI(this._uri).join(", "),
                             false);
         this._rebuildTagsSelectorList();
       }
       break;
     case "keyword":
       this._initTextField("keywordField",
                           PlacesUtils.bookmarks
                                      .getKeywordForBookmark(this._itemId));
--- a/browser/components/places/content/history-panel.xul
+++ b/browser/components/places/content/history-panel.xul
@@ -55,19 +55,19 @@
 <!-- we need to keep id="history-panel" for upgrade and switching
      between versions of the browser -->
 
 <page id="history-panel" orient="vertical"
       xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
       onload="HistorySidebarInit();"
       onunload="SidebarUtils.clearURLFromStatusBar();">
 
-  <script type="application/x-javascript" 
+  <script type="application/javascript" 
           src="chrome://browser/content/bookmarks/sidebarUtils.js"/>
-  <script type="application/x-javascript" 
+  <script type="application/javascript" 
           src="chrome://browser/content/places/history-panel.js"/>
 
   <commandset id="editMenuCommands"/>
   <commandset id="placesCommands"/>
 
   <keyset id="editMenuKeys">
 #ifdef XP_MACOSX
     <key id="key_delete2" keycode="VK_BACK" command="cmd_delete"/>
--- a/browser/components/places/content/moveBookmarks.xul
+++ b/browser/components/places/content/moveBookmarks.xul
@@ -52,17 +52,17 @@
         ondialogaccept="return gMoveBookmarksDialog.onOK(event);"
         title="&window.title;"
         onload="gMoveBookmarksDialog.init();"
         style="&window.style;"
         screenX="24"
         screenY="24"
         persist="screenX screenY width height">
 
-  <script type="application/x-javascript"
+  <script type="application/javascript"
           src="chrome://browser/content/places/moveBookmarks.js"/>
 
   <hbox flex="1">
     <label id="movetolabel" value="&moveTo.label;" control="foldersTree"/>
     <hbox flex="1">
       <tree id="foldersTree"
             class="placesTree"
             flex="1"
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -211,17 +211,17 @@ var PlacesOrganizer = {
    */
   _cachedLeftPaneSelectedURI: null,
   onPlaceSelected: function PO_onPlaceSelected(resetSearchBox) {
     // Don't change the right-hand pane contents when there's no selection.
     if (!this._places.hasSelection)
       return;
 
     var node = this._places.selectedNode;
-    var queries = asQuery(node).getQueries({});
+    var queries = asQuery(node).getQueries();
 
     // Items are only excluded on the left pane.
     var options = node.queryOptions.clone();
     options.excludeItems = false;
     var placeURI = PlacesUtils.history.queriesToQueryString(queries,
                                                             queries.length,
                                                             options);
 
@@ -354,17 +354,17 @@ var PlacesOrganizer = {
     return asQuery(this._content.getResult().root).queryOptions;
   },
 
   /**
    * Returns the queries associated with the query currently loaded in the
    * main places pane.
    */
   getCurrentQueries: function PO_getCurrentQueries() {
-    return asQuery(this._content.getResult().root).getQueries({});
+    return asQuery(this._content.getResult().root).getQueries();
   },
 
   /**
    * Show the migration wizard for importing from a file.
    */
   importBookmarks: function PO_import() {
     // XXX: ifdef it to be non-modal (non-"sheet") on mac (see bug 259039)
     var features = "modal,centerscreen,chrome,resizable=no";
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -73,17 +73,17 @@
         xmlns:html="http://www.w3.org/1999/xhtml"
         onload="PlacesOrganizer.init();"
         onunload="PlacesOrganizer.destroy();"
         width="&places.library.width;" height="&places.library.height;"
         screenX="10" screenY="10"
         toggletoolbar="true"
         persist="width height screenX screenY sizemode">
 
-  <script type="application/x-javascript"
+  <script type="application/javascript"
           src="chrome://browser/content/places/places.js"/>
   <script type="application/javascript"
           src="chrome://browser/content/utilityOverlay.js"/>
   <script type="application/javascript"
           src="chrome://browser/content/places/editBookmarkOverlay.js"/>
 
   <stringbundleset id="placesStringSet">
     <stringbundle id="brandStrings" src="chrome://branding/locale/brand.properties"/>
--- a/browser/components/places/content/placesOverlay.xul
+++ b/browser/components/places/content/placesOverlay.xul
@@ -42,27 +42,27 @@
 <!ENTITY % editMenuOverlayDTD SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
 %editMenuOverlayDTD;
 ]>
 
 <overlay id="placesOverlay"
          xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
-  <script type="application/x-javascript"
+  <script type="application/javascript"
           src="chrome://global/content/globalOverlay.js"/>
-  <script type="application/x-javascript"
+  <script type="application/javascript"
           src="chrome://browser/content/utilityOverlay.js"/>
-  <script type="application/x-javascript" 
+  <script type="application/javascript" 
           src="chrome://browser/content/places/utils.js"/>
-  <script type="application/x-javascript"
+  <script type="application/javascript"
           src="chrome://browser/content/places/controller.js"/>
-  <script type="application/x-javascript"
+  <script type="application/javascript"
           src="chrome://browser/content/places/treeView.js"/>
-  <script type="application/x-javascript"
+  <script type="application/javascript"
           src="chrome://global/content/nsDragAndDrop.js"/>
 
   <!-- Bookmarks and history tooltip -->
   <tooltip id="bhTooltip" noautohide="true"
            onpopupshowing="return window.top.BookmarksEventHandler.fillInBHTooltip(document, event)">
     <vbox id="bhTooltipTextBox" flex="1">
       <label id="bhtTitleText" class="tooltip-label" />
       <label id="bhtUrlText" crop="center" class="tooltip-label" />
--- a/browser/components/places/content/utils.js
+++ b/browser/components/places/content/utils.js
@@ -226,17 +226,17 @@ var PlacesUIUtils = {
     if (aData.dateAdded)
       childTxns.push(this.ptm.editItemDateAdded(null, aData.dateAdded));
     if (aData.lastModified)
       childTxns.push(this.ptm.editItemLastModified(null, aData.lastModified));
     if (aData.tags) {
       var tags = aData.tags.split(", ");
       // filter out tags already present, so that undo doesn't remove them
       // from pre-existing bookmarks
-      var storedTags = PlacesUtils.tagging.getTagsForURI(itemURL, {});
+      var storedTags = PlacesUtils.tagging.getTagsForURI(itemURL);
       tags = tags.filter(function (aTag) {
         return (storedTags.indexOf(aTag) == -1);
       }, this);
       if (tags.length)
         childTxns.push(this.ptm.tagURI(itemURL, tags));
     }
 
     return this.ptm.createItem(itemURL, aContainer, aIndex, itemTitle, keyword,
@@ -1142,17 +1142,17 @@ var PlacesUIUtils = {
     var allBookmarksId;
 
     // Shortcuts to services.
     var bs = PlacesUtils.bookmarks;
     var as = PlacesUtils.annotations;
 
     // Get all items marked as being the left pane folder.  We should only have
     // one of them.
-    var items = as.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
+    var items = as.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO);
     if (items.length > 1) {
       // Something went wrong, we cannot have more than one left pane folder,
       // remove all left pane folders and continue.  We will create a new one.
       items.forEach(bs.removeItem);
     }
     else if (items.length == 1 && items[0] != -1) {
       leftPaneRoot = items[0];
       // Check organizer left pane version.
@@ -1177,17 +1177,17 @@ var PlacesUIUtils = {
     };
 
     if (leftPaneRoot != -1) {
       // A valid left pane folder has been found.
       // Build the leftPaneQueries Map.  This is used to quickly access them
       // associating a mnemonic name to the real item ids.
       delete this.leftPaneQueries;
       this.leftPaneQueries = {};
-      var items = as.getItemsWithAnnotation(ORGANIZER_QUERY_ANNO, {});
+      var items = as.getItemsWithAnnotation(ORGANIZER_QUERY_ANNO);
       // While looping through queries we will also check for titles validity.
       for (var i = 0; i < items.length; i++) {
         var queryName = as.getItemAnnotation(items[i], ORGANIZER_QUERY_ANNO);
         this.leftPaneQueries[queryName] = items[i];
         // Titles could have been corrupted or the user could have changed his
         // locale.  Check title is correctly set and eventually fix it.
         if (bs.getItemTitle(items[i]) != queriesTitles[queryName])
           bs.setItemTitle(items[i], queriesTitles[queryName]);
--- a/browser/components/places/src/nsPlacesTransactionsService.js
+++ b/browser/components/places/src/nsPlacesTransactionsService.js
@@ -686,17 +686,17 @@ placesRemoveItemTransaction.prototype = 
     }
     else {
       PlacesUtils.bookmarks.removeItem(this._id);
       if (this._uri) {
         // if this was the last bookmark (excluding tag-items and livemark
         // children, see getMostRecentBookmarkForURI) for the bookmark's url,
         // remove the url from tag containers as well.
         if (PlacesUtils.getMostRecentBookmarkForURI(this._uri) == -1) {
-          this._tags = PlacesUtils.tagging.getTagsForURI(this._uri, {});
+          this._tags = PlacesUtils.tagging.getTagsForURI(this._uri);
           PlacesUtils.tagging.untagURI(this._uri, this._tags);
         }
       }
     }
   },
 
   undoTransaction: function PRIT_undoTransaction() {
     if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {
@@ -771,17 +771,17 @@ function placesEditBookmarkURITransactio
 
 placesEditBookmarkURITransactions.prototype = {
   __proto__: placesBaseTransaction.prototype,
 
   doTransaction: function PEBUT_doTransaction() {
     this._oldURI = PlacesUtils.bookmarks.getBookmarkURI(this._id);
     PlacesUtils.bookmarks.changeBookmarkURI(this._id, this._newURI);
     // move tags from old URI to new URI
-    this._tags = PlacesUtils.tagging.getTagsForURI(this._oldURI, {});
+    this._tags = PlacesUtils.tagging.getTagsForURI(this._oldURI);
     if (this._tags.length != 0) {
       // only untag the old URI if this is the only bookmark
       if (PlacesUtils.getBookmarksForURI(this._oldURI, {}).length == 0)
         PlacesUtils.tagging.untagURI(this._oldURI, this._tags);
       PlacesUtils.tagging.tagURI(this._newURI, this._tags);
     }
   },
 
@@ -1152,17 +1152,17 @@ function placesUntagURITransaction(aURI,
     // Thus, we convert each tag given by its itemId to name.
     this._tags = aTags;
     for (var i=0; i < aTags.length; i++) {
       if (typeof(this._tags[i]) == "number")
         this._tags[i] = PlacesUtils.bookmarks.getItemTitle(this._tags[i]);
     }
   }
   else
-    this._tags = PlacesUtils.tagging.getTagsForURI(this._uri, {});
+    this._tags = PlacesUtils.tagging.getTagsForURI(this._uri);
 
   this.redoTransaction = this.doTransaction;
 }
 
 placesUntagURITransaction.prototype = {
   __proto__: placesBaseTransaction.prototype,
 
   doTransaction: function PUTU_doTransaction() {
--- a/browser/components/places/tests/browser/browser_0_library_left_pane_migration.js
+++ b/browser/components/places/tests/browser/browser_0_library_left_pane_migration.js
@@ -55,17 +55,17 @@ var windowObserver = {
       organizer.addEventListener("load", function onLoad(event) {
         organizer.removeEventListener("load", onLoad, false);
         executeSoon(function () {
           // Check left pane.
           ok(PlacesUIUtils.leftPaneFolderId > 0,
              "Left pane folder correctly created");
           var leftPaneItems =
             PlacesUtils.annotations
-                       .getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
+                       .getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO);
           is(leftPaneItems.length, 1,
              "We correctly have only 1 left pane folder");
           var leftPaneRoot = leftPaneItems[0];
           is(leftPaneRoot, PlacesUIUtils.leftPaneFolderId,
              "leftPaneFolderId getter has correct value");
           // Check version has been upgraded.
           var version =
             PlacesUtils.annotations.getItemAnnotation(leftPaneRoot,
@@ -94,17 +94,17 @@ function test() {
   // Sanity checks.
   ok(PlacesUtils, "PlacesUtils is running in chrome context");
   ok(PlacesUIUtils, "PlacesUIUtils is running in chrome context");
   ok(ORGANIZER_LEFTPANE_VERSION > 0,
      "Left pane version in chrome context, current version is: " + ORGANIZER_LEFTPANE_VERSION );
 
   // Check if we have any left pane folder already set, remove it eventually.
   var leftPaneItems = PlacesUtils.annotations
-                                 .getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
+                                 .getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO);
   if (leftPaneItems.length > 0) {
     // The left pane has already been created, touching it now would cause
     // next tests to rely on wrong values (and possibly crash)
     is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder");
     // Check version.
     var version = PlacesUtils.annotations.getItemAnnotation(leftPaneItems[0],
                                                             ORGANIZER_FOLDER_ANNO);
     is(version, ORGANIZER_LEFTPANE_VERSION, "Left pane version is actual");
@@ -120,17 +120,17 @@ function test() {
   PlacesUtils.annotations.setItemAnnotation(fakeLeftPaneRoot,
                                             ORGANIZER_FOLDER_ANNO,
                                             ORGANIZER_LEFTPANE_VERSION - 1,
                                             0,
                                             PlacesUtils.annotations.EXPIRE_NEVER);
 
   // Check fake left pane root has been correctly created.
   var leftPaneItems =
-    PlacesUtils.annotations.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
+    PlacesUtils.annotations.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO);
   is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder");
   is(leftPaneItems[0], fakeLeftPaneRoot, "left pane root itemId is correct");
 
   // Check version.
   var version = PlacesUtils.annotations.getItemAnnotation(fakeLeftPaneRoot,
                                                           ORGANIZER_FOLDER_ANNO);
   is(version, ORGANIZER_LEFTPANE_VERSION - 1, "Left pane version correctly set");
 
--- a/browser/components/places/tests/browser/browser_410196_paste_into_tags.js
+++ b/browser/components/places/tests/browser/browser_410196_paste_into_tags.js
@@ -96,17 +96,17 @@ function test() {
           ok(gh.isVisited(testURI1), MOZURISPEC + " is a visited url.");
         },
 
         makeTag: function() {
           // create an initial tag to work with
           var bmId = add_bookmark(PlacesUtils._uri(TEST_URL));
           ok(bmId > 0, "A bookmark was added");
           ts.tagURI(PlacesUtils._uri(TEST_URL), ["foo"]);
-          var tags = ts.getTagsForURI(PU._uri(TEST_URL), {});
+          var tags = ts.getTagsForURI(PU._uri(TEST_URL));
           is(tags[0], 'foo', "tag is foo");
         },
 
         focusTag: function (paste){
           // focus the new tag
           PO.selectLeftPaneQuery("Tags");
           var tags = PO._places.selectedNode;
           tags.containerOpen = true;
@@ -163,23 +163,23 @@ function test() {
           // re-focus the history again
           PO.selectLeftPaneQuery("History");
           var histContainer = PO._places.selectedNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
           histContainer.containerOpen = true;
           PO._places.selectNode(histContainer.getChild(0));
           var histNode = PO._content.view.nodeForTreeIndex(0);
           ok(histNode, "histNode exists: " + histNode.title);
           // check to see if the history node is tagged!
-          var tags = PU.tagging.getTagsForURI(PU._uri(MOZURISPEC), {});
+          var tags = PU.tagging.getTagsForURI(PU._uri(MOZURISPEC));
           ok(tags.length == 1, "history node is tagged: " + tags.length);
           // check if a bookmark was created
           var isBookmarked = PU.bookmarks.isBookmarked(PU._uri(MOZURISPEC));
           is(isBookmarked, true, MOZURISPEC + " is bookmarked");
           var bookmarkIds = PU.bookmarks.getBookmarkIdsForURI(
-                              PU._uri(histNode.uri), {});
+                              PU._uri(histNode.uri));
           ok(bookmarkIds.length > 0, "bookmark exists for the tagged history item: " + bookmarkIds);
         },
 
         checkForBookmarkInUI: function(){
           // is the bookmark visible in the UI?
           // get the Unsorted Bookmarks node
           PO.selectLeftPaneQuery("UnfiledBookmarks");
           // now we can see what is in the _content tree
@@ -189,17 +189,17 @@ function test() {
         },
 
         tagNode: null,
 
         cleanUp: function(){
           ts.untagURI(PU._uri(MOZURISPEC), ["foo"]);
           ts.untagURI(PU._uri(TEST_URL), ["foo"]);
           hs.removeAllPages();
-          var tags = ts.getTagsForURI(PU._uri(TEST_URL), {});
+          var tags = ts.getTagsForURI(PU._uri(TEST_URL));
           is(tags.length, 0, "tags are gone");
           bs.removeFolderChildren(bs.unfiledBookmarksFolder);
         }
       };
 
       tests.sanity();
       tests.makeHistVisit();
       tests.makeTag();
--- a/browser/components/places/tests/browser/browser_423515.js
+++ b/browser/components/places/tests/browser/browser_423515.js
@@ -147,17 +147,17 @@ function test() {
         for (var i = 0; i < node.childCount; i++) {
           var child = node.getChild(i);
           if (child.itemId == aId) {
             node.containerOpen = false;
             return child;
           }
         }
         node.containerOpen = false;
-        throw("Unable to find child node");
+        ok(false, "Unable to find child node");
         return null;
       }
 
       for (var i = 0; i < this.folders.length; i++) {
         var id = this.folders[i];
 
         is(PlacesControllerDragHelper.canMoveContainer(id),
            false, "shouldn't be able to move special folder id");
--- a/browser/components/places/tests/browser/browser_bookmarksProperties.js
+++ b/browser/components/places/tests/browser/browser_bookmarksProperties.js
@@ -203,17 +203,17 @@ gTests.push({
 
   setup: function() {
     // Add a bookmark in unsorted bookmarks folder.
     this._itemId = add_bookmark(PlacesUtils._uri(TEST_URL));
     ok(this._itemId > 0, "Correctly added a bookmark");
     // Add a tag to this bookmark.
     PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL),
                                ["testTag"]);
-    var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
+    var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL));
     is(tags[0], "testTag", "Correctly added a tag");
   },
 
   selectNode: function(tree) {
     tree.selectItems([this._itemId]);
     is(tree.selectedNode.itemId, this._itemId, "Bookmark has been selected");
   },
 
@@ -277,17 +277,17 @@ gTests.push({
 
   finish: function() {
     toggleSidebar(this.sidebar, false);
     runNextTest();
   },
 
   cleanup: function() {
     // Check tags have not changed.
-    var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
+    var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL));
     is(tags[0], "testTag", "Tag on node has not changed");
 
     // Cleanup.
     PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL), ["testTag"]);
     PlacesUtils.bookmarks.removeItem(this._itemId);
   }
 });
 
@@ -361,17 +361,17 @@ gTests.push({
 
   setup: function() {
     // Add a bookmark in unsorted bookmarks folder.
     this._itemId = add_bookmark(PlacesUtils._uri(TEST_URL));
     ok(this._itemId > 0, "Correctly added a bookmark");
     // Add a tag to this bookmark.
     PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL),
                                ["testTag"]);
-    var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
+    var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL));
     is(tags[0], "testTag", "Correctly added a tag");
   },
 
   selectNode: function(tree) {
     tree.selectItems([this._itemId]);
     is(tree.selectedNode.itemId, this._itemId, "Bookmark has been selected");
   },
 
@@ -435,17 +435,17 @@ gTests.push({
 
   finish: function() {
     toggleSidebar(this.sidebar, false);
     runNextTest();
   },
 
   cleanup: function() {
     // Check tags have not changed.
-    var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
+    var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL));
     is(tags[0], "testTag", "Tag on node has not changed");
 
     // Cleanup.
     PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL),
                                  ["testTag"]);
     PlacesUtils.bookmarks.removeItem(this._itemId);
   }
 });
--- a/browser/components/places/tests/browser/browser_library_left_pane_fixnames.js
+++ b/browser/components/places/tests/browser/browser_library_left_pane_fixnames.js
@@ -82,28 +82,28 @@ function test() {
   ok(ORGANIZER_LEFTPANE_VERSION > 0,
      "Left pane version in chrome context, current version is: " + ORGANIZER_LEFTPANE_VERSION );
 
   // Ensure left pane is initialized.
   ok(PlacesUIUtils.leftPaneFolderId > 0, "left pane folder is initialized");
 
   // Get the left pane folder.
   var leftPaneItems = PlacesUtils.annotations
-                                 .getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
+                                 .getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO);
 
   is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder");
   // Check version.
   var version = PlacesUtils.annotations
                            .getItemAnnotation(leftPaneItems[0],
                                               ORGANIZER_FOLDER_ANNO);
   is(version, ORGANIZER_LEFTPANE_VERSION, "Left pane version is actual");
 
   // Get all left pane queries.
   var items = PlacesUtils.annotations
-                         .getItemsWithAnnotation(ORGANIZER_QUERY_ANNO, {});
+                         .getItemsWithAnnotation(ORGANIZER_QUERY_ANNO);
   // Get current queries names.
   for (var i = 0; i < items.length; i++) {
     var itemId = items[i];
     var queryName = PlacesUtils.annotations
                                .getItemAnnotation(items[i],
                                                   ORGANIZER_QUERY_ANNO);
     leftPaneQueries.push({ name: queryName,
                            itemId: itemId,
--- a/browser/components/places/tests/browser/browser_library_middleclick.js
+++ b/browser/components/places/tests/browser/browser_library_middleclick.js
@@ -313,17 +313,18 @@ function runNextTest() {
     // Close Library window.
     gLibrary.close();
 
     // Remove tabs listeners.
     gBrowser.tabContainer.removeEventListener("TabOpen", gTabsListener, false);
     gBrowser.removeTabsProgressListener(gTabsListener);
 
     // Restore history.
-    gPrefService.clearUserPref(DISABLE_HISTORY_PREF);
+    if (gPrefService.prefHasUserValue(DISABLE_HISTORY_PREF))
+      gPrefService.clearUserPref(DISABLE_HISTORY_PREF);
 
     finish();
   }
 }
 
 function mouseEventOnCell(aTree, aRowIndex, aColumnIndex, aEventDetails) {
   var selection = aTree.view.selection;
   selection.select(aRowIndex);
--- a/browser/components/places/tests/browser/browser_library_search.js
+++ b/browser/components/places/tests/browser/browser_library_search.js
@@ -200,17 +200,17 @@ function search(aFolderId, aSearchStr, a
        "Sanity check: left pane tree should have selection after selecting!");
 
     // getFolders() on a History query returns an empty array, so no use
     // comparing against aFolderId in that case.
     if (aFolderId !== PlacesUIUtils.leftPaneQueries["History"]) {
       // contentTree.place should be equal to contentTree.getResult().root.uri,
       // but it's not until bug 476952 is fixed.
       var query = queryStringToQuery(contentTree.getResult().root.uri);
-      is(query.getFolders({}, {})[0], aFolderId,
+      is(query.getFolders()[0], aFolderId,
          "Content tree's folder should be what was selected in the left pane");
     }
   }
 
   // Second, ensure that searching updates the content tree and search UI
   // properly.
   var searchBox = doc.getElementById("searchFilter");
   searchBox.value = aSearchStr;
--- a/browser/components/places/tests/chrome/test_bug485100-change-case-loses-tag.xul
+++ b/browser/components/places/tests/chrome/test_bug485100-change-case-loses-tag.xul
@@ -99,24 +99,24 @@
       ok(gEditItemOverlay, "gEditItemOverlay is in context");
       gEditItemOverlay.initPanel(itemId);
 
       // add a tag
       document.getElementById("editBMPanel_tagsField").value = testTag;
       gEditItemOverlay.onTagsFieldBlur();
 
       // test that the tag has been added in the backend
-      is(ts.getTagsForURI(testURI, {})[0], testTag, "tags match");
+      is(ts.getTagsForURI(testURI)[0], testTag, "tags match");
 
       // change the tag
       document.getElementById("editBMPanel_tagsField").value = testTagUpper;
       gEditItemOverlay.onTagsFieldBlur();
 
       // test that the tag has been added in the backend
-      is(ts.getTagsForURI(testURI, {})[0], testTagUpper, "tags match");
+      is(ts.getTagsForURI(testURI)[0], testTagUpper, "tags match");
 
       // Cleanup.
       ts.untagURI(testURI, [testTag]);
       bs.removeItem(itemId);
     }
   ]]>
   </script>
 
--- a/browser/components/places/tests/chrome/test_multiple_left_pane.xul
+++ b/browser/components/places/tests/chrome/test_multiple_left_pane.xul
@@ -76,33 +76,33 @@
            "current version is: " + ORGANIZER_LEFTPANE_VERSION );
 
       var fakeLeftPanes = [];
       var as = PlacesUtils.annotations;
       var bs = PlacesUtils.bookmarks;
 
       // We need 2 left pane folders to simulate a corrupt profile.
       do {
-        let leftPaneItems = as.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
+        let leftPaneItems = as.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO);
         // Create a fake left pane folder.
         let fakeLeftPaneRoot = bs.createFolder(PlacesUtils.placesRootId, "",
                                                bs.DEFAULT_INDEX);
         as.setItemAnnotation(fakeLeftPaneRoot, ORGANIZER_FOLDER_ANNO,
                              ORGANIZER_LEFTPANE_VERSION, 0,
                              as.EXPIRE_NEVER);
         fakeLeftPanes.push(fakeLeftPaneRoot);
       } while (fakeLeftPanes.length < 2);
 
       // Initialize the left pane queries.
       PlacesUIUtils.leftPaneFolderId;
 
       // Check left pane.
       ok(PlacesUIUtils.leftPaneFolderId > 0,
          "Left pane folder correctly created");
-      var leftPaneItems = as.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
+      var leftPaneItems = as.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO);
       is(leftPaneItems.length, 1,
          "We correctly have only 1 left pane folder");
 
       // Check that all old left pane items have been removed.
       fakeLeftPanes.forEach(function(aItemId) {
         try {
           bs.getItemTitle(aItemId);
           throw("This folder should have been removed");
--- a/browser/components/places/tests/unit/test_384370.js
+++ b/browser/components/places/tests/unit/test_384370.js
@@ -302,17 +302,17 @@ function testUnfiledBookmarks() {
   }
   rootNode.containerOpen = false;
 }
 
 function testTags() {
   for each(let {uri: u, tags: t} in tagData) {
     var i = 0;
     dump("test tags for " + u.spec + ": " + t + "\n");
-    var tt = PlacesUtils.tagging.getTagsForURI(u, {});
+    var tt = PlacesUtils.tagging.getTagsForURI(u);
     dump("true tags for " + u.spec + ": " + tt + "\n");
     do_check_true(t.every(function(el) {
       i++;
       return tt.indexOf(el) > -1;
     }));
     do_check_eq(i, t.length);
   }
 }
--- a/browser/components/places/tests/unit/test_398914.js
+++ b/browser/components/places/tests/unit/test_398914.js
@@ -165,17 +165,17 @@ function run_test() {
   var bm2da = bmsvc.getItemDateAdded(bm2);
   var bm2lm = bmsvc.getItemLastModified(bm2);
   LOG("bm2 dateAdded: " + bm2da + ", lastModified: " + bm2lm);
 
   do_check_eq(bm1da, bm2da);
   do_check_eq(bm1lm, bm2lm);
 
 
-  var ids = bmsvc.getBookmarkIdsForURI(testURI, {});
+  var ids = bmsvc.getBookmarkIdsForURI(testURI);
   do_check_eq(ids[0], bm2);
   do_check_eq(ids[1], bm1);
 
   [url, postdata] = PlacesUtils.getURLAndPostDataForKeyword("foo");
   do_check_eq(testURI.spec, url);
   do_check_eq(postdata, "pdata2");
 
   // cleanup
--- a/browser/components/places/tests/unit/test_421483.js
+++ b/browser/components/places/tests/unit/test_421483.js
@@ -71,52 +71,52 @@ try {
 const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
 const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
 
 // main
 function run_test() {
   // TEST 1: smart bookmarks disabled
   pref.setIntPref("browser.places.smartBookmarksVersion", -1);
   gluesvc.ensurePlacesDefaultQueriesInitialized();
-  var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, {});
+  var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
   do_check_eq(smartBookmarkItemIds.length, 0);
   // check that pref has not been bumped up
   do_check_eq(pref.getIntPref("browser.places.smartBookmarksVersion"), -1);
 
   // TEST 2: create smart bookmarks
   pref.setIntPref("browser.places.smartBookmarksVersion", 0);
   gluesvc.ensurePlacesDefaultQueriesInitialized();
-  smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, {});
+  smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
   do_check_neq(smartBookmarkItemIds.length, 0);
   // check that pref has been bumped up
   do_check_true(pref.getIntPref("browser.places.smartBookmarksVersion") > 0);
 
   var smartBookmarksCount = smartBookmarkItemIds.length;
 
   // TEST 3: smart bookmarks restore
   // remove one smart bookmark and restore
   bmsvc.removeItem(smartBookmarkItemIds[0]);
   pref.setIntPref("browser.places.smartBookmarksVersion", 0);
   gluesvc.ensurePlacesDefaultQueriesInitialized();
-  smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, {});
+  smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
   do_check_eq(smartBookmarkItemIds.length, smartBookmarksCount);
   // check that pref has been bumped up
   do_check_true(pref.getIntPref("browser.places.smartBookmarksVersion") > 0);
 
   // TEST 4: move a smart bookmark, change its title, then restore
   // smart bookmark should be restored in place
   var parent = bmsvc.getFolderIdForItem(smartBookmarkItemIds[0]);
   var oldTitle = bmsvc.getItemTitle(smartBookmarkItemIds[0]);
   // create a subfolder and move inside it
   var newParent = bmsvc.createFolder(parent, "test", bmsvc.DEFAULT_INDEX);
   bmsvc.moveItem(smartBookmarkItemIds[0], newParent, bmsvc.DEFAULT_INDEX);
   // change title
   bmsvc.setItemTitle(smartBookmarkItemIds[0], "new title");
   // restore
   pref.setIntPref("browser.places.smartBookmarksVersion", 0);
   gluesvc.ensurePlacesDefaultQueriesInitialized();
-  smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, {});
+  smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
   do_check_eq(smartBookmarkItemIds.length, smartBookmarksCount);
   do_check_eq(bmsvc.getFolderIdForItem(smartBookmarkItemIds[0]), newParent);
   do_check_eq(bmsvc.getItemTitle(smartBookmarkItemIds[0]), oldTitle);
   // check that pref has been bumped up
   do_check_true(pref.getIntPref("browser.places.smartBookmarksVersion") > 0);
 }
--- a/browser/components/places/tests/unit/test_browserGlue_distribution.js
+++ b/browser/components/places/tests/unit/test_browserGlue_distribution.js
@@ -42,17 +42,16 @@
  * bookmark on init, we should not try to import.
  */
 
 const PREF_SMART_BOOKMARKS_VERSION = "browser.places.smartBookmarksVersion";
 const PREF_BMPROCESSED = "distribution.516444.bookmarksProcessed";
 const PREF_DISTRIBUTION_ID = "distribution.id";
 
 const TOPIC_FINAL_UI_STARTUP = "final-ui-startup";
-const TOPIC_PLACES_INIT_COMPLETE = "places-init-complete";
 const TOPIC_CUSTOMIZATION_COMPLETE = "distribution-customization-complete";
 
 let os = Cc["@mozilla.org/observer-service;1"].
          getService(Ci.nsIObserverService);
 
 let observer = {
   observe: function(aSubject, aTopic, aData) {
     if (aTopic == TOPIC_CUSTOMIZATION_COMPLETE) {
@@ -90,20 +89,19 @@ function run_test() {
            getService(Ci.nsINavHistoryService);
   // Check a new database has been created.
   // nsBrowserGlue will use databaseStatus to manage initialization.
   do_check_eq(hs.databaseStatus, hs.DATABASE_STATUS_CREATE);
 
   // Initialize nsBrowserGlue.
   Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIBrowserGlue);
 
-  // Places initialization has already happened, so we need to simulate a new
-  // one.  This will force browserGlue::_initPlaces().
   os.notifyObservers(null, TOPIC_FINAL_UI_STARTUP, null);
-  os.notifyObservers(null, TOPIC_PLACES_INIT_COMPLETE, null);
+  // places-init-complete is an enqueued notification so it will be notified
+  // when exiting from this scope.
 
   do_test_pending();
   // Test will continue on customization complete notification.
 }
 
 function continue_test() {
   let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
            getService(Ci.nsINavBookmarksService);
--- a/browser/components/places/tests/unit/test_placesTxn.js
+++ b/browser/components/places/tests/unit/test_placesTxn.js
@@ -179,65 +179,65 @@ function run_test() {
   do_check_eq(observer._itemRemovedId, folderId);
   do_check_eq(observer._itemRemovedFolder, root);
   do_check_eq(observer._itemRemovedIndex, bmStartIndex);
 
   // Test creating an item
   // Create to Root
   var txn2 = ptSvc.createItem(uri("http://www.example.com"), root, bmStartIndex, "Testing1");
   ptSvc.doTransaction(txn2); // Also testing doTransaction
-  var b = (bmsvc.getBookmarkIdsForURI(uri("http://www.example.com"), {}))[0];
+  var b = (bmsvc.getBookmarkIdsForURI(uri("http://www.example.com")))[0];
   do_check_eq(observer._itemAddedId, b);
   do_check_eq(observer._itemAddedIndex, bmStartIndex);
   do_check_true(bmsvc.isBookmarked(uri("http://www.example.com")));
   txn2.undoTransaction();
   do_check_eq(observer._itemRemovedId, b);
   do_check_eq(observer._itemRemovedIndex, bmStartIndex);
   do_check_false(bmsvc.isBookmarked(uri("http://www.example.com")));
   txn2.redoTransaction();
   do_check_true(bmsvc.isBookmarked(uri("http://www.example.com")));
-  var newId = (bmsvc.getBookmarkIdsForURI(uri("http://www.example.com"), {}))[0];
+  var newId = (bmsvc.getBookmarkIdsForURI(uri("http://www.example.com")))[0];
   do_check_eq(observer._itemAddedIndex, bmStartIndex);
   do_check_eq(observer._itemAddedParent, root);
   do_check_eq(observer._itemAddedId, newId);
   txn2.undoTransaction();
   do_check_eq(observer._itemRemovedId, newId);
   do_check_eq(observer._itemRemovedFolder, root);
   do_check_eq(observer._itemRemovedIndex, bmStartIndex);
 
   // Create item to a folder
   var txn2a = ptSvc.createFolder("Folder", root, bmStartIndex);
   ptSvc.doTransaction(txn2a);
   var fldrId = observer._itemAddedId;
   do_check_eq(bmsvc.getItemTitle(fldrId), "Folder");
 
   var txn2b = ptSvc.createItem(uri("http://www.example2.com"), fldrId, bmStartIndex, "Testing1b");
   ptSvc.doTransaction(txn2b);
-  var b2 = (bmsvc.getBookmarkIdsForURI(uri("http://www.example2.com"), {}))[0];
+  var b2 = (bmsvc.getBookmarkIdsForURI(uri("http://www.example2.com")))[0];
   do_check_eq(observer._itemAddedId, b2);
   do_check_eq(observer._itemAddedIndex, bmStartIndex);
   do_check_true(bmsvc.isBookmarked(uri("http://www.example2.com")));
   txn2b.undoTransaction();
   do_check_eq(observer._itemRemovedId, b2);
   do_check_eq(observer._itemRemovedIndex, bmStartIndex);
   txn2b.redoTransaction();
-  newId = (bmsvc.getBookmarkIdsForURI(uri("http://www.example2.com"), {}))[0];
+  newId = (bmsvc.getBookmarkIdsForURI(uri("http://www.example2.com")))[0];
   do_check_eq(observer._itemAddedIndex, bmStartIndex);
   do_check_eq(observer._itemAddedParent, fldrId);
   do_check_eq(observer._itemAddedId, newId);
   txn2b.undoTransaction();
   do_check_eq(observer._itemRemovedId, newId);
   do_check_eq(observer._itemRemovedFolder, fldrId);
   do_check_eq(observer._itemRemovedIndex, bmStartIndex);
 
   // Testing moving an item
   ptSvc.doTransaction(ptSvc.createItem(uri("http://www.example3.com"), root, -1, "Testing2"));
   ptSvc.doTransaction(ptSvc.createItem(uri("http://www.example3.com"), root, -1, "Testing3"));
   ptSvc.doTransaction(ptSvc.createItem(uri("http://www.example3.com"), fldrId, -1, "Testing4"));
-  var bkmkIds = bmsvc.getBookmarkIdsForURI(uri("http://www.example3.com"), {});
+  var bkmkIds = bmsvc.getBookmarkIdsForURI(uri("http://www.example3.com"));
   bkmkIds.sort();
   var bkmk1Id = bkmkIds[0];
   var bkmk2Id = bkmkIds[1];
   var bkmk3Id = bkmkIds[2];
 
   // Moving items between the same folder
   var txn3 = ptSvc.moveItem(bkmk1Id, root, -1);
   txn3.doTransaction();
@@ -558,17 +558,17 @@ function run_test() {
 
   // sortFolderByName
   ptSvc.doTransaction(ptSvc.createFolder("Sorting folder", root, bmStartIndex, [], null));
   var srtFldId = observer._itemAddedId;
   do_check_eq(bmsvc.getItemTitle(srtFldId), "Sorting folder");
   ptSvc.doTransaction(ptSvc.createItem(uri("http://www.sortingtest.com"), srtFldId, -1, "c"));
   ptSvc.doTransaction(ptSvc.createItem(uri("http://www.sortingtest.com"), srtFldId, -1, "b"));   
   ptSvc.doTransaction(ptSvc.createItem(uri("http://www.sortingtest.com"), srtFldId, -1, "a"));
-  var b = bmsvc.getBookmarkIdsForURI(uri("http://www.sortingtest.com"), {});
+  var b = bmsvc.getBookmarkIdsForURI(uri("http://www.sortingtest.com"));
   b.sort();
   var b1 = b[0];
   var b2 = b[1];
   var b3 = b[2];
   do_check_eq(0, bmsvc.getItemIndex(b1));
   do_check_eq(1, bmsvc.getItemIndex(b2));
   do_check_eq(2, bmsvc.getItemIndex(b3));
   var txn17 = ptSvc.sortFolderByName(srtFldId);
@@ -590,33 +590,33 @@ function run_test() {
   do_check_eq(2, bmsvc.getItemIndex(b3));
 
   // editBookmarkMicrosummary
   var tmpMs = mss.createMicrosummary(uri("http://testmicro.com"), 
                                      uri("http://dietrich.ganx4.com/mozilla/test-microsummary.xml"));
   ptSvc.doTransaction(
   ptSvc.createItem(uri("http://dietrich.ganx4.com/mozilla/test-microsummary-content.php"),
                    root, -1, "micro test", null, null, null));
-  var bId = (bmsvc.getBookmarkIdsForURI(uri("http://dietrich.ganx4.com/mozilla/test-microsummary-content.php"),{}))[0];
+  var bId = (bmsvc.getBookmarkIdsForURI(uri("http://dietrich.ganx4.com/mozilla/test-microsummary-content.php")))[0];
   do_check_true(!mss.hasMicrosummary(bId));
   var txn18 = ptSvc.editBookmarkMicrosummary(bId, tmpMs);
   txn18.doTransaction();
   do_check_eq(observer._itemChangedId, bId);
   do_check_true(mss.hasMicrosummary(bId));
   txn18.undoTransaction();
   do_check_eq(observer._itemChangedId, bId);
   do_check_true(!mss.hasMicrosummary(bId));
 
   // Testing edit Post Data
   const POST_DATA_ANNO = "bookmarkProperties/POSTData";
   var postData = "foo";
   var postDataURI = uri("http://foo.com");
   ptSvc.doTransaction(
     ptSvc.createItem(postDataURI, root, -1, "postdata test", null, null, null));
-  var postDataId = (bmsvc.getBookmarkIdsForURI(postDataURI,{}))[0];
+  var postDataId = (bmsvc.getBookmarkIdsForURI(postDataURI))[0];
   var postDataTxn = ptSvc.editBookmarkPostData(postDataId, postData);
   postDataTxn.doTransaction();
   do_check_true(annosvc.itemHasAnnotation(postDataId, POST_DATA_ANNO))
   do_check_eq(annosvc.getItemAnnotation(postDataId, POST_DATA_ANNO), postData);
   postDataTxn.undoTransaction();
   do_check_false(annosvc.itemHasAnnotation(postDataId, POST_DATA_ANNO))
 
   // Test editing item date added
@@ -636,28 +636,28 @@ function run_test() {
   do_check_eq(newModified, bmsvc.getItemLastModified(bkmk1Id));
   eilmTxn.undoTransaction();
   do_check_eq(oldModified, bmsvc.getItemLastModified(bkmk1Id));
 
   // Test tagURI/untagURI
   var tagURI = uri("http://foo.tld");
   var tagTxn = ptSvc.tagURI(tagURI, ["foo", "bar"]);
   tagTxn.doTransaction();
-  do_check_eq(uneval(tagssvc.getTagsForURI(tagURI, { })), uneval(["bar","foo"]));
+  do_check_eq(uneval(tagssvc.getTagsForURI(tagURI)), uneval(["bar","foo"]));
   tagTxn.undoTransaction();
-  do_check_true(tagssvc.getTagsForURI(tagURI, { }).length == 0);
+  do_check_eq(tagssvc.getTagsForURI(tagURI).length, 0);
   tagTxn.redoTransaction();
-  do_check_eq(uneval(tagssvc.getTagsForURI(tagURI, { })), uneval(["bar","foo"]));
+  do_check_eq(uneval(tagssvc.getTagsForURI(tagURI)), uneval(["bar","foo"]));
   var untagTxn = ptSvc.untagURI(tagURI, ["bar"]);
   untagTxn.doTransaction();
-  do_check_eq(uneval(tagssvc.getTagsForURI(tagURI, { })), uneval(["foo"]));
+  do_check_eq(uneval(tagssvc.getTagsForURI(tagURI)), uneval(["foo"]));
   untagTxn.undoTransaction();
-  do_check_eq(uneval(tagssvc.getTagsForURI(tagURI, { })), uneval(["bar","foo"]));
+  do_check_eq(uneval(tagssvc.getTagsForURI(tagURI)), uneval(["bar","foo"]));
   untagTxn.redoTransaction();
-  do_check_eq(uneval(tagssvc.getTagsForURI(tagURI, { })), uneval(["foo"]));
+  do_check_eq(uneval(tagssvc.getTagsForURI(tagURI)), uneval(["foo"]));
 
   // Test aggregate removeItem transaction
   var bkmk1Id = bmsvc.insertBookmark(root, uri("http://www.mozilla.org/"), 0, "Mozilla");
   var bkmk2Id = bmsvc.insertSeparator(root, 1);
   var bkmk3Id = bmsvc.createFolder(root, "folder", 2);
   var bkmk3_1Id = bmsvc.insertBookmark(bkmk3Id, uri("http://www.mozilla.org/"), 0, "Mozilla");
   var bkmk3_2Id = bmsvc.insertSeparator(bkmk3Id, 1);
   var bkmk3_3Id = bmsvc.createFolder(bkmk3Id, "folder", 2);
@@ -746,29 +746,29 @@ function run_test() {
                            value: 123,
                            expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
   childTxns.push(ptSvc.setItemAnnotation(null, itemChildAnnoObj));
   var itemWChildTxn = ptSvc.createItem(uri("http://www.example.com"), root,
                                        bmStartIndex, "Testing1", null, null,
                                        childTxns);
   try {
     ptSvc.doTransaction(itemWChildTxn); // Also testing doTransaction
-    var itemId = (bmsvc.getBookmarkIdsForURI(uri("http://www.example.com"), {}))[0];
+    var itemId = (bmsvc.getBookmarkIdsForURI(uri("http://www.example.com")))[0];
     do_check_eq(observer._itemAddedId, itemId);
     do_check_eq(newDateAdded, bmsvc.getItemDateAdded(itemId));
     do_check_eq(observer._itemChangedProperty, "testAnno/testInt");
     do_check_eq(observer._itemChanged_isAnnotationProperty, true);
     do_check_true(annosvc.itemHasAnnotation(itemId, itemChildAnnoObj.name))
     do_check_eq(annosvc.getItemAnnotation(itemId, itemChildAnnoObj.name),
                 itemChildAnnoObj.value);
     itemWChildTxn.undoTransaction();
     do_check_eq(observer._itemRemovedId, itemId);
     itemWChildTxn.redoTransaction();
     do_check_true(bmsvc.isBookmarked(uri("http://www.example.com")));
-    var newId = (bmsvc.getBookmarkIdsForURI(uri("http://www.example.com"), {}))[0];
+    var newId = (bmsvc.getBookmarkIdsForURI(uri("http://www.example.com")))[0];
     do_check_eq(newDateAdded, bmsvc.getItemDateAdded(newId));
     do_check_eq(observer._itemAddedId, newId);
     do_check_eq(observer._itemChangedProperty, "testAnno/testInt");
     do_check_eq(observer._itemChanged_isAnnotationProperty, true);
     do_check_true(annosvc.itemHasAnnotation(newId, itemChildAnnoObj.name))
     do_check_eq(annosvc.getItemAnnotation(newId, itemChildAnnoObj.name),
                 itemChildAnnoObj.value);
     itemWChildTxn.undoTransaction();
@@ -777,24 +777,24 @@ function run_test() {
     do_throw("Setting a child transaction in a createItem transaction did throw: " + ex);
   }
 
   // Create a folder with child item transactions.
   var childItemTxn = ptSvc.createItem(uri("http://www.childItem.com"), root, bmStartIndex, "childItem");
   var folderWChildItemTxn = ptSvc.createFolder("Folder", root, bmStartIndex, null, [childItemTxn]);
   try {
     ptSvc.doTransaction(folderWChildItemTxn);
-    var childItemId = (bmsvc.getBookmarkIdsForURI(uri("http://www.childItem.com"), {}))[0];
+    var childItemId = (bmsvc.getBookmarkIdsForURI(uri("http://www.childItem.com")))[0];
     do_check_eq(observer._itemAddedId, childItemId);
     do_check_eq(observer._itemAddedIndex, 0);
     do_check_true(bmsvc.isBookmarked(uri("http://www.childItem.com")));
     folderWChildItemTxn.undoTransaction();
     do_check_false(bmsvc.isBookmarked(uri("http://www.childItem.com")));
     folderWChildItemTxn.redoTransaction();
-    var newchildItemId = (bmsvc.getBookmarkIdsForURI(uri("http://www.childItem.com"), {}))[0];
+    var newchildItemId = (bmsvc.getBookmarkIdsForURI(uri("http://www.childItem.com")))[0];
     do_check_eq(observer._itemAddedIndex, 0);
     do_check_eq(observer._itemAddedId, newchildItemId);
     do_check_true(bmsvc.isBookmarked(uri("http://www.childItem.com")));
     folderWChildItemTxn.undoTransaction();
     do_check_false(bmsvc.isBookmarked(uri("http://www.childItem.com")));
   } catch (ex) {
     do_throw("Setting a child item transaction in a createFolder transaction did throw: " + ex);
   }
--- a/browser/components/preferences/advanced-scripts.xul
+++ b/browser/components/preferences/advanced-scripts.xul
@@ -58,17 +58,17 @@
      <preference id="dom.disable_window_move_resize" name="dom.disable_window_move_resize" type="bool" inverted="true"/>
      <preference id="dom.disable_window_flip"        name="dom.disable_window_flip"        type="bool" inverted="true"/>
      <preference id="dom.disable_window_open_feature.status" inverted="true"
                  name="dom.disable_window_open_feature.status" type="bool"/>
      <preference id="dom.disable_window_status_change" inverted="true"
                  name="dom.disable_window_status_change" type="bool"/>
     </preferences>
     
-    <script type="application/x-javascript" src="chrome://browser/content/preferences/advanced-scripts.js"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/advanced-scripts.js"/>
 
     <stringbundle id="preferencesBundle" src="chrome://browser/locale/preferences/preferences.properties"/>
 
     <description value="&allowScripts.label;"/>
 
     <checkbox id="moveResizeWindows" label="&moveResizeWindows.label;" 
               accesskey="&moveResizeWindows.accesskey;"
               preference="dom.disable_window_move_resize"/>
--- a/browser/components/preferences/advanced.js
+++ b/browser/components/preferences/advanced.js
@@ -214,19 +214,19 @@ var gAdvancedPane = {
                                         "", params);
   },
 
   // XXX: duplicated in browser.js
   _getOfflineAppUsage: function (host, groups)
   {
     var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
                        getService(Components.interfaces.nsIApplicationCacheService);
-    if (!groups) {
-      groups = cacheService.getGroups({});
-    }
+    if (!groups)
+      groups = cacheService.getGroups();
+
     var ios = Components.classes["@mozilla.org/network/io-service;1"].
               getService(Components.interfaces.nsIIOService);
 
     var usage = 0;
     for (var i = 0; i < groups.length; i++) {
       var uri = ios.newURI(groups[i], null, null);
       if (uri.asciiHost == host) {
         var cache = cacheService.getActiveCache(groups[i]);
@@ -251,17 +251,17 @@ var gAdvancedPane = {
 
     var list = document.getElementById("offlineAppsList");
     while (list.firstChild) {
       list.removeChild(list.firstChild);
     }
 
     var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
                        getService(Components.interfaces.nsIApplicationCacheService);
-    var groups = cacheService.getGroups({});
+    var groups = cacheService.getGroups();
 
     var bundle = document.getElementById("bundlePreferences");
 
     var enumerator = pm.enumerator;
     while (enumerator.hasMoreElements()) {
       var perm = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
       if (perm.type == "offline-app" &&
           perm.capability != Components.interfaces.nsIPermissionManager.DEFAULT_ACTION &&
@@ -311,17 +311,17 @@ var gAdvancedPane = {
     if (result != 0)
       return;
 
     // clear offline cache entries
     var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
                        getService(Components.interfaces.nsIApplicationCacheService);
     var ios = Components.classes["@mozilla.org/network/io-service;1"].
               getService(Components.interfaces.nsIIOService);
-    var groups = cacheService.getGroups({});
+    var groups = cacheService.getGroups();
     for (var i = 0; i < groups.length; i++) {
         var uri = ios.newURI(groups[i], null, null);
         if (uri.asciiHost == host) {
             var cache = cacheService.getActiveCache(groups[i]);
             cache.discard();
         }
     }
 
--- a/browser/components/preferences/advanced.xul
+++ b/browser/components/preferences/advanced.xul
@@ -122,17 +122,17 @@
                   type="bool"/>
     </preferences>
     
 #ifdef HAVE_SHELL_SERVICE
     <stringbundle id="bundleShell" src="chrome://browser/locale/shellservice.properties"/>
     <stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
 #endif
 
-    <script type="application/x-javascript" src="chrome://browser/content/preferences/advanced.js"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/advanced.js"/>
 
     <tabbox id="advancedPrefs" flex="1"
             onselect="gAdvancedPane.tabSelectionChanged();">
 
       <tabs id="tabsElement">
         <tab id="generalTab" label="&generalTab.label;" helpTopic="prefs-advanced-general"/>
         <tab id="networkTab" label="&networkTab.label;" helpTopic="prefs-advanced-network"/>
         <tab id="updateTab" label="&updateTab.label;"  helpTopic="prefs-advanced-update"/>
--- a/browser/components/preferences/applications.xul
+++ b/browser/components/preferences/applications.xul
@@ -98,17 +98,17 @@
                   name="browser.audioFeeds.handlers.webservice"
                   type="string"/>
 
       <preference id="pref.downloads.disable_button.edit_actions"
                   name="pref.downloads.disable_button.edit_actions"
                   type="bool"/>
     </preferences>
 
-    <script type="application/x-javascript" src="chrome://browser/content/preferences/applications.js"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/applications.js"/>
 
     <keyset>
       <key key="&focusSearch1.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
       <key key="&focusSearch2.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
     </keyset>
 
     <hbox>
       <textbox id="filter" flex="1"
--- a/browser/components/preferences/connection.xul
+++ b/browser/components/preferences/connection.xul
@@ -88,17 +88,17 @@
       <preference id="network.proxy.backup.ssl"          name="network.proxy.backup.ssl"          type="string"/>
       <preference id="network.proxy.backup.ssl_port"     name="network.proxy.backup.ssl_port"     type="int"/>
       <preference id="network.proxy.backup.socks"        name="network.proxy.backup.socks"        type="string"/>
       <preference id="network.proxy.backup.socks_port"   name="network.proxy.backup.socks_port"   type="int"/>
       <preference id="network.proxy.backup.gopher"       name="network.proxy.backup.gopher"       type="string"/>
       <preference id="network.proxy.backup.gopher_port"  name="network.proxy.backup.gopher_port"  type="int"/>
     </preferences>
     
-    <script type="application/x-javascript" src="chrome://browser/content/preferences/connection.js"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/connection.js"/>
 
     <stringbundle id="preferencesBundle" src="chrome://browser/locale/preferences/preferences.properties"/>
 
     <groupbox>
       <caption label="&proxyTitle.label;"/>
 
       <radiogroup id="networkProxyType" preference="network.proxy.type"
                   onsyncfrompreference="return gConnectionsDialog.readProxyType();">
--- a/browser/components/preferences/content.xul
+++ b/browser/components/preferences/content.xul
@@ -70,18 +70,18 @@
 
       <!-- FONTS -->
       <preference id="font.language.group"
                   name="font.language.group"
                   type="wstring"
                   onchange="gContentPane._rebuildFonts();"/>
     </preferences>
     
-    <script type="application/x-javascript" src="chrome://mozapps/content/preferences/fontbuilder.js"/>
-    <script type="application/x-javascript" src="chrome://browser/content/preferences/content.js"/>
+    <script type="application/javascript" src="chrome://mozapps/content/preferences/fontbuilder.js"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/content.js"/>
 
     <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
 
     <!-- various checkboxes, font-fu -->
     <groupbox id="miscGroup">
       <grid id="contentGrid">
         <columns>
           <column flex="1"/>
--- a/browser/components/preferences/fonts.xul
+++ b/browser/components/preferences/fonts.xul
@@ -72,18 +72,18 @@
       <preference id="font.language.group"  name="font.language.group"  type="wstring"/>
       <preference id="browser.display.use_document_fonts"
                   name="browser.display.use_document_fonts"
                   type="int"/>
       <preference id="intl.charset.default" name="intl.charset.default" type="wstring"/>
     </preferences>
     
     <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
-    <script type="application/x-javascript" src="chrome://mozapps/content/preferences/fontbuilder.js"/>
-    <script type="application/x-javascript" src="chrome://browser/content/preferences/fonts.js"/>
+    <script type="application/javascript" src="chrome://mozapps/content/preferences/fontbuilder.js"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/fonts.js"/>
 
     <!-- Fonts for: [ Language ] -->
     <groupbox>
       <caption>
         <hbox align="center">
           <label accesskey="&language.accesskey;" control="selectLangs">&language.label;</label>
         </hbox>
         <menulist id="selectLangs" preference="font.language.group"
--- a/browser/components/preferences/languages.xul
+++ b/browser/components/preferences/languages.xul
@@ -67,17 +67,17 @@
       <preference id="pref.browser.language.disable_button.down"
                   name="pref.browser.language.disable_button.down"
                   type="bool"/>
       <preference id="pref.browser.language.disable_button.remove"
                   name="pref.browser.language.disable_button.remove"
                   type="bool"/>
     </preferences>
 
-    <script type="application/x-javascript" src="chrome://browser/content/preferences/languages.js"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/languages.js"/>
 
     <stringbundleset id="languageSet">
       <stringbundle id="bundleRegions"      src="chrome://global/locale/regionNames.properties"/>
       <stringbundle id="bundleLanguages"    src="chrome://global/locale/languageNames.properties"/>
       <stringbundle id="bundlePreferences"  src="chrome://browser/locale/preferences/preferences.properties"/>
       <stringbundle id="bundleAccepted"     src="resource://gre/res/language.properties"/>
     </stringbundleset>
 
--- a/browser/components/preferences/main.xul
+++ b/browser/components/preferences/main.xul
@@ -49,17 +49,17 @@
 
 <overlay id="MainPaneOverlay"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
            
   <prefpane id="paneMain" 
             onpaneload="gMainPane.init();"
             helpTopic="prefs-main">
 
-    <script type="application/x-javascript" src="chrome://browser/content/preferences/main.js"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/main.js"/>
 
     <preferences id="mainPreferences">
       <!-- XXX Button preferences -->
 
       <!-- Startup -->
       <preference id="browser.startup.page"
                   name="browser.startup.page"
                   type="int"/>
--- a/browser/components/preferences/privacy.xul
+++ b/browser/components/preferences/privacy.xul
@@ -115,17 +115,17 @@
                   name="browser.privatebrowsing.keep_current_session"
                   instantApply="true"
                   type="bool"/>
 
     </preferences>
     
     <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
     
-    <script type="application/x-javascript" src="chrome://browser/content/preferences/privacy.js"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/privacy.js"/>
 
     <!-- History -->
     <groupbox id="historyGroup">
       <caption label="&history.label;"/>
 
       <hbox align="center">
         <label id="historyModeLabel"
                control="historyMode"
--- a/browser/components/preferences/security.xul
+++ b/browser/components/preferences/security.xul
@@ -71,17 +71,17 @@
                   name="browser.safebrowsing.enabled"
                   type="bool"/>
 
       <!-- Passwords -->
       <preference id="signon.rememberSignons" name="signon.rememberSignons" type="bool"/>
 
     </preferences>
     
-    <script type="application/x-javascript" src="chrome://browser/content/preferences/security.js"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/security.js"/>
     
     <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
 
     <!-- addons, forgery (phishing) UI -->
     <groupbox id="addonsPhishingGroup"
               xmlns:aaa="http://www.w3.org/2005/07/aaa">
       <hbox id="addonInstallBox">
         <checkbox id="warnAddonInstall" flex="1"
--- a/browser/components/preferences/selectBookmark.xul
+++ b/browser/components/preferences/selectBookmark.xul
@@ -11,17 +11,17 @@
 
 <dialog id="selectBookmarkDialog"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         title="&selectBookmark.title;" style="width: 32em;"
         persist="screenX screenY width height" screenX="24" screenY="24"      
         onload="SelectBookmarkDialog.init();" 
         ondialogaccept="SelectBookmarkDialog.accept();">
 
-  <script type="application/x-javascript"
+  <script type="application/javascript"
           src="chrome://browser/content/preferences/selectBookmark.js"/>
   
   <description>&selectBookmark.label;</description>
 
   <separator class="thin"/>
 
   <tree id="bookmarks" flex="1" type="places" 
         style="height: 15em;" 
--- a/browser/components/preferences/tabs.xul
+++ b/browser/components/preferences/tabs.xul
@@ -55,17 +55,17 @@
     <preferences id="tabsPreferences">
       <preference id="browser.link.open_newwindow"     name="browser.link.open_newwindow"     type="int"/>
       <preference id="browser.tabs.autoHide"           name="browser.tabs.autoHide"           type="bool" inverted="true"/>
       <preference id="browser.tabs.loadInBackground"   name="browser.tabs.loadInBackground"   type="bool" inverted="true"/>
       <preference id="browser.tabs.warnOnClose"        name="browser.tabs.warnOnClose"        type="bool"/>
       <preference id="browser.tabs.warnOnOpen"         name="browser.tabs.warnOnOpen"         type="bool"/>
     </preferences>
     
-    <script type="application/x-javascript" src="chrome://browser/content/preferences/tabs.js"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/tabs.js"/>
 
     <!-- XXX flex below is a hack because wrapping checkboxes don't reflow
              properly; see bug 349098 -->
     <vbox id="tabPrefsBox" align="start" flex="1">
       <checkbox id="linkTargeting" label="&newWindowsAsTabs.label;"
                 accesskey="&newWindowsAsTabs.accesskey;"
                 preference="browser.link.open_newwindow"
                 onsyncfrompreference="return gTabsPane.readLinkTarget();"
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
@@ -48,17 +48,17 @@
   <!ENTITY % privatebrowsingpageDTD SYSTEM "chrome://browser/locale/aboutPrivateBrowsing.dtd">
   %privatebrowsingpageDTD;
 ]>
 
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all"/>
     <link rel="stylesheet" href="chrome://browser/skin/aboutPrivateBrowsing.css" type="text/css" media="all"/>
-    <script type="application/x-javascript;version=1.7"><![CDATA[
+    <script type="application/javascript;version=1.7"><![CDATA[
       const Cc = Components.classes;
       const Ci = Components.interfaces;
 
       var pb = Cc["@mozilla.org/privatebrowsing;1"].
                getService(Ci.nsIPrivateBrowsingService);
 
       if (!pb.privateBrowsingEnabled) {
         document.title = "]]>&privatebrowsingpage.title.normal;<![CDATA[";
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -159,23 +159,16 @@ PrivateBrowsingService.prototype = {
             "entries": [{
               "url": "about:blank"
             }]
           }],
           "_closedTabs": []
         }]
       });
 
-      // whether we should save and close the current session
-      this._saveSession = true;
-      try {
-        if (this._prefs.getBoolPref("browser.privatebrowsing.keep_current_session"))
-          this._saveSession = false;
-      } catch (ex) {}
-
       if (this._inPrivateBrowsing) {
         // save the whole browser state in order to restore all windows/tabs later
         if (this._saveSession && !this._savedBrowserState) {
           if (this._getBrowserWindow())
             this._savedBrowserState = ss.getBrowserState();
           else // no open browser windows, just restore a blank state on exit
             this._savedBrowserState = blankState;
         }
@@ -305,16 +298,25 @@ PrivateBrowsingService.prototype = {
 
   _getBrowserWindow: function PBS__getBrowserWindow() {
     return Cc["@mozilla.org/appshell/window-mediator;1"].
            getService(Ci.nsIWindowMediator).
            getMostRecentWindow("navigator:browser");
   },
 
   _ensureCanCloseWindows: function PBS__ensureCanCloseWindows() {
+    // whether we should save and close the current session
+    this._saveSession = true;
+    try {
+      if (this._prefs.getBoolPref("browser.privatebrowsing.keep_current_session")) {
+        this._saveSession = false;
+        return;
+      }
+    } catch (ex) {}
+
     let windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
                          getService(Ci.nsIWindowMediator);
     let windowsEnum = windowMediator.getXULWindowEnumerator("navigator:browser");
 
     while (windowsEnum.hasMoreElements()) {
       let win = windowsEnum.getNext().QueryInterface(Ci.nsIXULWindow);
       if (win.docShell.contentViewer.permitUnload(true))
         this._windowsToClose.push(win);
--- a/browser/components/privatebrowsing/test/browser/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/Makefile.in
@@ -41,36 +41,39 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = browser/components/privatebrowsing/test/browser
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES =  \
 		browser_console_clear.js \
+		browser_privatebrowsing_beforeunload.js \
 		browser_privatebrowsing_certexceptionsui.js \
 		browser_privatebrowsing_crh.js \
 		browser_privatebrowsing_downloadmonitor.js \
 		browser_privatebrowsing_findbar.js \
 		browser_privatebrowsing_forgetthissite.js \
 		browser_privatebrowsing_geoprompt.js \
 		browser_privatebrowsing_geoprompt_page.html \
 		browser_privatebrowsing_import.js \
 		browser_privatebrowsing_opendir.js \
 		browser_privatebrowsing_openlocation.js \
 		browser_privatebrowsing_pageinfo.js \
+		browser_privatebrowsing_placestitle.js \
 		browser_privatebrowsing_popupmode.js \
 		browser_privatebrowsing_searchbar.js \
 		browser_privatebrowsing_sslsite_transition.js \
 		browser_privatebrowsing_theming.js \
 		browser_privatebrowsing_transition.js \
 		browser_privatebrowsing_ui.js \
 		browser_privatebrowsing_urlbarfocus.js \
 		browser_privatebrowsing_viewsource.js \
 		browser_privatebrowsing_windowtitle.js \
 		browser_privatebrowsing_windowtitle_page.html \
 		browser_privatebrowsing_zoom.js \
 		browser_privatebrowsing_zoomrestore.js \
 		staller.sjs \
+		title.sjs \
 		$(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_beforeunload.js
@@ -0,0 +1,170 @@
+/* ***** 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 Private Browsing Tests.
+ *
+ * The Initial Developer of the Original Code is
+ * Nochum Sossonko.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Nochum Sossonko <highmind63@gmail.com> (Original Author)
+ *   Ehsan Akhgari <ehsan@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This test makes sure that cancelling the unloading of a page with a beforeunload
+// handler prevents the private browsing mode transition.
+
+function test() {
+  const kTestPage1 = "data:text/html,<body%20onbeforeunload='return%20false;'>first</body>";
+  const kTestPage2 = "data:text/html,<body%20onbeforeunload='return%20false;'>second</body>";
+  let pb = Cc["@mozilla.org/privatebrowsing;1"]
+             .getService(Ci.nsIPrivateBrowsingService);
+
+  let promptHelper = {
+    rejectDialog: 0,
+    acceptDialog: 0,
+    confirmCalls: 0,
+
+    observe: function(aSubject, aTopic, aData) {
+      let dialogWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
+      this.confirmCalls++;
+      let button;
+      if (this.acceptDialog-- > 0)
+        button = dialogWin.document.documentElement.getButton("accept").click();
+      else if (this.rejectDialog-- > 0)
+        button = dialogWin.document.documentElement.getButton("cancel").click();
+    }
+  };
+
+  Cc["@mozilla.org/observer-service;1"]
+    .getService(Ci.nsIObserverService)
+    .addObserver(promptHelper, "common-dialog-loaded", false);
+
+  waitForExplicitFinish();
+  let browser1 = gBrowser.getBrowserForTab(gBrowser.addTab());
+  browser1.addEventListener("load", function() {
+    browser1.removeEventListener("load", arguments.callee, true);
+
+    let browser2 = gBrowser.getBrowserForTab(gBrowser.addTab());
+    browser2.addEventListener("load", function() {
+      browser2.removeEventListener("load", arguments.callee, true);
+
+      promptHelper.rejectDialog = 1;
+      pb.privateBrowsingEnabled = true;
+
+      ok(!pb.privateBrowsingEnabled, "Private browsing mode should not have been activated");
+      is(promptHelper.confirmCalls, 1, "Only one confirm box should be shown");
+      is(gBrowser.tabContainer.childNodes.length, 3,
+         "No tabs should be closed because private browsing mode transition was canceled");
+      is(gBrowser.getBrowserForTab(gBrowser.tabContainer.firstChild).currentURI.spec, "about:blank",
+         "The first tab should be a blank tab");
+      is(gBrowser.getBrowserForTab(gBrowser.tabContainer.firstChild.nextSibling).currentURI.spec, kTestPage1,
+         "The middle tab should be the same one we opened");
+      is(gBrowser.getBrowserForTab(gBrowser.tabContainer.lastChild).currentURI.spec, kTestPage2,
+         "The last tab should be the same one we opened");
+      is(promptHelper.rejectDialog, 0, "Only one confirm dialog should have been rejected");
+
+      promptHelper.confirmCalls = 0;
+      promptHelper.acceptDialog = 2;
+      pb.privateBrowsingEnabled = true;
+
+      ok(pb.privateBrowsingEnabled, "Private browsing mode should have been activated");
+      is(promptHelper.confirmCalls, 2, "Only two confirm boxes should be shown");
+      is(gBrowser.tabContainer.childNodes.length, 1,
+         "Incorrect number of tabs after transition into private browsing");
+      gBrowser.selectedBrowser.addEventListener("load", function() {
+        gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+
+        is(gBrowser.selectedBrowser.currentURI.spec, "about:privatebrowsing",
+           "Incorrect page displayed after private browsing transition");
+        is(promptHelper.acceptDialog, 0, "Two confirm dialogs should have been accepted");
+
+        gBrowser.selectedBrowser.addEventListener("load", function() {
+          gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+
+          gBrowser.selectedTab = gBrowser.addTab();
+          gBrowser.selectedBrowser.addEventListener("load", function() {
+            gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+
+            promptHelper.confirmCalls = 0;
+            promptHelper.rejectDialog = 1;
+            pb.privateBrowsingEnabled = false;
+
+            ok(pb.privateBrowsingEnabled, "Private browsing mode should not have been deactivated");
+            is(promptHelper.confirmCalls, 1, "Only one confirm box should be shown");
+            is(gBrowser.tabContainer.childNodes.length, 2,
+               "No tabs should be closed because private browsing mode transition was canceled");
+            is(gBrowser.getBrowserForTab(gBrowser.tabContainer.firstChild).currentURI.spec, kTestPage1,
+               "The first tab should be the same one we opened");
+            is(gBrowser.getBrowserForTab(gBrowser.tabContainer.lastChild).currentURI.spec, kTestPage2,
+               "The last tab should be the same one we opened");
+            is(promptHelper.rejectDialog, 0, "Only one confirm dialog should have been rejected");
+
+            promptHelper.confirmCalls = 0;
+            promptHelper.acceptDialog = 2;
+            pb.privateBrowsingEnabled = false;
+
+            ok(!pb.privateBrowsingEnabled, "Private browsing mode should have been deactivated");
+            is(promptHelper.confirmCalls, 2, "Only two confirm boxes should be shown");
+            is(gBrowser.tabContainer.childNodes.length, 3,
+               "Incorrect number of tabs after transition into private browsing");
+
+            let loads = 0;
+            function waitForLoad(event) {
+              gBrowser.removeEventListener("load", arguments.callee, true);
+
+              if (++loads != 3)
+                return;
+
+              is(gBrowser.getBrowserForTab(gBrowser.tabContainer.firstChild).currentURI.spec, "about:blank",
+                 "The first tab should be a blank tab");
+              is(gBrowser.getBrowserForTab(gBrowser.tabContainer.firstChild.nextSibling).currentURI.spec, kTestPage1,
+                 "The middle tab should be the same one we opened");
+              is(gBrowser.getBrowserForTab(gBrowser.tabContainer.lastChild).currentURI.spec, kTestPage2,
+                 "The last tab should be the same one we opened");
+                      is(promptHelper.acceptDialog, 0, "Two confirm dialogs should have been accepted");
+              is(promptHelper.acceptDialog, 0, "Two prompts should have been raised");
+
+              promptHelper.acceptDialog = 2;
+              gBrowser.removeTab(gBrowser.tabContainer.lastChild);
+              gBrowser.removeTab(gBrowser.tabContainer.lastChild);
+
+              finish();
+            }
+            for (let i = 0; i < gBrowser.browsers.length; ++i)
+              gBrowser.browsers[i].addEventListener("load", waitForLoad, true);
+          }, true);
+          gBrowser.selectedBrowser.loadURI(kTestPage2);
+        }, true);
+        gBrowser.selectedBrowser.loadURI(kTestPage1);
+      }, true);
+    }, true);
+    browser2.loadURI(kTestPage2);
+  }, true);
+  browser1.loadURI(kTestPage1);
+}
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js
@@ -49,17 +49,18 @@ function test() {
   let file = dir2.clone();
   file.append("pbtest.file");
   file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
 
   const kPrefName = "browser.open.lastDir";
 
   function setupCleanSlate() {
     gLastOpenDirectory.reset();
-    gPrefService.clearUserPref(kPrefName);
+    if (gPrefService.prefHasUserValue(kPrefName))
+        gPrefService.clearUserPref(kPrefName);
   }
 
   setupCleanSlate();
 
   // Test 1: general workflow test
 
   // initial checks
   ok(!gLastOpenDirectory.path,
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_openlocation.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_openlocation.js
@@ -83,28 +83,31 @@ function test() {
     };
 
     ww.registerNotification(observer);
     gPrefService.setIntPref("general.open_location.last_window_choice", 0);
     openDialog("chrome://browser/content/openLocation.xul", "_blank",
                "chrome,titlebar", window);
   }
 
-  gPrefService.clearUserPref("general.open_location.last_url");
+
+  if (gPrefService.prefHasUserValue("general.open_location.last_url"))
+    gPrefService.clearUserPref("general.open_location.last_url");
 
   openLocation("http://example.com/", "", function() {
     openLocation("http://example.org/", "http://example.com/", function() {
       // enter private browsing mode
       pb.privateBrowsingEnabled = true;
       openLocation("about:logo", "", function() {
         openLocation("about:buildconfig", "about:logo", function() {
           // exit private browsing mode
           pb.privateBrowsingEnabled = false;
           openLocation("about:blank", "http://example.org/", function() {
             gPrefService.clearUserPref("general.open_location.last_url");
-            gPrefService.clearUserPref("general.open_location.last_window_choice");
+            if (gPrefService.prefHasUserValue("general.open_location.last_window_choice"))
+              gPrefService.clearUserPref("general.open_location.last_window_choice");
             finish();
           });
         });
       });
     });
   });
 }
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_pageinfo.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_pageinfo.js
@@ -37,78 +37,57 @@
 
 // This test makes sure that the page info dialogs will close when entering or
 // exiting the private browsing mode.
 
 function test() {
   // initialization
   let pb = Cc["@mozilla.org/privatebrowsing;1"].
            getService(Ci.nsIPrivateBrowsingService);
-  let obs = Cc["@mozilla.org/observer-service;1"].
-            getService(Ci.nsIObserverService);
-  let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-           getService(Ci.nsIWindowWatcher);
 
   function runTest(aPBMode, aCallBack) {
-    const kTestURL1 = "data:text/html,Test Page 1";
     let tab1 = gBrowser.addTab();
     gBrowser.selectedTab = tab1;
     let browser1 = gBrowser.getBrowserForTab(tab1);
-    browser1.addEventListener("load", function() {
+    browser1.addEventListener("load", function () {
       browser1.removeEventListener("load", arguments.callee, true);
 
       let pageInfo1 = BrowserPageInfo();
-      obs.addObserver({
-        observe: function (aSubject, aTopic, aData) {
-          obs.removeObserver(this, "page-info-dialog-loaded");
+      pageInfo1.addEventListener("load", function () {
 
-          const kTestURL2 = "data:text/plain,Test Page 2";
-          let tab2 = gBrowser.addTab();
-          gBrowser.selectedTab = tab2;
-          let browser2 = gBrowser.getBrowserForTab(tab2);
-          browser2.addEventListener("load", function () {
-            browser2.removeEventListener("load", arguments.callee, true);
+        let tab2 = gBrowser.addTab();
+        gBrowser.selectedTab = tab2;
+        let browser2 = gBrowser.getBrowserForTab(tab2);
+        browser2.addEventListener("load", function () {
+          browser2.removeEventListener("load", arguments.callee, true);
 
-            let pageInfo2 = BrowserPageInfo();
-            obs.addObserver({
-              observe: function (aSubject, aTopic, aData) {
-                obs.removeObserver(this, "page-info-dialog-loaded");
+          let pageInfo2 = BrowserPageInfo();
+          pageInfo2.addEventListener("load", function () {
 
-                ww.registerNotification({
-                  observe: function (aSubject, aTopic, aData) {
-                    is(aTopic, "domwindowclosed", "We should only receive window closed notifications");
-                    let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
-                    if (win == pageInfo1) {
-                      ok(true, "Page info 1 being closed as expected");
-                      pageInfo1 = null;
-                    }
-                    else if (win == pageInfo2) {
-                      ok(true, "Page info 2 being closed as expected");
-                      pageInfo2 = null;
-                    }
-                    else
-                      ok(false, "The closed window should be one of the two page info windows");
+            pageInfo1.addEventListener("unload", function () {
+              pageInfo1 = null;
+              ok(true, "Page info 1 being closed as expected");
+              if (!pageInfo2)
+                aCallBack();
+            }, false);
 
-                    if (!pageInfo1 && !pageInfo2) {
-                      ww.unregisterNotification(this);
-
-                      aCallBack();
-                    }
-                  }
-                });
+            pageInfo2.addEventListener("unload", function () {
+              pageInfo2 = null;
+              ok(true, "Page info 2 being closed as expected");
+              if (!pageInfo1)
+                aCallBack();
+            }, false);
 
-                pb.privateBrowsingEnabled = aPBMode;
-              }
-            }, "page-info-dialog-loaded", false);
-          }, true);
-          browser2.loadURI(kTestURL2);
-        }
-      }, "page-info-dialog-loaded", false);
+            pb.privateBrowsingEnabled = aPBMode;
+          }, false);
+        }, true);
+        browser2.loadURI("data:text/plain,Test Page 2");
+      }, false);
     }, true);
-    browser1.loadURI(kTestURL1);
+    browser1.loadURI("data:text/html,Test Page 1");
   }
 
   runTest(true, function() {
     runTest(false, function() {
       gBrowser.removeCurrentTab();
       gBrowser.removeCurrentTab();
 
       finish();
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placestitle.js
@@ -0,0 +1,125 @@
+/* ***** 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 Private Browsing Tests.
+ *
+ * The Initial Developer of the Original Code is
+ * Ehsan Akhgari.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This test makes sure that the title of existing history entries does not
+// change inside the private browsing mode.
+
+function test() {
+  // initialization
+  let pb = Cc["@mozilla.org/privatebrowsing;1"].
+           getService(Ci.nsIPrivateBrowsingService);
+  let bhist = Cc["@mozilla.org/browser/global-history;2"].
+              getService(Ci.nsIBrowserHistory);
+  let histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
+                getService(Ci.nsINavHistoryService).
+                QueryInterface(Ci.nsPIPlacesDatabase);
+  let cm = Cc["@mozilla.org/cookiemanager;1"].
+           getService(Ci.nsICookieManager);
+  waitForExplicitFinish();
+
+  const TEST_URL = "http://localhost:8888/browser/browser/components/privatebrowsing/test/browser/title.sjs";
+
+  function cleanup() {
+    // delete all history items
+    bhist.removeAllPages();
+    // delete all cookies
+    cm.removeAll();
+  }
+  cleanup();
+
+  let observer = {
+    pass: 1,
+    onBeginUpdateBatch: function() {
+    },
+    onEndUpdateBatch: function() {
+    },
+    onVisit: function(aURI, aVisitID, aTime, aSessionId, aReferringId,
+                      aTransitionType, _added) {
+    },
+    onTitleChanged: function(aURI, aPageTitle) {
+      if (aURI.spec != TEST_URL)
+        return;
+      switch (this.pass++) {
+      case 1: // the first time that the page is loaded
+        is(aPageTitle, "No Cookie", "The page should be loaded without any cookie for the first time");
+        gBrowser.selectedTab = gBrowser.addTab(TEST_URL);
+        break;
+      case 2: // the second time that the page is loaded
+        is(aPageTitle, "Cookie", "The page should be loaded with a cookie for the second time");
+        cleanup();
+        gBrowser.selectedTab = gBrowser.addTab(TEST_URL);
+        break;
+      case 3: // before entering the private browsing mode
+        is(aPageTitle, "No Cookie", "The page should be loaded without any cookie again");
+        // enter private browsing mode
+        pb.privateBrowsingEnabled = true;
+        gBrowser.selectedTab = gBrowser.addTab(TEST_URL);
+        executeSoon(function() {
+          histsvc.removeObserver(observer);
+          pb.privateBrowsingEnabled = false;
+          while (gBrowser.browsers.length > 1)
+            gBrowser.removeCurrentTab();
+          cleanup();
+          finish();
+        });
+        break;
+      default:
+        ok(false, "Unexpected pass: " + (this.pass - 1));
+      }
+    },
+    onBeforeDeleteURI: function(aURI) {
+    },
+    onDeleteURI: function(aURI) {
+    },
+    onClearHistory: function() {
+    },
+    onPageChanged: function(aURI, aWhat, aValue) {
+    },
+    onPageExpired: function(aURI, aVisitTime, aWholeEntry) {
+    },
+    QueryInterface: function(iid) {
+      if (iid.equals(Ci.nsINavHistoryObserver) ||
+          iid.equals(Ci.nsISupports)) {
+        return this;
+      }
+      throw Cr.NS_ERROR_NO_INTERFACE;
+    }
+  };
+  histsvc.addObserver(observer, false);
+
+  gBrowser.selectedTab = gBrowser.addTab(TEST_URL);
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/title.sjs
@@ -0,0 +1,55 @@
+/* ***** 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 Private Browsing Tests.
+ *
+ * The Initial Developer of the Original Code is
+ * Ehsan Akhgari.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This provides the tests with a page with different titles based on whether
+// a cookie is present or not.
+
+function handleRequest(request, response) {
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.setHeader("Content-Type", "text/html", false);
+
+  var cookie = "name=value";
+  var title = "No Cookie";
+  if (request.hasHeader("Cookie") && request.getHeader("Cookie") == cookie)
+    title = "Cookie";
+  else
+    response.setHeader("Set-Cookie", cookie, false);
+
+  response.write("<html><head><title>");
+  response.write(title);
+  response.write("</title><body>test page</body></html>");
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/unit/do_test_placesTitleNoUpdate.js
@@ -0,0 +1,81 @@
+/* ***** 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 Private Browsing Test Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Ehsan Akhgari <ehsan.akhgari@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 ***** */
+
+// Test to make sure that the visited page titles do not get updated inside the
+// private browsing mode.
+
+function do_test()
+{
+  let pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
+           getService(Ci.nsIPrivateBrowsingService);
+  let histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
+                getService(Ci.nsINavHistoryService);
+  let bhist = histsvc.QueryInterface(Ci.nsIBrowserHistory);
+
+  const TEST_URI = uri("http://mozilla.com/privatebrowsing");
+  const TITLE_1 = "Title 1";
+  const TITLE_2 = "Title 2";
+
+  bhist.removeAllPages();
+
+  bhist.addPageWithDetails(TEST_URI, TITLE_1, Date.now() * 1000);
+  do_check_eq(histsvc.getPageTitle(TEST_URI), TITLE_1);
+
+  pb.privateBrowsingEnabled = true;
+
+  bhist.addPageWithDetails(TEST_URI, TITLE_2, Date.now() * 2000);
+  do_check_eq(histsvc.getPageTitle(TEST_URI), TITLE_1);
+
+  pb.privateBrowsingEnabled = false;
+
+  do_check_eq(histsvc.getPageTitle(TEST_URI), TITLE_1);
+
+  pb.privateBrowsingEnabled = true;
+
+  bhist.setPageTitle(TEST_URI, TITLE_2);
+  do_check_eq(histsvc.getPageTitle(TEST_URI), TITLE_1);
+
+  pb.privateBrowsingEnabled = false;
+
+  do_check_eq(histsvc.getPageTitle(TEST_URI), TITLE_1);
+
+  bhist.removeAllPages();
+}
+
+// Support running tests on both the service itself and its wrapper
+function run_test() {
+  run_test_on_all_services();
+}
--- a/browser/components/privatebrowsing/test/unit/head_privatebrowsing.js
+++ b/browser/components/privatebrowsing/test/unit/head_privatebrowsing.js
@@ -50,16 +50,22 @@ const NS_APP_HISTORY_50_FILE = "UHist";
 
 function LOG(aMsg) {
   aMsg = ("*** PRIVATEBROWSING TESTS: " + aMsg);
   Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).
                                       logStringMessage(aMsg);
   print(aMsg);
 }
 
+function uri(spec) {
+  return Cc["@mozilla.org/network/io-service;1"].
+         getService(Ci.nsIIOService).
+         newURI(spec, null, null);
+}
+
 // If there's no location registered for the profile direcotry, register one now.
 var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
 var profileDir = null;
 try {
   profileDir = dirSvc.get(NS_APP_USER_PROFILE_50_DIR, Ci.nsIFile);
 } catch (e) {}
 if (!profileDir) {
   // Register our own provider for the profile directory.
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/unit/test_placesTitleNoUpdate.js
@@ -0,0 +1,44 @@
+/* ***** 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 Private Browsing Test Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Ehsan Akhgari <ehsan.akhgari@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 ***** */
+
+// Test to make sure that the visited page titles do not get updated inside the
+// private browsing mode.
+
+function run_test() {
+  PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing;1";
+  load("do_test_placesTitleNoUpdate.js");
+  do_test();
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/unit/test_privatebrowsingwrapper_placesTitleNoUpdate.js
@@ -0,0 +1,44 @@
+/* ***** 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 Private Browsing Test Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Ehsan Akhgari <ehsan.akhgari@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 ***** */
+
+// Test to make sure that the visited page titles do not get updated inside the
+// private browsing mode.
+
+function run_test() {
+  PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing-wrapper;1";
+  load("do_test_placesTitleNoUpdate.js");
+  do_test();
+}
--- a/browser/components/search/content/engineManager.xul
+++ b/browser/components/search/content/engineManager.xul
@@ -51,17 +51,17 @@
         ondialogaccept="gEngineManagerDialog.onOK();"
         ondialogcancel="gEngineManagerDialog.onCancel();"
         ondialogextra2="gEngineManagerDialog.onRestoreDefaults();"
         title="&engineManager.title;"
         style="&engineManager.style;"
         persist="screenX screenY"
         windowtype="Browser:SearchManager">
 
-  <script type="application/x-javascript"
+  <script type="application/javascript"
           src="chrome://browser/content/search/engineManager.js"/>
 
   <commandset id="engineManagerCommandSet">
     <command id="cmd_remove"
              oncommand="gEngineManagerDialog.remove();"
              disabled="true"/>
     <command id="cmd_moveup"
              oncommand="gEngineManagerDialog.bump(1);"
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -65,16 +65,17 @@ const STATE_QUITTING = -1;
 const STATE_STOPPED_STR = "stopped";
 const STATE_RUNNING_STR = "running";
 
 const PRIVACY_NONE = 0;
 const PRIVACY_ENCRYPTED = 1;
 const PRIVACY_FULL = 2;
 
 const NOTIFY_WINDOWS_RESTORED = "sessionstore-windows-restored";
+const NOTIFY_BROWSER_STATE_RESTORED = "sessionstore-browser-state-restored";
 
 // global notifications observed
 const OBSERVING = [
   "domwindowopened", "domwindowclosed",
   "quit-application-requested", "quit-application-granted",
   "browser-lastwindow-close-granted",
   "quit-application", "browser:purge-session-history",
   "private-browsing", "browser:purge-domain-data",
@@ -145,19 +146,23 @@ SessionStoreService.prototype = {
   _loadState: STATE_STOPPED,
 
   // minimal interval between two save operations (in milliseconds)
   _interval: 10000,
 
   // when crash recovery is disabled, session data is not written to disk
   _resume_from_crash: true,
 
-  // During the initial restore tracks the number of windows yet to be restored
+  // During the initial restore and setBrowserState calls tracks the number of
+  // windows yet to be restored
   _restoreCount: 0,
 
+  // whether a setBrowserState call is in progress
+  _browserSetState: false,
+
   // time in milliseconds (Date.now()) when the session was last written to file
   _lastSaveTime: 0, 
 
   // states for all currently opened windows
   _windows: {},
 
   // states for all recently closed windows
   _closedWindows: [],
@@ -736,16 +741,18 @@ SessionStoreService.prototype = {
     aBrowser.addEventListener("change", this, true);
     aBrowser.addEventListener("input", this, true);
     aBrowser.addEventListener("DOMAutoComplete", this, true);
     aBrowser.addEventListener("scroll", this, true);
     
     if (!aNoNotification) {
       this.saveStateDelayed(aWindow);
     }
+
+    this._updateCrashReportURL(aWindow);
   },
 
   /**
    * remove listeners for a tab
    * @param aWindow
    *        Window reference
    * @param aBrowser
    *        Browser reference
@@ -878,33 +885,39 @@ SessionStoreService.prototype = {
 
   setBrowserState: function sss_setBrowserState(aState) {
     try {
       var state = this._safeEval("(" + aState + ")");
     }
     catch (ex) { /* invalid state object - don't restore anything */ }
     if (!state || !state.windows)
       throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-    
+
+    this._browserSetState = true;
+
     var window = this._getMostRecentBrowserWindow();
     if (!window) {
+      this._restoreCount = 1;
       this._openWindowWithState(state);
       return;
     }
 
     // close all other browser windows
     this._forEachBrowserWindow(function(aWindow) {
       if (aWindow != window) {
         aWindow.close();
       }
     });
 
     // make sure closed window data isn't kept
     this._closedWindows = [];
 
+    // determine how many windows are meant to be restored
+    this._restoreCount = state.windows ? state.windows.length : 0;
+
     // restore to the given state
     this.restoreWindow(window, state, true);
   },
 
   getWindowState: function sss_getWindowState(aWindow) {
     if (!aWindow.__SSi && !aWindow.__SS_dyingCache)
       throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
     
@@ -1801,23 +1814,23 @@ SessionStoreService.prototype = {
     }
     // initialize window if necessary
     if (aWindow && (!aWindow.__SSi || !this._windows[aWindow.__SSi]))
       this.onLoad(aWindow);
 
     try {
       var root = typeof aState == "string" ? this._safeEval(aState) : aState;
       if (!root.windows[0]) {
-        this._notifyIfAllWindowsRestored();
+        this._sendRestoreCompletedNotifications();
         return; // nothing to restore
       }
     }
     catch (ex) { // invalid state object - don't restore anything 
       debug(ex);
-      this._notifyIfAllWindowsRestored();
+      this._sendRestoreCompletedNotifications();
       return;
     }
 
     if (root._closedWindows)
       this._closedWindows = root._closedWindows;
 
     var winData;
     if (!aState.selectedWindow) {
@@ -1894,17 +1907,17 @@ SessionStoreService.prototype = {
     }
     
     this.restoreHistoryPrecursor(aWindow, tabs, winData.tabs,
       (aOverwriteTabs ? (parseInt(winData.selected) || 1) : 0), 0, 0);
 
     // set smoothScroll back to the original value
     tabstrip.smoothScroll = smoothScroll;
 
-    this._notifyIfAllWindowsRestored();
+    this._sendRestoreCompletedNotifications();
   },
 
   /**
    * Manage history restoration for a window
    * @param aWindow
    *        Window to restore the tabs into
    * @param aTabs
    *        Array of tab references
@@ -2807,22 +2820,25 @@ SessionStoreService.prototype = {
       // instead of evalInSandbox everywhere
       jsonString = jsonString.replace(/[\u2028\u2029]/g,
                                       function($0) "\\u" + $0.charCodeAt(0).toString(16));
     }
     
     return jsonString;
   },
 
-  _notifyIfAllWindowsRestored: function sss_notifyIfAllWindowsRestored() {
+  _sendRestoreCompletedNotifications: function sss_sendRestoreCompletedNotifications() {
     if (this._restoreCount) {
       this._restoreCount--;
       if (this._restoreCount == 0) {
         // This was the last window restored at startup, notify observers.
-        this._observerService.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
+        this._observerService.notifyObservers(null,
+          this._browserSetState ? NOTIFY_BROWSER_STATE_RESTORED : NOTIFY_WINDOWS_RESTORED,
+          "");
+        this._browserSetState = false;
       }
     }
   },
 
   /**
    * @param aWindow
    *        Window reference
    * @returns whether this window's data is still cached in _statesToRestore
--- a/browser/components/sessionstore/test/browser/Makefile.in
+++ b/browser/components/sessionstore/test/browser/Makefile.in
@@ -103,12 +103,13 @@ include $(topsrcdir)/config/rules.mk
 	browser_485482_sample.html \
 	browser_485563.js \
 	browser_490040.js \
 	browser_491168.js \
 	browser_491577.js \
 	browser_493467.js \
 	browser_495495.js \
 	browser_514751.js \
+	browser_526613.js \
 	$(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/components/sessionstore/test/browser/browser_248970_a.js
+++ b/browser/components/sessionstore/test/browser/browser_248970_a.js
@@ -130,17 +130,18 @@ function test() {
 
             // private browsing session, close tab: (B)
             gBrowser.removeTab(tab_B);
 
             // private browsing session, close tab: (A)
             gBrowser.removeTab(tab_A);
 
             // record the timestamp of sessionstore.js at the end of the private session
-            gPrefService.clearUserPref("browser.sessionstore.interval");
+            if (gPrefService.prefHasUserValue("browser.sessionstore.interval"))
+              gPrefService.clearUserPref("browser.sessionstore.interval");
             gPrefService.setIntPref("browser.sessionstore.interval", 0);
             let endPBModeTimeStamp = getSessionstorejsModificationTime();
 
             // exit private browsing mode
             pb.privateBrowsingEnabled = false;
             ok(!pb.privateBrowsingEnabled, "private browsing disabled");
 
             // compare timestamps: pre and post private browsing session
--- a/browser/components/sessionstore/test/browser/browser_248970_b.js
+++ b/browser/components/sessionstore/test/browser/browser_248970_b.js
@@ -124,17 +124,17 @@ function test() {
     "getClosedTabCount should return zero or at most max_tabs_undo");
 
   // setup a state for tab (A) so we can check later that is restored
   let key = "key";
   let value = "Value " + Math.random();
   let state = { entries: [{ url: testURL }], extData: { key: value } };
 
   // public session, add new tab: (A)
-  tab_A = gBrowser.addTab(testURL);
+  let tab_A = gBrowser.addTab(testURL);
   ss.setTabState(tab_A, state.toSource());
   tab_A.linkedBrowser.addEventListener("load", function(aEvent) {
     this.removeEventListener("load", arguments.callee, true);
 
     // make sure that the next closed tab will increase getClosedTabCount
     gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1)
 
     // populate tab_A with form data
@@ -161,17 +161,17 @@ function test() {
       ok(pb.privateBrowsingEnabled, "private browsing enabled");
 
       // setup a state for tab (B) so we can check that its duplicated properly
       let key1 = "key1";
       let value1 = "Value " + Math.random();
       let state1 = { entries: [{ url: testURL2 }], extData: { key1: value1 } };
 
       // private browsing session, new tab: (B)
-      tab_B = gBrowser.addTab(testURL2);
+      let tab_B = gBrowser.addTab(testURL2);
       ss.setTabState(tab_B, state1.toSource());
       tab_B.linkedBrowser.addEventListener("load", function(aEvent) {
         this.removeEventListener("load", arguments.callee, true);
 
         // populate tab: (B) with different form data
         for (let item in fieldList)
           setFormValue(tab_B, item, fieldList[item]);
 
@@ -192,15 +192,16 @@ function test() {
           gBrowser.removeTab(tab_C);
           gBrowser.removeTab(tab_B);
 
           // exit private browsing mode
           pb.privateBrowsingEnabled = false;
           ok(!pb.privateBrowsingEnabled, "private browsing disabled");
 
           // cleanup
-          gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
+          if (gPrefService.prefHasUserValue("browser.privatebrowsing.keep_current_session"))
+            gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
           finish();
         }, true);
       }, true);
     }, true);
   }, true);
 }
--- a/browser/components/sessionstore/test/browser/browser_346337.js
+++ b/browser/components/sessionstore/test/browser/browser_346337.js
@@ -126,17 +126,18 @@ function test() {
       tab = undoCloseTab();
       tab.linkedBrowser.addEventListener("load", function(aEvent) {
         this.removeEventListener("load", arguments.callee, true);
         for (let xpath in fieldList)
           if (fieldList[xpath])
             ok(!compareFormValue(tab, xpath, fieldList[xpath]),
                "The value for \"" + xpath + "\" was correctly discarded");
         
-        gPrefService.clearUserPref("browser.sessionstore.privacy_level");
+        if (gPrefService.prefHasUserValue("browser.sessionstore.privacy_level"))
+          gPrefService.clearUserPref("browser.sessionstore.privacy_level");
         // undoCloseTab can reuse a single blank tab, so we have to
         // make sure not to close the window when closing our last tab
         if (tabbrowser.tabContainer.childNodes.length == 1)
           tabbrowser.addTab();
         tabbrowser.removeTab(tab);
         finish();
       }, true);
     }, true);
--- a/browser/components/sessionstore/test/browser/browser_350525.js
+++ b/browser/components/sessionstore/test/browser/browser_350525.js
@@ -90,14 +90,15 @@ function test() {
     tab = test(function() ss.undoCloseTab(window, 0));
     ok(tab, "undoCloseTab doesn't throw")
     
     tab.linkedBrowser.addEventListener("load", function(aEvent) {
       this.removeEventListener("load", arguments.callee, true);
       is(this.currentURI.spec, testURL, "correct tab was reopened");
       
       // clean up
-      gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
+      if (gPrefService.prefHasUserValue("browser.sessionstore.max_tabs_undo"))
+        gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
       tabbrowser.removeTab(tab);
       finish();
     }, true);
   }, true);
 }
--- a/browser/components/sessionstore/test/browser/browser_367052.js
+++ b/browser/components/sessionstore/test/browser/browser_367052.js
@@ -60,13 +60,14 @@ function test() {
       this.removeEventListener("load", arguments.callee, true);
       ok(history.count == 0, "the tab was restored without any history whatsoever");
       
       tabbrowser.removeTab(tab);
       ok(ss.getClosedTabCount(window) == closedTabCount,
          "The closed blank tab wasn't added to Recently Closed Tabs");
       
       // clean up
-      gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
+      if (gPrefService.prefHasUserValue("browser.sessionstore.max_tabs_undo"))
+        gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
       finish();
     }, true);
   }, true);
 }
--- a/browser/components/sessionstore/test/browser/browser_394759.js
+++ b/browser/components/sessionstore/test/browser/browser_394759.js
@@ -99,17 +99,18 @@ function test() {
                 let textbox = newWin2.content.document.getElementById("textbox");
                 is(textbox.wrappedJSObject.value, uniqueText,
                    "The window correctly restored the form");
                 is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
                    "The window correctly restored the data associated with it");
 
                 // clean up
                 newWin2.close();
-                gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
+                if (gPrefService.prefHasUserValue("browser.sessionstore.max_windows_undo"))
+                  gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
                 executeSoon(callback);
               }, true);
             }, false);
           });
         });
       }, true);
     }, false);
   }
--- a/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js
+++ b/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js
@@ -37,80 +37,97 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 function test() {
   /** Private Browsing Test for Bug 394759 **/
 
   waitForExplicitFinish();
 
-  // Setup.
-  let pb = Cc["@mozilla.org/privatebrowsing;1"].
-           getService(Ci.nsIPrivateBrowsingService);
+  // Set interval to a large time so state won't be written while we setup env.
+  gPrefService.setIntPref("browser.sessionstore.interval", 100000);
+
+  // Set up the browser in a blank state. Popup windows in previous tests result
+  // in different states on different platforms.
   let ss = Cc["@mozilla.org/browser/sessionstore;1"].
            getService(Ci.nsISessionStore);
-  let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-           getService(Ci.nsIWindowWatcher);
+  let blankState = JSON.stringify({
+    windows: [{
+      tabs: [{ entries: [{ url: "about:blank" }] }],
+      _closedTabs: []
+    }],
+    _closedWindows: []
+  });
+  ss.setBrowserState(blankState);
+
+  // Wait for the sessionstore.js file to be written before going on.
+  // Note: we don't wait for the complete event, since if asyncCopy fails we
+  // would timeout.
+  let os = Cc["@mozilla.org/observer-service;1"].
+           getService(Ci.nsIObserverService);
+  os.addObserver({observe: function(aSubject, aTopic, aData) {
+    os.removeObserver(this, aTopic);
+    info("sessionstore.js is being written");
+    executeSoon(continue_test);
+  }}, "sessionstore-state-write", false);
 
   // Remove the sessionstore.js file before setting the interval to 0
   let profilePath = Cc["@mozilla.org/file/directory_service;1"].
                     getService(Ci.nsIProperties).
                     get("ProfD", Ci.nsIFile);
   let sessionStoreJS = profilePath.clone();
   sessionStoreJS.append("sessionstore.js");
   if (sessionStoreJS.exists())
     sessionStoreJS.remove(false);
-  ok(sessionStoreJS.exists() == false, "sessionstore.js was removed");
+  info("sessionstore.js was correctly removed: " + (!sessionStoreJS.exists()));
+
   // Make sure that sessionstore.js can be forced to be created by setting
-  // the interval pref to 0
+  // the interval pref to 0.
   gPrefService.setIntPref("browser.sessionstore.interval", 0);
-  // sessionstore.js should be re-created at this point
-  sessionStoreJS = profilePath.clone();
-  sessionStoreJS.append("sessionstore.js");
+}
 
-  // Set up the browser in a blank state. Popup windows in previous tests result
-  // in different states on different platforms.
-  let blankState = JSON.stringify({
-    windows: [{
-      tabs: [{ entries: [{ url: "about:blank" }] }],
-      _closedTabs: []
-    }],
-    _closedWindows: []
-  });
-  ss.setBrowserState(blankState);
+function continue_test() {
+  let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
+           getService(Ci.nsIWindowWatcher);
+  let pb = Cc["@mozilla.org/privatebrowsing;1"].
+           getService(Ci.nsIPrivateBrowsingService);
+  // Ensure Private Browsing mode is disabled.
+  ok(!pb.privateBrowsingEnabled, "Private Browsing is disabled");
+  let ss = Cc["@mozilla.org/browser/sessionstore;1"].
+           getService(Ci.nsISessionStore);
 
   let closedWindowCount = ss.getClosedWindowCount();
   is(closedWindowCount, 0, "Correctly set window count");
 
   // Prevent VM timers issues, cache now and increment it manually.
-  const NOW = Date.now();
-
+  let now = Date.now();
   const TESTS = [
     { url: "about:config",
       key: "bug 394759 Non-PB",
-      value: "uniq" + (++NOW) },
+      value: "uniq" + (++now) },
     { url: "about:mozilla",
       key: "bug 394759 PB",
-      value: "uniq" + (++NOW) },
+      value: "uniq" + (++now) },
   ];
 
+  let loadWasCalled = false;
   function openWindowAndTest(aTestIndex, aRunNextTestInPBMode) {
     info("Opening new window");
     let windowObserver = {
       observe: function(aSubject, aTopic, aData) {
         if (aTopic === "domwindowopened") {
-          ww.unregisterNotification(this);
           info("New window has been opened");
           let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
           win.addEventListener("load", function onLoad(event) {
             win.removeEventListener("load", onLoad, false);
             info("New window has been loaded");
             win.gBrowser.addEventListener("load", function(aEvent) {
               win.gBrowser.removeEventListener("load", arguments.callee, true);
               info("New window browser has been loaded");
+              loadWasCalled = true;
               executeSoon(function() {
                 // Add a tab.
                 win.gBrowser.addTab();
 
                 executeSoon(function() {
                   // Mark the window with some unique data to be restored later on.
                   ss.setWindowValue(win, TESTS[aTestIndex].key, TESTS[aTestIndex].value);
 
@@ -142,35 +159,43 @@ function test() {
                     ok(!pb.privateBrowsingEnabled, "private browsing disabled");
 
                     // Ensure that we still have the closed windows from before.
                     is(ss.getClosedWindowCount(), closedWindowCount + 1,
                        "The correct number of recently closed windows were restored " +
                        "when exiting PB mode");
 
                     let data = JSON.parse(ss.getClosedWindowData())[0];
-                    ok(data.toSource().indexOf(TESTS[aTestIndex].value) > -1,
+                    ok(data.toSource().indexOf(TESTS[aTestIndex - 1].value) > -1,
                        "The data associated with the recently closed window was " +
                        "restored when exiting PB mode");
                   }
 
                   if (aTestIndex == TESTS.length - 1) {
-                    // Cleanup and finish.
-                    gPrefService.clearUserPref("browser.sessionstore.interval");
+                    if (gPrefService.prefHasUserValue("browser.sessionstore.interval"))
+                      gPrefService.clearUserPref("browser.sessionstore.interval");
                     finish();
                   }
                   else {
                     // Run next test.
                     openWindowAndTest(aTestIndex + 1, !aRunNextTestInPBMode);
                   }
                 });
               });
             }, true);
           }, false);
         }
+        else if (aTopic === "domwindowclosed") {
+          info("Window closed");
+          ww.unregisterNotification(this);
+          if (!loadWasCalled) {
+            ok(false, "Window was closed before load could fire!");
+            finish();
+          }
+        }
       }
     };
     ww.registerNotification(windowObserver);
     // Open a window.
     openDialog(location, "_blank", "chrome,all,dialog=no", TESTS[aTestIndex].url);
   }
 
   openWindowAndTest(0, true);
--- a/browser/components/sessionstore/test/browser/browser_423132.js
+++ b/browser/components/sessionstore/test/browser/browser_423132.js
@@ -92,16 +92,17 @@ function test() {
         if (cookie.name == cookie2.name)
           break;
       }
       is(cookie.name, cookie2.name, "cookie name successfully restored");
       is(cookie.value, cookie2.value, "cookie value successfully restored");
       is(cookie.path, cookie2.path, "cookie path successfully restored");
 
       // clean up
-      gPrefService.clearUserPref("browser.sessionstore.interval");
+      if (gPrefService.prefHasUserValue("browser.sessionstore.interval"))
+        gPrefService.clearUserPref("browser.sessionstore.interval");
       cs.removeAll();
       newWin.close();
       finish();
     }, true);
   }, false);
 }
 
--- a/browser/components/sessionstore/test/browser/browser_448741.js
+++ b/browser/components/sessionstore/test/browser/browser_448741.js
@@ -81,17 +81,18 @@ function test() {
     observe: function(aSubject, aTopic, aData) {
       ok(valueWasCleaned && aSubject instanceof Ci.nsISupportsString,
          "ready to check the cleaned state?");
       ok(aSubject.data.indexOf(uniqueValue) == -1, "data no longer contains our value?");
       
       // clean up
       gBrowser.removeTab(tab);
       os.removeObserver(this, aTopic, false);
-      gPrefService.clearUserPref("browser.sessionstore.interval");
+      if (gPrefService.prefHasUserValue("browser.sessionstore.interval"))
+        gPrefService.clearUserPref("browser.sessionstore.interval");
       finish();
     }
   };
   
   // last added observers are invoked first
   os.addObserver(checkingObserver, "sessionstore-state-write", false);
   os.addObserver(cleaningObserver, "sessionstore-state-write", false);
   
--- a/browser/components/sessionstore/test/browser/browser_454908.js
+++ b/browser/components/sessionstore/test/browser/browser_454908.js
@@ -66,17 +66,18 @@ function test() {
         let node = doc.getElementById(id);
         if (node.type == "password")
           is(node.value, "", "password wasn't saved/restored");
         else
           is(node.value, fieldValues[id], "username was saved/restored");
       }
       
       // clean up
-      gPrefService.clearUserPref("browser.sessionstore.privacy_level");
+      if (gPrefService.prefHasUserValue("browser.sessionstore.privacy_level"))
+        gPrefService.clearUserPref("browser.sessionstore.privacy_level");
       // undoCloseTab can reuse a single blank tab, so we have to
       // make sure not to close the window when closing our last tab
       if (gBrowser.tabContainer.childNodes.length == 1)
         gBrowser.addTab();
       gBrowser.removeTab(tab);
       finish();
     }, true);
   }, true);
--- a/browser/components/sessionstore/test/browser/browser_456342.js
+++ b/browser/components/sessionstore/test/browser/browser_456342.js
@@ -61,12 +61,13 @@ function test() {
       else
         countBad++;
     }
     
     is(countGood, 4, "Saved text for non-standard input fields");
     is(countBad,  0, "Didn't save text for ignored field types");
     
     // clean up
-    gPrefService.clearUserPref("browser.sessionstore.privacy_level");
+    if (gPrefService.prefHasUserValue("browser.sessionstore.privacy_level"))
+      gPrefService.clearUserPref("browser.sessionstore.privacy_level");
     finish();
   }, true);
 }
--- a/browser/components/sessionstore/test/browser/browser_459906.js
+++ b/browser/components/sessionstore/test/browser/browser_459906.js
@@ -57,21 +57,24 @@ function test() {
     frameCount = 0;
     let tab2 = gBrowser.duplicateTab(tab);
     tab2.linkedBrowser.addEventListener("load", function(aEvent) {
       // wait for all frames to load (and reload!) completely
       if (frameCount++ < 2)
         return;
       this.removeEventListener("load", arguments.callee, true);
 
-      let maxWait = Date.now() + 1000;
+      let pass = 0;
+      const MAX_PASS = 6;
       executeSoon(function() {
+        info("Checking innerHTML, pass: " + (pass + 1));
         let iframes = tab2.linkedBrowser.contentWindow.frames;
-        if (iframes[1].document.body.innerHTML != uniqueValue && Date.now() < maxWait) {
-          executeSoon(arguments.callee);
+        if (iframes[1].document.body.innerHTML != uniqueValue &&
+            ++pass <= MAX_PASS) {
+          setTimeout(arguments.callee, 500);
           return;
         }
         is(iframes[1].document.body.innerHTML, uniqueValue,
            "rich textarea's content correctly duplicated");
         
         let innerDomain = null;
         try {
           innerDomain = iframes[0].document.domain;
--- a/browser/components/sessionstore/test/browser/browser_461743.js
+++ b/browser/components/sessionstore/test/browser/browser_461743.js
@@ -38,20 +38,23 @@ function test() {
   /** Test for Bug 461743 **/
   
   waitForExplicitFinish();
   
   let testURL = "http://localhost:8888/browser/" +
     "browser/components/sessionstore/test/browser/browser_461743_sample.html";
   
   let tab = gBrowser.addTab(testURL);
+  info("New tab added");
   tab.linkedBrowser.addEventListener("load", function(aEvent) {
+    info("New tab loaded");
     this.removeEventListener("load", arguments.callee, true);
     executeSoon(function() {
       let tab2 = gBrowser.duplicateTab(tab);
+      info("Duplicated tab");
       tab2.linkedBrowser.addEventListener("461743", function(aEvent) {
         tab2.linkedBrowser.removeEventListener("461743", arguments.callee, true);
         is(aEvent.data, "done", "XSS injection was attempted");
         
         executeSoon(function() {
           let iframes = tab2.linkedBrowser.contentWindow.frames;
           let innerHTML = iframes[1].document.body.innerHTML;
           isnot(innerHTML, Components.utils.reportError.toString(),
--- a/browser/components/sessionstore/test/browser/browser_464199.js
+++ b/browser/components/sessionstore/test/browser/browser_464199.js
@@ -98,12 +98,13 @@ function test() {
        "The correct amout of tabs was removed");
     is(countByTitle(closedTabs, FORGET), 0,
        "All tabs to be forgotten were indeed removed");
     is(countByTitle(closedTabs, REMEMBER), remember_count,
        "... and tabs to be remembered weren't.");
     
     // clean up
     newWin.close();
-    gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
+    if (gPrefService.prefHasUserValue("browser.sessionstore.max_tabs_undo"))
+      gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
     finish();
   }, false);
 }
--- a/browser/components/sessionstore/test/browser/browser_480893.js
+++ b/browser/components/sessionstore/test/browser/browser_480893.js
@@ -72,16 +72,19 @@ function test() {
         browser.addEventListener("load", function(aEvent) {
           this.removeEventListener("load", arguments.callee, true);
           let doc = browser.contentDocument;
 
           is(doc.URL, homepage, "loaded page is the homepage");
 
           // close tab, restore default values and finish the test
           gBrowser.removeTab(tab);
-          gPrefService.clearUserPref("browser.startup.page");
+          // we need this if-statement because if there is no user set value, 
+          // clearUserPref throws a uncatched exception and finish is not called
+          if (gPrefService.prefHasUserValue("browser.startup.page"))
+            gPrefService.clearUserPref("browser.startup.page");
           gPrefService.clearUserPref("browser.startup.homepage");
           finish();
         }, true);
       }, true);
     }, true);
   }, true);
 }
--- a/browser/components/sessionstore/test/browser/browser_490040.js
+++ b/browser/components/sessionstore/test/browser/browser_490040.js
@@ -147,15 +147,16 @@ function test() {
   ];
 
   function runNextTest() {
     if (states.length) {
       let state = states.shift();
       testWithState(state);
     }
     else {
-      gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
+      if (gPrefService.prefHasUserValue("browser.sessionstore.max_windows_undo"))
+        gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
       finish();
     }
   }
   runNextTest();
 }
 
--- a/browser/components/sessionstore/test/browser/browser_491577.js
+++ b/browser/components/sessionstore/test/browser/browser_491577.js
@@ -144,12 +144,13 @@ function test() {
        "The correct amount of windows were removed");
     is(countByTitle(closedWindows, FORGET), 0,
        "All windows specifically forgotten were indeed removed");
     is(countByTitle(closedWindows, REMEMBER), remember_count,
        "... and windows not specifically forgetten weren't.");
 
     // clean up
     newWin.close();
-    gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
+    if (gPrefService.prefHasUserValue("browser.sessionstore.max_windows_undo"))
+      gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
     finish();
   }, false);
 }
--- a/browser/components/sessionstore/test/browser/browser_495495.js
+++ b/browser/components/sessionstore/test/browser/browser_495495.js
@@ -68,17 +68,17 @@ function test() {
                  "URL bar autocomplete should be enabled before setting the state");
               ss.setWindowState(win, state, true);
               is(win.gURLBar.readOnly, expected.readOnly,
                  "URL bar read-only state should be restored correctly");
               is(win.gURLBar.getAttribute("enablehistory"), expected.enablehistory,
                  "URL bar autocomplete state should be restored correctly");
 
               win.close();
-              callback();
+              executeSoon(callback);
             }, false);
           }
 
           testState(state1, {readOnly: false, enablehistory: "true"}, function() {
             testState(state2, {readOnly: true, enablehistory: "false"}, function() {
               executeSoon(finish);
             });
           });
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser/browser_526613.js
@@ -0,0 +1,102 @@
+/* ***** 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 sessionstore test code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *    Ehsan Akhgari <ehsan@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 ***** */
+
+function test() {
+  /** Test for Bug 526613 **/
+  
+  // test setup
+  let ss = Cc["@mozilla.org/browser/sessionstore;1"].
+           getService(Ci.nsISessionStore);
+  let os = Cc["@mozilla.org/observer-service;1"].
+           getService(Ci.nsIObserverService);
+  let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
+           getService(Ci.nsIWindowMediator);
+  waitForExplicitFinish();
+
+  function browserWindowsCount() {
+    let count = 0;
+    let e = wm.getXULWindowEnumerator("navigator:browser");
+    while (e.hasMoreElements()) {
+      ++count;
+      e.getNext();
+    }
+
+    return count;
+  }
+
+  is(browserWindowsCount(), 1, "Only one browser window should be open initially");
+
+  // backup old state
+  let oldState = ss.getBrowserState();
+  // create a new state for testing
+  let testState = {
+    windows: [
+      { tabs: [{ entries: [{ url: "http://example.com/" }] }], selected: 1 },
+      { tabs: [{ entries: [{ url: "about:robots"        }] }], selected: 1 },
+    ],
+    // make sure the first window is focused, otherwise when restoring the
+    // old state, the first window is closed and the test harness gets unloaded
+    selectedWindow: 1
+  };
+
+  let observer = {
+    pass: 1,
+    observe: function(aSubject, aTopic, aData) {
+      is(aTopic, "sessionstore-browser-state-restored",
+         "The sessionstore-browser-state-restored notification was observed");
+
+      if (this.pass++ == 1) {  
+        is(browserWindowsCount(), 2, "Two windows should exist at this point");
+
+        // executeSoon is needed here in order to let the first window be focused
+        // (see above)
+        executeSoon(function() {
+          ss.setBrowserState(oldState);
+        });
+      }
+      else {
+        is(browserWindowsCount(), 1, "Only one window should exist after cleanup");
+        os.removeObserver(this, "sessionstore-browser-state-restored");
+        finish();
+      }
+    }
+  };
+  os.addObserver(observer, "sessionstore-browser-state-restored", false);
+
+  // set browser to test state
+  ss.setBrowserState(JSON.stringify(testState));
+}
--- a/browser/components/wintaskbar/test/browser_taskbar_preview.js
+++ b/browser/components/wintaskbar/test/browser_taskbar_preview.js
@@ -89,17 +89,18 @@ function test() {
 
   // Change selection
   gBrowser.selectedTab = gBrowser.mTabs[0];
   checkSelectedTab();
   // Close nonselected tab via controller
   getPreviewForTab(gBrowser.mTabs[1]).controller.onClose();
   checkPreviews(1);
 
-  gPrefService.clearUserPref(ENABLE_PREF_NAME);
+  if (gPrefService.prefHasUserValue(ENABLE_PREF_NAME))
+    gPrefService.clearUserPref(ENABLE_PREF_NAME);
 
   finish();
 
   function checkPreviews(aPreviews, msg) {
     let nPreviews = AeroPeek.previews.length;
     is(aPreviews, gBrowser.mTabs.length, "Browser has expected number of tabs");
     is(nPreviews, gBrowser.mTabs.length, "Browser has one preview per tab");
     is(nPreviews, aPreviews, msg || "Got expected number of previews");
--- a/browser/fuel/src/fuelApplication.js
+++ b/browser/fuel/src/fuelApplication.js
@@ -282,17 +282,17 @@ BrowserTab.prototype = {
 //=================================================
 // Annotations implementation
 function Annotations(aId) {
   this._id = aId;
 }
 
 Annotations.prototype = {
   get names() {
-    return Utilities.annotations.getItemAnnotationNames(this._id, {});
+    return Utilities.annotations.getItemAnnotationNames(this._id);
   },
 
   has : function ann_has(aName) {
     return Utilities.annotations.itemHasAnnotation(this._id, aName);
   },
 
   get : function(aName) {
     if (this.has(aName))
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -89,16 +89,20 @@ endif
 ifeq (gtk2, $(MOZ_WIDGET_TOOLKIT))
 DEFINES += -DMOZ_GTK2=1
 endif
 
 ifdef NSS_DISABLE_DBM
 DEFINES += -DNSS_DISABLE_DBM=1
 endif
 
+ifdef MOZ_UPDATER
+DEFINES += -DMOZ_UPDATER=1
+endif
+
 ifdef MOZ_PKG_MANIFEST_P
 MOZ_PKG_MANIFEST = package-manifest
 
 $(MOZ_PKG_MANIFEST): $(MOZ_PKG_MANIFEST_P)
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $< > $@
 
 GARBAGE += $(MOZ_PKG_MANIFEST)
 endif
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -100,16 +100,17 @@
 @BINPATH@/run-mozilla.sh
 #endif
 #endif
 #ifdef MOZ_SPLASHSCREEN
 @BINPATH@/splash.bmp
 #endif
 
 ; [Components]
+@BINPATH@/components/components.list
 @BINPATH@/components/alerts.xpt
 #ifdef ACCESSIBILITY
 #ifdef XP_WIN32
 @BINPATH@/AccessibleMarshal.dll
 @BINPATH@/components/accessibility-msaa.xpt
 #endif
 @BINPATH@/components/accessibility.xpt
 #endif
@@ -290,17 +291,21 @@
 @BINPATH@/components/nsHelperAppDlg.js
 @BINPATH@/components/nsDownloadManagerUI.js
 @BINPATH@/components/nsProxyAutoConfig.js
 @BINPATH@/components/NetworkGeolocationProvider.js
 @BINPATH@/components/GPSDGeolocationProvider.js
 @BINPATH@/components/nsSidebar.js
 @BINPATH@/components/nsExtensionManager.js
 @BINPATH@/components/nsBlocklistService.js
+#ifdef MOZ_UPDATER
 @BINPATH@/components/nsUpdateService.js
+@BINPATH@/components/nsUpdateServiceStub.js
+#endif
+@BINPATH@/components/nsUpdateTimerManager.js
 @BINPATH@/components/pluginGlue.js
 @BINPATH@/components/nsSessionStartup.js
 @BINPATH@/components/nsSessionStore.js
 @BINPATH@/components/nsURLFormatter.js
 #ifndef XP_OS2
 @BINPATH@/components/@DLL_PREFIX@browserdirprovider@DLL_SUFFIX@
 @BINPATH@/components/@DLL_PREFIX@browsercomps@DLL_SUFFIX@
 #else
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -827,8 +827,12 @@ chrome.manifest
 install.rdf
 @DLL_PREFIX@jsj@DLL_SUFFIX@
 #ifdef XP_WIN
 js3250.dll
 #endif
 #ifdef XP_WIN
 components/brwsrcmp.dll
 #endif
+#ifndef MOZ_UPDATER
+components/nsUpdateService.js
+components/nsUpdateServiceStub.js
+#endif
--- a/browser/locales/en-US/chrome/browser/baseMenuOverlay.dtd
+++ b/browser/locales/en-US/chrome/browser/baseMenuOverlay.dtd
@@ -17,17 +17,17 @@
 <!ENTITY helpForIEUsers.label     "For Internet Explorer Users">
 <!ENTITY helpForIEUsers.accesskey "I">
 <!ENTITY openHelp.commandkey      "VK_F1">
 <!ENTITY helpMac.commandkey       "?">
 
 <!ENTITY helpReleaseNotes.label         "Release Notes">
 <!ENTITY helpReleaseNotes.accesskey     "N">
 
-<!ENTITY helpTroubleshooting.label      "Troubleshooting Information…">
+<!ENTITY helpTroubleshooting.label      "Troubleshooting Information">
 <!ENTITY helpTroubleshooting.accesskey  "T">
 
 <!ENTITY updateCmd.label                "Check for Updates…">
 
 <!ENTITY preferencesCmdMac.label        "Preferences…">
 <!ENTITY preferencesCmdMac.commandkey   ",">
 
 <!ENTITY servicesMenuMac.label          "Services">
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -224,19 +224,17 @@ menuitem:not([type]) {
   -moz-image-region: rect(0px 64px 16px 48px);
 }
 
 #menu_openFile {
   list-style-image: url("moz-icon://stock/gtk-open?size=menu");
 }
 
 #menu_close {
-  /*XXX Avoiding size=menu as some themes (e.g. Human) don't provide the icon
-        at 16*16px (bug 426930), and upscaled images are ugly (bug 422179). */
-  list-style-image: url("moz-icon://stock/gtk-close?size=toolbar");
+  list-style-image: url("moz-icon://stock/gtk-close?size=menu");
 }
 
 #context-media-play {
   list-style-image: url("moz-icon://stock/gtk-media-play?size=menu");
 }
 
 #context-media-pause {
   list-style-image: url("moz-icon://stock/gtk-media-pause?size=menu");
@@ -971,17 +969,17 @@ toolbar[iconsize="small"] #fullscreen-bu
 .autocomplete-treebody::-moz-tree-image(bookmark, treecolAutoCompleteImage) {
   list-style-image: url("chrome://browser/skin/places/pageStarred.png");
   width: 16px;
   height: 16px;
 }
 
 .ac-result-type-keyword,
 .autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage) {
-  list-style-image: url(chrome://global/skin/icons/Search-glass.png);
+  list-style-image: url(moz-icon://stock/gtk-find?size=menu);
   width: 16px;
   height: 16px;
 }
 
 .ac-result-type-tag,
 .autocomplete-treebody::-moz-tree-image(tag, treecolAutoCompleteImage) {
   list-style-image: url("chrome://browser/skin/places/tag.png");
   width: 16px;
@@ -1090,23 +1088,27 @@ statusbarpanel#statusbar-display {
   width: 20px;
 }
 
 /* Throbber */
 #navigator-throbber {
   width: 16px;
   min-height: 16px;
   margin: 0 3px;
-  list-style-image: url("chrome://global/skin/icons/notloading_16.png");
 }
 
 #navigator-throbber[busy="true"] {
   list-style-image: url("chrome://global/skin/icons/loading_16.png");
 }
 
+#navigator-throbber,
+#wrapper-navigator-throbber > #navigator-throbber {
+  list-style-image: url("chrome://global/skin/icons/notloading_16.png");
+}
+
 
 tabpanels {
   -moz-appearance: none;
 }
 
 /* Tabs */
 .tabbrowser-tab {
   border: none !important;
@@ -1184,19 +1186,17 @@ tabpanels {
   list-style-image: url("moz-icon://stock/gtk-clear?size=menu&state=disabled");
 }
 
 #context_undoCloseTab {
   list-style-image: url("moz-icon://stock/gtk-undelete?size=menu");
 }
 
 #context_closeTab {
-  /*XXX Avoiding size=menu as some themes (e.g. Human) don't provide the icon
-        at 16*16px (bug 426930), and upscaled images are ugly (bug 422179). */
-  list-style-image: url("moz-icon://stock/gtk-close?size=toolbar");
+  list-style-image: url("moz-icon://stock/gtk-close?size=menu");
 }
 
 /* tabbrowser-tab focus ring */
 .tabbrowser-tab > .tab-text {
   border: 1px dotted transparent;
 }
 
 .tabbrowser-tab:focus > .tab-text {
@@ -1269,23 +1269,29 @@ tabpanels {
 
 .tabs-closebutton > .toolbarbutton-icon {
   margin: 0;
 }
 
 /* Tabbrowser arrowscrollbox arrows */
 .tabbrowser-arrowscrollbox > .scrollbutton-up {
   -moz-appearance: tab-scroll-arrow-back;
-  margin: 0px;
+  margin: 0;
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-down {
   -moz-appearance: tab-scroll-arrow-forward;
-  margin: 0px;
-  outline-color: Highlight;
+  margin: 0;
+  -moz-transition: 1s -moz-box-shadow ease-out;
+  -moz-border-radius: 4px;
+}
+
+.tabbrowser-arrowscrollbox > .scrollbutton-down[notifybgtab] {
+  -moz-box-shadow: 0 0 7px 5px Highlight inset;
+  -moz-transition: none;
 }
 
 .tabs-alltabs-button {
   margin-bottom: 1px;
 }
 
 .tabs-alltabs-button > .toolbarbutton-icon {
   list-style-image: url("chrome://browser/skin/tabbrowser/alltabs.png");
--- a/browser/themes/gnomestripe/browser/searchbar.css
+++ b/browser/themes/gnomestripe/browser/searchbar.css
@@ -64,24 +64,20 @@
 
 /* Search go button */
 .search-go-container {
   -moz-box-align: center;
 }
 
 .search-go-button {
   padding: 1px;
-  list-style-image: url("chrome://global/skin/icons/Search-glass.png");
+  list-style-image: url(moz-icon://stock/gtk-find?size=menu);
   cursor: pointer;
 }
 
-.search-go-button:-moz-locale-dir(rtl) {
-  -moz-transform: scaleX(-1);
-}
-
 menuitem[cmd="cmd_clearhistory"] {
   list-style-image: url("moz-icon://stock/gtk-clear?size=menu");
 }
 
 menuitem[cmd="cmd_clearhistory"][disabled] {
   list-style-image: url("moz-icon://stock/gtk-clear?size=menu&state=disabled");
 }
 
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -1652,17 +1652,22 @@ tabbrowser > tabbox > tabpanels {
 .tabbrowser-arrowscrollbox > .scrollbutton-down {
   -moz-image-region: rect(0, 11px, 17px, 0);
   margin: 0;
   padding: 0 1px;
   border: none;
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-down {
-  outline-color: Highlight;
+  -moz-transition: 1s background-color ease-out;
+}
+
+.tabbrowser-arrowscrollbox > .scrollbutton-down[notifybgtab] {
+  background-color: Highlight;
+  -moz-transition: none;
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(ltr),
 .tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-locale-dir(rtl) {
   border-right: 2px solid;
   -moz-border-right-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15);
   list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-left.png");
 }
@@ -1673,16 +1678,17 @@ tabbrowser > tabbox > tabpanels {
   -moz-border-left-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15);
   list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-right.png");
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-up:hover,
 .tabbrowser-arrowscrollbox > .scrollbutton-down:hover {
   -moz-image-region: rect(0, 22px, 17px, 11px);
   background-color: rgba(0,0,0,0.10);
+  -moz-transition: none;
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-up:hover:active,
 .tabbrowser-arrowscrollbox > .scrollbutton-down:hover:active {
   -moz-image-region: rect(0, 44px, 17px, 33px);
   background-color: rgba(0,0,0,0.20);
 }
 
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -1137,23 +1137,27 @@ statusbarpanel#statusbar-display {
 }
 
 /* ::::: throbber ::::: */
 
 #navigator-throbber {
   width: 16px;
   min-height: 16px;
   margin: 0 3px;
-  list-style-image: url("chrome://global/skin/icons/notloading_16.png");
 }
 
 #navigator-throbber[busy="true"] {
   list-style-image: url("chrome://global/skin/icons/loading_16.png");
 }
 
+#navigator-throbber,
+#wrapper-navigator-throbber > #navigator-throbber {
+  list-style-image: url("chrome://global/skin/icons/notloading_16.png");
+}
+
 /* Tabstrip */
 .tabbrowser-tabs {
   -moz-appearance: -moz-win-browsertabbar-toolbox;
   background: -moz-dialog url("chrome://browser/skin/tabbrowser/tabbrowser-tabs-bkgnd.png") repeat-x;
 }
 
 .tabbrowser-tabs:-moz-system-metric(touch-enabled) {
   min-height: .81cm;
@@ -1400,17 +1404,22 @@ tabpanels {
 .tabs-container > .tabs-newtab-button:-moz-locale-dir(ltr),
 .tabs-alltabs-button:-moz-locale-dir(ltr) {
   border-right-style: none;
   -moz-border-radius-topleft: 2px;
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-down {
   list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-right.png");
-  outline-color: Highlight;
+  -moz-transition: 1s background-color ease-out;
+}
+
+.tabbrowser-arrowscrollbox > .scrollbutton-down[notifybgtab] {
+  background-color: Highlight;
+  -moz-transition: none;
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-locale-dir(rtl),
 .tabs-container > .tabs-newtab-button:-moz-locale-dir(rtl),
 .tabs-alltabs-button:-moz-locale-dir(rtl) {
   border-left-style: none;
   -moz-border-radius-topright: 2px;
 }
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -115,16 +115,18 @@ check::
         fi
 	@if ! test -f ./unify-test-universal; then \
           echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to produce a universal binary!"; \
           false; \
         fi
 	@if ! file -b ./unify-test-universal | head -n1 | grep -q "^Mach-O universal binary"; then \
           echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to produce a universal binary!"; \
           false; \
+        else \
+          echo "TEST-PASS | build/ | unify produced a universal binary!"; \
         fi
 # try unifying two identical Java class files
 	rm -f unifytesta.class unifytestb.class unifytestc.class
 	cp $(srcdir)/unifytest.class ./unifytesta.class
 	cp $(srcdir)/unifytest.class ./unifytestb.class
 	@if ! $(srcdir)/macosx/universal/unify ./unifytesta.class ./unifytestb.class \
           ./unifytestc.class; then \
           echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to unify a Java class file!"; \
@@ -132,16 +134,36 @@ check::
         fi
 	@if ! test -f ./unifytestc.class; then \
           echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to unify a Java class file!"; \
           false; \
         fi
 	@if ! diff -q ./unifytesta.class ./unifytestc.class; then \
           echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to unify a Java class file!"; \
           false; \
+        else \
+          echo "TEST-PASS | build/ | unify unified a Java class file!"; \
+        fi
+# try unifying some files that differ only in line ordering
+	rm -rf unify-sort-test
+	mkdir unify-sort-test unify-sort-test/a unify-sort-test/b
+	printf "lmn\nabc\nxyz\n" > unify-sort-test/a/file.foo
+	printf "xyz\nlmn\nabc\n" > unify-sort-test/b/file.foo
+	printf "abc\nlmn\nxyz\n" > unify-sort-test/expected-result
+	@if ! $(srcdir)/macosx/universal/unify --unify-with-sort "\.foo$$" \
+          ./unify-sort-test/a ./unify-sort-test/b \
+          ./unify-sort-test/c; then \
+          echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to unify files with differing line ordering!"; \
+          false; \
+        fi
+	@if ! diff -q ./unify-sort-test/expected-result ./unify-sort-test/c/file.foo; then \
+          echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to unify files with differing line ordering!"; \
+          false; \
+        else \
+          echo "TEST-PASS | build/ | unify unified files with differing line ordering!"; \
         fi
 endif
 
 ifeq ($(OS_ARCH),Linux)
 libs:: $(topsrcdir)/tools/rb/fix-linux-stack.pl
 	$(INSTALL) $< $(DIST)/bin
 endif
 endif # ENABLE_TESTS
--- a/build/automation-build.mk
+++ b/build/automation-build.mk
@@ -63,16 +63,22 @@ AUTOMATION_PPARGS += -DIS_TEST_BUILD=0
 endif
 
 ifeq ($(MOZ_DEBUG), 1)
 AUTOMATION_PPARGS += -DIS_DEBUG_BUILD=1
 else
 AUTOMATION_PPARGS += -DIS_DEBUG_BUILD=0
 endif
 
+ifdef MOZ_CRASHREPORTER
+AUTOMATION_PPARGS += -DCRASHREPORTER=1
+else
+AUTOMATION_PPARGS += -DCRASHREPORTER=0
+endif
+
 $(CURDIR)/automationutils.py: $(MOZILLA_DIR)/build/automationutils.py
 	$(INSTALL) $< .
 
 automation.py: $(MOZILLA_DIR)/build/automation.py.in $(MOZILLA_DIR)/build/automation-build.mk $(CURDIR)/automationutils.py
 	$(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \
 	$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
 
 GARBAGE += automation.py $(CURDIR)/automationutils.py
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -38,16 +38,17 @@
 # ***** END LICENSE BLOCK *****
 
 import codecs
 from datetime import datetime
 import itertools
 import logging
 import os
 import re
+import select
 import shutil
 import signal
 import subprocess
 import sys
 import threading
 
 from automationutils import checkForCrashes
 
@@ -67,18 +68,22 @@ SCRIPT_DIR = os.path.abspath(os.path.rea
            "Process",
            "initializeProfile",
            "DIST_BIN",
            "DEFAULT_APP",
            "CERTS_SRC_DIR",
            "environment",
            "IS_TEST_BUILD",
            "IS_DEBUG_BUILD",
+           "DEFAULT_TIMEOUT",
           ]
 
+# timeout, in seconds
+DEFAULT_TIMEOUT = 60.0
+
 # These are generated in mozilla/build/Makefile.in
 #expand DIST_BIN = __XPC_BIN_PATH__
 #expand IS_WIN32 = len("__WIN32__") != 0
 #expand IS_MAC = __IS_MAC__ != 0
 #expand IS_LINUX = __IS_LINUX__ != 0
 #ifdef IS_CYGWIN
 #expand IS_CYGWIN = __IS_CYGWIN__ == 1
 #else
@@ -89,16 +94,17 @@ IS_CYGWIN = False
 #expand PERL = __PERL__
 
 UNIXISH = not IS_WIN32 and not IS_MAC
 
 #expand DEFAULT_APP = "./" + __BROWSER_PATH__
 #expand CERTS_SRC_DIR = __CERTS_SRC_DIR__
 #expand IS_TEST_BUILD = __IS_TEST_BUILD__
 #expand IS_DEBUG_BUILD = __IS_DEBUG_BUILD__
+#expand CRASHREPORTER = __CRASHREPORTER__ == 1
 
 ###########
 # LOGGING #
 ###########
 
 # We use the logging system here primarily because it'll handle multiple
 # threads, which is needed to process the output of the server and application
 # processes simultaneously.
@@ -429,25 +435,82 @@ def environment(env = None, xrePath = DI
     env["PATH"] = env["PATH"] + ";" + ldLibraryPath
 
   if crashreporter:
     env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
     env['MOZ_CRASHREPORTER'] = '1'
   env['GNOME_DISABLE_CRASH_DIALOG'] = "1"
   return env
 
+if IS_WIN32:
+  #XXX: disabled on windows for now, see bug 525370 
+  def readWithTimeout(f, timeout):
+    return (f.readline(), False)
+elif False:
+  #XXX: figure out what's going wrong with this code!
+  import ctypes, time, msvcrt
+  PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe
+  GetLastError = ctypes.windll.kernel32.GetLastError
+  def readWithTimeout(f, timeout):
+    """Try to read a line of output from the file object |f|.
+    |f| must be a  pipe, like the |stdout| member of a subprocess.Popen
+    object created with stdout=PIPE. If no output
+    is received within |timeout| seconds, return a blank line.
+    Returns a tuple (line, did_timeout), where |did_timeout| is True
+    if the read timed out, and False otherwise."""
+    x = msvcrt.get_osfhandle(f.fileno())
+    l = ctypes.c_long()
+    buf = ctypes.create_string_buffer('', 1024)
+    done = time.time() + timeout
+    while time.time() < done:
+        if PeekNamedPipe(x, buf, len(buf), None, ctypes.byref(l), None) == 0:
+            err = GetLastError()
+            if err == 38 or err == 109: # ERROR_HANDLE_EOF || ERROR_BROKEN_PIPE
+                return ('', False)
+        if (l > 0 and '\n' in buf.value):
+            return (f.readline(), False)
+        time.sleep(0.1)
+    return ('', True)
+else:
+  def readWithTimeout(f, timeout):
+    """Try to read a line of output from the file object |f|. If no output
+    is received within |timeout| seconds, return a blank line.
+    Returns a tuple (line, did_timeout), where |did_timeout| is True
+    if the read timed out, and False otherwise."""
+    (r, w, e) = select.select([f], [], [], timeout)
+    if len(r) == 0:
+      return ('', True)
+    return (f.readline(), False)
+
+def triggerBreakpad(proc, utilityPath):
+  """Attempt to kill this process in a way that triggers Breakpad crash
+  reporting, if we know how for this platform. Otherwise just .kill() it."""
+  if CRASHREPORTER:
+    if UNIXISH:
+      # SEGV will get picked up by Breakpad's signal handler
+      os.kill(proc.pid, signal.SIGSEGV)
+      return
+    elif IS_WIN32:
+      # We should have a "crashinject" program in our utility path
+      crashinject = os.path.normpath(os.path.join(utilityPath, "crashinject.exe"))
+      if os.path.exists(crashinject) and subprocess.Popen([crashinject, str(proc.pid)]).wait() == 0:
+        return
+  #TODO: kill the process such that it triggers Breakpad on OS X
+  log.info("Can't trigger Breakpad, just killing process")
+  proc.kill()
 
 ###############
 # RUN THE APP #
 ###############
 
 def runApp(testURL, env, app, profileDir, extraArgs,
            runSSLTunnel = False, utilityPath = DIST_BIN,
            xrePath = DIST_BIN, certPath = CERTS_SRC_DIR,
-           debuggerInfo = None, symbolsPath = None):
+           debuggerInfo = None, symbolsPath = None,
+           timeout = DEFAULT_TIMEOUT):
   "Run the app, log the duration it took to execute, return the status code."
 
   # copy env so we don't munge the caller's environment
   env = dict(env);
   env["NO_EM_RESTART"] = "1"
 
   if IS_TEST_BUILD and runSSLTunnel:
     # create certificate database for the profile
@@ -501,41 +564,45 @@ def runApp(testURL, env, app, profileDir
   proc = Process([cmd] + args,
                  env = environment(env, xrePath = xrePath,
                                    crashreporter = not debuggerInfo),
                  stdout = outputPipe,
                  stderr = subprocess.STDOUT)
   log.info("INFO | automation.py | Application pid: %d", proc.pid)
 
   stackFixerProcess = None
+  didTimeout = False
   if outputPipe is None:
     log.info("TEST-INFO: Not logging stdout or stderr due to debugger connection")
   else:
     logsource = proc.stdout
     if IS_DEBUG_BUILD:
       stackFixerCommand = None
       if IS_MAC:
         stackFixerCommand = "fix-macosx-stack.pl"
       elif IS_LINUX:
         stackFixerCommand = "fix-linux-stack.pl"
       if stackFixerCommand is not None:
         stackFixerProcess = Process([PERL, os.path.join(utilityPath, stackFixerCommand)], stdin=logsource, stdout=subprocess.PIPE)
         logsource = stackFixerProcess.stdout
 
-    line = logsource.readline()
-    while line != "":
+    (line, didTimeout) = readWithTimeout(logsource, timeout)
+    while line != "" and not didTimeout:
       log.info(line.rstrip())
-      line = logsource.readline()
+      (line, didTimeout) = readWithTimeout(logsource, timeout)
+    if didTimeout:
+      log.info("TEST-UNEXPECTED-FAIL | automation.py | application timed out after %d seconds with no output", int(timeout))
+      triggerBreakpad(proc, utilityPath)
 
   status = proc.wait()
-  if status != 0:
+  if status != 0 and not didTimeout:
     log.info("TEST-UNEXPECTED-FAIL | automation.py | Exited with code %d during test run", status)
   if stackFixerProcess is not None:
     status = stackFixerProcess.wait()
-    if status != 0:
+    if status != 0 and not didTimeout:
       log.info("TEST-UNEXPECTED-FAIL | automation.py | Stack fixer process exited with code %d during test run", status)
   log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
 
   if checkForCrashes(os.path.join(profileDir, "minidumps"), symbolsPath):
     status = -1
 
   if IS_TEST_BUILD and runSSLTunnel:
     ssltunnelProcess.kill()
--- a/build/macosx/universal/flight.mk
+++ b/build/macosx/universal/flight.mk
@@ -100,16 +100,18 @@ postflight_all:
 	$(TOPSRCDIR)/build/macosx/universal/fix-buildconfig \
 	  $(DIST_PPC)/$(MOZ_PKG_APPNAME)/$(APPNAME)/$(BUILDCONFIG_JAR) \
 	  $(DIST_X86)/$(MOZ_PKG_APPNAME)/$(APPNAME)/$(BUILDCONFIG_JAR)
 	mkdir -p $(DIST_UNI)/$(MOZ_PKG_APPNAME)
 	rm -f $(DIST_X86)/universal
 	ln -s $(DIST_UNI) $(DIST_X86)/universal
 	rm -rf $(DIST_UNI)/$(MOZ_PKG_APPNAME)/$(APPNAME)
 	$(TOPSRCDIR)/build/macosx/universal/unify \
+          --unify-with-sort "\.manifest$$" \
+          --unify-with-sort "components\.list$$" \
 	  $(DIST_PPC)/$(MOZ_PKG_APPNAME)/$(APPNAME) \
 	  $(DIST_X86)/$(MOZ_PKG_APPNAME)/$(APPNAME) \
 	  $(DIST_UNI)/$(MOZ_PKG_APPNAME)/$(APPNAME)
 # A universal .dmg can now be produced by making in either architecture's
 # INSTALLER_DIR.
 # Now, repeat the process for the test package.
 	$(MAKE) -C $(OBJDIR_PPC) UNIVERSAL_BINARY= package-tests
 	$(MAKE) -C $(OBJDIR_X86) UNIVERSAL_BINARY= package-tests
@@ -118,11 +120,12 @@ postflight_all:
 # dist/bin. It doesn't matter which one we use.
 	if test -d $(DIST_PPC)/test-package-stage -a                 \
                 -d $(DIST_X86)/test-package-stage; then              \
            cp $(DIST_PPC)/test-package-stage/mochitest/automation.py \
              $(DIST_X86)/test-package-stage/mochitest/;              \
            cp $(DIST_PPC)/test-package-stage/reftest/automation.py   \
              $(DIST_X86)/test-package-stage/reftest/;                \
            $(TOPSRCDIR)/build/macosx/universal/unify                 \
+             --unify-with-sort "all-test-dirs\.list$$"               \
              $(DIST_PPC)/test-package-stage                          \
              $(DIST_X86)/test-package-stage                          \
              $(DIST_UNI)/test-package-stage; fi
--- a/build/macosx/universal/unify
+++ b/build/macosx/universal/unify
@@ -48,16 +48,17 @@ B<unify> - Mac OS X universal binary pac
 
 B<unify>
 I<ppc-path>
 I<x86-path>
 I<universal-path>
 [B<--dry-run>]
 [B<--only-one> I<action>]
 [B<--verbosity> I<level>]
+[B<--unify-with-sort> I<regex>]
 
 =head1 DESCRIPTION
 
 I<unify> merges any two architecture-specific files or directory trees
 into a single file or tree suitable for use on either architecture as a
 "fat" or "universal binary."
 
 Architecture-specific Mach-O files will be merged into fat Mach-O files
@@ -129,16 +130,23 @@ I<level> are:
   0 - B<unify> never prints anything.
       (Other programs that B<unify> calls may still print messages.)
   1 - Fatal error messages are printed to stderr.
   2 - Nonfatal warnings are printed to stderr.
   3 - Commands are printed to stdout as they are executed.
 
 The default I<level> is 2.
 
+=item B<--unify-with-sort> I<regex>
+
+Allows merging files matching I<regex> that differ only by the ordering
+of the lines contained within them. The unified file will have its contents
+sorted. This option may be given multiple times to specify multiple
+regexes for matching files.
+
 =back
 
 =head1 EXAMPLES
 
 =over 5
 
 =item Create a universal .app bundle from two architecture-specific .app
 bundles:
@@ -178,23 +186,27 @@ L<cmp(1)>, L<ditto(1)>, L<lipo(1)>
 
 use Archive::Zip(':ERROR_CODES');
 use Errno;
 use Fcntl;
 use File::Compare;
 use File::Copy;
 use Getopt::Long;
 
-my (%gConfig, $gDryRun, $gOnlyOne, $gVerbosity);
+my (%gConfig, $gDryRun, $gOnlyOne, $gVerbosity, @gSortMatches);
 
 sub argumentEscape(@);
 sub command(@);
 sub compareZipArchives($$);
 sub complain($$@);
 sub copyIfIdentical($$$);
+sub slurp($);
+sub compare_sorted($$);
+sub copy_sorted($$);
+sub copyIfIdenticalWhenSorted($$$);
 sub createUniqueFile($$);
 sub makeUniversal($$$);
 sub makeUniversalDirectory($$$);
 sub makeUniversalInternal($$$$);
 sub makeUniversalFile($$$);
 sub usage();
 sub readZipCRCs($);
 
@@ -223,22 +235,24 @@ sub readZipCRCs($);
 %gConfig = (
   'cmd_lipo' => 'lipo',
   'cmd_rm'   => 'rm',
 );
 
 $gDryRun = 0;
 $gOnlyOne = 'copy';
 $gVerbosity = 2;
+@gSortMatches = ();
 
 Getopt::Long::Configure('pass_through');
-GetOptions('dry-run'     => \$gDryRun,
-           'only-one=s'  => \$gOnlyOne,
-           'verbosity=i' => \$gVerbosity,
-           'config=s'    => \%gConfig); # "hidden" option not in usage()
+GetOptions('dry-run'           => \$gDryRun,
+           'only-one=s'        => \$gOnlyOne,
+           'verbosity=i'       => \$gVerbosity,
+           'unify-with-sort=s' => \@gSortMatches,
+           'config=s'          => \%gConfig); # "hidden" option not in usage()
 
 if (scalar(@ARGV) != 3 || $gVerbosity < 0 || $gVerbosity > 3 ||
     ($gOnlyOne ne 'skip' && $gOnlyOne ne 'copy' && $gOnlyOne ne 'fail')) {
   usage();
   exit(1);
 }
 
 if (!makeUniversal($ARGV[0],$ARGV[1],$ARGV[2])) {
@@ -476,16 +490,126 @@ sub copyIfIdentical($$$) {
       unlink($target);
       return 0;
     }
   }
 
   return 1;
 }
 
+# slurp($file)
+#
+# Read the contents of $file into an array and return it.
+# Returns undef on error.
+sub slurp($) {
+  my $file = $_[0];
+  open FILE, $file or return undef;
+  my @lines = <FILE>;
+  close FILE;
+  return @lines;
+}
+
+# compare_sorted($file1, $file2)
+#
+# Read the contents of both files into arrays, sort the arrays,
+# and then compare the two arrays for equality.
+#
+# Returns 0 if the sorted array contents are equal, or 1 if not.
+# Returns undef on error.
+sub compare_sorted($$) {
+  my ($file1, $file2) = @_;
+  my @lines1 = sort(slurp($file1));
+  my @lines2 = sort(slurp($file2));
+
+  return undef if !@lines1 || !@lines2;
+  return 1 unless scalar @lines1 == scalar @lines2;
+
+  for (my $i = 0; $i < scalar @lines1; $i++) {
+    return 1 if $lines1[$i] ne $lines2[$i];
+  }
+  return 0;
+}
+
+# copy_sorted($source, $destination)
+#
+# $source and $destination are filenames. Read the contents of $source
+# into an array, sort it, and then write the sorted contents to $destination.
+# Returns 1 on success, and undef on failure.
+sub copy_sorted($$) {
+  my ($src, $dest) = @_;
+  my @lines = sort(slurp($src));
+  return undef unless @lines;
+  open FILE, "> $dest" or return undef;
+  print FILE @lines;
+  close FILE;
+  return 1;
+}
+
+# copyIfIdenticalWhenSorted($source1, $source2, $target)
+#
+# $source1 and $source2 are FileAttrCache objects that are compared, and if
+# identical, copied to path string $target.  The comparison is done by
+# sorting the individual lines within the two files and comparing the results.
+#
+# Returns true on success, false for files that are not equivalent,
+# and undef if an error occurs.
+sub copyIfIdenticalWhenSorted($$$) {
+  my ($source1, $source2, $target);
+  ($source1, $source2, $target) = @_;
+
+  if ($gVerbosity >= 3 || $gDryRun) {
+    print('cmp -s '.
+          join(' ',argumentEscape($source1->path(), $source2->path()))."\n");
+  }
+  my ($comparison);
+  if (!defined($comparison = compare_sorted($source1->path(),
+                                            $source2->path())) ||
+      $comparison == -1) {
+    return complain(1, 'copyIfIdenticalWhenSorted: compare: '.$!
+                    .' while comparing:',
+                      $source1->path(),
+                      $source2->path());
+  }
+  if ($comparison != 0) {
+    return complain(1, 'copyIfIdenticalWhenSorted: files differ:',
+                    $source1->path(),
+                    $source2->path());
+  }
+
+  if ($gVerbosity >= 3 || $gDryRun) {
+    print('cp '.
+          join(' ',argumentEscape($source1->path(), $target))."\n");
+  }
+
+  if (!$gDryRun) {
+    my ($isExecutable);
+
+    # Set the execute bits (as allowed by the umask) on the new file if any
+    # execute bit is set on either old file.
+    $isExecutable = $source1->lIsExecutable() ||
+                    (defined($source2) && $source2->lIsExecutable());
+
+    if (!createUniqueFile($target, $isExecutable ? 0777 : 0666)) {
+      # createUniqueFile printed an error.
+      return 0;
+    }
+
+    if (!copy_sorted($source1->path(), $target)) {
+      complain(1, 'copyIfIdenticalWhenSorted: copy_sorted: '.$!
+               .' while copying',
+               $source1->path(),
+               $target);
+      unlink($target);
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
 # createUniqueFile($path, $mode)
 #
 # Creates a new plain empty file at pathname $path, provided it does not
 # yet exist.  $mode is used as the file mode.  The actual file's mode will
 # be modified by the effective umask.  Returns false if the file could
 # not be created, setting $! to the error.  An error message is printed
 # in the event of failure.
 sub createUniqueFile($$) {
@@ -963,16 +1087,22 @@ sub makeUniversalInternal($$$$) {
                   $fileX86->path());
     }
 
     if ($machPPC) {
       # makeUniversalFile will print an error if it fails.
       return makeUniversalFile($filePPC, $fileX86, $fileTargetPath);
     }
 
+    if (grep { $filePPC->path() =~ m/$_/; } @gSortMatches) {
+      # Regular files, but should be compared with sorting first.
+      # copyIfIdenticalWhenSorted will print an error if it fails.
+      return copyIfIdenticalWhenSorted($filePPC, $fileX86, $fileTargetPath);
+    }
+
     # Regular file.  copyIfIdentical will print an error if it fails.
     return copyIfIdentical($filePPC, $fileX86, $fileTargetPath);
   }
 
   # Special file, don't know how to handle.
   return complain(1, 'makeUniversal: cannot handle special file:',
                   $filePPC->path(),
                   $fileX86->path());
--- a/build/pgo/profileserver.py.in
+++ b/build/pgo/profileserver.py.in
@@ -63,10 +63,16 @@ if __name__ == '__main__':
   t.start()
 
   automation.initializeProfile(PROFILE_DIRECTORY)
   browserEnv = automation.environment()
   browserEnv["XPCOM_DEBUG_BREAK"] = "warn"
 
   url = "http://localhost:%d/index.html" % PORT
   appPath = os.path.join(SCRIPT_DIR, automation.DEFAULT_APP)
-  status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY, {})
+  status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY, {},
+                             # the profiling HTML doesn't output anything,
+                             # so let's just set this really high for now.
+                             #FIXME: the POSIX codepath accepts None
+                             # as "no timeout", the Windows codepath
+                             # should too.
+                             timeout = 1800.0)
   sys.exit(status)
--- a/build/win32/Makefile.in
+++ b/build/win32/Makefile.in
@@ -37,16 +37,25 @@
 
 DEPTH = ../..
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
+ifdef ENABLE_TESTS
+DIRS += crashinjectdll
+
+PROGRAM = crashinject$(BIN_SUFFIX)
+USE_STATIC_LIBS = 1
+CPPSRCS = crashinject.cpp
+
+endif
+
 include $(topsrcdir)/config/rules.mk
 
 ifdef WIN32_REDIST_DIR
 
 ifeq (1400,$(_MSC_VER))
 REDIST_FILES = \
 	Microsoft.VC80.CRT.manifest \
 	msvcm80.dll \
new file mode 100644
--- /dev/null
+++ b/build/win32/crashinject.cpp
@@ -0,0 +1,128 @@
+/* ***** 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 Crash Injection Utility
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ted Mielczarek <ted.mielczarek@gmail.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 ***** */
+
+/*
+ * Given a PID, this program attempts to inject a DLL into the process
+ * with that PID. The DLL it attempts to inject, "crashinjectdll.dll",
+ * must exist alongside this exe. The DLL will then crash the process.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <Windows.h>
+
+int main(int argc, char** argv)
+{
+  if (argc != 2) {
+    fprintf(stderr, "Usage: crashinject <PID>\n");
+    return 1;
+  }
+  
+  int pid = atoi(argv[1]);
+  if (pid <= 0) {
+    fprintf(stderr, "Usage: crashinject <PID>\n");
+    return 1;
+  }
+
+  // find our DLL to inject
+  wchar_t filename[_MAX_PATH];
+  if (GetModuleFileNameW(NULL, filename, sizeof(filename) / sizeof(wchar_t)) == 0)
+    return 1;
+
+  wchar_t* slash = wcsrchr(filename, L'\\');
+  if (slash == NULL)
+    return 1;
+
+  slash++;
+  wcscpy(slash, L"crashinjectdll.dll");
+
+  // now find our target process
+  HANDLE targetProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD,
+                                  FALSE,
+                                  pid);
+  if (targetProc == NULL) {
+    fprintf(stderr, "Error %d opening target process\n", GetLastError());
+    return 1;
+  }
+
+  /*
+   * This is sort of insane, but we're implementing a technique described here:
+   * http://www.codeproject.com/KB/threads/winspy.aspx#section_2
+   *
+   * The gist is to use CreateRemoteThread to create a thread in the other
+   * process, but cheat and make the thread function kernel32!LoadLibrary,
+   * so that the only remote data we have to pass to the other process
+   * is the path to the library we want to load. The library we're loading
+   * will then do its dirty work inside the other process.
+   */
+  HMODULE hKernel32 = GetModuleHandleW(L"Kernel32");
+  // allocate some memory to hold the path in the remote process
+  void*   pLibRemote = VirtualAllocEx(targetProc, NULL, sizeof(filename),
+                                      MEM_COMMIT, PAGE_READWRITE);
+  if (pLibRemote == NULL) {
+    fprintf(stderr, "Error %d in VirtualAllocEx\n", GetLastError());
+    CloseHandle(targetProc);
+    return 1;
+  }
+
+  if (!WriteProcessMemory(targetProc, pLibRemote, (void*)filename,
+                          sizeof(filename), NULL)) {
+    fprintf(stderr, "Error %d in WriteProcessMemory\n", GetLastError());
+    VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE);
+    CloseHandle(targetProc);
+    return 1;
+  }
+  // Now create a thread in the target process that will load our DLL
+  HANDLE hThread = CreateRemoteThread(
+                     targetProc, NULL, 0,
+                     (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32,
+                                                            "LoadLibraryW"),
+                     pLibRemote, 0, NULL);
+  if (hThread == NULL) {
+    fprintf(stderr, "Error %d in CreateRemoteThread\n", GetLastError());
+    VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE);
+    CloseHandle(targetProc);
+    return 1;
+  }
+  WaitForSingleObject(hThread, INFINITE);
+  // Cleanup, not that it's going to matter at this point
+  CloseHandle(hThread);
+  VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE);
+  CloseHandle(targetProc);
+  
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/build/win32/crashinjectdll/Makefile.in
@@ -0,0 +1,53 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla core build scripts.
+#
+# The Initial Developer of the Original Code is
+# The Mozilla Foundation
+#
+# Portions created by the Initial Developer are Copyright (C) 2009
+# the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
+#
+# Contributor(s): 
+#   Ted Mielczarek <ted.mielczarek@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+LIBRARY_NAME = crashinjectdll
+DEFFILE = $(srcdir)/crashinjectdll.def
+FORCE_SHARED_LIB = 1
+USE_STATIC_LIBS = 1
+
+CPPSRCS = crashinjectdll.cpp
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/build/win32/crashinjectdll/crashinjectdll.cpp
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <Windows.h>
+
+// make sure we only ever spawn one thread
+DWORD tid = -1;
+
+DWORD WINAPI CrashingThread(
+  LPVOID lpParameter
+)
+{
+  // not a very friendly DLL
+  volatile int* x = (int *)0x0;
+  *x = 1;
+  return 0;
+}
+
+BOOL WINAPI DllMain(
+  HANDLE hinstDLL, 
+  DWORD dwReason, 
+  LPVOID lpvReserved
+)
+{
+  if (tid == -1)
+    // we have to crash on another thread because LoadLibrary() will
+    // catch memory access errors and return failure to the calling process
+    CreateThread( 
+                 NULL,                   // default security attributes
+                 0,                      // use default stack size  
+                 CrashingThread  ,       // thread function name
+                 NULL,                   // argument to thread function 
+                 0,                      // use default creation flags 
+                 &tid);                  // returns the thread identifier 
+  return TRUE;
+}
new file mode 100644
--- /dev/null
+++ b/build/win32/crashinjectdll/crashinjectdll.def
@@ -0,0 +1,3 @@
+LIBRARY crashinjectdll
+EXPORTS
+     DllMain
--- a/build/wince/shunt/mozce_shunt.def.in
+++ b/build/wince/shunt/mozce_shunt.def.in
@@ -42,22 +42,13 @@ malloc
 valloc
 calloc
 realloc
 free
 posix_memalign
 memalign
 malloc_usable_size
 jemalloc_stats
-xmalloc
-xcalloc
-xrealloc
-xmemalign
-reserve_cb_register
-reserve_cb_unregister
-reserve_cur_get
-reserve_min_get
-reserve_min_set
 _strdup
 _wcsdup
 _strndup
 _wcsndup
 #endif
--- a/chrome/src/nsChromeRegistry.cpp
+++ b/chrome/src/nsChromeRegistry.cpp
@@ -507,61 +507,37 @@ nsChromeRegistry::Init()
   if (safeMode)
     prefserv->GetDefaultBranch(nsnull, getter_AddRefs(prefs));
   else
     prefs = do_QueryInterface(prefserv);
 
   if (!prefs) {
     NS_WARNING("Could not get pref service!");
   }
-
-  PRBool useLocalePref = PR_TRUE;
-
-  if (prefs) {
-    // check the pref first
-    PRBool matchOS = PR_FALSE;
-    rv = prefs->GetBoolPref(MATCH_OS_LOCALE_PREF, &matchOS);
-
-    // match os locale
-    if (NS_SUCCEEDED(rv) && matchOS) {
-      // compute lang and region code only when needed!
-      nsCAutoString uiLocale;
-      rv = getUILangCountry(uiLocale);
-      if (NS_SUCCEEDED(rv)) {
-        useLocalePref = PR_FALSE;
-        mSelectedLocale = uiLocale;
-      }
-    }
-  }
-      
-  if (prefs) {
+  else {
     nsXPIDLCString provider;
-
     rv = prefs->GetCharPref(SELECTED_SKIN_PREF, getter_Copies(provider));
     if (NS_SUCCEEDED(rv))
       mSelectedSkin = provider;
 
-    nsCOMPtr<nsIPrefBranch2> prefs2 (do_QueryInterface(prefs));
-
-    if (prefs2)
-      rv = prefs2->AddObserver(SELECTED_SKIN_PREF, this, PR_TRUE);
+    SelectLocaleFromPref(prefs);
 
-    if (useLocalePref) {
-      rv = prefs->GetCharPref(SELECTED_LOCALE_PREF, getter_Copies(provider));
-      if (NS_SUCCEEDED(rv))
-        mSelectedLocale = provider;
-      
-      if (prefs2)
-        prefs2->AddObserver(SELECTED_LOCALE_PREF, this, PR_TRUE);
+    nsCOMPtr<nsIPrefBranch2> prefs2 (do_QueryInterface(prefs));
+    if (prefs2) {
+      rv = prefs2->AddObserver(MATCH_OS_LOCALE_PREF, this, PR_TRUE);
+      rv = prefs2->AddObserver(SELECTED_LOCALE_PREF, this, PR_TRUE);
+      rv = prefs2->AddObserver(SELECTED_SKIN_PREF, this, PR_TRUE);
     }
   }
 
   nsCOMPtr<nsIObserverService> obsService (do_GetService("@mozilla.org/observer-service;1"));
-  if (obsService)
+  if (obsService) {
     obsService->AddObserver(this, "command-line-startup", PR_TRUE);
+    obsService->AddObserver(this, "profile-initial-state", PR_TRUE);
+  }
 
   CheckForNewChrome();
 
   mInitialized = PR_TRUE;
 
   return NS_OK;
 }
 
@@ -1286,40 +1262,67 @@ nsChromeRegistry::WrappersEnabled(nsIURI
     static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
                                                     & (nsACString&) package,
                                                     PL_DHASH_LOOKUP));
 
   return PL_DHASH_ENTRY_IS_LIVE(entry) &&
          entry->flags & PackageEntry::XPCNATIVEWRAPPERS;
 }
 
+nsresult
+nsChromeRegistry::SelectLocaleFromPref(nsIPrefBranch* prefs)
+{
+  nsresult rv;
+  PRBool matchOSLocale = PR_FALSE;
+  rv = prefs->GetBoolPref(MATCH_OS_LOCALE_PREF, &matchOSLocale);
+
+  if (NS_SUCCEEDED(rv) && matchOSLocale) {
+    // compute lang and region code only when needed!
+    nsCAutoString uiLocale;
+    rv = getUILangCountry(uiLocale);
+    if (NS_SUCCEEDED(rv))
+      mSelectedLocale = uiLocale;
+  }
+  else {
+    nsXPIDLCString provider;
+    rv = prefs->GetCharPref(SELECTED_LOCALE_PREF, getter_Copies(provider));
+    if (NS_SUCCEEDED(rv)) {
+      mSelectedLocale = provider;
+    }
+  }
+
+  return rv;
+}
+
 NS_IMETHODIMP nsChromeRegistry::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
 {
   nsresult rv = NS_OK;
 
   if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
     nsCOMPtr<nsIPrefBranch> prefs (do_QueryInterface(aSubject));
     NS_ASSERTION(prefs, "Bad observer call!");
 
     NS_ConvertUTF16toUTF8 pref(someData);
 
-    nsXPIDLCString provider;
-    rv = prefs->GetCharPref(pref.get(), getter_Copies(provider));
-    if (NS_FAILED(rv)) {
-      NS_ERROR("Couldn't get new locale or skin pref!");
-      return rv;
+    if (pref.EqualsLiteral(MATCH_OS_LOCALE_PREF) ||
+        pref.EqualsLiteral(SELECTED_LOCALE_PREF)) {
+      rv = SelectLocaleFromPref(prefs);
+      if (NS_SUCCEEDED(rv) && mProfileLoaded)
+        FlushAllCaches();
     }
+    else if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) {
+      nsXPIDLCString provider;
+      rv = prefs->GetCharPref(pref.get(), getter_Copies(provider));
+      if (NS_FAILED(rv)) {
+        NS_ERROR("Couldn't get new locale pref!");
+        return rv;
+      }
 
-    if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) {
       mSelectedSkin = provider;
       RefreshSkins();
-    }
-    else if (pref.EqualsLiteral(SELECTED_LOCALE_PREF)) {
-      mSelectedLocale = provider;
-      FlushAllCaches();
     } else {
       NS_ERROR("Unexpected pref!");
     }
   }
   else if (!strcmp("command-line-startup", aTopic)) {
     nsCOMPtr<nsICommandLine> cmdLine (do_QueryInterface(aSubject));
     if (cmdLine) {
       nsAutoString uiLocale;
@@ -1329,16 +1332,19 @@ NS_IMETHODIMP nsChromeRegistry::Observe(
         CopyUTF16toUTF8(uiLocale, mSelectedLocale);
         nsCOMPtr<nsIPrefBranch2> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
         if (prefs) {
           prefs->RemoveObserver(SELECTED_LOCALE_PREF, this);
         }
       }
     }
   }
+  else if (!strcmp("profile-initial-state", aTopic)) {
+    mProfileLoaded = PR_TRUE;
+  }
   else {
     NS_ERROR("Unexpected observer topic!");
   }
 
   return rv;
 }
 
 nsresult
--- a/chrome/src/nsChromeRegistry.h
+++ b/chrome/src/nsChromeRegistry.h
@@ -57,16 +57,17 @@
 #include "nsInterfaceHashtable.h"
 
 struct PRFileDesc;
 class nsIAtom;
 class nsICSSLoader;
 class nsICSSStyleSheet;
 class nsIDOMWindowInternal;
 class nsILocalFile;
+class nsIPrefBranch;
 class nsIRDFDataSource;
 class nsIRDFResource;
 class nsIRDFService;
 class nsISimpleEnumerator;
 class nsIURL;
 
 // for component registration
 // {47049e42-1d87-482a-984d-56ae185e367a}
@@ -90,17 +91,17 @@ public:
 
 #ifdef MOZ_XUL
   NS_DECL_NSIXULOVERLAYPROVIDER
 #endif
 
   NS_DECL_NSIOBSERVER
 
   // nsChromeRegistry methods:
-  nsChromeRegistry() : mInitialized(PR_FALSE) {
+  nsChromeRegistry() : mInitialized(PR_FALSE), mProfileLoaded(PR_FALSE) {
     mPackagesHash.ops = nsnull;
   }
   ~nsChromeRegistry();
 
   nsresult Init();
 
   static nsChromeRegistry* gChromeRegistry;
 
@@ -111,16 +112,18 @@ protected:
 
   nsresult LoadInstallDataSource();
   nsresult LoadProfileDataSource();
 
   void FlushSkinCaches();
   void FlushAllCaches();
 
 private:
+  nsresult SelectLocaleFromPref(nsIPrefBranch* prefs);
+
   static nsresult RefreshWindow(nsIDOMWindowInternal* aWindow,
                                 nsICSSLoader* aCSSLoader);
   static nsresult GetProviderAndPath(nsIURL* aChromeURL,
                                      nsACString& aProvider, nsACString& aPath);
 
 #ifdef MOZ_XUL
   NS_HIDDEN_(void) ProcessProvider(PRFileDesc *fd, nsIRDFService* aRDFs,
                                    nsIRDFDataSource* ds, nsIRDFResource* aRoot,
@@ -240,16 +243,17 @@ public:
     const nsCOMArray<nsIURI>* GetArray(nsIURI* aBase);
 
   private:
     nsTHashtable<OverlayListEntry> mTable;
   };
 
 private:
   PRBool mInitialized;
+  PRBool mProfileLoaded;
 
   // Hash of package names ("global") to PackageEntry objects
   PLDHashTable mPackagesHash;
 
   // Hashes on the file to be overlaid (chrome://browser/content/browser.xul)
   // to a list of overlays/stylesheets
   OverlayListHash mOverlayHash;
   OverlayListHash mStyleHash;
new file mode 100644
--- /dev/null
+++ b/chrome/test/unit/data/test_bug519468.manifest
@@ -0,0 +1,2 @@
+locale testmatchos en-US jar:en-US.jar!/locale/en-US/global/
+locale testmatchos fr-FR jar:en-US.jar!/locale/en-US/global/
new file mode 100644
--- /dev/null
+++ b/chrome/test/unit/test_bug519468.js
@@ -0,0 +1,80 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *      Vivien Nicolas <21@vingtetun.org>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 MANIFESTS = [
+  do_get_file("data/test_bug519468.manifest")
+];
+
+registerManifests(MANIFESTS);
+
+var chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
+                .getService(Ci.nsIXULChromeRegistry)
+                .QueryInterface(Ci.nsIToolkitChromeRegistry);
+
+var localeService = Cc["@mozilla.org/intl/nslocaleservice;1"]
+                    .getService(Ci.nsILocaleService);
+
+var prefService = Cc["@mozilla.org/preferences-service;1"]
+                  .getService(Ci.nsIPrefService)
+                  .QueryInterface(Ci.nsIPrefBranch);
+
+function test_locale(aTest) {
+  prefService.setBoolPref("intl.locale.matchOS", aTest.matchOS);
+  prefService.setCharPref("general.useragent.locale", aTest.selected || "en-US");
+
+  var selectedLocale = chromeReg.getSelectedLocale("testmatchos");
+  do_check_eq(selectedLocale, aTest.locale);
+}
+
+function run_test()
+{
+  var systemLocale = localeService.getLocaleComponentForUserAgent();
+
+  var tests = [
+    {matchOS: false, selected: null, locale: "en-US"},
+    {matchOS: true, selected: null, locale: systemLocale},
+    {matchOS: true, selected: "fr-FR", locale: systemLocale},
+    {matchOS: false, selected: "fr-FR", locale: "fr-FR"},
+    {matchOS: true, selected: null, locale: systemLocale}
+  ];
+
+  for (var i = 0; i < tests.length; ++ i) {
+    var test = tests[i];
+    test_locale(test);
+  }
+}
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -882,16 +882,17 @@ else
 	$(INSTALL) $(IFLAGS1) $(LIBRARY) $(DIST)/lib
 endif
 endif # DIST_INSTALL
 endif # LIBRARY
 ifdef SHARED_LIBRARY
 ifdef IS_COMPONENT
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
 	$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
+	@$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_TARGET)/components/components.list $(SHARED_LIBRARY)
 ifdef BEOS_ADDON_WORKAROUND
 	( cd $(FINAL_TARGET)/components && $(CC) -nostart -o $(SHARED_LIBRARY).stub $(SHARED_LIBRARY) )
 endif
 else # ! IS_COMPONENT
 ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
 	$(INSTALL) $(IFLAGS2) $(IMPORT_LIBRARY) $(DIST)/lib
 else
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DIST)/lib
@@ -1802,29 +1803,32 @@ endif # XPIDLSRCS
 endif # MOZ_JAVAXPCOM
 
 ################################################################################
 # Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components
 ifdef EXTRA_COMPONENTS
 libs:: $(EXTRA_COMPONENTS)
 ifndef NO_DIST_INSTALL
 	$(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/components
+	@$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_TARGET)/components/components.list $(notdir $^)
 endif
 
 endif
 
 ifdef EXTRA_PP_COMPONENTS
 libs:: $(EXTRA_PP_COMPONENTS)
 ifndef NO_DIST_INSTALL
 	$(EXIT_ON_ERROR) \
 	$(NSINSTALL) -D $(FINAL_TARGET)/components; \
 	for i in $^; do \
-	  dest=$(FINAL_TARGET)/components/`basename $$i`; \
+	  fname=`basename $$i`; \
+	  dest=$(FINAL_TARGET)/components/$${fname}; \
 	  $(RM) -f $$dest; \
 	  $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \
+	  $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_TARGET)/components/components.list $$fname; \
 	done
 endif
 
 endif
 
 ################################################################################
 # Copy each element of EXTRA_JS_MODULES to $(FINAL_TARGET)/modules
 ifdef EXTRA_JS_MODULES
--- a/configure.in
+++ b/configure.in
@@ -128,17 +128,17 @@ WINDRES_VERSION=2.14.90
 W32API_VERSION=3.8
 GNOMEVFS_VERSION=2.0
 GNOMEUI_VERSION=2.2.0
 GCONF_VERSION=1.2.1
 LIBGNOME_VERSION=2.0
 GIO_VERSION=2.0
 STARTUP_NOTIFICATION_VERSION=0.8
 DBUS_VERSION=0.60
-SQLITE_VERSION=3.6.16
+SQLITE_VERSION=3.6.20
 LIBNOTIFY_VERSION=0.4
 
 MSMANIFEST_TOOL=
 
 dnl Set various checks
 dnl ========================================================
 MISSING_X=
 AC_PROG_AWK
@@ -4151,17 +4151,25 @@ AC_CACHE_CHECK(for trouble comparing to 
                                 template <class T> int operator!=(const T2*, const T&) { return 0; }],
                                [Foo<int> f; return (0 != f);],
                                ac_cv_trouble_comparing_to_zero=no,
                                ac_cv_trouble_comparing_to_zero=yes)])
 if test "$ac_cv_trouble_comparing_to_zero" = yes ; then
   AC_DEFINE(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
 fi
 
-
+AC_CACHE_CHECK(for __thread keyword for TLS variables,
+               ac_cv_thread_keyword,
+               [AC_TRY_LINK([__thread bool tlsIsMainThread = false;],
+                            [return tlsIsMainThread;],
+                            ac_cv_thread_keyword=yes,
+                            ac_cv_thread_keyword=no)])
+if test "$ac_cv_thread_keyword" = yes; then
+  AC_DEFINE(HAVE_THREAD_TLS_KEYWORD)
+fi
 
 dnl End of C++ language/feature checks
 AC_LANG_C
 
 dnl ========================================================
 dnl =  Internationalization checks
 dnl ========================================================
 dnl
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -65,16 +65,17 @@ struct nsNativeKeyEvent; // Don't includ
 
 class nsIDOMScriptObjectFactory;
 class nsIXPConnect;
 class nsINode;
 class nsIContent;
 class nsIDOMNode;
 class nsIDOMKeyEvent;
 class nsIDocument;
+class nsIDocumentObserver;
 class nsIDocShell;
 class nsINameSpaceManager;
 class nsIScriptSecurityManager;
 class nsIJSContextStack;
 class nsIThreadJSContextStack;
 class nsIParserService;
 class nsIIOService;
 class nsIURI;
@@ -1669,37 +1670,23 @@ public:
   ~nsAutoScriptBlocker() {
     nsContentUtils::RemoveScriptBlocker();
   }
 };
 
 class mozAutoRemovableBlockerRemover
 {
 public:
-  mozAutoRemovableBlockerRemover()
-  {
-    mNestingLevel = nsContentUtils::GetRemovableScriptBlockerLevel();
-    for (PRUint32 i = 0; i < mNestingLevel; ++i) {
-      nsContentUtils::RemoveRemovableScriptBlocker();
-    }
-
-    NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), "killing mutation events");
-  }
-
-  ~mozAutoRemovableBlockerRemover()
-  {
-    NS_ASSERTION(nsContentUtils::GetRemovableScriptBlockerLevel() == 0,
-                 "Should have had none");
-    for (PRUint32 i = 0; i < mNestingLevel; ++i) {
-      nsContentUtils::AddRemovableScriptBlocker();
-    }
-  }
+  mozAutoRemovableBlockerRemover(nsIDocument* aDocument);
+  ~mozAutoRemovableBlockerRemover();
 
 private:
   PRUint32 mNestingLevel;
+  nsCOMPtr<nsIDocument> mDocument;
+  nsCOMPtr<nsIDocumentObserver> mObserver;
 };
 
 #define NS_AUTO_GCROOT_PASTE2(tok,line) tok##line
 #define NS_AUTO_GCROOT_PASTE(tok,line) \
   NS_AUTO_GCROOT_PASTE2(tok,line)
 #define NS_AUTO_GCROOT(ptr, result) \ \
   nsAutoGCRoot NS_AUTO_GCROOT_PASTE(_autoGCRoot_, __LINE__) \
   (ptr, result)
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -100,18 +100,18 @@ class nsBindingManager;
 class nsIDOMNodeList;
 class mozAutoSubtreeModified;
 struct JSObject;
 class nsFrameLoader;
 class nsIBoxObject;
 
 // IID for the nsIDocument interface
 #define NS_IDOCUMENT_IID      \
-  { 0x2ca82a51, 0x4a6a, 0x4dfa, \
-      { 0xa6, 0x5f, 0x49, 0x52, 0xa3, 0xaa, 0x02, 0xef } }
+{ 0xd16d73c1, 0xe0f7, 0x415c, \
+ { 0xbd, 0x68, 0x9c, 0x1f, 0x93, 0xb8, 0x73, 0x7a } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 //----------------------------------------------------------------------
 
 // Document interface.  This is implemented by all document objects in
 // Gecko.
@@ -1202,16 +1202,18 @@ public:
    * according to the element's href.
    *
    * If the given node is the same as the current first base node, this
    * function still updates the document's base URI according to the node's
    * href, if it changed.
    */
   virtual nsresult SetFirstBaseNodeWithHref(nsIContent *node) = 0;
 
+  virtual nsISupports* GetCurrentContentSink() = 0;
+
 protected:
   ~nsIDocument()
   {
     // XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and
     //     releasing it) happens in the nsDocument destructor. We'd prefer to
     //     do it here but nsNodeInfoManager is a concrete class that we don't
     //     want to expose to users of the nsIDocument API outside of Gecko.
   }
--- a/content/base/public/nsXMLNameSpaceMap.h
+++ b/content/base/public/nsXMLNameSpaceMap.h
@@ -56,20 +56,20 @@ struct nsNameSpaceEntry
 /**
  * nsXMLNameSpaceMap contains a set of prefixes which are mapped onto
  * namespaces.  It allows the set to be searched by prefix or by namespace ID.
  */
 class nsXMLNameSpaceMap
 {
 public:
   /**
-   * Allocates a new nsXMLNameSpaceMap (with new()) and initializes it with the
-   * xmlns and xml namespaces.
+   * Allocates a new nsXMLNameSpaceMap (with new()) and if aForXML is
+   * true initializes it with the xmlns and xml namespaces.
    */
-  static NS_HIDDEN_(nsXMLNameSpaceMap*) Create();
+  static NS_HIDDEN_(nsXMLNameSpaceMap*) Create(PRBool aForXML);
 
   /**
    * Add a prefix and its corresponding namespace ID to the map.
    * Passing a null |aPrefix| corresponds to the default namespace, which may
    * be set to something other than kNameSpaceID_None.
    */
   NS_HIDDEN_(nsresult) AddPrefix(nsIAtom *aPrefix, PRInt32 aNameSpaceID);
 
new file mode 100644
--- /dev/null
+++ b/content/base/src/Link.cpp
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "Link.h"
+
+namespace mozilla {
+namespace dom {
+
+Link::Link()
+  : mLinkState(defaultState)
+{
+}
+
+nsLinkState
+Link::GetLinkState() const
+{
+  return mLinkState;
+}
+
+void
+Link::SetLinkState(nsLinkState aState)
+{
+  mLinkState = aState;
+}
+
+void
+Link::ResetLinkState()
+{
+  nsCOMPtr<nsIContent> content(do_QueryInterface(this));
+  NS_ASSERTION(content, "Why isn't this an nsIContent node?!");
+
+  nsIDocument *doc = content->GetCurrentDoc();
+  if (doc) {
+    doc->ForgetLink(content);
+  }
+  mLinkState = defaultState;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/base/src/Link.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * This is the base class for all link classes.
+ */
+
+#ifndef mozilla_dom_Link_h__
+#define mozilla_dom_Link_h__
+
+#include "nsIContent.h"
+
+namespace mozilla {
+namespace dom {
+
+class Link : public nsISupports
+{
+public:
+  static const nsLinkState defaultState = eLinkState_Unknown;
+  Link();
+  virtual nsLinkState GetLinkState() const;
+  virtual void SetLinkState(nsLinkState aState);
+
+protected:
+  /**
+   * Invalidates any link caching, and resets the state to the default.
+   */
+  virtual void ResetLinkState();
+
+  nsLinkState mLinkState;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_Link_h__
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -127,16 +127,17 @@ CPPSRCS		= \
 		nsTextFragment.cpp \
 		nsTextNode.cpp \
 		nsTraversal.cpp \
 		nsTreeWalker.cpp \
 		nsXHTMLContentSerializer.cpp \
 		nsXMLContentSerializer.cpp \
 		nsXMLHttpRequest.cpp \
 		nsXMLNameSpaceMap.cpp \
+		Link.cpp \
 		$(NULL)
 
 GQI_SRCS = contentbase.gqi
 
 # we don't want the shared lib, but we want to force the creation of a
 # static lib.
 FORCE_STATIC_LIB = 1
 
--- a/content/base/src/nsContentAreaDragDrop.cpp
+++ b/content/base/src/nsContentAreaDragDrop.cpp
@@ -324,16 +324,17 @@ nsContentAreaDragDrop::DragOver(nsIDOMDr
         if (sourceRoot && sourceRoot == eventRoot) {
           dropAllowed = PR_FALSE;
         }
       }
     }
   }
 
   session->SetCanDrop(dropAllowed);
+
   return NS_OK;
 }
 
 
 //
 // ExtractURLFromData
 //
 // build up a url from whatever data we get from the OS. How we
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -1582,17 +1582,17 @@ nsContentSink::FavorPerformanceHint(PRBo
   if (appShell)
     appShell->FavorPerformanceHint(perfOverStarvation, starvationDelay);
 }
 
 void
 nsContentSink::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
 {
   // Remember nested updates from updates that we started.
-  if (mInNotification && mUpdatesInNotification < 2) {
+  if (mInNotification > 0 && mUpdatesInNotification < 2) {
     ++mUpdatesInNotification;
   }
 
   // If we're in a script and we didn't do the notification,
   // something else in the script processing caused the
   // notification to occur. Since this could result in frame
   // creation, make sure we've flushed everything before we
   // continue.
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -5168,8 +5168,36 @@ nsContentUtils::WrapNative(JSContext *cx
                                      vp, aHolder);
 
   if (push) {
     sThreadJSContextStack->Pop(nsnull);
   }
 
   return rv;
 }
+
+mozAutoRemovableBlockerRemover::mozAutoRemovableBlockerRemover(nsIDocument* aDocument)
+{
+  mNestingLevel = nsContentUtils::GetRemovableScriptBlockerLevel();
+  mDocument = aDocument;
+  nsISupports* sink = aDocument ? aDocument->GetCurrentContentSink() : nsnull;
+  mObserver = do_QueryInterface(sink);
+  for (PRUint32 i = 0; i < mNestingLevel; ++i) {
+    if (mObserver) {
+      mObserver->EndUpdate(mDocument, UPDATE_CONTENT_MODEL);
+    }
+    nsContentUtils::RemoveRemovableScriptBlocker();
+  }
+
+  NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), "killing mutation events");
+}
+
+mozAutoRemovableBlockerRemover::~mozAutoRemovableBlockerRemover()
+{
+  NS_ASSERTION(nsContentUtils::GetRemovableScriptBlockerLevel() == 0,
+               "Should have had none");
+  for (PRUint32 i = 0; i < mNestingLevel; ++i) {
+    nsContentUtils::AddRemovableScriptBlocker();
+    if (mObserver) {
+      mObserver->BeginUpdate(mDocument, UPDATE_CONTENT_MODEL);
+    }
+  }
+}
--- a/content/base/src/nsDOMAttribute.cpp
+++ b/content/base/src/nsDOMAttribute.cpp
@@ -718,17 +718,17 @@ nsDOMAttribute::RemoveChildAt(PRUint32 a
   mozAutoDocUpdate updateBatch(GetOwnerDoc(), UPDATE_CONTENT_MODEL, aNotify);
   nsMutationGuard guard;
 
   mozAutoSubtreeModified subtree(nsnull, nsnull);
   if (aNotify &&
       nsContentUtils::HasMutationListeners(mChild,
                                            NS_EVENT_BITS_MUTATION_NODEREMOVED,
                                            this)) {
-    mozAutoRemovableBlockerRemover blockerRemover;
+    mozAutoRemovableBlockerRemover blockerRemover(GetOwnerDoc());
     nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEREMOVED);
     mutation.mRelatedNode =
       do_QueryInterface(static_cast<nsIAttribute*>(this));
     subtree.UpdateTarget(GetOwnerDoc(), this);
     nsEventDispatcher::Dispatch(mChild, nsnull, &mutation);
   }
   if (guard.Mutated(0) && mChild != child) {
     return NS_OK;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -164,17 +164,19 @@ static NS_DEFINE_CID(kDOMEventGroupCID, 
 #include "nsIContentViewer.h"
 #include "nsIXMLContentSink.h"
 #include "nsContentErrors.h"
 #include "nsIXULDocument.h"
 #include "nsIPrompt.h"
 #include "nsIPropertyBag2.h"
 #include "nsIDOMPageTransitionEvent.h"
 #include "nsFrameLoader.h"
+#ifdef MOZ_MEDIA
 #include "nsHTMLMediaElement.h"
+#endif // MOZ_MEDIA
 
 #include "mozAutoDocUpdate.h"
 
 #ifdef MOZ_SMIL
 #include "nsSMILAnimationController.h"
 #include "imgIContainer.h"
 #include "nsSVGUtils.h"
 #endif // MOZ_SMIL
@@ -7319,17 +7321,17 @@ nsDocument::MutationEventDispatched(nsIN
         realTargets.AppendObject(possibleTarget);
       }
     }
 
     mSubtreeModifiedTargets.Clear();
 
     PRInt32 realTargetCount = realTargets.Count();
     for (PRInt32 k = 0; k < realTargetCount; ++k) {
-      mozAutoRemovableBlockerRemover blockerRemover;
+      mozAutoRemovableBlockerRemover blockerRemover(this);
 
       nsMutationEvent mutation(PR_TRUE, NS_MUTATION_SUBTREEMODIFIED);
       nsEventDispatcher::Dispatch(realTargets[k], nsnull, &mutation);
     }
   }
 }
 
 static PRUint32 GetURIHash(nsIURI* aURI)
@@ -7763,16 +7765,22 @@ nsDocument::UnsuppressEventHandlingAndFi
 
   if (aFireEvents) {
     NS_DispatchToCurrentThread(new nsDelayedEventDispatcher(documents));
   } else {
     FireOrClearDelayedEvents(documents, PR_FALSE);
   }
 }
 
+nsISupports*
+nsDocument::GetCurrentContentSink()
+{
+  return mParser ? mParser->GetContentSink() : nsnull;
+}
+
 void
 nsIDocument::RegisterFreezableElement(nsIContent* aContent)
 {
   if (!mFreezableElements) {
     mFreezableElements = new nsTHashtable<nsPtrHashKey<nsIContent> >();
     if (!mFreezableElements)
       return;
     mFreezableElements->Init();
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1006,16 +1006,19 @@ public:
 
   nsresult CloneDocHelper(nsDocument* clone) const;
 
   void MaybeInitializeFinalizeFrameLoaders();
 
   void MaybeEndOutermostXBLUpdate();
 
   virtual void MaybePreLoadImage(nsIURI* uri);
+
+  virtual nsISupports* GetCurrentContentSink();
+
 protected:
   friend class nsNodeUtils;
   void RegisterNamedItems(nsIContent *aContent);
   void UnregisterNamedItems(nsIContent *aContent);
   void UpdateNameTableEntry(nsIContent *aContent);
   void UpdateIdTableEntry(nsIContent *aContent);
   void RemoveFromNameTable(nsIContent *aContent);
   void RemoveFromIdTable(nsIContent *aContent);
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -1394,34 +1394,41 @@ nsHTMLCopyEncoder::PromoteAncestorChain(
 {
   if (!ioNode || !ioStartOffset || !ioEndOffset) return NS_ERROR_NULL_POINTER;
 
   nsresult rv = NS_OK;
   PRBool done = PR_FALSE;
 
   nsCOMPtr<nsIDOMNode> frontNode, endNode, parent;
   PRInt32 frontOffset, endOffset;
+
+  //save the editable state of the ioNode, so we don't promote an ancestor if it has different editable state
+  nsCOMPtr<nsINode> node = do_QueryInterface(*ioNode);
+  PRBool isEditable = node->IsEditable();
   
   // loop for as long as we can promote both endpoints
   while (!done)
   {
     rv = (*ioNode)->GetParentNode(getter_AddRefs(parent));
     if ((NS_FAILED(rv)) || !parent)
       done = PR_TRUE;
     else
     {
       // passing parent as last param to GetPromotedPoint() allows it to promote only one level
       // up the hierarchy.
       rv = GetPromotedPoint( kStart, *ioNode, *ioStartOffset, address_of(frontNode), &frontOffset, parent);
       NS_ENSURE_SUCCESS(rv, rv);
       // then we make the same attempt with the endpoint
       rv = GetPromotedPoint( kEnd, *ioNode, *ioEndOffset, address_of(endNode), &endOffset, parent);
       NS_ENSURE_SUCCESS(rv, rv);
-      // if both endpoints were promoted one level, keep looping - otherwise we are done.
-      if ( (frontNode != parent) || (endNode != parent) )
+
+      nsCOMPtr<nsINode> frontINode = do_QueryInterface(frontNode);
+      // if both endpoints were promoted one level and isEditable is the same as the original node, 
+      // keep looping - otherwise we are done.
+      if ( (frontNode != parent) || (endNode != parent) || (frontINode->IsEditable() != isEditable) )
         done = PR_TRUE;
       else
       {
         *ioNode = frontNode;  
         *ioStartOffset = frontOffset;
         *ioEndOffset = endOffset;
       }
     }
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -436,17 +436,17 @@ nsGenericDOMDataNode::SetTextInternal(PR
       aOffset == textLength,
       aOffset,
       endOffset,
       aLength
     };
     nsNodeUtils::CharacterDataChanged(this, &info);
 
     if (haveMutationListeners) {
-      mozAutoRemovableBlockerRemover blockerRemover;
+      mozAutoRemovableBlockerRemover blockerRemover(GetOwnerDoc());
 
       nsMutationEvent mutation(PR_TRUE, NS_MUTATION_CHARACTERDATAMODIFIED);
 
       mutation.mPrevAttrValue = oldValue;
       if (aLength > 0) {
         nsAutoString val;
         mText.AppendTo(val);
         mutation.mNewAttrValue = do_GetAtom(val);
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -3295,17 +3295,17 @@ nsGenericElement::doInsertChildAt(nsICon
     if (aParent && isAppend) {
       nsNodeUtils::ContentAppended(aParent, aIndex);
     } else {
       nsNodeUtils::ContentInserted(container, aKid, aIndex);
     }
 
     if (nsContentUtils::HasMutationListeners(aKid,
           NS_EVENT_BITS_MUTATION_NODEINSERTED, container)) {
-      mozAutoRemovableBlockerRemover blockerRemover;
+      mozAutoRemovableBlockerRemover blockerRemover(container->GetOwnerDoc());
       
       nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEINSERTED);
       mutation.mRelatedNode = do_QueryInterface(container);
 
       mozAutoSubtreeModified subtree(container->GetOwnerDoc(), container);
       nsEventDispatcher::Dispatch(aKid, nsnull, &mutation);
     }
   }
@@ -3367,17 +3367,17 @@ nsGenericElement::doRemoveChildAt(PRUint
 
   nsMutationGuard guard;
 
   mozAutoSubtreeModified subtree(nsnull, nsnull);
   if (aNotify &&
       aMutationEvent &&
       nsContentUtils::HasMutationListeners(aKid,
         NS_EVENT_BITS_MUTATION_NODEREMOVED, container)) {
-    mozAutoRemovableBlockerRemover blockerRemover;
+    mozAutoRemovableBlockerRemover blockerRemover(container->GetOwnerDoc());
 
     nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEREMOVED);
     mutation.mRelatedNode = do_QueryInterface(container);
 
     subtree.UpdateTarget(container->GetOwnerDoc(), container);
     nsEventDispatcher::Dispatch(aKid, nsnull, &mutation);
   }
 
@@ -3933,17 +3933,17 @@ nsGenericElement::doReplaceOrInsertBefor
     if (doc && (window = doc->GetInnerWindow()) &&
         window->HasMutationListeners(NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
 
       for (i = 0; i < count; ++i, ++insPos) {
         nsIContent* childContent = fragChildren[i];
 
         if (nsContentUtils::HasMutationListeners(childContent,
               NS_EVENT_BITS_MUTATION_NODEINSERTED, container)) {
-          mozAutoRemovableBlockerRemover blockerRemover;
+          mozAutoRemovableBlockerRemover blockerRemover(container->GetOwnerDoc());
 
           nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEINSERTED);
           mutation.mRelatedNode = do_QueryInterface(container);
 
           mozAutoSubtreeModified subtree(container->GetOwnerDoc(), container);
           nsEventDispatcher::Dispatch(childContent, nsnull, &mutation);
         }
       }
@@ -4443,17 +4443,17 @@ nsGenericElement::SetAttrAndNotify(PRInt
     mNodeInfo->GetDocument()->AddXMLEventsContent(this);
   }
   if (aValueForAfterSetAttr) {
     rv = AfterSetAttr(aNamespaceID, aName, aValueForAfterSetAttr, aNotify);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (aFireMutation) {
-    mozAutoRemovableBlockerRemover blockerRemover;
+    mozAutoRemovableBlockerRemover blockerRemover(GetOwnerDoc());
     
     nsMutationEvent mutation(PR_TRUE, NS_MUTATION_ATTRMODIFIED);
 
     nsAutoString attrName;
     aName->ToString(attrName);
     nsCOMPtr<nsIDOMAttr> attrNode;
     nsAutoString ns;
     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
@@ -4699,17 +4699,17 @@ nsGenericElement::UnsetAttr(PRInt32 aNam
                                   nsIDOMMutationEvent::REMOVAL,
                                   stateMask);
   }
 
   rv = AfterSetAttr(aNameSpaceID, aName, nsnull, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (hasMutationListeners) {
-    mozAutoRemovableBlockerRemover blockerRemover;
+    mozAutoRemovableBlockerRemover blockerRemover(GetOwnerDoc());
 
     nsCOMPtr<nsIDOMEventTarget> node =
       do_QueryInterface(static_cast<nsIContent *>(this));
     nsMutationEvent mutation(PR_TRUE, NS_MUTATION_ATTRMODIFIED);
 
     mutation.mRelatedNode = attrNode;
     mutation.mAttrName = aName;
 
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -51,17 +51,19 @@
 #include "nsCOMArray.h"
 #include "nsPIDOMWindow.h"
 #include "nsDocument.h"
 #ifdef MOZ_XUL
 #include "nsXULElement.h"
 #endif
 #include "nsBindingManager.h"
 #include "nsGenericHTMLElement.h"
+#ifdef MOZ_MEDIA
 #include "nsHTMLMediaElement.h"
+#endif // MOZ_MEDIA
 
 // This macro expects the ownerDocument of content_ to be in scope as
 // |nsIDocument* doc|
 #define IMPL_MUTATION_NOTIFICATION(func_, content_, params_)      \
   PR_BEGIN_MACRO                                                  \
   nsINode* node = content_;                                       \
   NS_ASSERTION(node->GetOwnerDoc() == doc, "Bogus document");     \
   if (doc) {                                                      \
--- a/content/base/src/nsXMLNameSpaceMap.cpp
+++ b/content/base/src/nsXMLNameSpaceMap.cpp
@@ -58,28 +58,30 @@ class nsDefaultComparator <nsNameSpaceEn
   public:
     PRBool Equals(const nsNameSpaceEntry& aEntry, const PRInt32& aNameSpace) const {
       return aEntry.nameSpaceID == aNameSpace;
     }
 };
 
 
 /* static */ nsXMLNameSpaceMap*
-nsXMLNameSpaceMap::Create()
+nsXMLNameSpaceMap::Create(PRBool aForXML)
 {
   nsXMLNameSpaceMap *map = new nsXMLNameSpaceMap();
   NS_ENSURE_TRUE(map, nsnull);
 
-  nsresult rv = map->AddPrefix(nsGkAtoms::xmlns,
-                               kNameSpaceID_XMLNS);
-  rv |= map->AddPrefix(nsGkAtoms::xml, kNameSpaceID_XML);
+  if (aForXML) {
+    nsresult rv = map->AddPrefix(nsGkAtoms::xmlns,
+                                 kNameSpaceID_XMLNS);
+    rv |= map->AddPrefix(nsGkAtoms::xml, kNameSpaceID_XML);
 
-  if (NS_FAILED(rv)) {
-    delete map;
-    map = nsnull;
+    if (NS_FAILED(rv)) {
+      delete map;
+      map = nsnull;
+    }
   }
 
   return map;
 }
 
 nsXMLNameSpaceMap::nsXMLNameSpaceMap()
   : mNameSpaces(4)
 {
--- a/content/base/test/test_htmlcopyencoder.html
+++ b/content/base/test/test_htmlcopyencoder.html
@@ -152,16 +152,25 @@ function testHtmlCopyEncoder () {
 
   select.selectAllChildren(node);
   encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
   encoder.setSelection(select);
   out = encoder.encodeToString();
   expected = '<ol id=\"aList\">\n   <li value=\"8\">Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
   is(out, expected, "test list selection with a value on a LI");
 
+  //test Bug 436703
+  node = document.getElementById('aContentEditable');
+  select.selectAllChildren(node);
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<p>one</p><p>two</p>';
+  is(out, expected, "select all children in an contentEditable div should not select the div itself");
+
   SimpleTest.finish();
 }
 
 
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(testHtmlCopyEncoder);
 
@@ -178,10 +187,12 @@ addLoadEvent(testHtmlCopyEncoder);
    <li>Lorem ipsum dolor</li>
   <li>sit amet, <strong>consectetuer</strong> </li>
   <li>adipiscing elit</li>
   <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class</li>
   <li>aptent taciti</li>
 </ol>
 foo bar
 </div>
+
+<div id="aContentEditable" contentEditable="true"><p>one</p><p>two</p></div>
 </body>
 </html>
--- a/content/canvas/public/WebGLArray.h
+++ b/content/canvas/public/WebGLArray.h
@@ -33,16 +33,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef WEBGLARRAY_H_
 #define WEBGLARRAY_H_
 
+nsresult NS_NewCanvasArrayBuffer(nsISupports **aNewObject);
 nsresult NS_NewCanvasFloatArray(nsISupports **aNewObject);
 nsresult NS_NewCanvasByteArray(nsISupports **aNewObject);
 nsresult NS_NewCanvasUnsignedByteArray(nsISupports **aNewObject);
 nsresult NS_NewCanvasShortArray(nsISupports **aNewObject);
 nsresult NS_NewCanvasUnsignedShortArray(nsISupports **aNewObject);
 nsresult NS_NewCanvasIntArray(nsISupports **aNewObject);
 nsresult NS_NewCanvasUnsignedIntArray(nsISupports **aNewObject);
 
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -60,16 +60,17 @@ CPPSRCS += \
 	$(NULL)
 endif
 
 # Canvas 3D Pieces
 
 ifdef MOZ_WEBGL
 
 CPPSRCS += \
+	WebGLArrays.cpp \
 	WebGLContext.cpp \
 	WebGLContextGL.cpp \
 	WebGLContextUtils.cpp \
 	WebGLContextValidate.cpp \
 	NativeJSContext.cpp \
 	glwrap.cpp \
 	nsGLPbuffer.cpp \
 	nsGLPbufferOSMesa.cpp \
--- a/content/canvas/src/SimpleBuffer.h
+++ b/content/canvas/src/SimpleBuffer.h
@@ -80,17 +80,17 @@ public:
         if (type == LOCAL_GL_FLOAT) return sizeof(float);
         if (type == LOCAL_GL_SHORT) return sizeof(short);
         if (type == LOCAL_GL_UNSIGNED_SHORT) return sizeof(unsigned short);
         if (type == LOCAL_GL_BYTE) return 1;
         if (type == LOCAL_GL_UNSIGNED_BYTE) return 1;
         if (type == LOCAL_GL_INT) return sizeof(int);
         if (type == LOCAL_GL_UNSIGNED_INT) return sizeof(unsigned int);
         if (type == LOCAL_GL_DOUBLE) return sizeof(double);
-        return 0;
+        return 1;
     }
 
     void Clear() {
         Release();
     }
 
     void Set(PRUint32 t, PRUint32 spv, PRUint32 count, void* vals) {
         Prepare(t, spv, count);
@@ -113,16 +113,20 @@ public:
     void Release() {
         if (data)
             free(data);
         length = 0;
         capacity = 0;
         data = nsnull;
     }
 
+    void Zero() {
+        memset(data, 0, capacity);
+    }
+
     void EnsureCapacity(PRBool preserve, PRUint32 cap) {
         if (capacity >= cap)
             return;
 
         void* newdata = malloc(cap);
         if (preserve && length)
             memcpy(newdata, data, length*ElementSize());
         free(data);
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/WebGLArrays.cpp
@@ -0,0 +1,1777 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mark Steele <mwsteele@gmail.com>
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "WebGLArrays.h"
+
+#include "NativeJSContext.h"
+
+// TODO:
+// XXX: fix overflow in integer mult in ::Set!
+// XXX: get rid of code duplication, use inline helpers, templates, or macros
+// XXX: Prepare/Zero in initializers is inefficient, we should really
+//      just be doing calloc
+// XXX: array Set() shouldn't call into the inner Set(), because that
+//      repeats the length check and is probably not getting inlined
+// write benchmarks
+
+using namespace mozilla;
+
+nsresult
+NS_NewCanvasArrayBuffer(nsISupports **aResult)
+{
+    nsICanvasArrayBuffer *wgab = new WebGLArrayBuffer();
+    if (!wgab)
+        return NS_ERROR_OUT_OF_MEMORY;
+
+    NS_ADDREF(*aResult = wgab);
+    return NS_OK;
+}
+
+WebGLArrayBuffer::WebGLArrayBuffer(PRUint32 length)
+{
+    EnsureCapacity(PR_FALSE, length);
+}
+
+NS_IMETHODIMP
+WebGLArrayBuffer::Initialize(nsISupports *owner,
+                             JSContext *cx,
+                             JSObject *obj,
+                             PRUint32 argc,
+                             jsval *argv)
+{
+    /* Constructor: WebGLArrayBuffer(n) */
+    if (JSVAL_IS_NUMBER(argv[0])) {
+        uint32 length;
+        ::JS_ValueToECMAUint32(cx, argv[0], &length);
+        if (length == 0)
+            return NS_ERROR_FAILURE;
+
+        EnsureCapacity(PR_FALSE, length);
+
+        return NS_OK;
+    }
+
+    return NS_ERROR_DOM_SYNTAX_ERR;
+}
+
+/* readonly attribute unsigned long byteLength; */
+NS_IMETHODIMP WebGLArrayBuffer::GetByteLength(PRUint32 *aByteLength)
+{
+    *aByteLength = capacity;
+    return NS_OK;
+}
+
+/* [noscript, notxpcom] voidPtr GetNativeArrayBuffer (); */
+NS_IMETHODIMP_(WebGLArrayBuffer *) WebGLArrayBuffer::GetNativeArrayBuffer()
+{
+    return this;
+}
+
+/* [noscript, notxpcom] voidPtr nativePointer (); */
+NS_IMETHODIMP_(void *) WebGLArrayBuffer::NativePointer()
+{
+    return data;
+}
+
+/* [noscript, notxpcom] unsigned long nativeSize (); */
+NS_IMETHODIMP_(PRUint32) WebGLArrayBuffer::NativeSize()
+{
+    return capacity;
+}
+
+/*
+ * CanvasFloatArray
+ */
+
+nsresult
+NS_NewCanvasFloatArray(nsISupports **aResult)
+{
+    nsICanvasFloatArray *wgfa = new WebGLFloatArray();
+    if (!wgfa)
+        return NS_ERROR_OUT_OF_MEMORY;
+
+    NS_ADDREF(*aResult = wgfa);
+    return NS_OK;
+}
+
+WebGLFloatArray::WebGLFloatArray(PRUint32 length)
+    : mOffset(0), mLength(length)
+{
+    mBuffer = new WebGLArrayBuffer(length * sizeof(float));
+}
+
+WebGLFloatArray::WebGLFloatArray(WebGLArrayBuffer *buffer, PRUint32 offset, PRUint32 length)
+    : mBuffer(buffer), mOffset(offset), mLength(length)
+{
+}
+
+WebGLFloatArray::WebGLFloatArray(JSContext *cx, JSObject *arrayObj, jsuint arrayLen)
+    : mOffset(0), mLength(arrayLen)
+{
+    mBuffer = new WebGLArrayBuffer();
+    mBuffer->InitFromJSArray(LOCAL_GL_FLOAT, 1, cx, arrayObj, arrayLen);
+}
+
+NS_IMETHODIMP
+WebGLFloatArray::Initialize(nsISupports *owner,
+                            JSContext *cx,
+                            JSObject *obj,
+                            PRUint32 argc,
+                            jsval *argv)
+{
+    if (JSVAL_IS_NUMBER(argv[0])) {
+        uint32 length;
+        ::JS_ValueToECMAUint32(cx, argv[0], &length);
+        mBuffer = new WebGLArrayBuffer();
+        mBuffer->Prepare(LOCAL_GL_FLOAT, 1, length);
+        mBuffer->Zero();
+        mLength = length;
+    } else {
+        JSObject *arrayObj;
+        jsuint arrayLen;
+        jsuint byteOffset = 0;
+        jsuint length = 0;
+
+        if (!::JS_ConvertArguments(cx, argc, argv, "o/uu", &arrayObj, &byteOffset, &length) ||
+            arrayObj == NULL)
+        {
+            return NS_ERROR_DOM_SYNTAX_ERR;
+        }
+
+        if (::JS_IsArrayObject(cx, arrayObj) &&
+            ::JS_GetArrayLength(cx, arrayObj, &arrayLen))
+        {
+            mBuffer = new WebGLArrayBuffer();
+            mBuffer->InitFromJSArray(LOCAL_GL_FLOAT, 1, cx, arrayObj, arrayLen);
+            mLength = arrayLen;
+        } else {
+            nsCOMPtr<nsICanvasArrayBuffer> canvasObj;
+            nsresult rv;
+            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsICanvasArrayBuffer), getter_AddRefs(canvasObj));
+            if (NS_FAILED(rv) || !canvasObj) {
+                return NS_ERROR_DOM_SYNTAX_ERR;
+            }
+
+            mBuffer = canvasObj->GetNativeArrayBuffer();
+
+            if (byteOffset % sizeof(float))
+                return NS_ERROR_FAILURE;
+
+            if ((byteOffset + (length * sizeof(float))) > mBuffer->capacity)
+                return NS_ERROR_FAILURE;
+
+            if (length > 0) {
+                mLength = length;
+            } else {
+                if ((mBuffer->capacity - byteOffset) % sizeof(float))
+                    return NS_ERROR_FAILURE;
+
+                mLength = (mBuffer->capacity - byteOffset) / sizeof(float);
+            }
+        }
+    }
+
+    return NS_OK;
+}
+
+/* readonly attribute nsICanvasArrayBuffer buffer; */
+NS_IMETHODIMP WebGLFloatArray::GetBuffer(nsICanvasArrayBuffer **aBuffer)
+{
+    NS_ADDREF(*aBuffer = mBuffer);
+    return NS_OK;
+}
+
+/* readonly attribute unsigned long byteOffset; */
+NS_IMETHODIMP WebGLFloatArray::GetByteOffset(PRUint32 *aByteOffset)
+{
+    *aByteOffset = mOffset;
+    return NS_OK;
+}
+
+/* readonly attribute unsigned long byteLength; */
+NS_IMETHODIMP WebGLFloatArray::GetByteLength(PRUint32 *aByteLength)
+{
+    *aByteLength = mLength * sizeof(float);
+    return NS_OK;
+}
+
+/* attribute unsigned long length; */
+NS_IMETHODIMP WebGLFloatArray::GetLength(PRUint32 *aLength)
+{
+    *aLength = mLength;
+    return NS_OK;
+}
+
+/* unsigned long alignedSizeInBytes (); */
+NS_IMETHODIMP WebGLFloatArray::AlignedSizeInBytes(PRUint32 *retval)
+{
+    *retval = mBuffer->capacity;