Bug 731663. (Av1b-SM-a210) Port |Bug 593566 - Bookmarks with blank name are wrongly exported (broken codepage symbols in the exported file)| to SeaMonkey. r=IanN a=Callek.
authorSerge Gautherie <sgautherie.bz@free.fr>
Mon, 19 Mar 2012 00:28:33 +0100
changeset 11219 aa57d84a566c8c9ac9b378f5807e65a5a6af3482
parent 11218 985be5ac46304550811db252e8ddd713a5b6c0f4
child 11220 2698b91bc7f4304e5f5b5b3d4f342ab6c1a9366c
push id463
push userbugzilla@standard8.plus.com
push dateTue, 24 Apr 2012 17:34:51 +0000
treeherdercomm-beta@e53588e8f7b0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersIanN, Callek
bugs731663, 593566
Bug 731663. (Av1b-SM-a210) Port |Bug 593566 - Bookmarks with blank name are wrongly exported (broken codepage symbols in the exported file)| to SeaMonkey. r=IanN a=Callek.
suite/common/places/tests/unit/bookmarks.preplaces.html
suite/common/places/tests/unit/test_bookmarks_html.js
--- a/suite/common/places/tests/unit/bookmarks.preplaces.html
+++ b/suite/common/places/tests/unit/bookmarks.preplaces.html
@@ -2,29 +2,16 @@
 <!-- This is an automatically generated file.
      It will be read and overwritten.
      DO NOT EDIT! -->
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
 <TITLE>Bookmarks</TITLE>
 <H1 LAST_MODIFIED="1177541029">Bookmarks</H1>
 
 <DL><p>
-    <DT><H3 UNFILED_BOOKMARKS_FOLDER="true">Unsorted Bookmarks</H3>
-    <DL><p>
-        <DT><A HREF="http://example.tld">Example.tld</A>
-    </DL><p>
-    <DT><H3 LAST_MODIFIED="1177541040" PERSONAL_TOOLBAR_FOLDER="true" ID="NC:PersonalToolbarFolder">Bookmarks Toolbar Folder</H3>
-<DD>Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar
-    <DL><p>
-        <DT><A HREF="http://www.seamonkey-project.org/" LAST_VISIT="1274050000" LAST_CHARSET="UTF-8" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QwCEiUG/+wAegAAAu5JREFUOMtlk01oXFUUx3/3vfte3kydmeeQJgUTMsEaKX40tREbDHYE6UIXnZVUujCIiu3GKl0EXRh3ol1EF8WutItuuum4sRTRRXFRFGUyRPxIyVe1mK+ZZD46d968e6+LSduoFw7/c+D+Dv8D5wj+984NDQ4mz6TT/iiAMWCMRanO1urqnaJSZy/u/i12F2H46Qe5XGo6DAOMscSxQWuL1t08imI2NlRpba05CVOz/2qQSJx7+/DhfTPAPUhrQxwbJl54mHemJnCkg20pxh67sFStqlGY2pZd/OOjIyPZmTi+D91t0N+/h/enn2NuFW78aXm6dRvfd3NBIItK8bwEGB5Oz3iei1IxWpt7lrW2vPjKKKoDv65bMr5m4kiOvr4kjUaUh0+OO/DRwSBwR5WKabc1Smnu5zGFwgjfLsIv69CKDL+vG44dGyaKNK5rJ+XAQCqfTifY3Gzumrurp04dom0dlrag3gZtBc2OIZPpIZVK0tubycuxsSfD44VnsQaMBbsTxsDBIx3O/2hRsSAbWFwBf21b8vmn6N83zvz8SijL5YhGo47rguOC0YZsVjI+nuAP7RNpCANLpREzkBYMZly+vhxRLivq9Ri5vLxdqlQaaA1as2MfTp7u4fqGS0dbDvVp6hlBJrD0bFkuXarheaBUpSS1Xii1WvsxJovWXfufnX+QK5uSB3xN0tGkfIdHeyFahddfqxIEAs+DZvPv0s4iXf1CiCcmoQvf2Bvw8oEYAazUBM/sFfz8XZsLnzdRyiKlwJg15uau5XYWafYMpAvvvvd4OD+U4PRDMeYO3F7QbP7W4c1ii1YLPA+CQCBExK1b5Wk4uywArLVDxZ+aX6qeZD5ZiXjrRAXP69qUsqueJ5ASoqjC4uIP07Xaqx8CONbaK9+v2KUDuT3sV2uFky99U3TdJkEgCAJBItFVKSNqtYWlmzevT96FAYS19iiwJYSY3X3S2ewjBd8PQinBcaBaXSnV62989d/j/wcgGYelT45hgQAAAABJRU5ErkJggg==" ID="rdf:#$q2rCs3">SeaMonkey</A>
-        <DT><A HREF="http://www.mozilla.org/" LAST_VISIT="1274050586" LAST_CHARSET="UTF-8" ID="rdf:#$r2rCs3">mozilla.org</A>
-        <DT><A HREF="http://www.mozillazine.org/" ID="rdf:#$s2rCs3">mozillaZine</A>
-        <DT><A HREF="http://en-US.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/" LAST_MODIFIED="1177541035" FEEDURL="http://en-US.fxfeeds.mozilla.com/en-US/firefox/headlines.xml" ID="rdf:#$HvPhC3">Latest Headlines</A>
-<DD>Livemark test comment
-    </DL><p>
     <DT><H3 ID="rdf:#$u2rCs3">SeaMonkey and Mozilla</H3>
     <DL><p>
         <DT><A HREF="http://www.seamonkey-project.org/" LAST_VISIT="1274050000" LAST_CHARSET="UTF-8" ID="rdf:#$v2rCs3">The SeaMonkey Project</A>
         <DT><H3 ID="rdf:#$w2rCs3">mozilla.org</H3>
         <DL><p>
             <DT><A HREF="http://www.mozilla.org/" LAST_VISIT="1274050586" LAST_CHARSET="UTF-8" ID="rdf:#$x2rCs3">The Mozilla Organization</A>
             <DT><A HREF="http://www.mozilla.org/projects/" ID="rdf:#$y2rCs3">Mozilla Projects</A>
             <DT><A HREF="http://www.mozilla.org/about/" ID="rdf:#$z2rCs3">About Mozilla</A>
@@ -53,9 +40,22 @@
     </DL><p>
     <HR>
     <DT><H3 ADD_DATE="1177541020" LAST_MODIFIED="1177541050" ID="rdf:#$74Gpx2">test</H3>
 <DD>folder test comment
     <DL><p>
         <DT><A HREF="http://test/post" ADD_DATE="1177375336" LAST_MODIFIED="1177375423" SHORTCUTURL="test" WEB_PANEL="true" POST_DATA="hidden1%3Dbar&amp;text1%3D%25s" LAST_CHARSET="ISO-8859-1" ID="rdf:#$pYFe7">test post keyword</A>
 <DD>item description
     </DL>
+    <DT><H3 UNFILED_BOOKMARKS_FOLDER="true">Unsorted Bookmarks</H3>
+    <DL><p>
+        <DT><A HREF="http://example.tld">Example.tld</A>
+    </DL><p>
+    <DT><H3 LAST_MODIFIED="1177541040" PERSONAL_TOOLBAR_FOLDER="true" ID="NC:PersonalToolbarFolder">Bookmarks Toolbar Folder</H3>
+<DD>Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar
+    <DL><p>
+        <DT><A HREF="http://www.seamonkey-project.org/" LAST_VISIT="1274050000" LAST_CHARSET="UTF-8" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QwCEiUG/+wAegAAAu5JREFUOMtlk01oXFUUx3/3vfte3kydmeeQJgUTMsEaKX40tREbDHYE6UIXnZVUujCIiu3GKl0EXRh3ol1EF8WutItuuum4sRTRRXFRFGUyRPxIyVe1mK+ZZD46d968e6+LSduoFw7/c+D+Dv8D5wj+984NDQ4mz6TT/iiAMWCMRanO1urqnaJSZy/u/i12F2H46Qe5XGo6DAOMscSxQWuL1t08imI2NlRpba05CVOz/2qQSJx7+/DhfTPAPUhrQxwbJl54mHemJnCkg20pxh67sFStqlGY2pZd/OOjIyPZmTi+D91t0N+/h/enn2NuFW78aXm6dRvfd3NBIItK8bwEGB5Oz3iei1IxWpt7lrW2vPjKKKoDv65bMr5m4kiOvr4kjUaUh0+OO/DRwSBwR5WKabc1Smnu5zGFwgjfLsIv69CKDL+vG44dGyaKNK5rJ+XAQCqfTifY3Gzumrurp04dom0dlrag3gZtBc2OIZPpIZVK0tubycuxsSfD44VnsQaMBbsTxsDBIx3O/2hRsSAbWFwBf21b8vmn6N83zvz8SijL5YhGo47rguOC0YZsVjI+nuAP7RNpCANLpREzkBYMZly+vhxRLivq9Ri5vLxdqlQaaA1as2MfTp7u4fqGS0dbDvVp6hlBJrD0bFkuXarheaBUpSS1Xii1WvsxJovWXfufnX+QK5uSB3xN0tGkfIdHeyFahddfqxIEAs+DZvPv0s4iXf1CiCcmoQvf2Bvw8oEYAazUBM/sFfz8XZsLnzdRyiKlwJg15uau5XYWafYMpAvvvvd4OD+U4PRDMeYO3F7QbP7W4c1ii1YLPA+CQCBExK1b5Wk4uywArLVDxZ+aX6qeZD5ZiXjrRAXP69qUsqueJ5ASoqjC4uIP07Xaqx8CONbaK9+v2KUDuT3sV2uFky99U3TdJkEgCAJBItFVKSNqtYWlmzevT96FAYS19iiwJYSY3X3S2ewjBd8PQinBcaBaXSnV62989d/j/wcgGYelT45hgQAAAABJRU5ErkJggg==" ID="rdf:#$q2rCs3">SeaMonkey</A>
+        <DT><A HREF="http://www.mozilla.org/" LAST_VISIT="1274050586" LAST_CHARSET="UTF-8" ID="rdf:#$r2rCs3">mozilla.org</A>
+        <DT><A HREF="http://www.mozillazine.org/" ID="rdf:#$s2rCs3">mozillaZine</A>
+        <DT><A HREF="http://en-US.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/" LAST_MODIFIED="1177541035" FEEDURL="http://en-US.fxfeeds.mozilla.com/en-US/firefox/headlines.xml" ID="rdf:#$HvPhC3">Latest Headlines</A>
+<DD>Livemark test comment
+    </DL><p>
 </DL><p>
--- a/suite/common/places/tests/unit/test_bookmarks_html.js
+++ b/suite/common/places/tests/unit/test_bookmarks_html.js
@@ -16,124 +16,181 @@
  * The Original Code is mozilla.com code.
  *
  * The Initial Developer of the Original Code is Mozilla Corp.
  * Portions created by the Initial Developer are Copyright (C) 2007
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *  Dietrich Ayala <dietrich@mozilla.com>
+ *  Marco Bonardo <mak77@bonardo.net>
  *
  * 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 ***** */
 
-// get history service
-try {
-  var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].getService(Ci.nsINavHistoryService);
-} catch(ex) {
-  do_throw("Could not get nav-history-service\n");
-}
-
-// Get bookmark service
-try {
-  var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].getService(Ci.nsINavBookmarksService);
-} catch(ex) {
-  do_throw("Could not get nav-bookmarks-service\n");
-}
-
-// Get annotation service
-try {
-  var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].getService(Ci.nsIAnnotationService);
-} catch(ex) {
-  do_throw("Could not get annotation service\n");
-} 
-
-// Get livemark service
-try {
-  var livemarksvc = Cc["@mozilla.org/browser/livemark-service;2"].getService(Ci.nsILivemarkService);
-} catch(ex) {
-  do_throw("Could not get livemark service\n");
-} 
+// An object representing the contents of bookmarks.preplaces.html.
+let test_bookmarks = {
+  menu: [
+    { title: "SeaMonkey and Mozilla",
+      children: [
+        { title: "The SeaMonkey Project",
+          url: "http://www.seamonkey-project.org/"
+        },
+        { title: "mozilla.org",
+          children: [
+            { title: "The Mozilla Organization",
+              url: "http://www.mozilla.org/"
+            },
+            { title: "Mozilla Projects",
+              url: "http://www.mozilla.org/projects/"
+            },
+            { title: "About Mozilla",
+              url: "http://www.mozilla.org/about/"
+            }
+          ]
+        },
+        { title: "Extending SeaMonkey",
+          // 6 children: bother to count, but not to check their details.
+          children: [
+            {},
+            {},
+            {},
+            {},
+            {},
+            {}
+          ]
+        },
+        { title: "Community & Support",
+          // 3 children: don't even bother to count.
+        }
+      ]
+    },
+    { title: "Search the Web",
+      children: [
+        { title: "Google",
+          url: "http://www.google.com/"
+        },
+        { title: "Google Groups",
+          url: "http://groups.google.com/"
+        },
+        { title: "Google News",
+          url: "http://news.google.com/"
+        }
+      ]
+    },
+    { // <HR>
+    },
+    { title: "test",
+      description: "folder test comment",
+      dateAdded: 1177541020000000,
+      lastModified: 1177541050000000,
+      children: [
+        { title: "test post keyword",
+          description: "item description",
+          dateAdded: 1177375336000000,
+          lastModified: 1177375423000000,
+          keyword: "test",
+          sidebar: true,
+          postData: "hidden1%3Dbar&text1%3D%25s",
+          charset: "ISO-8859-1"
+        }
+      ]
+    }
+  ],
+  toolbar: [
+    { title: "SeaMonkey",
+      url: "http://www.seamonkey-project.org/",
+      icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QwCEiUG/+wAegAAAu5JREFUOMtlk01oXFUUx3/3vfte3kydmeeQJgUTMsEaKX40tREbDHYE6UIXnZVUujCIiu3GKl0EXRh3ol1EF8WutItuuum4sRTRRXFRFGUyRPxIyVe1mK+ZZD46d968e6+LSduoFw7/c+D+Dv8D5wj+984NDQ4mz6TT/iiAMWCMRanO1urqnaJSZy/u/i12F2H46Qe5XGo6DAOMscSxQWuL1t08imI2NlRpba05CVOz/2qQSJx7+/DhfTPAPUhrQxwbJl54mHemJnCkg20pxh67sFStqlGY2pZd/OOjIyPZmTi+D91t0N+/h/enn2NuFW78aXm6dRvfd3NBIItK8bwEGB5Oz3iei1IxWpt7lrW2vPjKKKoDv65bMr5m4kiOvr4kjUaUh0+OO/DRwSBwR5WKabc1Smnu5zGFwgjfLsIv69CKDL+vG44dGyaKNK5rJ+XAQCqfTifY3Gzumrurp04dom0dlrag3gZtBc2OIZPpIZVK0tubycuxsSfD44VnsQaMBbsTxsDBIx3O/2hRsSAbWFwBf21b8vmn6N83zvz8SijL5YhGo47rguOC0YZsVjI+nuAP7RNpCANLpREzkBYMZly+vhxRLivq9Ri5vLxdqlQaaA1as2MfTp7u4fqGS0dbDvVp6hlBJrD0bFkuXarheaBUpSS1Xii1WvsxJovWXfufnX+QK5uSB3xN0tGkfIdHeyFahddfqxIEAs+DZvPv0s4iXf1CiCcmoQvf2Bvw8oEYAazUBM/sFfz8XZsLnzdRyiKlwJg15uau5XYWafYMpAvvvvd4OD+U4PRDMeYO3F7QbP7W4c1ii1YLPA+CQCBExK1b5Wk4uywArLVDxZ+aX6qeZD5ZiXjrRAXP69qUsqueJ5ASoqjC4uIP07Xaqx8CONbaK9+v2KUDuT3sV2uFky99U3TdJkEgCAJBItFVKSNqtYWlmzevT96FAYS19iiwJYSY3X3S2ewjBd8PQinBcaBaXSnV62989d/j/wcgGYelT45hgQAAAABJRU5ErkJggg=="
+    },
+    { title: "mozilla.org",
+      url: "http://www.mozilla.org/"
+    },
+    { title: "mozillaZine",
+      url: "http://www.mozillazine.org/"
+    },
+    { title: "Latest Headlines",
+      description: "Livemark test comment",
+      url: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
+      feedUrl: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml"
+    }
+  ],
+  unfiled: [
+    { title: "Example.tld",
+      url: "http://example.tld/"
+    }
+  ]
+};
 
-// Get favicon service
-try {
-  var iconsvc = Cc["@mozilla.org/browser/favicon-service;1"].getService(Ci.nsIFaviconService);
-} catch(ex) {
-  do_throw("Could not get favicon service\n");
-} 
-
-// Get io service
-try {
-  var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
-} catch (ex) {
-  do_throw("Could not get io service\n");
-}
+// Pre-Places bookmarks.html file pointer.
+let gBookmarksFileOld;
+// Places bookmarks.html file pointer.
+let gBookmarksFileNew;
 
-const DESCRIPTION_ANNO = "bookmarkProperties/description";
-const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
-const POST_DATA_ANNO = "bookmarkProperties/POSTData";
-
-const TEST_FAVICON_PAGE_URL = "http://www.seamonkey-project.org/";
-const TEST_FAVICON_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QwCEiUG/+wAegAAAu5JREFUOMtlk01oXFUUx3/3vfte3kydmeeQJgUTMsEaKX40tREbDHYE6UIXnZVUujCIiu3GKl0EXRh3ol1EF8WutItuuum4sRTRRXFRFGUyRPxIyVe1mK+ZZD46d968e6+LSduoFw7/c+D+Dv8D5wj+984NDQ4mz6TT/iiAMWCMRanO1urqnaJSZy/u/i12F2H46Qe5XGo6DAOMscSxQWuL1t08imI2NlRpba05CVOz/2qQSJx7+/DhfTPAPUhrQxwbJl54mHemJnCkg20pxh67sFStqlGY2pZd/OOjIyPZmTi+D91t0N+/h/enn2NuFW78aXm6dRvfd3NBIItK8bwEGB5Oz3iei1IxWpt7lrW2vPjKKKoDv65bMr5m4kiOvr4kjUaUh0+OO/DRwSBwR5WKabc1Smnu5zGFwgjfLsIv69CKDL+vG44dGyaKNK5rJ+XAQCqfTifY3Gzumrurp04dom0dlrag3gZtBc2OIZPpIZVK0tubycuxsSfD44VnsQaMBbsTxsDBIx3O/2hRsSAbWFwBf21b8vmn6N83zvz8SijL5YhGo47rguOC0YZsVjI+nuAP7RNpCANLpREzkBYMZly+vhxRLivq9Ri5vLxdqlQaaA1as2MfTp7u4fqGS0dbDvVp6hlBJrD0bFkuXarheaBUpSS1Xii1WvsxJovWXfufnX+QK5uSB3xN0tGkfIdHeyFahddfqxIEAs+DZvPv0s4iXf1CiCcmoQvf2Bvw8oEYAazUBM/sFfz8XZsLnzdRyiKlwJg15uau5XYWafYMpAvvvvd4OD+U4PRDMeYO3F7QbP7W4c1ii1YLPA+CQCBExK1b5Wk4uywArLVDxZ+aX6qeZD5ZiXjrRAXP69qUsqueJ5ASoqjC4uIP07Xaqx8CONbaK9+v2KUDuT3sV2uFky99U3TdJkEgCAJBItFVKSNqtYWlmzevT96FAYS19iiwJYSY3X3S2ewjBd8PQinBcaBaXSnV62989d/j/wcgGYelT45hgQAAAABJRU5ErkJggg==";
+let importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
+               getService(Ci.nsIPlacesImportExportService);
 
-// main
-function run_test() {
-  // get places import/export service
-  var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].getService(Ci.nsIPlacesImportExportService);
-
-  // avoid creating the places smart folder during tests
+function run_test()
+{
+  // Avoid creating smart bookmarks during the test.
   Services.prefs.setIntPref("browser.places.smartBookmarksVersion", -1);
 
-  // file pointer to legacy bookmarks file
-  var bookmarksFileOld = do_get_file("bookmarks.preplaces.html");
-  // file pointer to a new places-exported bookmarks file
-  var bookmarksFileNew = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
-  bookmarksFileNew.append("bookmarks.exported.html");
+  // File pointer to legacy bookmarks file.
+  gBookmarksFileOld = do_get_file("bookmarks.preplaces.html");
 
-  // create bookmarks.exported.html
-  if (bookmarksFileNew.exists())
-    bookmarksFileNew.remove(false);
-  bookmarksFileNew.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600);
-  if (!bookmarksFileNew.exists())
+  // File pointer to a new Places-exported bookmarks file.
+  gBookmarksFileNew = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
+  gBookmarksFileNew.append("bookmarks.exported.html");
+  if (gBookmarksFileNew.exists()) {
+    gBookmarksFileNew.remove(false);
+  }
+  gBookmarksFileNew.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600);
+  if (!gBookmarksFileNew.exists()) {
     do_throw("couldn't create file: bookmarks.exported.html");
+  }
 
+  // This test must be the first one, since it setups the new bookmarks.html.
   // Test importing a pre-Places canonical bookmarks file.
   // 1. import bookmarks.preplaces.html
   // 2. run the test-suite
   // Note: we do not empty the db before this import to catch bugs like 380999
   try {
-    importer.importHTMLFromFile(bookmarksFileOld, true);
+    importer.importHTMLFromFile(gBookmarksFileOld, true);
   } catch(ex) { do_throw("couldn't import legacy bookmarks file: " + ex); }
-  testCanonicalBookmarks(bmsvc.bookmarksMenuFolder);
+
+  testImportedBookmarks();
+
+  // Prepare for next tests.
+  try {
+    importer.exportHTMLToFile(gBookmarksFileNew);
+  } catch(ex) { do_throw("couldn't export to file: " + ex); }
 
-  // Test exporting a Places canonical bookmarks file.
-  // 1. export to bookmarks.exported.html
-  // 2. empty bookmarks db
-  // 3. import bookmarks.exported.html
-  // 4. run the test-suite
+  remove_all_bookmarks();
+  run_next_test();
+}
+
+add_test(function test_import_new()
+{
+  // Test importing a Places bookmarks.html file.
+  // 1. import bookmarks.exported.html
+  // 2. run the test-suite
+
   try {
-    importer.exportHTMLToFile(bookmarksFileNew);
-  } catch(ex) { do_throw("couldn't export to file: " + ex); }
-  bmsvc.removeFolderChildren(bmsvc.bookmarksMenuFolder);
-  bmsvc.removeFolderChildren(bmsvc.toolbarFolder);
-  try {
-    importer.importHTMLFromFile(bookmarksFileNew, true);
+    importer.importHTMLFromFile(gBookmarksFileNew, true);
   } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
-  testCanonicalBookmarks(bmsvc.bookmarksMenuFolder);
 
   /*
   // XXX import-to-folder tests disabled due to bug 363634
   // Test importing a pre-Places canonical bookmarks file to a specific folder.
   // 1. create a new folder
   // 2. import bookmarks.preplaces.html to that folder
   // 3. run the test-suite
   var testFolder = bmsvc.createFolder(bmsvc.bookmarksMenuFolder, "test-import", bmsvc.DEFAULT_INDEX);
@@ -149,151 +206,214 @@ function run_test() {
   // 3. run the test-suite
   var testFolder = bmsvc.createFolder(bmsvc.bookmarksMenuFolder, "test-import", bmsvc.DEFAULT_INDEX);
   try {
     importer.importHTMLFromFileToFolder(bookmarksFileNew, testFolder, false);
   } catch(ex) { do_throw("couldn't import the exported file to folder: " + ex); }
   testCanonicalBookmarks(testFolder); 
   bmsvc.removeFolder(testFolder);
 
-  // XXX Disabled due to bug 381129 - separators will be duplicated on re-import
+  testImportedBookmarks();
+
+  remove_all_bookmarks();
+  run_next_test();
+});
+
+add_test(function test_emptytitle_export()
+{
+  // Test exporting and importing with an empty-titled bookmark.
+  // 1. import bookmarks
+  // 1. create an empty-titled bookmark.
+  // 2. export to bookmarks.exported.html
+  // 3. empty bookmarks db
+  // 4. import bookmarks.exported.html
+  // 5. run the test-suite
+
+  try {
+    importer.importHTMLFromFile(gBookmarksFileNew, true);
+  } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
+
+  const NOTITLE_URL = "http://notitle.mozilla.org/";
+  let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
+                                                NetUtil.newURI(NOTITLE_URL),
+                                                PlacesUtils.bookmarks.DEFAULT_INDEX,
+                                                "");
+  test_bookmarks.unfiled.push({ title: "", url: NOTITLE_URL });
+
+  try {
+    importer.exportHTMLToFile(gBookmarksFileNew);
+  } catch(ex) { do_throw("couldn't export to file: " + ex); }
+
+  remove_all_bookmarks();
+
+  try {
+    importer.importHTMLFromFile(gBookmarksFileNew, true);
+  } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
+
+  testImportedBookmarks();
+
+  // Cleanup.
+  test_bookmarks.unfiled.pop();
+  PlacesUtils.bookmarks.removeItem(id);
+
+  try {
+    importer.exportHTMLToFile(gBookmarksFileNew);
+  } catch(ex) { do_throw("couldn't export to file: " + ex); }
+
+  remove_all_bookmarks();
+  run_next_test();
+});
+
+add_test(function test_import_ontop()
+{
   // Test importing the exported bookmarks.html file *on top of* the existing
-  // bookmarks. This tests import of IDs. If we support IDs correctly, there
-  // should be no difference after the import.
+  // bookmarks.
   // 1. empty bookmarks db
   // 2. import the exported bookmarks file
   // 3. export to file
   // 3. import the exported bookmarks file
   // 4. run the test-suite
-  bmsvc.removeFolderChildren(bmsvc.bookmarksMenuFolder);
+
   try {
-    importer.importHTMLFromFile(bookmarksFileNew, true);
+    importer.importHTMLFromFile(gBookmarksFileNew, true);
   } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
   try {
-    importer.exportHTMLToFile(bookmarksFileNew);
+    importer.exportHTMLToFile(gBookmarksFileNew);
   } catch(ex) { do_throw("couldn't export to file: " + ex); }
   try {
-    importer.importHTMLFromFile(bookmarksFileNew, true);
+    importer.importHTMLFromFile(gBookmarksFileNew, true);
   } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
-  testCanonicalBookmarks(bmsvc.bookmarksMenuFolder);
   */
-  /*
-  XXX if there are new fields we add to the bookmarks HTML format
-  then test them here
-  Test importing a Places canonical bookmarks file
-  1. empty the bookmarks datastore
-  2. import bookmarks.places.html
-  3. run the test-suite
-  4. run the additional-test-suite
-  */
+
+  testImportedBookmarks();
+
+  remove_all_bookmarks();
+  run_next_test();
+});
+
+function testImportedBookmarks()
+{
+  for (let group in test_bookmarks) {
+    do_print("[testImportedBookmarks()] Checking group '" + group + "'");
+
+    let root;
+    switch (group) {
+      case "menu":
+        root = PlacesUtils.getFolderContents(PlacesUtils.bookmarksMenuFolderId).root;
+        break;
+      case "toolbar":
+        root = PlacesUtils.getFolderContents(PlacesUtils.toolbarFolderId).root;
+        break;
+      case "unfiled":
+        root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
+        break;
+    }
+
+    let items = test_bookmarks[group];
+    do_check_eq(root.childCount, items.length);
+
+    items.forEach(function (item, index) checkItem(item, root.getChild(index)));
+
+    root.containerOpen = false;
+  }
 }
 
-// Tests a bookmarks datastore that has a set of bookmarks, etc
-// that flex each supported field and feature.
-function testCanonicalBookmarks(aFolder) {
-  // query to see if the deleted folder and items have been imported
-  var query = histsvc.getNewQuery();
-  query.setFolders([aFolder], 1);
-  var result = histsvc.executeQuery(query, histsvc.getNewQueryOptions());
-  var rootNode = result.root;
-  rootNode.containerOpen = true;
+function testImportedBookmarksToFolder(aFolder)
+{
+  root = PlacesUtils.getFolderContents(aFolder).root;
 
-  // 6-2: the toolbar folder and unfiled bookmarks folder imported to the
-  // corresponding places folders
-  do_check_eq(rootNode.childCount, DEFAULT_BOOKMARKS_ON_MENU + 1);
-
-  // get test folder
-  var testFolder = rootNode.getChild(DEFAULT_BOOKMARKS_ON_MENU);
-  do_check_eq(testFolder.type, testFolder.RESULT_TYPE_FOLDER);
-  do_check_eq(testFolder.title, "test");
-
-  // add date 
-  do_check_eq(bmsvc.getItemDateAdded(testFolder.itemId)/1000000, 1177541020);
-  // last modified
-  do_check_eq(bmsvc.getItemLastModified(testFolder.itemId)/1000000, 1177541050);
+  // Menu bookmarks are put directly into the folder, while other roots are
+  // imported into subfolders.
+  let rootFolderCount = test_bookmarks.menu.length;
 
-  testFolder = testFolder.QueryInterface(Ci.nsINavHistoryQueryResultNode);
-  do_check_eq(testFolder.hasChildren, true);
-  // folder description
-  do_check_true(annosvc.itemHasAnnotation(testFolder.itemId,
-                                          DESCRIPTION_ANNO));
-  do_check_eq("folder test comment",
-              annosvc.getItemAnnotation(testFolder.itemId, DESCRIPTION_ANNO));
-  // open test folder, and test the children
-  testFolder.containerOpen = true;
-  var cc = testFolder.childCount;
-  // XXX Bug 380468
-  // do_check_eq(cc, 2);
-  do_check_eq(cc, 1);
+  for (let i = 0; i < root.childCount; i++) {
+    let child = root.getChild(i);
+    // This check depends on all "menu" bookmarks being listed first in the imported file :-|
+    if (i < rootFolderCount) {
+      checkItem(test_bookmarks.menu[i], child);
+    }
+    else {
+      let container = child.QueryInterface(Ci.nsINavHistoryContainerResultNode);
+      let group = /Toolbar/.test(container.title) ? test_bookmarks.toolbar
+                                                  : test_bookmarks.unfiled;
+      container.containerOpen = true;
+      do_print("[testImportedBookmarksToFolder()] Checking container '" + container.title + "'");
+      for (let t = 0; t < container.childCount; t++) {
+        checkItem(group[t], container.getChild(t));
+      }
+      container.containerOpen = false;
+    }
+  }
 
-  // test bookmark 1
-  var testBookmark1 = testFolder.getChild(0);
-  // url
-  do_check_eq("http://test/post", testBookmark1.uri);
-  // title
-  do_check_eq("test post keyword", testBookmark1.title);
-  // keyword
-  do_check_eq("test", bmsvc.getKeywordForBookmark(testBookmark1.itemId));
-  // sidebar
-  do_check_true(annosvc.itemHasAnnotation(testBookmark1.itemId,
-                                          LOAD_IN_SIDEBAR_ANNO));
-  // add date 
-  do_check_eq(testBookmark1.dateAdded/1000000, 1177375336);
-
-  // last modified
-  do_check_eq(testBookmark1.lastModified/1000000, 1177375423);
+  root.containerOpen = false;
+}
 
-  // post data
-  do_check_true(annosvc.itemHasAnnotation(testBookmark1.itemId,
-                                          POST_DATA_ANNO));
-  do_check_eq("hidden1%3Dbar&text1%3D%25s",
-              annosvc.getItemAnnotation(testBookmark1.itemId, POST_DATA_ANNO));
-
-  // last charset
-  var testURI = uri(testBookmark1.uri);
-  do_check_eq("ISO-8859-1", histsvc.getCharsetForURI(testURI));
-
-  // description
-  do_check_true(annosvc.itemHasAnnotation(testBookmark1.itemId,
-                                          DESCRIPTION_ANNO));
-  do_check_eq("item description",
-              annosvc.getItemAnnotation(testBookmark1.itemId,
-                                        DESCRIPTION_ANNO));
-
- // clean up
-  testFolder.containerOpen = false;
-  rootNode.containerOpen = false;
+function checkItem(aExpected, aNode)
+{
+  let id = aNode.itemId;
+  for (prop in aExpected) {
+    switch (prop) {
+      case "title":
+        do_check_eq(aNode.title, aExpected.title);
+        break;
+      case "description":
+        do_check_eq(PlacesUtils.annotations
+                               .getItemAnnotation(id, PlacesUIUtils.DESCRIPTION_ANNO),
+                    aExpected.description);
+        break;
+      case "dateAdded":
+          do_check_eq(PlacesUtils.bookmarks.getItemDateAdded(id),
+                      aExpected.dateAdded);
+        break;
+      case "lastModified":
+          do_check_eq(PlacesUtils.bookmarks.getItemLastModified(id),
+                      aExpected.lastModified);
+        break;
+      case "url":
+        if (!PlacesUtils.livemarks.isLivemark(id))
+          do_check_eq(aNode.uri, aExpected.url);
+        break;
+      case "icon":
+        let faviconURI = PlacesUtils.favicons.getFaviconForPage(
+          NetUtil.newURI(aExpected.url)
+        );
+        let dataURL = PlacesUtils.favicons.getFaviconDataAsDataURL(faviconURI);
+        // Avoid do_check_eq for console spam.
+        do_check_true(dataURL == aExpected.icon);
+        break;
+      case "keyword":
+        break;
+      case "sidebar":
+        do_check_eq(PlacesUtils.annotations
+                               .itemHasAnnotation(id, PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO),
+                    aExpected.sidebar);
+        break;
+      case "postData":
+        do_check_eq(PlacesUtils.annotations
+                               .getItemAnnotation(id, PlacesUtils.POST_DATA_ANNO),
+                    aExpected.postData);
+        break;
+      case "charset":
+        do_check_eq(PlacesUtils.history.getCharsetForURI(NetUtil.newURI(aNode.uri)),
+                    aExpected.charset);
+        break;
+      case "feedUrl":
+        do_check_true(PlacesUtils.livemarks.isLivemark(id));
+        do_check_eq(PlacesUtils.livemarks.getSiteURI(id).spec,
+                    aExpected.url);
+        do_check_eq(PlacesUtils.livemarks.getFeedURI(id).spec,
+                    aExpected.feedUrl);
+        break;
+      case "children":
+        let folder = aNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
+        do_check_eq(folder.hasChildren, aExpected.children.length > 0);
+        folder.containerOpen = true;
+        do_check_eq(folder.childCount, aExpected.children.length);
 
-  query.setFolders([bmsvc.toolbarFolder], 1);
-  result = histsvc.executeQuery(query, histsvc.getNewQueryOptions());
-  // bookmarks toolbar
-  var toolbar = result.root;
-  toolbar.containerOpen = true;
-  do_check_eq(toolbar.childCount, DEFAULT_BOOKMARKS_ON_TOOLBAR);
-  
-  // livemark
-  var livemark = toolbar.getChild(DEFAULT_BOOKMARKS_ON_TOOLBAR - 1);
-  // title
-  do_check_eq("Latest Headlines", livemark.title);
-  // livemark check
-  do_check_true(livemarksvc.isLivemark(livemark.itemId));
-  // site url
-  do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
-              livemarksvc.getSiteURI(livemark.itemId).spec);
-  // feed url
-  do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
-              livemarksvc.getFeedURI(livemark.itemId).spec);
+        aExpected.children.forEach(function (item, index) checkItem(item, folder.getChild(index)));
 
-  toolbar.containerOpen = false;
-  
-  // unfiled bookmarks
-  query.setFolders([bmsvc.unfiledBookmarksFolder], 1);
-  result = histsvc.executeQuery(query, histsvc.getNewQueryOptions());
-  var unfiledBookmarks = result.root;
-  unfiledBookmarks.containerOpen = true;
-  do_check_eq(unfiledBookmarks.childCount, 1);
-  unfiledBookmarks.containerOpen = false;
-
-  // favicons
-  var faviconURI = iconsvc.getFaviconForPage(uri(TEST_FAVICON_PAGE_URL));
-  var dataURL = iconsvc.getFaviconDataAsDataURL(faviconURI);
-  do_check_eq(TEST_FAVICON_DATA_URL, dataURL);
+        folder.containerOpen = false;
+        break;
+      default:
+        throw new Error("Unknown property");
+    }
+  };
 }