Merge m-c to tracemonkey.
authorRobert Sayre <sayrer@gmail.com>
Thu, 04 Jun 2009 23:14:49 -0400
changeset 28958 c473a5f0786c9711b56be49c3e17688ea495fcdd
parent 28952 c074f0f0ad2d50de61119811ce2ba0d767f60921 (current diff)
parent 28946 c2542ef0c8ef04eae1c8af06f0d01bc8320b3ed2 (diff)
child 28959 62a274461e45e413ac59da212fdb1a796d80a464
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.2a1pre
Merge m-c to tracemonkey.
--- a/browser/components/places/tests/browser/browser_drag_bookmarks_on_toolbar.js
+++ b/browser/components/places/tests/browser/browser_drag_bookmarks_on_toolbar.js
@@ -243,13 +243,22 @@ function nextTest() {
 
     setTimeout(nextTest, 0);
   }
   else
     finish();
 }
 
 function test() {
+  var osString = Cc["@mozilla.org/xre/app-info;1"].
+                 getService(Ci.nsIXULRuntime).OS;
+
+  // XXX bug 496277: this test fails on linux for some reason
+  if (osString == "Linux") {
+    finish();
+    return;
+  }
+
   waitForExplicitFinish();
 
   nextTest();
 }
 
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -702,20 +702,20 @@ static void
 jsds_ScriptHookProc (JSDContext* jsdc, JSDScript* jsdscript, JSBool creating,
                      void* callerdata)
 {
 #ifdef CAUTIOUS_SCRIPTHOOK
     JSContext *cx = JSD_GetDefaultJSContext(jsdc);
     JSRuntime *rt = JS_GetRuntime(cx);
 #endif
 
-    nsCOMPtr<jsdIScriptHook> hook;
-    gJsds->GetScriptHook (getter_AddRefs(hook));
-    
     if (creating) {
+        nsCOMPtr<jsdIScriptHook> hook;
+        gJsds->GetScriptHook(getter_AddRefs(hook));
+
         /* a script is being created */
         if (!hook) {
             /* nobody cares, just exit */
             return;
         }
             
         nsCOMPtr<jsdIScript> script = 
             getter_AddRefs(jsdScript::FromPtr(jsdc, jsdscript));
@@ -731,22 +731,25 @@ jsds_ScriptHookProc (JSDContext* jsdc, J
     } else {
         /* a script is being destroyed.  even if there is no registered hook
          * we'll still need to invalidate the jsdIScript record, in order
          * to remove the reference held in the JSDScript private data. */
         nsCOMPtr<jsdIScript> jsdis = 
             static_cast<jsdIScript *>(JSD_GetScriptPrivate(jsdscript));
         if (!jsdis)
             return;
-        
+
         jsdis->Invalidate();
-        if (!hook)
-            return;
-        
+
         if (gGCStatus == JSGC_END) {
+            nsCOMPtr<jsdIScriptHook> hook;
+            gJsds->GetScriptHook(getter_AddRefs(hook));
+            if (!hook)
+                return;
+
             /* if GC *isn't* running, we can tell the user about the script
              * delete now. */
 #ifdef CAUTIOUS_SCRIPTHOOK
             JS_UNKEEP_ATOMS(rt);
 #endif
                 
             gJsds->Pause(nsnull);
             hook->OnScriptDestroyed (jsdis);
--- a/layout/generic/test/plugin_clipping_helper.xhtml
+++ b/layout/generic/test/plugin_clipping_helper.xhtml
@@ -159,19 +159,31 @@ function checkClipRegion(id, rects) {
 
 function checkClipRegionForFrame(fid, id, rects) {
   var f = document.getElementById(fid);
   var bounds = f.getBoundingClientRect();
   checkClipRegionWithDoc(f.contentDocument, bounds.left, bounds.top, id, rects);
 }
 
 function runTests2() {
-  var p = document.getElementById("p1");
-  if (p.getClipRegionRectEdge(0, 0) == p.getClipRegionRectEdge(0, 2)) {
-    // plugin hasn't been updated yet. wait.
+  function check(id, doc) {
+    var p = (doc || document).getElementById(id);
+    if (p.getClipRegionRectEdge(0, 0) ==
+        p.getClipRegionRectEdge(0, 2))
+      throw id;
+  }
+
+  try {
+    check("p1");
+    check("p2");
+    check("p3");
+    check("p4");
+    check("p5", f1.contentDocument);
+  } catch (id) {
+    // One or more plugins haven't been updated yet. Wait.
     setTimeout(runTests2, 100);
     return;
   }
 
   checkClipRegion("p1", [[0, 0, 200, 200]]);
   checkClipRegion("p2", [[100, 100, 200, 200]]);
   checkClipRegion("p3", [[100, 100, 200, 200]]);
   checkClipRegion("p4", [[100, 100, 200, 200]]);
--- a/other-licenses/branding/firefox/pref/firefox-branding.js
+++ b/other-licenses/branding/firefox/pref/firefox-branding.js
@@ -11,11 +11,10 @@ pref("app.update.download.backgroundInte
 pref("app.update.url.manual", "http://%LOCALE%.www.mozilla.com/%LOCALE%/%APP%/");
 // A default value for the "More information about this update" link
 // supplied in the "An update is available" page of the update wizard. 
 pref("app.update.url.details", "http://%LOCALE%.www.mozilla.com/%LOCALE%/%APP%/releases/");
 
 // Release notes URL
 pref("app.releaseNotesURL", "http://%LOCALE%.www.mozilla.com/%LOCALE%/%APP%/%VERSION%/releasenotes/");
 
-pref("browser.search.param.yahoo-fr", "moz2");
-pref("browser.search.param.yahoo-fr-cjkt", "moz2");
-pref("browser.search.param.yahoo-f-CN", "D3_g");
+pref("browser.search.param.yahoo-fr", "moz35");
+pref("browser.search.param.yahoo-fr-cjkt", "moz35");
--- a/testing/xpcshell/head.js
+++ b/testing/xpcshell/head.js
@@ -18,16 +18,17 @@
  * The Initial Developer of the Original Code is Google Inc.
  * Portions created by the Initial Developer are Copyright (C) 2005
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *  Darin Fisher <darin@meer.net>
  *  Boris Zbarsky <bzbarsky@mit.edu>
  *  Jeff Walden <jwalden+code@mit.edu>
+ *  Serge Gautherie <sgautherie.bz@free.fr>
  *
  * 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
@@ -40,18 +41,19 @@
 
 /*
  * This file contains common code that is loaded before each test file(s).
  * See http://developer.mozilla.org/en/docs/Writing_xpcshell-based_unit_tests
  * for more information.
  */
 
 var _quit = false;
-var _fail = false;
+var _passed = true;
 var _tests_pending = 0;
+var _passedChecks = 0, _falsePassedChecks = 0;
 
 // Disable automatic network detection, so tests work correctly when
 // not connected to a network.
 let (ios = Components.classes["@mozilla.org/network/io-service;1"]
            .getService(Components.interfaces.nsIIOService2)) {
   ios.manageOfflineStatus = false;
   ios.offline = false;
 }
@@ -83,107 +85,140 @@ function _TimerCallback(expr) {
     eval(this._expr);
   }
 };
 
 function _do_main() {
   if (_quit)
     return;
 
-  dump("*** running event loop\n");
+  dump("TEST-INFO | (xpcshell/head.js) | running event loop\n");
+
   var thr = Components.classes["@mozilla.org/thread-manager;1"]
                       .getService().currentThread;
 
   while (!_quit)
     thr.processNextEvent(true);
 
   while (thr.hasPendingEvents())
     thr.processNextEvent(true);
 }
 
 function _do_quit() {
-  dump("*** exiting\n");
+  dump("TEST-INFO | (xpcshell/head.js) | exiting test\n");
 
   _quit = true;
 }
 
 function _execute_test() {
   try {
     do_test_pending();
     run_test();
     do_test_finished();
     _do_main();
   } catch (e) {
-    _fail = true;
-    dump(e + "\n");
+    _passed = false;
+    // Print exception, but not do_throw() result.
+    // Hopefully, this won't mask other NS_ERROR_ABORTs.
+    if (!_quit || e != Components.results.NS_ERROR_ABORT)
+      dump("TEST-UNEXPECTED-FAIL | (xpcshell/head.js) | " + e + "\n");
   }
 
-  if (_fail)
-    dump("*** FAIL ***\n");
+  if (!_passed)
+    return;
+
+  var truePassedChecks = _passedChecks - _falsePassedChecks;
+  if (truePassedChecks > 0)
+    dump("TEST-PASS | (xpcshell/head.js) | " + truePassedChecks + " (+ " +
+            _falsePassedChecks + ") check(s) passed\n");
   else
-    dump("*** PASS ***\n");
+    // ToDo: switch to TEST-UNEXPECTED-FAIL when all tests have been updated. (Bug 496443)
+    dump("TEST-INFO | (xpcshell/head.js) | No (+ " + _falsePassedChecks + ") checks actually run\n");
 }
 
 
 /************** Functions to be used from the tests **************/
 
 
 function do_timeout(delay, expr) {
   var timer = Components.classes["@mozilla.org/timer;1"]
                         .createInstance(Components.interfaces.nsITimer);
   timer.initWithCallback(new _TimerCallback(expr), delay, timer.TYPE_ONE_SHOT);
 }
 
 function do_throw(text, stack) {
   if (!stack)
     stack = Components.stack.caller;
-  _fail = true;
-  _do_quit();
-  dump("*** TEST-UNEXPECTED-FAIL | " + stack.filename + " | " + text + "\n");
+
+  _passed = false;
+  dump("TEST-UNEXPECTED-FAIL | " + stack.filename + " | " + text +
+         " - See following stack:\n");
   var frame = Components.stack;
   while (frame != null) {
     dump(frame + "\n");
     frame = frame.caller;
   }
+
+  _do_quit();
   throw Components.results.NS_ERROR_ABORT;
 }
 
 function do_check_neq(left, right, stack) {
   if (!stack)
     stack = Components.stack.caller;
+
+  var text = left + " != " + right;
   if (left == right)
-    do_throw(left + " != " + right, stack);
+    do_throw(text, stack);
+  else {
+    ++_passedChecks;
+    dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " +
+         stack.lineNumber + "] " + text + "\n");
+  }
 }
 
 function do_check_eq(left, right, stack) {
   if (!stack)
     stack = Components.stack.caller;
+
+  var text = left + " == " + right;
   if (left != right)
-    do_throw(left + " == " + right, stack);
+    do_throw(text, stack);
+  else {
+    ++_passedChecks;
+    dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " +
+         stack.lineNumber + "] " + text + "\n");
+  }
 }
 
 function do_check_true(condition, stack) {
   if (!stack)
     stack = Components.stack.caller;
+
   do_check_eq(condition, true, stack);
 }
 
 function do_check_false(condition, stack) {
   if (!stack)
     stack = Components.stack.caller;
+
   do_check_eq(condition, false, stack);
 }
 
 function do_test_pending() {
-  dump("*** test pending\n");
-  _tests_pending++;
+  ++_tests_pending;
+
+  dump("TEST-INFO | (xpcshell/head.js) | test " + _tests_pending +
+         " pending\n");
 }
 
 function do_test_finished() {
-  dump("*** test finished\n");
+  dump("TEST-INFO | (xpcshell/head.js) | test " + _tests_pending +
+         " finished\n");
+
   if (--_tests_pending == 0)
     _do_quit();
 }
 
 function do_get_file(path, allowNonexistent) {
   try {
     let lf = Components.classes["@mozilla.org/file/directory_service;1"]
       .getService(Components.interfaces.nsIProperties)
@@ -194,40 +229,45 @@ function do_get_file(path, allowNonexist
       if (bits[i]) {
         if (bits[i] == "..")
           lf = lf.parent;
         else
           lf.append(bits[i]);
       }
     }
 
-    if (!allowNonexistent) {
-      if (!lf.exists()) {
-        print(lf.path + " doesn't exist\n");
-      }
-      do_check_true(lf.exists());
+    if (!allowNonexistent && !lf.exists()) {
+      // Not using do_throw(): caller will continue.
+      _passed = false;
+      var stack = Components.stack.caller;
+      dump("TEST-UNEXPECTED-FAIL | " + stack.filename + " | [" +
+             stack.name + " : " + stack.lineNumber + "] " + lf.path +
+             " does not exist\n");
     }
 
     return lf;
   }
-  catch(ex) {
+  catch (ex) {
     do_throw(ex.toString(), Components.stack.caller);
   }
+
   return null;
 }
 
 // do_get_cwd() isn't exactly self-explanatory, so provide a helper
 function do_get_cwd() {
   return do_get_file("");
 }
 
 function do_load_module(path) {
   var lf = do_get_file(path);
   const nsIComponentRegistrar = Components.interfaces.nsIComponentRegistrar;
   do_check_true(Components.manager instanceof nsIComponentRegistrar);
+  // Previous do_check_true() is not a test check.
+  ++_falsePassedChecks;
   Components.manager.autoRegister(lf);
 }
 
 /**
  * Parse a DOM document.
  *
  * @param aPath File path to the document.
  * @param aType Content type to use in DOMParser.
@@ -237,18 +277,19 @@ function do_load_module(path) {
 function do_parse_document(aPath, aType) {
   switch (aType) {
     case "application/xhtml+xml":
     case "application/xml":
     case "text/xml":
       break;
 
     default:
-      throw new Error("do_parse_document requires content-type of " +
-                      "application/xhtml+xml, application/xml, or text/xml.");
+      do_throw("type: expected application/xhtml+xml, application/xml or text/xml," +
+                 " got '" + aType + "'",
+               Components.stack.caller);
   }
 
   var lf = do_get_file(aPath);
   const C_i = Components.interfaces;
   const parserClass = "@mozilla.org/xmlextras/domparser;1";
   const streamClass = "@mozilla.org/network/file-input-stream;1";
   var stream = Components.classes[streamClass]
                          .createInstance(C_i.nsIFileInputStream);
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -15,33 +15,34 @@
 #
 # The Original Code is mozilla.org code.
 #
 # The Initial Developer of the Original Code is The Mozilla Foundation
 # Portions created by the Initial Developer are Copyright (C) 2009
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
+#  Serge Gautherie <sgautherie.bz@free.fr>
 #  Ted Mielczarek <ted.mielczarek@gmail.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK ***** */
 
-import sys, os, os.path, logging
+import re, sys, os, os.path, logging
 import tempfile
 from glob import glob
 from optparse import OptionParser
 from subprocess import Popen, PIPE, STDOUT
 
 from automationutils import addCommonOptions, checkForCrashes
 
 # Init logging
@@ -209,25 +210,25 @@ def runTests(xpcshell, testdirs=[], xreP
                    env=env, cwd=testdir)
       # |stderr == None| as |pstderr| was either |None| or redirected to |stdout|.
       stdout, stderr = proc.communicate()
 
       if interactive:
         # not sure what else to do here...
         return True
 
-      if proc.returncode != 0 or (stdout is not None and stdout.find("*** PASS") == -1):
+      if proc.returncode != 0 or (stdout is not None and re.search("^TEST-UNEXPECTED-FAIL", stdout, re.MULTILINE)):
         print """TEST-UNEXPECTED-FAIL | %s | test failed (with xpcshell return code: %d), see following log:
   >>>>>>>
   %s
   <<<<<<<""" % (test, proc.returncode, stdout)
         checkForCrashes(testdir, symbolsPath, testName=test)
         success = False
       else:
-        print "TEST-PASS | %s | all tests passed" % test
+        print "TEST-PASS | %s | test passed" % test
 
       leakReport = processLeakLog(leakLogFile)
 
       if stdout is not None:
         try:
           f = open(test + '.log', 'w')
           f.write(stdout)
           if leakReport:
--- a/toolkit/components/places/src/nsNavHistoryResult.cpp
+++ b/toolkit/components/places/src/nsNavHistoryResult.cpp
@@ -2896,26 +2896,40 @@ nsNavHistoryQueryResultNode::OnPageChang
 
 NS_IMETHODIMP
 nsNavHistoryQueryResultNode::OnPageExpired(nsIURI* aURI, PRTime aVisitTime,
                                            PRBool aWholeEntry)
 {
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsNavHistoryQueryResultNode::OnItemAdded(PRInt64 aItemId,
+                                         PRInt64 aFolder,
+                                         PRInt32 aIndex)
+{
+  nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
+  NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
+  PRUint16 itemType;
+  nsresult rv = bookmarks->GetItemType(aItemId, &itemType);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return OnItemAdded(aItemId, aFolder, aIndex, itemType);
+}
 
 // nsNavHistoryQueryResultNode bookmark observers
 //
 //    These are the bookmark observer functions for query nodes. They listen
 //    for bookmark events and refresh the results if we have any dependence on
 //    the bookmark system.
 
 NS_IMETHODIMP
-nsNavHistoryQueryResultNode::OnItemAdded(PRInt64 aItemId, PRInt64 aFolder,
-                                          PRInt32 aIndex)
+nsNavHistoryQueryResultNode::OnItemAdded(PRInt64 aItemId,
+                                         PRInt64 aFolder,
+                                         PRInt32 aIndex,
+                                         PRUint16 aItemType)
 {
   if (mLiveUpdate == QUERYUPDATE_COMPLEX_WITH_BOOKMARKS)
     return Refresh();
   return NS_OK;
 }
 NS_IMETHODIMP
 nsNavHistoryQueryResultNode::OnBeforeItemRemoved(PRInt64 aItemId)
 {
@@ -3418,92 +3432,114 @@ nsNavHistoryFolderResultNode::OnBeginUpd
 
 NS_IMETHODIMP
 nsNavHistoryFolderResultNode::OnEndUpdateBatch()
 {
   return NS_OK;
 }
 
 
+NS_IMETHODIMP
+nsNavHistoryFolderResultNode::OnItemAdded(PRInt64 aItemId,
+                                         PRInt64 aFolder,
+                                         PRInt32 aIndex)
+{
+  nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
+  NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
+  PRUint16 itemType;
+  nsresult rv = bookmarks->GetItemType(aItemId, &itemType);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return OnItemAdded(aItemId, aFolder, aIndex, itemType);
+}
+
+
 // nsNavHistoryFolderResultNode::OnItemAdded (nsINavBookmarkObserver)
 
 NS_IMETHODIMP
 nsNavHistoryFolderResultNode::OnItemAdded(PRInt64 aItemId,
                                           PRInt64 aParentFolder,
-                                          PRInt32 aIndex)
+                                          PRInt32 aIndex,
+                                          PRUint16 aItemType)
 {
   NS_ASSERTION(aParentFolder == mItemId, "Got wrong bookmark update");
 
   // here, try to do something reasonable if the bookmark service gives us
   // a bogus index.
   if (aIndex < 0) {
     NS_NOTREACHED("Invalid index for item adding: <0");
     aIndex = 0;
-  } else if (aIndex > mChildren.Count()) {
+  }
+  else if (aIndex > mChildren.Count()) {
+    PRBool excludeItems = (mResult && mResult->mRootNode->mOptions->ExcludeItems()) ||
+                          (mParent && mParent->mOptions->ExcludeItems()) ||
+                          mOptions->ExcludeItems();
+    if (excludeItems &&
+        (aItemType == nsINavBookmarksService::TYPE_BOOKMARK ||
+         aItemType == nsINavBookmarksService::TYPE_SEPARATOR))
+      return NS_OK;
+
     NS_NOTREACHED("Invalid index for item adding: greater than count");
     aIndex = mChildren.Count();
   }
 
   nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
   NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
 
-  PRUint16 itemType;
-  nsresult rv = bookmarks->GetItemType(aItemId, &itemType);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsresult rv;
 
   // check for query URIs, which are bookmarks, but treated as containers
   // in results and views.
   PRBool isQuery = PR_FALSE;
-  if (itemType == nsINavBookmarksService::TYPE_BOOKMARK) {
+  if (aItemType == nsINavBookmarksService::TYPE_BOOKMARK) {
     nsCOMPtr<nsIURI> itemURI;
     rv = bookmarks->GetBookmarkURI(aItemId, getter_AddRefs(itemURI));
     NS_ENSURE_SUCCESS(rv, rv);
     nsCAutoString itemURISpec;
     rv = itemURI->GetSpec(itemURISpec);
     NS_ENSURE_SUCCESS(rv, rv);
     isQuery = IsQueryURI(itemURISpec);
   }
 
-  if (itemType != nsINavBookmarksService::TYPE_FOLDER &&
+  if (aItemType != nsINavBookmarksService::TYPE_FOLDER &&
       !isQuery && mOptions->ExcludeItems()) {
     // don't update items when we aren't displaying them, but we still need
     // to adjust bookmark indices to account for the insertion
     ReindexRange(aIndex, PR_INT32_MAX, 1);
     return NS_OK; 
   }
 
   if (!StartIncrementalUpdate())
     return NS_OK; // folder was completely refreshed for us
 
   // adjust indices to account for insertion
   ReindexRange(aIndex, PR_INT32_MAX, 1);
 
   nsRefPtr<nsNavHistoryResultNode> node;
-  if (itemType == nsINavBookmarksService::TYPE_BOOKMARK) {
+  if (aItemType == nsINavBookmarksService::TYPE_BOOKMARK) {
     nsNavHistory* history = nsNavHistory::GetHistoryService();
     NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
     rv = history->BookmarkIdToResultNode(aItemId, mOptions, getter_AddRefs(node));
     NS_ENSURE_SUCCESS(rv, rv);
     // Correctly set batch status for new query nodes.
     if (mResult && node->IsQuery())
       node->GetAsQuery()->mBatchInProgress = mResult->mBatchInProgress;
   }
-  else if (itemType == nsINavBookmarksService::TYPE_FOLDER ||
-           itemType == nsINavBookmarksService::TYPE_DYNAMIC_CONTAINER) {
+  else if (aItemType == nsINavBookmarksService::TYPE_FOLDER ||
+           aItemType == nsINavBookmarksService::TYPE_DYNAMIC_CONTAINER) {
     rv = bookmarks->ResultNodeForContainer(aItemId, mOptions, getter_AddRefs(node));
     NS_ENSURE_SUCCESS(rv, rv);
   }
-  else if (itemType == nsINavBookmarksService::TYPE_SEPARATOR) {
+  else if (aItemType == nsINavBookmarksService::TYPE_SEPARATOR) {
     node = new nsNavHistorySeparatorResultNode();
     NS_ENSURE_TRUE(node, NS_ERROR_OUT_OF_MEMORY);
     node->mItemId = aItemId;
   }
   node->mBookmarkIndex = aIndex;
 
-  if (itemType == nsINavBookmarksService::TYPE_SEPARATOR ||
+  if (aItemType == nsINavBookmarksService::TYPE_SEPARATOR ||
       GetSortType() == nsINavHistoryQueryOptions::SORT_BY_NONE) {
     // insert at natural bookmarks position
     return InsertChildAt(node, aIndex);
   }
   // insert at sorted position
   return InsertSortedChild(node, PR_FALSE);
 }
 
@@ -3516,37 +3552,45 @@ nsNavHistoryFolderResultNode::OnBeforeIt
   return NS_OK;
 }
 
 
 // nsNavHistoryFolderResultNode::OnItemRemoved (nsINavBookmarkObserver)
 
 NS_IMETHODIMP
 nsNavHistoryFolderResultNode::OnItemRemoved(PRInt64 aItemId,
-                                            PRInt64 aParentFolder, PRInt32 aIndex)
+                                            PRInt64 aParentFolder,
+                                            PRInt32 aIndex)
 {
   // We only care about notifications when a child changes. When the deleted
   // item is us, our parent should also be registered and will remove us from
   // its list.
   if (mItemId == aItemId)
     return NS_OK;
 
+  NS_ASSERTION(aParentFolder == mItemId, "Got wrong bookmark update");
+
+  PRBool excludeItems = (mResult && mResult->mRootNode->mOptions->ExcludeItems()) ||
+                        (mParent && mParent->mOptions->ExcludeItems()) ||
+                        mOptions->ExcludeItems();
+
   // don't trust the index from the bookmark service, find it ourselves. The
   // sorting could be different, or the bookmark services indices and ours might
   // be out of sync somehow.
   PRUint32 index;
   nsNavHistoryResultNode* node = FindChildById(aItemId, &index);
   if (!node) {
+    if (excludeItems)
+      return NS_OK;
+
     NS_NOTREACHED("Removing item we don't have");
     return NS_ERROR_FAILURE;
   }
 
-  NS_ASSERTION(aParentFolder == mItemId, "Got wrong bookmark update");
-
-  if ((node->IsURI() || node->IsSeparator()) && mOptions->ExcludeItems()) {
+  if ((node->IsURI() || node->IsSeparator()) && excludeItems) {
     // don't update items when we aren't displaying them, but we do need to
     // adjust everybody's bookmark indices to account for the removal
     ReindexRange(aIndex, PR_INT32_MAX, -1);
     return NS_OK;
   }
 
   if (!StartIncrementalUpdate())
     return NS_OK; // we are completely refreshed
@@ -4194,20 +4238,28 @@ nsNavHistoryResult::OnEndUpdateBatch()
 
 // nsNavHistoryResult::OnItemAdded (nsINavBookmarkObserver)
 
 NS_IMETHODIMP
 nsNavHistoryResult::OnItemAdded(PRInt64 aItemId,
                                 PRInt64 aFolder,
                                 PRInt32 aIndex)
 {
+  nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
+  NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
+
+  PRUint16 itemType;
+  nsresult rv = bookmarks->GetItemType(aItemId, &itemType);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   ENUMERATE_BOOKMARK_FOLDER_OBSERVERS(aFolder,
-      OnItemAdded(aItemId, aFolder, aIndex));
-  ENUMERATE_HISTORY_OBSERVERS(OnItemAdded(aItemId, aFolder, aIndex));
-  ENUMERATE_ALL_BOOKMARKS_OBSERVERS(OnItemAdded(aItemId, aFolder, aIndex));
+      OnItemAdded(aItemId, aFolder, aIndex, itemType));
+  ENUMERATE_HISTORY_OBSERVERS(OnItemAdded(aItemId, aFolder, aIndex, itemType));
+  ENUMERATE_ALL_BOOKMARKS_OBSERVERS(OnItemAdded(aItemId, aFolder, aIndex,
+                                                itemType));
   return NS_OK;
 }
 
 
 // nsNavHistoryResult::OnBeforeItemRemoved (nsINavBookmarkObserver)
 
 NS_IMETHODIMP
 nsNavHistoryResult::OnBeforeItemRemoved(PRInt64 aItemId)
@@ -4236,48 +4288,46 @@ nsNavHistoryResult::OnItemRemoved(PRInt6
 // nsNavHistoryResult::OnItemChanged (nsINavBookmarkObserver)
 
 NS_IMETHODIMP
 nsNavHistoryResult::OnItemChanged(PRInt64 aItemId,
                                   const nsACString &aProperty,
                                   PRBool aIsAnnotationProperty,
                                   const nsACString &aValue)
 {
-  nsNavBookmarks* bookmarkService = nsNavBookmarks::GetBookmarksService();
-  NS_ENSURE_TRUE(bookmarkService, NS_ERROR_OUT_OF_MEMORY);
-
   ENUMERATE_ALL_BOOKMARKS_OBSERVERS(
     OnItemChanged(aItemId, aProperty, aIsAnnotationProperty, aValue));
 
-  PRUint16 itemType;
-  nsresult rv = bookmarkService->GetItemType(aItemId, &itemType);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   // Note: folder-nodes set their own bookmark observer only once they're
   // opened, meaning we cannot optimize this code path for changes done to
   // folder-nodes.
 
+  nsNavBookmarks* bookmarkService = nsNavBookmarks::GetBookmarksService();
+  NS_ENSURE_TRUE(bookmarkService, NS_ERROR_OUT_OF_MEMORY);
+
   // Find the changed items under the folders list
   PRInt64 folderId;
-  rv = bookmarkService->GetFolderIdForItem(aItemId, &folderId);
+  nsresult rv = bookmarkService->GetFolderIdForItem(aItemId, &folderId);
   NS_ENSURE_SUCCESS(rv, rv);
 
   FolderObserverList* list = BookmarkFolderObserversForId(folderId, PR_FALSE);
   if (!list)
     return NS_OK;
 
   for (PRUint32 i = 0; i < list->Length(); i++) {
     nsRefPtr<nsNavHistoryFolderResultNode> folder = list->ElementAt(i);
     if (folder) {
       PRUint32 nodeIndex;
-      nsRefPtr<nsNavHistoryResultNode> node = folder->FindChildById(aItemId, &nodeIndex);
+      nsRefPtr<nsNavHistoryResultNode> node =
+        folder->FindChildById(aItemId, &nodeIndex);
       // if ExcludeItems is true we don't update non visible items
+      PRBool excludeItems = (mRootNode->mOptions->ExcludeItems()) ||
+                             folder->mOptions->ExcludeItems();
       if (node &&
-          (!folder->mOptions->ExcludeItems() ||
-           !(node->IsURI() || node->IsSeparator())) &&
+          (!excludeItems || !(node->IsURI() || node->IsSeparator())) &&
           folder->StartIncrementalUpdate()) {
         node->OnItemChanged(aItemId, aProperty, aIsAnnotationProperty, aValue);
       }
     }
   }
 
   // Note: we do NOT call history observers in this case. This notification is
   // the same as other history notification, except that here we know the item
--- a/toolkit/components/places/src/nsNavHistoryResult.h
+++ b/toolkit/components/places/src/nsNavHistoryResult.h
@@ -92,26 +92,29 @@ private:
 
 
 // Declare methods for implementing nsINavBookmarkObserver
 // and nsINavHistoryObserver (some methods, such as BeginUpdateBatch overlap)
 #define NS_DECL_BOOKMARK_HISTORY_OBSERVER                               \
   NS_DECL_NSINAVBOOKMARKOBSERVER                                        \
   NS_IMETHOD OnVisit(nsIURI* aURI, PRInt64 aVisitId, PRTime aTime,      \
                      PRInt64 aSessionId, PRInt64 aReferringId,          \
-                     PRUint32 aTransitionType, PRUint32* aAdded);      \
+                     PRUint32 aTransitionType, PRUint32* aAdded);       \
   NS_IMETHOD OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle); \
   NS_IMETHOD OnBeforeDeleteURI(nsIURI *aURI);                           \
   NS_IMETHOD OnDeleteURI(nsIURI *aURI);                                 \
   NS_IMETHOD OnClearHistory();                                          \
   NS_IMETHOD OnPageChanged(nsIURI *aURI, PRUint32 aWhat,                \
                            const nsAString &aValue);                    \
   NS_IMETHOD OnPageExpired(nsIURI* aURI, PRTime aVisitTime,             \
                            PRBool aWholeEntry);
 
+#define NS_DECL_EXTENDED_BOOKMARK_OBSERVER                              \
+  NS_IMETHOD OnItemAdded(PRInt64 aItemId, PRInt64 aFolder,              \
+                         PRInt32 aIndex, PRUint16 aItemType);
 
 // nsNavHistoryResult
 //
 //    nsNavHistory creates this object and fills in mChildren (by getting
 //    it through GetTopLevel()). Then FilledAllResults() is called to finish
 //    object initialization.
 //
 //    This object implements nsITreeView so you can just set it to a tree
@@ -712,16 +715,17 @@ public:
   NS_DECL_NSINAVHISTORYQUERYRESULTNODE
 
   PRBool CanExpand();
   PRBool IsContainersQuery();
 
   virtual nsresult OpenContainer();
 
   NS_DECL_BOOKMARK_HISTORY_OBSERVER
+  NS_DECL_EXTENDED_BOOKMARK_OBSERVER
   virtual void OnRemoving();
 
 public:
   // this constructs lazily mURI from mQueries and mOptions, call
   // VerifyQueriesSerialized either this or mQueries/mOptions should be valid
   nsresult VerifyQueriesSerialized();
 
   // these may be constructed lazily from mURI, call VerifyQueriesParsed
@@ -785,19 +789,19 @@ public:
   NS_DECL_NSINAVHISTORYQUERYRESULTNODE
 
   virtual nsresult OpenContainer();
 
   // This object implements a bookmark observer interface without deriving from
   // the bookmark observers. This is called from the result's actual observer
   // and it knows all observers are FolderResultNodes
   NS_DECL_NSINAVBOOKMARKOBSERVER
+  NS_DECL_EXTENDED_BOOKMARK_OBSERVER
 
   virtual void OnRemoving();
-
 public:
 
   // this indicates whether the folder contents are valid, they don't go away
   // after the container is closed until a notification comes in
   PRBool mContentsValid;
 
   // If the node is generated from a place:folder=X query, this is the query's
   // itemId.
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -508,16 +508,21 @@
                             break;
                         case "suspend":
                             this.setupStatusFader();
                             break;
                         case "timeupdate":
                             var currentTime = Math.round(this.video.currentTime * 1000); // in ms
                             var duration = Math.round(this.video.duration * 1000); // in ms
 
+                            // If playing/seeking after the video ended, we won't get a "play"
+                            // event, so update the button state here.
+                            if (!this.video.paused)
+                                this.setPlayButtonState(false);
+
                             this.timeUpdateCount++;
                             // Whether we show the statusFader sometimes depends
                             // on whether we've seen more than one timeupdate
                             // event (if we haven't, there hasn't been any
                             // "playback activity" and we may wish to show the
                             // statusFader while we wait for HAVE_ENOUGH_DATA).
                             // If we've seen more than 2 timeupdate events,
                             // the count is no longer relevant to setupStatusFader.
--- a/toolkit/crashreporter/test/unit/test_crashreporter.js
+++ b/toolkit/crashreporter/test/unit/test_crashreporter.js
@@ -46,9 +46,11 @@ function run_test()
   cr.minidumpPath = cwd;
   do_check_eq(cr.minidumpPath.path, cwd.path);
 
   // check that we can disable the crashreporter
   cr.enabled = false;
   do_check_false(cr.enabled);
   // ensure that double-disabling doesn't error
   cr.enabled = false;
+  // leave it enabled at the end in case of shutdown crashes
+  cr.enabled = true;
 }
--- a/widget/src/qt/mozqwidget.cpp
+++ b/widget/src/qt/mozqwidget.cpp
@@ -5,16 +5,22 @@
 MozQWidget::MozQWidget(nsWindow *receiver, QWidget *parent,
                        const char *name, int f)
     : QWidget(parent, (Qt::WindowFlags)f),
       mReceiver(receiver)
 {
     setAttribute(Qt::WA_QuitOnClose, false);
 }
 
+MozQWidget::~MozQWidget()
+{
+    if (mReceiver)
+        mReceiver->QWidgetDestroyed();
+}
+
 bool MozQWidget::event(QEvent *e)
 {
     nsEventStatus status = nsEventStatus_eIgnore;
     bool handled = true;
 
     // always handle (delayed) delete requests triggered by
     // calling deleteLater() on this widget:
     if (e->type() == QEvent::DeferredDelete)
--- a/widget/src/qt/mozqwidget.h
+++ b/widget/src/qt/mozqwidget.h
@@ -9,16 +9,18 @@ class nsWindow;
 
 class MozQWidget : public QWidget
 {
     Q_OBJECT
 public:
     MozQWidget(nsWindow* receiver, QWidget *parent,
                const char *name, int f);
 
+    ~MozQWidget();
+
     /**
      * Mozilla helper.
      */
     void setModal(bool);
     bool SetCursor(nsCursor aCursor);
     void dropReceiver() { mReceiver = 0x0; };
     nsWindow* getReceiver() { return mReceiver; };
 
--- a/widget/src/qt/nsWindow.cpp
+++ b/widget/src/qt/nsWindow.cpp
@@ -104,16 +104,18 @@
 #include <qobject.h>
 #include <execinfo.h>
 #include <stdlib.h>
 
 #ifdef Q_WS_X11
 #include "qx11info_x11.h"
 #endif
 
+#include <QtCore/QDebug>
+
 #include <execinfo.h>
 
 #include "mozqwidget.h"
 
 /* For PrepareNativeWidget */
 static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
 
 // initialization static functions 
@@ -311,16 +313,17 @@ nsWindow::Destroy(void)
         mMozQWidget->dropReceiver();
 
         // Call deleteLater instead of delete; Qt still needs the object
         // to be valid even after sending it a Close event.  We could
         // also set WA_DeleteOnClose, but this gives us more control.
         mMozQWidget->deleteLater();
     }
 
+    mMozQWidget = nsnull;
     mDrawingArea = nsnull;
 
     OnDestroy();
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -1963,16 +1966,22 @@ nsWindow::ConvertBorderStyles(nsBorderSt
 #ifdef DEBUG
         printf("we don't handle eBorderStyle_close yet... please fix me\n");
 #endif
     }
 */
     return w;
 }
 
+void nsWindow::QWidgetDestroyed()
+{
+    mDrawingArea = nsnull;
+    mMozQWidget = nsnull;
+}
+
 NS_IMETHODIMP
 nsWindow::MakeFullScreen(PRBool aFullScreen)
 {
 /*
 #if GTK_CHECK_VERSION(2,2,0)
     if (aFullScreen)
         gdk_window_fullscreen (mDrawingArea->window);
     else
--- a/widget/src/qt/nsWindow.h
+++ b/widget/src/qt/nsWindow.h
@@ -203,16 +203,18 @@ public:
 
     //
     // utility methods
     //
 
     void               LoseFocus();
     qint32             ConvertBorderStyles(nsBorderStyle aStyle);
 
+    void               QWidgetDestroyed();
+
 
     /***** from CommonWidget *****/
 
     // event handling code
 
     void DispatchGotFocusEvent(void);
     void DispatchLostFocusEvent(void);
     void DispatchActivateEvent(void);