Merge mozilla-central and mozilla-inbound
authorMatt Brubeck <mbrubeck@mozilla.com>
Thu, 01 Dec 2011 11:17:54 -0800
changeset 81889 c120734d20ba448629dd4fc97e8441c33bcd1e01
parent 81867 b4782acec285875d8ad6dad5868b843eee713ab6 (current diff)
parent 81888 1b3f17ffa656540baebc5cac1e5df43e0303d587 (diff)
child 81890 2050e4dfe6e30286ba36223c9fca2e5b12f24451
child 82149 3dca8a1ee5febc58c7297986b6f1d219fc5a3321
child 83771 3f71aa2136934e28898b7b6f4fe366ac391c0b72
child 108967 c1b222852377b86e59026f904681e11b08101f95
push idunknown
push userunknown
push dateunknown
milestone11.0a1
Merge mozilla-central and mozilla-inbound
tools/profiler/sps/platform.cc
--- a/accessible/src/base/TextUpdater.cpp
+++ b/accessible/src/base/TextUpdater.cpp
@@ -117,23 +117,17 @@ TextUpdater::DoUpdate(const nsAString& a
 
     if (strLen2 > 0) {
       // Fire text change event for insertion.
       nsRefPtr<AccEvent> textInsertEvent =
         new AccTextChangeEvent(mHyperText, mTextOffset, str2, true);
       mDocument->FireDelayedAccessibleEvent(textInsertEvent);
     }
 
-    // Fire value change event.
-    if (mHyperText->Role() == nsIAccessibleRole::ROLE_ENTRY) {
-      nsRefPtr<AccEvent> valueChangeEvent =
-        new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, mHyperText,
-                     eAutoDetect, AccEvent::eRemoveDupes);
-      mDocument->FireDelayedAccessibleEvent(valueChangeEvent);
-    }
+    mDocument->MaybeNotifyOfValueChange(mHyperText);
 
     // Update the text.
     mTextLeaf->SetText(aNewText);
     return;
   }
 
   // Otherwise find the difference between strings and fire events.
   // Note: we can skip initial and final coinciding characters since they don't
@@ -168,22 +162,17 @@ TextUpdater::DoUpdate(const nsAString& a
   ComputeTextChangeEvents(str1, str2, entries, events);
 
   delete [] entries;
 
   // Fire events.
   for (PRInt32 idx = events.Length() - 1; idx >= 0; idx--)
     mDocument->FireDelayedAccessibleEvent(events[idx]);
 
-  if (mHyperText->Role() == nsIAccessibleRole::ROLE_ENTRY) {
-    nsRefPtr<AccEvent> valueChangeEvent =
-      new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, mHyperText,
-                   eAutoDetect, AccEvent::eRemoveDupes);
-    mDocument->FireDelayedAccessibleEvent(valueChangeEvent);
-  }
+  mDocument->MaybeNotifyOfValueChange(mHyperText);
 
   // Update the text.
   mTextLeaf->SetText(aNewText);
 }
 
 void
 TextUpdater::ComputeTextChangeEvents(const nsAString& aStr1,
                                      const nsAString& aStr2,
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1846,21 +1846,17 @@ nsDocAccessible::UpdateTree(nsAccessible
       // Don't climb above this document.
       if (ancestor == this)
         break;
 
       ancestor = ancestor->Parent();
     }
   }
 
-  // Fire value change event.
-  if (aContainer->Role() == nsIAccessibleRole::ROLE_ENTRY) {
-    FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
-                               aContainer->GetNode());
-  }
+  MaybeNotifyOfValueChange(aContainer);
 
   // Fire reorder event so the MSAA clients know the children have changed. Also
   // the event is used internally by MSAA layer.
   nsRefPtr<AccEvent> reorderEvent =
     new AccEvent(nsIAccessibleEvent::EVENT_REORDER, aContainer->GetNode(),
                  eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
   if (reorderEvent)
     FireDelayedAccessibleEvent(reorderEvent);
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -200,16 +200,31 @@ public:
   /**
    * Fire accessible event after timeout.
    *
    * @param aEvent  [in] the event to fire
    */
   nsresult FireDelayedAccessibleEvent(AccEvent* aEvent);
 
   /**
+   * Fire value change event on the given accessible if applicable.
+   */
+  inline void MaybeNotifyOfValueChange(nsAccessible* aAccessible)
+  {
+    PRUint32 role = aAccessible->Role();
+    if (role == nsIAccessibleRole::ROLE_ENTRY ||
+        role == nsIAccessibleRole::ROLE_COMBOBOX) {
+      nsRefPtr<AccEvent> valueChangeEvent =
+        new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible,
+                     eAutoDetect, AccEvent::eRemoveDupes);
+      FireDelayedAccessibleEvent(valueChangeEvent);
+    }
+  }
+
+  /**
    * Get/set the anchor jump.
    */
   inline nsAccessible* AnchorJump()
     { return GetAccessibleOrContainer(mAnchorJumpElm); }
 
   inline void SetAnchorJump(nsIContent* aTargetNode)
     { mAnchorJumpElm = aTargetNode; }
 
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -307,32 +307,35 @@ STDMETHODIMP nsAccessibleWrap::get_accNa
 
 
 STDMETHODIMP nsAccessibleWrap::get_accValue(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszValue)
 {
 __try {
   *pszValue = NULL;
-  nsAccessible *xpAccessible = GetXPAccessibleFor(varChild);
-  if (xpAccessible) {
-    nsAutoString value;
-    if (NS_FAILED(xpAccessible->GetValue(value)))
-      return E_FAIL;
+
+  nsAccessible* xpAccessible = GetXPAccessibleFor(varChild);
+  if (!xpAccessible || xpAccessible->IsDefunct())
+    return E_FAIL;
+
+  nsAutoString value;
+  if (NS_FAILED(xpAccessible->GetValue(value)))
+    return E_FAIL;
 
-    // see bug 438784: Need to expose URL on doc's value attribute.
-    // For this, reverting part of fix for bug 425693 to make this MSAA method 
-    // behave IAccessible2-style.
-    if (value.IsEmpty())
-      return S_FALSE;
+  // See bug 438784: need to expose URL on doc's value attribute. For this,
+  // reverting part of fix for bug 425693 to make this MSAA method behave
+  // IAccessible2-style.
+  if (value.IsEmpty())
+    return S_FALSE;
 
-    *pszValue = ::SysAllocStringLen(value.get(), value.Length());
-    if (!*pszValue)
-      return E_OUTOFMEMORY;
-  }
+  *pszValue = ::SysAllocStringLen(value.get(), value.Length());
+  if (!*pszValue)
+    return E_OUTOFMEMORY;
+
 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return S_OK;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::get_accDescription(VARIANT varChild,
                                      BSTR __RPC_FAR *pszDescription)
 {
--- a/accessible/tests/mochitest/events/test_valuechange.html
+++ b/accessible/tests/mochitest/events/test_valuechange.html
@@ -53,32 +53,55 @@
             "Wrong value of " + prettyName(aNodeOrID));
       }
 
       this.getID = function changeValue_getID() {
         return prettyName(aNodeOrID) + " value changed";
       }
     }
 
+    function changeInputValue(aID, aValue)
+    {
+      this.DOMNode = getNode(aID);
+
+      this.invoke = function changeInputValue_invoke()
+      {
+        this.DOMNode.value = aValue;
+      }
+
+      this.check = function changeInputValue_check()
+      {
+        var acc = getAccessible(this.DOMNode);
+        is(acc.value, aValue, "Wrong value for " + prettyName(aID));
+      }
+
+      this.getID = function changeInputValue_getID()
+      {
+        return prettyName(aID) + " value changed";
+      }
+    }
+
     function doTests()
     {
       // Test initial values
       testValue("slider_vn", "5", 5, 0, 1000, 0);
       testValue("slider_vnvt", "plain", 0, 0, 5, 0);
       testValue("slider_vt", "hi", 0, 0, 3, 0);
       testValue("scrollbar", "5", 5, 0, 1000, 0);
 
       // Test value change events
       gQueue = new eventQueue(nsIAccessibleEvent.EVENT_VALUE_CHANGE);
 
       gQueue.push(new changeValue("slider_vn", "6", undefined));
       gQueue.push(new changeValue("slider_vt", undefined, "hey!"));
       gQueue.push(new changeValue("slider_vnvt", "3", "sweet"));
       gQueue.push(new changeValue("scrollbar", "6", undefined));
 
+      gQueue.push(new changeInputValue("combobox", "hello"));
+
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
 
@@ -89,16 +112,21 @@
      title=" Fire delayed value changed event for aria-valuetext changes">
     Mozilla Bug 478032
   </a>
   <a target="_blank"
     href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289"
     title="We dont expose new aria role 'scrollbar' and property aria-orientation">
    Mozilla Bug 529289
   </a>
+  <a target="_blank"
+    href="https://bugzilla.mozilla.org/show_bug.cgi?id=703202"
+    title="ARIA comboboxes don't fire value change events">
+   Mozilla Bug 703202
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
   <!-- ARIA sliders -->
@@ -109,10 +137,13 @@
        aria-valuemin="0" aria-valuemax="3">greeting slider</div>
 
   <div id="slider_vnvt" role="slider" aria-valuenow="0" aria-valuetext="plain"
        aria-valuemin="0" aria-valuemax="5">sweetness slider</div>
 
   <!-- ARIA scrollbar -->
   <div id="scrollbar" role="scrollbar" aria-valuenow="5"
        aria-valuemin="0" aria-valuemax="1000">slider</div>
+
+  <!-- ARIA combobox -->
+  <input id="combobox" role="combobox" aria-autocomplete="inline">
 </body>
 </html>
--- a/build/macosx/universal/mozconfig.common
+++ b/build/macosx/universal/mozconfig.common
@@ -34,48 +34,43 @@
 #
 # ***** END LICENSE BLOCK *****
 
 mk_add_options MOZ_UNIFY_BDATE=1
 
 mk_add_options MOZ_POSTFLIGHT_ALL+=build/macosx/universal/flight.mk
 
 # Note, the version (10) is used by libffi's configure.
-ac_add_app_options ppc  --target=powerpc-apple-darwin10
 ac_add_app_options i386 --target=i386-apple-darwin10
 ac_add_app_options x86_64 --target=x86_64-apple-darwin10
 
-ac_add_app_options ppc --with-macos-sdk=/Developer/SDKs/MacOSX10.5.sdk
 ac_add_app_options i386 --with-macos-sdk=/Developer/SDKs/MacOSX10.5.sdk
 ac_add_app_options x86_64 --with-macos-sdk=/Developer/SDKs/MacOSX10.6.sdk
 
 # $MOZ_BUILD_APP is only defined when sourced by configure.  That's not a
 # problem, because the variables it affects only need to be set for
 # configure.
 if test -n "$MOZ_BUILD_APP" ; then
-if test "$MOZ_BUILD_APP" = "i386" -o  "$MOZ_BUILD_APP" = "ppc" -o "$MOZ_BUILD_APP" = "x86_64"; then
+if test "$MOZ_BUILD_APP" = "i386" -o "$MOZ_BUILD_APP" = "x86_64"; then
   TARGET_CPU=$MOZ_BUILD_APP
 
   if test -z "$CC" ; then
      CC=gcc-4.2
   fi
 
   if test -z "$CXX" ; then
      CXX=g++-4.2
   fi
 
   # $HOST_CXX is presently unused.  $HOST_CC will only be used during a cross
   # compile.
   HOST_CC=$CC
   HOST_CXX=$CXX
 
   NATIVE_CPU=`$topsrcdir/build/autoconf/config.guess | cut -f1 -d-`
-  if test "$NATIVE_CPU" = "powerpc" ; then
-    NATIVE_CPU=ppc
-  fi
 
   # It's not strictly necessary to specify -arch during native builds, but it
   # makes the merged about:buildconfig easier to follow, and it reduces
   # conditionalized differences between builds.
   CC="$CC -arch $TARGET_CPU"
   CXX="$CXX -arch $TARGET_CPU"
 
   # These must be set for cross builds, and don't hurt straight builds.
--- a/configure.in
+++ b/configure.in
@@ -2666,18 +2666,18 @@ ia64*-hpux*)
             AC_MSG_ERROR([You are targeting i386 but using the 64-bit compiler.])
         fi
 
         if test $_MSC_VER -ge 1400; then
             LDFLAGS="$LDFLAGS -SAFESEH"
         fi
 
         if test -n "$GNU_CC"; then
-            CFLAGS="$CFLAGS -mstackrealign"
-            CXXFLAGS="$CXXFLAGS -mstackrealign"
+            CFLAGS="$CFLAGS -mstackrealign -fno-keep-inline-dllexport"
+            CXXFLAGS="$CXXFLAGS -mstackrealign -fno-keep-inline-dllexport"
         else
             AC_DEFINE(HAVE_STDCALL)
         fi
 
         MOZ_CHECK_HEADERS(mmintrin.h)
     	AC_DEFINE(_X86_)
 	;;
     x86_64-*)
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -1966,16 +1966,20 @@ nsresult nsHTMLMediaElement::InitializeD
 
   return FinishDecoderSetup(decoder);
 }
 
 nsresult nsHTMLMediaElement::FinishDecoderSetup(nsMediaDecoder* aDecoder)
 {
   NS_ASSERTION(mLoadingSrc, "mLoadingSrc set up");
 
+  nsCAutoString src;
+  GetCurrentSpec(src);
+  printf("*** nsHTMLElement::FinishDecoderSetup() mDecoder=%p src=%s\n",
+         aDecoder, src.get());
   mDecoder = aDecoder;
   AddMediaElementToURITable();
 
   // Force a same-origin check before allowing events for this media resource.
   mMediaSecurityVerified = false;
 
   // The new stream has not been suspended by us.
   mPausedForInactiveDocument = false;
--- a/content/media/nsMediaStream.cpp
+++ b/content/media/nsMediaStream.cpp
@@ -746,29 +746,33 @@ public:
 private:
   nsRefPtr<nsMediaDecoder> mDecoder;
   nsresult                 mStatus;
 };
 
 void
 nsMediaChannelStream::CacheClientNotifyDataEnded(nsresult aStatus)
 {
+  printf("*** nsMediaChannelStream::CacheClientNotifyDataEnded() mDecoder=%p\n", mDecoder);
+
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
   // NOTE: this can be called with the media cache lock held, so don't
   // block or do anything which might try to acquire a lock!
 
   nsCOMPtr<nsIRunnable> event = new DataEnded(mDecoder, aStatus);
   NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
 }
 
 nsresult
 nsMediaChannelStream::CacheClientSeek(PRInt64 aOffset, bool aResume)
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
 
+  printf("*** nsMediaChannelStream::CacheClientSeek() mDecoder=%p\n", mDecoder);
+
   CloseChannel();
 
   if (aResume) {
     NS_ASSERTION(mSuspendCount > 0, "Too many resumes!");
     // No need to mess with the channel, since we're making a new one
     --mSuspendCount;
   }
 
@@ -778,25 +782,29 @@ nsMediaChannelStream::CacheClientSeek(PR
 
   mOffset = aOffset;
   return OpenChannel(nsnull);
 }
 
 nsresult
 nsMediaChannelStream::CacheClientSuspend()
 {
+  printf("*** nsMediaChannelStream::CacheClientSuspend() mDecoder=%p\n", mDecoder);
+
   Suspend(false);
 
   mDecoder->NotifySuspendedStatusChanged();
   return NS_OK;
 }
 
 nsresult
 nsMediaChannelStream::CacheClientResume()
 {
+  printf("*** nsMediaChannelStream::CacheClientResume() mDecoder=%p\n", mDecoder);
+
   Resume();
 
   mDecoder->NotifySuspendedStatusChanged();
   return NS_OK;
 }
 
 PRInt64
 nsMediaChannelStream::GetNextCachedData(PRInt64 aOffset)
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -85,38 +85,26 @@ bool Navigator::sDoNotTrackEnabled = fal
 void
 Navigator::Init()
 {
   Preferences::AddBoolVarCache(&sDoNotTrackEnabled,
                                "privacy.donottrackheader.enabled",
                                false);
 }
 
-Navigator::Navigator(nsIDocShell* aDocShell)
-  : mDocShell(aDocShell)
+Navigator::Navigator(nsPIDOMWindow* aWindow)
+  : mWindow(do_GetWeakReference(aWindow))
 {
+  NS_ASSERTION(aWindow->IsInnerWindow(),
+               "Navigator must get an inner window!");
 }
 
 Navigator::~Navigator()
 {
-  if (mMimeTypes) {
-    mMimeTypes->Invalidate();
-  }
-
-  if (mPlugins) {
-    mPlugins->Invalidate();
-  }
-
-  if (mBatteryManager) {
-    mBatteryManager->Shutdown();
-  }
-
-  if (mSmsManager) {
-    mSmsManager->Shutdown();
-  }
+  Invalidate();
 }
 
 NS_INTERFACE_MAP_BEGIN(Navigator)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNavigator)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator)
   NS_INTERFACE_MAP_ENTRY(nsIDOMClientInformation)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorGeolocation)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorBattery)
@@ -124,22 +112,23 @@ NS_INTERFACE_MAP_BEGIN(Navigator)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorSms)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(Navigator)
 NS_IMPL_RELEASE(Navigator)
 
 void
-Navigator::SetDocShell(nsIDocShell* aDocShell)
+Navigator::Invalidate()
 {
-  mDocShell = aDocShell;
+  mWindow = nsnull;
 
   if (mPlugins) {
-    mPlugins->SetDocShell(aDocShell);
+    mPlugins->Invalidate();
+    mPlugins = nsnull;
   }
 
   // If there is a page transition, make sure delete the geolocation object.
   if (mGeolocation) {
     mGeolocation->Shutdown();
     mGeolocation = nsnull;
   }
 
@@ -154,16 +143,25 @@ Navigator::SetDocShell(nsIDocShell* aDoc
   }
 
   if (mSmsManager) {
     mSmsManager->Shutdown();
     mSmsManager = nsnull;
   }
 }
 
+nsPIDOMWindow *
+Navigator::GetWindow()
+{
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+  return win;
+}
+
+
 //*****************************************************************************
 //    Navigator::nsIDOMNavigator
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetUserAgent(nsAString& aUserAgent)
 {
   return NS_GetNavigatorUserAgent(aUserAgent);
@@ -361,17 +359,19 @@ Navigator::GetMimeTypes(nsIDOMMimeTypeAr
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Navigator::GetPlugins(nsIDOMPluginArray** aPlugins)
 {
   if (!mPlugins) {
-    mPlugins = new nsPluginArray(this, mDocShell);
+    nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+    mPlugins = new nsPluginArray(this, win ? win->GetDocShell() : nsnull);
   }
 
   NS_ADDREF(*aPlugins = mPlugins);
 
   return NS_OK;
 }
 
 // Values for the network.cookie.cookieBehavior pref are documented in
@@ -383,17 +383,23 @@ Navigator::GetCookieEnabled(bool* aCooki
 {
   *aCookieEnabled =
     (Preferences::GetInt("network.cookie.cookieBehavior",
                          COOKIE_BEHAVIOR_REJECT) != COOKIE_BEHAVIOR_REJECT);
 
   // Check whether an exception overrides the global cookie behavior
   // Note that the code for getting the URI here matches that in
   // nsHTMLDocument::SetCookie.
-  nsCOMPtr<nsIDocument> doc = do_GetInterface(mDocShell);
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+  if (!win || !win->GetDocShell()) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument());
   if (!doc) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIURI> codebaseURI;
   doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
 
   if (!codebaseURI) {
@@ -503,60 +509,21 @@ Navigator::JavaEnabled(bool* aReturn)
       break;
     }
   }
 
   return NS_OK;
 }
 
 void
-Navigator::LoadingNewDocument()
-{
-  // Release these so that they will be recreated for the
-  // new document (if requested).  The plugins or mime types
-  // arrays may have changed.  See bug 150087.
-  if (mMimeTypes) {
-    mMimeTypes->Invalidate();
-    mMimeTypes = nsnull;
-  }
-
-  if (mPlugins) {
-    mPlugins->Invalidate();
-    mPlugins = nsnull;
-  }
-
-  if (mGeolocation) {
-    mGeolocation->Shutdown();
-    mGeolocation = nsnull;
-  }
-
-  if (mNotification) {
-    mNotification->Shutdown();
-    mNotification = nsnull;
-  }
-
-  if (mBatteryManager) {
-    mBatteryManager->Shutdown();
-    mBatteryManager = nsnull;
-  }
-
-  if (mSmsManager) {
-    mSmsManager->Shutdown();
-    mSmsManager = nsnull;
-  }
-}
-
-nsresult
 Navigator::RefreshMIMEArray()
 {
   if (mMimeTypes) {
-    return mMimeTypes->Refresh();
+    mMimeTypes->Refresh();
   }
-
-  return NS_OK;
 }
 
 bool
 Navigator::HasDesktopNotificationSupport()
 {
   return Preferences::GetBool("notification.feature.enabled", false);
 }
 
@@ -564,57 +531,51 @@ Navigator::HasDesktopNotificationSupport
 //    Navigator::nsIDOMClientInformation
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::RegisterContentHandler(const nsAString& aMIMEType,
                                   const nsAString& aURI,
                                   const nsAString& aTitle)
 {
-  if (!mDocShell) {
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+  if (!win || !win->GetOuterWindow() || !win->GetDocShell()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
     do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
   if (!registrar) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDOMWindow> contentDOMWindow = do_GetInterface(mDocShell);
-  if (!contentDOMWindow) {
-    return NS_OK;
-  }
-
   return registrar->RegisterContentHandler(aMIMEType, aURI, aTitle,
-                                           contentDOMWindow);
+                                           win->GetOuterWindow());
 }
 
 NS_IMETHODIMP
 Navigator::RegisterProtocolHandler(const nsAString& aProtocol,
                                    const nsAString& aURI,
                                    const nsAString& aTitle)
 {
-  if (!mDocShell) {
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+  if (!win || !win->GetOuterWindow() || !win->GetDocShell()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
     do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
   if (!registrar) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDOMWindow> contentDOMWindow = do_GetInterface(mDocShell);
-  if (!contentDOMWindow) {
-    return NS_OK;
-  }
-
   return registrar->RegisterProtocolHandler(aProtocol, aURI, aTitle,
-                                            contentDOMWindow);
+                                            win->GetOuterWindow());
 }
 
 NS_IMETHODIMP
 Navigator::MozIsLocallyAvailable(const nsAString &aURI,
                                  bool aWhenOffline,
                                  bool* aIsAvailable)
 {
   nsCOMPtr<nsIURI> uri;
@@ -697,31 +658,28 @@ NS_IMETHODIMP Navigator::GetGeolocation(
     return NS_OK;
   }
 
   if (mGeolocation) {
     NS_ADDREF(*_retval = mGeolocation);
     return NS_OK;
   }
 
-  if (!mDocShell) {
-    return NS_ERROR_FAILURE;
-  }
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
 
-  nsCOMPtr<nsIDOMWindow> contentDOMWindow = do_GetInterface(mDocShell);
-  if (!contentDOMWindow) {
+  if (!win || !win->GetOuterWindow() || !win->GetDocShell()) {
     return NS_ERROR_FAILURE;
   }
 
   mGeolocation = new nsGeolocation();
   if (!mGeolocation) {
     return NS_ERROR_FAILURE;
   }
 
-  if (NS_FAILED(mGeolocation->Init(contentDOMWindow))) {
+  if (NS_FAILED(mGeolocation->Init(win->GetOuterWindow()))) {
     mGeolocation = nsnull;
     return NS_ERROR_FAILURE;
   }
 
   NS_ADDREF(*_retval = mGeolocation);
   return NS_OK;
 }
 
@@ -734,59 +692,48 @@ NS_IMETHODIMP Navigator::GetMozNotificat
   NS_ENSURE_ARG_POINTER(aRetVal);
   *aRetVal = nsnull;
 
   if (mNotification) {
     NS_ADDREF(*aRetVal = mNotification);
     return NS_OK;
   }
 
-  nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mDocShell);
-  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsIDocument> document = do_GetInterface(mDocShell);
-  NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
-
-  nsIScriptGlobalObject* sgo = document->GetScopeObject();
-  NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+  nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(win));
+  NS_ENSURE_TRUE(sgo && win->GetDocShell(), NS_ERROR_FAILURE);
 
   nsIScriptContext* scx = sgo->GetContext();
   NS_ENSURE_TRUE(scx, NS_ERROR_FAILURE);
 
-  mNotification = new nsDesktopNotificationCenter(window->GetCurrentInnerWindow(),
-                                                  scx);
+  mNotification = new nsDesktopNotificationCenter(win, scx);
 
   NS_ADDREF(*aRetVal = mNotification);
   return NS_OK;
 }
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorBattery
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetMozBattery(nsIDOMMozBatteryManager** aBattery)
 {
   if (!mBatteryManager) {
     *aBattery = nsnull;
 
-    nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mDocShell);
-    NS_ENSURE_TRUE(window, NS_OK);
-
-    nsCOMPtr<nsIDocument> document = do_GetInterface(mDocShell);
-    NS_ENSURE_TRUE(document, NS_OK);
-
-    nsIScriptGlobalObject* sgo = document->GetScopeObject();
-    NS_ENSURE_TRUE(sgo, NS_OK);
+    nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+    nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(win));
+    NS_ENSURE_TRUE(sgo && win->GetDocShell(), NS_OK);
 
     nsIScriptContext* scx = sgo->GetContext();
     NS_ENSURE_TRUE(scx, NS_OK);
 
     mBatteryManager = new battery::BatteryManager();
-    mBatteryManager->Init(window->GetCurrentInnerWindow(), scx);
+    mBatteryManager->Init(win, scx);
   }
 
   NS_ADDREF(*aBattery = mBatteryManager);
 
   return NS_OK;
 }
 
 //*****************************************************************************
@@ -804,17 +751,23 @@ Navigator::IsSmsAllowed() const
   }
 
   // In addition of having 'dom.sms.enabled' set to true, we require the
   // website to be whitelisted. This is a temporary 'security model'.
   // 'dom.sms.whitelist' has to contain comma-separated values of URI prepath.
   // For local files, "file://" must be listed.
   // For data-urls: "moz-nullprincipal:".
   // Chrome files also have to be whitelisted for the moment.
-  nsCOMPtr<nsIDocument> doc = do_GetInterface(mDocShell);
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+  if (!win || !win->GetDocShell()) {
+    return defaultSmsPermission;
+  }
+
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument());
   if (!doc) {
     return defaultSmsPermission;
   }
 
   nsCOMPtr<nsIURI> uri;
   doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
 
   if (!uri) {
@@ -859,30 +812,27 @@ Navigator::GetMozSms(nsIDOMMozSmsManager
 {
   *aSmsManager = nsnull;
 
   if (!mSmsManager) {
     if (!IsSmsSupported() || !IsSmsAllowed()) {
       return NS_OK;
     }
 
-    nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mDocShell);
-    NS_ENSURE_TRUE(window, NS_OK);
+    nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+    NS_ENSURE_TRUE(window && window->GetDocShell(), NS_OK);
 
-    nsCOMPtr<nsIDocument> document = do_GetInterface(mDocShell);
-    NS_ENSURE_TRUE(document, NS_OK);
-
-    nsIScriptGlobalObject* sgo = document->GetScopeObject();
+    nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window);
     NS_ENSURE_TRUE(sgo, NS_OK);
 
     nsIScriptContext* scx = sgo->GetContext();
     NS_ENSURE_TRUE(scx, NS_OK);
 
     mSmsManager = new sms::SmsManager();
-    mSmsManager->Init(window->GetCurrentInnerWindow(), scx);
+    mSmsManager->Init(window, scx);
   }
 
   NS_ADDREF(*aSmsManager = mSmsManager);
 
   return NS_OK;
 }
 
 PRInt64
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -45,22 +45,23 @@
 
 #include "nsIDOMNavigator.h"
 #include "nsIDOMNavigatorGeolocation.h"
 #include "nsIDOMNavigatorDesktopNotification.h"
 #include "nsIDOMClientInformation.h"
 #include "nsIDOMNavigatorBattery.h"
 #include "nsIDOMNavigatorSms.h"
 #include "nsAutoPtr.h"
+#include "nsWeakReference.h"
 
 class nsPluginArray;
 class nsMimeTypeArray;
 class nsGeolocation;
 class nsDesktopNotificationCenter;
-class nsIDocShell;
+class nsPIDOMWindow;
 
 //*****************************************************************************
 // Navigator: Script "navigator" object
 //*****************************************************************************
 
 namespace mozilla {
 namespace dom {
 
@@ -75,37 +76,33 @@ class SmsManager;
 class Navigator : public nsIDOMNavigator,
                   public nsIDOMClientInformation,
                   public nsIDOMNavigatorGeolocation,
                   public nsIDOMNavigatorDesktopNotification,
                   public nsIDOMMozNavigatorBattery,
                   public nsIDOMMozNavigatorSms
 {
 public:
-  Navigator(nsIDocShell *aDocShell);
+  Navigator(nsPIDOMWindow *aInnerWindow);
   virtual ~Navigator();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMNAVIGATOR
   NS_DECL_NSIDOMCLIENTINFORMATION
   NS_DECL_NSIDOMNAVIGATORGEOLOCATION
   NS_DECL_NSIDOMNAVIGATORDESKTOPNOTIFICATION
   NS_DECL_NSIDOMMOZNAVIGATORBATTERY
   NS_DECL_NSIDOMMOZNAVIGATORSMS
 
   static void Init();
 
-  void SetDocShell(nsIDocShell *aDocShell);
-  nsIDocShell *GetDocShell()
-  {
-    return mDocShell;
-  }
+  void Invalidate();
+  nsPIDOMWindow *GetWindow();
 
-  void LoadingNewDocument();
-  nsresult RefreshMIMEArray();
+  void RefreshMIMEArray();
 
   static bool HasDesktopNotificationSupport();
 
   PRInt64 SizeOf() const;
 
 private:
   bool IsSmsAllowed() const;
   bool IsSmsSupported() const;
@@ -113,17 +110,17 @@ private:
   static bool sDoNotTrackEnabled;
 
   nsRefPtr<nsMimeTypeArray> mMimeTypes;
   nsRefPtr<nsPluginArray> mPlugins;
   nsRefPtr<nsGeolocation> mGeolocation;
   nsRefPtr<nsDesktopNotificationCenter> mNotification;
   nsRefPtr<battery::BatteryManager> mBatteryManager;
   nsRefPtr<sms::SmsManager> mSmsManager;
-  nsIDocShell* mDocShell; // weak reference
+  nsWeakPtr mWindow;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 nsresult NS_GetNavigatorUserAgent(nsAString& aUserAgent);
 nsresult NS_GetNavigatorPlatform(nsAString& aPlatform);
 nsresult NS_GetNavigatorAppVersion(nsAString& aAppVersion);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -6817,16 +6817,18 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
       NS_ENSURE_SUCCESS(rv, rv);
 
       jsval v;
       nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
       rv = WrapNative(cx, obj, navigator, &NS_GET_IID(nsIDOMNavigator), true,
                       &v, getter_AddRefs(holder));
       NS_ENSURE_SUCCESS(rv, rv);
 
+      // Hold on to the navigator object as a global property so we
+      // don't need to worry about losing expando properties etc.
       if (!::JS_DefinePropertyById(cx, obj, id, v, nsnull, nsnull,
                                    JSPROP_READONLY | JSPROP_PERMANENT |
                                    JSPROP_ENUMERATE)) {
         return NS_ERROR_FAILURE;
       }
       *objp = obj;
 
       return NS_OK;
@@ -7149,46 +7151,41 @@ nsNavigatorSH::NewResolve(nsIXPConnectWr
   return ok ? NS_OK : NS_ERROR_FAILURE;
 }
 
 // static
 nsresult
 nsNavigatorSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
                          JSObject *globalObj, JSObject **parentObj)
 {
-  // window.navigator is persisted across document transitions if
-  // we're loading a page from the same origin. Because of that we
-  // need to parent the navigator wrapper at the outer window to avoid
-  // holding on to the inner window where the navigator was initially
-  // created too long.
+  // window.navigator can hold expandos and thus we need to only ever
+  // create one wrapper per navigator object so that expandos are
+  // visible independently of who's looking it up.
   *parentObj = globalObj;
 
   nsCOMPtr<nsIDOMNavigator> safeNav(do_QueryInterface(nativeObj));
   if (!safeNav) {
     // Oops, this wasn't really a navigator object. This can happen if someone
     // tries to use our scriptable helper as a real object and tries to wrap
     // it, see bug 319296.
     return NS_OK;
   }
 
   Navigator *nav = static_cast<Navigator*>(safeNav.get());
-  nsIDocShell *ds = nav->GetDocShell();
-  if (!ds) {
+  nsGlobalWindow *win = static_cast<nsGlobalWindow*>(nav->GetWindow());
+  if (!win) {
     NS_WARNING("Refusing to create a navigator in the wrong scope");
+
     return NS_ERROR_UNEXPECTED;
   }
 
-  nsCOMPtr<nsIScriptGlobalObject> sgo = do_GetInterface(ds);
-
-  if (sgo) {
-    JSObject *global = sgo->GetGlobalJSObject();
-
-    if (global) {
-      *parentObj = global;
-    }
+  JSObject *global = win->GetGlobalJSObject();
+
+  if (global) {
+    *parentObj = global;
   }
 
   return NS_OK;
 }
 
 // DOM Node helper
 
 template<nsresult (*func)(JSContext *cx, JSObject *obj, jsval *vp)>
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1267,16 +1267,21 @@ nsGlobalWindow::ClearScopeWhenAllScripts
   }
 }
 
 void
 nsGlobalWindow::FreeInnerObjects(bool aClearScope)
 {
   NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
 
+  // Make sure that this is called before we null out the document and
+  // other members that the window destroyed observers could
+  // re-create.
+  NotifyDOMWindowDestroyed(this);
+
   // Kill all of the workers for this window.
   nsIScriptContext *scx = GetContextInternal();
   JSContext *cx = scx ? scx->GetNativeContext() : nsnull;
   mozilla::dom::workers::CancelWorkersForWindow(cx, this);
 
   // Close all IndexedDB databases for this window.
   indexedDB::IndexedDatabaseManager* idbManager =
     indexedDB::IndexedDatabaseManager::Get();
@@ -1291,31 +1296,33 @@ nsGlobalWindow::FreeInnerObjects(bool aC
   if (mListenerManager) {
     mListenerManager->Disconnect();
     mListenerManager = nsnull;
   }
 
   mLocation = nsnull;
   mHistory = nsnull;
 
+  if (mNavigator) {
+    mNavigator->Invalidate();
+    mNavigator = nsnull;
+  }
+
   if (mDocument) {
     NS_ASSERTION(mDoc, "Why is mDoc null?");
 
     // Remember the document's principal.
     mDocumentPrincipal = mDoc->NodePrincipal();
   }
 
 #ifdef DEBUG
   if (mDocument)
     nsCycleCollector_DEBUG_shouldBeFreed(nsCOMPtr<nsISupports>(do_QueryInterface(mDocument)));
 #endif
 
-  // Make sure that this is called before we null out the document.
-  NotifyDOMWindowDestroyed(this);
-
   // Remove our reference to the document and the document principal.
   mDocument = nsnull;
   mDoc = nsnull;
 
   if (mApplicationCache) {
     static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->Disconnect();
     mApplicationCache = nsnull;
   }
@@ -1728,59 +1735,53 @@ nsGlobalWindow::GetPopupControlState() c
 class WindowStateHolder : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(WINDOWSTATEHOLDER_IID)
   NS_DECL_ISUPPORTS
 
   WindowStateHolder(nsGlobalWindow *aWindow,
                     nsIXPConnectJSObjectHolder *aHolder,
-                    Navigator *aNavigator,
                     nsIXPConnectJSObjectHolder *aOuterProto,
                     nsIXPConnectJSObjectHolder *aOuterRealProto);
 
   nsGlobalWindow* GetInnerWindow() { return mInnerWindow; }
   nsIXPConnectJSObjectHolder *GetInnerWindowHolder()
   { return mInnerWindowHolder; }
 
-  Navigator* GetNavigator() { return mNavigator; }
   nsIXPConnectJSObjectHolder* GetOuterProto() { return mOuterProto; }
   nsIXPConnectJSObjectHolder* GetOuterRealProto() { return mOuterRealProto; }
 
   void DidRestoreWindow()
   {
     mInnerWindow = nsnull;
 
     mInnerWindowHolder = nsnull;
-    mNavigator = nsnull;
     mOuterProto = nsnull;
     mOuterRealProto = nsnull;
   }
 
 protected:
   ~WindowStateHolder();
 
   nsGlobalWindow *mInnerWindow;
   // We hold onto this to make sure the inner window doesn't go away. The outer
   // window ends up recalculating it anyway.
   nsCOMPtr<nsIXPConnectJSObjectHolder> mInnerWindowHolder;
-  nsRefPtr<Navigator> mNavigator;
   nsCOMPtr<nsIXPConnectJSObjectHolder> mOuterProto;
   nsCOMPtr<nsIXPConnectJSObjectHolder> mOuterRealProto;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(WindowStateHolder, WINDOWSTATEHOLDER_IID)
 
 WindowStateHolder::WindowStateHolder(nsGlobalWindow *aWindow,
                                      nsIXPConnectJSObjectHolder *aHolder,
-                                     Navigator *aNavigator,
                                      nsIXPConnectJSObjectHolder *aOuterProto,
                                      nsIXPConnectJSObjectHolder *aOuterRealProto)
   : mInnerWindow(aWindow),
-    mNavigator(aNavigator),
     mOuterProto(aOuterProto),
     mOuterRealProto(aOuterRealProto)
 {
   NS_PRECONDITION(aWindow, "null window");
   NS_PRECONDITION(aWindow->IsInnerWindow(), "Saving an outer window");
 
   mInnerWindowHolder = aHolder;
 
@@ -1925,42 +1926,16 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   // Remember the old document's principal.
   nsIPrincipal *oldPrincipal = nsnull;
   if (oldDoc) {
     oldPrincipal = oldDoc->NodePrincipal();
   }
 
   nsresult rv = NS_OK;
 
-  // Drop our reference to the navigator object unless we're reusing
-  // the existing inner window or the new document is from the same
-  // origin as the old document.
-  if (!reUseInnerWindow && mNavigator && oldPrincipal) {
-    bool equal;
-    rv = oldPrincipal->Equals(aDocument->NodePrincipal(), &equal);
-
-    if (NS_FAILED(rv) || !equal) {
-      // Different origins.  Release the navigator object so it gets
-      // recreated for the new document.  The plugins or mime types
-      // arrays may have changed. See bug 150087.
-      mNavigator->SetDocShell(nsnull);
-
-      mNavigator = nsnull;
-    }
-  }
-
-  if (mNavigator && aDocument != oldDoc) {
-    // We didn't drop our reference to our old navigator object and
-    // we're loading a new document. Notify the navigator object about
-    // the new document load so that it can make sure it is ready for
-    // the new document.
-
-    mNavigator->LoadingNewDocument();
-  }
-
   // Set mDocument even if this is an outer window to avoid
   // having to *always* reach into the inner window to find the
   // document.
   mDocument = do_QueryInterface(aDocument);
   mDoc = aDocument;
 
 #ifdef DEBUG
   mLastOpenedURI = aDocument->GetDocumentURI();
@@ -1968,18 +1943,16 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 
   mContext->WillInitializeContext();
 
   nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
 
   nsRefPtr<nsGlobalWindow> newInnerWindow;
 
   bool thisChrome = IsChromeWindow();
-  nsCOMPtr<nsIXPConnectJSObjectHolder> navigatorHolder;
-  jsval nav;
 
   bool isChrome = false;
 
   nsCxPusher cxPusher;
   if (!cxPusher.Push(cx)) {
     return NS_ERROR_FAILURE;
   }
 
@@ -1989,21 +1962,16 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   NS_ASSERTION(!aState || wsh, "What kind of weird state are you giving me here?");
 
   // Make sure to clear scope on the outer window *before* we
   // initialize the new inner window. If we don't, things
   // (Object.prototype etc) could leak from the old outer to the new
   // inner scope.
   mContext->ClearScope(mJSObject, false);
 
-  // This code should not be called during shutdown any more (now that
-  // we don't ever call SetNewDocument(nsnull), so no need to null
-  // check xpc here.
-  nsIXPConnect *xpc = nsContentUtils::XPConnect();
-  nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
   if (reUseInnerWindow) {
     // We're reusing the current inner window.
     NS_ASSERTION(!currentInner->IsFrozen(),
                  "We should never be reusing a shared inner window");
     newInnerWindow = currentInner;
 
     if (aDocument != oldDoc) {
       nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
@@ -2018,49 +1986,25 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       return NS_ERROR_FAILURE;
     }
   } else {
     if (aState) {
       newInnerWindow = wsh->GetInnerWindow();
       mInnerWindowHolder = wsh->GetInnerWindowHolder();
       
       NS_ASSERTION(newInnerWindow, "Got a state without inner window");
-
-      // These assignments addref.
-      mNavigator = wsh->GetNavigator();
-
-      if (mNavigator) {
-        // Update mNavigator's docshell pointer now.
-        mNavigator->SetDocShell(mDocShell);
-        mNavigator->LoadingNewDocument();
-      }
     } else if (thisChrome) {
       newInnerWindow = new nsGlobalChromeWindow(this);
       isChrome = true;
     } else if (mIsModalContentWindow) {
       newInnerWindow = new nsGlobalModalWindow(this);
     } else {
       newInnerWindow = new nsGlobalWindow(this);
     }
 
-    if (currentInner && currentInner->mJSObject) {
-      if (mNavigator && !aState) {
-        // Hold on to the navigator wrapper so that we can set
-        // window.navigator in the new window to point to the same
-        // object (assuming we didn't change origins etc). See bug
-        // 163645 for more on why we need this.
-
-        nsIDOMNavigator* navigator =
-          static_cast<nsIDOMNavigator*>(mNavigator.get());
-        nsContentUtils::WrapNative(cx, currentInner->mJSObject, navigator,
-                                   &NS_GET_IID(nsIDOMNavigator), &nav,
-                                   getter_AddRefs(navigatorHolder));
-      }
-    }
-
     if (!aState) {
       // This is redundant if we're restoring from a previous inner window.
       nsIScriptGlobalObject *sgo =
         (nsIScriptGlobalObject *)newInnerWindow.get();
 
       // Freeze the outer window and null out the inner window so
       // that initializing classes on the new inner doesn't end up
       // reaching into the old inner window for classes etc.
@@ -2284,43 +2228,16 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       }
     } else {
       rv = newInnerWindow->InnerSetNewDocument(aDocument);
       NS_ENSURE_SUCCESS(rv, rv);
 
       // Initialize DOM classes etc on the inner window.
       rv = mContext->InitClasses(newInnerWindow->mJSObject);
       NS_ENSURE_SUCCESS(rv, rv);
-
-      if (navigatorHolder) {
-        JS_ASSERT(JSVAL_IS_OBJECT(nav));
-
-        if (js::GetObjectCompartment(JSVAL_TO_OBJECT(nav)) ==
-            js::GetObjectCompartment(newInnerWindow->mJSObject)) {
-          // Restore window.navigator onto the new inner window.
-
-          ::JS_DefineProperty(cx, newInnerWindow->mJSObject, "navigator",
-                              nav, nsnull, nsnull,
-                              JSPROP_ENUMERATE | JSPROP_PERMANENT |
-                              JSPROP_READONLY);
-
-          // The Navigator's prototype object keeps a reference to the
-          // window in which it was first created and can thus cause that
-          // window to stay alive for too long. Reparenting it here allows
-          // the window to be collected sooner.
-          nsIDOMNavigator* navigator =
-            static_cast<nsIDOMNavigator*>(mNavigator);
-
-          xpc->
-            ReparentWrappedNativeIfFound(cx, JSVAL_TO_OBJECT(nav),
-                                         newInnerWindow->mJSObject,
-                                         navigator,
-                                         getter_AddRefs(navigatorHolder));
-        }
-      }
     }
 
     if (mArguments) {
       newInnerWindow->DefineArgumentsProperty(mArguments);
       newInnerWindow->mArguments = mArguments;
       newInnerWindow->mArgumentsOrigin = mArgumentsOrigin;
 
       mArguments = nsnull;
@@ -2497,18 +2414,18 @@ nsGlobalWindow::SetDocShell(nsIDocShell*
 #ifdef DEBUG
     nsCycleCollector_DEBUG_shouldBeFreed(mContext);
     nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this));
 #endif
   }
 
   mDocShell = aDocShell;        // Weak Reference
 
-  if (mNavigator)
-    mNavigator->SetDocShell(aDocShell);
+  NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
+
   if (mFrames)
     mFrames->SetDocShell(aDocShell);
   if (mScreen)
     mScreen->SetDocShell(aDocShell);
 
   if (!mDocShell) {
     MaybeForgiveSpamCount();
     CleanUp(false);
@@ -2994,22 +2911,22 @@ nsGlobalWindow::GetSelf(nsIDOMWindow** a
   *aWindow = static_cast<nsIDOMWindow*>(this);
   NS_ADDREF(*aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetNavigator(nsIDOMNavigator** aNavigator)
 {
-  FORWARD_TO_OUTER(GetNavigator, (aNavigator), NS_ERROR_NOT_INITIALIZED);
+  FORWARD_TO_INNER(GetNavigator, (aNavigator), NS_ERROR_NOT_INITIALIZED);
 
   *aNavigator = nsnull;
 
   if (!mNavigator) {
-    mNavigator = new Navigator(mDocShell);
+    mNavigator = new Navigator(this);
   }
 
   NS_ADDREF(*aNavigator = mNavigator);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -9955,17 +9872,16 @@ nsGlobalWindow::SaveWindowState(nsISuppo
   nsCOMPtr<nsIXPConnectJSObjectHolder> realProtoHolder;
   if (realProto) {
     rv = xpc->HoldObject(cx, realProto, getter_AddRefs(realProtoHolder));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCOMPtr<nsISupports> state = new WindowStateHolder(inner,
                                                       mInnerWindowHolder,
-                                                      mNavigator,
                                                       proto,
                                                       realProtoHolder);
   NS_ENSURE_TRUE(state, NS_ERROR_OUT_OF_MEMORY);
 
   JSObject *wnProto;
   proto->GetJSObject(&wnProto);
   if (!JS_SetPrototype(cx, mJSObject, wnProto)) {
     return NS_ERROR_FAILURE;
--- a/dom/base/nsMimeTypeArray.cpp
+++ b/dom/base/nsMimeTypeArray.cpp
@@ -205,30 +205,33 @@ nsMimeTypeArray::NamedItem(const nsAStri
 {
   nsresult rv;
 
   NS_IF_ADDREF(*aReturn = GetNamedItem(aName, &rv));
 
   return rv;
 }
 
-void  nsMimeTypeArray::Clear()
+void
+nsMimeTypeArray::Clear()
 {
   mInited = false;
   mMimeTypeArray.Clear();
   mPluginMimeTypeCount = 0;
 }
 
-nsresult nsMimeTypeArray::Refresh()
+void
+nsMimeTypeArray::Refresh()
 {
   Clear();
-  return GetMimeTypes();
+  GetMimeTypes();
 }
 
-nsresult nsMimeTypeArray::GetMimeTypes()
+nsresult
+nsMimeTypeArray::GetMimeTypes()
 {
   NS_PRECONDITION(!mInited && mPluginMimeTypeCount==0,
                       "already initialized");
 
   if (!mNavigator) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
--- a/dom/base/nsMimeTypeArray.h
+++ b/dom/base/nsMimeTypeArray.h
@@ -53,17 +53,17 @@ class nsMimeTypeArray : public nsIDOMMim
 {
 public:
   nsMimeTypeArray(nsIDOMNavigator* navigator);
   virtual ~nsMimeTypeArray();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMMIMETYPEARRAY
 
-  nsresult Refresh();
+  void Refresh();
 
   nsIDOMMimeType* GetItemAt(PRUint32 aIndex, nsresult* aResult);
   nsIDOMMimeType* GetNamedItem(const nsAString& aName, nsresult* aResult);
 
   static nsMimeTypeArray* FromSupports(nsISupports* aSupports)
   {
 #ifdef DEBUG
     {
--- a/dom/base/nsPluginArray.cpp
+++ b/dom/base/nsPluginArray.cpp
@@ -50,23 +50,22 @@
 #include "nsContentUtils.h"
 #include "nsPluginHost.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsPluginArray::nsPluginArray(Navigator* navigator,
                              nsIDocShell *aDocShell)
+  : mNavigator(navigator),
+    mPluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID)),
+    mPluginCount(0),
+    mPluginArray(nsnull),
+    mDocShell(do_GetWeakReference(aDocShell))
 {
-  nsresult rv;
-  mNavigator = navigator; // don't ADDREF here, needed for parent of script object.
-  mPluginHost = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &rv);
-  mPluginCount = 0;
-  mPluginArray = nsnull;
-  mDocShell = aDocShell;
 }
 
 nsPluginArray::~nsPluginArray()
 {
   if (mPluginArray != nsnull) {
     for (PRUint32 i = 0; i < mPluginCount; i++) {
       NS_IF_RELEASE(mPluginArray[i]);
     }
@@ -96,18 +95,20 @@ nsPluginArray::GetLength(PRUint32* aLeng
   *aLength = 0;
   return NS_OK;
 }
 
 bool
 nsPluginArray::AllowPlugins()
 {
   bool allowPlugins = false;
-  if (mDocShell)
-    if (NS_FAILED(mDocShell->GetAllowPlugins(&allowPlugins)))
+  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
+
+  if (docShell)
+    if (NS_FAILED(docShell->GetAllowPlugins(&allowPlugins)))
       allowPlugins = false;
 
   return allowPlugins;
 }
 
 nsIDOMPlugin*
 nsPluginArray::GetItemAt(PRUint32 aIndex, nsresult* aResult)
 {
@@ -189,22 +190,16 @@ nsPluginArray::GetPluginHost(nsIPluginHo
 
   *aPluginHost = mPluginHost;
   NS_IF_ADDREF(*aPluginHost);
 
   return rv;
 }
 
 void
-nsPluginArray::SetDocShell(nsIDocShell *aDocShell)
-{
-  mDocShell = aDocShell;
-}
-
-void
 nsPluginArray::Invalidate()
 {
   mDocShell = nsnull;
   mNavigator = nsnull;
 }
 
 NS_IMETHODIMP
 nsPluginArray::Refresh(bool aReloadDocuments)
@@ -227,17 +222,17 @@ nsPluginArray::Refresh(bool aReloadDocum
   if(mPluginHost)
     pluginsNotChanged = (NS_ERROR_PLUGINS_PLUGINSNOTCHANGED == mPluginHost->ReloadPlugins(aReloadDocuments));
 
   // no need to reload the page if plugins have not been changed
   // in fact, if we do reload we can hit recursive load problem, see bug 93351
   if(pluginsNotChanged)
     return res;
 
-  nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(mDocShell);
+  nsCOMPtr<nsIWebNavigation> webNav = do_QueryReferent(mDocShell);
 
   if (mPluginArray != nsnull) {
     for (PRUint32 i = 0; i < mPluginCount; i++) 
       NS_IF_RELEASE(mPluginArray[i]);
 
     delete[] mPluginArray;
   }
 
--- a/dom/base/nsPluginArray.h
+++ b/dom/base/nsPluginArray.h
@@ -38,16 +38,17 @@
 #ifndef nsPluginArray_h___
 #define nsPluginArray_h___
 
 #include "nsCOMPtr.h"
 #include "nsIDOMPluginArray.h"
 #include "nsIDOMPlugin.h"
 #include "nsIPluginHost.h"
 #include "nsIURL.h"
+#include "nsWeakReference.h"
 
 namespace mozilla {
 namespace dom {
 class Navigator;
 } // namespace dom
 } // namespace mozilla
 
 class nsIDocShell;
@@ -87,25 +88,24 @@ public:
     return static_cast<nsPluginArray*>(aSupports);
   }
 
 private:
   nsresult GetPlugins();
   bool AllowPlugins();
 
 public:
-  void SetDocShell(nsIDocShell *aDocShell);
   void Invalidate();
 
 protected:
   mozilla::dom::Navigator* mNavigator;
   nsCOMPtr<nsIPluginHost> mPluginHost;
   PRUint32 mPluginCount;
   nsIDOMPlugin** mPluginArray;
-  nsIDocShell* mDocShell; // weak reference
+  nsWeakPtr mDocShell;
 };
 
 class nsPluginElement : public nsIDOMPlugin
 {
 public:
   nsPluginElement(nsIDOMPlugin* plugin);
   virtual ~nsPluginElement();
 
--- a/dom/battery/BatteryManager.cpp
+++ b/dom/battery/BatteryManager.cpp
@@ -82,17 +82,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetWrapperCache)
 
 NS_IMPL_ADDREF_INHERITED(BatteryManager, nsDOMEventTargetWrapperCache)
 NS_IMPL_RELEASE_INHERITED(BatteryManager, nsDOMEventTargetWrapperCache)
 
 BatteryManager::BatteryManager()
   : mLevel(kDefaultLevel)
   , mCharging(kDefaultCharging)
-  , mRemainingTime(kUnknownRemainingTime)
+  , mRemainingTime(kDefaultRemainingTime)
 {
 }
 
 BatteryManager::~BatteryManager()
 {
   if (mListenerManager) {
     mListenerManager->Disconnect();
   }
@@ -186,16 +186,24 @@ BatteryManager::DispatchTrustedEventToSe
 }
 
 void
 BatteryManager::UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo)
 {
   mLevel = aBatteryInfo.level();
   mCharging = aBatteryInfo.charging();
   mRemainingTime = aBatteryInfo.remainingTime();
+
+  // Add some guards to make sure the values are coherent.
+  if (mLevel == 1.0 && mCharging == true &&
+      mRemainingTime != kDefaultRemainingTime) {
+    mRemainingTime = kDefaultRemainingTime;
+    NS_ERROR("Battery API: When charging and level at 1.0, remaining time "
+             "should be 0. Please fix your backend!");
+  }
 }
 
 void
 BatteryManager::Notify(const hal::BatteryInformation& aBatteryInfo)
 {
   double previousLevel = mLevel;
   bool previousCharging = mCharging;
   double previousRemainingTime = mRemainingTime;
--- a/dom/battery/Constants.h
+++ b/dom/battery/Constants.h
@@ -43,15 +43,16 @@
  * It's not part of BatteryManager.h to prevent those backends to include it.
  */
 namespace mozilla {
 namespace dom {
 namespace battery {
 
   static const double kDefaultLevel         = 1.0;
   static const bool   kDefaultCharging      = true;
+  static const double kDefaultRemainingTime = 0;
   static const double kUnknownRemainingTime = -1;
 
 } // namespace battery
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_battery_Constants_h__
--- a/dom/battery/test/test_battery_basics.html
+++ b/dom/battery/test/test_battery_basics.html
@@ -21,14 +21,14 @@ ok(!("BatteryManager" in window), "Batte
 ok(("MozBatteryManager" in window), "MozBatteryManager should be visible");
 
 ok('mozBattery' in navigator, "navigator.mozBattery should exist");
 
 var battery = navigator.mozBattery;
 is(battery.level, 1.0, "Default battery level should be 1.0");
 is(battery.charging, true, "Default charging value should be true");
 is(battery.dischargingTime, Infinity, "Default dischargingTime should be Inifinity");
-is(battery.chargingTime, Infinity, "Default chargingTime should be Inifinity");
+is(battery.chargingTime, 0, "Default chargingTime should be 0");
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/plugins/test/testplugin/nptest_utils.cpp
+++ b/dom/plugins/test/testplugin/nptest_utils.cpp
@@ -80,39 +80,32 @@ doubleVariantToIdentifier(NPVariant vari
   assert(NPVARIANT_IS_DOUBLE(variant));
   double value = NPVARIANT_TO_DOUBLE(variant);
   // sadly there is no "getdoubleidentifier"
   int32_t integer = static_cast<int32_t>(value);
   return NPN_GetIntIdentifier(integer);
 }
 
 /*
- * Parse a color in hex format, like AARRGGBB
- * If the string is short, portions to the left are assumed omitted.
- * R G B default to 0, A defaults to 0xFF
+ * Parse a color in hex format, #AARRGGBB or AARRGGBB.
  */
 PRUint32
 parseHexColor(const char* color, int len)
 {
   PRUint8 bgra[4] = { 0, 0, 0, 0xFF };
   int i = 0;
 
+  assert(len == 9 || len == 8);
+
   // start from the right and work to the left
-  while (len > 0) {
+  while (len >= 2) { // we have at least #AA or AA left.
     char byte[3];
-    if (len > 1) {
-      // parse two hex digits
-      byte[0] = color[len - 2];
-      byte[1] = color[len - 1];
-    }
-    else {
-      // only one digit left
-      byte[0] = '0';
-      byte[1] = color[len - 1];
-    }
+    // parse two hex digits
+    byte[0] = color[len - 2];
+    byte[1] = color[len - 1];
     byte[2] = '\0';
 
     bgra[i] = (PRUint8)(strtoul(byte, NULL, 16) & 0xFF);
     i++;
     len -= 2;
   }
   return (bgra[3] << 24) | (bgra[2] << 16) | (bgra[1] << 8) | bgra[0];
 }
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -299,18 +299,16 @@ nsDOMStorageManager::Initialize()
   NS_ENSURE_SUCCESS(rv, rv);
   rv = os->AddObserver(gStorageManager, "perm-changed", true);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = os->AddObserver(gStorageManager, "browser:purge-domain-data", true);
   NS_ENSURE_SUCCESS(rv, rv);
   // Used for temporary table flushing
   rv = os->AddObserver(gStorageManager, "profile-before-change", true);
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = os->AddObserver(gStorageManager, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
-  NS_ENSURE_SUCCESS(rv, rv);
   rv = os->AddObserver(gStorageManager, NS_DOMSTORAGE_FLUSH_TIMER_TOPIC, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 //static
 nsDOMStorageManager*
@@ -324,16 +322,23 @@ nsDOMStorageManager::GetInstance()
 
 //static
 void
 nsDOMStorageManager::Shutdown()
 {
   NS_IF_RELEASE(gStorageManager);
   gStorageManager = nsnull;
 
+  ShutdownDB();
+}
+
+//static
+void
+nsDOMStorageManager::ShutdownDB()
+{
   delete DOMStorageImpl::gStorageDB;
   DOMStorageImpl::gStorageDB = nsnull;
 }
 
 static PLDHashOperator
 ClearStorage(nsDOMStorageEntry* aEntry, void* userArg)
 {
   aEntry->mStorage->ClearAll();
@@ -479,23 +484,24 @@ nsDOMStorageManager::Observe(nsISupports
 
     // Clear the storage entries for matching domains
     mStorages.EnumerateEntries(ClearStorageIfDomainMatches, &key);
 
     rv = DOMStorageImpl::InitDB();
     NS_ENSURE_SUCCESS(rv, rv);
 
     DOMStorageImpl::gStorageDB->RemoveOwner(aceDomain, true);
-  } else if (!strcmp(aTopic, "profile-before-change") || 
-             !strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
+  } else if (!strcmp(aTopic, "profile-before-change")) {
     if (DOMStorageImpl::gStorageDB) {
       DebugOnly<nsresult> rv =
         DOMStorageImpl::gStorageDB->FlushAndDeleteTemporaryTables(true);
       NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
                        "DOMStorage: temporary table commit failed");
+      DOMStorageImpl::gStorageDB->Close();
+      nsDOMStorageManager::ShutdownDB();
     }
   } else if (!strcmp(aTopic, NS_DOMSTORAGE_FLUSH_TIMER_TOPIC)) {
     if (DOMStorageImpl::gStorageDB) {
       DebugOnly<nsresult> rv =
         DOMStorageImpl::gStorageDB->FlushAndDeleteTemporaryTables(false);
       NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
                        "DOMStorage: temporary table commit failed");
     }
--- a/dom/src/storage/nsDOMStorage.h
+++ b/dom/src/storage/nsDOMStorage.h
@@ -124,16 +124,17 @@ public:
 
   nsresult ClearAllStorages();
 
   bool InPrivateBrowsingMode() { return mInPrivateBrowsing; }
 
   static nsresult Initialize();
   static nsDOMStorageManager* GetInstance();
   static void Shutdown();
+  static void ShutdownDB();
 
   /**
    * Checks whether there is any data waiting to be flushed from a temp table.
    */
   bool UnflushedDataExists();
 
   static nsDOMStorageManager* gStorageManager;
 
--- a/dom/src/storage/nsDOMStorageDBWrapper.cpp
+++ b/dom/src/storage/nsDOMStorageDBWrapper.cpp
@@ -73,16 +73,23 @@ void ReverseString(const nsCSubstring& s
 nsDOMStorageDBWrapper::nsDOMStorageDBWrapper()
 {
 }
 
 nsDOMStorageDBWrapper::~nsDOMStorageDBWrapper()
 {
 }
 
+void
+nsDOMStorageDBWrapper::Close()
+{
+  mPersistentDB.Close();
+  mChromePersistentDB.Close();
+}
+
 nsresult
 nsDOMStorageDBWrapper::Init()
 {
   nsresult rv;
 
   rv = mPersistentDB.Init(NS_LITERAL_STRING("webappsstore.sqlite"));
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/src/storage/nsDOMStorageDBWrapper.h
+++ b/dom/src/storage/nsDOMStorageDBWrapper.h
@@ -84,16 +84,21 @@ class nsSessionStorageEntry;
  * quota key for localStorage at http://foo.bar.com is "moc.rab.". */
 
 class nsDOMStorageDBWrapper
 {
 public:
   nsDOMStorageDBWrapper();
   ~nsDOMStorageDBWrapper();
 
+  /**
+   * Close the connections, finalizing all the cached statements.
+   */
+  void Close();
+
   nsresult
   Init();
 
   /**
    * Retrieve a list of all the keys associated with a particular domain.
    */
   nsresult
   GetAllKeys(DOMStorageImpl* aStorage,
--- a/dom/src/storage/nsDOMStoragePersistentDB.cpp
+++ b/dom/src/storage/nsDOMStoragePersistentDB.cpp
@@ -49,16 +49,18 @@
 #include "mozStorageHelper.h"
 #include "mozIStorageService.h"
 #include "mozIStorageBindingParamsArray.h"
 #include "mozIStorageBindingParams.h"
 #include "mozIStorageValueArray.h"
 #include "mozIStorageFunction.h"
 #include "nsNetUtil.h"
 
+using namespace mozilla;
+
 // Temporary tables for a storage scope will be flushed if found older
 // then this time in seconds since the load
 #define TEMP_TABLE_MAX_AGE (10) // seconds
 
 class nsReverseStringSQLFunction : public mozIStorageFunction
 {
   NS_DECL_ISUPPORTS
   NS_DECL_MOZISTORAGEFUNCTION
@@ -442,16 +444,38 @@ nsDOMStoragePersistentDB::Init(const nsS
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = transaction.Commit();
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
+void
+nsDOMStoragePersistentDB::Close()
+{
+  // Null the statements, this will finalize them.
+  mCopyToTempTableStatement = nsnull;
+  mCopyBackToDiskStatement = nsnull;
+  mDeleteTemporaryTableStatement = nsnull;
+  mGetAllKeysStatement = nsnull;
+  mGetKeyValueStatement = nsnull;
+  mInsertKeyStatement = nsnull;
+  mSetSecureStatement = nsnull;
+  mRemoveKeyStatement = nsnull;
+  mRemoveOwnerStatement = nsnull;
+  mRemoveStorageStatement = nsnull;
+  mRemoveAllStatement = nsnull;
+  mGetOfflineExcludedUsageStatement = nsnull;
+  mGetFullUsageStatement = nsnull;
+
+  DebugOnly<nsresult> rv = mConnection->Close();
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+}
+
 nsresult
 nsDOMStoragePersistentDB::EnsureLoadTemporaryTableForStorage(DOMStorageImpl* aStorage)
 {
   TimeStamp timeStamp;
 
   if (!mTempTableLoads.Get(aStorage->GetScopeDBKey(), &timeStamp)) {
     nsresult rv;
 
--- a/dom/src/storage/nsDOMStoragePersistentDB.h
+++ b/dom/src/storage/nsDOMStoragePersistentDB.h
@@ -58,16 +58,22 @@ class nsDOMStoragePersistentDB : public 
 public:
   nsDOMStoragePersistentDB();
   ~nsDOMStoragePersistentDB() {}
 
   nsresult
   Init(const nsString& aDatabaseName);
 
   /**
+   * Close the connection, finalizing all the cached statements.
+   */
+  void
+  Close();
+
+  /**
    * Retrieve a list of all the keys associated with a particular domain.
    */
   nsresult
   GetAllKeys(DOMStorageImpl* aStorage,
              nsTHashtable<nsSessionStorageEntry>* aKeys);
 
   /**
    * Retrieve a value and secure flag for a key from storage.
@@ -194,16 +200,17 @@ protected:
   nsCOMPtr<mozIStorageStatement> mInsertKeyStatement;
   nsCOMPtr<mozIStorageStatement> mSetSecureStatement;
   nsCOMPtr<mozIStorageStatement> mRemoveKeyStatement;
   nsCOMPtr<mozIStorageStatement> mRemoveOwnerStatement;
   nsCOMPtr<mozIStorageStatement> mRemoveStorageStatement;
   nsCOMPtr<mozIStorageStatement> mRemoveAllStatement;
   nsCOMPtr<mozIStorageStatement> mGetOfflineExcludedUsageStatement;
   nsCOMPtr<mozIStorageStatement> mGetFullUsageStatement;
+  // If you add an statement, remember to null in in Close.
 
   nsCString mCachedOwner;
   PRInt32 mCachedUsage;
 
   // Maps ScopeDBKey to time of the temporary table load for that scope.
   // If a record is present, the temp table has been loaded. If it is not
   // present, the table has not yet been loaded or has alrady been flushed.
   nsDataHashtable<nsCStringHashKey, TimeStamp> mTempTableLoads; 
--- a/dom/system/NetworkGeolocationProvider.js
+++ b/dom/system/NetworkGeolocationProvider.js
@@ -95,20 +95,20 @@ function WifiGeoPositionProvider() {
   try {
     gLoggingEnabled = Services.prefs.getBoolPref("geo.wifi.logging.enabled");
   } catch (e) {}
 
   try {
     gTestingEnabled = Services.prefs.getBoolPref("geo.wifi.testing");
   } catch (e) {}
 
-  wifiService = null;
-  timer = null;
-  hasSeenWiFi = false;
-  started = false;
+  this.wifiService = null;
+  this.timer = null;
+  this.hasSeenWiFi = false;
+  this.started = false;
 }
 
 WifiGeoPositionProvider.prototype = {
   classID:          Components.ID("{77DA64D3-7458-4920-9491-86CC9914F904}"),
   QueryInterface:   XPCOMUtils.generateQI([Ci.nsIGeolocationProvider,
                                            Ci.nsIWifiListener,
                                            Ci.nsITimerCallback]),
   startup:  function() {
--- a/embedding/android/GeckoBatteryManager.java
+++ b/embedding/android/GeckoBatteryManager.java
@@ -50,23 +50,24 @@ import android.os.BatteryManager;
 
 public class GeckoBatteryManager
   extends BroadcastReceiver
 {
   // Those constants should be keep in sync with the ones in:
   // dom/battery/Constants.h
   private final static double  kDefaultLevel         = 1.0;
   private final static boolean kDefaultCharging      = true;
+  private final static double  kDefaultRemainingTime = -1.0;
   private final static double  kUnknownRemainingTime = -1.0;
 
   private static Date    sLastLevelChange            = new Date(0);
   private static boolean sNotificationsEnabled       = false;
   private static double  sLevel                      = kDefaultLevel;
   private static boolean sCharging                   = kDefaultCharging;
-  private static double  sRemainingTime              = kUnknownRemainingTime;;
+  private static double  sRemainingTime              = kDefaultRemainingTime;;
 
   @Override
   public void onReceive(Context context, Intent intent) {
     if (!intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
       Log.e("GeckoBatteryManager", "Got an unexpected intent!");
       return;
     }
 
@@ -130,17 +131,17 @@ public class GeckoBatteryManager
         } else {
           // That's the first time we got an update, we can't do anything.
           sLastLevelChange = new Date();
         }
       }
     } else {
       sLevel = kDefaultLevel;
       sCharging = kDefaultCharging;
-      sRemainingTime = kUnknownRemainingTime;
+      sRemainingTime = kDefaultRemainingTime;
     }
 
     /*
      * We want to inform listeners if the following conditions are fulfilled:
      *  - we have at least one observer;
      *  - the charging state or the level has changed.
      *
      * Note: no need to check for a remaining time change given that it's only
--- a/hal/linux/UPowerClient.cpp
+++ b/hal/linux/UPowerClient.cpp
@@ -194,17 +194,17 @@ UPowerClient::GetInstance()
 }
 
 UPowerClient::UPowerClient()
   : mDBusConnection(nsnull)
   , mUPowerProxy(nsnull)
   , mTrackedDevice(nsnull)
   , mLevel(kDefaultLevel)
   , mCharging(kDefaultCharging)
-  , mRemainingTime(kUnknownRemainingTime)
+  , mRemainingTime(kDefaultRemainingTime)
 {
 }
 
 UPowerClient::~UPowerClient()
 {
   NS_ASSERTION(!mDBusConnection && !mUPowerProxy && !mTrackedDevice,
                "The observers have not been correctly removed! "
                "(StopListening should have been called)");
@@ -274,17 +274,17 @@ UPowerClient::StopListening()
   mUPowerProxy = nsnull;
 
   dbus_g_connection_unref(mDBusConnection);
   mDBusConnection = nsnull;
 
   // We should now show the default values, not the latest we got.
   mLevel = kDefaultLevel;
   mCharging = kDefaultCharging;
-  mRemainingTime = kUnknownRemainingTime;
+  mRemainingTime = kDefaultRemainingTime;
 }
 
 void
 UPowerClient::UpdateTrackedDevice()
 {
   GType typeGPtrArray = dbus_g_type_get_collection("GPtrArray",
                                                    DBUS_TYPE_G_OBJECT_PATH);
   GPtrArray* devices = nsnull;
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2492,18 +2492,18 @@ ia64*-hpux*)
             AC_MSG_ERROR([You are targeting i386 but using the 64-bit compiler.])
         fi
 
         if test $_MSC_VER -ge 1400; then
             LDFLAGS="$LDFLAGS -SAFESEH"
         fi
 
         if test -n "$GNU_CC"; then
-            CFLAGS="$CFLAGS -mstackrealign"
-            CXXFLAGS="$CXXFLAGS -mstackrealign"
+            CFLAGS="$CFLAGS -mstackrealign -fno-keep-inline-dllexport"
+            CXXFLAGS="$CXXFLAGS -mstackrealign -fno-keep-inline-dllexport"
         fi
 
         MOZ_CHECK_HEADERS(mmintrin.h)
     	AC_DEFINE(_X86_)
 	;;
     x86_64-*)
         AC_DEFINE(_AMD64_)
         ;;
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -149,18 +149,16 @@ IsPermitted(const char *name, JSFlatStri
              PROP('m', R("message")))
         NAME('H', "History",
              PROP('b', R("back"))
              PROP('f', R("forward"))
              PROP('g', R("go")))
         NAME('L', "Location",
              PROP('h', W("hash") W("href"))
              PROP('r', R("replace")))
-        NAME('N', "Navigator",
-             PROP('p', RW("preference")))
         NAME('W', "Window",
              PROP('b', R("blur"))
              PROP('c', R("close") R("closed"))
              PROP('f', R("focus") R("frames"))
              PROP('h', R("history"))
              PROP('l', RW("location") R("length"))
              PROP('o', R("opener"))
              PROP('p', R("parent") R("postMessage"))
--- a/layout/Makefile.in
+++ b/layout/Makefile.in
@@ -65,16 +65,17 @@ PARALLEL_DIRS += inspector/public inspec
 ifdef ENABLE_TESTS
 PARALLEL_DIRS += inspector/tests inspector/tests/chrome
 endif
 
 DIRS           += build
 
 ifdef ENABLE_TESTS
 PARALLEL_DIRS += \
+  mathml/tests \
   xul/test \
   xul/base/test \
   $(NULL)
 
 TOOL_DIRS      += tools/reftest reftests/fonts reftests/fonts/mplus
 DIRS           += tools/pageloader
 
 ifdef MOZ_DEBUG
--- a/layout/mathml/nsMathMLmactionFrame.cpp
+++ b/layout/mathml/nsMathMLmactionFrame.cpp
@@ -79,22 +79,22 @@ NS_NewMathMLmactionFrame(nsIPresShell* a
 
 NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmactionFrame)
 
 nsMathMLmactionFrame::~nsMathMLmactionFrame()
 {
   // unregister us as a mouse event listener ...
   //  printf("maction:%p unregistering as mouse event listener ...\n", this);
   if (mListener) {
-    mContent->RemoveEventListener(NS_LITERAL_STRING("click"), mListener,
-                                  false);
-    mContent->RemoveEventListener(NS_LITERAL_STRING("mouseover"), mListener,
-                                  false);
-    mContent->RemoveEventListener(NS_LITERAL_STRING("mouseout"), mListener,
-                                  false);
+    mContent->RemoveSystemEventListener(NS_LITERAL_STRING("click"), mListener,
+                                        false);
+    mContent->RemoveSystemEventListener(NS_LITERAL_STRING("mouseover"), mListener,
+                                        false);
+    mContent->RemoveSystemEventListener(NS_LITERAL_STRING("mouseout"), mListener,
+                                        false);
   }
 }
 
 NS_IMETHODIMP
 nsMathMLmactionFrame::Init(nsIContent*      aContent,
                            nsIFrame*        aParent,
                            nsIFrame*        aPrevInFlow)
 {
@@ -223,22 +223,22 @@ nsMathMLmactionFrame::SetInitialChildLis
   // embellished operator if the selected child is an embellished operator
   if (!GetSelectedFrame()) {
     mActionType = NS_MATHML_ACTION_TYPE_NONE;
   }
   else {
     // create mouse event listener and register it
     mListener = new nsMathMLmactionFrame::MouseListener(this);
     // printf("maction:%p registering as mouse event listener ...\n", this);
-    mContent->AddEventListener(NS_LITERAL_STRING("click"), mListener,
-                               false, false);
-    mContent->AddEventListener(NS_LITERAL_STRING("mouseover"), mListener,
-                               false, false);
-    mContent->AddEventListener(NS_LITERAL_STRING("mouseout"), mListener,
-                               false, false);
+    mContent->AddSystemEventListener(NS_LITERAL_STRING("click"), mListener,
+                                     false, false);
+    mContent->AddSystemEventListener(NS_LITERAL_STRING("mouseover"), mListener,
+                                     false, false);
+    mContent->AddSystemEventListener(NS_LITERAL_STRING("mouseout"), mListener,
+                                     false, false);
   }
   return rv;
 }
 
 //  Only paint the selected child...
 NS_IMETHODIMP
 nsMathMLmactionFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                        const nsRect&           aDirtyRect,
new file mode 100644
--- /dev/null
+++ b/layout/mathml/tests/Makefile.in
@@ -0,0 +1,52 @@
+#
+# ***** 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) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# 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 *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = layout/mathml/tests
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES =\
+	test_bug706406.html \
+	$(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/layout/mathml/tests/test_bug706406.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=706406
+-->
+<head>
+  <title>Test for Bug 706406</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=706406">Mozilla Bug 706406</a>
+<p id="display"></p>
+<math xmlns="http://www.w3.org/1998/Math/MathML">
+  <maction actiontype="toggle" id="maction">
+    <mn>1</mn>
+    <mn>2</mn>
+  </maction>
+</math>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 706406 **/
+
+function doTest()
+{
+  function doStopPropagation(aEvent) {
+    aEvent.stopPropagation();
+  }
+
+  var maction = document.getElementById("maction");
+
+  synthesizeMouseAtCenter(maction, {});
+
+  is(maction.getAttribute("selection"), "2",
+     "maction's selection attribute isn't 2 by first click");
+
+  synthesizeMouseAtCenter(maction, {});
+
+  is(maction.getAttribute("selection"), "1",
+     "maction's selection attribute isn't 1 by second click");
+
+  window.addEventListener("mousedown", doStopPropagation, true);
+  window.addEventListener("mouseup", doStopPropagation, true);
+  window.addEventListener("click", doStopPropagation, true);
+
+  synthesizeMouseAtCenter(maction, {});
+
+  is(maction.getAttribute("selection"), "2",
+     "maction's selection attribute isn't 2 by first click called stopPropagation()");
+
+  synthesizeMouseAtCenter(maction, {});
+
+  is(maction.getAttribute("selection"), "1",
+     "maction's selection attribute isn't 1 by second click called stopPropagation()");
+
+  window.removeEventListener("mousedown", doStopPropagation, true);
+  window.removeEventListener("mouseup", doStopPropagation, true);
+  window.removeEventListener("click", doStopPropagation, true);
+
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(doTest);
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/467444-1-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-print"><head>
+<style>
+div.spacer {
+  height: 5px;
+  width:  10px;
+}
+img, td.spacer {
+  height: 140px;
+  width:  30px;
+}
+</style>
+<title>rowspan pagination</title>
+</head>
+<body>
+ <div class="spacer"> </div>
+ <table>
+  <tbody>
+   <tr><td class="spacer"></td></tr>
+   <tr style="page-break-before:always">
+    <td rowspan="2">
+     <img  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRF/wAAAAAAQaMSAwAAABJJREFUeNpiYBgFo2AwAIAAAwACigABtnCV2AAAAABJRU5ErkJggg==">
+    </td>
+   </tr>
+   <tr></tr>
+  </tbody>
+ </table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/467444-1.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-print"><head>
+<style>
+div.spacer {
+  height: 5px;
+  width:  10px;
+}
+img, td.spacer {
+  height: 140px;
+  width:  30px;
+}
+</style>
+<title>rowspan pagination</title>
+</head>
+<body>
+ <div class="spacer"> </div>
+ <table>
+  <tbody>
+   <tr><td class="spacer"></td></tr>
+   <tr>
+    <td rowspan="2">
+     <img  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRF/wAAAAAAQaMSAwAAABJJREFUeNpiYBgFo2AwAIAAAwACigABtnCV2AAAAABJRU5ErkJggg==">
+    </td>
+   </tr>
+   <tr></tr>
+  </tbody>
+ </table>
+</body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1228,16 +1228,17 @@ fails-if(cocoaWidget) == 456147.xul 4561
 == 463217-1.xul 463217-1-ref.xul
 == 463952-1.html 463952-1-ref.html
 == 464811-1.html 464811-1-ref.html
 == 466258-1.html 466258-1-ref.html
 == 466395-1.html 466395-1-ref.html
 == 466395-2.html 466395-2-ref.html
 == 467084-1.html 467084-1-ref.html
 == 467084-2.html 467084-2-ref.html
+== 467444-1.html 467444-1-ref.html
 == 467460-1.html 467460-1-ref.html
 == 468546-1.xhtml 468546-1-ref.xhtml
 == 468473-1.xul 468473-1-ref.xul
 == 471356-1.html 471356-1-ref.html
 == 471594-1.xhtml 471594-1-ref.html
 == 472020-1a.xul 472020-1-ref.xul
 fails == 472020-1b.xul 472020-1-ref.xul
 fails == 472020-2.xul 472020-2-ref.xul
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -1231,17 +1231,17 @@ nsTableRowGroupFrame::SplitRowGroup(nsPr
           // Try to put firstTruncateRow on the next page 
           nsTableRowFrame* rowBefore = ::GetRowBefore(*firstRowThisPage, *firstTruncatedRow);
           nscoord oldSpanningRowBottom = spanningRowBottom;
           spanningRowBottom = rowBefore->GetRect().YMost();
 
           UndoContinuedRow(aPresContext, contRow);
           contRow = nsnull;
           nsTableRowFrame* oldLastRowThisPage = lastRowThisPage;
-          lastRowThisPage = firstTruncatedRow;
+          lastRowThisPage = rowBefore;
           aStatus = NS_FRAME_NOT_COMPLETE;
 
           // Call SplitSpanningCells again with rowBefore as the last row on the page
           SplitSpanningCells(*aPresContext, aReflowState, *aTableFrame, 
                              *firstRowThisPage, *rowBefore, aReflowState.mFlags.mIsTopOfPage, 
                              spanningRowBottom, contRow, firstTruncatedRow, aDesiredSize.height);
           if (firstTruncatedRow) {
             if (aReflowState.mFlags.mIsTopOfPage) {
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -413,20 +413,16 @@ pref("capability.policy.default.History.
 pref("capability.policy.default.History.next", "UniversalBrowserRead");
 pref("capability.policy.default.History.previous", "UniversalBrowserRead");
 pref("capability.policy.default.History.toString", "UniversalBrowserRead");
 
 pref("capability.policy.default.Location.hash.set", "allAccess");
 pref("capability.policy.default.Location.href.set", "allAccess");
 pref("capability.policy.default.Location.replace.get", "allAccess");
 
-pref("capability.policy.default.Navigator.preference", "allAccess");
-pref("capability.policy.default.Navigator.preferenceinternal.get", "UniversalPreferencesRead");
-pref("capability.policy.default.Navigator.preferenceinternal.set", "UniversalPreferencesWrite");
-
 pref("capability.policy.default.Window.blur.get", "allAccess");
 pref("capability.policy.default.Window.close.get", "allAccess");
 pref("capability.policy.default.Window.closed.get", "allAccess");
 pref("capability.policy.default.Window.focus.get", "allAccess");
 pref("capability.policy.default.Window.frames.get", "allAccess");
 pref("capability.policy.default.Window.history.get", "allAccess");
 pref("capability.policy.default.Window.length.get", "allAccess");
 pref("capability.policy.default.Window.location", "allAccess");
--- a/netwerk/protocol/http/nsAHttpConnection.h
+++ b/netwerk/protocol/http/nsAHttpConnection.h
@@ -119,16 +119,20 @@ public:
     // Used by a transaction to manage the state of previous response bodies on
     // the same connection and work around buggy servers.
     virtual bool LastTransactionExpectedNoContent() = 0;
     virtual void   SetLastTransactionExpectedNoContent(bool) = 0;
 
     // Transfer the base http connection object along with a
     // reference to it to the caller.
     virtual nsHttpConnection *TakeHttpConnection() = 0;
+
+    // Get the nsISocketTransport used by the connection without changing
+    //  references or ownership.
+    virtual nsISocketTransport *Transport() = 0;
 };
 
 #define NS_DECL_NSAHTTPCONNECTION \
     nsresult OnHeadersAvailable(nsAHttpTransaction *, nsHttpRequestHead *, nsHttpResponseHead *, bool *reset); \
     nsresult ResumeSend(); \
     nsresult ResumeRecv(); \
     void CloseTransaction(nsAHttpTransaction *, nsresult); \
     void GetConnectionInfo(nsHttpConnectionInfo **); \
@@ -136,11 +140,12 @@ public:
                            nsIAsyncInputStream **,   \
                            nsIAsyncOutputStream **); \
     void GetSecurityInfo(nsISupports **); \
     bool IsPersistent(); \
     bool IsReused(); \
     nsresult PushBack(const char *, PRUint32); \
     bool LastTransactionExpectedNoContent(); \
     void   SetLastTransactionExpectedNoContent(bool); \
-    nsHttpConnection *TakeHttpConnection();
+    nsHttpConnection *TakeHttpConnection(); \
+    nsISocketTransport *Transport();
 
 #endif // nsAHttpConnection_h__
--- a/netwerk/protocol/http/nsHttpConnection.h
+++ b/netwerk/protocol/http/nsHttpConnection.h
@@ -118,16 +118,17 @@ public:
         return mLastTransactionExpectedNoContent;
     }
 
     void     SetLastTransactionExpectedNoContent(bool val)
     {
         mLastTransactionExpectedNoContent = val;
     }
 
+    nsISocketTransport   *Transport()      { return mSocketTransport; }
     nsAHttpTransaction   *Transaction()    { return mTransaction; }
     nsHttpConnectionInfo *ConnectionInfo() { return mConnInfo; }
 
     // nsAHttpConnection compatible methods (non-virtual):
     nsresult OnHeadersAvailable(nsAHttpTransaction *, nsHttpRequestHead *, nsHttpResponseHead *, bool *reset);
     void     CloseTransaction(nsAHttpTransaction *, nsresult reason);
     void     GetConnectionInfo(nsHttpConnectionInfo **ci) { NS_IF_ADDREF(*ci = mConnInfo); }
     nsresult TakeTransport(nsISocketTransport **,
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -1688,8 +1688,16 @@ nsHttpConnectionMgr::nsConnectionHandle:
 }
 
 void
 nsHttpConnectionMgr::
 nsConnectionHandle::SetLastTransactionExpectedNoContent(bool val)
 {
      mConn->SetLastTransactionExpectedNoContent(val);
 }
+
+nsISocketTransport *
+nsHttpConnectionMgr::nsConnectionHandle::Transport()
+{
+    if (!mConn)
+        return nsnull;
+    return mConn->Transport();
+}
--- a/netwerk/protocol/http/nsHttpPipeline.cpp
+++ b/netwerk/protocol/http/nsHttpPipeline.cpp
@@ -96,16 +96,19 @@ nsHttpPipeline::nsHttpPipeline()
     : mConnection(nsnull)
     , mStatus(NS_OK)
     , mRequestIsPartial(false)
     , mResponseIsPartial(false)
     , mClosed(false)
     , mPushBackBuf(nsnull)
     , mPushBackLen(0)
     , mPushBackMax(0)
+    , mReceivingFromProgress(0)
+    , mSendingToProgress(0)
+    , mSuppressSendEvents(true)
 {
 }
 
 nsHttpPipeline::~nsHttpPipeline()
 {
     // make sure we aren't still holding onto any transactions!
     Close(NS_ERROR_ABORT);
 
@@ -320,16 +323,24 @@ nsHttpPipeline::SetLastTransactionExpect
 nsHttpConnection *
 nsHttpPipeline::TakeHttpConnection()
 {
     if (mConnection)
         return mConnection->TakeHttpConnection();
     return nsnull;
 }
 
+nsISocketTransport *
+nsHttpPipeline::Transport()
+{
+    if (!mConnection)
+        return nsnull;
+    return mConnection->Transport();
+}
+
 void
 nsHttpPipeline::SetSSLConnectFailed()
 {
     nsAHttpTransaction *trans = Request(0);
 
     if (trans)
         trans->SetSSLConnectFailed();
 }
@@ -385,31 +396,90 @@ nsHttpPipeline::OnTransportStatus(nsITra
                                   nsresult status, PRUint64 progress)
 {
     LOG(("nsHttpPipeline::OnStatus [this=%x status=%x progress=%llu]\n",
         this, status, progress));
 
     NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
     nsAHttpTransaction *trans;
+    PRInt32 i, count;
+
     switch (status) {
-    case NS_NET_STATUS_RECEIVING_FROM:
-        // forward this only to the transaction currently recieving data
-        trans = Response(0);
+
+    case NS_NET_STATUS_RESOLVING_HOST:
+    case NS_NET_STATUS_RESOLVED_HOST:
+    case NS_NET_STATUS_CONNECTING_TO:
+    case NS_NET_STATUS_CONNECTED_TO:
+        // These should only appear at most once per pipeline.
+        // Deliver to the first transaction.
+
+        trans = Request(0);
+        if (!trans)
+            trans = Response(0);
         if (trans)
             trans->OnTransportStatus(transport, status, progress);
+
         break;
+
+    case NS_NET_STATUS_SENDING_TO:
+        // This is generated by the socket transport when (part) of
+        // a transaction is written out
+        //
+        // In pipelining this is generated out of FillSendBuf(), but it cannot do
+        // so until the connection is confirmed by CONNECTED_TO.
+        // See patch for bug 196827.
+        //
+
+        if (mSuppressSendEvents) {
+            mSuppressSendEvents = false;
+            
+            // catch up by sending the event to all the transactions that have
+            // moved from request to response and any that have been partially
+            // sent. Also send WAITING_FOR to those that were completely sent
+            count = mResponseQ.Length();
+            for (i = 0; i < count; ++i) {
+                Response(i)->OnTransportStatus(transport,
+                                               NS_NET_STATUS_SENDING_TO,
+                                               progress);
+                Response(i)->OnTransportStatus(transport, 
+                                               NS_NET_STATUS_WAITING_FOR,
+                                               progress);
+            }
+            if (mRequestIsPartial && Request(0))
+                Request(0)->OnTransportStatus(transport,
+                                              NS_NET_STATUS_SENDING_TO,
+                                              progress);
+            mSendingToProgress = progress;
+        }
+        // otherwise ignore it
+        break;
+        
+    case NS_NET_STATUS_WAITING_FOR: 
+        // Created by nsHttpConnection when request pipeline has been totally
+        // sent. Ignore it here because it is simulated in FillSendBuf() when
+        // a request is moved from request to response.
+        
+        // ignore it
+        break;
+
+    case NS_NET_STATUS_RECEIVING_FROM:
+        // Forward this only to the transaction currently recieving data. It is
+        // normally generated by the socket transport, but can also
+        // be repeated by the pushbackwriter if necessary.
+        mReceivingFromProgress = progress;
+        if (Response(0))
+            Response(0)->OnTransportStatus(transport, status, progress);
+        break;
+
     default:
-        // forward other notifications to all transactions
-        PRInt32 i, count = mRequestQ.Length();
-        for (i=0; i<count; ++i) {
-            trans = Request(i);
-            if (trans)
-                trans->OnTransportStatus(transport, status, progress);
-        }
+        // forward other notifications to all request transactions
+        count = mRequestQ.Length();
+        for (i = 0; i < count; ++i)
+            Request(i)->OnTransportStatus(transport, status, progress);
         break;
     }
 }
 
 bool
 nsHttpPipeline::IsDone()
 {
     bool done = true;
@@ -543,16 +613,26 @@ nsHttpPipeline::WriteSegments(nsAHttpSeg
         else
             mResponseIsPartial = true;
     }
 
     if (mPushBackLen) {
         nsHttpPushBackWriter writer(mPushBackBuf, mPushBackLen);
         PRUint32 len = mPushBackLen, n;
         mPushBackLen = 0;
+
+        // This progress notification has previously been sent from
+        // the socket transport code, but it was delivered to the
+        // previous transaction on the pipeline.
+        nsITransport *transport = Transport();
+        if (transport)
+            OnTransportStatus(transport,
+                              nsISocketTransport::STATUS_RECEIVING_FROM,
+                              mReceivingFromProgress);
+
         // the push back buffer is never larger than NS_HTTP_SEGMENT_SIZE,
         // so we are guaranteed that the next response will eat the entire
         // push back buffer (even though it might again call PushBack).
         rv = WriteSegments(&writer, len, &n);
     }
 
     return rv;
 }
@@ -633,31 +713,49 @@ nsHttpPipeline::FillSendBuf()
                         nsIOService::gDefaultSegmentSize,  /* max size */
                         true, true,
                         nsIOService::gBufferCache);
         if (NS_FAILED(rv)) return rv;
     }
 
     PRUint32 n, avail;
     nsAHttpTransaction *trans;
+    nsITransport *transport = Transport();
+
     while ((trans = Request(0)) != nsnull) {
         avail = trans->Available();
         if (avail) {
             rv = trans->ReadSegments(this, avail, &n);
             if (NS_FAILED(rv)) return rv;
             
             if (n == 0) {
                 LOG(("send pipe is full"));
                 break;
             }
+
+            mSendingToProgress += n;
+            if (!mSuppressSendEvents && transport) {
+                // Simulate a SENDING_TO event
+                trans->OnTransportStatus(transport,
+                                         NS_NET_STATUS_SENDING_TO,
+                                         mSendingToProgress);
+            }
         }
+
         avail = trans->Available();
         if (avail == 0) {
             // move transaction from request queue to response queue
             mRequestQ.RemoveElementAt(0);
             mResponseQ.AppendElement(trans);
             mRequestIsPartial = false;
+
+            if (!mSuppressSendEvents && transport) {
+                // Simulate a WAITING_FOR event
+                trans->OnTransportStatus(transport,
+                                         NS_NET_STATUS_WAITING_FOR,
+                                         mSendingToProgress);
+            }
         }
         else
             mRequestIsPartial = true;
     }
     return NS_OK;
 }
--- a/netwerk/protocol/http/nsHttpPipeline.h
+++ b/netwerk/protocol/http/nsHttpPipeline.h
@@ -106,11 +106,16 @@ private:
     // send buffer
     nsCOMPtr<nsIInputStream>  mSendBufIn;
     nsCOMPtr<nsIOutputStream> mSendBufOut;
 
     // the push back buffer.  not exceeding nsIOService::gDefaultSegmentSize bytes.
     char     *mPushBackBuf;
     PRUint32  mPushBackLen;
     PRUint32  mPushBackMax;
+
+    // For support of OnTransportStatus()
+    PRUint64  mReceivingFromProgress;
+    PRUint64  mSendingToProgress;
+    bool      mSuppressSendEvents;
 };
 
 #endif // nsHttpPipeline_h__
--- a/toolkit/toolkit-makefiles.sh
+++ b/toolkit/toolkit-makefiles.sh
@@ -819,16 +819,17 @@ if [ "$ENABLE_TESTS" ]; then
     js/xpconnect/tests/idl/Makefile
     js/xpconnect/tests/mochitest/Makefile
     layout/base/tests/Makefile
     layout/base/tests/chrome/Makefile
     layout/forms/test/Makefile
     layout/generic/test/Makefile
     layout/inspector/tests/Makefile
     layout/inspector/tests/chrome/Makefile
+    layout/mathml/tests/Makefile
     layout/reftests/fonts/Makefile
     layout/reftests/fonts/mplus/Makefile
     layout/style/test/Makefile
     layout/style/test/chrome/Makefile
     layout/tables/test/Makefile
     layout/tools/pageloader/Makefile
     layout/tools/reftest/Makefile
     layout/xul/base/test/Makefile
--- a/tools/profiler/Makefile.in
+++ b/tools/profiler/Makefile.in
@@ -77,15 +77,15 @@ EXTRA_JS_MODULES = \
   Profiler.jsm \
   $(NULL)
 
 ifeq ($(OS_TARGET),Android)
 
 DEFINES += -DMOZ_ENABLE_PROFILER_SPS
 
 CPPSRCS += \
-  platform.cc \
+  platform-linux.cc \
   TableTicker.cpp \
   $(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/tools/profiler/sps/platform-linux.cc
@@ -0,0 +1,322 @@
+// Copyright (c) 2006-2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*
+# vim: sw=2
+*/
+#include <stdio.h>
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#ifdef ANDROID
+#include <android/log.h>
+#else
+#define __android_log_print(a, ...)
+#endif
+// Ubuntu Dapper requires memory pages to be marked as
+// executable. Otherwise, OS raises an exception when executing code
+// in that page.
+#include <sys/types.h>  // mmap & munmap
+#include <sys/mman.h>   // mmap & munmap
+#include <sys/stat.h>   // open
+#include <fcntl.h>      // open
+#include <unistd.h>     // sysconf
+#ifdef __GLIBC__
+#include <execinfo.h>   // backtrace, backtrace_symbols
+#endif  // def __GLIBC__
+#include <strings.h>    // index
+#include <errno.h>
+#include <stdarg.h>
+#include "v8-support.h"
+#include "platform.h"
+
+#include <string.h>
+#include <stdio.h>
+
+// Real time signals are not supported on android.
+// This behaves as a standard signal.
+#define SIGNAL_SAVE_PROFILE 42
+
+#define PATH_MAX_TOSTRING(x) #x
+#define PATH_MAX_STRING(x) PATH_MAX_TOSTRING(x)
+
+#ifdef ENABLE_SPS_LEAF_DATA
+/* a crapy version of getline, because it's not included in bionic */
+static ssize_t getline(char **lineptr, size_t *n, FILE *stream)
+{
+ char *ret;
+ if (!*lineptr) {
+   *lineptr = (char*)malloc(4096);
+ }
+ ret = fgets(*lineptr, 4096, stream);
+ if (!ret)
+   return 0;
+ return strlen(*lineptr);
+}
+
+MapInfo getmaps(pid_t pid)
+{
+ MapInfo info;
+ char path[PATH_MAX];
+ snprintf(path, PATH_MAX, "/proc/%d/maps", pid);
+ FILE *maps = fopen(path, "r");
+ char *line = NULL;
+ int count = 0;
+ size_t line_size = 0;
+ while (maps && getline (&line, &line_size, maps) > 0) {
+   int ret;
+   //XXX: needs input sanitizing
+   unsigned long start;
+   unsigned long end;
+   char perm[6] = "";
+   unsigned long offset;
+   char name[PATH_MAX] = "";
+   ret = sscanf(line,
+                "%lx-%lx %6s %lx %*s %*x %" PATH_MAX_STRING(PATH_MAX) "s\n",
+                &start, &end, perm, &offset, name);
+   if (!strchr(perm, 'x')) {
+     // Ignore non executable entries
+     continue;
+   }
+   if (ret != 5 && ret != 4) {
+     LOG("Get maps line failed");
+     continue;
+   }
+   MapEntry entry(start, end, offset, name);
+   info.AddMapEntry(entry);
+   if (count > 10000) {
+     LOG("Get maps failed");
+     break;
+   }
+   count++;
+ }
+ free(line);
+ return info;
+}
+#endif
+
+static Sampler* sActiveSampler = NULL;
+
+
+#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
+// Android runs a fairly new Linux kernel, so signal info is there,
+// but the C library doesn't have the structs defined.
+
+struct sigcontext {
+  uint32_t trap_no;
+  uint32_t error_code;
+  uint32_t oldmask;
+  uint32_t gregs[16];
+  uint32_t arm_cpsr;
+  uint32_t fault_address;
+};
+typedef uint32_t __sigset_t;
+typedef struct sigcontext mcontext_t;
+typedef struct ucontext {
+  uint32_t uc_flags;
+  struct ucontext* uc_link;
+  stack_t uc_stack;
+  mcontext_t uc_mcontext;
+  __sigset_t uc_sigmask;
+} ucontext_t;
+enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11};
+
+#endif
+
+static void ProfilerSaveSignalHandler(int signal, siginfo_t* info, void* context) {
+  sActiveSampler->RequestSave();
+}
+
+#ifdef ANDROID
+#define V8_HOST_ARCH_ARM 1
+#define SYS_gettid __NR_gettid
+#define SYS_tgkill __NR_tgkill
+#else
+#define V8_HOST_ARCH_X64 1
+#endif
+static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
+  if (!sActiveSampler)
+    return;
+
+#ifndef ENABLE_SPS_LEAF_DATA
+  TickSample* sample = NULL;
+#else
+  TickSample sample_obj;
+  TickSample* sample = &sample_obj;
+
+  // If profiling, we extract the current pc and sp.
+  if (sActiveSampler->IsProfiling()) {
+    // Extracting the sample from the context is extremely machine dependent.
+    ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
+    mcontext_t& mcontext = ucontext->uc_mcontext;
+#if V8_HOST_ARCH_IA32
+    sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
+    sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
+    sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
+#elif V8_HOST_ARCH_X64
+    sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
+    sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
+    sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
+#elif V8_HOST_ARCH_ARM
+// An undefined macro evaluates to 0, so this applies to Android's Bionic also.
+#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
+    sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
+    sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
+    sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
+#else
+    sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
+    sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
+    sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
+#endif
+#elif V8_HOST_ARCH_MIPS
+    // Implement this on MIPS.
+    UNIMPLEMENTED();
+#endif
+  }
+#endif
+  sActiveSampler->Tick(sample);
+}
+
+void tgkill(pid_t tgid, pid_t tid, int signalno) {
+  syscall(SYS_tgkill, tgid, tid, signalno);
+}
+
+class Sampler::PlatformData : public Malloced {
+ public:
+  explicit PlatformData(Sampler* sampler)
+      : sampler_(sampler),
+        signal_handler_installed_(false),
+        vm_tgid_(getpid()),
+        // Glibc doesn't provide a wrapper for gettid(2).
+        vm_tid_(gettid()),
+        signal_sender_launched_(false) {
+  }
+
+  void SignalSender() {
+    while (sampler_->IsActive()) {
+      sampler_->HandleSaveRequest();
+
+      // Glibc doesn't provide a wrapper for tgkill(2).
+      tgkill(vm_tgid_, vm_tid_, SIGPROF);
+      // Convert ms to us and subtract 100 us to compensate delays
+      // occuring during signal delivery.
+
+      // TODO measure and confirm this.
+      const useconds_t interval = sampler_->interval_ * 1000 - 100;
+      //int result = usleep(interval);
+      usleep(interval);
+      // sometimes usleep is defined as returning void
+      int result = 0;
+#ifdef DEBUG
+      if (result != 0 && errno != EINTR) {
+        LOG("SignalSender usleep error");
+        ASSERT(result == 0 || errno == EINTR);
+      }
+#endif
+      mozilla::unused << result;
+    }
+  }
+
+  Sampler* sampler_;
+  bool signal_handler_installed_;
+  struct sigaction old_sigprof_signal_handler_;
+  struct sigaction old_sigsave_signal_handler_;
+  pid_t vm_tgid_;
+  pid_t vm_tid_;
+  bool signal_sender_launched_;
+  pthread_t signal_sender_thread_;
+};
+
+
+static void* SenderEntry(void* arg) {
+  Sampler::PlatformData* data =
+      reinterpret_cast<Sampler::PlatformData*>(arg);
+  data->SignalSender();
+  return 0;
+}
+
+
+Sampler::Sampler(int interval, bool profiling)
+    : interval_(interval),
+      profiling_(profiling),
+      synchronous_(profiling),
+      active_(false) {
+  data_ = new PlatformData(this);
+}
+
+Sampler::~Sampler() {
+  ASSERT(!data_->signal_sender_launched_);
+  delete data_;
+}
+
+
+void Sampler::Start() {
+  LOG("Sampler Started");
+  if (sActiveSampler != NULL) return;
+
+  // Request profiling signals.
+  LOG("Request signal");
+  struct sigaction sa;
+  sa.sa_sigaction = ProfilerSignalHandler;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = SA_RESTART | SA_SIGINFO;
+  if (sigaction(SIGPROF, &sa, &data_->old_sigprof_signal_handler_) != 0) {
+    LOG("Error installing signal");
+    return;
+  }
+
+  // Request save profile signals
+  struct sigaction sa2;
+  sa2.sa_sigaction = ProfilerSaveSignalHandler;
+  sigemptyset(&sa2.sa_mask);
+  sa2.sa_flags = SA_RESTART | SA_SIGINFO;
+  if (sigaction(SIGNAL_SAVE_PROFILE, &sa2, &data_->old_sigsave_signal_handler_) != 0) {
+    LOG("Error installing start signal");
+    return;
+  }
+  LOG("Signal installed");
+  data_->signal_handler_installed_ = true;
+
+  // Start a thread that sends SIGPROF signal to VM thread.
+  // Sending the signal ourselves instead of relying on itimer provides
+  // much better accuracy.
+  active_ = true;
+  if (pthread_create(
+          &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
+    data_->signal_sender_launched_ = true;
+  }
+  LOG("Profiler thread started");
+
+  // Set this sampler as the active sampler.
+  sActiveSampler = this;
+}
+
+
+void Sampler::Stop() {
+  active_ = false;
+
+  // Wait for signal sender termination (it will exit after setting
+  // active_ to false).
+  if (data_->signal_sender_launched_) {
+    pthread_join(data_->signal_sender_thread_, NULL);
+    data_->signal_sender_launched_ = false;
+  }
+
+  // Restore old signal handler
+  if (data_->signal_handler_installed_) {
+    sigaction(SIGPROF, &data_->old_sigsave_signal_handler_, 0);
+    sigaction(SIGPROF, &data_->old_sigprof_signal_handler_, 0);
+    data_->signal_handler_installed_ = false;
+  }
+
+  // This sampler is no longer the active sampler.
+  sActiveSampler = NULL;
+}
+
deleted file mode 100644
--- a/tools/profiler/sps/platform.cc
+++ /dev/null
@@ -1,322 +0,0 @@
-// Copyright (c) 2006-2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/*
-# vim: sw=2
-*/
-#include <stdio.h>
-
-#include <pthread.h>
-#include <semaphore.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#ifdef ANDROID
-#include <android/log.h>
-#else
-#define __android_log_print(a, ...)
-#endif
-// Ubuntu Dapper requires memory pages to be marked as
-// executable. Otherwise, OS raises an exception when executing code
-// in that page.
-#include <sys/types.h>  // mmap & munmap
-#include <sys/mman.h>   // mmap & munmap
-#include <sys/stat.h>   // open
-#include <fcntl.h>      // open
-#include <unistd.h>     // sysconf
-#ifdef __GLIBC__
-#include <execinfo.h>   // backtrace, backtrace_symbols
-#endif  // def __GLIBC__
-#include <strings.h>    // index
-#include <errno.h>
-#include <stdarg.h>
-#include "platform.h"
-
-#include <string.h>
-#include <stdio.h>
-
-// Real time signals are not supported on android.
-// This behaves as a standard signal.
-#define SIGNAL_SAVE_PROFILE 42
-
-#define PATH_MAX_TOSTRING(x) #x
-#define PATH_MAX_STRING(x) PATH_MAX_TOSTRING(x)
-
-#ifdef ENABLE_SPS_LEAF_DATA
-/* a crapy version of getline, because it's not included in bionic */
-static ssize_t getline(char **lineptr, size_t *n, FILE *stream)
-{
- char *ret;
- if (!*lineptr) {
-   *lineptr = (char*)malloc(4096);
- }
- ret = fgets(*lineptr, 4096, stream);
- if (!ret)
-   return 0;
- return strlen(*lineptr);
-}
-
-MapInfo getmaps(pid_t pid)
-{
- MapInfo info;
- char path[PATH_MAX];
- snprintf(path, PATH_MAX, "/proc/%d/maps", pid);
- FILE *maps = fopen(path, "r");
- char *line = NULL;
- int count = 0;
- size_t line_size = 0;
- while (maps && getline (&line, &line_size, maps) > 0) {
-   int ret;
-   //XXX: needs input sanitizing
-   unsigned long start;
-   unsigned long end;
-   char perm[6] = "";
-   unsigned long offset;
-   char name[PATH_MAX] = "";
-   ret = sscanf(line,
-                "%lx-%lx %6s %lx %*s %*x %" PATH_MAX_STRING(PATH_MAX) "s\n",
-                &start, &end, perm, &offset, name);
-   if (!strchr(perm, 'x')) {
-     // Ignore non executable entries
-     continue;
-   }
-   if (ret != 5 && ret != 4) {
-     LOG("Get maps line failed");
-     continue;
-   }
-   MapEntry entry(start, end, offset, name);
-   info.AddMapEntry(entry);
-   if (count > 10000) {
-     LOG("Get maps failed");
-     break;
-   }
-   count++;
- }
- free(line);
- return info;
-}
-#endif
-
-static Sampler* sActiveSampler = NULL;
-
-
-#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
-// Android runs a fairly new Linux kernel, so signal info is there,
-// but the C library doesn't have the structs defined.
-
-struct sigcontext {
-  uint32_t trap_no;
-  uint32_t error_code;
-  uint32_t oldmask;
-  uint32_t gregs[16];
-  uint32_t arm_cpsr;
-  uint32_t fault_address;
-};
-typedef uint32_t __sigset_t;
-typedef struct sigcontext mcontext_t;
-typedef struct ucontext {
-  uint32_t uc_flags;
-  struct ucontext* uc_link;
-  stack_t uc_stack;
-  mcontext_t uc_mcontext;
-  __sigset_t uc_sigmask;
-} ucontext_t;
-enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11};
-
-#endif
-
-static void ProfilerSaveSignalHandler(int signal, siginfo_t* info, void* context) {
-  sActiveSampler->RequestSave();
-}
-
-#ifdef ANDROID
-#define V8_HOST_ARCH_ARM 1
-#define SYS_gettid __NR_gettid
-#define SYS_tgkill __NR_tgkill
-#else
-#define V8_HOST_ARCH_X64 1
-#endif
-static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
-  if (!sActiveSampler)
-    return;
-
-#ifndef ENABLE_SPS_LEAF_DATA
-  TickSample* sample = NULL;
-#else
-  TickSample sample_obj;
-  TickSample* sample = &sample_obj;
-
-  // If profiling, we extract the current pc and sp.
-  if (sActiveSampler->IsProfiling()) {
-    // Extracting the sample from the context is extremely machine dependent.
-    ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
-    mcontext_t& mcontext = ucontext->uc_mcontext;
-#if V8_HOST_ARCH_IA32
-    sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
-    sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
-    sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
-#elif V8_HOST_ARCH_X64
-    sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
-    sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
-    sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
-#elif V8_HOST_ARCH_ARM
-// An undefined macro evaluates to 0, so this applies to Android's Bionic also.
-#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
-    sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
-    sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
-    sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
-#else
-    sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
-    sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
-    sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
-#endif
-#elif V8_HOST_ARCH_MIPS
-    // Implement this on MIPS.
-    UNIMPLEMENTED();
-#endif
-  }
-#endif
-  sActiveSampler->Tick(sample);
-}
-
-void tgkill(pid_t tgid, pid_t tid, int signalno) {
-  syscall(SYS_tgkill, tgid, tid, signalno);
-}
-
-//class Sampler::PlatformData : public Malloced {
-class Sampler::PlatformData {
- public:
-  explicit PlatformData(Sampler* sampler)
-      : sampler_(sampler),
-        signal_handler_installed_(false),
-        vm_tgid_(getpid()),
-        // Glibc doesn't provide a wrapper for gettid(2).
-        vm_tid_(gettid()),
-        signal_sender_launched_(false) {
-  }
-
-  void SignalSender() {
-    while (sampler_->IsActive()) {
-      sampler_->HandleSaveRequest();
-
-      // Glibc doesn't provide a wrapper for tgkill(2).
-      tgkill(vm_tgid_, vm_tid_, SIGPROF);
-      // Convert ms to us and subtract 100 us to compensate delays
-      // occuring during signal delivery.
-
-      // TODO measure and confirm this.
-      const useconds_t interval = sampler_->interval_ * 1000 - 100;
-      //int result = usleep(interval);
-      usleep(interval);
-      // sometimes usleep is defined as returning void
-      int result = 0;
-#ifdef DEBUG
-      if (result != 0 && errno != EINTR) {
-        LOG("SignalSender usleep error");
-        ASSERT(result == 0 || errno == EINTR);
-      }
-#endif
-      mozilla::unused << result;
-    }
-  }
-
-  Sampler* sampler_;
-  bool signal_handler_installed_;
-  struct sigaction old_sigprof_signal_handler_;
-  struct sigaction old_sigsave_signal_handler_;
-  pid_t vm_tgid_;
-  pid_t vm_tid_;
-  bool signal_sender_launched_;
-  pthread_t signal_sender_thread_;
-};
-
-
-static void* SenderEntry(void* arg) {
-  Sampler::PlatformData* data =
-      reinterpret_cast<Sampler::PlatformData*>(arg);
-  data->SignalSender();
-  return 0;
-}
-
-
-Sampler::Sampler(int interval, bool profiling)
-    : interval_(interval),
-      profiling_(profiling),
-      synchronous_(profiling),
-      active_(false) {
-  data_ = new PlatformData(this);
-}
-
-Sampler::~Sampler() {
-  ASSERT(!data_->signal_sender_launched_);
-  delete data_;
-}
-
-
-void Sampler::Start() {
-  LOG("Sampler Started");
-  if (sActiveSampler != NULL) return;
-
-  // Request profiling signals.
-  LOG("Request signal");
-  struct sigaction sa;
-  sa.sa_sigaction = ProfilerSignalHandler;
-  sigemptyset(&sa.sa_mask);
-  sa.sa_flags = SA_RESTART | SA_SIGINFO;
-  if (sigaction(SIGPROF, &sa, &data_->old_sigprof_signal_handler_) != 0) {
-    LOG("Error installing signal");
-    return;
-  }
-
-  // Request save profile signals
-  struct sigaction sa2;
-  sa2.sa_sigaction = ProfilerSaveSignalHandler;
-  sigemptyset(&sa2.sa_mask);
-  sa2.sa_flags = SA_RESTART | SA_SIGINFO;
-  if (sigaction(SIGNAL_SAVE_PROFILE, &sa2, &data_->old_sigsave_signal_handler_) != 0) {
-    LOG("Error installing start signal");
-    return;
-  }
-  LOG("Signal installed");
-  data_->signal_handler_installed_ = true;
-
-  // Start a thread that sends SIGPROF signal to VM thread.
-  // Sending the signal ourselves instead of relying on itimer provides
-  // much better accuracy.
-  active_ = true;
-  if (pthread_create(
-          &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
-    data_->signal_sender_launched_ = true;
-  }
-  LOG("Profiler thread started");
-
-  // Set this sampler as the active sampler.
-  sActiveSampler = this;
-}
-
-
-void Sampler::Stop() {
-  active_ = false;
-
-  // Wait for signal sender termination (it will exit after setting
-  // active_ to false).
-  if (data_->signal_sender_launched_) {
-    pthread_join(data_->signal_sender_thread_, NULL);
-    data_->signal_sender_launched_ = false;
-  }
-
-  // Restore old signal handler
-  if (data_->signal_handler_installed_) {
-    sigaction(SIGPROF, &data_->old_sigsave_signal_handler_, 0);
-    sigaction(SIGPROF, &data_->old_sigprof_signal_handler_, 0);
-    data_->signal_handler_installed_ = false;
-  }
-
-  // This sampler is no longer the active sampler.
-  sActiveSampler = NULL;
-}
-
--- a/tools/profiler/sps/sps_sampler.h
+++ b/tools/profiler/sps/sps_sampler.h
@@ -54,17 +54,17 @@ extern pthread_key_t pkey_ticker;
 //                  we need to make stores are not re-ordered by the compiler
 //                  or hardware to make sure the profile is consistent at
 //                  every point the signal can fire.
 #ifdef ARCH_CPU_ARM_FAMILY
 // TODO Is there something cheaper that will prevent
 //      memory stores from being reordered
 // Uses: pLinuxKernelMemoryBarrier
 # define STORE_SEQUENCER() base::subtle::MemoryBarrier();
-#elif ARCH_CPU_ARM_FAMILY
+#elif ARCH_CPU_X86_FAMILY
 # define STORE_SEQUENCER() asm volatile("" ::: "memory");
 #else
 # error "Memory clobber not supported for your platform."
 #endif
 
 // Returns a handdle to pass on exit. This can check that we are popping the
 // correct callstack.
 inline void* mozilla_sampler_call_enter(const char *aInfo);
new file mode 100644
--- /dev/null
+++ b/tools/profiler/sps/v8-support.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** 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) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jeff Muizelaar <jmuizelaar@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 ***** */
+
+/* This contains stubs and infrastructure to support code from v8 */
+
+class Malloced {
+};
--- a/widget/src/cocoa/nsAppShell.mm
+++ b/widget/src/cocoa/nsAppShell.mm
@@ -178,26 +178,40 @@ bool nsCocoaAppModalWindowList::GeckoMod
 //
 // Subclass of NSApplication for filtering out certain events.
 @interface GeckoNSApplication : NSApplication
 {
 }
 @end
 
 @implementation GeckoNSApplication
+
 - (void)sendEvent:(NSEvent *)anEvent
 {
   mozilla::HangMonitor::NotifyActivity();
   if ([anEvent type] == NSApplicationDefined &&
       [anEvent subtype] == kEventSubtypeTrace) {
     mozilla::SignalTracerThread();
     return;
   }
   [super sendEvent:anEvent];
 }
+
+- (NSEvent*)nextEventMatchingMask:(NSUInteger)mask
+                        untilDate:(NSDate*)expiration
+                           inMode:(NSString*)mode
+                          dequeue:(BOOL)flag
+{
+  if (expiration) {
+    mozilla::HangMonitor::Suspend();
+  }
+  return [super nextEventMatchingMask:mask
+          untilDate:expiration inMode:mode dequeue:flag];
+}
+
 @end
 
 
 // AppShellDelegate
 //
 // Cocoa bridge class.  An object of this class is registered to receive
 // notifications.
 //