mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-09 00:37:32 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
9
toolkit/components/places/tests/.eslintrc.js
Normal file
9
toolkit/components/places/tests/.eslintrc.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"../../../../testing/mochitest/mochitest.eslintrc.js",
|
||||
"../../../../testing/mochitest/chrome.eslintrc.js",
|
||||
"../../../../testing/xpcshell/xpcshell.eslintrc.js"
|
||||
]
|
||||
};
|
||||
163
toolkit/components/places/tests/PlacesTestUtils.jsm
Normal file
163
toolkit/components/places/tests/PlacesTestUtils.jsm
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"PlacesTestUtils",
|
||||
];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.importGlobalProperties(["URL"]);
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
this.PlacesTestUtils = Object.freeze({
|
||||
/**
|
||||
* Asynchronously adds visits to a page.
|
||||
*
|
||||
* @param aPlaceInfo
|
||||
* Can be an nsIURI, in such a case a single LINK visit will be added.
|
||||
* Otherwise can be an object describing the visit to add, or an array
|
||||
* of these objects:
|
||||
* { uri: nsIURI of the page,
|
||||
* [optional] transition: one of the TRANSITION_* from nsINavHistoryService,
|
||||
* [optional] title: title of the page,
|
||||
* [optional] visitDate: visit date, either in microseconds from the epoch or as a date object
|
||||
* [optional] referrer: nsIURI of the referrer for this visit
|
||||
* }
|
||||
*
|
||||
* @return {Promise}
|
||||
* @resolves When all visits have been added successfully.
|
||||
* @rejects JavaScript exception.
|
||||
*/
|
||||
addVisits: Task.async(function* (placeInfo) {
|
||||
let places = [];
|
||||
let infos = [];
|
||||
|
||||
if (placeInfo instanceof Ci.nsIURI ||
|
||||
placeInfo instanceof URL ||
|
||||
typeof placeInfo == "string") {
|
||||
places.push({ uri: placeInfo });
|
||||
}
|
||||
else if (Array.isArray(placeInfo)) {
|
||||
places = places.concat(placeInfo);
|
||||
} else if (typeof placeInfo == "object" && placeInfo.uri) {
|
||||
places.push(placeInfo)
|
||||
} else {
|
||||
throw new Error("Unsupported type passed to addVisits");
|
||||
}
|
||||
|
||||
// Create a PageInfo for each entry.
|
||||
for (let place of places) {
|
||||
let info = {url: place.uri};
|
||||
info.title = (typeof place.title === "string") ? place.title : "test visit for " + info.url.spec ;
|
||||
if (typeof place.referrer == "string") {
|
||||
place.referrer = NetUtil.newURI(place.referrer);
|
||||
} else if (place.referrer && place.referrer instanceof URL) {
|
||||
place.referrer = NetUtil.newURI(place.referrer.href);
|
||||
}
|
||||
let visitDate = place.visitDate;
|
||||
if (visitDate) {
|
||||
if (!(visitDate instanceof Date)) {
|
||||
visitDate = PlacesUtils.toDate(visitDate);
|
||||
}
|
||||
} else {
|
||||
visitDate = new Date();
|
||||
}
|
||||
info.visits = [{
|
||||
transition: place.transition,
|
||||
date: visitDate,
|
||||
referrer: place.referrer
|
||||
}];
|
||||
infos.push(info);
|
||||
}
|
||||
return PlacesUtils.history.insertMany(infos);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Clear all history.
|
||||
*
|
||||
* @return {Promise}
|
||||
* @resolves When history was cleared successfully.
|
||||
* @rejects JavaScript exception.
|
||||
*/
|
||||
clearHistory() {
|
||||
let expirationFinished = new Promise(resolve => {
|
||||
Services.obs.addObserver(function observe(subj, topic, data) {
|
||||
Services.obs.removeObserver(observe, topic);
|
||||
resolve();
|
||||
}, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
|
||||
});
|
||||
|
||||
return Promise.all([expirationFinished, PlacesUtils.history.clear()]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Waits for all pending async statements on the default connection.
|
||||
*
|
||||
* @return {Promise}
|
||||
* @resolves When all pending async statements finished.
|
||||
* @rejects Never.
|
||||
*
|
||||
* @note The result is achieved by asynchronously executing a query requiring
|
||||
* a write lock. Since all statements on the same connection are
|
||||
* serialized, the end of this write operation means that all writes are
|
||||
* complete. Note that WAL makes so that writers don't block readers, but
|
||||
* this is a problem only across different connections.
|
||||
*/
|
||||
promiseAsyncUpdates() {
|
||||
return PlacesUtils.withConnectionWrapper("promiseAsyncUpdates", Task.async(function* (db) {
|
||||
try {
|
||||
yield db.executeCached("BEGIN EXCLUSIVE");
|
||||
yield db.executeCached("COMMIT");
|
||||
} catch (ex) {
|
||||
// If we fail to start a transaction, it's because there is already one.
|
||||
// In such a case we should not try to commit the existing transaction.
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Asynchronously checks if an address is found in the database.
|
||||
* @param aURI
|
||||
* nsIURI or address to look for.
|
||||
*
|
||||
* @return {Promise}
|
||||
* @resolves Returns true if the page is found.
|
||||
* @rejects JavaScript exception.
|
||||
*/
|
||||
isPageInDB: Task.async(function* (aURI) {
|
||||
let url = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
|
||||
let db = yield PlacesUtils.promiseDBConnection();
|
||||
let rows = yield db.executeCached(
|
||||
"SELECT id FROM moz_places WHERE url_hash = hash(:url) AND url = :url",
|
||||
{ url });
|
||||
return rows.length > 0;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Asynchronously checks how many visits exist for a specified page.
|
||||
* @param aURI
|
||||
* nsIURI or address to look for.
|
||||
*
|
||||
* @return {Promise}
|
||||
* @resolves Returns the number of visits found.
|
||||
* @rejects JavaScript exception.
|
||||
*/
|
||||
visitsInDB: Task.async(function* (aURI) {
|
||||
let url = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
|
||||
let db = yield PlacesUtils.promiseDBConnection();
|
||||
let rows = yield db.executeCached(
|
||||
`SELECT count(*) FROM moz_historyvisits v
|
||||
JOIN moz_places h ON h.id = v.place_id
|
||||
WHERE url_hash = hash(:url) AND url = :url`,
|
||||
{ url });
|
||||
return rows[0].getResultByIndex(0);
|
||||
})
|
||||
});
|
||||
7
toolkit/components/places/tests/bookmarks/.eslintrc.js
Normal file
7
toolkit/components/places/tests/bookmarks/.eslintrc.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"../../../../../testing/xpcshell/xpcshell.eslintrc.js"
|
||||
]
|
||||
};
|
||||
20
toolkit/components/places/tests/bookmarks/head_bookmarks.js
Normal file
20
toolkit/components/places/tests/bookmarks/head_bookmarks.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var Ci = Components.interfaces;
|
||||
var Cc = Components.classes;
|
||||
var Cr = Components.results;
|
||||
var Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// Import common head.
|
||||
{
|
||||
let commonFile = do_get_file("../head_common.js", false);
|
||||
let uri = Services.io.newFileURI(commonFile);
|
||||
Services.scriptloader.loadSubScript(uri.spec, this);
|
||||
}
|
||||
|
||||
// Put any other stuff relative to this test folder below.
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
/* Bug 1016953 - When a previous bookmark backup exists with the same hash
|
||||
regardless of date, an automatic backup should attempt to either rename it to
|
||||
today's date if the backup was for an old date or leave it alone if it was for
|
||||
the same date. However if the file ext was json it will accidentally rename it
|
||||
to jsonlz4 while keeping the json contents
|
||||
*/
|
||||
|
||||
add_task(function* test_same_date_same_hash() {
|
||||
// If old file has been created on the same date and has the same hash
|
||||
// the file should be left alone
|
||||
let backupFolder = yield PlacesBackups.getBackupFolder();
|
||||
// Save to profile dir to obtain hash and nodeCount to append to filename
|
||||
let tempPath = OS.Path.join(OS.Constants.Path.profileDir,
|
||||
"bug10169583_bookmarks.json");
|
||||
let {count, hash} = yield BookmarkJSONUtils.exportToFile(tempPath);
|
||||
|
||||
// Save JSON file in backup folder with hash appended
|
||||
let dateObj = new Date();
|
||||
let filename = "bookmarks-" + PlacesBackups.toISODateString(dateObj) + "_" +
|
||||
count + "_" + hash + ".json";
|
||||
let backupFile = OS.Path.join(backupFolder, filename);
|
||||
yield OS.File.move(tempPath, backupFile);
|
||||
|
||||
// Force a compressed backup which fallbacks to rename
|
||||
yield PlacesBackups.create();
|
||||
let mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup();
|
||||
// check to ensure not renamed to jsonlz4
|
||||
Assert.equal(mostRecentBackupFile, backupFile);
|
||||
// inspect contents and check if valid json
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
|
||||
createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
let result = yield OS.File.read(mostRecentBackupFile);
|
||||
let jsonString = converter.convertFromByteArray(result, result.length);
|
||||
do_print("Check is valid JSON");
|
||||
JSON.parse(jsonString);
|
||||
|
||||
// Cleanup
|
||||
yield OS.File.remove(backupFile);
|
||||
yield OS.File.remove(tempPath);
|
||||
PlacesBackups._backupFiles = null; // To force re-cache of backupFiles
|
||||
});
|
||||
|
||||
add_task(function* test_same_date_diff_hash() {
|
||||
// If the old file has been created on the same date, but has a different hash
|
||||
// the existing file should be overwritten with the newer compressed version
|
||||
let backupFolder = yield PlacesBackups.getBackupFolder();
|
||||
let tempPath = OS.Path.join(OS.Constants.Path.profileDir,
|
||||
"bug10169583_bookmarks.json");
|
||||
let {count} = yield BookmarkJSONUtils.exportToFile(tempPath);
|
||||
let dateObj = new Date();
|
||||
let filename = "bookmarks-" + PlacesBackups.toISODateString(dateObj) + "_" +
|
||||
count + "_" + "differentHash==" + ".json";
|
||||
let backupFile = OS.Path.join(backupFolder, filename);
|
||||
yield OS.File.move(tempPath, backupFile);
|
||||
yield PlacesBackups.create(); // Force compressed backup
|
||||
mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup();
|
||||
|
||||
// Decode lz4 compressed file to json and check if json is valid
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
|
||||
createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
let result = yield OS.File.read(mostRecentBackupFile, { compression: "lz4" });
|
||||
let jsonString = converter.convertFromByteArray(result, result.length);
|
||||
do_print("Check is valid JSON");
|
||||
JSON.parse(jsonString);
|
||||
|
||||
// Cleanup
|
||||
yield OS.File.remove(mostRecentBackupFile);
|
||||
yield OS.File.remove(tempPath);
|
||||
PlacesBackups._backupFiles = null; // To force re-cache of backupFiles
|
||||
});
|
||||
|
||||
add_task(function* test_diff_date_same_hash() {
|
||||
// If the old file has been created on an older day but has the same hash
|
||||
// it should be renamed with today's date without altering the contents.
|
||||
let backupFolder = yield PlacesBackups.getBackupFolder();
|
||||
let tempPath = OS.Path.join(OS.Constants.Path.profileDir,
|
||||
"bug10169583_bookmarks.json");
|
||||
let {count, hash} = yield BookmarkJSONUtils.exportToFile(tempPath);
|
||||
let oldDate = new Date(2014, 1, 1);
|
||||
let curDate = new Date();
|
||||
let oldFilename = "bookmarks-" + PlacesBackups.toISODateString(oldDate) + "_" +
|
||||
count + "_" + hash + ".json";
|
||||
let newFilename = "bookmarks-" + PlacesBackups.toISODateString(curDate) + "_" +
|
||||
count + "_" + hash + ".json";
|
||||
let backupFile = OS.Path.join(backupFolder, oldFilename);
|
||||
let newBackupFile = OS.Path.join(backupFolder, newFilename);
|
||||
yield OS.File.move(tempPath, backupFile);
|
||||
|
||||
// Ensure file has been renamed correctly
|
||||
yield PlacesBackups.create();
|
||||
let mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup();
|
||||
Assert.equal(mostRecentBackupFile, newBackupFile);
|
||||
|
||||
// Cleanup
|
||||
yield OS.File.remove(mostRecentBackupFile);
|
||||
yield OS.File.remove(tempPath);
|
||||
});
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Bug 1017502 - Add a foreign_count column to moz_places
|
||||
This tests, tests the triggers that adjust the foreign_count when a bookmark is
|
||||
added or removed and also the maintenance task to fix wrong counts.
|
||||
*/
|
||||
|
||||
const T_URI = NetUtil.newURI("https://www.mozilla.org/firefox/nightly/firstrun/");
|
||||
|
||||
function* getForeignCountForURL(conn, url) {
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
url = url instanceof Ci.nsIURI ? url.spec : url;
|
||||
let rows = yield conn.executeCached(
|
||||
`SELECT foreign_count FROM moz_places WHERE url_hash = hash(:t_url)
|
||||
AND url = :t_url`, { t_url: url });
|
||||
return rows[0].getResultByName("foreign_count");
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* add_remove_change_bookmark_test() {
|
||||
let conn = yield PlacesUtils.promiseDBConnection();
|
||||
|
||||
// Simulate a visit to the url
|
||||
yield PlacesTestUtils.addVisits(T_URI);
|
||||
Assert.equal((yield getForeignCountForURL(conn, T_URI)), 0);
|
||||
|
||||
// Add 1st bookmark which should increment foreign_count by 1
|
||||
let id1 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
T_URI, PlacesUtils.bookmarks.DEFAULT_INDEX, "First Run");
|
||||
Assert.equal((yield getForeignCountForURL(conn, T_URI)), 1);
|
||||
|
||||
// Add 2nd bookmark
|
||||
let id2 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarksMenuFolderId,
|
||||
T_URI, PlacesUtils.bookmarks.DEFAULT_INDEX, "First Run");
|
||||
Assert.equal((yield getForeignCountForURL(conn, T_URI)), 2);
|
||||
|
||||
// Remove 2nd bookmark which should decrement foreign_count by 1
|
||||
PlacesUtils.bookmarks.removeItem(id2);
|
||||
Assert.equal((yield getForeignCountForURL(conn, T_URI)), 1);
|
||||
|
||||
// Change first bookmark's URI
|
||||
const URI2 = NetUtil.newURI("http://www.mozilla.org");
|
||||
PlacesUtils.bookmarks.changeBookmarkURI(id1, URI2);
|
||||
// Check foreign count for original URI
|
||||
Assert.equal((yield getForeignCountForURL(conn, T_URI)), 0);
|
||||
// Check foreign count for new URI
|
||||
Assert.equal((yield getForeignCountForURL(conn, URI2)), 1);
|
||||
|
||||
// Cleanup - Remove changed bookmark
|
||||
let id = PlacesUtils.bookmarks.getBookmarkIdsForURI(URI2);
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
Assert.equal((yield getForeignCountForURL(conn, URI2)), 0);
|
||||
|
||||
});
|
||||
|
||||
add_task(function* maintenance_foreign_count_test() {
|
||||
let conn = yield PlacesUtils.promiseDBConnection();
|
||||
|
||||
// Simulate a visit to the url
|
||||
yield PlacesTestUtils.addVisits(T_URI);
|
||||
|
||||
// Adjust the foreign_count for the added entry to an incorrect value
|
||||
let deferred = Promise.defer();
|
||||
let stmt = DBConn().createAsyncStatement(
|
||||
`UPDATE moz_places SET foreign_count = 10 WHERE url_hash = hash(:t_url)
|
||||
AND url = :t_url `);
|
||||
stmt.params.t_url = T_URI.spec;
|
||||
stmt.executeAsync({
|
||||
handleCompletion: function() {
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
stmt.finalize();
|
||||
yield deferred.promise;
|
||||
Assert.equal((yield getForeignCountForURL(conn, T_URI)), 10);
|
||||
|
||||
// Run maintenance
|
||||
Components.utils.import("resource://gre/modules/PlacesDBUtils.jsm");
|
||||
let promiseMaintenanceFinished =
|
||||
promiseTopicObserved("places-maintenance-finished");
|
||||
PlacesDBUtils.maintenanceOnIdle();
|
||||
yield promiseMaintenanceFinished;
|
||||
|
||||
// Check if the foreign_count has been adjusted to the correct value
|
||||
Assert.equal((yield getForeignCountForURL(conn, T_URI)), 0);
|
||||
});
|
||||
|
||||
add_task(function* add_remove_tags_test() {
|
||||
let conn = yield PlacesUtils.promiseDBConnection();
|
||||
|
||||
yield PlacesTestUtils.addVisits(T_URI);
|
||||
Assert.equal((yield getForeignCountForURL(conn, T_URI)), 0);
|
||||
|
||||
// Check foreign count incremented by 1 for a single tag
|
||||
PlacesUtils.tagging.tagURI(T_URI, ["test tag"]);
|
||||
Assert.equal((yield getForeignCountForURL(conn, T_URI)), 1);
|
||||
|
||||
// Check foreign count is incremented by 2 for two tags
|
||||
PlacesUtils.tagging.tagURI(T_URI, ["one", "two"]);
|
||||
Assert.equal((yield getForeignCountForURL(conn, T_URI)), 3);
|
||||
|
||||
// Check foreign count is set to 0 when all tags are removed
|
||||
PlacesUtils.tagging.untagURI(T_URI, ["test tag", "one", "two"]);
|
||||
Assert.equal((yield getForeignCountForURL(conn, T_URI)), 0);
|
||||
});
|
||||
76
toolkit/components/places/tests/bookmarks/test_1129529.js
Normal file
76
toolkit/components/places/tests/bookmarks/test_1129529.js
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
var now = Date.now() * 1000;
|
||||
|
||||
// Test that importing bookmark data where a bookmark has a tag longer than 100
|
||||
// chars imports everything except the tags for that bookmark.
|
||||
add_task(function* () {
|
||||
let aData = {
|
||||
guid: "root________",
|
||||
index: 0,
|
||||
id: 1,
|
||||
type: "text/x-moz-place-container",
|
||||
dateAdded: now,
|
||||
lastModified: now,
|
||||
root: "placesRoot",
|
||||
children: [{
|
||||
guid: "unfiled_____",
|
||||
index: 0,
|
||||
id: 2,
|
||||
type: "text/x-moz-place-container",
|
||||
dateAdded: now,
|
||||
lastModified: now,
|
||||
root: "unfiledBookmarksFolder",
|
||||
children: [
|
||||
{
|
||||
guid: "___guid1____",
|
||||
index: 0,
|
||||
id: 3,
|
||||
charset: "UTF-8",
|
||||
tags: "tag0",
|
||||
type: "text/x-moz-place",
|
||||
dateAdded: now,
|
||||
lastModified: now,
|
||||
uri: "http://test0.com/"
|
||||
},
|
||||
{
|
||||
guid: "___guid2____",
|
||||
index: 1,
|
||||
id: 4,
|
||||
charset: "UTF-8",
|
||||
tags: "tag1," + "a" + "0123456789".repeat(10), // 101 chars
|
||||
type: "text/x-moz-place",
|
||||
dateAdded: now,
|
||||
lastModified: now,
|
||||
uri: "http://test1.com/"
|
||||
},
|
||||
{
|
||||
guid: "___guid3____",
|
||||
index: 2,
|
||||
id: 5,
|
||||
charset: "UTF-8",
|
||||
tags: "tag2",
|
||||
type: "text/x-moz-place",
|
||||
dateAdded: now,
|
||||
lastModified: now,
|
||||
uri: "http://test2.com/"
|
||||
}
|
||||
]
|
||||
}]
|
||||
};
|
||||
|
||||
let contentType = "application/json";
|
||||
let uri = "data:" + contentType + "," + JSON.stringify(aData);
|
||||
yield BookmarkJSONUtils.importFromURL(uri, false);
|
||||
|
||||
let [bookmarks] = yield PlacesBackups.getBookmarksTree();
|
||||
let unsortedBookmarks = bookmarks.children[2].children;
|
||||
Assert.equal(unsortedBookmarks.length, 3);
|
||||
|
||||
for (let i = 0; i < unsortedBookmarks.length; ++i) {
|
||||
let bookmark = unsortedBookmarks[i];
|
||||
Assert.equal(bookmark.charset, "UTF-8");
|
||||
Assert.equal(bookmark.dateAdded, now);
|
||||
Assert.equal(bookmark.lastModified, now);
|
||||
Assert.equal(bookmark.uri, "http://test" + i + ".com/");
|
||||
Assert.equal(bookmark.tags, "tag" + i);
|
||||
}
|
||||
});
|
||||
98
toolkit/components/places/tests/bookmarks/test_384228.js
Normal file
98
toolkit/components/places/tests/bookmarks/test_384228.js
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* test querying for bookmarks in multiple folders.
|
||||
*/
|
||||
add_task(function* search_bookmark_in_folder() {
|
||||
let testFolder1 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "bug 384228 test folder 1"
|
||||
});
|
||||
Assert.equal(testFolder1.index, 0);
|
||||
|
||||
let testFolder2 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "bug 384228 test folder 2"
|
||||
});
|
||||
Assert.equal(testFolder2.index, 1);
|
||||
|
||||
let testFolder3 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "bug 384228 test folder 3"
|
||||
});
|
||||
Assert.equal(testFolder3.index, 2);
|
||||
|
||||
let b1 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: testFolder1.guid,
|
||||
url: "http://foo.tld/",
|
||||
title: "title b1 (folder 1)"
|
||||
});
|
||||
Assert.equal(b1.index, 0);
|
||||
|
||||
let b2 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: testFolder1.guid,
|
||||
url: "http://foo.tld/",
|
||||
title: "title b2 (folder 1)"
|
||||
});
|
||||
Assert.equal(b2.index, 1);
|
||||
|
||||
let b3 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: testFolder2.guid,
|
||||
url: "http://foo.tld/",
|
||||
title: "title b3 (folder 2)"
|
||||
});
|
||||
Assert.equal(b3.index, 0);
|
||||
|
||||
let b4 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: testFolder3.guid,
|
||||
url: "http://foo.tld/",
|
||||
title: "title b4 (folder 3)"
|
||||
});
|
||||
Assert.equal(b4.index, 0);
|
||||
|
||||
// also test recursive search
|
||||
let testFolder1_1 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: testFolder1.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "bug 384228 test folder 1.1"
|
||||
});
|
||||
Assert.equal(testFolder1_1.index, 2);
|
||||
|
||||
let b5 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: testFolder1_1.guid,
|
||||
url: "http://foo.tld/",
|
||||
title: "title b5 (folder 1.1)"
|
||||
});
|
||||
Assert.equal(b5.index, 0);
|
||||
|
||||
|
||||
// query folder 1, folder 2 and get 4 bookmarks
|
||||
let folderIds = [];
|
||||
folderIds.push(yield PlacesUtils.promiseItemId(testFolder1.guid));
|
||||
folderIds.push(yield PlacesUtils.promiseItemId(testFolder2.guid));
|
||||
|
||||
let hs = PlacesUtils.history;
|
||||
let options = hs.getNewQueryOptions();
|
||||
let query = hs.getNewQuery();
|
||||
query.searchTerms = "title";
|
||||
options.queryType = options.QUERY_TYPE_BOOKMARKS;
|
||||
query.setFolders(folderIds, folderIds.length);
|
||||
let rootNode = hs.executeQuery(query, options).root;
|
||||
rootNode.containerOpen = true;
|
||||
|
||||
// should not match item from folder 3
|
||||
Assert.equal(rootNode.childCount, 4);
|
||||
Assert.equal(rootNode.getChild(0).bookmarkGuid, b1.guid);
|
||||
Assert.equal(rootNode.getChild(1).bookmarkGuid, b2.guid);
|
||||
Assert.equal(rootNode.getChild(2).bookmarkGuid, b3.guid);
|
||||
Assert.equal(rootNode.getChild(3).bookmarkGuid, b5.guid);
|
||||
|
||||
rootNode.containerOpen = false;
|
||||
});
|
||||
182
toolkit/components/places/tests/bookmarks/test_385829.js
Normal file
182
toolkit/components/places/tests/bookmarks/test_385829.js
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
add_task(function* search_bookmark_by_lastModified_dateDated() {
|
||||
// test search on folder with various sorts and max results
|
||||
// see bug #385829 for more details
|
||||
let folder = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "bug 385829 test"
|
||||
});
|
||||
|
||||
let now = new Date();
|
||||
// ensure some unique values for date added and last modified
|
||||
// for date added: b1 < b2 < b3 < b4
|
||||
// for last modified: b1 > b2 > b3 > b4
|
||||
let b1 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: folder.guid,
|
||||
url: "http://a1.com/",
|
||||
title: "1 title",
|
||||
dateAdded: new Date(now.getTime() + 1000)
|
||||
});
|
||||
let b2 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: folder.guid,
|
||||
url: "http://a2.com/",
|
||||
title: "2 title",
|
||||
dateAdded: new Date(now.getTime() + 2000)
|
||||
});
|
||||
let b3 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: folder.guid,
|
||||
url: "http://a3.com/",
|
||||
title: "3 title",
|
||||
dateAdded: new Date(now.getTime() + 3000)
|
||||
});
|
||||
let b4 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: folder.guid,
|
||||
url: "http://a4.com/",
|
||||
title: "4 title",
|
||||
dateAdded: new Date(now.getTime() + 4000)
|
||||
});
|
||||
|
||||
// make sure lastModified is larger than dateAdded
|
||||
let modifiedTime = new Date(now.getTime() + 5000);
|
||||
yield PlacesUtils.bookmarks.update({
|
||||
guid: b1.guid,
|
||||
lastModified: new Date(modifiedTime.getTime() + 4000)
|
||||
});
|
||||
yield PlacesUtils.bookmarks.update({
|
||||
guid: b2.guid,
|
||||
lastModified: new Date(modifiedTime.getTime() + 3000)
|
||||
});
|
||||
yield PlacesUtils.bookmarks.update({
|
||||
guid: b3.guid,
|
||||
lastModified: new Date(modifiedTime.getTime() + 2000)
|
||||
});
|
||||
yield PlacesUtils.bookmarks.update({
|
||||
guid: b4.guid,
|
||||
lastModified: new Date(modifiedTime.getTime() + 1000)
|
||||
});
|
||||
|
||||
let hs = PlacesUtils.history;
|
||||
let options = hs.getNewQueryOptions();
|
||||
let query = hs.getNewQuery();
|
||||
options.queryType = options.QUERY_TYPE_BOOKMARKS;
|
||||
options.maxResults = 3;
|
||||
let folderIds = [];
|
||||
folderIds.push(yield PlacesUtils.promiseItemId(folder.guid));
|
||||
query.setFolders(folderIds, 1);
|
||||
|
||||
let result = hs.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
|
||||
// test SORT_BY_DATEADDED_ASCENDING (live update)
|
||||
result.sortingMode = options.SORT_BY_DATEADDED_ASCENDING;
|
||||
Assert.equal(rootNode.childCount, 3);
|
||||
Assert.equal(rootNode.getChild(0).bookmarkGuid, b1.guid);
|
||||
Assert.equal(rootNode.getChild(1).bookmarkGuid, b2.guid);
|
||||
Assert.equal(rootNode.getChild(2).bookmarkGuid, b3.guid);
|
||||
Assert.ok(rootNode.getChild(0).dateAdded <
|
||||
rootNode.getChild(1).dateAdded);
|
||||
Assert.ok(rootNode.getChild(1).dateAdded <
|
||||
rootNode.getChild(2).dateAdded);
|
||||
|
||||
// test SORT_BY_DATEADDED_DESCENDING (live update)
|
||||
result.sortingMode = options.SORT_BY_DATEADDED_DESCENDING;
|
||||
Assert.equal(rootNode.childCount, 3);
|
||||
Assert.equal(rootNode.getChild(0).bookmarkGuid, b3.guid);
|
||||
Assert.equal(rootNode.getChild(1).bookmarkGuid, b2.guid);
|
||||
Assert.equal(rootNode.getChild(2).bookmarkGuid, b1.guid);
|
||||
Assert.ok(rootNode.getChild(0).dateAdded >
|
||||
rootNode.getChild(1).dateAdded);
|
||||
Assert.ok(rootNode.getChild(1).dateAdded >
|
||||
rootNode.getChild(2).dateAdded);
|
||||
|
||||
// test SORT_BY_LASTMODIFIED_ASCENDING (live update)
|
||||
result.sortingMode = options.SORT_BY_LASTMODIFIED_ASCENDING;
|
||||
Assert.equal(rootNode.childCount, 3);
|
||||
Assert.equal(rootNode.getChild(0).bookmarkGuid, b3.guid);
|
||||
Assert.equal(rootNode.getChild(1).bookmarkGuid, b2.guid);
|
||||
Assert.equal(rootNode.getChild(2).bookmarkGuid, b1.guid);
|
||||
Assert.ok(rootNode.getChild(0).lastModified <
|
||||
rootNode.getChild(1).lastModified);
|
||||
Assert.ok(rootNode.getChild(1).lastModified <
|
||||
rootNode.getChild(2).lastModified);
|
||||
|
||||
// test SORT_BY_LASTMODIFIED_DESCENDING (live update)
|
||||
result.sortingMode = options.SORT_BY_LASTMODIFIED_DESCENDING;
|
||||
|
||||
Assert.equal(rootNode.childCount, 3);
|
||||
Assert.equal(rootNode.getChild(0).bookmarkGuid, b1.guid);
|
||||
Assert.equal(rootNode.getChild(1).bookmarkGuid, b2.guid);
|
||||
Assert.equal(rootNode.getChild(2).bookmarkGuid, b3.guid);
|
||||
Assert.ok(rootNode.getChild(0).lastModified >
|
||||
rootNode.getChild(1).lastModified);
|
||||
Assert.ok(rootNode.getChild(1).lastModified >
|
||||
rootNode.getChild(2).lastModified);
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
// test SORT_BY_DATEADDED_ASCENDING
|
||||
options.sortingMode = options.SORT_BY_DATEADDED_ASCENDING;
|
||||
result = hs.executeQuery(query, options);
|
||||
rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
Assert.equal(rootNode.childCount, 3);
|
||||
Assert.equal(rootNode.getChild(0).bookmarkGuid, b1.guid);
|
||||
Assert.equal(rootNode.getChild(1).bookmarkGuid, b2.guid);
|
||||
Assert.equal(rootNode.getChild(2).bookmarkGuid, b3.guid);
|
||||
Assert.ok(rootNode.getChild(0).dateAdded <
|
||||
rootNode.getChild(1).dateAdded);
|
||||
Assert.ok(rootNode.getChild(1).dateAdded <
|
||||
rootNode.getChild(2).dateAdded);
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
// test SORT_BY_DATEADDED_DESCENDING
|
||||
options.sortingMode = options.SORT_BY_DATEADDED_DESCENDING;
|
||||
result = hs.executeQuery(query, options);
|
||||
rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
Assert.equal(rootNode.childCount, 3);
|
||||
Assert.equal(rootNode.getChild(0).bookmarkGuid, b4.guid);
|
||||
Assert.equal(rootNode.getChild(1).bookmarkGuid, b3.guid);
|
||||
Assert.equal(rootNode.getChild(2).bookmarkGuid, b2.guid);
|
||||
Assert.ok(rootNode.getChild(0).dateAdded >
|
||||
rootNode.getChild(1).dateAdded);
|
||||
Assert.ok(rootNode.getChild(1).dateAdded >
|
||||
rootNode.getChild(2).dateAdded);
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
// test SORT_BY_LASTMODIFIED_ASCENDING
|
||||
options.sortingMode = options.SORT_BY_LASTMODIFIED_ASCENDING;
|
||||
result = hs.executeQuery(query, options);
|
||||
rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
Assert.equal(rootNode.childCount, 3);
|
||||
Assert.equal(rootNode.getChild(0).bookmarkGuid, b4.guid);
|
||||
Assert.equal(rootNode.getChild(1).bookmarkGuid, b3.guid);
|
||||
Assert.equal(rootNode.getChild(2).bookmarkGuid, b2.guid);
|
||||
Assert.ok(rootNode.getChild(0).lastModified <
|
||||
rootNode.getChild(1).lastModified);
|
||||
Assert.ok(rootNode.getChild(1).lastModified <
|
||||
rootNode.getChild(2).lastModified);
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
// test SORT_BY_LASTMODIFIED_DESCENDING
|
||||
options.sortingMode = options.SORT_BY_LASTMODIFIED_DESCENDING;
|
||||
result = hs.executeQuery(query, options);
|
||||
rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
Assert.equal(rootNode.childCount, 3);
|
||||
Assert.equal(rootNode.getChild(0).bookmarkGuid, b1.guid);
|
||||
Assert.equal(rootNode.getChild(1).bookmarkGuid, b2.guid);
|
||||
Assert.equal(rootNode.getChild(2).bookmarkGuid, b3.guid);
|
||||
Assert.ok(rootNode.getChild(0).lastModified >
|
||||
rootNode.getChild(1).lastModified);
|
||||
Assert.ok(rootNode.getChild(1).lastModified >
|
||||
rootNode.getChild(2).lastModified);
|
||||
rootNode.containerOpen = false;
|
||||
});
|
||||
52
toolkit/components/places/tests/bookmarks/test_388695.js
Normal file
52
toolkit/components/places/tests/bookmarks/test_388695.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
var gTestRoot;
|
||||
var gURI;
|
||||
var gItemId1;
|
||||
var gItemId2;
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
gURI = uri("http://foo.tld.com/");
|
||||
gTestRoot = bmsvc.createFolder(bmsvc.placesRoot, "test folder",
|
||||
bmsvc.DEFAULT_INDEX);
|
||||
|
||||
// test getBookmarkIdsForURI
|
||||
// getBookmarkIdsForURI sorts by the most recently added/modified (descending)
|
||||
//
|
||||
// we cannot rely on dateAdded growing when doing so in a simple iteration,
|
||||
// see PR_Now() documentation
|
||||
do_test_pending();
|
||||
|
||||
gItemId1 = bmsvc.insertBookmark(gTestRoot, gURI, bmsvc.DEFAULT_INDEX, "");
|
||||
do_timeout(100, phase2);
|
||||
}
|
||||
|
||||
function phase2() {
|
||||
gItemId2 = bmsvc.insertBookmark(gTestRoot, gURI, bmsvc.DEFAULT_INDEX, "");
|
||||
var b = bmsvc.getBookmarkIdsForURI(gURI);
|
||||
do_check_eq(b[0], gItemId2);
|
||||
do_check_eq(b[1], gItemId1);
|
||||
do_timeout(100, phase3);
|
||||
}
|
||||
|
||||
function phase3() {
|
||||
// trigger last modified change
|
||||
bmsvc.setItemTitle(gItemId1, "");
|
||||
var b = bmsvc.getBookmarkIdsForURI(gURI);
|
||||
do_check_eq(b[0], gItemId1);
|
||||
do_check_eq(b[1], gItemId2);
|
||||
do_test_finished();
|
||||
}
|
||||
102
toolkit/components/places/tests/bookmarks/test_393498.js
Normal file
102
toolkit/components/places/tests/bookmarks/test_393498.js
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var observer = {
|
||||
__proto__: NavBookmarkObserver.prototype,
|
||||
|
||||
onItemAdded: function (id, folder, index) {
|
||||
this._itemAddedId = id;
|
||||
this._itemAddedParent = folder;
|
||||
this._itemAddedIndex = index;
|
||||
},
|
||||
onItemChanged: function (id, property, isAnnotationProperty, value) {
|
||||
this._itemChangedId = id;
|
||||
this._itemChangedProperty = property;
|
||||
this._itemChanged_isAnnotationProperty = isAnnotationProperty;
|
||||
this._itemChangedValue = value;
|
||||
}
|
||||
};
|
||||
PlacesUtils.bookmarks.addObserver(observer, false);
|
||||
|
||||
do_register_cleanup(function () {
|
||||
PlacesUtils.bookmarks.removeObserver(observer);
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
// We set times in the past to workaround a timing bug due to virtual
|
||||
// machines and the skew between PR_Now() and Date.now(), see bug 427142 and
|
||||
// bug 858377 for details.
|
||||
const PAST_PRTIME = (Date.now() - 86400000) * 1000;
|
||||
|
||||
// Insert a new bookmark.
|
||||
let testFolder = PlacesUtils.bookmarks.createFolder(
|
||||
PlacesUtils.placesRootId, "test Folder",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
let bookmarkId = PlacesUtils.bookmarks.insertBookmark(
|
||||
testFolder, uri("http://google.com/"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, "");
|
||||
|
||||
// Sanity check.
|
||||
do_check_true(observer.itemChangedProperty === undefined);
|
||||
|
||||
// Set dateAdded in the past and verify the bookmarks cache.
|
||||
PlacesUtils.bookmarks.setItemDateAdded(bookmarkId, PAST_PRTIME);
|
||||
do_check_eq(observer._itemChangedProperty, "dateAdded");
|
||||
do_check_eq(observer._itemChangedValue, PAST_PRTIME);
|
||||
let dateAdded = PlacesUtils.bookmarks.getItemDateAdded(bookmarkId);
|
||||
do_check_eq(dateAdded, PAST_PRTIME);
|
||||
|
||||
// After just inserting, modified should be the same as dateAdded.
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemLastModified(bookmarkId), dateAdded);
|
||||
|
||||
// Set lastModified in the past and verify the bookmarks cache.
|
||||
PlacesUtils.bookmarks.setItemLastModified(bookmarkId, PAST_PRTIME);
|
||||
do_check_eq(observer._itemChangedProperty, "lastModified");
|
||||
do_check_eq(observer._itemChangedValue, PAST_PRTIME);
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemLastModified(bookmarkId),
|
||||
PAST_PRTIME);
|
||||
|
||||
// Set bookmark title
|
||||
PlacesUtils.bookmarks.setItemTitle(bookmarkId, "Google");
|
||||
|
||||
// Test notifications.
|
||||
do_check_eq(observer._itemChangedId, bookmarkId);
|
||||
do_check_eq(observer._itemChangedProperty, "title");
|
||||
do_check_eq(observer._itemChangedValue, "Google");
|
||||
|
||||
// Check lastModified has been updated.
|
||||
is_time_ordered(PAST_PRTIME,
|
||||
PlacesUtils.bookmarks.getItemLastModified(bookmarkId));
|
||||
|
||||
// Check that node properties are updated.
|
||||
let root = PlacesUtils.getFolderContents(testFolder).root;
|
||||
do_check_eq(root.childCount, 1);
|
||||
let childNode = root.getChild(0);
|
||||
|
||||
// confirm current dates match node properties
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemDateAdded(bookmarkId),
|
||||
childNode.dateAdded);
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemLastModified(bookmarkId),
|
||||
childNode.lastModified);
|
||||
|
||||
// Test live update of lastModified when setting title.
|
||||
PlacesUtils.bookmarks.setItemLastModified(bookmarkId, PAST_PRTIME);
|
||||
PlacesUtils.bookmarks.setItemTitle(bookmarkId, "Google");
|
||||
|
||||
// Check lastModified has been updated.
|
||||
is_time_ordered(PAST_PRTIME, childNode.lastModified);
|
||||
// Test that node value matches db value.
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemLastModified(bookmarkId),
|
||||
childNode.lastModified);
|
||||
|
||||
// Test live update of the exposed date apis.
|
||||
PlacesUtils.bookmarks.setItemDateAdded(bookmarkId, PAST_PRTIME);
|
||||
do_check_eq(childNode.dateAdded, PAST_PRTIME);
|
||||
PlacesUtils.bookmarks.setItemLastModified(bookmarkId, PAST_PRTIME);
|
||||
do_check_eq(childNode.lastModified, PAST_PRTIME);
|
||||
|
||||
root.containerOpen = false;
|
||||
}
|
||||
87
toolkit/components/places/tests/bookmarks/test_395101.js
Normal file
87
toolkit/components/places/tests/bookmarks/test_395101.js
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// 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 history service
|
||||
try {
|
||||
var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].getService(Ci.nsINavHistoryService);
|
||||
} catch (ex) {
|
||||
do_throw("Could not get history service\n");
|
||||
}
|
||||
|
||||
// Get tagging service
|
||||
try {
|
||||
var tagssvc = Cc["@mozilla.org/browser/tagging-service;1"].
|
||||
getService(Ci.nsITaggingService);
|
||||
} catch (ex) {
|
||||
do_throw("Could not get tagging service\n");
|
||||
}
|
||||
|
||||
// get bookmarks root id
|
||||
var root = bmsvc.bookmarksMenuFolder;
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
// test searching for tagged bookmarks
|
||||
|
||||
// test folder
|
||||
var folder = bmsvc.createFolder(root, "bug 395101 test", bmsvc.DEFAULT_INDEX);
|
||||
|
||||
// create a bookmark
|
||||
var testURI = uri("http://a1.com");
|
||||
var b1 = bmsvc.insertBookmark(folder, testURI,
|
||||
bmsvc.DEFAULT_INDEX, "1 title");
|
||||
|
||||
// tag the bookmarked URI
|
||||
tagssvc.tagURI(testURI, ["elephant", "walrus", "giraffe", "turkey", "hiPPo", "BABOON", "alf"]);
|
||||
|
||||
// search for the bookmark, using a tag
|
||||
var query = histsvc.getNewQuery();
|
||||
query.searchTerms = "elephant";
|
||||
var options = histsvc.getNewQueryOptions();
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
query.setFolders([folder], 1);
|
||||
|
||||
var result = histsvc.executeQuery(query, options);
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
|
||||
do_check_eq(rootNode.childCount, 1);
|
||||
do_check_eq(rootNode.getChild(0).itemId, b1);
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
// partial matches are okay
|
||||
query.searchTerms = "wal";
|
||||
result = histsvc.executeQuery(query, options);
|
||||
rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
do_check_eq(rootNode.childCount, 1);
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
// case insensitive search term
|
||||
query.searchTerms = "WALRUS";
|
||||
result = histsvc.executeQuery(query, options);
|
||||
rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
do_check_eq(rootNode.childCount, 1);
|
||||
do_check_eq(rootNode.getChild(0).itemId, b1);
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
// case insensitive tag
|
||||
query.searchTerms = "baboon";
|
||||
result = histsvc.executeQuery(query, options);
|
||||
rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
do_check_eq(rootNode.childCount, 1);
|
||||
do_check_eq(rootNode.getChild(0).itemId, b1);
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
69
toolkit/components/places/tests/bookmarks/test_395593.js
Normal file
69
toolkit/components/places/tests/bookmarks/test_395593.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
|
||||
function check_queries_results(aQueries, aOptions, aExpectedItemIds) {
|
||||
var result = hs.executeQueries(aQueries, aQueries.length, aOptions);
|
||||
var root = result.root;
|
||||
root.containerOpen = true;
|
||||
|
||||
// Dump found nodes.
|
||||
for (let i = 0; i < root.childCount; i++) {
|
||||
dump("nodes[" + i + "]: " + root.getChild(0).title + "\n");
|
||||
}
|
||||
|
||||
do_check_eq(root.childCount, aExpectedItemIds.length);
|
||||
for (let i = 0; i < root.childCount; i++) {
|
||||
do_check_eq(root.getChild(i).itemId, aExpectedItemIds[i]);
|
||||
}
|
||||
|
||||
root.containerOpen = false;
|
||||
}
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
var id1 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"),
|
||||
bs.DEFAULT_INDEX, "123 0");
|
||||
var id2 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"),
|
||||
bs.DEFAULT_INDEX, "456");
|
||||
var id3 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"),
|
||||
bs.DEFAULT_INDEX, "123 456");
|
||||
var id4 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"),
|
||||
bs.DEFAULT_INDEX, "789 456");
|
||||
|
||||
/**
|
||||
* All of the query objects are ORed together. Within a query, all the terms
|
||||
* are ANDed together. See nsINavHistory.idl.
|
||||
*/
|
||||
var queries = [];
|
||||
queries.push(hs.getNewQuery());
|
||||
queries.push(hs.getNewQuery());
|
||||
var options = hs.getNewQueryOptions();
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
|
||||
// Test 1
|
||||
dump("Test searching for 123 OR 789\n");
|
||||
queries[0].searchTerms = "123";
|
||||
queries[1].searchTerms = "789";
|
||||
check_queries_results(queries, options, [id1, id3, id4]);
|
||||
|
||||
// Test 2
|
||||
dump("Test searching for 123 OR 456\n");
|
||||
queries[0].searchTerms = "123";
|
||||
queries[1].searchTerms = "456";
|
||||
check_queries_results(queries, options, [id1, id2, id3, id4]);
|
||||
|
||||
// Test 3
|
||||
dump("Test searching for 00 OR 789\n");
|
||||
queries[0].searchTerms = "00";
|
||||
queries[1].searchTerms = "789";
|
||||
check_queries_results(queries, options, [id4]);
|
||||
}
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var tests = [];
|
||||
|
||||
/*
|
||||
|
||||
Backup/restore tests example:
|
||||
|
||||
var myTest = {
|
||||
populate: function () { ... add bookmarks ... },
|
||||
validate: function () { ... query for your bookmarks ... }
|
||||
}
|
||||
|
||||
this.push(myTest);
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
test summary:
|
||||
- create folders with content
|
||||
- create a query bookmark for those folders
|
||||
- backs up bookmarks
|
||||
- restores bookmarks
|
||||
- confirms that the query has the new ids for the same folders
|
||||
|
||||
scenarios:
|
||||
- 1 folder (folder shortcut)
|
||||
- n folders (single query)
|
||||
- n folders (multiple queries)
|
||||
|
||||
*/
|
||||
|
||||
const DEFAULT_INDEX = PlacesUtils.bookmarks.DEFAULT_INDEX;
|
||||
|
||||
var test = {
|
||||
_testRootId: null,
|
||||
_testRootTitle: "test root",
|
||||
_folderIds: [],
|
||||
_bookmarkURIs: [],
|
||||
_count: 3,
|
||||
|
||||
populate: function populate() {
|
||||
// folder to hold this test
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.toolbarFolderId);
|
||||
this._testRootId =
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.toolbarFolderId,
|
||||
this._testRootTitle, DEFAULT_INDEX);
|
||||
|
||||
// create test folders each with a bookmark
|
||||
for (var i = 0; i < this._count; i++) {
|
||||
var folderId =
|
||||
PlacesUtils.bookmarks.createFolder(this._testRootId, "folder" + i, DEFAULT_INDEX);
|
||||
this._folderIds.push(folderId)
|
||||
|
||||
var bookmarkURI = uri("http://" + i);
|
||||
PlacesUtils.bookmarks.insertBookmark(folderId, bookmarkURI,
|
||||
DEFAULT_INDEX, "bookmark" + i);
|
||||
this._bookmarkURIs.push(bookmarkURI);
|
||||
}
|
||||
|
||||
// create a query URI with 1 folder (ie: folder shortcut)
|
||||
this._queryURI1 = uri("place:folder=" + this._folderIds[0] + "&queryType=1");
|
||||
this._queryTitle1 = "query1";
|
||||
PlacesUtils.bookmarks.insertBookmark(this._testRootId, this._queryURI1,
|
||||
DEFAULT_INDEX, this._queryTitle1);
|
||||
|
||||
// create a query URI with _count folders
|
||||
this._queryURI2 = uri("place:folder=" + this._folderIds.join("&folder=") + "&queryType=1");
|
||||
this._queryTitle2 = "query2";
|
||||
PlacesUtils.bookmarks.insertBookmark(this._testRootId, this._queryURI2,
|
||||
DEFAULT_INDEX, this._queryTitle2);
|
||||
|
||||
// create a query URI with _count queries (each with a folder)
|
||||
// first get a query object for each folder
|
||||
var queries = this._folderIds.map(function(aFolderId) {
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([aFolderId], 1);
|
||||
return query;
|
||||
});
|
||||
var options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.queryType = options.QUERY_TYPE_BOOKMARKS;
|
||||
this._queryURI3 =
|
||||
uri(PlacesUtils.history.queriesToQueryString(queries, queries.length, options));
|
||||
this._queryTitle3 = "query3";
|
||||
PlacesUtils.bookmarks.insertBookmark(this._testRootId, this._queryURI3,
|
||||
DEFAULT_INDEX, this._queryTitle3);
|
||||
},
|
||||
|
||||
clean: function () {},
|
||||
|
||||
validate: function validate() {
|
||||
// Throw a wrench in the works by inserting some new bookmarks,
|
||||
// ensuring folder ids won't be the same, when restoring.
|
||||
for (let i = 0; i < 10; i++) {
|
||||
PlacesUtils.bookmarks.
|
||||
insertBookmark(PlacesUtils.bookmarksMenuFolderId, uri("http://aaaa"+i), DEFAULT_INDEX, "");
|
||||
}
|
||||
|
||||
var toolbar =
|
||||
PlacesUtils.getFolderContents(PlacesUtils.toolbarFolderId,
|
||||
false, true).root;
|
||||
do_check_true(toolbar.childCount, 1);
|
||||
|
||||
var folderNode = toolbar.getChild(0);
|
||||
do_check_eq(folderNode.type, folderNode.RESULT_TYPE_FOLDER);
|
||||
do_check_eq(folderNode.title, this._testRootTitle);
|
||||
folderNode.QueryInterface(Ci.nsINavHistoryQueryResultNode);
|
||||
folderNode.containerOpen = true;
|
||||
|
||||
// |_count| folders + the query node
|
||||
do_check_eq(folderNode.childCount, this._count+3);
|
||||
|
||||
for (let i = 0; i < this._count; i++) {
|
||||
var subFolder = folderNode.getChild(i);
|
||||
do_check_eq(subFolder.title, "folder"+i);
|
||||
subFolder.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
subFolder.containerOpen = true;
|
||||
do_check_eq(subFolder.childCount, 1);
|
||||
var child = subFolder.getChild(0);
|
||||
do_check_eq(child.title, "bookmark"+i);
|
||||
do_check_true(uri(child.uri).equals(uri("http://" + i)))
|
||||
}
|
||||
|
||||
// validate folder shortcut
|
||||
this.validateQueryNode1(folderNode.getChild(this._count));
|
||||
|
||||
// validate folders query
|
||||
this.validateQueryNode2(folderNode.getChild(this._count + 1));
|
||||
|
||||
// validate multiple queries query
|
||||
this.validateQueryNode3(folderNode.getChild(this._count + 2));
|
||||
|
||||
// clean up
|
||||
folderNode.containerOpen = false;
|
||||
toolbar.containerOpen = false;
|
||||
},
|
||||
|
||||
validateQueryNode1: function validateQueryNode1(aNode) {
|
||||
do_check_eq(aNode.title, this._queryTitle1);
|
||||
do_check_true(PlacesUtils.nodeIsFolder(aNode));
|
||||
|
||||
aNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
aNode.containerOpen = true;
|
||||
do_check_eq(aNode.childCount, 1);
|
||||
var child = aNode.getChild(0);
|
||||
do_check_true(uri(child.uri).equals(uri("http://0")))
|
||||
do_check_eq(child.title, "bookmark0")
|
||||
aNode.containerOpen = false;
|
||||
},
|
||||
|
||||
validateQueryNode2: function validateQueryNode2(aNode) {
|
||||
do_check_eq(aNode.title, this._queryTitle2);
|
||||
do_check_true(PlacesUtils.nodeIsQuery(aNode));
|
||||
|
||||
aNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
aNode.containerOpen = true;
|
||||
do_check_eq(aNode.childCount, this._count);
|
||||
for (var i = 0; i < aNode.childCount; i++) {
|
||||
var child = aNode.getChild(i);
|
||||
do_check_true(uri(child.uri).equals(uri("http://" + i)))
|
||||
do_check_eq(child.title, "bookmark" + i)
|
||||
}
|
||||
aNode.containerOpen = false;
|
||||
},
|
||||
|
||||
validateQueryNode3: function validateQueryNode3(aNode) {
|
||||
do_check_eq(aNode.title, this._queryTitle3);
|
||||
do_check_true(PlacesUtils.nodeIsQuery(aNode));
|
||||
|
||||
aNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
aNode.containerOpen = true;
|
||||
do_check_eq(aNode.childCount, this._count);
|
||||
for (var i = 0; i < aNode.childCount; i++) {
|
||||
var child = aNode.getChild(i);
|
||||
do_check_true(uri(child.uri).equals(uri("http://" + i)))
|
||||
do_check_eq(child.title, "bookmark" + i)
|
||||
}
|
||||
aNode.containerOpen = false;
|
||||
}
|
||||
}
|
||||
tests.push(test);
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
// make json file
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
|
||||
// populate db
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.populate();
|
||||
// sanity
|
||||
aTest.validate();
|
||||
});
|
||||
|
||||
// export json to file
|
||||
yield BookmarkJSONUtils.exportToFile(jsonFile);
|
||||
|
||||
// clean
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.clean();
|
||||
});
|
||||
|
||||
// restore json file
|
||||
yield BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
|
||||
// validate
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.validate();
|
||||
});
|
||||
|
||||
// clean up
|
||||
yield OS.File.remove(jsonFile);
|
||||
});
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const EXCLUDE_FROM_BACKUP_ANNO = "places/excludeFromBackup";
|
||||
// Menu, Toolbar, Unsorted, Tags, Mobile
|
||||
const PLACES_ROOTS_COUNT = 5;
|
||||
var tests = [];
|
||||
|
||||
/*
|
||||
|
||||
Backup/restore tests example:
|
||||
|
||||
var myTest = {
|
||||
populate: function () { ... add bookmarks ... },
|
||||
validate: function () { ... query for your bookmarks ... }
|
||||
}
|
||||
|
||||
this.push(myTest);
|
||||
|
||||
*/
|
||||
|
||||
var test = {
|
||||
populate: function populate() {
|
||||
// check initial size
|
||||
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
|
||||
false, false).root;
|
||||
do_check_eq(rootNode.childCount, PLACES_ROOTS_COUNT );
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
var idx = PlacesUtils.bookmarks.DEFAULT_INDEX;
|
||||
|
||||
// create a root to be restore
|
||||
this._restoreRootTitle = "restore root";
|
||||
var restoreRootId = PlacesUtils.bookmarks
|
||||
.createFolder(PlacesUtils.placesRootId,
|
||||
this._restoreRootTitle, idx);
|
||||
// add a test bookmark
|
||||
this._restoreRootURI = uri("http://restore.uri");
|
||||
PlacesUtils.bookmarks.insertBookmark(restoreRootId, this._restoreRootURI,
|
||||
idx, "restore uri");
|
||||
// add a test bookmark to be exclude
|
||||
this._restoreRootExcludeURI = uri("http://exclude.uri");
|
||||
var exItemId = PlacesUtils.bookmarks
|
||||
.insertBookmark(restoreRootId,
|
||||
this._restoreRootExcludeURI,
|
||||
idx, "exclude uri");
|
||||
// Annotate the bookmark for exclusion.
|
||||
PlacesUtils.annotations.setItemAnnotation(exItemId,
|
||||
EXCLUDE_FROM_BACKUP_ANNO, 1, 0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
|
||||
// create a root to be exclude
|
||||
this._excludeRootTitle = "exclude root";
|
||||
this._excludeRootId = PlacesUtils.bookmarks
|
||||
.createFolder(PlacesUtils.placesRootId,
|
||||
this._excludeRootTitle, idx);
|
||||
// Annotate the root for exclusion.
|
||||
PlacesUtils.annotations.setItemAnnotation(this._excludeRootId,
|
||||
EXCLUDE_FROM_BACKUP_ANNO, 1, 0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
// add a test bookmark exclude by exclusion of its parent
|
||||
PlacesUtils.bookmarks.insertBookmark(this._excludeRootId,
|
||||
this._restoreRootExcludeURI,
|
||||
idx, "exclude uri");
|
||||
},
|
||||
|
||||
validate: function validate(aEmptyBookmarks) {
|
||||
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
|
||||
false, false).root;
|
||||
|
||||
if (!aEmptyBookmarks) {
|
||||
// since restore does not remove backup exclude items both
|
||||
// roots should still exist.
|
||||
do_check_eq(rootNode.childCount, PLACES_ROOTS_COUNT + 2);
|
||||
// open exclude root and check it still contains one item
|
||||
var restoreRootIndex = PLACES_ROOTS_COUNT;
|
||||
var excludeRootIndex = PLACES_ROOTS_COUNT+1;
|
||||
var excludeRootNode = rootNode.getChild(excludeRootIndex);
|
||||
do_check_eq(this._excludeRootTitle, excludeRootNode.title);
|
||||
excludeRootNode.QueryInterface(Ci.nsINavHistoryQueryResultNode);
|
||||
excludeRootNode.containerOpen = true;
|
||||
do_check_eq(excludeRootNode.childCount, 1);
|
||||
var excludeRootChildNode = excludeRootNode.getChild(0);
|
||||
do_check_eq(excludeRootChildNode.uri, this._restoreRootExcludeURI.spec);
|
||||
excludeRootNode.containerOpen = false;
|
||||
}
|
||||
else {
|
||||
// exclude root should not exist anymore
|
||||
do_check_eq(rootNode.childCount, PLACES_ROOTS_COUNT + 1);
|
||||
restoreRootIndex = PLACES_ROOTS_COUNT;
|
||||
}
|
||||
|
||||
var restoreRootNode = rootNode.getChild(restoreRootIndex);
|
||||
do_check_eq(this._restoreRootTitle, restoreRootNode.title);
|
||||
restoreRootNode.QueryInterface(Ci.nsINavHistoryQueryResultNode);
|
||||
restoreRootNode.containerOpen = true;
|
||||
do_check_eq(restoreRootNode.childCount, 1);
|
||||
var restoreRootChildNode = restoreRootNode.getChild(0);
|
||||
do_check_eq(restoreRootChildNode.uri, this._restoreRootURI.spec);
|
||||
restoreRootNode.containerOpen = false;
|
||||
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function*() {
|
||||
// make json file
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
|
||||
// populate db
|
||||
test.populate();
|
||||
|
||||
yield BookmarkJSONUtils.exportToFile(jsonFile);
|
||||
|
||||
// restore json file
|
||||
yield BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
|
||||
// validate without removing all bookmarks
|
||||
// restore do not remove backup exclude entries
|
||||
test.validate(false);
|
||||
|
||||
// cleanup
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
// manually remove the excluded root
|
||||
PlacesUtils.bookmarks.removeItem(test._excludeRootId);
|
||||
// restore json file
|
||||
yield BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
|
||||
// validate after a complete bookmarks cleanup
|
||||
test.validate(true);
|
||||
|
||||
// clean up
|
||||
yield OS.File.remove(jsonFile);
|
||||
});
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var tests = [];
|
||||
|
||||
/*
|
||||
|
||||
Backup/restore tests example:
|
||||
|
||||
var myTest = {
|
||||
populate: function () { ... add bookmarks ... },
|
||||
validate: function () { ... query for your bookmarks ... }
|
||||
}
|
||||
|
||||
this.push(myTest);
|
||||
|
||||
*/
|
||||
|
||||
tests.push({
|
||||
excludeItemsFromRestore: [],
|
||||
populate: function populate() {
|
||||
// check initial size
|
||||
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
|
||||
false, false).root;
|
||||
do_check_eq(rootNode.childCount, 5);
|
||||
|
||||
// create a test root
|
||||
this._folderTitle = "test folder";
|
||||
this._folderId =
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId,
|
||||
this._folderTitle,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
do_check_eq(rootNode.childCount, 6);
|
||||
|
||||
// add a tag
|
||||
this._testURI = PlacesUtils._uri("http://test");
|
||||
this._tags = ["a", "b"];
|
||||
PlacesUtils.tagging.tagURI(this._testURI, this._tags);
|
||||
|
||||
// add a child to each root, including our test root
|
||||
this._roots = [PlacesUtils.bookmarksMenuFolderId, PlacesUtils.toolbarFolderId,
|
||||
PlacesUtils.unfiledBookmarksFolderId, PlacesUtils.mobileFolderId,
|
||||
this._folderId];
|
||||
this._roots.forEach(function(aRootId) {
|
||||
// clean slate
|
||||
PlacesUtils.bookmarks.removeFolderChildren(aRootId);
|
||||
// add a test bookmark
|
||||
PlacesUtils.bookmarks.insertBookmark(aRootId, this._testURI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, "test");
|
||||
}, this);
|
||||
|
||||
// add a folder to exclude from replacing during restore
|
||||
// this will still be present post-restore
|
||||
var excludedFolderId =
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId,
|
||||
"excluded",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
do_check_eq(rootNode.childCount, 7);
|
||||
this.excludeItemsFromRestore.push(excludedFolderId);
|
||||
|
||||
// add a test bookmark to it
|
||||
PlacesUtils.bookmarks.insertBookmark(excludedFolderId, this._testURI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, "test");
|
||||
},
|
||||
|
||||
inbetween: function inbetween() {
|
||||
// add some items that should be removed by the restore
|
||||
|
||||
// add a folder
|
||||
this._litterTitle = "otter";
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId,
|
||||
this._litterTitle, 0);
|
||||
|
||||
// add some tags
|
||||
PlacesUtils.tagging.tagURI(this._testURI, ["c", "d"]);
|
||||
},
|
||||
|
||||
validate: function validate() {
|
||||
// validate tags restored
|
||||
var tags = PlacesUtils.tagging.getTagsForURI(this._testURI);
|
||||
// also validates that litter tags are gone
|
||||
do_check_eq(this._tags.toString(), tags.toString());
|
||||
|
||||
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
|
||||
false, false).root;
|
||||
|
||||
// validate litter is gone
|
||||
do_check_neq(rootNode.getChild(0).title, this._litterTitle);
|
||||
|
||||
// test root count is the same
|
||||
do_check_eq(rootNode.childCount, 7);
|
||||
|
||||
var foundTestFolder = 0;
|
||||
for (var i = 0; i < rootNode.childCount; i++) {
|
||||
var node = rootNode.getChild(i);
|
||||
|
||||
do_print("validating " + node.title);
|
||||
if (node.itemId != PlacesUtils.tagsFolderId) {
|
||||
if (node.title == this._folderTitle) {
|
||||
// check the test folder's properties
|
||||
do_check_eq(node.type, node.RESULT_TYPE_FOLDER);
|
||||
do_check_eq(node.title, this._folderTitle);
|
||||
foundTestFolder++;
|
||||
}
|
||||
|
||||
// test contents
|
||||
node.QueryInterface(Ci.nsINavHistoryContainerResultNode).containerOpen = true;
|
||||
do_check_eq(node.childCount, 1);
|
||||
var child = node.getChild(0);
|
||||
do_check_true(PlacesUtils._uri(child.uri).equals(this._testURI));
|
||||
|
||||
// clean up
|
||||
node.containerOpen = false;
|
||||
}
|
||||
}
|
||||
do_check_eq(foundTestFolder, 1);
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
// make json file
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
|
||||
// populate db
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.populate();
|
||||
// sanity
|
||||
aTest.validate();
|
||||
|
||||
if (aTest.excludedItemsFromRestore)
|
||||
excludedItemsFromRestore = excludedItems.concat(aTest.excludedItemsFromRestore);
|
||||
});
|
||||
|
||||
yield BookmarkJSONUtils.exportToFile(jsonFile);
|
||||
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.inbetween();
|
||||
});
|
||||
|
||||
// restore json file
|
||||
yield BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
|
||||
// validate
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.validate();
|
||||
});
|
||||
|
||||
// clean up
|
||||
yield OS.File.remove(jsonFile);
|
||||
});
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var tests = [];
|
||||
|
||||
/*
|
||||
|
||||
Backup/restore tests example:
|
||||
|
||||
var myTest = {
|
||||
populate: function () { ... add bookmarks ... },
|
||||
validate: function () { ... query for your bookmarks ... }
|
||||
}
|
||||
|
||||
this.push(myTest);
|
||||
|
||||
*/
|
||||
|
||||
var quotesTest = {
|
||||
_folderTitle: '"quoted folder"',
|
||||
_folderId: null,
|
||||
|
||||
populate: function () {
|
||||
this._folderId =
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.toolbarFolderId,
|
||||
this._folderTitle,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
PlacesUtils.bookmarks.removeItem(this._folderId);
|
||||
},
|
||||
|
||||
validate: function () {
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1);
|
||||
var result = PlacesUtils.history.executeQuery(query, PlacesUtils.history.getNewQueryOptions());
|
||||
|
||||
var toolbar = result.root;
|
||||
toolbar.containerOpen = true;
|
||||
|
||||
// test for our quoted folder
|
||||
do_check_true(toolbar.childCount, 1);
|
||||
var folderNode = toolbar.getChild(0);
|
||||
do_check_eq(folderNode.type, folderNode.RESULT_TYPE_FOLDER);
|
||||
do_check_eq(folderNode.title, this._folderTitle);
|
||||
|
||||
// clean up
|
||||
toolbar.containerOpen = false;
|
||||
}
|
||||
}
|
||||
tests.push(quotesTest);
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
// make json file
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
|
||||
// populate db
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.populate();
|
||||
// sanity
|
||||
aTest.validate();
|
||||
});
|
||||
|
||||
// export json to file
|
||||
yield BookmarkJSONUtils.exportToFile(jsonFile);
|
||||
|
||||
// clean
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.clean();
|
||||
});
|
||||
|
||||
// restore json file
|
||||
yield BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
|
||||
// validate
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.validate();
|
||||
});
|
||||
|
||||
// clean up
|
||||
yield OS.File.remove(jsonFile);
|
||||
|
||||
});
|
||||
113
toolkit/components/places/tests/bookmarks/test_448584.js
Normal file
113
toolkit/components/places/tests/bookmarks/test_448584.js
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var tests = [];
|
||||
|
||||
// Get database connection
|
||||
try {
|
||||
var mDBConn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||
.DBConnection;
|
||||
}
|
||||
catch (ex) {
|
||||
do_throw("Could not get database connection\n");
|
||||
}
|
||||
|
||||
/*
|
||||
This test is:
|
||||
- don't try to add invalid uri nodes to a JSON backup
|
||||
*/
|
||||
|
||||
var invalidURITest = {
|
||||
_itemTitle: "invalid uri",
|
||||
_itemUrl: "http://test.mozilla.org/",
|
||||
_itemId: null,
|
||||
|
||||
populate: function () {
|
||||
// add a valid bookmark
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId,
|
||||
PlacesUtils._uri(this._itemUrl),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
this._itemTitle);
|
||||
// this bookmark will go corrupt
|
||||
this._itemId =
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId,
|
||||
PlacesUtils._uri(this._itemUrl),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
this._itemTitle);
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
PlacesUtils.bookmarks.removeItem(this._itemId);
|
||||
},
|
||||
|
||||
validate: function (aExpectValidItemsCount) {
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1);
|
||||
var options = PlacesUtils.history.getNewQueryOptions();
|
||||
var result = PlacesUtils.history.executeQuery(query, options);
|
||||
|
||||
var toolbar = result.root;
|
||||
toolbar.containerOpen = true;
|
||||
|
||||
// test for our bookmark
|
||||
do_check_eq(toolbar.childCount, aExpectValidItemsCount);
|
||||
for (var i = 0; i < toolbar.childCount; i++) {
|
||||
var folderNode = toolbar.getChild(0);
|
||||
do_check_eq(folderNode.type, folderNode.RESULT_TYPE_URI);
|
||||
do_check_eq(folderNode.title, this._itemTitle);
|
||||
}
|
||||
|
||||
// clean up
|
||||
toolbar.containerOpen = false;
|
||||
}
|
||||
}
|
||||
tests.push(invalidURITest);
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function*() {
|
||||
// make json file
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
|
||||
// populate db
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.populate();
|
||||
// sanity
|
||||
aTest.validate(2);
|
||||
// Something in the code went wrong and we finish up losing the place, so
|
||||
// the bookmark uri becomes null.
|
||||
var sql = "UPDATE moz_bookmarks SET fk = 1337 WHERE id = ?1";
|
||||
var stmt = mDBConn.createStatement(sql);
|
||||
stmt.bindByIndex(0, aTest._itemId);
|
||||
try {
|
||||
stmt.execute();
|
||||
} finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
});
|
||||
|
||||
yield BookmarkJSONUtils.exportToFile(jsonFile);
|
||||
|
||||
// clean
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.clean();
|
||||
});
|
||||
|
||||
// restore json file
|
||||
try {
|
||||
yield BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
} catch (ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
|
||||
// validate
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.validate(1);
|
||||
});
|
||||
|
||||
// clean up
|
||||
yield OS.File.remove(jsonFile);
|
||||
});
|
||||
131
toolkit/components/places/tests/bookmarks/test_458683.js
Normal file
131
toolkit/components/places/tests/bookmarks/test_458683.js
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var tests = [];
|
||||
|
||||
// Get database connection
|
||||
try {
|
||||
var mDBConn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||
.DBConnection;
|
||||
}
|
||||
catch (ex) {
|
||||
do_throw("Could not get database connection\n");
|
||||
}
|
||||
|
||||
/*
|
||||
This test is:
|
||||
- don't block while doing backup and restore if tag containers contain
|
||||
bogus items (separators, folders)
|
||||
*/
|
||||
|
||||
var invalidTagChildTest = {
|
||||
_itemTitle: "invalid uri",
|
||||
_itemUrl: "http://test.mozilla.org/",
|
||||
_itemId: -1,
|
||||
_tag: "testTag",
|
||||
_tagItemId: -1,
|
||||
|
||||
populate: function () {
|
||||
// add a valid bookmark
|
||||
this._itemId = PlacesUtils.bookmarks
|
||||
.insertBookmark(PlacesUtils.toolbarFolderId,
|
||||
PlacesUtils._uri(this._itemUrl),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
this._itemTitle);
|
||||
|
||||
// create a tag
|
||||
PlacesUtils.tagging.tagURI(PlacesUtils._uri(this._itemUrl), [this._tag]);
|
||||
// get tag folder id
|
||||
var options = PlacesUtils.history.getNewQueryOptions();
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([PlacesUtils.bookmarks.tagsFolder], 1);
|
||||
var result = PlacesUtils.history.executeQuery(query, options);
|
||||
var tagRoot = result.root;
|
||||
tagRoot.containerOpen = true;
|
||||
do_check_eq(tagRoot.childCount, 1);
|
||||
var tagNode = tagRoot.getChild(0)
|
||||
.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
this._tagItemId = tagNode.itemId;
|
||||
tagRoot.containerOpen = false;
|
||||
|
||||
// add a separator and a folder inside tag folder
|
||||
PlacesUtils.bookmarks.insertSeparator(this._tagItemId,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.createFolder(this._tagItemId,
|
||||
"test folder",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
|
||||
// add a separator and a folder inside tag root
|
||||
PlacesUtils.bookmarks.insertSeparator(PlacesUtils.bookmarks.tagsFolder,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.bookmarks.tagsFolder,
|
||||
"test tags root folder",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
PlacesUtils.tagging.untagURI(PlacesUtils._uri(this._itemUrl), [this._tag]);
|
||||
PlacesUtils.bookmarks.removeItem(this._itemId);
|
||||
},
|
||||
|
||||
validate: function () {
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1);
|
||||
var options = PlacesUtils.history.getNewQueryOptions();
|
||||
var result = PlacesUtils.history.executeQuery(query, options);
|
||||
|
||||
var toolbar = result.root;
|
||||
toolbar.containerOpen = true;
|
||||
|
||||
// test for our bookmark
|
||||
do_check_eq(toolbar.childCount, 1);
|
||||
for (var i = 0; i < toolbar.childCount; i++) {
|
||||
var folderNode = toolbar.getChild(0);
|
||||
do_check_eq(folderNode.type, folderNode.RESULT_TYPE_URI);
|
||||
do_check_eq(folderNode.title, this._itemTitle);
|
||||
}
|
||||
toolbar.containerOpen = false;
|
||||
|
||||
// test for our tag
|
||||
var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(this._itemUrl));
|
||||
do_check_eq(tags.length, 1);
|
||||
do_check_eq(tags[0], this._tag);
|
||||
}
|
||||
}
|
||||
tests.push(invalidTagChildTest);
|
||||
|
||||
function run_test() {
|
||||
run_next_test()
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
|
||||
// populate db
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.populate();
|
||||
// sanity
|
||||
aTest.validate();
|
||||
});
|
||||
|
||||
yield BookmarkJSONUtils.exportToFile(jsonFile);
|
||||
|
||||
// clean
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.clean();
|
||||
});
|
||||
|
||||
// restore json file
|
||||
yield BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
|
||||
// validate
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.validate();
|
||||
});
|
||||
|
||||
// clean up
|
||||
yield OS.File.remove(jsonFile);
|
||||
});
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Since PlacesBackups.getbackupFiles() is a lazy getter, these tests must
|
||||
// run in the given order, to avoid making it out-of-sync.
|
||||
|
||||
add_task(function* check_max_backups_is_respected() {
|
||||
// Get bookmarkBackups directory
|
||||
let backupFolder = yield PlacesBackups.getBackupFolder();
|
||||
|
||||
// Create 2 json dummy backups in the past.
|
||||
let oldJsonPath = OS.Path.join(backupFolder, "bookmarks-2008-01-01.json");
|
||||
let oldJsonFile = yield OS.File.open(oldJsonPath, { truncate: true });
|
||||
oldJsonFile.close();
|
||||
do_check_true(yield OS.File.exists(oldJsonPath));
|
||||
|
||||
let jsonPath = OS.Path.join(backupFolder, "bookmarks-2008-01-31.json");
|
||||
let jsonFile = yield OS.File.open(jsonPath, { truncate: true });
|
||||
jsonFile.close();
|
||||
do_check_true(yield OS.File.exists(jsonPath));
|
||||
|
||||
// Export bookmarks to JSON.
|
||||
// Allow 2 backups, the older one should be removed.
|
||||
yield PlacesBackups.create(2);
|
||||
|
||||
let count = 0;
|
||||
let lastBackupPath = null;
|
||||
let iterator = new OS.File.DirectoryIterator(backupFolder);
|
||||
try {
|
||||
yield iterator.forEach(aEntry => {
|
||||
count++;
|
||||
if (PlacesBackups.filenamesRegex.test(aEntry.name))
|
||||
lastBackupPath = aEntry.path;
|
||||
});
|
||||
} finally {
|
||||
iterator.close();
|
||||
}
|
||||
|
||||
do_check_eq(count, 2);
|
||||
do_check_neq(lastBackupPath, null);
|
||||
do_check_false(yield OS.File.exists(oldJsonPath));
|
||||
do_check_true(yield OS.File.exists(jsonPath));
|
||||
});
|
||||
|
||||
add_task(function* check_max_backups_greater_than_backups() {
|
||||
// Get bookmarkBackups directory
|
||||
let backupFolder = yield PlacesBackups.getBackupFolder();
|
||||
|
||||
// Export bookmarks to JSON.
|
||||
// Allow 3 backups, none should be removed.
|
||||
yield PlacesBackups.create(3);
|
||||
|
||||
let count = 0;
|
||||
let lastBackupPath = null;
|
||||
let iterator = new OS.File.DirectoryIterator(backupFolder);
|
||||
try {
|
||||
yield iterator.forEach(aEntry => {
|
||||
count++;
|
||||
if (PlacesBackups.filenamesRegex.test(aEntry.name))
|
||||
lastBackupPath = aEntry.path;
|
||||
});
|
||||
} finally {
|
||||
iterator.close();
|
||||
}
|
||||
do_check_eq(count, 2);
|
||||
do_check_neq(lastBackupPath, null);
|
||||
});
|
||||
|
||||
add_task(function* check_max_backups_null() {
|
||||
// Get bookmarkBackups directory
|
||||
let backupFolder = yield PlacesBackups.getBackupFolder();
|
||||
|
||||
// Export bookmarks to JSON.
|
||||
// Allow infinite backups, none should be removed, a new one is not created
|
||||
// since one for today already exists.
|
||||
yield PlacesBackups.create(null);
|
||||
|
||||
let count = 0;
|
||||
let lastBackupPath = null;
|
||||
let iterator = new OS.File.DirectoryIterator(backupFolder);
|
||||
try {
|
||||
yield iterator.forEach(aEntry => {
|
||||
count++;
|
||||
if (PlacesBackups.filenamesRegex.test(aEntry.name))
|
||||
lastBackupPath = aEntry.path;
|
||||
});
|
||||
} finally {
|
||||
iterator.close();
|
||||
}
|
||||
do_check_eq(count, 2);
|
||||
do_check_neq(lastBackupPath, null);
|
||||
});
|
||||
|
||||
add_task(function* check_max_backups_undefined() {
|
||||
// Get bookmarkBackups directory
|
||||
let backupFolder = yield PlacesBackups.getBackupFolder();
|
||||
|
||||
// Export bookmarks to JSON.
|
||||
// Allow infinite backups, none should be removed, a new one is not created
|
||||
// since one for today already exists.
|
||||
yield PlacesBackups.create();
|
||||
|
||||
let count = 0;
|
||||
let lastBackupPath = null;
|
||||
let iterator = new OS.File.DirectoryIterator(backupFolder);
|
||||
try {
|
||||
yield iterator.forEach(aEntry => {
|
||||
count++;
|
||||
if (PlacesBackups.filenamesRegex.test(aEntry.name))
|
||||
lastBackupPath = aEntry.path;
|
||||
});
|
||||
} finally {
|
||||
iterator.close();
|
||||
}
|
||||
do_check_eq(count, 2);
|
||||
do_check_neq(lastBackupPath, null);
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
Task.spawn(function*() {
|
||||
let backupFolder = yield PlacesBackups.getBackupFolder();
|
||||
let bookmarksBackupDir = new FileUtils.File(backupFolder);
|
||||
// Remove all files from backups folder.
|
||||
let files = bookmarksBackupDir.directoryEntries;
|
||||
while (files.hasMoreElements()) {
|
||||
let entry = files.getNext().QueryInterface(Ci.nsIFile);
|
||||
entry.remove(false);
|
||||
}
|
||||
|
||||
// Create a json dummy backup in the future.
|
||||
let dateObj = new Date();
|
||||
dateObj.setYear(dateObj.getFullYear() + 1);
|
||||
let name = PlacesBackups.getFilenameForDate(dateObj);
|
||||
do_check_eq(name, "bookmarks-" + PlacesBackups.toISODateString(dateObj) + ".json");
|
||||
files = bookmarksBackupDir.directoryEntries;
|
||||
while (files.hasMoreElements()) {
|
||||
let entry = files.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (PlacesBackups.filenamesRegex.test(entry.leafName))
|
||||
entry.remove(false);
|
||||
}
|
||||
|
||||
let futureBackupFile = bookmarksBackupDir.clone();
|
||||
futureBackupFile.append(name);
|
||||
futureBackupFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0o600);
|
||||
do_check_true(futureBackupFile.exists());
|
||||
|
||||
do_check_eq((yield PlacesBackups.getBackupFiles()).length, 0);
|
||||
|
||||
yield PlacesBackups.create();
|
||||
// Check that a backup for today has been created.
|
||||
do_check_eq((yield PlacesBackups.getBackupFiles()).length, 1);
|
||||
let mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup();
|
||||
do_check_neq(mostRecentBackupFile, null);
|
||||
do_check_true(PlacesBackups.filenamesRegex.test(OS.Path.basename(mostRecentBackupFile)));
|
||||
|
||||
// Check that future backup has been removed.
|
||||
do_check_false(futureBackupFile.exists());
|
||||
|
||||
// Cleanup.
|
||||
mostRecentBackupFile = new FileUtils.File(mostRecentBackupFile);
|
||||
mostRecentBackupFile.remove(false);
|
||||
do_check_false(mostRecentBackupFile.exists());
|
||||
|
||||
do_test_finished()
|
||||
});
|
||||
}
|
||||
56
toolkit/components/places/tests/bookmarks/test_675416.js
Normal file
56
toolkit/components/places/tests/bookmarks/test_675416.js
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
/**
|
||||
* Requests information to the service, so that bookmark's data is cached.
|
||||
* @param aItemId
|
||||
* Id of the bookmark to be cached.
|
||||
*/
|
||||
function forceBookmarkCaching(aItemId) {
|
||||
PlacesUtils.bookmarks.getFolderIdForItem(aItemId);
|
||||
}
|
||||
|
||||
let observer = {
|
||||
onBeginUpdateBatch: () => forceBookmarkCaching(itemId1),
|
||||
onEndUpdateBatch: () => forceBookmarkCaching(itemId1),
|
||||
onItemAdded: forceBookmarkCaching,
|
||||
onItemChanged: forceBookmarkCaching,
|
||||
onItemMoved: forceBookmarkCaching,
|
||||
onItemRemoved: function(id) {
|
||||
try {
|
||||
forceBookmarkCaching(id);
|
||||
do_throw("trying to fetch a removed bookmark should throw");
|
||||
} catch (ex) {}
|
||||
},
|
||||
onItemVisited: forceBookmarkCaching,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
|
||||
};
|
||||
PlacesUtils.bookmarks.addObserver(observer, false);
|
||||
|
||||
let folderId1 = PlacesUtils.bookmarks
|
||||
.createFolder(PlacesUtils.bookmarksMenuFolderId,
|
||||
"Bookmarks",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
let itemId1 = PlacesUtils.bookmarks
|
||||
.insertBookmark(folderId1,
|
||||
NetUtil.newURI("http:/www.wired.com/wiredscience"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"Wired Science");
|
||||
|
||||
PlacesUtils.bookmarks.removeItem(folderId1);
|
||||
|
||||
let folderId2 = PlacesUtils.bookmarks
|
||||
.createFolder(PlacesUtils.bookmarksMenuFolderId,
|
||||
"Science",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
let folderId3 = PlacesUtils.bookmarks
|
||||
.createFolder(folderId2,
|
||||
"Blogs",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
// Check title is correctly reported.
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemTitle(folderId3), "Blogs");
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemTitle(folderId2), "Science");
|
||||
|
||||
PlacesUtils.bookmarks.removeObserver(observer, false);
|
||||
}
|
||||
56
toolkit/components/places/tests/bookmarks/test_711914.js
Normal file
56
toolkit/components/places/tests/bookmarks/test_711914.js
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
/**
|
||||
* Requests information to the service, so that bookmark's data is cached.
|
||||
* @param aItemId
|
||||
* Id of the bookmark to be cached.
|
||||
*/
|
||||
function forceBookmarkCaching(aItemId) {
|
||||
let parent = PlacesUtils.bookmarks.getFolderIdForItem(aItemId);
|
||||
PlacesUtils.bookmarks.getFolderIdForItem(parent);
|
||||
}
|
||||
|
||||
let observer = {
|
||||
onBeginUpdateBatch: () => forceBookmarkCaching(itemId1),
|
||||
onEndUpdateBatch: () => forceBookmarkCaching(itemId1),
|
||||
onItemAdded: forceBookmarkCaching,
|
||||
onItemChanged: forceBookmarkCaching,
|
||||
onItemMoved: forceBookmarkCaching,
|
||||
onItemRemoved: function (id) {
|
||||
try {
|
||||
forceBookmarkCaching(id);
|
||||
do_throw("trying to fetch a removed bookmark should throw");
|
||||
} catch (ex) {}
|
||||
},
|
||||
onItemVisited: forceBookmarkCaching,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
|
||||
};
|
||||
PlacesUtils.bookmarks.addObserver(observer, false);
|
||||
|
||||
let folder1 = PlacesUtils.bookmarks
|
||||
.createFolder(PlacesUtils.bookmarksMenuFolderId,
|
||||
"Folder1",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
let folder2 = PlacesUtils.bookmarks
|
||||
.createFolder(folder1,
|
||||
"Folder2",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.insertBookmark(folder2,
|
||||
NetUtil.newURI("http://mozilla.org/"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"Mozilla");
|
||||
|
||||
PlacesUtils.bookmarks.removeFolderChildren(folder1);
|
||||
|
||||
// Check title is correctly reported.
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemTitle(folder1), "Folder1");
|
||||
try {
|
||||
PlacesUtils.bookmarks.getItemTitle(folder2);
|
||||
do_throw("trying to fetch a removed bookmark should throw");
|
||||
} catch (ex) {}
|
||||
|
||||
PlacesUtils.bookmarks.removeObserver(observer, false);
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Checks that automatically created bookmark backups are discarded if they are
|
||||
* duplicate of an existing ones.
|
||||
*/
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function*() {
|
||||
// Create a backup for yesterday in the backups folder.
|
||||
let backupFolder = yield PlacesBackups.getBackupFolder();
|
||||
let dateObj = new Date();
|
||||
dateObj.setDate(dateObj.getDate() - 1);
|
||||
let oldBackupName = PlacesBackups.getFilenameForDate(dateObj);
|
||||
let oldBackup = OS.Path.join(backupFolder, oldBackupName);
|
||||
let {count: count, hash: hash} = yield BookmarkJSONUtils.exportToFile(oldBackup);
|
||||
do_check_true(count > 0);
|
||||
do_check_eq(hash.length, 24);
|
||||
oldBackupName = oldBackupName.replace(/\.json/, "_" + count + "_" + hash + ".json");
|
||||
yield OS.File.move(oldBackup, OS.Path.join(backupFolder, oldBackupName));
|
||||
|
||||
// Create a backup.
|
||||
// This should just rename the existing backup, so in the end there should be
|
||||
// only one backup with today's date.
|
||||
yield PlacesBackups.create();
|
||||
|
||||
// Get the hash of the generated backup
|
||||
let backupFiles = yield PlacesBackups.getBackupFiles();
|
||||
do_check_eq(backupFiles.length, 1);
|
||||
|
||||
let matches = OS.Path.basename(backupFiles[0]).match(PlacesBackups.filenamesRegex);
|
||||
do_check_eq(matches[1], PlacesBackups.toISODateString(new Date()));
|
||||
do_check_eq(matches[2], count);
|
||||
do_check_eq(matches[3], hash);
|
||||
|
||||
// Add a bookmark and create another backup.
|
||||
let bookmarkId = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarks.bookmarksMenuFolder,
|
||||
uri("http://foo.com"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"foo");
|
||||
// We must enforce a backup since one for today already exists. The forced
|
||||
// backup will replace the existing one.
|
||||
yield PlacesBackups.create(undefined, true);
|
||||
do_check_eq(backupFiles.length, 1);
|
||||
recentBackup = yield PlacesBackups.getMostRecentBackup();
|
||||
do_check_neq(recentBackup, OS.Path.join(backupFolder, oldBackupName));
|
||||
matches = OS.Path.basename(recentBackup).match(PlacesBackups.filenamesRegex);
|
||||
do_check_eq(matches[1], PlacesBackups.toISODateString(new Date()));
|
||||
do_check_eq(matches[2], count + 1);
|
||||
do_check_neq(matches[3], hash);
|
||||
|
||||
// Clean up
|
||||
PlacesUtils.bookmarks.removeItem(bookmarkId);
|
||||
yield PlacesBackups.create(0);
|
||||
});
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* compress_bookmark_backups_test() {
|
||||
// Check for jsonlz4 extension
|
||||
let todayFilename = PlacesBackups.getFilenameForDate(new Date(2014, 4, 15), true);
|
||||
do_check_eq(todayFilename, "bookmarks-2014-05-15.jsonlz4");
|
||||
|
||||
yield PlacesBackups.create();
|
||||
|
||||
// Check that a backup for today has been created and the regex works fine for lz4.
|
||||
do_check_eq((yield PlacesBackups.getBackupFiles()).length, 1);
|
||||
let mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup();
|
||||
do_check_neq(mostRecentBackupFile, null);
|
||||
do_check_true(PlacesBackups.filenamesRegex.test(OS.Path.basename(mostRecentBackupFile)));
|
||||
|
||||
// The most recent backup file has to be removed since saveBookmarksToJSONFile
|
||||
// will otherwise over-write the current backup, since it will be made on the
|
||||
// same date
|
||||
yield OS.File.remove(mostRecentBackupFile);
|
||||
do_check_false((yield OS.File.exists(mostRecentBackupFile)));
|
||||
|
||||
// Check that, if the user created a custom backup out of the default
|
||||
// backups folder, it gets copied (compressed) into it.
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
yield PlacesBackups.saveBookmarksToJSONFile(jsonFile);
|
||||
do_check_eq((yield PlacesBackups.getBackupFiles()).length, 1);
|
||||
|
||||
// Check if import works from lz4 compressed json
|
||||
let uri = NetUtil.newURI("http://www.mozilla.org/en-US/");
|
||||
let bm = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
uri,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
|
||||
// Force create a compressed backup, Remove the bookmark, the restore the backup
|
||||
yield PlacesBackups.create(undefined, true);
|
||||
let recentBackup = yield PlacesBackups.getMostRecentBackup();
|
||||
PlacesUtils.bookmarks.removeItem(bm);
|
||||
yield BookmarkJSONUtils.importFromFile(recentBackup, true);
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
|
||||
let node = root.getChild(0);
|
||||
do_check_eq(node.uri, uri.spec);
|
||||
|
||||
root.containerOpen = false;
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
|
||||
// Cleanup.
|
||||
yield OS.File.remove(jsonFile);
|
||||
});
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* To confirm that metadata i.e. bookmark count is set and retrieved for
|
||||
* automatic backups.
|
||||
*/
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* test_saveBookmarksToJSONFile_and_create()
|
||||
{
|
||||
// Add a bookmark
|
||||
let uri = NetUtil.newURI("http://getfirefox.com/");
|
||||
let bookmarkId =
|
||||
PlacesUtils.bookmarks.insertBookmark(
|
||||
PlacesUtils.unfiledBookmarksFolderId, uri,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
|
||||
|
||||
// Test saveBookmarksToJSONFile()
|
||||
let backupFile = FileUtils.getFile("TmpD", ["bookmarks.json"]);
|
||||
backupFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, parseInt("0600", 8));
|
||||
|
||||
let nodeCount = yield PlacesBackups.saveBookmarksToJSONFile(backupFile, true);
|
||||
do_check_true(nodeCount > 0);
|
||||
do_check_true(backupFile.exists());
|
||||
do_check_eq(backupFile.leafName, "bookmarks.json");
|
||||
|
||||
// Ensure the backup would be copied to our backups folder when the original
|
||||
// backup is saved somewhere else.
|
||||
let recentBackup = yield PlacesBackups.getMostRecentBackup();
|
||||
let matches = OS.Path.basename(recentBackup).match(PlacesBackups.filenamesRegex);
|
||||
do_check_eq(matches[2], nodeCount);
|
||||
do_check_eq(matches[3].length, 24);
|
||||
|
||||
// Clear all backups in our backups folder.
|
||||
yield PlacesBackups.create(0);
|
||||
do_check_eq((yield PlacesBackups.getBackupFiles()).length, 0);
|
||||
|
||||
// Test create() which saves bookmarks with metadata on the filename.
|
||||
yield PlacesBackups.create();
|
||||
do_check_eq((yield PlacesBackups.getBackupFiles()).length, 1);
|
||||
|
||||
mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup();
|
||||
do_check_neq(mostRecentBackupFile, null);
|
||||
matches = OS.Path.basename(recentBackup).match(PlacesBackups.filenamesRegex);
|
||||
do_check_eq(matches[2], nodeCount);
|
||||
do_check_eq(matches[3].length, 24);
|
||||
|
||||
// Cleanup
|
||||
backupFile.remove(false);
|
||||
yield PlacesBackups.create(0);
|
||||
PlacesUtils.bookmarks.removeItem(bookmarkId);
|
||||
});
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Checks that backups properly include all of the bookmarks if the hierarchy
|
||||
* in the database is unordered so that a hierarchy is defined before its
|
||||
* ancestor in the bookmarks table.
|
||||
*/
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function*() {
|
||||
let bm = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
NetUtil.newURI("http://mozilla.org/"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
let f2 = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId, "f2",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.moveItem(bm, f2, PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
let f1 = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId, "f1",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.moveItem(f2, f1, PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
|
||||
// Create a backup.
|
||||
yield PlacesBackups.create();
|
||||
|
||||
// Remove the bookmarks, then restore the backup.
|
||||
PlacesUtils.bookmarks.removeItem(f1);
|
||||
yield BookmarkJSONUtils.importFromFile((yield PlacesBackups.getMostRecentBackup()), true);
|
||||
|
||||
do_print("Checking first level");
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
|
||||
let level1 = root.getChild(0);
|
||||
do_check_eq(level1.title, "f1");
|
||||
do_print("Checking second level");
|
||||
PlacesUtils.asContainer(level1).containerOpen = true
|
||||
let level2 = level1.getChild(0);
|
||||
do_check_eq(level2.title, "f2");
|
||||
do_print("Checking bookmark");
|
||||
PlacesUtils.asContainer(level2).containerOpen = true
|
||||
let bookmark = level2.getChild(0);
|
||||
do_check_eq(bookmark.title, "bookmark");
|
||||
level2.containerOpen = false;
|
||||
level1.containerOpen = false;
|
||||
root.containerOpen = false;
|
||||
});
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Checks that we don't encodeURI twice when creating bookmarks.html.
|
||||
*/
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
let uri = NetUtil.newURI("http://bt.ktxp.com/search.php?keyword=%E5%A6%84%E6%83%B3%E5%AD%A6%E7%94%9F%E4%BC%9A");
|
||||
let bm = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
uri,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
|
||||
let file = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.exported.997030.html");
|
||||
if ((yield OS.File.exists(file))) {
|
||||
yield OS.File.remove(file);
|
||||
}
|
||||
yield BookmarkHTMLUtils.exportToFile(file);
|
||||
|
||||
// Remove the bookmarks, then restore the backup.
|
||||
PlacesUtils.bookmarks.removeItem(bm);
|
||||
yield BookmarkHTMLUtils.importFromFile(file, true);
|
||||
|
||||
do_print("Checking first level");
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
|
||||
let node = root.getChild(0);
|
||||
do_check_eq(node.uri, uri.spec);
|
||||
|
||||
root.containerOpen = false;
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
});
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* This test checks that bookmarks service is correctly forwarding async
|
||||
* events like visit or favicon additions. */
|
||||
|
||||
const NOW = Date.now() * 1000;
|
||||
|
||||
var observer = {
|
||||
bookmarks: [],
|
||||
observedBookmarks: 0,
|
||||
observedVisitId: 0,
|
||||
deferred: null,
|
||||
|
||||
/**
|
||||
* Returns a promise that is resolved when the observer determines that the
|
||||
* test can continue. This is required rather than calling run_next_test
|
||||
* directly in the observer because there are cases where we must wait for
|
||||
* other asynchronous events to be completed in addition to this.
|
||||
*/
|
||||
setupCompletionPromise: function ()
|
||||
{
|
||||
this.observedBookmarks = 0;
|
||||
this.deferred = Promise.defer();
|
||||
return this.deferred.promise;
|
||||
},
|
||||
|
||||
onBeginUpdateBatch: function () {},
|
||||
onEndUpdateBatch: function () {},
|
||||
onItemAdded: function () {},
|
||||
onItemRemoved: function () {},
|
||||
onItemMoved: function () {},
|
||||
onItemChanged: function(aItemId, aProperty, aIsAnnotation, aNewValue,
|
||||
aLastModified, aItemType)
|
||||
{
|
||||
do_print("Check that we got the correct change information.");
|
||||
do_check_neq(this.bookmarks.indexOf(aItemId), -1);
|
||||
if (aProperty == "favicon") {
|
||||
do_check_false(aIsAnnotation);
|
||||
do_check_eq(aNewValue, SMALLPNG_DATA_URI.spec);
|
||||
do_check_eq(aLastModified, 0);
|
||||
do_check_eq(aItemType, PlacesUtils.bookmarks.TYPE_BOOKMARK);
|
||||
}
|
||||
else if (aProperty == "cleartime") {
|
||||
do_check_false(aIsAnnotation);
|
||||
do_check_eq(aNewValue, "");
|
||||
do_check_eq(aLastModified, 0);
|
||||
do_check_eq(aItemType, PlacesUtils.bookmarks.TYPE_BOOKMARK);
|
||||
}
|
||||
else {
|
||||
do_throw("Unexpected property change " + aProperty);
|
||||
}
|
||||
|
||||
if (++this.observedBookmarks == this.bookmarks.length) {
|
||||
this.deferred.resolve();
|
||||
}
|
||||
},
|
||||
onItemVisited: function(aItemId, aVisitId, aTime)
|
||||
{
|
||||
do_print("Check that we got the correct visit information.");
|
||||
do_check_neq(this.bookmarks.indexOf(aItemId), -1);
|
||||
this.observedVisitId = aVisitId;
|
||||
do_check_eq(aTime, NOW);
|
||||
if (++this.observedBookmarks == this.bookmarks.length) {
|
||||
this.deferred.resolve();
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsINavBookmarkObserver,
|
||||
])
|
||||
};
|
||||
PlacesUtils.bookmarks.addObserver(observer, false);
|
||||
|
||||
add_task(function* test_add_visit()
|
||||
{
|
||||
let observerPromise = observer.setupCompletionPromise();
|
||||
|
||||
// Add a visit to the bookmark and wait for the observer.
|
||||
let visitId;
|
||||
let deferUpdatePlaces = Promise.defer();
|
||||
PlacesUtils.asyncHistory.updatePlaces({
|
||||
uri: NetUtil.newURI("http://book.ma.rk/"),
|
||||
visits: [{ transitionType: TRANSITION_TYPED, visitDate: NOW }]
|
||||
}, {
|
||||
handleError: function TAV_handleError() {
|
||||
deferUpdatePlaces.reject(new Error("Unexpected error in adding visit."));
|
||||
},
|
||||
handleResult: function (aPlaceInfo) {
|
||||
visitId = aPlaceInfo.visits[0].visitId;
|
||||
},
|
||||
handleCompletion: function TAV_handleCompletion() {
|
||||
deferUpdatePlaces.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
// Wait for both the observer and the asynchronous update, in any order.
|
||||
yield deferUpdatePlaces.promise;
|
||||
yield observerPromise;
|
||||
|
||||
// Check that both asynchronous results are consistent.
|
||||
do_check_eq(observer.observedVisitId, visitId);
|
||||
});
|
||||
|
||||
add_task(function* test_add_icon()
|
||||
{
|
||||
let observerPromise = observer.setupCompletionPromise();
|
||||
PlacesUtils.favicons.setAndFetchFaviconForPage(NetUtil.newURI("http://book.ma.rk/"),
|
||||
SMALLPNG_DATA_URI, true,
|
||||
PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
|
||||
null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
yield observerPromise;
|
||||
});
|
||||
|
||||
add_task(function* test_remove_page()
|
||||
{
|
||||
let observerPromise = observer.setupCompletionPromise();
|
||||
PlacesUtils.history.removePage(NetUtil.newURI("http://book.ma.rk/"));
|
||||
yield observerPromise;
|
||||
});
|
||||
|
||||
add_task(function cleanup()
|
||||
{
|
||||
PlacesUtils.bookmarks.removeObserver(observer, false);
|
||||
});
|
||||
|
||||
add_task(function* shutdown()
|
||||
{
|
||||
// Check that async observers don't try to create async statements after
|
||||
// shutdown. That would cause assertions, since the async thread is gone
|
||||
// already. Note that in such a case the notifications are not fired, so we
|
||||
// cannot test for them.
|
||||
// Put an history notification that triggers AsyncGetBookmarksForURI between
|
||||
// asyncClose() and the actual connection closing. Enqueuing a main-thread
|
||||
// event just after places-will-close-connection should ensure it runs before
|
||||
// places-connection-closed.
|
||||
// Notice this code is not using helpers cause it depends on a very specific
|
||||
// order, a change in the helpers code could make this test useless.
|
||||
let deferred = Promise.defer();
|
||||
|
||||
Services.obs.addObserver(function onNotification() {
|
||||
Services.obs.removeObserver(onNotification, "places-will-close-connection");
|
||||
do_check_true(true, "Observed fake places shutdown");
|
||||
|
||||
Services.tm.mainThread.dispatch(() => {
|
||||
// WARNING: this is very bad, never use out of testing code.
|
||||
PlacesUtils.bookmarks.QueryInterface(Ci.nsINavHistoryObserver)
|
||||
.onPageChanged(NetUtil.newURI("http://book.ma.rk/"),
|
||||
Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON,
|
||||
"test", "test");
|
||||
deferred.resolve(promiseTopicObserved("places-connection-closed"));
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}, "places-will-close-connection", false);
|
||||
shutdownPlaces();
|
||||
|
||||
yield deferred.promise;
|
||||
});
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// Add multiple bookmarks to the same uri.
|
||||
observer.bookmarks.push(
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
NetUtil.newURI("http://book.ma.rk/"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"Bookmark")
|
||||
);
|
||||
observer.bookmarks.push(
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId,
|
||||
NetUtil.newURI("http://book.ma.rk/"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"Bookmark")
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
124
toolkit/components/places/tests/bookmarks/test_bmindex.js
Normal file
124
toolkit/components/places/tests/bookmarks/test_bmindex.js
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const NUM_BOOKMARKS = 20;
|
||||
const NUM_SEPARATORS = 5;
|
||||
const NUM_FOLDERS = 10;
|
||||
const NUM_ITEMS = NUM_BOOKMARKS + NUM_SEPARATORS + NUM_FOLDERS;
|
||||
const MIN_RAND = -5;
|
||||
const MAX_RAND = 40;
|
||||
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
|
||||
function check_contiguous_indexes(aBookmarks) {
|
||||
var indexes = [];
|
||||
aBookmarks.forEach(function(aBookmarkId) {
|
||||
let bmIndex = bs.getItemIndex(aBookmarkId);
|
||||
dump("Index: " + bmIndex + "\n");
|
||||
dump("Checking duplicates\n");
|
||||
do_check_eq(indexes.indexOf(bmIndex), -1);
|
||||
dump("Checking out of range, found " + aBookmarks.length + " items\n");
|
||||
do_check_true(bmIndex >= 0 && bmIndex < aBookmarks.length);
|
||||
indexes.push(bmIndex);
|
||||
});
|
||||
dump("Checking all valid indexes have been used\n");
|
||||
do_check_eq(indexes.length, aBookmarks.length);
|
||||
}
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
var bookmarks = [];
|
||||
// Insert bookmarks with random indexes.
|
||||
for (let i = 0; bookmarks.length < NUM_BOOKMARKS; i++) {
|
||||
let randIndex = Math.round(MIN_RAND + (Math.random() * (MAX_RAND - MIN_RAND)));
|
||||
try {
|
||||
let id = bs.insertBookmark(bs.unfiledBookmarksFolder,
|
||||
uri("http://" + i + ".mozilla.org/"),
|
||||
randIndex, "Test bookmark " + i);
|
||||
if (randIndex < -1)
|
||||
do_throw("Creating a bookmark at an invalid index should throw");
|
||||
bookmarks.push(id);
|
||||
}
|
||||
catch (ex) {
|
||||
if (randIndex >= -1)
|
||||
do_throw("Creating a bookmark at a valid index should not throw");
|
||||
}
|
||||
}
|
||||
check_contiguous_indexes(bookmarks);
|
||||
|
||||
// Insert separators with random indexes.
|
||||
for (let i = 0; bookmarks.length < NUM_BOOKMARKS + NUM_SEPARATORS; i++) {
|
||||
let randIndex = Math.round(MIN_RAND + (Math.random() * (MAX_RAND - MIN_RAND)));
|
||||
try {
|
||||
let id = bs.insertSeparator(bs.unfiledBookmarksFolder, randIndex);
|
||||
if (randIndex < -1)
|
||||
do_throw("Creating a separator at an invalid index should throw");
|
||||
bookmarks.push(id);
|
||||
}
|
||||
catch (ex) {
|
||||
if (randIndex >= -1)
|
||||
do_throw("Creating a separator at a valid index should not throw");
|
||||
}
|
||||
}
|
||||
check_contiguous_indexes(bookmarks);
|
||||
|
||||
// Insert folders with random indexes.
|
||||
for (let i = 0; bookmarks.length < NUM_ITEMS; i++) {
|
||||
let randIndex = Math.round(MIN_RAND + (Math.random() * (MAX_RAND - MIN_RAND)));
|
||||
try {
|
||||
let id = bs.createFolder(bs.unfiledBookmarksFolder,
|
||||
"Test folder " + i, randIndex);
|
||||
if (randIndex < -1)
|
||||
do_throw("Creating a folder at an invalid index should throw");
|
||||
bookmarks.push(id);
|
||||
}
|
||||
catch (ex) {
|
||||
if (randIndex >= -1)
|
||||
do_throw("Creating a folder at a valid index should not throw");
|
||||
}
|
||||
}
|
||||
check_contiguous_indexes(bookmarks);
|
||||
|
||||
// Execute some random bookmark delete.
|
||||
for (let i = 0; i < Math.ceil(NUM_ITEMS / 4); i++) {
|
||||
let id = bookmarks.splice(Math.floor(Math.random() * bookmarks.length), 1);
|
||||
dump("Removing item with id " + id + "\n");
|
||||
bs.removeItem(id);
|
||||
}
|
||||
check_contiguous_indexes(bookmarks);
|
||||
|
||||
// Execute some random bookmark move. This will also try to move it to
|
||||
// invalid index values.
|
||||
for (let i = 0; i < Math.ceil(NUM_ITEMS / 4); i++) {
|
||||
let randIndex = Math.floor(Math.random() * bookmarks.length);
|
||||
let id = bookmarks[randIndex];
|
||||
let newIndex = Math.round(MIN_RAND + (Math.random() * (MAX_RAND - MIN_RAND)));
|
||||
dump("Moving item with id " + id + " to index " + newIndex + "\n");
|
||||
try {
|
||||
bs.moveItem(id, bs.unfiledBookmarksFolder, newIndex);
|
||||
if (newIndex < -1)
|
||||
do_throw("Moving an item to a negative index should throw\n");
|
||||
}
|
||||
catch (ex) {
|
||||
if (newIndex >= -1)
|
||||
do_throw("Moving an item to a valid index should not throw\n");
|
||||
}
|
||||
|
||||
}
|
||||
check_contiguous_indexes(bookmarks);
|
||||
|
||||
// Ensure setItemIndex throws if we pass it a negative index.
|
||||
try {
|
||||
bs.setItemIndex(bookmarks[0], -1);
|
||||
do_throw("setItemIndex should throw for a negative index");
|
||||
} catch (ex) {}
|
||||
// Ensure setItemIndex throws if we pass it a bad itemId.
|
||||
try {
|
||||
bs.setItemIndex(0, 5);
|
||||
do_throw("setItemIndex should throw for a bad itemId");
|
||||
} catch (ex) {}
|
||||
}
|
||||
718
toolkit/components/places/tests/bookmarks/test_bookmarks.js
Normal file
718
toolkit/components/places/tests/bookmarks/test_bookmarks.js
Normal file
|
|
@ -0,0 +1,718 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var bs = PlacesUtils.bookmarks;
|
||||
var hs = PlacesUtils.history;
|
||||
var anno = PlacesUtils.annotations;
|
||||
|
||||
|
||||
var bookmarksObserver = {
|
||||
onBeginUpdateBatch: function() {
|
||||
this._beginUpdateBatch = true;
|
||||
},
|
||||
onEndUpdateBatch: function() {
|
||||
this._endUpdateBatch = true;
|
||||
},
|
||||
onItemAdded: function(id, folder, index, itemType, uri, title, dateAdded,
|
||||
guid) {
|
||||
this._itemAddedId = id;
|
||||
this._itemAddedParent = folder;
|
||||
this._itemAddedIndex = index;
|
||||
this._itemAddedURI = uri;
|
||||
this._itemAddedTitle = title;
|
||||
|
||||
// Ensure that we've created a guid for this item.
|
||||
let stmt = DBConn().createStatement(
|
||||
`SELECT guid
|
||||
FROM moz_bookmarks
|
||||
WHERE id = :item_id`
|
||||
);
|
||||
stmt.params.item_id = id;
|
||||
do_check_true(stmt.executeStep());
|
||||
do_check_false(stmt.getIsNull(0));
|
||||
do_check_valid_places_guid(stmt.row.guid);
|
||||
do_check_eq(stmt.row.guid, guid);
|
||||
stmt.finalize();
|
||||
},
|
||||
onItemRemoved: function(id, folder, index, itemType) {
|
||||
this._itemRemovedId = id;
|
||||
this._itemRemovedFolder = folder;
|
||||
this._itemRemovedIndex = index;
|
||||
},
|
||||
onItemChanged: function(id, property, isAnnotationProperty, value,
|
||||
lastModified, itemType, parentId, guid, parentGuid,
|
||||
oldValue) {
|
||||
this._itemChangedId = id;
|
||||
this._itemChangedProperty = property;
|
||||
this._itemChanged_isAnnotationProperty = isAnnotationProperty;
|
||||
this._itemChangedValue = value;
|
||||
this._itemChangedOldValue = oldValue;
|
||||
},
|
||||
onItemVisited: function(id, visitID, time) {
|
||||
this._itemVisitedId = id;
|
||||
this._itemVisitedVistId = visitID;
|
||||
this._itemVisitedTime = time;
|
||||
},
|
||||
onItemMoved: function(id, oldParent, oldIndex, newParent, newIndex,
|
||||
itemType) {
|
||||
this._itemMovedId = id
|
||||
this._itemMovedOldParent = oldParent;
|
||||
this._itemMovedOldIndex = oldIndex;
|
||||
this._itemMovedNewParent = newParent;
|
||||
this._itemMovedNewIndex = newIndex;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsINavBookmarkObserver,
|
||||
])
|
||||
};
|
||||
|
||||
|
||||
// Get bookmarks menu folder id.
|
||||
var root = bs.bookmarksMenuFolder;
|
||||
// Index at which items should begin.
|
||||
var bmStartIndex = 0;
|
||||
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* test_bookmarks() {
|
||||
bs.addObserver(bookmarksObserver, false);
|
||||
|
||||
// test special folders
|
||||
do_check_true(bs.placesRoot > 0);
|
||||
do_check_true(bs.bookmarksMenuFolder > 0);
|
||||
do_check_true(bs.tagsFolder > 0);
|
||||
do_check_true(bs.toolbarFolder > 0);
|
||||
do_check_true(bs.unfiledBookmarksFolder > 0);
|
||||
|
||||
// test getFolderIdForItem() with bogus item id will throw
|
||||
try {
|
||||
bs.getFolderIdForItem(0);
|
||||
do_throw("getFolderIdForItem accepted bad input");
|
||||
} catch (ex) {}
|
||||
|
||||
// test getFolderIdForItem() with bogus item id will throw
|
||||
try {
|
||||
bs.getFolderIdForItem(-1);
|
||||
do_throw("getFolderIdForItem accepted bad input");
|
||||
} catch (ex) {}
|
||||
|
||||
// test root parentage
|
||||
do_check_eq(bs.getFolderIdForItem(bs.bookmarksMenuFolder), bs.placesRoot);
|
||||
do_check_eq(bs.getFolderIdForItem(bs.tagsFolder), bs.placesRoot);
|
||||
do_check_eq(bs.getFolderIdForItem(bs.toolbarFolder), bs.placesRoot);
|
||||
do_check_eq(bs.getFolderIdForItem(bs.unfiledBookmarksFolder), bs.placesRoot);
|
||||
|
||||
// create a folder to hold all the tests
|
||||
// this makes the tests more tolerant of changes to default_places.html
|
||||
let testRoot = bs.createFolder(root, "places bookmarks xpcshell tests",
|
||||
bs.DEFAULT_INDEX);
|
||||
do_check_eq(bookmarksObserver._itemAddedId, testRoot);
|
||||
do_check_eq(bookmarksObserver._itemAddedParent, root);
|
||||
do_check_eq(bookmarksObserver._itemAddedIndex, bmStartIndex);
|
||||
do_check_eq(bookmarksObserver._itemAddedURI, null);
|
||||
let testStartIndex = 0;
|
||||
|
||||
// test getItemIndex for folders
|
||||
do_check_eq(bs.getItemIndex(testRoot), bmStartIndex);
|
||||
|
||||
// test getItemType for folders
|
||||
do_check_eq(bs.getItemType(testRoot), bs.TYPE_FOLDER);
|
||||
|
||||
// insert a bookmark.
|
||||
// the time before we insert, in microseconds
|
||||
let beforeInsert = Date.now() * 1000;
|
||||
do_check_true(beforeInsert > 0);
|
||||
|
||||
let newId = bs.insertBookmark(testRoot, uri("http://google.com/"),
|
||||
bs.DEFAULT_INDEX, "");
|
||||
do_check_eq(bookmarksObserver._itemAddedId, newId);
|
||||
do_check_eq(bookmarksObserver._itemAddedParent, testRoot);
|
||||
do_check_eq(bookmarksObserver._itemAddedIndex, testStartIndex);
|
||||
do_check_true(bookmarksObserver._itemAddedURI.equals(uri("http://google.com/")));
|
||||
do_check_eq(bs.getBookmarkURI(newId).spec, "http://google.com/");
|
||||
|
||||
let dateAdded = bs.getItemDateAdded(newId);
|
||||
// dateAdded can equal beforeInsert
|
||||
do_check_true(is_time_ordered(beforeInsert, dateAdded));
|
||||
|
||||
// after just inserting, modified should not be set
|
||||
let lastModified = bs.getItemLastModified(newId);
|
||||
do_check_eq(lastModified, dateAdded);
|
||||
|
||||
// The time before we set the title, in microseconds.
|
||||
let beforeSetTitle = Date.now() * 1000;
|
||||
do_check_true(beforeSetTitle >= beforeInsert);
|
||||
|
||||
// Workaround possible VM timers issues moving lastModified and dateAdded
|
||||
// to the past.
|
||||
lastModified -= 1000;
|
||||
bs.setItemLastModified(newId, lastModified);
|
||||
dateAdded -= 1000;
|
||||
bs.setItemDateAdded(newId, dateAdded);
|
||||
|
||||
// set bookmark title
|
||||
bs.setItemTitle(newId, "Google");
|
||||
do_check_eq(bookmarksObserver._itemChangedId, newId);
|
||||
do_check_eq(bookmarksObserver._itemChangedProperty, "title");
|
||||
do_check_eq(bookmarksObserver._itemChangedValue, "Google");
|
||||
|
||||
// check that dateAdded hasn't changed
|
||||
let dateAdded2 = bs.getItemDateAdded(newId);
|
||||
do_check_eq(dateAdded2, dateAdded);
|
||||
|
||||
// check lastModified after we set the title
|
||||
let lastModified2 = bs.getItemLastModified(newId);
|
||||
do_print("test setItemTitle");
|
||||
do_print("dateAdded = " + dateAdded);
|
||||
do_print("beforeSetTitle = " + beforeSetTitle);
|
||||
do_print("lastModified = " + lastModified);
|
||||
do_print("lastModified2 = " + lastModified2);
|
||||
do_check_true(is_time_ordered(lastModified, lastModified2));
|
||||
do_check_true(is_time_ordered(dateAdded, lastModified2));
|
||||
|
||||
// get item title
|
||||
let title = bs.getItemTitle(newId);
|
||||
do_check_eq(title, "Google");
|
||||
|
||||
// test getItemType for bookmarks
|
||||
do_check_eq(bs.getItemType(newId), bs.TYPE_BOOKMARK);
|
||||
|
||||
// get item title bad input
|
||||
try {
|
||||
bs.getItemTitle(-3);
|
||||
do_throw("getItemTitle accepted bad input");
|
||||
} catch (ex) {}
|
||||
|
||||
// get the folder that the bookmark is in
|
||||
let folderId = bs.getFolderIdForItem(newId);
|
||||
do_check_eq(folderId, testRoot);
|
||||
|
||||
// test getItemIndex for bookmarks
|
||||
do_check_eq(bs.getItemIndex(newId), testStartIndex);
|
||||
|
||||
// create a folder at a specific index
|
||||
let workFolder = bs.createFolder(testRoot, "Work", 0);
|
||||
do_check_eq(bookmarksObserver._itemAddedId, workFolder);
|
||||
do_check_eq(bookmarksObserver._itemAddedParent, testRoot);
|
||||
do_check_eq(bookmarksObserver._itemAddedIndex, 0);
|
||||
do_check_eq(bookmarksObserver._itemAddedURI, null);
|
||||
|
||||
do_check_eq(bs.getItemTitle(workFolder), "Work");
|
||||
bs.setItemTitle(workFolder, "Work #");
|
||||
do_check_eq(bs.getItemTitle(workFolder), "Work #");
|
||||
|
||||
// add item into subfolder, specifying index
|
||||
let newId2 = bs.insertBookmark(workFolder,
|
||||
uri("http://developer.mozilla.org/"),
|
||||
0, "");
|
||||
do_check_eq(bookmarksObserver._itemAddedId, newId2);
|
||||
do_check_eq(bookmarksObserver._itemAddedParent, workFolder);
|
||||
do_check_eq(bookmarksObserver._itemAddedIndex, 0);
|
||||
|
||||
// change item
|
||||
bs.setItemTitle(newId2, "DevMo");
|
||||
do_check_eq(bookmarksObserver._itemChangedProperty, "title");
|
||||
|
||||
// insert item into subfolder
|
||||
let newId3 = bs.insertBookmark(workFolder,
|
||||
uri("http://msdn.microsoft.com/"),
|
||||
bs.DEFAULT_INDEX, "");
|
||||
do_check_eq(bookmarksObserver._itemAddedId, newId3);
|
||||
do_check_eq(bookmarksObserver._itemAddedParent, workFolder);
|
||||
do_check_eq(bookmarksObserver._itemAddedIndex, 1);
|
||||
|
||||
// change item
|
||||
bs.setItemTitle(newId3, "MSDN");
|
||||
do_check_eq(bookmarksObserver._itemChangedProperty, "title");
|
||||
|
||||
// remove item
|
||||
bs.removeItem(newId2);
|
||||
do_check_eq(bookmarksObserver._itemRemovedId, newId2);
|
||||
do_check_eq(bookmarksObserver._itemRemovedFolder, workFolder);
|
||||
do_check_eq(bookmarksObserver._itemRemovedIndex, 0);
|
||||
|
||||
// insert item into subfolder
|
||||
let newId4 = bs.insertBookmark(workFolder,
|
||||
uri("http://developer.mozilla.org/"),
|
||||
bs.DEFAULT_INDEX, "");
|
||||
do_check_eq(bookmarksObserver._itemAddedId, newId4);
|
||||
do_check_eq(bookmarksObserver._itemAddedParent, workFolder);
|
||||
do_check_eq(bookmarksObserver._itemAddedIndex, 1);
|
||||
|
||||
// create folder
|
||||
let homeFolder = bs.createFolder(testRoot, "Home", bs.DEFAULT_INDEX);
|
||||
do_check_eq(bookmarksObserver._itemAddedId, homeFolder);
|
||||
do_check_eq(bookmarksObserver._itemAddedParent, testRoot);
|
||||
do_check_eq(bookmarksObserver._itemAddedIndex, 2);
|
||||
|
||||
// insert item
|
||||
let newId5 = bs.insertBookmark(homeFolder, uri("http://espn.com/"),
|
||||
bs.DEFAULT_INDEX, "");
|
||||
do_check_eq(bookmarksObserver._itemAddedId, newId5);
|
||||
do_check_eq(bookmarksObserver._itemAddedParent, homeFolder);
|
||||
do_check_eq(bookmarksObserver._itemAddedIndex, 0);
|
||||
|
||||
// change item
|
||||
bs.setItemTitle(newId5, "ESPN");
|
||||
do_check_eq(bookmarksObserver._itemChangedId, newId5);
|
||||
do_check_eq(bookmarksObserver._itemChangedProperty, "title");
|
||||
|
||||
// insert query item
|
||||
let uri6 = uri("place:domain=google.com&type="+
|
||||
Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY);
|
||||
let newId6 = bs.insertBookmark(testRoot, uri6, bs.DEFAULT_INDEX, "");
|
||||
do_check_eq(bookmarksObserver._itemAddedParent, testRoot);
|
||||
do_check_eq(bookmarksObserver._itemAddedIndex, 3);
|
||||
|
||||
// change item
|
||||
bs.setItemTitle(newId6, "Google Sites");
|
||||
do_check_eq(bookmarksObserver._itemChangedProperty, "title");
|
||||
|
||||
// test getIdForItemAt
|
||||
do_check_eq(bs.getIdForItemAt(testRoot, 0), workFolder);
|
||||
// wrong parent, should return -1
|
||||
do_check_eq(bs.getIdForItemAt(1337, 0), -1);
|
||||
// wrong index, should return -1
|
||||
do_check_eq(bs.getIdForItemAt(testRoot, 1337), -1);
|
||||
// wrong parent and index, should return -1
|
||||
do_check_eq(bs.getIdForItemAt(1337, 1337), -1);
|
||||
|
||||
// move folder, appending, to different folder
|
||||
let oldParentCC = getChildCount(testRoot);
|
||||
bs.moveItem(workFolder, homeFolder, bs.DEFAULT_INDEX);
|
||||
do_check_eq(bookmarksObserver._itemMovedId, workFolder);
|
||||
do_check_eq(bookmarksObserver._itemMovedOldParent, testRoot);
|
||||
do_check_eq(bookmarksObserver._itemMovedOldIndex, 0);
|
||||
do_check_eq(bookmarksObserver._itemMovedNewParent, homeFolder);
|
||||
do_check_eq(bookmarksObserver._itemMovedNewIndex, 1);
|
||||
|
||||
// test that the new index is properly stored
|
||||
do_check_eq(bs.getItemIndex(workFolder), 1);
|
||||
do_check_eq(bs.getFolderIdForItem(workFolder), homeFolder);
|
||||
|
||||
// try to get index of the item from within the old parent folder
|
||||
// check that it has been really removed from there
|
||||
do_check_neq(bs.getIdForItemAt(testRoot, 0), workFolder);
|
||||
// check the last item from within the old parent folder
|
||||
do_check_neq(bs.getIdForItemAt(testRoot, -1), workFolder);
|
||||
// check the index of the item within the new parent folder
|
||||
do_check_eq(bs.getIdForItemAt(homeFolder, 1), workFolder);
|
||||
// try to get index of the last item within the new parent folder
|
||||
do_check_eq(bs.getIdForItemAt(homeFolder, -1), workFolder);
|
||||
// XXX expose FolderCount, and check that the old parent has one less child?
|
||||
do_check_eq(getChildCount(testRoot), oldParentCC-1);
|
||||
|
||||
// move item, appending, to different folder
|
||||
bs.moveItem(newId5, testRoot, bs.DEFAULT_INDEX);
|
||||
do_check_eq(bookmarksObserver._itemMovedId, newId5);
|
||||
do_check_eq(bookmarksObserver._itemMovedOldParent, homeFolder);
|
||||
do_check_eq(bookmarksObserver._itemMovedOldIndex, 0);
|
||||
do_check_eq(bookmarksObserver._itemMovedNewParent, testRoot);
|
||||
do_check_eq(bookmarksObserver._itemMovedNewIndex, 3);
|
||||
|
||||
// test get folder's index
|
||||
let tmpFolder = bs.createFolder(testRoot, "tmp", 2);
|
||||
do_check_eq(bs.getItemIndex(tmpFolder), 2);
|
||||
|
||||
// test setKeywordForBookmark
|
||||
let kwTestItemId = bs.insertBookmark(testRoot, uri("http://keywordtest.com"),
|
||||
bs.DEFAULT_INDEX, "");
|
||||
bs.setKeywordForBookmark(kwTestItemId, "bar");
|
||||
|
||||
// test getKeywordForBookmark
|
||||
let k = bs.getKeywordForBookmark(kwTestItemId);
|
||||
do_check_eq("bar", k);
|
||||
|
||||
// test getURIForKeyword
|
||||
let u = bs.getURIForKeyword("bar");
|
||||
do_check_eq("http://keywordtest.com/", u.spec);
|
||||
|
||||
// test removeFolderChildren
|
||||
// 1) add/remove each child type (bookmark, separator, folder)
|
||||
tmpFolder = bs.createFolder(testRoot, "removeFolderChildren",
|
||||
bs.DEFAULT_INDEX);
|
||||
bs.insertBookmark(tmpFolder, uri("http://foo9.com/"), bs.DEFAULT_INDEX, "");
|
||||
bs.createFolder(tmpFolder, "subfolder", bs.DEFAULT_INDEX);
|
||||
bs.insertSeparator(tmpFolder, bs.DEFAULT_INDEX);
|
||||
// 2) confirm that folder has 3 children
|
||||
let options = hs.getNewQueryOptions();
|
||||
let query = hs.getNewQuery();
|
||||
query.setFolders([tmpFolder], 1);
|
||||
try {
|
||||
let result = hs.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
do_check_eq(rootNode.childCount, 3);
|
||||
rootNode.containerOpen = false;
|
||||
} catch (ex) {
|
||||
do_throw("test removeFolderChildren() - querying for children failed: " + ex);
|
||||
}
|
||||
// 3) remove all children
|
||||
bs.removeFolderChildren(tmpFolder);
|
||||
// 4) confirm that folder has 0 children
|
||||
try {
|
||||
result = hs.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
do_check_eq(rootNode.childCount, 0);
|
||||
rootNode.containerOpen = false;
|
||||
} catch (ex) {
|
||||
do_throw("removeFolderChildren(): " + ex);
|
||||
}
|
||||
|
||||
// XXX - test folderReadOnly
|
||||
|
||||
// test bookmark id in query output
|
||||
try {
|
||||
options = hs.getNewQueryOptions();
|
||||
query = hs.getNewQuery();
|
||||
query.setFolders([testRoot], 1);
|
||||
let result = hs.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
let cc = rootNode.childCount;
|
||||
do_print("bookmark itemId test: CC = " + cc);
|
||||
do_check_true(cc > 0);
|
||||
for (let i=0; i < cc; ++i) {
|
||||
let node = rootNode.getChild(i);
|
||||
if (node.type == node.RESULT_TYPE_FOLDER ||
|
||||
node.type == node.RESULT_TYPE_URI ||
|
||||
node.type == node.RESULT_TYPE_SEPARATOR ||
|
||||
node.type == node.RESULT_TYPE_QUERY) {
|
||||
do_check_true(node.itemId > 0);
|
||||
}
|
||||
else {
|
||||
do_check_eq(node.itemId, -1);
|
||||
}
|
||||
}
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
catch (ex) {
|
||||
do_throw("bookmarks query: " + ex);
|
||||
}
|
||||
|
||||
// test that multiple bookmarks with same URI show up right in bookmark
|
||||
// folder queries, todo: also to do for complex folder queries
|
||||
try {
|
||||
// test uri
|
||||
let mURI = uri("http://multiple.uris.in.query");
|
||||
|
||||
let testFolder = bs.createFolder(testRoot, "test Folder", bs.DEFAULT_INDEX);
|
||||
// add 2 bookmarks
|
||||
bs.insertBookmark(testFolder, mURI, bs.DEFAULT_INDEX, "title 1");
|
||||
bs.insertBookmark(testFolder, mURI, bs.DEFAULT_INDEX, "title 2");
|
||||
|
||||
// query
|
||||
options = hs.getNewQueryOptions();
|
||||
query = hs.getNewQuery();
|
||||
query.setFolders([testFolder], 1);
|
||||
let result = hs.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
let cc = rootNode.childCount;
|
||||
do_check_eq(cc, 2);
|
||||
do_check_eq(rootNode.getChild(0).title, "title 1");
|
||||
do_check_eq(rootNode.getChild(1).title, "title 2");
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
catch (ex) {
|
||||
do_throw("bookmarks query: " + ex);
|
||||
}
|
||||
|
||||
// test change bookmark uri
|
||||
let newId10 = bs.insertBookmark(testRoot, uri("http://foo10.com/"),
|
||||
bs.DEFAULT_INDEX, "");
|
||||
dateAdded = bs.getItemDateAdded(newId10);
|
||||
// after just inserting, modified should not be set
|
||||
lastModified = bs.getItemLastModified(newId10);
|
||||
do_check_eq(lastModified, dateAdded);
|
||||
|
||||
// Workaround possible VM timers issues moving lastModified and dateAdded
|
||||
// to the past.
|
||||
lastModified -= 1000;
|
||||
bs.setItemLastModified(newId10, lastModified);
|
||||
dateAdded -= 1000;
|
||||
bs.setItemDateAdded(newId10, dateAdded);
|
||||
|
||||
bs.changeBookmarkURI(newId10, uri("http://foo11.com/"));
|
||||
|
||||
// check that lastModified is set after we change the bookmark uri
|
||||
lastModified2 = bs.getItemLastModified(newId10);
|
||||
do_print("test changeBookmarkURI");
|
||||
do_print("dateAdded = " + dateAdded);
|
||||
do_print("lastModified = " + lastModified);
|
||||
do_print("lastModified2 = " + lastModified2);
|
||||
do_check_true(is_time_ordered(lastModified, lastModified2));
|
||||
do_check_true(is_time_ordered(dateAdded, lastModified2));
|
||||
|
||||
do_check_eq(bookmarksObserver._itemChangedId, newId10);
|
||||
do_check_eq(bookmarksObserver._itemChangedProperty, "uri");
|
||||
do_check_eq(bookmarksObserver._itemChangedValue, "http://foo11.com/");
|
||||
do_check_eq(bookmarksObserver._itemChangedOldValue, "http://foo10.com/");
|
||||
|
||||
// test getBookmarkURI
|
||||
let newId11 = bs.insertBookmark(testRoot, uri("http://foo11.com/"),
|
||||
bs.DEFAULT_INDEX, "");
|
||||
let bmURI = bs.getBookmarkURI(newId11);
|
||||
do_check_eq("http://foo11.com/", bmURI.spec);
|
||||
|
||||
// test getBookmarkURI with non-bookmark items
|
||||
try {
|
||||
bs.getBookmarkURI(testRoot);
|
||||
do_throw("getBookmarkURI() should throw for non-bookmark items!");
|
||||
} catch (ex) {}
|
||||
|
||||
// test getItemIndex
|
||||
let newId12 = bs.insertBookmark(testRoot, uri("http://foo11.com/"), 1, "");
|
||||
let bmIndex = bs.getItemIndex(newId12);
|
||||
do_check_eq(1, bmIndex);
|
||||
|
||||
// insert a bookmark with title ZZZXXXYYY and then search for it.
|
||||
// this test confirms that we can find bookmarks that we haven't visited
|
||||
// (which are "hidden") and that we can find by title.
|
||||
// see bug #369887 for more details
|
||||
let newId13 = bs.insertBookmark(testRoot, uri("http://foobarcheese.com/"),
|
||||
bs.DEFAULT_INDEX, "");
|
||||
do_check_eq(bookmarksObserver._itemAddedId, newId13);
|
||||
do_check_eq(bookmarksObserver._itemAddedParent, testRoot);
|
||||
do_check_eq(bookmarksObserver._itemAddedIndex, 11);
|
||||
|
||||
// set bookmark title
|
||||
bs.setItemTitle(newId13, "ZZZXXXYYY");
|
||||
do_check_eq(bookmarksObserver._itemChangedId, newId13);
|
||||
do_check_eq(bookmarksObserver._itemChangedProperty, "title");
|
||||
do_check_eq(bookmarksObserver._itemChangedValue, "ZZZXXXYYY");
|
||||
|
||||
// check if setting an item annotation triggers onItemChanged
|
||||
bookmarksObserver._itemChangedId = -1;
|
||||
anno.setItemAnnotation(newId3, "test-annotation", "foo", 0, 0);
|
||||
do_check_eq(bookmarksObserver._itemChangedId, newId3);
|
||||
do_check_eq(bookmarksObserver._itemChangedProperty, "test-annotation");
|
||||
do_check_true(bookmarksObserver._itemChanged_isAnnotationProperty);
|
||||
do_check_eq(bookmarksObserver._itemChangedValue, "");
|
||||
|
||||
// test search on bookmark title ZZZXXXYYY
|
||||
try {
|
||||
options = hs.getNewQueryOptions();
|
||||
options.excludeQueries = 1;
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
query = hs.getNewQuery();
|
||||
query.searchTerms = "ZZZXXXYYY";
|
||||
let result = hs.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
let cc = rootNode.childCount;
|
||||
do_check_eq(cc, 1);
|
||||
let node = rootNode.getChild(0);
|
||||
do_check_eq(node.title, "ZZZXXXYYY");
|
||||
do_check_true(node.itemId > 0);
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
catch (ex) {
|
||||
do_throw("bookmarks query: " + ex);
|
||||
}
|
||||
|
||||
// test dateAdded and lastModified properties
|
||||
// for a search query
|
||||
try {
|
||||
options = hs.getNewQueryOptions();
|
||||
options.excludeQueries = 1;
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
query = hs.getNewQuery();
|
||||
query.searchTerms = "ZZZXXXYYY";
|
||||
let result = hs.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
let cc = rootNode.childCount;
|
||||
do_check_eq(cc, 1);
|
||||
let node = rootNode.getChild(0);
|
||||
|
||||
do_check_eq(typeof node.dateAdded, "number");
|
||||
do_check_true(node.dateAdded > 0);
|
||||
|
||||
do_check_eq(typeof node.lastModified, "number");
|
||||
do_check_true(node.lastModified > 0);
|
||||
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
catch (ex) {
|
||||
do_throw("bookmarks query: " + ex);
|
||||
}
|
||||
|
||||
// test dateAdded and lastModified properties
|
||||
// for a folder query
|
||||
try {
|
||||
options = hs.getNewQueryOptions();
|
||||
query = hs.getNewQuery();
|
||||
query.setFolders([testRoot], 1);
|
||||
let result = hs.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
let cc = rootNode.childCount;
|
||||
do_check_true(cc > 0);
|
||||
for (let i = 0; i < cc; i++) {
|
||||
let node = rootNode.getChild(i);
|
||||
|
||||
if (node.type == node.RESULT_TYPE_URI) {
|
||||
do_check_eq(typeof node.dateAdded, "number");
|
||||
do_check_true(node.dateAdded > 0);
|
||||
|
||||
do_check_eq(typeof node.lastModified, "number");
|
||||
do_check_true(node.lastModified > 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
catch (ex) {
|
||||
do_throw("bookmarks query: " + ex);
|
||||
}
|
||||
|
||||
// check setItemLastModified() and setItemDateAdded()
|
||||
let newId14 = bs.insertBookmark(testRoot, uri("http://bar.tld/"),
|
||||
bs.DEFAULT_INDEX, "");
|
||||
dateAdded = bs.getItemDateAdded(newId14);
|
||||
lastModified = bs.getItemLastModified(newId14);
|
||||
do_check_eq(lastModified, dateAdded);
|
||||
bs.setItemLastModified(newId14, 1234000000000000);
|
||||
let fakeLastModified = bs.getItemLastModified(newId14);
|
||||
do_check_eq(fakeLastModified, 1234000000000000);
|
||||
bs.setItemDateAdded(newId14, 4321000000000000);
|
||||
let fakeDateAdded = bs.getItemDateAdded(newId14);
|
||||
do_check_eq(fakeDateAdded, 4321000000000000);
|
||||
|
||||
// ensure that removing an item removes its annotations
|
||||
do_check_true(anno.itemHasAnnotation(newId3, "test-annotation"));
|
||||
bs.removeItem(newId3);
|
||||
do_check_false(anno.itemHasAnnotation(newId3, "test-annotation"));
|
||||
|
||||
// bug 378820
|
||||
let uri1 = uri("http://foo.tld/a");
|
||||
bs.insertBookmark(testRoot, uri1, bs.DEFAULT_INDEX, "");
|
||||
yield PlacesTestUtils.addVisits(uri1);
|
||||
|
||||
// bug 646993 - test bookmark titles longer than the maximum allowed length
|
||||
let title15 = Array(TITLE_LENGTH_MAX + 5).join("X");
|
||||
let title15expected = title15.substring(0, TITLE_LENGTH_MAX);
|
||||
let newId15 = bs.insertBookmark(testRoot, uri("http://evil.com/"),
|
||||
bs.DEFAULT_INDEX, title15);
|
||||
|
||||
do_check_eq(bs.getItemTitle(newId15).length,
|
||||
title15expected.length);
|
||||
do_check_eq(bookmarksObserver._itemAddedTitle, title15expected);
|
||||
// test title length after updates
|
||||
bs.setItemTitle(newId15, title15 + " updated");
|
||||
do_check_eq(bs.getItemTitle(newId15).length,
|
||||
title15expected.length);
|
||||
do_check_eq(bookmarksObserver._itemChangedId, newId15);
|
||||
do_check_eq(bookmarksObserver._itemChangedProperty, "title");
|
||||
do_check_eq(bookmarksObserver._itemChangedValue, title15expected);
|
||||
|
||||
testSimpleFolderResult();
|
||||
});
|
||||
|
||||
function testSimpleFolderResult() {
|
||||
// the time before we create a folder, in microseconds
|
||||
// Workaround possible VM timers issues subtracting 1us.
|
||||
let beforeCreate = Date.now() * 1000 - 1;
|
||||
do_check_true(beforeCreate > 0);
|
||||
|
||||
// create a folder
|
||||
let parent = bs.createFolder(root, "test", bs.DEFAULT_INDEX);
|
||||
|
||||
let dateCreated = bs.getItemDateAdded(parent);
|
||||
do_print("check that the folder was created with a valid dateAdded");
|
||||
do_print("beforeCreate = " + beforeCreate);
|
||||
do_print("dateCreated = " + dateCreated);
|
||||
do_check_true(is_time_ordered(beforeCreate, dateCreated));
|
||||
|
||||
// the time before we insert, in microseconds
|
||||
// Workaround possible VM timers issues subtracting 1ms.
|
||||
let beforeInsert = Date.now() * 1000 - 1;
|
||||
do_check_true(beforeInsert > 0);
|
||||
|
||||
// insert a separator
|
||||
let sep = bs.insertSeparator(parent, bs.DEFAULT_INDEX);
|
||||
|
||||
let dateAdded = bs.getItemDateAdded(sep);
|
||||
do_print("check that the separator was created with a valid dateAdded");
|
||||
do_print("beforeInsert = " + beforeInsert);
|
||||
do_print("dateAdded = " + dateAdded);
|
||||
do_check_true(is_time_ordered(beforeInsert, dateAdded));
|
||||
|
||||
// re-set item title separately so can test nodes' last modified
|
||||
let item = bs.insertBookmark(parent, uri("about:blank"),
|
||||
bs.DEFAULT_INDEX, "");
|
||||
bs.setItemTitle(item, "test bookmark");
|
||||
|
||||
// see above
|
||||
let folder = bs.createFolder(parent, "test folder", bs.DEFAULT_INDEX);
|
||||
bs.setItemTitle(folder, "test folder");
|
||||
|
||||
let longName = Array(TITLE_LENGTH_MAX + 5).join("A");
|
||||
let folderLongName = bs.createFolder(parent, longName, bs.DEFAULT_INDEX);
|
||||
do_check_eq(bookmarksObserver._itemAddedTitle, longName.substring(0, TITLE_LENGTH_MAX));
|
||||
|
||||
let options = hs.getNewQueryOptions();
|
||||
let query = hs.getNewQuery();
|
||||
query.setFolders([parent], 1);
|
||||
let result = hs.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
do_check_eq(rootNode.childCount, 4);
|
||||
|
||||
let node = rootNode.getChild(0);
|
||||
do_check_true(node.dateAdded > 0);
|
||||
do_check_eq(node.lastModified, node.dateAdded);
|
||||
do_check_eq(node.itemId, sep);
|
||||
do_check_eq(node.title, "");
|
||||
node = rootNode.getChild(1);
|
||||
do_check_eq(node.itemId, item);
|
||||
do_check_true(node.dateAdded > 0);
|
||||
do_check_true(node.lastModified > 0);
|
||||
do_check_eq(node.title, "test bookmark");
|
||||
node = rootNode.getChild(2);
|
||||
do_check_eq(node.itemId, folder);
|
||||
do_check_eq(node.title, "test folder");
|
||||
do_check_true(node.dateAdded > 0);
|
||||
do_check_true(node.lastModified > 0);
|
||||
node = rootNode.getChild(3);
|
||||
do_check_eq(node.itemId, folderLongName);
|
||||
do_check_eq(node.title, longName.substring(0, TITLE_LENGTH_MAX));
|
||||
do_check_true(node.dateAdded > 0);
|
||||
do_check_true(node.lastModified > 0);
|
||||
|
||||
// update with another long title
|
||||
bs.setItemTitle(folderLongName, longName + " updated");
|
||||
do_check_eq(bookmarksObserver._itemChangedId, folderLongName);
|
||||
do_check_eq(bookmarksObserver._itemChangedProperty, "title");
|
||||
do_check_eq(bookmarksObserver._itemChangedValue, longName.substring(0, TITLE_LENGTH_MAX));
|
||||
|
||||
node = rootNode.getChild(3);
|
||||
do_check_eq(node.title, longName.substring(0, TITLE_LENGTH_MAX));
|
||||
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
|
||||
function getChildCount(aFolderId) {
|
||||
let cc = -1;
|
||||
try {
|
||||
let options = hs.getNewQueryOptions();
|
||||
let query = hs.getNewQuery();
|
||||
query.setFolders([aFolderId], 1);
|
||||
let result = hs.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
cc = rootNode.childCount;
|
||||
rootNode.containerOpen = false;
|
||||
} catch (ex) {
|
||||
do_throw("getChildCount failed: " + ex);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
add_task(function* test_eraseEverything() {
|
||||
yield PlacesTestUtils.addVisits({ uri: NetUtil.newURI("http://example.com/") });
|
||||
yield PlacesTestUtils.addVisits({ uri: NetUtil.newURI("http://mozilla.org/") });
|
||||
let frecencyForExample = frecencyForUrl("http://example.com/");
|
||||
let frecencyForMozilla = frecencyForUrl("http://example.com/");
|
||||
Assert.ok(frecencyForExample > 0);
|
||||
Assert.ok(frecencyForMozilla > 0);
|
||||
let unfiledFolder = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
checkBookmarkObject(unfiledFolder);
|
||||
let unfiledBookmark = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/" });
|
||||
checkBookmarkObject(unfiledBookmark);
|
||||
let unfiledBookmarkInFolder =
|
||||
yield PlacesUtils.bookmarks.insert({ parentGuid: unfiledFolder.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://mozilla.org/" });
|
||||
checkBookmarkObject(unfiledBookmarkInFolder);
|
||||
PlacesUtils.annotations.setItemAnnotation((yield PlacesUtils.promiseItemId(unfiledBookmarkInFolder.guid)),
|
||||
"testanno1", "testvalue1", 0, 0);
|
||||
|
||||
let menuFolder = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
checkBookmarkObject(menuFolder);
|
||||
let menuBookmark = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/" });
|
||||
checkBookmarkObject(menuBookmark);
|
||||
let menuBookmarkInFolder =
|
||||
yield PlacesUtils.bookmarks.insert({ parentGuid: menuFolder.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://mozilla.org/" });
|
||||
checkBookmarkObject(menuBookmarkInFolder);
|
||||
PlacesUtils.annotations.setItemAnnotation((yield PlacesUtils.promiseItemId(menuBookmarkInFolder.guid)),
|
||||
"testanno1", "testvalue1", 0, 0);
|
||||
|
||||
let toolbarFolder = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
checkBookmarkObject(toolbarFolder);
|
||||
let toolbarBookmark = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/" });
|
||||
checkBookmarkObject(toolbarBookmark);
|
||||
let toolbarBookmarkInFolder =
|
||||
yield PlacesUtils.bookmarks.insert({ parentGuid: toolbarFolder.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://mozilla.org/" });
|
||||
checkBookmarkObject(toolbarBookmarkInFolder);
|
||||
PlacesUtils.annotations.setItemAnnotation((yield PlacesUtils.promiseItemId(toolbarBookmarkInFolder.guid)),
|
||||
"testanno1", "testvalue1", 0, 0);
|
||||
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
Assert.ok(frecencyForUrl("http://example.com/") > frecencyForExample);
|
||||
Assert.ok(frecencyForUrl("http://example.com/") > frecencyForMozilla);
|
||||
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
Assert.equal(frecencyForUrl("http://example.com/"), frecencyForExample);
|
||||
Assert.equal(frecencyForUrl("http://example.com/"), frecencyForMozilla);
|
||||
|
||||
// Check there are no orphan annotations.
|
||||
let conn = yield PlacesUtils.promiseDBConnection();
|
||||
let annoAttrs = yield conn.execute(`SELECT id, name FROM moz_anno_attributes`);
|
||||
// Bug 1306445 will eventually remove the mobile root anno.
|
||||
Assert.equal(annoAttrs.length, 1);
|
||||
Assert.equal(annoAttrs[0].getResultByName("name"), PlacesUtils.MOBILE_ROOT_ANNO);
|
||||
let annos = rows = yield conn.execute(`SELECT item_id, anno_attribute_id FROM moz_items_annos`);
|
||||
Assert.equal(annos.length, 1);
|
||||
Assert.equal(annos[0].getResultByName("item_id"), PlacesUtils.mobileFolderId);
|
||||
Assert.equal(annos[0].getResultByName("anno_attribute_id"), annoAttrs[0].getResultByName("id"));
|
||||
});
|
||||
|
||||
add_task(function* test_eraseEverything_roots() {
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
// Ensure the roots have not been removed.
|
||||
Assert.ok(yield PlacesUtils.bookmarks.fetch(PlacesUtils.bookmarks.unfiledGuid));
|
||||
Assert.ok(yield PlacesUtils.bookmarks.fetch(PlacesUtils.bookmarks.toolbarGuid));
|
||||
Assert.ok(yield PlacesUtils.bookmarks.fetch(PlacesUtils.bookmarks.menuGuid));
|
||||
Assert.ok(yield PlacesUtils.bookmarks.fetch(PlacesUtils.bookmarks.tagsGuid));
|
||||
Assert.ok(yield PlacesUtils.bookmarks.fetch(PlacesUtils.bookmarks.rootGuid));
|
||||
});
|
||||
|
||||
add_task(function* test_eraseEverything_reparented() {
|
||||
// Create a folder with 1 bookmark in it...
|
||||
let folder1 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER
|
||||
});
|
||||
let bookmark1 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: folder1.guid,
|
||||
url: "http://example.com/"
|
||||
});
|
||||
// ...and a second folder.
|
||||
let folder2 = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER
|
||||
});
|
||||
|
||||
// Reparent the bookmark to the 2nd folder.
|
||||
bookmark1.parentGuid = folder2.guid;
|
||||
yield PlacesUtils.bookmarks.update(bookmark1);
|
||||
|
||||
// Erase everything.
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
// All the above items should no longer be in the GUIDHelper cache.
|
||||
for (let guid of [folder1.guid, bookmark1.guid, folder2.guid]) {
|
||||
yield Assert.rejects(PlacesUtils.promiseItemId(guid),
|
||||
/no item found for the given GUID/);
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gAccumulator = {
|
||||
get callback() {
|
||||
this.results = [];
|
||||
return result => this.results.push(result);
|
||||
}
|
||||
};
|
||||
|
||||
add_task(function* invalid_input_throws() {
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch(),
|
||||
/Input should be a valid object/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch(null),
|
||||
/Input should be a valid object/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ guid: "123456789012",
|
||||
parentGuid: "012345678901" }),
|
||||
/The following properties were expected: index/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ guid: "123456789012",
|
||||
index: 0 }),
|
||||
/The following properties were expected: parentGuid/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({}),
|
||||
/Unexpected number of conditions provided: 0/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ guid: "123456789012",
|
||||
parentGuid: "012345678901",
|
||||
index: 0 }),
|
||||
/Unexpected number of conditions provided: 2/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ guid: "123456789012",
|
||||
url: "http://example.com"}),
|
||||
/Unexpected number of conditions provided: 2/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch("test"),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch(123),
|
||||
/Invalid value for property 'guid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ guid: "test" }),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ guid: null }),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ guid: 123 }),
|
||||
/Invalid value for property 'guid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ parentGuid: "test",
|
||||
index: 0 }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ parentGuid: null,
|
||||
index: 0 }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ parentGuid: 123,
|
||||
index: 0 }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ parentGuid: "123456789012",
|
||||
index: "0" }),
|
||||
/Invalid value for property 'index'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ parentGuid: "123456789012",
|
||||
index: null }),
|
||||
/Invalid value for property 'index'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ parentGuid: "123456789012",
|
||||
index: -10 }),
|
||||
/Invalid value for property 'index'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ url: "http://te st/" }),
|
||||
/Invalid value for property 'url'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ url: null }),
|
||||
/Invalid value for property 'url'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch({ url: -10 }),
|
||||
/Invalid value for property 'url'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch("123456789012", "test"),
|
||||
/onResult callback must be a valid function/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.fetch("123456789012", {}),
|
||||
/onResult callback must be a valid function/);
|
||||
});
|
||||
|
||||
add_task(function* fetch_nonexistent_guid() {
|
||||
let bm = yield PlacesUtils.bookmarks.fetch({ guid: "123456789012" },
|
||||
gAccumulator.callback);
|
||||
Assert.equal(bm, null);
|
||||
Assert.equal(gAccumulator.results.length, 0);
|
||||
});
|
||||
|
||||
add_task(function* fetch_bookmark() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.fetch(bm1.guid,
|
||||
gAccumulator.callback);
|
||||
checkBookmarkObject(bm2);
|
||||
Assert.equal(gAccumulator.results.length, 1);
|
||||
checkBookmarkObject(gAccumulator.results[0]);
|
||||
Assert.deepEqual(gAccumulator.results[0], bm1);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm2.index, 0);
|
||||
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
|
||||
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
|
||||
Assert.equal(bm2.url.href, "http://example.com/");
|
||||
Assert.equal(bm2.title, "a bookmark");
|
||||
|
||||
yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
});
|
||||
|
||||
add_task(function* fetch_bookmar_empty_title() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/",
|
||||
title: "" });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.fetch(bm1.guid);
|
||||
checkBookmarkObject(bm2);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.index, 0);
|
||||
Assert.ok(!("title" in bm2));
|
||||
|
||||
yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
});
|
||||
|
||||
add_task(function* fetch_folder() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "a folder" });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.fetch(bm1.guid);
|
||||
checkBookmarkObject(bm2);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm2.index, 0);
|
||||
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
|
||||
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_FOLDER);
|
||||
Assert.equal(bm2.title, "a folder");
|
||||
Assert.ok(!("url" in bm2));
|
||||
|
||||
yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
});
|
||||
|
||||
add_task(function* fetch_folder_empty_title() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "" });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.fetch(bm1.guid);
|
||||
checkBookmarkObject(bm2);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.index, 0);
|
||||
Assert.ok(!("title" in bm2));
|
||||
|
||||
yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
});
|
||||
|
||||
add_task(function* fetch_separator() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.fetch(bm1.guid);
|
||||
checkBookmarkObject(bm2);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm2.index, 0);
|
||||
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
|
||||
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_SEPARATOR);
|
||||
Assert.ok(!("url" in bm2));
|
||||
Assert.ok(!("title" in bm2));
|
||||
|
||||
yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
});
|
||||
|
||||
add_task(function* fetch_byposition_nonexisting_parentGuid() {
|
||||
let bm = yield PlacesUtils.bookmarks.fetch({ parentGuid: "123456789012",
|
||||
index: 0 },
|
||||
gAccumulator.callback);
|
||||
Assert.equal(bm, null);
|
||||
Assert.equal(gAccumulator.results.length, 0);
|
||||
});
|
||||
|
||||
add_task(function* fetch_byposition_nonexisting_index() {
|
||||
let bm = yield PlacesUtils.bookmarks.fetch({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
index: 100 },
|
||||
gAccumulator.callback);
|
||||
Assert.equal(bm, null);
|
||||
Assert.equal(gAccumulator.results.length, 0);
|
||||
});
|
||||
|
||||
add_task(function* fetch_byposition() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.fetch({ parentGuid: bm1.parentGuid,
|
||||
index: bm1.index },
|
||||
gAccumulator.callback);
|
||||
checkBookmarkObject(bm2);
|
||||
Assert.equal(gAccumulator.results.length, 1);
|
||||
checkBookmarkObject(gAccumulator.results[0]);
|
||||
Assert.deepEqual(gAccumulator.results[0], bm1);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm2.index, 0);
|
||||
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
|
||||
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
|
||||
Assert.equal(bm2.url.href, "http://example.com/");
|
||||
Assert.equal(bm2.title, "a bookmark");
|
||||
});
|
||||
|
||||
add_task(function* fetch_byposition_default_index() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/last",
|
||||
title: "last child" });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.fetch({ parentGuid: bm1.parentGuid,
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX },
|
||||
gAccumulator.callback);
|
||||
checkBookmarkObject(bm2);
|
||||
Assert.equal(gAccumulator.results.length, 1);
|
||||
checkBookmarkObject(gAccumulator.results[0]);
|
||||
Assert.deepEqual(gAccumulator.results[0], bm1);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm2.index, 1);
|
||||
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
|
||||
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
|
||||
Assert.equal(bm2.url.href, "http://example.com/last");
|
||||
Assert.equal(bm2.title, "last child");
|
||||
|
||||
yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
});
|
||||
|
||||
add_task(function* fetch_byurl_nonexisting() {
|
||||
let bm = yield PlacesUtils.bookmarks.fetch({ url: "http://nonexisting.com/" },
|
||||
gAccumulator.callback);
|
||||
Assert.equal(bm, null);
|
||||
Assert.equal(gAccumulator.results.length, 0);
|
||||
});
|
||||
|
||||
add_task(function* fetch_byurl() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://byurl.com/",
|
||||
title: "a bookmark" });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
// Also ensure that fecth-by-url excludes the tags folder.
|
||||
PlacesUtils.tagging.tagURI(uri(bm1.url.href), ["Test Tag"]);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.fetch({ url: bm1.url },
|
||||
gAccumulator.callback);
|
||||
checkBookmarkObject(bm2);
|
||||
Assert.equal(gAccumulator.results.length, 1);
|
||||
checkBookmarkObject(gAccumulator.results[0]);
|
||||
Assert.deepEqual(gAccumulator.results[0], bm1);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
|
||||
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
|
||||
Assert.equal(bm2.url.href, "http://byurl.com/");
|
||||
Assert.equal(bm2.title, "a bookmark");
|
||||
|
||||
let bm3 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://byurl.com/",
|
||||
title: "a bookmark" });
|
||||
let bm4 = yield PlacesUtils.bookmarks.fetch({ url: bm1.url },
|
||||
gAccumulator.callback);
|
||||
checkBookmarkObject(bm4);
|
||||
Assert.deepEqual(bm3, bm4);
|
||||
Assert.equal(gAccumulator.results.length, 2);
|
||||
gAccumulator.results.forEach(checkBookmarkObject);
|
||||
Assert.deepEqual(gAccumulator.results[0], bm4);
|
||||
|
||||
// After an update the returned bookmark should change.
|
||||
yield PlacesUtils.bookmarks.update({ guid: bm1.guid, title: "new title" });
|
||||
let bm5 = yield PlacesUtils.bookmarks.fetch({ url: bm1.url },
|
||||
gAccumulator.callback);
|
||||
checkBookmarkObject(bm5);
|
||||
// Cannot use deepEqual cause lastModified changed.
|
||||
Assert.equal(bm1.guid, bm5.guid);
|
||||
Assert.ok(bm5.lastModified > bm1.lastModified);
|
||||
Assert.equal(gAccumulator.results.length, 2);
|
||||
gAccumulator.results.forEach(checkBookmarkObject);
|
||||
Assert.deepEqual(gAccumulator.results[0], bm5);
|
||||
|
||||
// cleanup
|
||||
PlacesUtils.tagging.untagURI(uri(bm1.url.href), ["Test Tag"]);
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
add_task(function* invalid_input_throws() {
|
||||
Assert.throws(() => PlacesUtils.bookmarks.getRecent(),
|
||||
/numberOfItems argument is required/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.getRecent("abc"),
|
||||
/numberOfItems argument must be an integer/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.getRecent(1.2),
|
||||
/numberOfItems argument must be an integer/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.getRecent(0),
|
||||
/numberOfItems argument must be greater than zero/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.getRecent(-1),
|
||||
/numberOfItems argument must be greater than zero/);
|
||||
});
|
||||
|
||||
add_task(function* getRecent_returns_recent_bookmarks() {
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
let bm2 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.org/path",
|
||||
title: "another bookmark" });
|
||||
let bm3 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.net/",
|
||||
title: "another bookmark" });
|
||||
let bm4 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.net/path",
|
||||
title: "yet another bookmark" });
|
||||
checkBookmarkObject(bm1);
|
||||
checkBookmarkObject(bm2);
|
||||
checkBookmarkObject(bm3);
|
||||
checkBookmarkObject(bm4);
|
||||
|
||||
let results = yield PlacesUtils.bookmarks.getRecent(3);
|
||||
Assert.equal(results.length, 3);
|
||||
checkBookmarkObject(results[0]);
|
||||
Assert.deepEqual(bm4, results[0]);
|
||||
checkBookmarkObject(results[1]);
|
||||
Assert.deepEqual(bm3, results[1]);
|
||||
checkBookmarkObject(results[2]);
|
||||
Assert.deepEqual(bm2, results[2]);
|
||||
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
add_task(function* invalid_input_throws() {
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert(),
|
||||
/Input should be a valid object/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert(null),
|
||||
/Input should be a valid object/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({}),
|
||||
/The following properties were expected/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ guid: "test" }),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ guid: null }),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ guid: 123 }),
|
||||
/Invalid value for property 'guid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ parentGuid: "test" }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ parentGuid: null }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ parentGuid: 123 }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ index: "1" }),
|
||||
/Invalid value for property 'index'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ index: -10 }),
|
||||
/Invalid value for property 'index'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ dateAdded: -10 }),
|
||||
/Invalid value for property 'dateAdded'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ dateAdded: "today" }),
|
||||
/Invalid value for property 'dateAdded'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ dateAdded: Date.now() }),
|
||||
/Invalid value for property 'dateAdded'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ lastModified: -10 }),
|
||||
/Invalid value for property 'lastModified'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ lastModified: "today" }),
|
||||
/Invalid value for property 'lastModified'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ lastModified: Date.now() }),
|
||||
/Invalid value for property 'lastModified'/);
|
||||
let time = new Date();
|
||||
let future = new Date(time + 86400000);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ dateAdded: future,
|
||||
lastModified: time }),
|
||||
/Invalid value for property 'dateAdded'/);
|
||||
let past = new Date(time - 86400000);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ lastModified: past }),
|
||||
/Invalid value for property 'lastModified'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: -1 }),
|
||||
/Invalid value for property 'type'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: 100 }),
|
||||
/Invalid value for property 'type'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: "bookmark" }),
|
||||
/Invalid value for property 'type'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
title: -1 }),
|
||||
/Invalid value for property 'title'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: 10 }),
|
||||
/Invalid value for property 'url'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://te st" }),
|
||||
/Invalid value for property 'url'/);
|
||||
let longurl = "http://www.example.com/";
|
||||
for (let i = 0; i < 65536; i++) {
|
||||
longurl += "a";
|
||||
}
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: longurl }),
|
||||
/Invalid value for property 'url'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: NetUtil.newURI(longurl) }),
|
||||
/Invalid value for property 'url'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "te st" }),
|
||||
/Invalid value for property 'url'/);
|
||||
});
|
||||
|
||||
add_task(function* invalid_properties_for_bookmark_type() {
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
url: "http://www.moz.com/" }),
|
||||
/Invalid value for property 'url'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
url: "http://www.moz.com/" }),
|
||||
/Invalid value for property 'url'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
title: "test" }),
|
||||
/Invalid value for property 'title'/);
|
||||
});
|
||||
|
||||
add_task(function* long_title_trim() {
|
||||
let longtitle = "a";
|
||||
for (let i = 0; i < 4096; i++) {
|
||||
longtitle += "a";
|
||||
}
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: longtitle });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.equal(bm.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm.index, 0);
|
||||
Assert.equal(bm.dateAdded, bm.lastModified);
|
||||
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_FOLDER);
|
||||
Assert.equal(bm.title.length, 4096, "title should have been trimmed");
|
||||
Assert.ok(!("url" in bm), "url should not be set");
|
||||
});
|
||||
|
||||
add_task(function* create_separator() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.equal(bm.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm.index, 1);
|
||||
Assert.equal(bm.dateAdded, bm.lastModified);
|
||||
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_SEPARATOR);
|
||||
Assert.ok(!("title" in bm), "title should not be set");
|
||||
});
|
||||
|
||||
add_task(function* create_separator_w_title_fail() {
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
title: "a separator" });
|
||||
Assert.ok(false, "Trying to set title for a separator should reject");
|
||||
} catch (ex) {}
|
||||
});
|
||||
|
||||
add_task(function* create_separator_invalid_parent_fail() {
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.insert({ parentGuid: "123456789012",
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
title: "a separator" });
|
||||
Assert.ok(false, "Trying to create an item in a non existing parent reject");
|
||||
} catch (ex) {}
|
||||
});
|
||||
|
||||
add_task(function* create_separator_given_guid() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
guid: "123456789012" });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.equal(bm.guid, "123456789012");
|
||||
Assert.equal(bm.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm.index, 2);
|
||||
Assert.equal(bm.dateAdded, bm.lastModified);
|
||||
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_SEPARATOR);
|
||||
Assert.ok(!("title" in bm), "title should not be set");
|
||||
});
|
||||
|
||||
add_task(function* create_item_given_guid_no_type_fail() {
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.insert({ parentGuid: "123456789012" });
|
||||
Assert.ok(false, "Trying to create an item with a given guid but no type should reject");
|
||||
} catch (ex) {}
|
||||
});
|
||||
|
||||
add_task(function* create_separator_big_index() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
index: 9999 });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.equal(bm.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm.index, 3);
|
||||
Assert.equal(bm.dateAdded, bm.lastModified);
|
||||
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_SEPARATOR);
|
||||
Assert.ok(!("title" in bm), "title should not be set");
|
||||
});
|
||||
|
||||
add_task(function* create_separator_given_dateAdded() {
|
||||
let time = new Date();
|
||||
let past = new Date(time - 86400000);
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
dateAdded: past });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.equal(bm.dateAdded, past);
|
||||
Assert.equal(bm.lastModified, past);
|
||||
});
|
||||
|
||||
add_task(function* create_folder() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.equal(bm.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm.dateAdded, bm.lastModified);
|
||||
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_FOLDER);
|
||||
Assert.ok(!("title" in bm), "title should not be set");
|
||||
|
||||
// And then create a nested folder.
|
||||
let parentGuid = bm.guid;
|
||||
bm = yield PlacesUtils.bookmarks.insert({ parentGuid: parentGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "a folder" });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.equal(bm.parentGuid, parentGuid);
|
||||
Assert.equal(bm.index, 0);
|
||||
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_FOLDER);
|
||||
Assert.strictEqual(bm.title, "a folder");
|
||||
});
|
||||
|
||||
add_task(function* create_bookmark() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
let parentGuid = bm.guid;
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.insert({ parentGuid: parentGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.equal(bm.parentGuid, parentGuid);
|
||||
Assert.equal(bm.index, 0);
|
||||
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
|
||||
Assert.equal(bm.url.href, "http://example.com/");
|
||||
Assert.equal(bm.title, "a bookmark");
|
||||
|
||||
// Check parent lastModified.
|
||||
let parent = yield PlacesUtils.bookmarks.fetch({ guid: bm.parentGuid });
|
||||
Assert.deepEqual(parent.lastModified, bm.dateAdded);
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.insert({ parentGuid: parentGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: new URL("http://example.com/") });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.equal(bm.parentGuid, parentGuid);
|
||||
Assert.equal(bm.index, 1);
|
||||
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
|
||||
Assert.equal(bm.url.href, "http://example.com/");
|
||||
Assert.ok(!("title" in bm), "title should not be set");
|
||||
});
|
||||
|
||||
add_task(function* create_bookmark_frecency() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
checkBookmarkObject(bm);
|
||||
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
Assert.ok(frecencyForUrl(bm.url) > 0, "Check frecency has been updated")
|
||||
});
|
||||
|
||||
add_task(function* create_bookmark_without_type() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.equal(bm.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
|
||||
Assert.equal(bm.url.href, "http://example.com/");
|
||||
Assert.equal(bm.title, "a bookmark");
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
|
@ -0,0 +1,527 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
add_task(function* insert_separator_notification() {
|
||||
let observer = expectNotifications();
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid});
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
observer.check([ { name: "onItemAdded",
|
||||
arguments: [ itemId, parentId, bm.index, bm.type,
|
||||
null, null, bm.dateAdded,
|
||||
bm.guid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* insert_folder_notification() {
|
||||
let observer = expectNotifications();
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
title: "a folder" });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
observer.check([ { name: "onItemAdded",
|
||||
arguments: [ itemId, parentId, bm.index, bm.type,
|
||||
null, bm.title, bm.dateAdded,
|
||||
bm.guid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* insert_folder_notitle_notification() {
|
||||
let observer = expectNotifications();
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
observer.check([ { name: "onItemAdded",
|
||||
arguments: [ itemId, parentId, bm.index, bm.type,
|
||||
null, null, bm.dateAdded,
|
||||
bm.guid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* insert_bookmark_notification() {
|
||||
let observer = expectNotifications();
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: new URL("http://example.com/"),
|
||||
title: "a bookmark" });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
observer.check([ { name: "onItemAdded",
|
||||
arguments: [ itemId, parentId, bm.index, bm.type,
|
||||
bm.url, bm.title, bm.dateAdded,
|
||||
bm.guid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* insert_bookmark_notitle_notification() {
|
||||
let observer = expectNotifications();
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: new URL("http://example.com/") });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
observer.check([ { name: "onItemAdded",
|
||||
arguments: [ itemId, parentId, bm.index, bm.type,
|
||||
bm.url, null, bm.dateAdded,
|
||||
bm.guid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* insert_bookmark_tag_notification() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: new URL("http://tag.example.com/") });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
|
||||
let tagFolder = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.tagsGuid,
|
||||
title: "tag" });
|
||||
let observer = expectNotifications();
|
||||
let tag = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: tagFolder.guid,
|
||||
url: new URL("http://tag.example.com/") });
|
||||
let tagId = yield PlacesUtils.promiseItemId(tag.guid);
|
||||
let tagParentId = yield PlacesUtils.promiseItemId(tag.parentGuid);
|
||||
|
||||
observer.check([ { name: "onItemAdded",
|
||||
arguments: [ tagId, tagParentId, tag.index, tag.type,
|
||||
tag.url, null, tag.dateAdded,
|
||||
tag.guid, tag.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemChanged",
|
||||
arguments: [ itemId, "tags", false, "",
|
||||
bm.lastModified, bm.type, parentId,
|
||||
bm.guid, bm.parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* update_bookmark_lastModified() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: new URL("http://lastmod.example.com/") });
|
||||
let observer = expectNotifications();
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
lastModified: new Date() });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
|
||||
observer.check([ { name: "onItemChanged",
|
||||
arguments: [ itemId, "lastModified", false,
|
||||
`${bm.lastModified * 1000}`, bm.lastModified,
|
||||
bm.type, parentId, bm.guid, bm.parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* update_bookmark_title() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: new URL("http://title.example.com/") });
|
||||
let observer = expectNotifications();
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
title: "new title" });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
|
||||
observer.check([ { name: "onItemChanged",
|
||||
arguments: [ itemId, "title", false, bm.title,
|
||||
bm.lastModified, bm.type, parentId, bm.guid,
|
||||
bm.parentGuid, "", Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* update_bookmark_uri() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: new URL("http://url.example.com/") });
|
||||
let observer = expectNotifications();
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
url: "http://mozilla.org/" });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
|
||||
observer.check([ { name: "onItemChanged",
|
||||
arguments: [ itemId, "uri", false, bm.url.href,
|
||||
bm.lastModified, bm.type, parentId, bm.guid,
|
||||
bm.parentGuid, "http://url.example.com/",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* update_move_same_folder() {
|
||||
// Ensure there are at least two items in place (others test do so for us,
|
||||
// but we don't have to depend on that).
|
||||
yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: new URL("http://move.example.com/") });
|
||||
let bmItemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let bmParentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
let bmOldIndex = bm.index;
|
||||
|
||||
let observer = expectNotifications();
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
index: 0 });
|
||||
Assert.equal(bm.index, 0);
|
||||
observer.check([ { name: "onItemMoved",
|
||||
arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index,
|
||||
bm.type, bm.guid, bm.parentGuid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
|
||||
// Test that we get the right index for DEFAULT_INDEX input.
|
||||
bmOldIndex = 0;
|
||||
observer = expectNotifications();
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX });
|
||||
Assert.ok(bm.index > 0);
|
||||
observer.check([ { name: "onItemMoved",
|
||||
arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index,
|
||||
bm.type, bm.guid, bm.parentGuid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* update_move_different_folder() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: new URL("http://move.example.com/") });
|
||||
let folder = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
let bmItemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let bmOldParentId = PlacesUtils.unfiledBookmarksFolderId;
|
||||
let bmOldIndex = bm.index;
|
||||
|
||||
let observer = expectNotifications();
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
parentGuid: folder.guid,
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX });
|
||||
Assert.equal(bm.index, 0);
|
||||
let bmNewParentId = yield PlacesUtils.promiseItemId(folder.guid);
|
||||
observer.check([ { name: "onItemMoved",
|
||||
arguments: [ bmItemId, bmOldParentId, bmOldIndex, bmNewParentId,
|
||||
bm.index, bm.type, bm.guid,
|
||||
PlacesUtils.bookmarks.unfiledGuid,
|
||||
bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* remove_bookmark() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: new URL("http://remove.example.com/") });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
|
||||
let observer = expectNotifications();
|
||||
bm = yield PlacesUtils.bookmarks.remove(bm.guid);
|
||||
// TODO (Bug 653910): onItemAnnotationRemoved notified even if there were no
|
||||
// annotations.
|
||||
observer.check([ { name: "onItemRemoved",
|
||||
arguments: [ itemId, parentId, bm.index, bm.type, bm.url,
|
||||
bm.guid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* remove_folder() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
|
||||
let observer = expectNotifications();
|
||||
bm = yield PlacesUtils.bookmarks.remove(bm.guid);
|
||||
observer.check([ { name: "onItemRemoved",
|
||||
arguments: [ itemId, parentId, bm.index, bm.type, null,
|
||||
bm.guid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* remove_bookmark_tag_notification() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: new URL("http://untag.example.com/") });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
|
||||
let tagFolder = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.tagsGuid,
|
||||
title: "tag" });
|
||||
let tag = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: tagFolder.guid,
|
||||
url: new URL("http://untag.example.com/") });
|
||||
let tagId = yield PlacesUtils.promiseItemId(tag.guid);
|
||||
let tagParentId = yield PlacesUtils.promiseItemId(tag.parentGuid);
|
||||
|
||||
let observer = expectNotifications();
|
||||
yield PlacesUtils.bookmarks.remove(tag.guid);
|
||||
|
||||
observer.check([ { name: "onItemRemoved",
|
||||
arguments: [ tagId, tagParentId, tag.index, tag.type,
|
||||
tag.url, tag.guid, tag.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemChanged",
|
||||
arguments: [ itemId, "tags", false, "",
|
||||
bm.lastModified, bm.type, parentId,
|
||||
bm.guid, bm.parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* remove_folder_notification() {
|
||||
let folder1 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
let folder1Id = yield PlacesUtils.promiseItemId(folder1.guid);
|
||||
let folder1ParentId = yield PlacesUtils.promiseItemId(folder1.parentGuid);
|
||||
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: folder1.guid,
|
||||
url: new URL("http://example.com/") });
|
||||
let bmItemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
|
||||
let folder2 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: folder1.guid });
|
||||
let folder2Id = yield PlacesUtils.promiseItemId(folder2.guid);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: folder2.guid,
|
||||
url: new URL("http://example.com/") });
|
||||
let bm2ItemId = yield PlacesUtils.promiseItemId(bm2.guid);
|
||||
|
||||
let observer = expectNotifications();
|
||||
yield PlacesUtils.bookmarks.remove(folder1.guid);
|
||||
|
||||
observer.check([ { name: "onItemRemoved",
|
||||
arguments: [ bm2ItemId, folder2Id, bm2.index, bm2.type,
|
||||
bm2.url, bm2.guid, bm2.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemRemoved",
|
||||
arguments: [ folder2Id, folder1Id, folder2.index,
|
||||
folder2.type, null, folder2.guid,
|
||||
folder2.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemRemoved",
|
||||
arguments: [ bmItemId, folder1Id, bm.index, bm.type,
|
||||
bm.url, bm.guid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemRemoved",
|
||||
arguments: [ folder1Id, folder1ParentId, folder1.index,
|
||||
folder1.type, null, folder1.guid,
|
||||
folder1.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* eraseEverything_notification() {
|
||||
// Let's start from a clean situation.
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
let folder1 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
let folder1Id = yield PlacesUtils.promiseItemId(folder1.guid);
|
||||
let folder1ParentId = yield PlacesUtils.promiseItemId(folder1.parentGuid);
|
||||
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: folder1.guid,
|
||||
url: new URL("http://example.com/") });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
|
||||
let folder2 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
let folder2Id = yield PlacesUtils.promiseItemId(folder2.guid);
|
||||
let folder2ParentId = yield PlacesUtils.promiseItemId(folder2.parentGuid);
|
||||
|
||||
let toolbarBm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
url: new URL("http://example.com/") });
|
||||
let toolbarBmId = yield PlacesUtils.promiseItemId(toolbarBm.guid);
|
||||
let toolbarBmParentId = yield PlacesUtils.promiseItemId(toolbarBm.parentGuid);
|
||||
|
||||
let menuBm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
url: new URL("http://example.com/") });
|
||||
let menuBmId = yield PlacesUtils.promiseItemId(menuBm.guid);
|
||||
let menuBmParentId = yield PlacesUtils.promiseItemId(menuBm.parentGuid);
|
||||
|
||||
let observer = expectNotifications();
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
// Bookmarks should always be notified before their parents.
|
||||
observer.check([ { name: "onItemRemoved",
|
||||
arguments: [ itemId, parentId, bm.index, bm.type,
|
||||
bm.url, bm.guid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemRemoved",
|
||||
arguments: [ folder2Id, folder2ParentId, folder2.index,
|
||||
folder2.type, null, folder2.guid,
|
||||
folder2.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemRemoved",
|
||||
arguments: [ folder1Id, folder1ParentId, folder1.index,
|
||||
folder1.type, null, folder1.guid,
|
||||
folder1.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemRemoved",
|
||||
arguments: [ menuBmId, menuBmParentId,
|
||||
menuBm.index, menuBm.type,
|
||||
menuBm.url, menuBm.guid,
|
||||
menuBm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemRemoved",
|
||||
arguments: [ toolbarBmId, toolbarBmParentId,
|
||||
toolbarBm.index, toolbarBm.type,
|
||||
toolbarBm.url, toolbarBm.guid,
|
||||
toolbarBm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* eraseEverything_reparented_notification() {
|
||||
// Let's start from a clean situation.
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
let folder1 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
let folder1Id = yield PlacesUtils.promiseItemId(folder1.guid);
|
||||
let folder1ParentId = yield PlacesUtils.promiseItemId(folder1.parentGuid);
|
||||
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: folder1.guid,
|
||||
url: new URL("http://example.com/") });
|
||||
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
|
||||
|
||||
let folder2 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
let folder2Id = yield PlacesUtils.promiseItemId(folder2.guid);
|
||||
let folder2ParentId = yield PlacesUtils.promiseItemId(folder2.parentGuid);
|
||||
|
||||
bm.parentGuid = folder2.guid;
|
||||
bm = yield PlacesUtils.bookmarks.update(bm);
|
||||
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
|
||||
|
||||
let observer = expectNotifications();
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
// Bookmarks should always be notified before their parents.
|
||||
observer.check([ { name: "onItemRemoved",
|
||||
arguments: [ itemId, parentId, bm.index, bm.type,
|
||||
bm.url, bm.guid, bm.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemRemoved",
|
||||
arguments: [ folder2Id, folder2ParentId, folder2.index,
|
||||
folder2.type, null, folder2.guid,
|
||||
folder2.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemRemoved",
|
||||
arguments: [ folder1Id, folder1ParentId, folder1.index,
|
||||
folder1.type, null, folder1.guid,
|
||||
folder1.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
]);
|
||||
});
|
||||
|
||||
add_task(function* reorder_notification() {
|
||||
let bookmarks = [
|
||||
{ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example1.com/",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
},
|
||||
{ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
},
|
||||
{ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
},
|
||||
{ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example2.com/",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
},
|
||||
{ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example3.com/",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
},
|
||||
];
|
||||
let sorted = [];
|
||||
for (let bm of bookmarks) {
|
||||
sorted.push(yield PlacesUtils.bookmarks.insert(bm));
|
||||
}
|
||||
|
||||
// Randomly reorder the array.
|
||||
sorted.sort(() => 0.5 - Math.random());
|
||||
|
||||
let observer = expectNotifications();
|
||||
yield PlacesUtils.bookmarks.reorder(PlacesUtils.bookmarks.unfiledGuid,
|
||||
sorted.map(bm => bm.guid));
|
||||
|
||||
let expectedNotifications = [];
|
||||
for (let i = 0; i < sorted.length; ++i) {
|
||||
let child = sorted[i];
|
||||
let childId = yield PlacesUtils.promiseItemId(child.guid);
|
||||
expectedNotifications.push({ name: "onItemMoved",
|
||||
arguments: [ childId,
|
||||
PlacesUtils.unfiledBookmarksFolderId,
|
||||
child.index,
|
||||
PlacesUtils.unfiledBookmarksFolderId,
|
||||
i,
|
||||
child.type,
|
||||
child.guid,
|
||||
child.parentGuid,
|
||||
child.parentGuid,
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT
|
||||
] });
|
||||
}
|
||||
observer.check(expectedNotifications);
|
||||
});
|
||||
|
||||
function expectNotifications() {
|
||||
let notifications = [];
|
||||
let observer = new Proxy(NavBookmarkObserver, {
|
||||
get(target, name) {
|
||||
if (name == "check") {
|
||||
PlacesUtils.bookmarks.removeObserver(observer);
|
||||
return expectedNotifications =>
|
||||
Assert.deepEqual(notifications, expectedNotifications);
|
||||
}
|
||||
|
||||
if (name.startsWith("onItem")) {
|
||||
return (...origArgs) => {
|
||||
let args = Array.from(origArgs, arg => {
|
||||
if (arg && arg instanceof Ci.nsIURI)
|
||||
return new URL(arg.spec);
|
||||
if (arg && typeof(arg) == "number" && arg >= Date.now() * 1000)
|
||||
return new Date(parseInt(arg/1000));
|
||||
return arg;
|
||||
});
|
||||
notifications.push({ name: name, arguments: args });
|
||||
}
|
||||
}
|
||||
|
||||
if (name in target)
|
||||
return target[name];
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
PlacesUtils.bookmarks.addObserver(observer, false);
|
||||
return observer;
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
add_task(function* invalid_input_throws() {
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove(),
|
||||
/Input should be a valid object/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove(null),
|
||||
/Input should be a valid object/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove("test"),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove(123),
|
||||
/Invalid value for property 'guid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove({ guid: "test" }),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove({ guid: null }),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove({ guid: 123 }),
|
||||
/Invalid value for property 'guid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove({ parentGuid: "test" }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove({ parentGuid: null }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove({ parentGuid: 123 }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove({ url: "http://te st/" }),
|
||||
/Invalid value for property 'url'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove({ url: null }),
|
||||
/Invalid value for property 'url'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove({ url: -10 }),
|
||||
/Invalid value for property 'url'/);
|
||||
});
|
||||
|
||||
add_task(function* remove_nonexistent_guid() {
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.remove({ guid: "123456789012"});
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/No bookmarks found for the provided GUID/.test(ex));
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function* remove_roots_fail() {
|
||||
let guids = [PlacesUtils.bookmarks.rootGuid,
|
||||
PlacesUtils.bookmarks.unfiledGuid,
|
||||
PlacesUtils.bookmarks.menuGuid,
|
||||
PlacesUtils.bookmarks.toolbarGuid,
|
||||
PlacesUtils.bookmarks.tagsGuid,
|
||||
PlacesUtils.bookmarks.mobileGuid];
|
||||
for (let guid of guids) {
|
||||
Assert.throws(() => PlacesUtils.bookmarks.remove(guid),
|
||||
/It's not possible to remove Places root folders/);
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function* remove_normal_folder_under_root_succeeds() {
|
||||
let folder = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
checkBookmarkObject(folder);
|
||||
let removed_folder = yield PlacesUtils.bookmarks.remove(folder);
|
||||
Assert.deepEqual(folder, removed_folder);
|
||||
Assert.strictEqual((yield PlacesUtils.bookmarks.fetch(folder.guid)), null);
|
||||
});
|
||||
|
||||
add_task(function* remove_bookmark() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
checkBookmarkObject(bm2);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm2.index, 0);
|
||||
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
|
||||
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
|
||||
Assert.equal(bm2.url.href, "http://example.com/");
|
||||
Assert.equal(bm2.title, "a bookmark");
|
||||
});
|
||||
|
||||
|
||||
add_task(function* remove_bookmark_orphans() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
checkBookmarkObject(bm1);
|
||||
PlacesUtils.annotations.setItemAnnotation((yield PlacesUtils.promiseItemId(bm1.guid)),
|
||||
"testanno", "testvalue", 0, 0);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
checkBookmarkObject(bm2);
|
||||
|
||||
// Check there are no orphan annotations.
|
||||
let conn = yield PlacesUtils.promiseDBConnection();
|
||||
let annoAttrs = yield conn.execute(`SELECT id, name FROM moz_anno_attributes`);
|
||||
// Bug 1306445 will eventually remove the mobile root anno.
|
||||
Assert.equal(annoAttrs.length, 1);
|
||||
Assert.equal(annoAttrs[0].getResultByName("name"), PlacesUtils.MOBILE_ROOT_ANNO);
|
||||
let annos = rows = yield conn.execute(`SELECT item_id, anno_attribute_id FROM moz_items_annos`);
|
||||
Assert.equal(annos.length, 1);
|
||||
Assert.equal(annos[0].getResultByName("item_id"), PlacesUtils.mobileFolderId);
|
||||
Assert.equal(annos[0].getResultByName("anno_attribute_id"), annoAttrs[0].getResultByName("id"));
|
||||
});
|
||||
|
||||
add_task(function* remove_bookmark_empty_title() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/",
|
||||
title: "" });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
checkBookmarkObject(bm2);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.index, 0);
|
||||
Assert.ok(!("title" in bm2));
|
||||
});
|
||||
|
||||
add_task(function* remove_folder() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "a folder" });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
checkBookmarkObject(bm2);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm2.index, 0);
|
||||
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
|
||||
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_FOLDER);
|
||||
Assert.equal(bm2.title, "a folder");
|
||||
Assert.ok(!("url" in bm2));
|
||||
});
|
||||
|
||||
add_task(function* test_nested_contents_removed() {
|
||||
let folder1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "a folder" });
|
||||
let folder2 = yield PlacesUtils.bookmarks.insert({ parentGuid: folder1.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "a folder" });
|
||||
let sep = yield PlacesUtils.bookmarks.insert({ parentGuid: folder2.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR });
|
||||
yield PlacesUtils.bookmarks.remove(folder1);
|
||||
Assert.strictEqual((yield PlacesUtils.bookmarks.fetch(folder1.guid)), null);
|
||||
Assert.strictEqual((yield PlacesUtils.bookmarks.fetch(folder2.guid)), null);
|
||||
Assert.strictEqual((yield PlacesUtils.bookmarks.fetch(sep.guid)), null);
|
||||
});
|
||||
|
||||
add_task(function* remove_folder_empty_title() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "" });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
checkBookmarkObject(bm2);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.index, 0);
|
||||
Assert.ok(!("title" in bm2));
|
||||
});
|
||||
|
||||
add_task(function* remove_separator() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR });
|
||||
checkBookmarkObject(bm1);
|
||||
|
||||
let bm2 = yield PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
checkBookmarkObject(bm2);
|
||||
|
||||
Assert.deepEqual(bm1, bm2);
|
||||
Assert.equal(bm2.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
|
||||
Assert.equal(bm2.index, 0);
|
||||
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
|
||||
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_SEPARATOR);
|
||||
Assert.ok(!("url" in bm2));
|
||||
Assert.ok(!("title" in bm2));
|
||||
});
|
||||
|
||||
add_task(function* test_nested_content_fails_when_not_allowed() {
|
||||
let folder1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "a folder" });
|
||||
yield PlacesUtils.bookmarks.insert({ parentGuid: folder1.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "a folder" });
|
||||
yield Assert.rejects(PlacesUtils.bookmarks.remove(folder1, {preventRemovalOfNonEmptyFolders: true}),
|
||||
/Cannot remove a non-empty folder./);
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
add_task(function* invalid_input_throws() {
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder(),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder(null),
|
||||
/Invalid value for property 'guid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder("test"),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder(123),
|
||||
/Invalid value for property 'guid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder({ guid: "test" }),
|
||||
/Invalid value for property 'guid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder("123456789012"),
|
||||
/Must provide a sorted array of children GUIDs./);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder("123456789012", {}),
|
||||
/Must provide a sorted array of children GUIDs./);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder("123456789012", null),
|
||||
/Must provide a sorted array of children GUIDs./);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder("123456789012", []),
|
||||
/Must provide a sorted array of children GUIDs./);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder("123456789012", [ null ]),
|
||||
/Invalid GUID found in the sorted children array/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder("123456789012", [ "" ]),
|
||||
/Invalid GUID found in the sorted children array/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder("123456789012", [ {} ]),
|
||||
/Invalid GUID found in the sorted children array/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.reorder("123456789012", [ "012345678901", null ]),
|
||||
/Invalid GUID found in the sorted children array/);
|
||||
});
|
||||
|
||||
add_task(function* reorder_nonexistent_guid() {
|
||||
yield Assert.rejects(PlacesUtils.bookmarks.reorder("123456789012", [ "012345678901" ]),
|
||||
/No folder found for the provided GUID/,
|
||||
"Should throw for nonexisting guid");
|
||||
});
|
||||
|
||||
add_task(function* reorder() {
|
||||
let bookmarks = [
|
||||
{ url: "http://example1.com/",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
},
|
||||
{ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
},
|
||||
{ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
},
|
||||
{ url: "http://example2.com/",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
},
|
||||
{ url: "http://example3.com/",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
}
|
||||
];
|
||||
|
||||
let sorted = [];
|
||||
for (let bm of bookmarks) {
|
||||
sorted.push(yield PlacesUtils.bookmarks.insert(bm));
|
||||
}
|
||||
|
||||
// Check the initial append sorting.
|
||||
Assert.ok(sorted.every((bm, i) => bm.index == i),
|
||||
"Initial bookmarks sorting is correct");
|
||||
|
||||
// Apply random sorting and run multiple tests.
|
||||
for (let t = 0; t < 4; t++) {
|
||||
sorted.sort(() => 0.5 - Math.random());
|
||||
let sortedGuids = sorted.map(child => child.guid);
|
||||
dump("Expected order: " + sortedGuids.join() + "\n");
|
||||
// Add a nonexisting guid to the array, to ensure nothing will break.
|
||||
sortedGuids.push("123456789012");
|
||||
yield PlacesUtils.bookmarks.reorder(PlacesUtils.bookmarks.unfiledGuid,
|
||||
sortedGuids);
|
||||
for (let i = 0; i < sorted.length; ++i) {
|
||||
let item = yield PlacesUtils.bookmarks.fetch(sorted[i].guid);
|
||||
Assert.equal(item.index, i);
|
||||
}
|
||||
}
|
||||
|
||||
do_print("Test partial sorting");
|
||||
// Try a partial sorting by passing only 2 entries.
|
||||
// The unspecified entries should retain the original order.
|
||||
sorted = [ sorted[1], sorted[0] ].concat(sorted.slice(2));
|
||||
let sortedGuids = [ sorted[0].guid, sorted[1].guid ];
|
||||
dump("Expected order: " + sorted.map(b => b.guid).join() + "\n");
|
||||
yield PlacesUtils.bookmarks.reorder(PlacesUtils.bookmarks.unfiledGuid,
|
||||
sortedGuids);
|
||||
for (let i = 0; i < sorted.length; ++i) {
|
||||
let item = yield PlacesUtils.bookmarks.fetch(sorted[i].guid);
|
||||
Assert.equal(item.index, i);
|
||||
}
|
||||
|
||||
// Use triangular numbers to detect skipped position.
|
||||
let db = yield PlacesUtils.promiseDBConnection();
|
||||
let rows = yield db.execute(
|
||||
`SELECT parent
|
||||
FROM moz_bookmarks
|
||||
GROUP BY parent
|
||||
HAVING (SUM(DISTINCT position + 1) - (count(*) * (count(*) + 1) / 2)) <> 0`);
|
||||
Assert.equal(rows.length, 0, "All the bookmarks should have consistent positions");
|
||||
});
|
||||
|
||||
add_task(function* move_and_reorder() {
|
||||
// Start clean.
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({
|
||||
url: "http://example1.com/",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
});
|
||||
let f1 = yield PlacesUtils.bookmarks.insert({
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
});
|
||||
let bm2 = yield PlacesUtils.bookmarks.insert({
|
||||
url: "http://example2.com/",
|
||||
parentGuid: f1.guid
|
||||
});
|
||||
let f2 = yield PlacesUtils.bookmarks.insert({
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
});
|
||||
let bm3 = yield PlacesUtils.bookmarks.insert({
|
||||
url: "http://example3.com/",
|
||||
parentGuid: f2.guid
|
||||
});
|
||||
let bm4 = yield PlacesUtils.bookmarks.insert({
|
||||
url: "http://example4.com/",
|
||||
parentGuid: f2.guid
|
||||
});
|
||||
let bm5 = yield PlacesUtils.bookmarks.insert({
|
||||
url: "http://example5.com/",
|
||||
parentGuid: f2.guid
|
||||
});
|
||||
|
||||
// Invert f2 children.
|
||||
// This is critical to reproduce the bug, cause it inverts the position
|
||||
// compared to the natural insertion order.
|
||||
yield PlacesUtils.bookmarks.reorder(f2.guid, [bm5.guid, bm4.guid, bm3.guid]);
|
||||
|
||||
bm1.parentGuid = f1.guid;
|
||||
bm1.index = 0;
|
||||
yield PlacesUtils.bookmarks.update(bm1);
|
||||
|
||||
bm1 = yield PlacesUtils.bookmarks.fetch(bm1.guid);
|
||||
Assert.equal(bm1.index, 0);
|
||||
bm2 = yield PlacesUtils.bookmarks.fetch(bm2.guid);
|
||||
Assert.equal(bm2.index, 1);
|
||||
bm3 = yield PlacesUtils.bookmarks.fetch(bm3.guid);
|
||||
Assert.equal(bm3.index, 2);
|
||||
bm4 = yield PlacesUtils.bookmarks.fetch(bm4.guid);
|
||||
Assert.equal(bm4.index, 1);
|
||||
bm5 = yield PlacesUtils.bookmarks.fetch(bm5.guid);
|
||||
Assert.equal(bm5.index, 0);
|
||||
|
||||
// No-op reorder on f1 children.
|
||||
// Nothing should change. Though, due to bug 1293365 this was causing children
|
||||
// of other folders to get messed up.
|
||||
yield PlacesUtils.bookmarks.reorder(f1.guid, [bm1.guid, bm2.guid]);
|
||||
|
||||
bm1 = yield PlacesUtils.bookmarks.fetch(bm1.guid);
|
||||
Assert.equal(bm1.index, 0);
|
||||
bm2 = yield PlacesUtils.bookmarks.fetch(bm2.guid);
|
||||
Assert.equal(bm2.index, 1);
|
||||
bm3 = yield PlacesUtils.bookmarks.fetch(bm3.guid);
|
||||
Assert.equal(bm3.index, 2);
|
||||
bm4 = yield PlacesUtils.bookmarks.fetch(bm4.guid);
|
||||
Assert.equal(bm4.index, 1);
|
||||
bm5 = yield PlacesUtils.bookmarks.fetch(bm5.guid);
|
||||
Assert.equal(bm5.index, 0);
|
||||
});
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
add_task(function* invalid_input_throws() {
|
||||
Assert.throws(() => PlacesUtils.bookmarks.search(),
|
||||
/Query object is required/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.search(null),
|
||||
/Query object is required/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.search({title: 50}),
|
||||
/Title option must be a string/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.search({url: {url: "wombat"}}),
|
||||
/Url option must be a string or a URL object/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.search(50),
|
||||
/Query must be an object or a string/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.search(true),
|
||||
/Query must be an object or a string/);
|
||||
});
|
||||
|
||||
add_task(function* search_bookmark() {
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
let bm2 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.org/",
|
||||
title: "another bookmark" });
|
||||
let bm3 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
url: "http://menu.org/",
|
||||
title: "an on-menu bookmark" });
|
||||
let bm4 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
url: "http://toolbar.org/",
|
||||
title: "an on-toolbar bookmark" });
|
||||
checkBookmarkObject(bm1);
|
||||
checkBookmarkObject(bm2);
|
||||
checkBookmarkObject(bm3);
|
||||
checkBookmarkObject(bm4);
|
||||
|
||||
// finds a result by query
|
||||
let results = yield PlacesUtils.bookmarks.search("example.com");
|
||||
Assert.equal(results.length, 1);
|
||||
checkBookmarkObject(results[0]);
|
||||
Assert.deepEqual(bm1, results[0]);
|
||||
|
||||
// finds multiple results
|
||||
results = yield PlacesUtils.bookmarks.search("example");
|
||||
Assert.equal(results.length, 2);
|
||||
checkBookmarkObject(results[0]);
|
||||
checkBookmarkObject(results[1]);
|
||||
|
||||
// finds menu bookmarks
|
||||
results = yield PlacesUtils.bookmarks.search("an on-menu bookmark");
|
||||
Assert.equal(results.length, 1);
|
||||
checkBookmarkObject(results[0]);
|
||||
Assert.deepEqual(bm3, results[0]);
|
||||
|
||||
// finds toolbar bookmarks
|
||||
results = yield PlacesUtils.bookmarks.search("an on-toolbar bookmark");
|
||||
Assert.equal(results.length, 1);
|
||||
checkBookmarkObject(results[0]);
|
||||
Assert.deepEqual(bm4, results[0]);
|
||||
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
|
||||
add_task(function* search_bookmark_by_query_object() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
let bm2 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.org/",
|
||||
title: "another bookmark" });
|
||||
checkBookmarkObject(bm1);
|
||||
checkBookmarkObject(bm2);
|
||||
|
||||
let results = yield PlacesUtils.bookmarks.search({query: "example.com"});
|
||||
Assert.equal(results.length, 1);
|
||||
checkBookmarkObject(results[0]);
|
||||
|
||||
Assert.deepEqual(bm1, results[0]);
|
||||
|
||||
results = yield PlacesUtils.bookmarks.search({query: "example"});
|
||||
Assert.equal(results.length, 2);
|
||||
checkBookmarkObject(results[0]);
|
||||
checkBookmarkObject(results[1]);
|
||||
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
|
||||
add_task(function* search_bookmark_by_url() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
let bm2 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.org/path",
|
||||
title: "another bookmark" });
|
||||
let bm3 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.org/path",
|
||||
title: "third bookmark" });
|
||||
checkBookmarkObject(bm1);
|
||||
checkBookmarkObject(bm2);
|
||||
checkBookmarkObject(bm3);
|
||||
|
||||
// finds the correct result by url
|
||||
let results = yield PlacesUtils.bookmarks.search({url: "http://example.com/"});
|
||||
Assert.equal(results.length, 1);
|
||||
checkBookmarkObject(results[0]);
|
||||
Assert.deepEqual(bm1, results[0]);
|
||||
|
||||
// normalizes the url
|
||||
results = yield PlacesUtils.bookmarks.search({url: "http:/example.com"});
|
||||
Assert.equal(results.length, 1);
|
||||
checkBookmarkObject(results[0]);
|
||||
Assert.deepEqual(bm1, results[0]);
|
||||
|
||||
// returns multiple matches
|
||||
results = yield PlacesUtils.bookmarks.search({url: "http://example.org/path"});
|
||||
Assert.equal(results.length, 2);
|
||||
|
||||
// requires exact match
|
||||
results = yield PlacesUtils.bookmarks.search({url: "http://example.org/"});
|
||||
Assert.equal(results.length, 0);
|
||||
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
|
||||
add_task(function* search_bookmark_by_title() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
let bm2 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.org/path",
|
||||
title: "another bookmark" });
|
||||
let bm3 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.net/",
|
||||
title: "another bookmark" });
|
||||
checkBookmarkObject(bm1);
|
||||
checkBookmarkObject(bm2);
|
||||
checkBookmarkObject(bm3);
|
||||
|
||||
// finds the correct result by title
|
||||
let results = yield PlacesUtils.bookmarks.search({title: "a bookmark"});
|
||||
Assert.equal(results.length, 1);
|
||||
checkBookmarkObject(results[0]);
|
||||
Assert.deepEqual(bm1, results[0]);
|
||||
|
||||
// returns multiple matches
|
||||
results = yield PlacesUtils.bookmarks.search({title: "another bookmark"});
|
||||
Assert.equal(results.length, 2);
|
||||
|
||||
// requires exact match
|
||||
results = yield PlacesUtils.bookmarks.search({title: "bookmark"});
|
||||
Assert.equal(results.length, 0);
|
||||
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
|
||||
add_task(function* search_bookmark_combinations() {
|
||||
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
let bm2 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.org/path",
|
||||
title: "another bookmark" });
|
||||
let bm3 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.net/",
|
||||
title: "third bookmark" });
|
||||
checkBookmarkObject(bm1);
|
||||
checkBookmarkObject(bm2);
|
||||
checkBookmarkObject(bm3);
|
||||
|
||||
// finds the correct result if title and url match
|
||||
let results = yield PlacesUtils.bookmarks.search({url: "http://example.com/", title: "a bookmark"});
|
||||
Assert.equal(results.length, 1);
|
||||
checkBookmarkObject(results[0]);
|
||||
Assert.deepEqual(bm1, results[0]);
|
||||
|
||||
// does not match if query is not matching but url and title match
|
||||
results = yield PlacesUtils.bookmarks.search({url: "http://example.com/", title: "a bookmark", query: "nonexistent"});
|
||||
Assert.equal(results.length, 0);
|
||||
|
||||
// does not match if one parameter is not matching
|
||||
results = yield PlacesUtils.bookmarks.search({url: "http://what.ever", title: "a bookmark"});
|
||||
Assert.equal(results.length, 0);
|
||||
|
||||
// query only matches if other fields match as well
|
||||
results = yield PlacesUtils.bookmarks.search({query: "bookmark", url: "http://example.net/"});
|
||||
Assert.equal(results.length, 1);
|
||||
checkBookmarkObject(results[0]);
|
||||
Assert.deepEqual(bm3, results[0]);
|
||||
|
||||
// non-matching query will also return no results
|
||||
results = yield PlacesUtils.bookmarks.search({query: "nonexistent", url: "http://example.net/"});
|
||||
Assert.equal(results.length, 0);
|
||||
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
|
||||
add_task(function* search_folder() {
|
||||
let folder = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "a test folder" });
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: folder.guid,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark" });
|
||||
checkBookmarkObject(folder);
|
||||
checkBookmarkObject(bm);
|
||||
|
||||
// also finds folders
|
||||
let results = yield PlacesUtils.bookmarks.search("a test folder");
|
||||
Assert.equal(results.length, 1);
|
||||
checkBookmarkObject(results[0]);
|
||||
Assert.equal(folder.title, results[0].title);
|
||||
Assert.equal(folder.type, results[0].type);
|
||||
Assert.equal(folder.parentGuid, results[0].parentGuid);
|
||||
|
||||
// finds elements in folders
|
||||
results = yield PlacesUtils.bookmarks.search("example.com");
|
||||
Assert.equal(results.length, 1);
|
||||
checkBookmarkObject(results[0]);
|
||||
Assert.deepEqual(bm, results[0]);
|
||||
Assert.equal(folder.guid, results[0].parentGuid);
|
||||
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
|
||||
|
|
@ -0,0 +1,414 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
add_task(function* invalid_input_throws() {
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update(),
|
||||
/Input should be a valid object/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update(null),
|
||||
/Input should be a valid object/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({}),
|
||||
/The following properties were expected/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ guid: "test" }),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ guid: null }),
|
||||
/Invalid value for property 'guid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ guid: 123 }),
|
||||
/Invalid value for property 'guid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ parentGuid: "test" }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ parentGuid: null }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ parentGuid: 123 }),
|
||||
/Invalid value for property 'parentGuid'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ index: "1" }),
|
||||
/Invalid value for property 'index'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ index: -10 }),
|
||||
/Invalid value for property 'index'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ dateAdded: -10 }),
|
||||
/Invalid value for property 'dateAdded'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ dateAdded: "today" }),
|
||||
/Invalid value for property 'dateAdded'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ dateAdded: Date.now() }),
|
||||
/Invalid value for property 'dateAdded'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ lastModified: -10 }),
|
||||
/Invalid value for property 'lastModified'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ lastModified: "today" }),
|
||||
/Invalid value for property 'lastModified'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ lastModified: Date.now() }),
|
||||
/Invalid value for property 'lastModified'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ type: -1 }),
|
||||
/Invalid value for property 'type'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ type: 100 }),
|
||||
/Invalid value for property 'type'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ type: "bookmark" }),
|
||||
/Invalid value for property 'type'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ url: 10 }),
|
||||
/Invalid value for property 'url'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ url: "http://te st" }),
|
||||
/Invalid value for property 'url'/);
|
||||
let longurl = "http://www.example.com/";
|
||||
for (let i = 0; i < 65536; i++) {
|
||||
longurl += "a";
|
||||
}
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ url: longurl }),
|
||||
/Invalid value for property 'url'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ url: NetUtil.newURI(longurl) }),
|
||||
/Invalid value for property 'url'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ url: "te st" }),
|
||||
/Invalid value for property 'url'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ title: -1 }),
|
||||
/Invalid value for property 'title'/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ title: {} }),
|
||||
/Invalid value for property 'title'/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ guid: "123456789012" }),
|
||||
/Not enough properties to update/);
|
||||
|
||||
Assert.throws(() => PlacesUtils.bookmarks.update({ guid: "123456789012",
|
||||
parentGuid: "012345678901" }),
|
||||
/The following properties were expected: index/);
|
||||
});
|
||||
|
||||
add_task(function* nonexisting_bookmark_throws() {
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.update({ guid: "123456789012",
|
||||
title: "test" });
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/No bookmarks found for the provided GUID/.test(ex));
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function* invalid_properties_for_existing_bookmark() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.com/" });
|
||||
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/The bookmark type cannot be changed/.test(ex));
|
||||
}
|
||||
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
dateAdded: new Date() });
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/The bookmark dateAdded cannot be changed/.test(ex));
|
||||
}
|
||||
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
dateAdded: new Date() });
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/The bookmark dateAdded cannot be changed/.test(ex));
|
||||
}
|
||||
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
parentGuid: "123456789012",
|
||||
index: 1 });
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/No bookmarks found for the provided parentGuid/.test(ex));
|
||||
}
|
||||
|
||||
let past = new Date(Date.now() - 86400000);
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
lastModified: past });
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/Invalid value for property 'lastModified'/.test(ex));
|
||||
}
|
||||
|
||||
let folder = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.update({ guid: folder.guid,
|
||||
url: "http://example.com/" });
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/Invalid value for property 'url'/.test(ex));
|
||||
}
|
||||
|
||||
let separator = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.update({ guid: separator.guid,
|
||||
url: "http://example.com/" });
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/Invalid value for property 'url'/.test(ex));
|
||||
}
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.update({ guid: separator.guid,
|
||||
title: "test" });
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/Invalid value for property 'title'/.test(ex));
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function* long_title_trim() {
|
||||
let longtitle = "a";
|
||||
for (let i = 0; i < 4096; i++) {
|
||||
longtitle += "a";
|
||||
}
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "title" });
|
||||
checkBookmarkObject(bm);
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
title: longtitle });
|
||||
let newTitle = bm.title;
|
||||
Assert.equal(newTitle.length, 4096, "title should have been trimmed");
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.fetch(bm.guid);
|
||||
Assert.equal(bm.title, newTitle);
|
||||
});
|
||||
|
||||
add_task(function* update_lastModified() {
|
||||
let yesterday = new Date(Date.now() - 86400000);
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "title",
|
||||
dateAdded: yesterday });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.deepEqual(bm.lastModified, yesterday);
|
||||
|
||||
let time = new Date();
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
lastModified: time });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.deepEqual(bm.lastModified, time);
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.fetch(bm.guid);
|
||||
Assert.deepEqual(bm.lastModified, time);
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
lastModified: yesterday });
|
||||
Assert.deepEqual(bm.lastModified, yesterday);
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
title: "title2" });
|
||||
Assert.ok(bm.lastModified >= time);
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
title: "" });
|
||||
Assert.ok(!("title" in bm));
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.fetch(bm.guid);
|
||||
Assert.ok(!("title" in bm));
|
||||
});
|
||||
|
||||
add_task(function* update_url() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/",
|
||||
title: "title" });
|
||||
checkBookmarkObject(bm);
|
||||
let lastModified = bm.lastModified;
|
||||
let frecency = frecencyForUrl(bm.url);
|
||||
Assert.ok(frecency > 0, "Check frecency has been updated");
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
url: "http://mozilla.org/" });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.ok(bm.lastModified >= lastModified);
|
||||
Assert.equal(bm.url.href, "http://mozilla.org/");
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.fetch(bm.guid);
|
||||
Assert.equal(bm.url.href, "http://mozilla.org/");
|
||||
Assert.ok(bm.lastModified >= lastModified);
|
||||
|
||||
Assert.equal(frecencyForUrl("http://example.com/"), frecency, "Check frecency for example.com");
|
||||
Assert.equal(frecencyForUrl("http://mozilla.org/"), frecency, "Check frecency for mozilla.org");
|
||||
});
|
||||
|
||||
add_task(function* update_index() {
|
||||
let parent = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER }) ;
|
||||
let f1 = yield PlacesUtils.bookmarks.insert({ parentGuid: parent.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
Assert.equal(f1.index, 0);
|
||||
let f2 = yield PlacesUtils.bookmarks.insert({ parentGuid: parent.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
Assert.equal(f2.index, 1);
|
||||
let f3 = yield PlacesUtils.bookmarks.insert({ parentGuid: parent.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
Assert.equal(f3.index, 2);
|
||||
let lastModified = f1.lastModified;
|
||||
|
||||
f1 = yield PlacesUtils.bookmarks.update({ guid: f1.guid,
|
||||
parentGuid: f1.parentGuid,
|
||||
index: 1});
|
||||
checkBookmarkObject(f1);
|
||||
Assert.equal(f1.index, 1);
|
||||
Assert.ok(f1.lastModified >= lastModified);
|
||||
|
||||
parent = yield PlacesUtils.bookmarks.fetch(f1.parentGuid);
|
||||
Assert.deepEqual(parent.lastModified, f1.lastModified);
|
||||
|
||||
f2 = yield PlacesUtils.bookmarks.fetch(f2.guid);
|
||||
Assert.equal(f2.index, 0);
|
||||
|
||||
f3 = yield PlacesUtils.bookmarks.fetch(f3.guid);
|
||||
Assert.equal(f3.index, 2);
|
||||
|
||||
f3 = yield PlacesUtils.bookmarks.update({ guid: f3.guid,
|
||||
index: 0 });
|
||||
f1 = yield PlacesUtils.bookmarks.fetch(f1.guid);
|
||||
Assert.equal(f1.index, 2);
|
||||
|
||||
f2 = yield PlacesUtils.bookmarks.fetch(f2.guid);
|
||||
Assert.equal(f2.index, 1);
|
||||
});
|
||||
|
||||
add_task(function* update_move_folder_into_descendant_throws() {
|
||||
let parent = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER }) ;
|
||||
let descendant = yield PlacesUtils.bookmarks.insert({ parentGuid: parent.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.update({ guid: parent.guid,
|
||||
parentGuid: parent.guid,
|
||||
index: 0 });
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/Cannot insert a folder into itself or one of its descendants/.test(ex));
|
||||
}
|
||||
|
||||
try {
|
||||
yield PlacesUtils.bookmarks.update({ guid: parent.guid,
|
||||
parentGuid: descendant.guid,
|
||||
index: 0 });
|
||||
Assert.ok(false, "Should have thrown");
|
||||
} catch (ex) {
|
||||
Assert.ok(/Cannot insert a folder into itself or one of its descendants/.test(ex));
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function* update_move() {
|
||||
let parent = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER }) ;
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: parent.guid,
|
||||
url: "http://example.com/",
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK }) ;
|
||||
let descendant = yield PlacesUtils.bookmarks.insert({ parentGuid: parent.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
Assert.equal(descendant.index, 1);
|
||||
let lastModified = bm.lastModified;
|
||||
|
||||
// This is moving to a nonexisting index by purpose, it will be appended.
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
parentGuid: descendant.guid,
|
||||
index: 1 });
|
||||
checkBookmarkObject(bm);
|
||||
Assert.equal(bm.parentGuid, descendant.guid);
|
||||
Assert.equal(bm.index, 0);
|
||||
Assert.ok(bm.lastModified >= lastModified);
|
||||
|
||||
parent = yield PlacesUtils.bookmarks.fetch(parent.guid);
|
||||
descendant = yield PlacesUtils.bookmarks.fetch(descendant.guid);
|
||||
Assert.deepEqual(parent.lastModified, bm.lastModified);
|
||||
Assert.deepEqual(descendant.lastModified, bm.lastModified);
|
||||
Assert.equal(descendant.index, 0);
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.fetch(bm.guid);
|
||||
Assert.equal(bm.parentGuid, descendant.guid);
|
||||
Assert.equal(bm.index, 0);
|
||||
|
||||
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
|
||||
parentGuid: parent.guid,
|
||||
index: 0 });
|
||||
Assert.equal(bm.parentGuid, parent.guid);
|
||||
Assert.equal(bm.index, 0);
|
||||
|
||||
descendant = yield PlacesUtils.bookmarks.fetch(descendant.guid);
|
||||
Assert.equal(descendant.index, 1);
|
||||
});
|
||||
|
||||
add_task(function* update_move_append() {
|
||||
let folder_a =
|
||||
yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
checkBookmarkObject(folder_a);
|
||||
let folder_b =
|
||||
yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
checkBookmarkObject(folder_b);
|
||||
|
||||
/* folder_a: [sep_1, sep_2, sep_3], folder_b: [] */
|
||||
let sep_1 = yield PlacesUtils.bookmarks.insert({ parentGuid: folder_a.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR });
|
||||
checkBookmarkObject(sep_1);
|
||||
let sep_2 = yield PlacesUtils.bookmarks.insert({ parentGuid: folder_a.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR });
|
||||
checkBookmarkObject(sep_2);
|
||||
let sep_3 = yield PlacesUtils.bookmarks.insert({ parentGuid: folder_a.guid,
|
||||
type: PlacesUtils.bookmarks.TYPE_SEPARATOR });
|
||||
checkBookmarkObject(sep_3);
|
||||
|
||||
function ensurePosition(info, parentGuid, index) {
|
||||
checkBookmarkObject(info);
|
||||
Assert.equal(info.parentGuid, parentGuid);
|
||||
Assert.equal(info.index, index);
|
||||
}
|
||||
|
||||
// folder_a: [sep_2, sep_3, sep_1], folder_b: []
|
||||
sep_1.index = PlacesUtils.bookmarks.DEFAULT_INDEX;
|
||||
// Note sep_1 includes parentGuid even though we're not moving the item to
|
||||
// another folder
|
||||
sep_1 = yield PlacesUtils.bookmarks.update(sep_1);
|
||||
ensurePosition(sep_1, folder_a.guid, 2);
|
||||
sep_2 = yield PlacesUtils.bookmarks.fetch(sep_2.guid);
|
||||
ensurePosition(sep_2, folder_a.guid, 0);
|
||||
sep_3 = yield PlacesUtils.bookmarks.fetch(sep_3.guid);
|
||||
ensurePosition(sep_3, folder_a.guid, 1);
|
||||
sep_1 = yield PlacesUtils.bookmarks.fetch(sep_1.guid);
|
||||
ensurePosition(sep_1, folder_a.guid, 2);
|
||||
|
||||
// folder_a: [sep_2, sep_1], folder_b: [sep_3]
|
||||
sep_3.index = PlacesUtils.bookmarks.DEFAULT_INDEX;
|
||||
sep_3.parentGuid = folder_b.guid;
|
||||
sep_3 = yield PlacesUtils.bookmarks.update(sep_3);
|
||||
ensurePosition(sep_3, folder_b.guid, 0);
|
||||
sep_2 = yield PlacesUtils.bookmarks.fetch(sep_2.guid);
|
||||
ensurePosition(sep_2, folder_a.guid, 0);
|
||||
sep_1 = yield PlacesUtils.bookmarks.fetch(sep_1.guid);
|
||||
ensurePosition(sep_1, folder_a.guid, 1);
|
||||
sep_3 = yield PlacesUtils.bookmarks.fetch(sep_3.guid);
|
||||
ensurePosition(sep_3, folder_b.guid, 0);
|
||||
|
||||
// folder_a: [sep_1], folder_b: [sep_3, sep_2]
|
||||
sep_2.index = Number.MAX_SAFE_INTEGER;
|
||||
sep_2.parentGuid = folder_b.guid;
|
||||
sep_2 = yield PlacesUtils.bookmarks.update(sep_2);
|
||||
ensurePosition(sep_2, folder_b.guid, 1);
|
||||
sep_1 = yield PlacesUtils.bookmarks.fetch(sep_1.guid);
|
||||
ensurePosition(sep_1, folder_a.guid, 0);
|
||||
sep_3 = yield PlacesUtils.bookmarks.fetch(sep_3.guid);
|
||||
ensurePosition(sep_3, folder_b.guid, 0);
|
||||
sep_2 = yield PlacesUtils.bookmarks.fetch(sep_2.guid);
|
||||
ensurePosition(sep_2, folder_b.guid, 1);
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
// Bug 1192692 - promiseBookmarksTree caches items without adding observers to
|
||||
// invalidate the cache.
|
||||
add_task(function* boookmarks_tree_cache() {
|
||||
// Note that for this test to be effective, it needs to use the "old" sync
|
||||
// bookmarks methods - using, eg, PlacesUtils.bookmarks.insert() doesn't
|
||||
// demonstrate the problem as it indirectly arranges for the observers to
|
||||
// be added.
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
uri("http://example.com"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"A title");
|
||||
yield PlacesUtils.promiseBookmarksTree();
|
||||
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
|
||||
yield Assert.rejects(PlacesUtils.promiseItemGuid(id));
|
||||
});
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Get bookmark service
|
||||
var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
|
||||
/**
|
||||
* Ensures that the Places APIs recognize that aBookmarkedUri is bookmarked
|
||||
* via aBookmarkId and that aUnbookmarkedUri is not bookmarked at all.
|
||||
*
|
||||
* @param aBookmarkId
|
||||
* an item ID whose corresponding URI is aBookmarkedUri
|
||||
* @param aBookmarkedUri
|
||||
* a bookmarked URI that has a corresponding item ID aBookmarkId
|
||||
* @param aUnbookmarkedUri
|
||||
* a URI that is not currently bookmarked at all
|
||||
*/
|
||||
function checkUris(aBookmarkId, aBookmarkedUri, aUnbookmarkedUri)
|
||||
{
|
||||
// Ensure that aBookmarkedUri equals some URI that is bookmarked
|
||||
var uri = bmsvc.getBookmarkedURIFor(aBookmarkedUri);
|
||||
do_check_neq(uri, null);
|
||||
do_check_true(uri.equals(aBookmarkedUri));
|
||||
|
||||
// Ensure that aBookmarkedUri is considered bookmarked
|
||||
do_check_true(bmsvc.isBookmarked(aBookmarkedUri));
|
||||
|
||||
// Ensure that the URI corresponding to aBookmarkId equals aBookmarkedUri
|
||||
do_check_true(bmsvc.getBookmarkURI(aBookmarkId).equals(aBookmarkedUri));
|
||||
|
||||
// Ensure that aUnbookmarkedUri does not equal any URI that is bookmarked
|
||||
uri = bmsvc.getBookmarkedURIFor(aUnbookmarkedUri);
|
||||
do_check_eq(uri, null);
|
||||
|
||||
// Ensure that aUnbookmarkedUri is not considered bookmarked
|
||||
do_check_false(bmsvc.isBookmarked(aUnbookmarkedUri));
|
||||
}
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
// Create a folder
|
||||
var folderId = bmsvc.createFolder(bmsvc.toolbarFolder,
|
||||
"test",
|
||||
bmsvc.DEFAULT_INDEX);
|
||||
|
||||
// Create 2 URIs
|
||||
var uri1 = uri("http://www.dogs.com");
|
||||
var uri2 = uri("http://www.cats.com");
|
||||
|
||||
// Bookmark the first one
|
||||
var bookmarkId = bmsvc.insertBookmark(folderId,
|
||||
uri1,
|
||||
bmsvc.DEFAULT_INDEX,
|
||||
"Dogs");
|
||||
|
||||
// uri1 is bookmarked via bookmarkId, uri2 is not
|
||||
checkUris(bookmarkId, uri1, uri2);
|
||||
|
||||
// Change the URI of the bookmark to uri2
|
||||
bmsvc.changeBookmarkURI(bookmarkId, uri2);
|
||||
|
||||
// uri2 is now bookmarked via bookmarkId, uri1 is not
|
||||
checkUris(bookmarkId, uri2, uri1);
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Test bookmarksService.getBookmarkedURIFor(aURI);
|
||||
*/
|
||||
|
||||
var hs = PlacesUtils.history;
|
||||
var bs = PlacesUtils.bookmarks;
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* test_getBookmarkedURIFor() {
|
||||
let now = Date.now() * 1000;
|
||||
const sourceURI = uri("http://test.mozilla.org/");
|
||||
// Add a visit and a bookmark.
|
||||
yield PlacesTestUtils.addVisits({ uri: sourceURI, visitDate: now });
|
||||
do_check_eq(bs.getBookmarkedURIFor(sourceURI), null);
|
||||
|
||||
let sourceItemId = bs.insertBookmark(bs.unfiledBookmarksFolder,
|
||||
sourceURI,
|
||||
bs.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
do_check_true(bs.getBookmarkedURIFor(sourceURI).equals(sourceURI));
|
||||
|
||||
// Add a redirected visit.
|
||||
const permaURI = uri("http://perma.mozilla.org/");
|
||||
yield PlacesTestUtils.addVisits({
|
||||
uri: permaURI,
|
||||
transition: TRANSITION_REDIRECT_PERMANENT,
|
||||
visitDate: now++,
|
||||
referrer: sourceURI
|
||||
});
|
||||
do_check_true(bs.getBookmarkedURIFor(sourceURI).equals(sourceURI));
|
||||
do_check_true(bs.getBookmarkedURIFor(permaURI).equals(sourceURI));
|
||||
// Add a bookmark to the destination.
|
||||
let permaItemId = bs.insertBookmark(bs.unfiledBookmarksFolder,
|
||||
permaURI,
|
||||
bs.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
do_check_true(bs.getBookmarkedURIFor(sourceURI).equals(sourceURI));
|
||||
do_check_true(bs.getBookmarkedURIFor(permaURI).equals(permaURI));
|
||||
// Now remove the bookmark on the destination.
|
||||
bs.removeItem(permaItemId);
|
||||
// We should see the source as bookmark.
|
||||
do_check_true(bs.getBookmarkedURIFor(permaURI).equals(sourceURI));
|
||||
|
||||
// Add another redirected visit.
|
||||
const tempURI = uri("http://perma.mozilla.org/");
|
||||
yield PlacesTestUtils.addVisits({
|
||||
uri: tempURI,
|
||||
transition: TRANSITION_REDIRECT_TEMPORARY,
|
||||
visitDate: now++,
|
||||
referrer: permaURI
|
||||
});
|
||||
|
||||
do_check_true(bs.getBookmarkedURIFor(sourceURI).equals(sourceURI));
|
||||
do_check_true(bs.getBookmarkedURIFor(tempURI).equals(sourceURI));
|
||||
// Add a bookmark to the destination.
|
||||
let tempItemId = bs.insertBookmark(bs.unfiledBookmarksFolder,
|
||||
tempURI,
|
||||
bs.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
do_check_true(bs.getBookmarkedURIFor(sourceURI).equals(sourceURI));
|
||||
do_check_true(bs.getBookmarkedURIFor(tempURI).equals(tempURI));
|
||||
|
||||
// Now remove the bookmark on the destination.
|
||||
bs.removeItem(tempItemId);
|
||||
// We should see the source as bookmark.
|
||||
do_check_true(bs.getBookmarkedURIFor(tempURI).equals(sourceURI));
|
||||
// Remove the source bookmark as well.
|
||||
bs.removeItem(sourceItemId);
|
||||
do_check_eq(bs.getBookmarkedURIFor(tempURI), null);
|
||||
|
||||
// Try to pass in a never seen URI, should return null and a new entry should
|
||||
// not be added to the database.
|
||||
do_check_eq(bs.getBookmarkedURIFor(uri("http://does.not.exist/")), null);
|
||||
do_check_false(page_in_database("http://does.not.exist/"));
|
||||
});
|
||||
310
toolkit/components/places/tests/bookmarks/test_keywords.js
Normal file
310
toolkit/components/places/tests/bookmarks/test_keywords.js
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
const URI1 = NetUtil.newURI("http://test1.mozilla.org/");
|
||||
const URI2 = NetUtil.newURI("http://test2.mozilla.org/");
|
||||
const URI3 = NetUtil.newURI("http://test3.mozilla.org/");
|
||||
|
||||
function check_keyword(aURI, aKeyword) {
|
||||
if (aKeyword)
|
||||
aKeyword = aKeyword.toLowerCase();
|
||||
|
||||
for (let bm of PlacesUtils.getBookmarksForURI(aURI)) {
|
||||
let keyword = PlacesUtils.bookmarks.getKeywordForBookmark(bm);
|
||||
if (keyword && !aKeyword) {
|
||||
throw (`${aURI.spec} should not have a keyword`);
|
||||
} else if (aKeyword && keyword == aKeyword) {
|
||||
Assert.equal(keyword, aKeyword);
|
||||
}
|
||||
}
|
||||
|
||||
if (aKeyword) {
|
||||
let uri = PlacesUtils.bookmarks.getURIForKeyword(aKeyword);
|
||||
Assert.equal(uri.spec, aURI.spec);
|
||||
// Check case insensitivity.
|
||||
uri = PlacesUtils.bookmarks.getURIForKeyword(aKeyword.toUpperCase());
|
||||
Assert.equal(uri.spec, aURI.spec);
|
||||
}
|
||||
}
|
||||
|
||||
function* check_orphans() {
|
||||
let db = yield PlacesUtils.promiseDBConnection();
|
||||
let rows = yield db.executeCached(
|
||||
`SELECT id FROM moz_keywords k
|
||||
WHERE NOT EXISTS (SELECT 1 FROM moz_places WHERE id = k.place_id)
|
||||
`);
|
||||
Assert.equal(rows.length, 0);
|
||||
}
|
||||
|
||||
function expectNotifications() {
|
||||
let notifications = [];
|
||||
let observer = new Proxy(NavBookmarkObserver, {
|
||||
get(target, name) {
|
||||
if (name == "check") {
|
||||
PlacesUtils.bookmarks.removeObserver(observer);
|
||||
return expectedNotifications =>
|
||||
Assert.deepEqual(notifications, expectedNotifications);
|
||||
}
|
||||
|
||||
if (name.startsWith("onItemChanged")) {
|
||||
return function(id, prop, isAnno, val, lastMod, itemType, parentId, guid, parentGuid, oldVal) {
|
||||
if (prop != "keyword")
|
||||
return;
|
||||
let args = Array.from(arguments, arg => {
|
||||
if (arg && arg instanceof Ci.nsIURI)
|
||||
return new URL(arg.spec);
|
||||
if (arg && typeof(arg) == "number" && arg >= Date.now() * 1000)
|
||||
return new Date(parseInt(arg/1000));
|
||||
return arg;
|
||||
});
|
||||
notifications.push({ name: name, arguments: args });
|
||||
}
|
||||
}
|
||||
|
||||
return target[name];
|
||||
}
|
||||
});
|
||||
PlacesUtils.bookmarks.addObserver(observer, false);
|
||||
return observer;
|
||||
}
|
||||
|
||||
add_task(function test_invalid_input() {
|
||||
Assert.throws(() => PlacesUtils.bookmarks.getURIForKeyword(null),
|
||||
/NS_ERROR_ILLEGAL_VALUE/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.getURIForKeyword(""),
|
||||
/NS_ERROR_ILLEGAL_VALUE/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.getKeywordForBookmark(null),
|
||||
/NS_ERROR_ILLEGAL_VALUE/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.getKeywordForBookmark(0),
|
||||
/NS_ERROR_ILLEGAL_VALUE/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.setKeywordForBookmark(null, "k"),
|
||||
/NS_ERROR_ILLEGAL_VALUE/);
|
||||
Assert.throws(() => PlacesUtils.bookmarks.setKeywordForBookmark(0, "k"),
|
||||
/NS_ERROR_ILLEGAL_VALUE/);
|
||||
});
|
||||
|
||||
add_task(function* test_addBookmarkAndKeyword() {
|
||||
check_keyword(URI1, null);
|
||||
let fc = yield foreign_count(URI1);
|
||||
let observer = expectNotifications();
|
||||
|
||||
let itemId =
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
URI1,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"test");
|
||||
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "keyword");
|
||||
let bookmark = yield PlacesUtils.bookmarks.fetch({ url: URI1 });
|
||||
observer.check([ { name: "onItemChanged",
|
||||
arguments: [ itemId, "keyword", false, "keyword",
|
||||
bookmark.lastModified, bookmark.type,
|
||||
(yield PlacesUtils.promiseItemId(bookmark.parentGuid)),
|
||||
bookmark.guid, bookmark.parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
|
||||
check_keyword(URI1, "keyword");
|
||||
Assert.equal((yield foreign_count(URI1)), fc + 2); // + 1 bookmark + 1 keyword
|
||||
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
yield check_orphans();
|
||||
});
|
||||
|
||||
add_task(function* test_addBookmarkToURIHavingKeyword() {
|
||||
// The uri has already a keyword.
|
||||
check_keyword(URI1, "keyword");
|
||||
let fc = yield foreign_count(URI1);
|
||||
|
||||
let itemId =
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
URI1,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"test");
|
||||
check_keyword(URI1, "keyword");
|
||||
Assert.equal((yield foreign_count(URI1)), fc + 1); // + 1 bookmark
|
||||
|
||||
PlacesUtils.bookmarks.removeItem(itemId);
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
check_orphans();
|
||||
});
|
||||
|
||||
add_task(function* test_sameKeywordDifferentURI() {
|
||||
let fc1 = yield foreign_count(URI1);
|
||||
let fc2 = yield foreign_count(URI2);
|
||||
let observer = expectNotifications();
|
||||
|
||||
let itemId =
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
URI2,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"test2");
|
||||
check_keyword(URI1, "keyword");
|
||||
check_keyword(URI2, null);
|
||||
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "kEyWoRd");
|
||||
|
||||
let bookmark1 = yield PlacesUtils.bookmarks.fetch({ url: URI1 });
|
||||
let bookmark2 = yield PlacesUtils.bookmarks.fetch({ url: URI2 });
|
||||
observer.check([ { name: "onItemChanged",
|
||||
arguments: [ (yield PlacesUtils.promiseItemId(bookmark1.guid)),
|
||||
"keyword", false, "",
|
||||
bookmark1.lastModified, bookmark1.type,
|
||||
(yield PlacesUtils.promiseItemId(bookmark1.parentGuid)),
|
||||
bookmark1.guid, bookmark1.parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemChanged",
|
||||
arguments: [ itemId, "keyword", false, "keyword",
|
||||
bookmark2.lastModified, bookmark2.type,
|
||||
(yield PlacesUtils.promiseItemId(bookmark2.parentGuid)),
|
||||
bookmark2.guid, bookmark2.parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
|
||||
// The keyword should have been "moved" to the new URI.
|
||||
check_keyword(URI1, null);
|
||||
Assert.equal((yield foreign_count(URI1)), fc1 - 1); // - 1 keyword
|
||||
check_keyword(URI2, "keyword");
|
||||
Assert.equal((yield foreign_count(URI2)), fc2 + 2); // + 1 bookmark + 1 keyword
|
||||
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
check_orphans();
|
||||
});
|
||||
|
||||
add_task(function* test_sameURIDifferentKeyword() {
|
||||
let fc = yield foreign_count(URI2);
|
||||
let observer = expectNotifications();
|
||||
|
||||
let itemId =
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
URI2,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"test2");
|
||||
check_keyword(URI2, "keyword");
|
||||
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "keyword2");
|
||||
|
||||
let bookmarks = [];
|
||||
yield PlacesUtils.bookmarks.fetch({ url: URI2 }, bookmark => bookmarks.push(bookmark));
|
||||
observer.check([ { name: "onItemChanged",
|
||||
arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[0].guid)),
|
||||
"keyword", false, "keyword2",
|
||||
bookmarks[0].lastModified, bookmarks[0].type,
|
||||
(yield PlacesUtils.promiseItemId(bookmarks[0].parentGuid)),
|
||||
bookmarks[0].guid, bookmarks[0].parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemChanged",
|
||||
arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[1].guid)),
|
||||
"keyword", false, "keyword2",
|
||||
bookmarks[1].lastModified, bookmarks[1].type,
|
||||
(yield PlacesUtils.promiseItemId(bookmarks[1].parentGuid)),
|
||||
bookmarks[1].guid, bookmarks[1].parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
|
||||
check_keyword(URI2, "keyword2");
|
||||
Assert.equal((yield foreign_count(URI2)), fc + 2); // + 1 bookmark + 1 keyword
|
||||
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
check_orphans();
|
||||
});
|
||||
|
||||
add_task(function* test_removeBookmarkWithKeyword() {
|
||||
let fc = yield foreign_count(URI2);
|
||||
let itemId =
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
URI2,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"test");
|
||||
|
||||
// The keyword should not be removed, since there are other bookmarks yet.
|
||||
PlacesUtils.bookmarks.removeItem(itemId);
|
||||
|
||||
check_keyword(URI2, "keyword2");
|
||||
Assert.equal((yield foreign_count(URI2)), fc); // + 1 bookmark - 1 bookmark
|
||||
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
check_orphans();
|
||||
});
|
||||
|
||||
add_task(function* test_unsetKeyword() {
|
||||
let fc = yield foreign_count(URI2);
|
||||
let observer = expectNotifications();
|
||||
|
||||
let itemId =
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
URI2,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"test");
|
||||
|
||||
// The keyword should be removed from any bookmark.
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(itemId, null);
|
||||
|
||||
let bookmarks = [];
|
||||
yield PlacesUtils.bookmarks.fetch({ url: URI2 }, bookmark => bookmarks.push(bookmark));
|
||||
do_print(bookmarks.length);
|
||||
observer.check([ { name: "onItemChanged",
|
||||
arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[0].guid)),
|
||||
"keyword", false, "",
|
||||
bookmarks[0].lastModified, bookmarks[0].type,
|
||||
(yield PlacesUtils.promiseItemId(bookmarks[0].parentGuid)),
|
||||
bookmarks[0].guid, bookmarks[0].parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemChanged",
|
||||
arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[1].guid)),
|
||||
"keyword", false, "",
|
||||
bookmarks[1].lastModified, bookmarks[1].type,
|
||||
(yield PlacesUtils.promiseItemId(bookmarks[1].parentGuid)),
|
||||
bookmarks[1].guid, bookmarks[1].parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
|
||||
{ name: "onItemChanged",
|
||||
arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[2].guid)),
|
||||
"keyword", false, "",
|
||||
bookmarks[2].lastModified, bookmarks[2].type,
|
||||
(yield PlacesUtils.promiseItemId(bookmarks[2].parentGuid)),
|
||||
bookmarks[2].guid, bookmarks[2].parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
|
||||
check_keyword(URI1, null);
|
||||
check_keyword(URI2, null);
|
||||
Assert.equal((yield foreign_count(URI2)), fc - 1); // + 1 bookmark - 2 keyword
|
||||
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
check_orphans();
|
||||
});
|
||||
|
||||
add_task(function* test_addRemoveBookmark() {
|
||||
let observer = expectNotifications();
|
||||
|
||||
let itemId =
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
URI3,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"test3");
|
||||
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "keyword");
|
||||
let bookmark = yield PlacesUtils.bookmarks.fetch({ url: URI3 });
|
||||
let parentId = yield PlacesUtils.promiseItemId(bookmark.parentGuid);
|
||||
PlacesUtils.bookmarks.removeItem(itemId);
|
||||
|
||||
observer.check([ { name: "onItemChanged",
|
||||
arguments: [ itemId,
|
||||
"keyword", false, "keyword",
|
||||
bookmark.lastModified, bookmark.type,
|
||||
parentId,
|
||||
bookmark.guid, bookmark.parentGuid, "",
|
||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
|
||||
]);
|
||||
|
||||
check_keyword(URI3, null);
|
||||
// Don't check the foreign count since the process is async.
|
||||
// The new test_keywords.js in unit is checking this though.
|
||||
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
check_orphans();
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
|
@ -0,0 +1,640 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that each nsINavBookmarksObserver method gets the correct input.
|
||||
Cu.import("resource://gre/modules/PromiseUtils.jsm");
|
||||
|
||||
const GUID_RE = /^[a-zA-Z0-9\-_]{12}$/;
|
||||
|
||||
var gBookmarksObserver = {
|
||||
expected: [],
|
||||
setup(expected) {
|
||||
this.expected = expected;
|
||||
this.deferred = PromiseUtils.defer();
|
||||
return this.deferred.promise;
|
||||
},
|
||||
validate: function (aMethodName, aArguments) {
|
||||
do_check_eq(this.expected[0].name, aMethodName);
|
||||
|
||||
let args = this.expected.shift().args;
|
||||
do_check_eq(aArguments.length, args.length);
|
||||
for (let i = 0; i < aArguments.length; i++) {
|
||||
do_check_true(args[i].check(aArguments[i]), aMethodName + "(args[" + i + "]: " + args[i].name + ")");
|
||||
}
|
||||
|
||||
if (this.expected.length === 0) {
|
||||
this.deferred.resolve();
|
||||
}
|
||||
},
|
||||
|
||||
// nsINavBookmarkObserver
|
||||
onBeginUpdateBatch() {
|
||||
return this.validate("onBeginUpdateBatch", arguments);
|
||||
},
|
||||
onEndUpdateBatch() {
|
||||
return this.validate("onEndUpdateBatch", arguments);
|
||||
},
|
||||
onItemAdded() {
|
||||
return this.validate("onItemAdded", arguments);
|
||||
},
|
||||
onItemRemoved() {
|
||||
return this.validate("onItemRemoved", arguments);
|
||||
},
|
||||
onItemChanged() {
|
||||
return this.validate("onItemChanged", arguments);
|
||||
},
|
||||
onItemVisited() {
|
||||
return this.validate("onItemVisited", arguments);
|
||||
},
|
||||
onItemMoved() {
|
||||
return this.validate("onItemMoved", arguments);
|
||||
},
|
||||
|
||||
// nsISupports
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver]),
|
||||
};
|
||||
|
||||
var gBookmarkSkipObserver = {
|
||||
skipTags: true,
|
||||
skipDescendantsOnItemRemoval: true,
|
||||
|
||||
expected: null,
|
||||
setup(expected) {
|
||||
this.expected = expected;
|
||||
this.deferred = PromiseUtils.defer();
|
||||
return this.deferred.promise;
|
||||
},
|
||||
validate: function (aMethodName) {
|
||||
do_check_eq(this.expected.shift(), aMethodName);
|
||||
if (this.expected.length === 0) {
|
||||
this.deferred.resolve();
|
||||
}
|
||||
},
|
||||
|
||||
// nsINavBookmarkObserver
|
||||
onBeginUpdateBatch() {
|
||||
return this.validate("onBeginUpdateBatch", arguments);
|
||||
},
|
||||
onEndUpdateBatch() {
|
||||
return this.validate("onEndUpdateBatch", arguments);
|
||||
},
|
||||
onItemAdded() {
|
||||
return this.validate("onItemAdded", arguments);
|
||||
},
|
||||
onItemRemoved() {
|
||||
return this.validate("onItemRemoved", arguments);
|
||||
},
|
||||
onItemChanged() {
|
||||
return this.validate("onItemChanged", arguments);
|
||||
},
|
||||
onItemVisited() {
|
||||
return this.validate("onItemVisited", arguments);
|
||||
},
|
||||
onItemMoved() {
|
||||
return this.validate("onItemMoved", arguments);
|
||||
},
|
||||
|
||||
// nsISupports
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver]),
|
||||
};
|
||||
|
||||
|
||||
add_task(function setup() {
|
||||
PlacesUtils.bookmarks.addObserver(gBookmarksObserver, false);
|
||||
PlacesUtils.bookmarks.addObserver(gBookmarkSkipObserver, false);
|
||||
});
|
||||
|
||||
add_task(function* batch() {
|
||||
let promise = Promise.all([
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onBeginUpdateBatch",
|
||||
args: [] },
|
||||
{ name: "onEndUpdateBatch",
|
||||
args: [] },
|
||||
]),
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onBeginUpdateBatch", "onEndUpdateBatch"
|
||||
])]);
|
||||
PlacesUtils.bookmarks.runInBatchMode({
|
||||
runBatched: function () {
|
||||
// Nothing.
|
||||
}
|
||||
}, null);
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function* onItemAdded_bookmark() {
|
||||
const TITLE = "Bookmark 1";
|
||||
let uri = NetUtil.newURI("http://1.mozilla.org/");
|
||||
let promise = Promise.all([
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onItemAdded"
|
||||
]),
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onItemAdded",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
|
||||
{ name: "title", check: v => v === TITLE },
|
||||
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
])]);
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
uri, PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
TITLE);
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function* onItemAdded_separator() {
|
||||
let promise = Promise.all([
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onItemAdded"
|
||||
]),
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onItemAdded",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "index", check: v => v === 1 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_SEPARATOR },
|
||||
{ name: "uri", check: v => v === null },
|
||||
{ name: "title", check: v => v === null },
|
||||
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
])]);
|
||||
PlacesUtils.bookmarks.insertSeparator(PlacesUtils.unfiledBookmarksFolderId,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function* onItemAdded_folder() {
|
||||
const TITLE = "Folder 1";
|
||||
let promise = Promise.all([
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onItemAdded"
|
||||
]),
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onItemAdded",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "index", check: v => v === 2 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
|
||||
{ name: "uri", check: v => v === null },
|
||||
{ name: "title", check: v => v === TITLE },
|
||||
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
])]);
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TITLE,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function* onItemChanged_title_bookmark() {
|
||||
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
|
||||
const TITLE = "New title";
|
||||
let promise = Promise.all([
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onItemChanged"
|
||||
]),
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onItemChanged", // This is an unfortunate effect of bug 653910.
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "property", check: v => v === "title" },
|
||||
{ name: "isAnno", check: v => v === false },
|
||||
{ name: "newValue", check: v => v === TITLE },
|
||||
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "oldValue", check: v => typeof(v) == "string" },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
])]);
|
||||
PlacesUtils.bookmarks.setItemTitle(id, TITLE);
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function* onItemChanged_tags_bookmark() {
|
||||
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
|
||||
let uri = PlacesUtils.bookmarks.getBookmarkURI(id);
|
||||
const TAG = "tag";
|
||||
let promise = Promise.all([
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onItemChanged", "onItemChanged"
|
||||
]),
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onItemAdded", // This is the tag folder.
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.tagsFolderId },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
|
||||
{ name: "uri", check: v => v === null },
|
||||
{ name: "title", check: v => v === TAG },
|
||||
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemAdded", // This is the tag.
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
|
||||
{ name: "title", check: v => v === null },
|
||||
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemChanged",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "property", check: v => v === "tags" },
|
||||
{ name: "isAnno", check: v => v === false },
|
||||
{ name: "newValue", check: v => v === "" },
|
||||
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "oldValue", check: v => typeof(v) == "string" },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemRemoved", // This is the tag.
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemRemoved", // This is the tag folder.
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.tagsFolderId },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
|
||||
{ name: "uri", check: v => v === null },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemChanged",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "property", check: v => v === "tags" },
|
||||
{ name: "isAnno", check: v => v === false },
|
||||
{ name: "newValue", check: v => v === "" },
|
||||
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "oldValue", check: v => typeof(v) == "string" },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
])]);
|
||||
PlacesUtils.tagging.tagURI(uri, [TAG]);
|
||||
PlacesUtils.tagging.untagURI(uri, [TAG]);
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function* onItemMoved_bookmark() {
|
||||
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
|
||||
let promise = Promise.all([
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onItemMoved", "onItemMoved"
|
||||
]),
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onItemMoved",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "oldParentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "oldIndex", check: v => v === 0 },
|
||||
{ name: "newParentId", check: v => v === PlacesUtils.toolbarFolderId },
|
||||
{ name: "newIndex", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "oldParentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "newParentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemMoved",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "oldParentId", check: v => v === PlacesUtils.toolbarFolderId },
|
||||
{ name: "oldIndex", check: v => v === 0 },
|
||||
{ name: "newParentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "newIndex", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "oldParentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "newParentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
])]);
|
||||
PlacesUtils.bookmarks.moveItem(id, PlacesUtils.toolbarFolderId, 0);
|
||||
PlacesUtils.bookmarks.moveItem(id, PlacesUtils.unfiledBookmarksFolderId, 0);
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function* onItemMoved_bookmark() {
|
||||
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
|
||||
let uri = PlacesUtils.bookmarks.getBookmarkURI(id);
|
||||
let promise = Promise.all([
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onItemVisited"
|
||||
]),
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onItemVisited",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "visitId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "time", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "transitionType", check: v => v === PlacesUtils.history.TRANSITION_TYPED },
|
||||
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
] },
|
||||
])]);
|
||||
PlacesTestUtils.addVisits({ uri: uri, transition: TRANSITION_TYPED });
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function* onItemRemoved_bookmark() {
|
||||
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
|
||||
let uri = PlacesUtils.bookmarks.getBookmarkURI(id);
|
||||
let promise = Promise.all([
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onItemChanged", "onItemRemoved"
|
||||
]),
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onItemChanged", // This is an unfortunate effect of bug 653910.
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "property", check: v => v === "" },
|
||||
{ name: "isAnno", check: v => v === true },
|
||||
{ name: "newValue", check: v => v === "" },
|
||||
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "oldValue", check: v => typeof(v) == "string" },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemRemoved",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
])]);
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function* onItemRemoved_separator() {
|
||||
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
|
||||
let promise = Promise.all([
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onItemChanged", "onItemRemoved"
|
||||
]),
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onItemChanged", // This is an unfortunate effect of bug 653910.
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "property", check: v => v === "" },
|
||||
{ name: "isAnno", check: v => v === true },
|
||||
{ name: "newValue", check: v => v === "" },
|
||||
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_SEPARATOR },
|
||||
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "oldValue", check: v => typeof(v) == "string" },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemRemoved",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_SEPARATOR },
|
||||
{ name: "uri", check: v => v === null },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
])]);
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function* onItemRemoved_folder() {
|
||||
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
|
||||
let promise = Promise.all([
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onItemChanged", "onItemRemoved"
|
||||
]),
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onItemChanged", // This is an unfortunate effect of bug 653910.
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "property", check: v => v === "" },
|
||||
{ name: "isAnno", check: v => v === true },
|
||||
{ name: "newValue", check: v => v === "" },
|
||||
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
|
||||
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "oldValue", check: v => typeof(v) == "string" },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemRemoved",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
|
||||
{ name: "uri", check: v => v === null },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
])]);
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function* onItemRemoved_folder_recursive() {
|
||||
const TITLE = "Folder 3";
|
||||
const BMTITLE = "Bookmark 1";
|
||||
let uri = NetUtil.newURI("http://1.mozilla.org/");
|
||||
let promise = Promise.all([
|
||||
gBookmarkSkipObserver.setup([
|
||||
"onItemAdded", "onItemAdded", "onItemAdded", "onItemAdded",
|
||||
"onItemChanged", "onItemRemoved"
|
||||
]),
|
||||
gBookmarksObserver.setup([
|
||||
{ name: "onItemAdded",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
|
||||
{ name: "uri", check: v => v === null },
|
||||
{ name: "title", check: v => v === TITLE },
|
||||
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemAdded",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0) },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
|
||||
{ name: "title", check: v => v === BMTITLE },
|
||||
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemAdded",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0) },
|
||||
{ name: "index", check: v => v === 1 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
|
||||
{ name: "uri", check: v => v === null },
|
||||
{ name: "title", check: v => v === TITLE },
|
||||
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemAdded",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => v === PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0), 1) },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
|
||||
{ name: "title", check: v => v === BMTITLE },
|
||||
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemChanged", // This is an unfortunate effect of bug 653910.
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "property", check: v => v === "" },
|
||||
{ name: "isAnno", check: v => v === true },
|
||||
{ name: "newValue", check: v => v === "" },
|
||||
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
|
||||
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "oldValue", check: v => typeof(v) == "string" },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemRemoved",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemRemoved",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "index", check: v => v === 1 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
|
||||
{ name: "uri", check: v => v === null },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemRemoved",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
|
||||
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
{ name: "onItemRemoved",
|
||||
args: [
|
||||
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
|
||||
{ name: "index", check: v => v === 0 },
|
||||
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
|
||||
{ name: "uri", check: v => v === null },
|
||||
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
|
||||
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
|
||||
] },
|
||||
])]);
|
||||
let folder = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TITLE,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.insertBookmark(folder,
|
||||
uri, PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
BMTITLE);
|
||||
let folder2 = PlacesUtils.bookmarks.createFolder(folder, TITLE,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.insertBookmark(folder2,
|
||||
uri, PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
BMTITLE);
|
||||
|
||||
PlacesUtils.bookmarks.removeItem(folder);
|
||||
yield promise;
|
||||
});
|
||||
|
||||
add_task(function cleanup()
|
||||
{
|
||||
PlacesUtils.bookmarks.removeObserver(gBookmarksObserver);
|
||||
PlacesUtils.bookmarks.removeObserver(gBookmarkSkipObserver);
|
||||
});
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test()
|
||||
{
|
||||
const ROOTS = [
|
||||
PlacesUtils.bookmarksMenuFolderId,
|
||||
PlacesUtils.toolbarFolderId,
|
||||
PlacesUtils.unfiledBookmarksFolderId,
|
||||
PlacesUtils.tagsFolderId,
|
||||
PlacesUtils.placesRootId,
|
||||
PlacesUtils.mobileFolderId,
|
||||
];
|
||||
|
||||
for (let root of ROOTS) {
|
||||
do_check_true(PlacesUtils.isRootItem(root));
|
||||
|
||||
try {
|
||||
PlacesUtils.bookmarks.removeItem(root);
|
||||
do_throw("Trying to remove a root should throw");
|
||||
} catch (ex) {}
|
||||
|
||||
try {
|
||||
PlacesUtils.bookmarks.moveItem(root, PlacesUtils.placesRootId, 0);
|
||||
do_throw("Trying to move a root should throw");
|
||||
} catch (ex) {}
|
||||
|
||||
try {
|
||||
PlacesUtils.bookmarks.removeFolderChildren(root);
|
||||
if (root == PlacesUtils.placesRootId)
|
||||
do_throw("Trying to remove children of the main root should throw");
|
||||
} catch (ex) {
|
||||
if (root != PlacesUtils.placesRootId)
|
||||
do_throw("Trying to remove children of other roots should not throw");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* This test ensures that reinserting a folder within a transaction gives it
|
||||
* a different GUID, and passes the GUID to the observers.
|
||||
*/
|
||||
|
||||
add_task(function* test_removeFolderTransaction_reinsert() {
|
||||
let folder = yield PlacesUtils.bookmarks.insert({
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
title: "Test folder",
|
||||
});
|
||||
let folderId = yield PlacesUtils.promiseItemId(folder.guid);
|
||||
let fx = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: folder.guid,
|
||||
title: "Get Firefox!",
|
||||
url: "http://getfirefox.com",
|
||||
});
|
||||
let fxId = yield PlacesUtils.promiseItemId(fx.guid);
|
||||
let tb = yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: folder.guid,
|
||||
title: "Get Thunderbird!",
|
||||
url: "http://getthunderbird.com",
|
||||
});
|
||||
let tbId = yield PlacesUtils.promiseItemId(tb.guid);
|
||||
|
||||
let notifications = [];
|
||||
function checkNotifications(expected, message) {
|
||||
deepEqual(notifications, expected, message);
|
||||
notifications.length = 0;
|
||||
}
|
||||
|
||||
let observer = {
|
||||
onItemAdded(itemId, parentId, index, type, uri, title, dateAdded, guid,
|
||||
parentGuid) {
|
||||
notifications.push(["onItemAdded", itemId, parentId, guid, parentGuid]);
|
||||
},
|
||||
onItemRemoved(itemId, parentId, index, type, uri, guid, parentGuid) {
|
||||
notifications.push(["onItemRemoved", itemId, parentId, guid, parentGuid]);
|
||||
},
|
||||
};
|
||||
PlacesUtils.bookmarks.addObserver(observer, false);
|
||||
PlacesUtils.registerShutdownFunction(function() {
|
||||
PlacesUtils.bookmarks.removeObserver(observer);
|
||||
});
|
||||
|
||||
let transaction = PlacesUtils.bookmarks.getRemoveFolderTransaction(folderId);
|
||||
deepEqual(notifications, [], "We haven't executed the transaction yet");
|
||||
|
||||
transaction.doTransaction();
|
||||
checkNotifications([
|
||||
["onItemRemoved", tbId, folderId, tb.guid, folder.guid],
|
||||
["onItemRemoved", fxId, folderId, fx.guid, folder.guid],
|
||||
["onItemRemoved", folderId, PlacesUtils.bookmarksMenuFolderId, folder.guid,
|
||||
PlacesUtils.bookmarks.menuGuid],
|
||||
], "Executing transaction should remove folder and its descendants");
|
||||
|
||||
transaction.undoTransaction();
|
||||
// At this point, the restored folder has the same ID, but a different GUID.
|
||||
let newFolderGuid = yield PlacesUtils.promiseItemGuid(folderId);
|
||||
checkNotifications([
|
||||
["onItemAdded", folderId, PlacesUtils.bookmarksMenuFolderId, newFolderGuid,
|
||||
PlacesUtils.bookmarks.menuGuid],
|
||||
], "Undo should reinsert folder with same ID and different GUID");
|
||||
|
||||
transaction.redoTransaction();
|
||||
checkNotifications([
|
||||
["onItemRemoved", folderId, PlacesUtils.bookmarksMenuFolderId,
|
||||
newFolderGuid, PlacesUtils.bookmarks.menuGuid],
|
||||
], "Redo should forward new GUID to observer");
|
||||
});
|
||||
30
toolkit/components/places/tests/bookmarks/test_removeItem.js
Normal file
30
toolkit/components/places/tests/bookmarks/test_removeItem.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var tests = [];
|
||||
|
||||
|
||||
const DEFAULT_INDEX = PlacesUtils.bookmarks.DEFAULT_INDEX;
|
||||
|
||||
function run_test() {
|
||||
// folder to hold this test
|
||||
var folderId =
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.toolbarFolderId,
|
||||
"", DEFAULT_INDEX);
|
||||
|
||||
// add a bookmark to the new folder
|
||||
var bookmarkURI = uri("http://iasdjkf");
|
||||
do_check_false(PlacesUtils.bookmarks.isBookmarked(bookmarkURI));
|
||||
var bookmarkId = PlacesUtils.bookmarks.insertBookmark(folderId, bookmarkURI,
|
||||
DEFAULT_INDEX, "");
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemTitle(bookmarkId), "");
|
||||
|
||||
// remove the folder using removeItem
|
||||
PlacesUtils.bookmarks.removeItem(folderId);
|
||||
do_check_eq(PlacesUtils.bookmarks.getBookmarkIdsForURI(bookmarkURI).length, 0);
|
||||
do_check_false(PlacesUtils.bookmarks.isBookmarked(bookmarkURI));
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemIndex(bookmarkId), -1);
|
||||
}
|
||||
209
toolkit/components/places/tests/bookmarks/test_savedsearches.js
Normal file
209
toolkit/components/places/tests/bookmarks/test_savedsearches.js
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// get bookmarks root id
|
||||
var root = PlacesUtils.bookmarksMenuFolderId;
|
||||
|
||||
// a search term that matches a default bookmark
|
||||
const searchTerm = "about";
|
||||
|
||||
var testRoot;
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
// create a folder to hold all the tests
|
||||
// this makes the tests more tolerant of changes to the default bookmarks set
|
||||
// also, name it using the search term, for testing that containers that match don't show up in query results
|
||||
testRoot = PlacesUtils.bookmarks.createFolder(
|
||||
root, searchTerm, PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_test(function test_savedsearches_bookmarks() {
|
||||
// add a bookmark that matches the search term
|
||||
var bookmarkId = PlacesUtils.bookmarks.insertBookmark(
|
||||
root, uri("http://foo.com"), PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
searchTerm);
|
||||
|
||||
// create a saved-search that matches a default bookmark
|
||||
var searchId = PlacesUtils.bookmarks.insertBookmark(
|
||||
testRoot, uri("place:terms=" + searchTerm + "&excludeQueries=1&expandQueries=1&queryType=1"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, searchTerm);
|
||||
|
||||
// query for the test root, expandQueries=0
|
||||
// the query should show up as a regular bookmark
|
||||
try {
|
||||
let options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.expandQueries = 0;
|
||||
let query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([testRoot], 1);
|
||||
let result = PlacesUtils.history.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
let cc = rootNode.childCount;
|
||||
do_check_eq(cc, 1);
|
||||
for (let i = 0; i < cc; i++) {
|
||||
let node = rootNode.getChild(i);
|
||||
// test that queries have valid itemId
|
||||
do_check_true(node.itemId > 0);
|
||||
// test that the container is closed
|
||||
node.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
do_check_eq(node.containerOpen, false);
|
||||
}
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
catch (ex) {
|
||||
do_throw("expandQueries=0 query error: " + ex);
|
||||
}
|
||||
|
||||
// bookmark saved search
|
||||
// query for the test root, expandQueries=1
|
||||
// the query should show up as a query container, with 1 child
|
||||
try {
|
||||
let options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.expandQueries = 1;
|
||||
let query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([testRoot], 1);
|
||||
let result = PlacesUtils.history.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
let cc = rootNode.childCount;
|
||||
do_check_eq(cc, 1);
|
||||
for (let i = 0; i < cc; i++) {
|
||||
let node = rootNode.getChild(i);
|
||||
// test that query node type is container when expandQueries=1
|
||||
do_check_eq(node.type, node.RESULT_TYPE_QUERY);
|
||||
// test that queries (as containers) have valid itemId
|
||||
do_check_true(node.itemId > 0);
|
||||
node.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
node.containerOpen = true;
|
||||
|
||||
// test that queries have children when excludeItems=1
|
||||
// test that query nodes don't show containers (shouldn't have our folder that matches)
|
||||
// test that queries don't show themselves in query results (shouldn't have our saved search)
|
||||
do_check_eq(node.childCount, 1);
|
||||
|
||||
// test that bookmark shows in query results
|
||||
var item = node.getChild(0);
|
||||
do_check_eq(item.itemId, bookmarkId);
|
||||
|
||||
// XXX - FAILING - test live-update of query results - add a bookmark that matches the query
|
||||
// var tmpBmId = PlacesUtils.bookmarks.insertBookmark(
|
||||
// root, uri("http://" + searchTerm + ".com"),
|
||||
// PlacesUtils.bookmarks.DEFAULT_INDEX, searchTerm + "blah");
|
||||
// do_check_eq(query.childCount, 2);
|
||||
|
||||
// XXX - test live-update of query results - delete a bookmark that matches the query
|
||||
// PlacesUtils.bookmarks.removeItem(tmpBMId);
|
||||
// do_check_eq(query.childCount, 1);
|
||||
|
||||
// test live-update of query results - add a folder that matches the query
|
||||
PlacesUtils.bookmarks.createFolder(
|
||||
root, searchTerm + "zaa", PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
do_check_eq(node.childCount, 1);
|
||||
// test live-update of query results - add a query that matches the query
|
||||
PlacesUtils.bookmarks.insertBookmark(
|
||||
root, uri("place:terms=foo&excludeQueries=1&expandQueries=1&queryType=1"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, searchTerm + "blah");
|
||||
do_check_eq(node.childCount, 1);
|
||||
}
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
catch (ex) {
|
||||
do_throw("expandQueries=1 bookmarks query: " + ex);
|
||||
}
|
||||
|
||||
// delete the bookmark search
|
||||
PlacesUtils.bookmarks.removeItem(searchId);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_task(function* test_savedsearches_history() {
|
||||
// add a visit that matches the search term
|
||||
var testURI = uri("http://" + searchTerm + ".com");
|
||||
yield PlacesTestUtils.addVisits({ uri: testURI, title: searchTerm });
|
||||
|
||||
// create a saved-search that matches the visit we added
|
||||
var searchId = PlacesUtils.bookmarks.insertBookmark(testRoot,
|
||||
uri("place:terms=" + searchTerm + "&excludeQueries=1&expandQueries=1&queryType=0"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, searchTerm);
|
||||
|
||||
// query for the test root, expandQueries=1
|
||||
// the query should show up as a query container, with 1 child
|
||||
try {
|
||||
var options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.expandQueries = 1;
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([testRoot], 1);
|
||||
var result = PlacesUtils.history.executeQuery(query, options);
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
var cc = rootNode.childCount;
|
||||
do_check_eq(cc, 1);
|
||||
for (var i = 0; i < cc; i++) {
|
||||
var node = rootNode.getChild(i);
|
||||
// test that query node type is container when expandQueries=1
|
||||
do_check_eq(node.type, node.RESULT_TYPE_QUERY);
|
||||
// test that queries (as containers) have valid itemId
|
||||
do_check_eq(node.itemId, searchId);
|
||||
node.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
node.containerOpen = true;
|
||||
|
||||
// test that queries have children when excludeItems=1
|
||||
// test that query nodes don't show containers (shouldn't have our folder that matches)
|
||||
// test that queries don't show themselves in query results (shouldn't have our saved search)
|
||||
do_check_eq(node.childCount, 1);
|
||||
|
||||
// test that history visit shows in query results
|
||||
var item = node.getChild(0);
|
||||
do_check_eq(item.type, item.RESULT_TYPE_URI);
|
||||
do_check_eq(item.itemId, -1); // history visit
|
||||
do_check_eq(item.uri, testURI.spec); // history visit
|
||||
|
||||
// test live-update of query results - add a history visit that matches the query
|
||||
yield PlacesTestUtils.addVisits({
|
||||
uri: uri("http://foo.com"),
|
||||
title: searchTerm + "blah"
|
||||
});
|
||||
do_check_eq(node.childCount, 2);
|
||||
|
||||
// test live-update of query results - delete a history visit that matches the query
|
||||
PlacesUtils.history.removePage(uri("http://foo.com"));
|
||||
do_check_eq(node.childCount, 1);
|
||||
node.containerOpen = false;
|
||||
}
|
||||
|
||||
// test live-update of moved queries
|
||||
var tmpFolderId = PlacesUtils.bookmarks.createFolder(
|
||||
testRoot, "foo", PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.moveItem(
|
||||
searchId, tmpFolderId, PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
var tmpFolderNode = rootNode.getChild(0);
|
||||
do_check_eq(tmpFolderNode.itemId, tmpFolderId);
|
||||
tmpFolderNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
tmpFolderNode.containerOpen = true;
|
||||
do_check_eq(tmpFolderNode.childCount, 1);
|
||||
|
||||
// test live-update of renamed queries
|
||||
PlacesUtils.bookmarks.setItemTitle(searchId, "foo");
|
||||
do_check_eq(tmpFolderNode.title, "foo");
|
||||
|
||||
// test live-update of deleted queries
|
||||
PlacesUtils.bookmarks.removeItem(searchId);
|
||||
try {
|
||||
tmpFolderNode = root.getChild(1);
|
||||
do_throw("query was not removed");
|
||||
} catch (ex) {}
|
||||
|
||||
tmpFolderNode.containerOpen = false;
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
catch (ex) {
|
||||
do_throw("expandQueries=1 bookmarks query: " + ex);
|
||||
}
|
||||
});
|
||||
50
toolkit/components/places/tests/bookmarks/xpcshell.ini
Normal file
50
toolkit/components/places/tests/bookmarks/xpcshell.ini
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
[DEFAULT]
|
||||
head = head_bookmarks.js
|
||||
tail =
|
||||
skip-if = toolkit == 'android'
|
||||
|
||||
[test_1016953-renaming-uncompressed.js]
|
||||
[test_1017502-bookmarks_foreign_count.js]
|
||||
[test_384228.js]
|
||||
[test_385829.js]
|
||||
[test_388695.js]
|
||||
[test_393498.js]
|
||||
[test_395101.js]
|
||||
[test_395593.js]
|
||||
[test_405938_restore_queries.js]
|
||||
[test_417228-exclude-from-backup.js]
|
||||
[test_417228-other-roots.js]
|
||||
[test_424958-json-quoted-folders.js]
|
||||
[test_448584.js]
|
||||
[test_458683.js]
|
||||
[test_466303-json-remove-backups.js]
|
||||
[test_477583_json-backup-in-future.js]
|
||||
[test_675416.js]
|
||||
[test_711914.js]
|
||||
[test_818584-discard-duplicate-backups.js]
|
||||
[test_818587_compress-bookmarks-backups.js]
|
||||
[test_818593-store-backup-metadata.js]
|
||||
[test_992901-backup-unsorted-hierarchy.js]
|
||||
[test_997030-bookmarks-html-encode.js]
|
||||
[test_1129529.js]
|
||||
[test_async_observers.js]
|
||||
[test_bmindex.js]
|
||||
[test_bookmarkstree_cache.js]
|
||||
[test_bookmarks.js]
|
||||
[test_bookmarks_eraseEverything.js]
|
||||
[test_bookmarks_fetch.js]
|
||||
[test_bookmarks_getRecent.js]
|
||||
[test_bookmarks_insert.js]
|
||||
[test_bookmarks_notifications.js]
|
||||
[test_bookmarks_remove.js]
|
||||
[test_bookmarks_reorder.js]
|
||||
[test_bookmarks_search.js]
|
||||
[test_bookmarks_update.js]
|
||||
[test_changeBookmarkURI.js]
|
||||
[test_getBookmarkedURIFor.js]
|
||||
[test_keywords.js]
|
||||
[test_nsINavBookmarkObserver.js]
|
||||
[test_protectRoots.js]
|
||||
[test_removeFolderTransaction_reinsert.js]
|
||||
[test_removeItem.js]
|
||||
[test_savedsearches.js]
|
||||
8
toolkit/components/places/tests/browser/.eslintrc.js
Normal file
8
toolkit/components/places/tests/browser/.eslintrc.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"../../../../../testing/mochitest/browser.eslintrc.js",
|
||||
"../../../../../testing/mochitest/mochitest.eslintrc.js"
|
||||
]
|
||||
};
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>history.go(0)</title>
|
||||
<script>
|
||||
setTimeout('history.go(0)', 1000);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Testing history.go(0)
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
|
||||
<meta http-equiv="refresh" content="1">
|
||||
<title>httprefresh</title>
|
||||
</head><body>
|
||||
Testing httprefresh
|
||||
</body></html>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>location.reload()</title>
|
||||
<script>
|
||||
setTimeout('location.reload();', 100);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Testing location.reload();
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>location.replace</title>
|
||||
<script>
|
||||
setTimeout('location.replace(window.location.href)', 1000);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Testing location.replace
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>window.location.href</title>
|
||||
<script>
|
||||
setTimeout('window.location.href = window.location.href', 1000);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Testing window.location.href
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>window.location</title>
|
||||
<script>
|
||||
setTimeout('window.location = window.location', 1000);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Testing window.location
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="iframe"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Link page 2</title>
|
||||
<style type="text/css">
|
||||
a:link { color: #0000ff; }
|
||||
a:visited { color: #ff0000; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p><a href="461710_visited_page.html" id="link">Link to the second visited page</a></p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Link page 3</title>
|
||||
<style type="text/css">
|
||||
a:link { color: #0000ff; }
|
||||
a:visited { color: #ff0000; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p><a href="461710_visited_page.html" id="link">Link to the third visited page</a></p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Link page</title>
|
||||
<style type="text/css">
|
||||
a:link { color: #0000ff; }
|
||||
a:visited { color: #ff0000; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p><a href="461710_visited_page.html" id="link">Link to the visited page</a></p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Visited page</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>This page is marked as visited</p>
|
||||
</body>
|
||||
</html>
|
||||
10
toolkit/components/places/tests/browser/begin.html
Normal file
10
toolkit/components/places/tests/browser/begin.html
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
|
||||
<html>
|
||||
<body>
|
||||
<a id="clickme" href="redirect_twice.sjs">Redirect twice</a>
|
||||
</body>
|
||||
</html>
|
||||
26
toolkit/components/places/tests/browser/browser.ini
Normal file
26
toolkit/components/places/tests/browser/browser.ini
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
colorAnalyzer/category-discover.png
|
||||
colorAnalyzer/dictionaryGeneric-16.png
|
||||
colorAnalyzer/extensionGeneric-16.png
|
||||
colorAnalyzer/localeGeneric.png
|
||||
head.js
|
||||
|
||||
[browser_bug248970.js]
|
||||
[browser_bug399606.js]
|
||||
[browser_bug461710.js]
|
||||
[browser_bug646422.js]
|
||||
[browser_bug680727.js]
|
||||
[browser_colorAnalyzer.js]
|
||||
[browser_double_redirect.js]
|
||||
[browser_favicon_privatebrowsing_perwindowpb.js]
|
||||
[browser_favicon_setAndFetchFaviconForPage.js]
|
||||
[browser_favicon_setAndFetchFaviconForPage_failures.js]
|
||||
[browser_history_post.js]
|
||||
[browser_notfound.js]
|
||||
[browser_redirect.js]
|
||||
[browser_settitle.js]
|
||||
[browser_visited_notfound.js]
|
||||
[browser_visituri.js]
|
||||
[browser_visituri_nohistory.js]
|
||||
[browser_visituri_privatebrowsing_perwindowpb.js]
|
||||
152
toolkit/components/places/tests/browser/browser_bug248970.js
Normal file
152
toolkit/components/places/tests/browser/browser_bug248970.js
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This test performs checks on the history testing area as outlined
|
||||
// https://wiki.mozilla.org/Firefox3.1/PrivateBrowsing/TestPlan#History
|
||||
// http://developer.mozilla.org/en/Using_the_Places_history_service
|
||||
|
||||
var visitedURIs = [
|
||||
"http://www.test-link.com/",
|
||||
"http://www.test-typed.com/",
|
||||
"http://www.test-bookmark.com/",
|
||||
"http://www.test-redirect-permanent.com/",
|
||||
"http://www.test-redirect-temporary.com/",
|
||||
"http://www.test-embed.com/",
|
||||
"http://www.test-framed.com/",
|
||||
"http://www.test-download.com/"
|
||||
].map(NetUtil.newURI.bind(NetUtil));
|
||||
|
||||
add_task(function* () {
|
||||
let windowsToClose = [];
|
||||
let placeItemsCount = 0;
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
windowsToClose.forEach(function(win) {
|
||||
win.close();
|
||||
});
|
||||
});
|
||||
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
|
||||
// Ensure we wait for the default bookmarks import.
|
||||
yield new Promise(resolve => {
|
||||
waitForCondition(() => {
|
||||
placeItemsCount = getPlacesItemsCount();
|
||||
return placeItemsCount > 0
|
||||
}, resolve, "Should have default bookmarks")
|
||||
});
|
||||
|
||||
// Create a handful of history items with various visit types
|
||||
yield PlacesTestUtils.addVisits([
|
||||
{ uri: visitedURIs[0], transition: TRANSITION_LINK },
|
||||
{ uri: visitedURIs[1], transition: TRANSITION_TYPED },
|
||||
{ uri: visitedURIs[2], transition: TRANSITION_BOOKMARK },
|
||||
{ uri: visitedURIs[3], transition: TRANSITION_REDIRECT_PERMANENT },
|
||||
{ uri: visitedURIs[4], transition: TRANSITION_REDIRECT_TEMPORARY },
|
||||
{ uri: visitedURIs[5], transition: TRANSITION_EMBED },
|
||||
{ uri: visitedURIs[6], transition: TRANSITION_FRAMED_LINK },
|
||||
{ uri: visitedURIs[7], transition: TRANSITION_DOWNLOAD }
|
||||
]);
|
||||
|
||||
placeItemsCount += 7;
|
||||
// We added 7 new items to history.
|
||||
is(getPlacesItemsCount(), placeItemsCount,
|
||||
"Check the total items count");
|
||||
|
||||
function* testOnWindow(aIsPrivate, aCount) {
|
||||
let win = yield new Promise(resolve => {
|
||||
whenNewWindowLoaded({ private: aIsPrivate }, resolve);
|
||||
});
|
||||
windowsToClose.push(win);
|
||||
|
||||
// History items should be retrievable by query
|
||||
yield checkHistoryItems();
|
||||
|
||||
// Updates the place items count
|
||||
let count = getPlacesItemsCount();
|
||||
|
||||
// Create Bookmark
|
||||
let title = "title " + windowsToClose.length;
|
||||
let keyword = "keyword " + windowsToClose.length;
|
||||
let url = "http://test-a-" + windowsToClose.length + ".com/";
|
||||
|
||||
yield PlacesUtils.bookmarks.insert({ url, title,
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid });
|
||||
yield PlacesUtils.keywords.insert({ url, keyword });
|
||||
count++;
|
||||
|
||||
ok((yield PlacesUtils.bookmarks.fetch({ url })),
|
||||
"Bookmark should be bookmarked, data should be retrievable");
|
||||
is(getPlacesItemsCount(), count,
|
||||
"Check the new bookmark items count");
|
||||
is(isBookmarkAltered(), false, "Check if bookmark has been visited");
|
||||
}
|
||||
|
||||
// Test on windows.
|
||||
yield testOnWindow(false);
|
||||
yield testOnWindow(true);
|
||||
yield testOnWindow(false);
|
||||
});
|
||||
|
||||
/**
|
||||
* Function performs a really simple query on our places entries,
|
||||
* and makes sure that the number of entries equal num_places_entries.
|
||||
*/
|
||||
function getPlacesItemsCount() {
|
||||
// Get bookmarks count
|
||||
let options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.includeHidden = true;
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
let root = PlacesUtils.history.executeQuery(
|
||||
PlacesUtils.history.getNewQuery(), options).root;
|
||||
root.containerOpen = true;
|
||||
let cc = root.childCount;
|
||||
root.containerOpen = false;
|
||||
|
||||
// Get history item count
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
|
||||
root = PlacesUtils.history.executeQuery(
|
||||
PlacesUtils.history.getNewQuery(), options).root;
|
||||
root.containerOpen = true;
|
||||
cc += root.childCount;
|
||||
root.containerOpen = false;
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
function* checkHistoryItems() {
|
||||
for (let i = 0; i < visitedURIs.length; i++) {
|
||||
let visitedUri = visitedURIs[i];
|
||||
ok((yield promiseIsURIVisited(visitedUri)), "");
|
||||
if (/embed/.test(visitedUri.spec)) {
|
||||
is((yield PlacesTestUtils.isPageInDB(visitedUri)), false, "Check if URI is in database");
|
||||
} else {
|
||||
ok((yield PlacesTestUtils.isPageInDB(visitedUri)), "Check if URI is in database");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function attempts to check if Bookmark-A has been visited
|
||||
* during private browsing mode, function should return false
|
||||
*
|
||||
* @returns false if the accessCount has not changed
|
||||
* true if the accessCount has changed
|
||||
*/
|
||||
function isBookmarkAltered() {
|
||||
let options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
options.maxResults = 1; // should only expect a new bookmark
|
||||
|
||||
let query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([PlacesUtils.bookmarks.bookmarksMenuFolder], 1);
|
||||
|
||||
let root = PlacesUtils.history.executeQuery(query, options).root;
|
||||
root.containerOpen = true;
|
||||
is(root.childCount, options.maxResults, "Check new bookmarks results");
|
||||
let node = root.getChild(0);
|
||||
root.containerOpen = false;
|
||||
|
||||
return (node.accessCount != 0);
|
||||
}
|
||||
77
toolkit/components/places/tests/browser/browser_bug399606.js
Normal file
77
toolkit/components/places/tests/browser/browser_bug399606.js
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
var URIs = [
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/399606-window.location.href.html",
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/399606-history.go-0.html",
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/399606-location.replace.html",
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/399606-location.reload.html",
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/399606-httprefresh.html",
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/399606-window.location.html",
|
||||
];
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
|
||||
// Create and add history observer.
|
||||
var historyObserver = {
|
||||
visitCount: Array(),
|
||||
onBeginUpdateBatch: function () {},
|
||||
onEndUpdateBatch: function () {},
|
||||
onVisit: function (aURI, aVisitID, aTime, aSessionID, aReferringID,
|
||||
aTransitionType) {
|
||||
info("Received onVisit: " + aURI.spec);
|
||||
if (aURI.spec in this.visitCount)
|
||||
this.visitCount[aURI.spec]++;
|
||||
else
|
||||
this.visitCount[aURI.spec] = 1;
|
||||
},
|
||||
onTitleChanged: function () {},
|
||||
onDeleteURI: function () {},
|
||||
onClearHistory: function () {},
|
||||
onPageChanged: function () {},
|
||||
onDeleteVisits: function () {},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
|
||||
};
|
||||
hs.addObserver(historyObserver, false);
|
||||
|
||||
function confirm_results() {
|
||||
gBrowser.removeCurrentTab();
|
||||
hs.removeObserver(historyObserver, false);
|
||||
for (let aURI in historyObserver.visitCount) {
|
||||
is(historyObserver.visitCount[aURI], 1,
|
||||
"onVisit has been received right number of times for " + aURI);
|
||||
}
|
||||
PlacesTestUtils.clearHistory().then(finish);
|
||||
}
|
||||
|
||||
var loadCount = 0;
|
||||
function handleLoad(aEvent) {
|
||||
loadCount++;
|
||||
info("new load count is " + loadCount);
|
||||
|
||||
if (loadCount == 3) {
|
||||
gBrowser.removeEventListener("DOMContentLoaded", handleLoad, true);
|
||||
gBrowser.loadURI("about:blank");
|
||||
executeSoon(check_next_uri);
|
||||
}
|
||||
}
|
||||
|
||||
function check_next_uri() {
|
||||
if (URIs.length) {
|
||||
let uri = URIs.shift();
|
||||
loadCount = 0;
|
||||
gBrowser.addEventListener("DOMContentLoaded", handleLoad, true);
|
||||
gBrowser.loadURI(uri);
|
||||
}
|
||||
else {
|
||||
confirm_results();
|
||||
}
|
||||
}
|
||||
executeSoon(check_next_uri);
|
||||
}
|
||||
82
toolkit/components/places/tests/browser/browser_bug461710.js
Normal file
82
toolkit/components/places/tests/browser/browser_bug461710.js
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
const kRed = "rgb(255, 0, 0)";
|
||||
const kBlue = "rgb(0, 0, 255)";
|
||||
|
||||
const prefix = "http://example.com/tests/toolkit/components/places/tests/browser/461710_";
|
||||
|
||||
add_task(function* () {
|
||||
let contentPage = prefix + "iframe.html";
|
||||
let normalWindow = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
let browser = normalWindow.gBrowser.selectedBrowser;
|
||||
BrowserTestUtils.loadURI(browser, contentPage);
|
||||
yield BrowserTestUtils.browserLoaded(browser, contentPage);
|
||||
|
||||
let privateWindow = yield BrowserTestUtils.openNewBrowserWindow({private: true});
|
||||
|
||||
browser = privateWindow.gBrowser.selectedBrowser;
|
||||
BrowserTestUtils.loadURI(browser, contentPage);
|
||||
yield BrowserTestUtils.browserLoaded(browser, contentPage);
|
||||
|
||||
let tests = [{
|
||||
win: normalWindow,
|
||||
topic: "uri-visit-saved",
|
||||
subtest: "visited_page.html"
|
||||
}, {
|
||||
win: normalWindow,
|
||||
topic: "visited-status-resolution",
|
||||
subtest: "link_page.html",
|
||||
color: kRed,
|
||||
message: "Visited link coloring should work outside of private mode"
|
||||
}, {
|
||||
win: privateWindow,
|
||||
topic: "visited-status-resolution",
|
||||
subtest: "link_page-2.html",
|
||||
color: kBlue,
|
||||
message: "Visited link coloring should not work inside of private mode"
|
||||
}, {
|
||||
win: normalWindow,
|
||||
topic: "visited-status-resolution",
|
||||
subtest: "link_page-3.html",
|
||||
color: kRed,
|
||||
message: "Visited link coloring should work outside of private mode"
|
||||
}];
|
||||
|
||||
let visited_page_url = prefix + tests[0].subtest;
|
||||
for (let test of tests) {
|
||||
let promise = new Promise(resolve => {
|
||||
let uri = NetUtil.newURI(visited_page_url);
|
||||
Services.obs.addObserver(function observe(aSubject) {
|
||||
if (uri.equals(aSubject.QueryInterface(Ci.nsIURI))) {
|
||||
Services.obs.removeObserver(observe, test.topic);
|
||||
resolve();
|
||||
}
|
||||
}, test.topic, false);
|
||||
});
|
||||
ContentTask.spawn(test.win.gBrowser.selectedBrowser, prefix + test.subtest, function* (aSrc) {
|
||||
content.document.getElementById("iframe").src = aSrc;
|
||||
});
|
||||
yield promise;
|
||||
|
||||
if (test.color) {
|
||||
// In e10s waiting for visited-status-resolution is not enough to ensure links
|
||||
// have been updated, because it only tells us that messages to update links
|
||||
// have been dispatched. We must still wait for the actual links to update.
|
||||
yield BrowserTestUtils.waitForCondition(function* () {
|
||||
let color = yield ContentTask.spawn(test.win.gBrowser.selectedBrowser, null, function* () {
|
||||
let iframe = content.document.getElementById("iframe");
|
||||
let elem = iframe.contentDocument.getElementById("link");
|
||||
return content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.getVisitedDependentComputedStyle(elem, "", "color");
|
||||
});
|
||||
return (color == test.color);
|
||||
}, test.message);
|
||||
// The harness will consider the test as failed overall if there were no
|
||||
// passes or failures, so record it as a pass.
|
||||
ok(true, test.message);
|
||||
}
|
||||
}
|
||||
|
||||
yield BrowserTestUtils.closeWindow(normalWindow);
|
||||
yield BrowserTestUtils.closeWindow(privateWindow);
|
||||
});
|
||||
51
toolkit/components/places/tests/browser/browser_bug646422.js
Normal file
51
toolkit/components/places/tests/browser/browser_bug646422.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Test for Bug 646224. Make sure that after changing the URI via
|
||||
* history.pushState, the history service has a title stored for the new URI.
|
||||
**/
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, 'http://example.com');
|
||||
|
||||
let newTitlePromise = new Promise(resolve => {
|
||||
let observer = {
|
||||
onTitleChanged: function(uri, title) {
|
||||
// If the uri of the page whose title is changing ends with 'new_page',
|
||||
// then it's the result of our pushState.
|
||||
if (/new_page$/.test(uri.spec)) {
|
||||
resolve(title);
|
||||
PlacesUtils.history.removeObserver(observer);
|
||||
}
|
||||
},
|
||||
|
||||
onBeginUpdateBatch: function() { },
|
||||
onEndUpdateBatch: function() { },
|
||||
onVisit: function() { },
|
||||
onDeleteURI: function() { },
|
||||
onClearHistory: function() { },
|
||||
onPageChanged: function() { },
|
||||
onDeleteVisits: function() { },
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
|
||||
};
|
||||
|
||||
PlacesUtils.history.addObserver(observer, false);
|
||||
});
|
||||
|
||||
yield ContentTask.spawn(tab.linkedBrowser, null, function* () {
|
||||
let title = content.document.title;
|
||||
content.history.pushState('', '', 'new_page');
|
||||
Assert.ok(title, "Content window should initially have a title.");
|
||||
});
|
||||
|
||||
let newtitle = yield newTitlePromise;
|
||||
|
||||
yield ContentTask.spawn(tab.linkedBrowser, { newtitle }, function* (args) {
|
||||
Assert.equal(args.newtitle, content.document.title, "Title after pushstate.");
|
||||
});
|
||||
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
109
toolkit/components/places/tests/browser/browser_bug680727.js
Normal file
109
toolkit/components/places/tests/browser/browser_bug680727.js
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Ensure that clicking the button in the Offline mode neterror page updates
|
||||
global history. See bug 680727. */
|
||||
/* TEST_PATH=toolkit/components/places/tests/browser/browser_bug680727.js make -C $(OBJDIR) mochitest-browser-chrome */
|
||||
|
||||
|
||||
const kUniqueURI = Services.io.newURI("http://mochi.test:8888/#bug_680727",
|
||||
null, null);
|
||||
var gAsyncHistory =
|
||||
Cc["@mozilla.org/browser/history;1"].getService(Ci.mozIAsyncHistory);
|
||||
|
||||
var proxyPrefValue;
|
||||
var ourTab;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Tests always connect to localhost, and per bug 87717, localhost is now
|
||||
// reachable in offline mode. To avoid this, disable any proxy.
|
||||
proxyPrefValue = Services.prefs.getIntPref("network.proxy.type");
|
||||
Services.prefs.setIntPref("network.proxy.type", 0);
|
||||
|
||||
// Clear network cache.
|
||||
Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Components.interfaces.nsICacheStorageService)
|
||||
.clear();
|
||||
|
||||
// Go offline, expecting the error page.
|
||||
Services.io.offline = true;
|
||||
|
||||
BrowserTestUtils.openNewForegroundTab(gBrowser).then(tab => {
|
||||
ourTab = tab;
|
||||
BrowserTestUtils.waitForContentEvent(ourTab.linkedBrowser, "DOMContentLoaded")
|
||||
.then(errorListener);
|
||||
BrowserTestUtils.loadURI(ourTab.linkedBrowser, kUniqueURI.spec);
|
||||
});
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// listen to loading the neterror page. (offline mode)
|
||||
function errorListener() {
|
||||
ok(Services.io.offline, "Services.io.offline is true.");
|
||||
|
||||
// This is an error page.
|
||||
ContentTask.spawn(ourTab.linkedBrowser, kUniqueURI.spec, function(uri) {
|
||||
Assert.equal(content.document.documentURI.substring(0, 27),
|
||||
"about:neterror?e=netOffline", "Document URI is the error page.");
|
||||
|
||||
// But location bar should show the original request.
|
||||
Assert.equal(content.location.href, uri, "Docshell URI is the original URI.");
|
||||
}).then(() => {
|
||||
// Global history does not record URI of a failed request.
|
||||
return PlacesTestUtils.promiseAsyncUpdates().then(() => {
|
||||
gAsyncHistory.isURIVisited(kUniqueURI, errorAsyncListener);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function errorAsyncListener(aURI, aIsVisited) {
|
||||
ok(kUniqueURI.equals(aURI) && !aIsVisited,
|
||||
"The neterror page is not listed in global history.");
|
||||
|
||||
Services.prefs.setIntPref("network.proxy.type", proxyPrefValue);
|
||||
|
||||
// Now press the "Try Again" button, with offline mode off.
|
||||
Services.io.offline = false;
|
||||
|
||||
BrowserTestUtils.waitForContentEvent(ourTab.linkedBrowser, "DOMContentLoaded")
|
||||
.then(reloadListener);
|
||||
|
||||
ContentTask.spawn(ourTab.linkedBrowser, null, function() {
|
||||
Assert.ok(content.document.getElementById("errorTryAgain"),
|
||||
"The error page has got a #errorTryAgain element");
|
||||
content.document.getElementById("errorTryAgain").click();
|
||||
});
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// listen to reload of neterror.
|
||||
function reloadListener() {
|
||||
// This listener catches "DOMContentLoaded" on being called
|
||||
// nsIWPL::onLocationChange(...). That is right *AFTER*
|
||||
// IHistory::VisitURI(...) is called.
|
||||
ok(!Services.io.offline, "Services.io.offline is false.");
|
||||
|
||||
ContentTask.spawn(ourTab.linkedBrowser, kUniqueURI.spec, function(uri) {
|
||||
// This is not an error page.
|
||||
Assert.equal(content.document.documentURI, uri,
|
||||
"Document URI is not the offline-error page, but the original URI.");
|
||||
}).then(() => {
|
||||
// Check if global history remembers the successfully-requested URI.
|
||||
PlacesTestUtils.promiseAsyncUpdates().then(() => {
|
||||
gAsyncHistory.isURIVisited(kUniqueURI, reloadAsyncListener);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function reloadAsyncListener(aURI, aIsVisited) {
|
||||
ok(kUniqueURI.equals(aURI) && aIsVisited, "We have visited the URI.");
|
||||
PlacesTestUtils.clearHistory().then(finish);
|
||||
}
|
||||
|
||||
registerCleanupFunction(function* () {
|
||||
Services.prefs.setIntPref("network.proxy.type", proxyPrefValue);
|
||||
Services.io.offline = false;
|
||||
yield BrowserTestUtils.removeTab(ourTab);
|
||||
});
|
||||
259
toolkit/components/places/tests/browser/browser_colorAnalyzer.js
Normal file
259
toolkit/components/places/tests/browser/browser_colorAnalyzer.js
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const CA = Cc["@mozilla.org/places/colorAnalyzer;1"].
|
||||
getService(Ci.mozIColorAnalyzer);
|
||||
|
||||
const hiddenWindowDoc = Cc["@mozilla.org/appshell/appShellService;1"].
|
||||
getService(Ci.nsIAppShellService).
|
||||
hiddenDOMWindow.document;
|
||||
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
/**
|
||||
* Passes the given uri to findRepresentativeColor.
|
||||
* If expected is null, you expect it to fail.
|
||||
* If expected is a function, it will call that function.
|
||||
* If expected is a color, you expect that color to be returned.
|
||||
* Message is used in the calls to is().
|
||||
*/
|
||||
function frcTest(uri, expected, message) {
|
||||
return new Promise(resolve => {
|
||||
CA.findRepresentativeColor(Services.io.newURI(uri, "", null),
|
||||
function(success, color) {
|
||||
if (expected == null) {
|
||||
ok(!success, message);
|
||||
} else if (typeof expected == "function") {
|
||||
expected(color, message);
|
||||
} else {
|
||||
ok(success, "success: " + message);
|
||||
is(color, expected, message);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handy function for getting an image into findRepresentativeColor and testing it.
|
||||
* Makes a canvas with the given dimensions, calls paintCanvasFunc with the 2d
|
||||
* context of the canvas, sticks the generated canvas into findRepresentativeColor.
|
||||
* See frcTest.
|
||||
*/
|
||||
function canvasTest(width, height, paintCanvasFunc, expected, message) {
|
||||
let canvas = hiddenWindowDoc.createElementNS(XHTML_NS, "canvas");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
paintCanvasFunc(canvas.getContext("2d"));
|
||||
let uri = canvas.toDataURL();
|
||||
return frcTest(uri, expected, message);
|
||||
}
|
||||
|
||||
// simple test - draw a red box in the center, make sure we get red back
|
||||
add_task(function* test_redSquare() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
ctx.fillStyle = "red";
|
||||
ctx.fillRect(2, 2, 12, 12);
|
||||
}, 0xFF0000, "redSquare analysis returns red");
|
||||
});
|
||||
|
||||
|
||||
// draw a blue square in one corner, red in the other, such that blue overlaps
|
||||
// red by one pixel, making it the dominant color
|
||||
add_task(function* test_blueOverlappingRed() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
ctx.fillStyle = "red";
|
||||
ctx.fillRect(0, 0, 8, 8);
|
||||
ctx.fillStyle = "blue";
|
||||
ctx.fillRect(7, 7, 8, 8);
|
||||
}, 0x0000FF, "blueOverlappingRed analysis returns blue");
|
||||
});
|
||||
|
||||
// draw a red gradient next to a solid blue rectangle to ensure that a large
|
||||
// block of similar colors beats out a smaller block of one color
|
||||
add_task(function* test_redGradientBlueSolid() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
let gradient = ctx.createLinearGradient(0, 0, 1, 15);
|
||||
gradient.addColorStop(0, "#FF0000");
|
||||
gradient.addColorStop(1, "#FF0808");
|
||||
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.fillRect(0, 0, 16, 16);
|
||||
ctx.fillStyle = "blue";
|
||||
ctx.fillRect(9, 0, 7, 16);
|
||||
}, function(actual, message) {
|
||||
ok(actual >= 0xFF0000 && actual <= 0xFF0808, message);
|
||||
}, "redGradientBlueSolid analysis returns redish");
|
||||
});
|
||||
|
||||
// try a transparent image, should fail
|
||||
add_task(function* test_transparent() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
// do nothing!
|
||||
}, null, "transparent analysis fails");
|
||||
});
|
||||
|
||||
add_task(function* test_invalidURI() {
|
||||
yield frcTest("data:blah,Imnotavaliddatauri", null, "invalid URI analysis fails");
|
||||
});
|
||||
|
||||
add_task(function* test_malformedPNGURI() {
|
||||
yield frcTest("data:image/png;base64,iVBORblahblahblah", null,
|
||||
"malformed PNG URI analysis fails");
|
||||
});
|
||||
|
||||
add_task(function* test_unresolvableURI() {
|
||||
yield frcTest("http://www.example.com/blah/idontexist.png", null,
|
||||
"unresolvable URI analysis fails");
|
||||
});
|
||||
|
||||
// draw a small blue box on a red background to make sure the algorithm avoids
|
||||
// using the background color
|
||||
add_task(function* test_blueOnRedBackground() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
ctx.fillStyle = "red";
|
||||
ctx.fillRect(0, 0, 16, 16);
|
||||
ctx.fillStyle = "blue";
|
||||
ctx.fillRect(4, 4, 8, 8);
|
||||
}, 0x0000FF, "blueOnRedBackground analysis returns blue");
|
||||
});
|
||||
|
||||
// draw a slightly different color in the corners to make sure the corner colors
|
||||
// don't have to be exactly equal to be considered the background color
|
||||
add_task(function* test_variableBackground() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
ctx.fillStyle = "white";
|
||||
ctx.fillRect(0, 0, 16, 16);
|
||||
ctx.fillStyle = "#FEFEFE";
|
||||
ctx.fillRect(15, 0, 1, 1);
|
||||
ctx.fillStyle = "#FDFDFD";
|
||||
ctx.fillRect(15, 15, 1, 1);
|
||||
ctx.fillStyle = "#FCFCFC";
|
||||
ctx.fillRect(0, 15, 1, 1);
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(4, 4, 8, 8);
|
||||
}, 0x000000, "variableBackground analysis returns black");
|
||||
});
|
||||
|
||||
// like the above test, but make the colors different enough that they aren't
|
||||
// considered the background color
|
||||
add_task(function* test_tooVariableBackground() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
ctx.fillStyle = "white";
|
||||
ctx.fillRect(0, 0, 16, 16);
|
||||
ctx.fillStyle = "#EEDDCC";
|
||||
ctx.fillRect(15, 0, 1, 1);
|
||||
ctx.fillStyle = "#DDDDDD";
|
||||
ctx.fillRect(15, 15, 1, 1);
|
||||
ctx.fillStyle = "#CCCCCC";
|
||||
ctx.fillRect(0, 15, 1, 1);
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(4, 4, 8, 8);
|
||||
}, function(actual, message) {
|
||||
isnot(actual, 0x000000, message);
|
||||
}, "tooVariableBackground analysis doesn't return black");
|
||||
});
|
||||
|
||||
// draw a small black/white box over transparent background to make sure the
|
||||
// algorithm doesn't think rgb(0,0,0) == rgba(0,0,0,0)
|
||||
add_task(function* test_transparentBackgroundConflation() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(2, 2, 12, 12);
|
||||
ctx.fillStyle = "white";
|
||||
ctx.fillRect(5, 5, 6, 6);
|
||||
}, 0x000000, "transparentBackgroundConflation analysis returns black");
|
||||
});
|
||||
|
||||
|
||||
// make sure we fall back to the background color if we have no other choice
|
||||
// (instead of failing as if there were no colors)
|
||||
add_task(function* test_backgroundFallback() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, 16, 16);
|
||||
}, 0x000000, "backgroundFallback analysis returns black");
|
||||
});
|
||||
|
||||
// draw red rectangle next to a pink one to make sure the algorithm picks the
|
||||
// more interesting color
|
||||
add_task(function* test_interestingColorPreference() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
ctx.fillStyle = "#FFDDDD";
|
||||
ctx.fillRect(0, 0, 16, 16);
|
||||
ctx.fillStyle = "red";
|
||||
ctx.fillRect(0, 0, 3, 16);
|
||||
}, 0xFF0000, "interestingColorPreference analysis returns red");
|
||||
});
|
||||
|
||||
// draw high saturation but dark red next to slightly less saturated color but
|
||||
// much lighter, to make sure the algorithm doesn't pick colors that are
|
||||
// nearly black just because of high saturation (in HSL terms)
|
||||
add_task(function* test_saturationDependence() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
ctx.fillStyle = "hsl(0, 100%, 5%)";
|
||||
ctx.fillRect(0, 0, 16, 16);
|
||||
ctx.fillStyle = "hsl(0, 90%, 35%)";
|
||||
ctx.fillRect(0, 0, 8, 16);
|
||||
}, 0xA90808, "saturationDependence analysis returns lighter red");
|
||||
});
|
||||
|
||||
// make sure the preference for interesting colors won't stupidly pick 1 pixel
|
||||
// of red over 169 black pixels
|
||||
add_task(function* test_interestingColorPreferenceLenient() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(1, 1, 13, 13);
|
||||
ctx.fillStyle = "red";
|
||||
ctx.fillRect(3, 3, 1, 1);
|
||||
}, 0x000000, "interestingColorPreferenceLenient analysis returns black");
|
||||
});
|
||||
|
||||
// ...but 6 pixels of red is more reasonable
|
||||
add_task(function* test_interestingColorPreferenceNotTooLenient() {
|
||||
yield canvasTest(16, 16, function(ctx) {
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(1, 1, 13, 13);
|
||||
ctx.fillStyle = "red";
|
||||
ctx.fillRect(3, 3, 3, 2);
|
||||
}, 0xFF0000, "interestingColorPreferenceNotTooLenient analysis returns red");
|
||||
});
|
||||
|
||||
var maxPixels = 144; // see ColorAnalyzer MAXIMUM_PIXELS const
|
||||
|
||||
// make sure that images larger than maxPixels*maxPixels fail
|
||||
add_task(function* test_imageTooLarge() {
|
||||
yield canvasTest(1+maxPixels, 1+maxPixels, function(ctx) {
|
||||
ctx.fillStyle = "red";
|
||||
ctx.fillRect(0, 0, 1+maxPixels, 1+maxPixels);
|
||||
}, null, "imageTooLarge analysis fails");
|
||||
});
|
||||
|
||||
// the rest of the tests are for coverage of "real" favicons
|
||||
// exact color isn't terribly important, just make sure it's reasonable
|
||||
const filePrefix = getRootDirectory(gTestPath) + "colorAnalyzer/";
|
||||
|
||||
add_task(function* test_categoryDiscover() {
|
||||
yield frcTest(filePrefix + "category-discover.png", 0xB28D3A,
|
||||
"category-discover analysis returns red");
|
||||
});
|
||||
|
||||
add_task(function* test_localeGeneric() {
|
||||
yield frcTest(filePrefix + "localeGeneric.png", 0x3EC23E,
|
||||
"localeGeneric analysis returns green");
|
||||
});
|
||||
|
||||
add_task(function* test_dictionaryGeneric() {
|
||||
yield frcTest(filePrefix + "dictionaryGeneric-16.png", 0x854C30,
|
||||
"dictionaryGeneric-16 analysis returns brown");
|
||||
});
|
||||
|
||||
add_task(function* test_extensionGeneric() {
|
||||
yield frcTest(filePrefix + "extensionGeneric-16.png", 0x53BA3F,
|
||||
"extensionGeneric-16 analysis returns green");
|
||||
});
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
// Test for bug 411966.
|
||||
// When a page redirects multiple times, from_visit should point to the
|
||||
// previous visit in the chain, not to the first visit in the chain.
|
||||
|
||||
add_task(function* () {
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
|
||||
const BASE_URL = "http://example.com/tests/toolkit/components/places/tests/browser/";
|
||||
const TEST_URI = NetUtil.newURI(BASE_URL + "begin.html");
|
||||
const FIRST_REDIRECTING_URI = NetUtil.newURI(BASE_URL + "redirect_twice.sjs");
|
||||
const FINAL_URI = NetUtil.newURI(BASE_URL + "final.html");
|
||||
|
||||
let promiseVisits = new Promise(resolve => {
|
||||
PlacesUtils.history.addObserver({
|
||||
__proto__: NavHistoryObserver.prototype,
|
||||
_notified: [],
|
||||
onVisit: function (uri, id, time, sessionId, referrerId, transition) {
|
||||
info("Received onVisit: " + uri.spec);
|
||||
this._notified.push(uri);
|
||||
|
||||
if (!uri.equals(FINAL_URI)) {
|
||||
return;
|
||||
}
|
||||
|
||||
is(this._notified.length, 4);
|
||||
PlacesUtils.history.removeObserver(this);
|
||||
|
||||
Task.spawn(function* () {
|
||||
// Get all pages visited from the original typed one
|
||||
let db = yield PlacesUtils.promiseDBConnection();
|
||||
let rows = yield db.execute(
|
||||
`SELECT url FROM moz_historyvisits
|
||||
JOIN moz_places h ON h.id = place_id
|
||||
WHERE from_visit IN
|
||||
(SELECT v.id FROM moz_historyvisits v
|
||||
JOIN moz_places p ON p.id = v.place_id
|
||||
WHERE p.url_hash = hash(:url) AND p.url = :url)
|
||||
`, { url: TEST_URI.spec });
|
||||
|
||||
is(rows.length, 1, "Found right number of visits");
|
||||
let visitedUrl = rows[0].getResultByName("url");
|
||||
// Check that redirect from_visit is not from the original typed one
|
||||
is(visitedUrl, FIRST_REDIRECTING_URI.spec, "Check referrer for " + visitedUrl);
|
||||
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
|
||||
PlacesUtils.history.markPageAsTyped(TEST_URI);
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: TEST_URI.spec,
|
||||
}, function* (browser) {
|
||||
// Load begin page, click link on page to record visits.
|
||||
yield BrowserTestUtils.synthesizeMouseAtCenter("#clickme", {}, browser);
|
||||
|
||||
yield promiseVisits;
|
||||
});
|
||||
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
});
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
const pageURI =
|
||||
"http://example.org/tests/toolkit/components/places/tests/browser/favicon.html";
|
||||
let windowsToClose = [];
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
windowsToClose.forEach(function(aWin) {
|
||||
aWin.close();
|
||||
});
|
||||
});
|
||||
|
||||
function testOnWindow(aIsPrivate, aCallback) {
|
||||
whenNewWindowLoaded({private: aIsPrivate}, function(aWin) {
|
||||
windowsToClose.push(aWin);
|
||||
executeSoon(() => aCallback(aWin));
|
||||
});
|
||||
}
|
||||
|
||||
function waitForTabLoad(aWin, aCallback) {
|
||||
aWin.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
aWin.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
aCallback();
|
||||
}, true);
|
||||
aWin.gBrowser.selectedBrowser.loadURI(pageURI);
|
||||
}
|
||||
|
||||
testOnWindow(true, function(win) {
|
||||
waitForTabLoad(win, function() {
|
||||
PlacesUtils.favicons.getFaviconURLForPage(NetUtil.newURI(pageURI),
|
||||
function(uri, dataLen, data, mimeType) {
|
||||
is(uri, null, "No result should be found");
|
||||
finish();
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This file tests the normal operation of setAndFetchFaviconForPage.
|
||||
function test() {
|
||||
// Initialization
|
||||
waitForExplicitFinish();
|
||||
let windowsToClose = [];
|
||||
let favIconLocation =
|
||||
"http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal32.png";
|
||||
let favIconURI = NetUtil.newURI(favIconLocation);
|
||||
let favIconMimeType= "image/png";
|
||||
let pageURI;
|
||||
let favIconData;
|
||||
|
||||
function testOnWindow(aOptions, aCallback) {
|
||||
whenNewWindowLoaded(aOptions, function(aWin) {
|
||||
windowsToClose.push(aWin);
|
||||
executeSoon(() => aCallback(aWin));
|
||||
});
|
||||
}
|
||||
|
||||
// This function is called after calling finish() on the test.
|
||||
registerCleanupFunction(function() {
|
||||
windowsToClose.forEach(function(aWin) {
|
||||
aWin.close();
|
||||
});
|
||||
});
|
||||
|
||||
function getIconFile(aCallback) {
|
||||
NetUtil.asyncFetch({
|
||||
uri: favIconLocation,
|
||||
loadUsingSystemPrincipal: true,
|
||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE_FAVICON
|
||||
}, function(inputStream, status) {
|
||||
if (!Components.isSuccessCode(status)) {
|
||||
ok(false, "Could not get the icon file");
|
||||
// Handle error.
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the returned size versus the expected size.
|
||||
let size = inputStream.available();
|
||||
favIconData = NetUtil.readInputStreamToString(inputStream, size);
|
||||
is(size, favIconData.length, "Check correct icon size");
|
||||
// Check that the favicon loaded correctly before starting the actual tests.
|
||||
is(favIconData.length, 344, "Check correct icon length (344)");
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testNormal(aWindow, aCallback) {
|
||||
pageURI = NetUtil.newURI("http://example.com/normal");
|
||||
waitForFaviconChanged(pageURI, favIconURI, aWindow,
|
||||
function testNormalCallback() {
|
||||
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
|
||||
aCallback);
|
||||
}
|
||||
);
|
||||
|
||||
addVisits({uri: pageURI, transition: TRANSITION_TYPED}, aWindow,
|
||||
function () {
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
|
||||
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function testAboutURIBookmarked(aWindow, aCallback) {
|
||||
pageURI = NetUtil.newURI("about:testAboutURI_bookmarked");
|
||||
waitForFaviconChanged(pageURI, favIconURI, aWindow,
|
||||
function testAboutURIBookmarkedCallback() {
|
||||
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
|
||||
aCallback);
|
||||
}
|
||||
);
|
||||
|
||||
aWindow.PlacesUtils.bookmarks.insertBookmark(
|
||||
aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
|
||||
aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
|
||||
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
}
|
||||
|
||||
function testPrivateBrowsingBookmarked(aWindow, aCallback) {
|
||||
pageURI = NetUtil.newURI("http://example.com/privateBrowsing_bookmarked");
|
||||
waitForFaviconChanged(pageURI, favIconURI, aWindow,
|
||||
function testPrivateBrowsingBookmarkedCallback() {
|
||||
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
|
||||
aCallback);
|
||||
}
|
||||
);
|
||||
|
||||
aWindow.PlacesUtils.bookmarks.insertBookmark(
|
||||
aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
|
||||
aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
|
||||
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_PRIVATE, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
}
|
||||
|
||||
function testDisabledHistoryBookmarked(aWindow, aCallback) {
|
||||
pageURI = NetUtil.newURI("http://example.com/disabledHistory_bookmarked");
|
||||
waitForFaviconChanged(pageURI, favIconURI, aWindow,
|
||||
function testDisabledHistoryBookmarkedCallback() {
|
||||
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
|
||||
aCallback);
|
||||
}
|
||||
);
|
||||
|
||||
// Disable history while changing the favicon.
|
||||
aWindow.Services.prefs.setBoolPref("places.history.enabled", false);
|
||||
|
||||
aWindow.PlacesUtils.bookmarks.insertBookmark(
|
||||
aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
|
||||
aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
|
||||
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
|
||||
// The setAndFetchFaviconForPage function calls CanAddURI synchronously, thus
|
||||
// we can set the preference back to true immediately. We don't clear the
|
||||
// preference because not all products enable Places by default.
|
||||
aWindow.Services.prefs.setBoolPref("places.history.enabled", true);
|
||||
}
|
||||
|
||||
getIconFile(function () {
|
||||
testOnWindow({}, function(aWin) {
|
||||
testNormal(aWin, function () {
|
||||
testOnWindow({}, function(aWin2) {
|
||||
testAboutURIBookmarked(aWin2, function () {
|
||||
testOnWindow({private: true}, function(aWin3) {
|
||||
testPrivateBrowsingBookmarked(aWin3, function () {
|
||||
testOnWindow({}, function(aWin4) {
|
||||
testDisabledHistoryBookmarked(aWin4, finish);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* This file tests setAndFetchFaviconForPage when it is called with invalid
|
||||
* arguments, and when no favicon is stored for the given arguments.
|
||||
*/
|
||||
function test() {
|
||||
// Initialization
|
||||
waitForExplicitFinish();
|
||||
let windowsToClose = [];
|
||||
let favIcon16Location =
|
||||
"http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal16.png";
|
||||
let favIcon32Location =
|
||||
"http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal32.png";
|
||||
let favIcon16URI = NetUtil.newURI(favIcon16Location);
|
||||
let favIcon32URI = NetUtil.newURI(favIcon32Location);
|
||||
let lastPageURI = NetUtil.newURI("http://example.com/verification");
|
||||
// This error icon must stay in sync with FAVICON_ERRORPAGE_URL in
|
||||
// nsIFaviconService.idl, aboutCertError.xhtml and netError.xhtml.
|
||||
let favIconErrorPageURI =
|
||||
NetUtil.newURI("chrome://global/skin/icons/warning-16.png");
|
||||
let favIconsResultCount = 0;
|
||||
|
||||
function testOnWindow(aOptions, aCallback) {
|
||||
whenNewWindowLoaded(aOptions, function(aWin) {
|
||||
windowsToClose.push(aWin);
|
||||
executeSoon(() => aCallback(aWin));
|
||||
});
|
||||
}
|
||||
|
||||
// This function is called after calling finish() on the test.
|
||||
registerCleanupFunction(function() {
|
||||
windowsToClose.forEach(function(aWin) {
|
||||
aWin.close();
|
||||
});
|
||||
});
|
||||
|
||||
function checkFavIconsDBCount(aCallback) {
|
||||
let stmt = DBConn().createAsyncStatement("SELECT url FROM moz_favicons");
|
||||
stmt.executeAsync({
|
||||
handleResult: function final_handleResult(aResultSet) {
|
||||
while (aResultSet.getNextRow()) {
|
||||
favIconsResultCount++;
|
||||
}
|
||||
},
|
||||
handleError: function final_handleError(aError) {
|
||||
throw ("Unexpected error (" + aError.result + "): " + aError.message);
|
||||
},
|
||||
handleCompletion: function final_handleCompletion(aReason) {
|
||||
// begin testing
|
||||
info("Previous records in moz_favicons: " + favIconsResultCount);
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
});
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
function testNullPageURI(aWindow, aCallback) {
|
||||
try {
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(null, favIcon16URI,
|
||||
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
throw ("Exception expected because aPageURI is null.");
|
||||
} catch (ex) {
|
||||
// We expected an exception.
|
||||
ok(true, "Exception expected because aPageURI is null");
|
||||
}
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
|
||||
function testNullFavIconURI(aWindow, aCallback) {
|
||||
try {
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(
|
||||
NetUtil.newURI("http://example.com/null_faviconURI"), null,
|
||||
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
|
||||
null, Services.scriptSecurityManager.getSystemPrincipal());
|
||||
throw ("Exception expected because aFaviconURI is null.");
|
||||
} catch (ex) {
|
||||
// We expected an exception.
|
||||
ok(true, "Exception expected because aFaviconURI is null.");
|
||||
}
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
|
||||
function testAboutURI(aWindow, aCallback) {
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(
|
||||
NetUtil.newURI("about:testAboutURI"), favIcon16URI,
|
||||
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
|
||||
null, Services.scriptSecurityManager.getSystemPrincipal());
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
|
||||
function testPrivateBrowsingNonBookmarkedURI(aWindow, aCallback) {
|
||||
let pageURI = NetUtil.newURI("http://example.com/privateBrowsing");
|
||||
addVisits({ uri: pageURI, transitionType: TRANSITION_TYPED }, aWindow,
|
||||
function () {
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI,
|
||||
favIcon16URI, true,
|
||||
aWindow.PlacesUtils.favicons.FAVICON_LOAD_PRIVATE, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testDisabledHistory(aWindow, aCallback) {
|
||||
let pageURI = NetUtil.newURI("http://example.com/disabledHistory");
|
||||
addVisits({ uri: pageURI, transition: TRANSITION_TYPED }, aWindow,
|
||||
function () {
|
||||
aWindow.Services.prefs.setBoolPref("places.history.enabled", false);
|
||||
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI,
|
||||
favIcon16URI, true,
|
||||
aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
|
||||
// The setAndFetchFaviconForPage function calls CanAddURI synchronously, thus
|
||||
// we can set the preference back to true immediately . We don't clear the
|
||||
// preference because not all products enable Places by default.
|
||||
aWindow.Services.prefs.setBoolPref("places.history.enabled", true);
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testErrorIcon(aWindow, aCallback) {
|
||||
let pageURI = NetUtil.newURI("http://example.com/errorIcon");
|
||||
addVisits({ uri: pageURI, transition: TRANSITION_TYPED }, aWindow,
|
||||
function () {
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI,
|
||||
favIconErrorPageURI, true,
|
||||
aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testNonExistingPage(aWindow, aCallback) {
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(
|
||||
NetUtil.newURI("http://example.com/nonexistingPage"), favIcon16URI,
|
||||
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
|
||||
function testFinalVerification(aWindow, aCallback) {
|
||||
// Only the last test should raise the onPageChanged notification,
|
||||
// executing the waitForFaviconChanged callback.
|
||||
waitForFaviconChanged(lastPageURI, favIcon32URI, aWindow,
|
||||
function final_callback() {
|
||||
// Check that only one record corresponding to the last favicon is present.
|
||||
let resultCount = 0;
|
||||
let stmt = DBConn().createAsyncStatement("SELECT url FROM moz_favicons");
|
||||
stmt.executeAsync({
|
||||
handleResult: function final_handleResult(aResultSet) {
|
||||
|
||||
// If the moz_favicons DB had been previously loaded (before our
|
||||
// test began), we should focus only in the URI we are testing and
|
||||
// skip the URIs not related to our test.
|
||||
if (favIconsResultCount > 0) {
|
||||
for (let row; (row = aResultSet.getNextRow()); ) {
|
||||
if (favIcon32URI.spec === row.getResultByIndex(0)) {
|
||||
is(favIcon32URI.spec, row.getResultByIndex(0),
|
||||
"Check equal favicons");
|
||||
resultCount++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let row; (row = aResultSet.getNextRow()); ) {
|
||||
is(favIcon32URI.spec, row.getResultByIndex(0),
|
||||
"Check equal favicons");
|
||||
resultCount++;
|
||||
}
|
||||
}
|
||||
},
|
||||
handleError: function final_handleError(aError) {
|
||||
throw ("Unexpected error (" + aError.result + "): " + aError.message);
|
||||
},
|
||||
handleCompletion: function final_handleCompletion(aReason) {
|
||||
is(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason,
|
||||
"Check reasons are equal");
|
||||
is(1, resultCount, "Check result count");
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
});
|
||||
stmt.finalize();
|
||||
});
|
||||
|
||||
// This is the only test that should cause the waitForFaviconChanged
|
||||
// callback to be invoked. In turn, the callback will invoke
|
||||
// finish() causing the tests to finish.
|
||||
addVisits({ uri: lastPageURI, transition: TRANSITION_TYPED }, aWindow,
|
||||
function () {
|
||||
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(lastPageURI,
|
||||
favIcon32URI, true,
|
||||
aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
});
|
||||
}
|
||||
|
||||
checkFavIconsDBCount(function () {
|
||||
testOnWindow({}, function(aWin) {
|
||||
testNullPageURI(aWin, function () {
|
||||
testOnWindow({}, function(aWin2) {
|
||||
testNullFavIconURI(aWin2, function() {
|
||||
testOnWindow({}, function(aWin3) {
|
||||
testAboutURI(aWin3, function() {
|
||||
testOnWindow({private: true}, function(aWin4) {
|
||||
testPrivateBrowsingNonBookmarkedURI(aWin4, function () {
|
||||
testOnWindow({}, function(aWin5) {
|
||||
testDisabledHistory(aWin5, function () {
|
||||
testOnWindow({}, function(aWin6) {
|
||||
testErrorIcon(aWin6, function() {
|
||||
testOnWindow({}, function(aWin7) {
|
||||
testNonExistingPage(aWin7, function() {
|
||||
testOnWindow({}, function(aWin8) {
|
||||
testFinalVerification(aWin8, function() {
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
const PAGE_URI = "http://example.com/tests/toolkit/components/places/tests/browser/history_post.html";
|
||||
const SJS_URI = NetUtil.newURI("http://example.com/tests/toolkit/components/places/tests/browser/history_post.sjs");
|
||||
|
||||
add_task(function* () {
|
||||
yield BrowserTestUtils.withNewTab({gBrowser, url: PAGE_URI}, Task.async(function* (aBrowser) {
|
||||
yield ContentTask.spawn(aBrowser, null, function* () {
|
||||
let doc = content.document;
|
||||
let submit = doc.getElementById("submit");
|
||||
let iframe = doc.getElementById("post_iframe");
|
||||
let p = new Promise((resolve, reject) => {
|
||||
iframe.addEventListener("load", function onLoad() {
|
||||
iframe.removeEventListener("load", onLoad);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
submit.click();
|
||||
yield p;
|
||||
});
|
||||
let visited = yield promiseIsURIVisited(SJS_URI);
|
||||
ok(!visited, "The POST page should not be added to history");
|
||||
ok(!(yield PlacesTestUtils.isPageInDB(SJS_URI.spec)), "The page should not be in the database");
|
||||
}));
|
||||
});
|
||||
46
toolkit/components/places/tests/browser/browser_notfound.js
Normal file
46
toolkit/components/places/tests/browser/browser_notfound.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
add_task(function* () {
|
||||
const TEST_URL = "http://mochi.test:8888/notFoundPage.html";
|
||||
|
||||
// Used to verify errors are not marked as typed.
|
||||
PlacesUtils.history.markPageAsTyped(NetUtil.newURI(TEST_URL));
|
||||
|
||||
// Create and add history observer.
|
||||
let visitedPromise = new Promise(resolve => {
|
||||
let historyObserver = {
|
||||
onVisit: function (aURI, aVisitID, aTime, aSessionID, aReferringID,
|
||||
aTransitionType) {
|
||||
PlacesUtils.history.removeObserver(historyObserver);
|
||||
info("Received onVisit: " + aURI.spec);
|
||||
fieldForUrl(aURI, "frecency", function (aFrecency) {
|
||||
is(aFrecency, 0, "Frecency should be 0");
|
||||
fieldForUrl(aURI, "hidden", function (aHidden) {
|
||||
is(aHidden, 0, "Page should not be hidden");
|
||||
fieldForUrl(aURI, "typed", function (aTyped) {
|
||||
is(aTyped, 0, "page should not be marked as typed");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
onBeginUpdateBatch: function () {},
|
||||
onEndUpdateBatch: function () {},
|
||||
onTitleChanged: function () {},
|
||||
onDeleteURI: function () {},
|
||||
onClearHistory: function () {},
|
||||
onPageChanged: function () {},
|
||||
onDeleteVisits: function () {},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
|
||||
};
|
||||
PlacesUtils.history.addObserver(historyObserver, false);
|
||||
});
|
||||
|
||||
let newTabPromise = BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
|
||||
yield Promise.all([visitedPromise, newTabPromise]);
|
||||
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
61
toolkit/components/places/tests/browser/browser_redirect.js
Normal file
61
toolkit/components/places/tests/browser/browser_redirect.js
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
add_task(function* () {
|
||||
const REDIRECT_URI = NetUtil.newURI("http://mochi.test:8888/tests/toolkit/components/places/tests/browser/redirect.sjs");
|
||||
const TARGET_URI = NetUtil.newURI("http://mochi.test:8888/tests/toolkit/components/places/tests/browser/redirect-target.html");
|
||||
|
||||
// Create and add history observer.
|
||||
let visitedPromise = new Promise(resolve => {
|
||||
let historyObserver = {
|
||||
_redirectNotified: false,
|
||||
onVisit: function (aURI, aVisitID, aTime, aSessionID, aReferringID,
|
||||
aTransitionType) {
|
||||
info("Received onVisit: " + aURI.spec);
|
||||
|
||||
if (aURI.equals(REDIRECT_URI)) {
|
||||
this._redirectNotified = true;
|
||||
// Wait for the target page notification.
|
||||
return;
|
||||
}
|
||||
|
||||
PlacesUtils.history.removeObserver(historyObserver);
|
||||
|
||||
ok(this._redirectNotified, "The redirect should have been notified");
|
||||
|
||||
fieldForUrl(REDIRECT_URI, "frecency", function (aFrecency) {
|
||||
ok(aFrecency != 0, "Frecency or the redirecting page should not be 0");
|
||||
|
||||
fieldForUrl(REDIRECT_URI, "hidden", function (aHidden) {
|
||||
is(aHidden, 1, "The redirecting page should be hidden");
|
||||
|
||||
fieldForUrl(TARGET_URI, "frecency", function (aFrecency2) {
|
||||
ok(aFrecency2 != 0, "Frecency of the target page should not be 0");
|
||||
|
||||
fieldForUrl(TARGET_URI, "hidden", function (aHidden2) {
|
||||
is(aHidden2, 0, "The target page should not be hidden");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
onBeginUpdateBatch: function () {},
|
||||
onEndUpdateBatch: function () {},
|
||||
onTitleChanged: function () {},
|
||||
onDeleteURI: function () {},
|
||||
onClearHistory: function () {},
|
||||
onPageChanged: function () {},
|
||||
onDeleteVisits: function () {},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
|
||||
};
|
||||
PlacesUtils.history.addObserver(historyObserver, false);
|
||||
});
|
||||
|
||||
let newTabPromise = BrowserTestUtils.openNewForegroundTab(gBrowser, REDIRECT_URI.spec);
|
||||
yield Promise.all([visitedPromise, newTabPromise]);
|
||||
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
76
toolkit/components/places/tests/browser/browser_settitle.js
Normal file
76
toolkit/components/places/tests/browser/browser_settitle.js
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
var conn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
|
||||
/**
|
||||
* Gets a single column value from either the places or historyvisits table.
|
||||
*/
|
||||
function getColumn(table, column, url)
|
||||
{
|
||||
var stmt = conn.createStatement(
|
||||
`SELECT ${column} FROM ${table} WHERE url_hash = hash(:val) AND url = :val`);
|
||||
try {
|
||||
stmt.params.val = url;
|
||||
stmt.executeStep();
|
||||
return stmt.row[column];
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
add_task(function* ()
|
||||
{
|
||||
// Make sure titles are correctly saved for a URI with the proper
|
||||
// notifications.
|
||||
|
||||
// Create and add history observer.
|
||||
let titleChangedPromise = new Promise(resolve => {
|
||||
var historyObserver = {
|
||||
data: [],
|
||||
onBeginUpdateBatch: function() {},
|
||||
onEndUpdateBatch: function() {},
|
||||
onVisit: function(aURI, aVisitID, aTime, aSessionID, aReferringID,
|
||||
aTransitionType) {
|
||||
},
|
||||
onTitleChanged: function(aURI, aPageTitle, aGUID) {
|
||||
this.data.push({ uri: aURI, title: aPageTitle, guid: aGUID });
|
||||
|
||||
// We only expect one title change.
|
||||
//
|
||||
// Although we are loading two different pages, the first page does not
|
||||
// have a title. Since the title starts out as empty and then is set
|
||||
// to empty, there is no title change notification.
|
||||
|
||||
PlacesUtils.history.removeObserver(this);
|
||||
resolve(this.data);
|
||||
},
|
||||
onDeleteURI: function() {},
|
||||
onClearHistory: function() {},
|
||||
onPageChanged: function() {},
|
||||
onDeleteVisits: function() {},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
|
||||
};
|
||||
PlacesUtils.history.addObserver(historyObserver, false);
|
||||
});
|
||||
|
||||
const url1 = "http://example.com/tests/toolkit/components/places/tests/browser/title1.html";
|
||||
yield BrowserTestUtils.openNewForegroundTab(gBrowser, url1);
|
||||
|
||||
const url2 = "http://example.com/tests/toolkit/components/places/tests/browser/title2.html";
|
||||
let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url2);
|
||||
yield loadPromise;
|
||||
|
||||
let data = yield titleChangedPromise;
|
||||
is(data[0].uri.spec, "http://example.com/tests/toolkit/components/places/tests/browser/title2.html");
|
||||
is(data[0].title, "Some title");
|
||||
is(data[0].guid, getColumn("moz_places", "guid", data[0].uri.spec));
|
||||
|
||||
data.forEach(function(item) {
|
||||
var title = getColumn("moz_places", "title", data[0].uri.spec);
|
||||
is(title, item.title);
|
||||
});
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
});
|
||||
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const TEST_URI = NetUtil.newURI("http://mochi.test:8888/notFoundPage.html");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
registerCleanupFunction(function() {
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// First add a visit to the page, this will ensure that later we skip
|
||||
// updating the frecency for a newly not-found page.
|
||||
addVisits({ uri: TEST_URI }, window, () => {
|
||||
info("Added visit");
|
||||
fieldForUrl(TEST_URI, "frecency", aFrecency => {
|
||||
ok(aFrecency > 0, "Frecency should be > 0");
|
||||
continueTest(aFrecency);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function continueTest(aOldFrecency) {
|
||||
// Used to verify errors are not marked as typed.
|
||||
PlacesUtils.history.markPageAsTyped(TEST_URI);
|
||||
gBrowser.selectedBrowser.loadURI(TEST_URI.spec);
|
||||
|
||||
// Create and add history observer.
|
||||
let historyObserver = {
|
||||
__proto__: NavHistoryObserver.prototype,
|
||||
onVisit: function (aURI, aVisitID, aTime, aSessionID, aReferringID,
|
||||
aTransitionType) {
|
||||
PlacesUtils.history.removeObserver(historyObserver);
|
||||
info("Received onVisit: " + aURI.spec);
|
||||
fieldForUrl(aURI, "frecency", function (aFrecency) {
|
||||
is(aFrecency, aOldFrecency, "Frecency should be unchanged");
|
||||
fieldForUrl(aURI, "hidden", function (aHidden) {
|
||||
is(aHidden, 0, "Page should not be hidden");
|
||||
fieldForUrl(aURI, "typed", function (aTyped) {
|
||||
is(aTyped, 0, "page should not be marked as typed");
|
||||
PlacesTestUtils.clearHistory().then(finish);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
PlacesUtils.history.addObserver(historyObserver, false);
|
||||
}
|
||||
84
toolkit/components/places/tests/browser/browser_visituri.js
Normal file
84
toolkit/components/places/tests/browser/browser_visituri.js
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* One-time observer callback.
|
||||
*/
|
||||
function promiseObserve(name, checkFn) {
|
||||
return new Promise(resolve => {
|
||||
Services.obs.addObserver(function observer(subject) {
|
||||
if (checkFn(subject)) {
|
||||
Services.obs.removeObserver(observer, name);
|
||||
resolve();
|
||||
}
|
||||
}, name, false);
|
||||
});
|
||||
}
|
||||
|
||||
var conn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
|
||||
/**
|
||||
* Gets a single column value from either the places or historyvisits table.
|
||||
*/
|
||||
function getColumn(table, column, fromColumnName, fromColumnValue) {
|
||||
let sql = `SELECT ${column}
|
||||
FROM ${table}
|
||||
WHERE ${fromColumnName} = :val
|
||||
${fromColumnName == "url" ? "AND url_hash = hash(:val)" : ""}
|
||||
LIMIT 1`;
|
||||
let stmt = conn.createStatement(sql);
|
||||
try {
|
||||
stmt.params.val = fromColumnValue;
|
||||
ok(stmt.executeStep(), "Expect to get a row");
|
||||
return stmt.row[column];
|
||||
}
|
||||
finally {
|
||||
stmt.reset();
|
||||
}
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
// Make sure places visit chains are saved correctly with a redirect
|
||||
// transitions.
|
||||
|
||||
// Part 1: observe history events that fire when a visit occurs.
|
||||
// Make sure visits appear in order, and that the visit chain is correct.
|
||||
var expectedUrls = [
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/begin.html",
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/redirect_twice.sjs",
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/redirect_once.sjs",
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/final.html"
|
||||
];
|
||||
var currentIndex = 0;
|
||||
|
||||
function checkObserver(subject) {
|
||||
var uri = subject.QueryInterface(Ci.nsIURI);
|
||||
var expected = expectedUrls[currentIndex];
|
||||
is(uri.spec, expected, "Saved URL visit " + uri.spec);
|
||||
|
||||
var placeId = getColumn("moz_places", "id", "url", uri.spec);
|
||||
var fromVisitId = getColumn("moz_historyvisits", "from_visit", "place_id", placeId);
|
||||
|
||||
if (currentIndex == 0) {
|
||||
is(fromVisitId, 0, "First visit has no from visit");
|
||||
}
|
||||
else {
|
||||
var lastVisitId = getColumn("moz_historyvisits", "place_id", "id", fromVisitId);
|
||||
var fromVisitUrl = getColumn("moz_places", "url", "id", lastVisitId);
|
||||
is(fromVisitUrl, expectedUrls[currentIndex - 1],
|
||||
"From visit was " + expectedUrls[currentIndex - 1]);
|
||||
}
|
||||
|
||||
currentIndex++;
|
||||
return (currentIndex >= expectedUrls.length);
|
||||
}
|
||||
let visitUriPromise = promiseObserve("uri-visit-saved", checkObserver);
|
||||
|
||||
const testUrl = "http://example.com/tests/toolkit/components/places/tests/browser/begin.html";
|
||||
yield BrowserTestUtils.openNewForegroundTab(gBrowser, testUrl);
|
||||
|
||||
// Load begin page, click link on page to record visits.
|
||||
yield BrowserTestUtils.synthesizeMouseAtCenter("#clickme", { }, gBrowser.selectedBrowser);
|
||||
yield visitUriPromise;
|
||||
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
const INITIAL_URL = "http://example.com/tests/toolkit/components/places/tests/browser/begin.html";
|
||||
const FINAL_URL = "http://example.com/tests/toolkit/components/places/tests/browser/final.html";
|
||||
|
||||
/**
|
||||
* One-time observer callback.
|
||||
*/
|
||||
function promiseObserve(name)
|
||||
{
|
||||
return new Promise(resolve => {
|
||||
Services.obs.addObserver(function observer(subject) {
|
||||
Services.obs.removeObserver(observer, name);
|
||||
resolve(subject);
|
||||
}, name, false);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* ()
|
||||
{
|
||||
yield new Promise(resolve => SpecialPowers.pushPrefEnv({"set": [["places.history.enabled", false]]}, resolve));
|
||||
|
||||
let visitUriPromise = promiseObserve("uri-visit-saved");
|
||||
|
||||
yield BrowserTestUtils.openNewForegroundTab(gBrowser, INITIAL_URL);
|
||||
|
||||
yield new Promise(resolve => SpecialPowers.popPrefEnv(resolve));
|
||||
|
||||
let browserLoadedPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
gBrowser.loadURI(FINAL_URL);
|
||||
yield browserLoadedPromise;
|
||||
|
||||
let subject = yield visitUriPromise;
|
||||
let uri = subject.QueryInterface(Ci.nsIURI);
|
||||
is(uri.spec, FINAL_URL, "received expected visit");
|
||||
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
waitForExplicitFinish();
|
||||
let windowsToClose = [];
|
||||
let initialURL =
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/begin.html";
|
||||
let finalURL =
|
||||
"http://example.com/tests/toolkit/components/places/tests/browser/final.html";
|
||||
let observer = null;
|
||||
let enumerator = null;
|
||||
let currentObserver = null;
|
||||
let uri = null;
|
||||
|
||||
function doTest(aIsPrivateMode, aWindow, aTestURI, aCallback) {
|
||||
observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
// The uri-visit-saved topic should only work when on normal mode.
|
||||
if (aTopic == "uri-visit-saved") {
|
||||
// Remove the observers set on per window private mode and normal
|
||||
// mode.
|
||||
enumerator = aWindow.Services.obs.enumerateObservers("uri-visit-saved");
|
||||
while (enumerator.hasMoreElements()) {
|
||||
currentObserver = enumerator.getNext();
|
||||
aWindow.Services.obs.removeObserver(currentObserver, "uri-visit-saved");
|
||||
}
|
||||
|
||||
// The expected visit should be the finalURL because private mode
|
||||
// should not register a visit with the initialURL.
|
||||
uri = aSubject.QueryInterface(Ci.nsIURI);
|
||||
is(uri.spec, finalURL, "Check received expected visit");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
aWindow.Services.obs.addObserver(observer, "uri-visit-saved", false);
|
||||
|
||||
BrowserTestUtils.browserLoaded(aWindow.gBrowser.selectedBrowser).then(aCallback);
|
||||
aWindow.gBrowser.selectedBrowser.loadURI(aTestURI);
|
||||
}
|
||||
|
||||
function testOnWindow(aOptions, aCallback) {
|
||||
whenNewWindowLoaded(aOptions, function(aWin) {
|
||||
windowsToClose.push(aWin);
|
||||
// execute should only be called when need, like when you are opening
|
||||
// web pages on the test. If calling executeSoon() is not necesary, then
|
||||
// call whenNewWindowLoaded() instead of testOnWindow() on your test.
|
||||
executeSoon(() => aCallback(aWin));
|
||||
});
|
||||
}
|
||||
|
||||
// This function is called after calling finish() on the test.
|
||||
registerCleanupFunction(function() {
|
||||
windowsToClose.forEach(function(aWin) {
|
||||
aWin.close();
|
||||
});
|
||||
});
|
||||
|
||||
// test first when on private mode
|
||||
testOnWindow({private: true}, function(aWin) {
|
||||
doTest(true, aWin, initialURL, function() {
|
||||
// then test when not on private mode
|
||||
testOnWindow({}, function(aWin2) {
|
||||
doTest(false, aWin2, finalURL, function () {
|
||||
PlacesTestUtils.clearHistory().then(finish);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 742 B |
Binary file not shown.
|
After Width: | Height: | Size: 554 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
BIN
toolkit/components/places/tests/browser/favicon-normal16.png
Normal file
BIN
toolkit/components/places/tests/browser/favicon-normal16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 286 B |
BIN
toolkit/components/places/tests/browser/favicon-normal32.png
Normal file
BIN
toolkit/components/places/tests/browser/favicon-normal32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 344 B |
13
toolkit/components/places/tests/browser/favicon.html
Normal file
13
toolkit/components/places/tests/browser/favicon.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<link rel="shortcut icon" href="http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal32.png">
|
||||
</head>
|
||||
<body>
|
||||
OK we're done!
|
||||
</body>
|
||||
</html>
|
||||
10
toolkit/components/places/tests/browser/final.html
Normal file
10
toolkit/components/places/tests/browser/final.html
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
|
||||
<html>
|
||||
<body>
|
||||
OK we're done!
|
||||
</body>
|
||||
</html>
|
||||
319
toolkit/components/places/tests/browser/head.js
Normal file
319
toolkit/components/places/tests/browser/head.js
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
|
||||
"resource://testing-common/PlacesTestUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserTestUtils",
|
||||
"resource://testing-common/BrowserTestUtils.jsm");
|
||||
|
||||
const TRANSITION_LINK = PlacesUtils.history.TRANSITION_LINK;
|
||||
const TRANSITION_TYPED = PlacesUtils.history.TRANSITION_TYPED;
|
||||
const TRANSITION_BOOKMARK = PlacesUtils.history.TRANSITION_BOOKMARK;
|
||||
const TRANSITION_REDIRECT_PERMANENT = PlacesUtils.history.TRANSITION_REDIRECT_PERMANENT;
|
||||
const TRANSITION_REDIRECT_TEMPORARY = PlacesUtils.history.TRANSITION_REDIRECT_TEMPORARY;
|
||||
const TRANSITION_EMBED = PlacesUtils.history.TRANSITION_EMBED;
|
||||
const TRANSITION_FRAMED_LINK = PlacesUtils.history.TRANSITION_FRAMED_LINK;
|
||||
const TRANSITION_DOWNLOAD = PlacesUtils.history.TRANSITION_DOWNLOAD;
|
||||
|
||||
/**
|
||||
* Returns a moz_places field value for a url.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI or spec to get field for.
|
||||
* param aCallback
|
||||
* Callback function that will get the property value.
|
||||
*/
|
||||
function fieldForUrl(aURI, aFieldName, aCallback)
|
||||
{
|
||||
let url = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
|
||||
let stmt = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||
.DBConnection.createAsyncStatement(
|
||||
`SELECT ${aFieldName} FROM moz_places WHERE url_hash = hash(:page_url) AND url = :page_url`
|
||||
);
|
||||
stmt.params.page_url = url;
|
||||
stmt.executeAsync({
|
||||
_value: -1,
|
||||
handleResult: function(aResultSet) {
|
||||
let row = aResultSet.getNextRow();
|
||||
if (!row)
|
||||
ok(false, "The page should exist in the database");
|
||||
this._value = row.getResultByName(aFieldName);
|
||||
},
|
||||
handleError: function() {},
|
||||
handleCompletion: function(aReason) {
|
||||
if (aReason != Ci.mozIStorageStatementCallback.REASON_FINISHED)
|
||||
ok(false, "The statement should properly succeed");
|
||||
aCallback(this._value);
|
||||
}
|
||||
});
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic nsINavHistoryObserver that doesn't implement anything, but provides
|
||||
* dummy methods to prevent errors about an object not having a certain method.
|
||||
*/
|
||||
function NavHistoryObserver() {}
|
||||
|
||||
NavHistoryObserver.prototype = {
|
||||
onBeginUpdateBatch: function () {},
|
||||
onEndUpdateBatch: function () {},
|
||||
onVisit: function () {},
|
||||
onTitleChanged: function () {},
|
||||
onDeleteURI: function () {},
|
||||
onClearHistory: function () {},
|
||||
onPageChanged: function () {},
|
||||
onDeleteVisits: function () {},
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsINavHistoryObserver,
|
||||
])
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits for the first OnPageChanged notification for ATTRIBUTE_FAVICON, and
|
||||
* verifies that it matches the expected page URI and associated favicon URI.
|
||||
*
|
||||
* This function also double-checks the GUID parameter of the notification.
|
||||
*
|
||||
* @param aExpectedPageURI
|
||||
* nsIURI object of the page whose favicon should change.
|
||||
* @param aExpectedFaviconURI
|
||||
* nsIURI object of the newly associated favicon.
|
||||
* @param aCallback
|
||||
* This function is called after the check finished.
|
||||
*/
|
||||
function waitForFaviconChanged(aExpectedPageURI, aExpectedFaviconURI, aWindow,
|
||||
aCallback) {
|
||||
let historyObserver = {
|
||||
__proto__: NavHistoryObserver.prototype,
|
||||
onPageChanged: function WFFC_onPageChanged(aURI, aWhat, aValue, aGUID) {
|
||||
if (aWhat != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
|
||||
return;
|
||||
}
|
||||
aWindow.PlacesUtils.history.removeObserver(this);
|
||||
|
||||
ok(aURI.equals(aExpectedPageURI),
|
||||
"Check URIs are equal for the page which favicon changed");
|
||||
is(aValue, aExpectedFaviconURI.spec,
|
||||
"Check changed favicon URI is the expected");
|
||||
checkGuidForURI(aURI, aGUID);
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
};
|
||||
aWindow.PlacesUtils.history.addObserver(historyObserver, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously adds visits to a page, invoking a callback function when done.
|
||||
*
|
||||
* @param aPlaceInfo
|
||||
* Either an nsIURI, in such a case a single LINK visit will be added.
|
||||
* Or can be an object describing the visit to add, or an array
|
||||
* of these objects:
|
||||
* { uri: nsIURI of the page,
|
||||
* transition: one of the TRANSITION_* from nsINavHistoryService,
|
||||
* [optional] title: title of the page,
|
||||
* [optional] visitDate: visit date in microseconds from the epoch
|
||||
* [optional] referrer: nsIURI of the referrer for this visit
|
||||
* }
|
||||
* @param [optional] aCallback
|
||||
* Function to be invoked on completion.
|
||||
* @param [optional] aStack
|
||||
* The stack frame used to report errors.
|
||||
*/
|
||||
function addVisits(aPlaceInfo, aWindow, aCallback, aStack) {
|
||||
let places = [];
|
||||
if (aPlaceInfo instanceof Ci.nsIURI) {
|
||||
places.push({ uri: aPlaceInfo });
|
||||
}
|
||||
else if (Array.isArray(aPlaceInfo)) {
|
||||
places = places.concat(aPlaceInfo);
|
||||
} else {
|
||||
places.push(aPlaceInfo)
|
||||
}
|
||||
|
||||
// Create mozIVisitInfo for each entry.
|
||||
let now = Date.now();
|
||||
for (let place of places) {
|
||||
if (!place.title) {
|
||||
place.title = "test visit for " + place.uri.spec;
|
||||
}
|
||||
place.visits = [{
|
||||
transitionType: place.transition === undefined ? TRANSITION_LINK
|
||||
: place.transition,
|
||||
visitDate: place.visitDate || (now++) * 1000,
|
||||
referrerURI: place.referrer
|
||||
}];
|
||||
}
|
||||
|
||||
aWindow.PlacesUtils.asyncHistory.updatePlaces(
|
||||
places,
|
||||
{
|
||||
handleError: function AAV_handleError() {
|
||||
throw ("Unexpected error in adding visit.");
|
||||
},
|
||||
handleResult: function () {},
|
||||
handleCompletion: function UP_handleCompletion() {
|
||||
if (aCallback)
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the favicon for the given page matches the provided data.
|
||||
*
|
||||
* @param aPageURI
|
||||
* nsIURI object for the page to check.
|
||||
* @param aExpectedMimeType
|
||||
* Expected MIME type of the icon, for example "image/png".
|
||||
* @param aExpectedData
|
||||
* Expected icon data, expressed as an array of byte values.
|
||||
* @param aCallback
|
||||
* This function is called after the check finished.
|
||||
*/
|
||||
function checkFaviconDataForPage(aPageURI, aExpectedMimeType, aExpectedData,
|
||||
aWindow, aCallback) {
|
||||
aWindow.PlacesUtils.favicons.getFaviconDataForPage(aPageURI,
|
||||
function (aURI, aDataLen, aData, aMimeType) {
|
||||
is(aExpectedMimeType, aMimeType, "Check expected MimeType");
|
||||
is(aExpectedData.length, aData.length,
|
||||
"Check favicon data for the given page matches the provided data");
|
||||
checkGuidForURI(aPageURI);
|
||||
aCallback();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a guid was set in moz_places for a given uri.
|
||||
*
|
||||
* @param aURI
|
||||
* The uri to check.
|
||||
* @param [optional] aGUID
|
||||
* The expected guid in the database.
|
||||
*/
|
||||
function checkGuidForURI(aURI, aGUID) {
|
||||
let guid = doGetGuidForURI(aURI);
|
||||
if (aGUID) {
|
||||
doCheckValidPlacesGuid(aGUID);
|
||||
is(guid, aGUID, "Check equal guid for URIs");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the guid for a given uri.
|
||||
*
|
||||
* @param aURI
|
||||
* The uri to check.
|
||||
* @return the associated the guid.
|
||||
*/
|
||||
function doGetGuidForURI(aURI) {
|
||||
let stmt = DBConn().createStatement(
|
||||
`SELECT guid
|
||||
FROM moz_places
|
||||
WHERE url_hash = hash(:url) AND url = :url`
|
||||
);
|
||||
stmt.params.url = aURI.spec;
|
||||
ok(stmt.executeStep(), "Check get guid for uri from moz_places");
|
||||
let guid = stmt.row.guid;
|
||||
stmt.finalize();
|
||||
doCheckValidPlacesGuid(guid);
|
||||
return guid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a given guid is valid for use in Places or not.
|
||||
*
|
||||
* @param aGuid
|
||||
* The guid to test.
|
||||
*/
|
||||
function doCheckValidPlacesGuid(aGuid) {
|
||||
ok(/^[a-zA-Z0-9\-_]{12}$/.test(aGuid), "Check guid for valid places");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the database connection. If the Places connection is invalid it will
|
||||
* try to create a new connection.
|
||||
*
|
||||
* @param [optional] aForceNewConnection
|
||||
* Forces creation of a new connection to the database. When a
|
||||
* connection is asyncClosed it cannot anymore schedule async statements,
|
||||
* though connectionReady will keep returning true (Bug 726990).
|
||||
*
|
||||
* @return The database connection or null if unable to get one.
|
||||
*/
|
||||
function DBConn(aForceNewConnection) {
|
||||
let gDBConn;
|
||||
if (!aForceNewConnection) {
|
||||
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||
.DBConnection;
|
||||
if (db.connectionReady)
|
||||
return db;
|
||||
}
|
||||
|
||||
// If the Places database connection has been closed, create a new connection.
|
||||
if (!gDBConn || aForceNewConnection) {
|
||||
let file = Services.dirsvc.get('ProfD', Ci.nsIFile);
|
||||
file.append("places.sqlite");
|
||||
let dbConn = gDBConn = Services.storage.openDatabase(file);
|
||||
|
||||
// Be sure to cleanly close this connection.
|
||||
Services.obs.addObserver(function DBCloseCallback(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(DBCloseCallback, aTopic);
|
||||
dbConn.asyncClose();
|
||||
}, "profile-before-change", false);
|
||||
}
|
||||
|
||||
return gDBConn.connectionReady ? gDBConn : null;
|
||||
}
|
||||
|
||||
function whenNewWindowLoaded(aOptions, aCallback) {
|
||||
BrowserTestUtils.waitForNewWindow().then(aCallback);
|
||||
OpenBrowserWindow(aOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously check a url is visited.
|
||||
*
|
||||
* @param aURI The URI.
|
||||
* @param aExpectedValue The expected value.
|
||||
* @return {Promise}
|
||||
* @resolves When the check has been added successfully.
|
||||
* @rejects JavaScript exception.
|
||||
*/
|
||||
function promiseIsURIVisited(aURI, aExpectedValue) {
|
||||
return new Promise(resolve => {
|
||||
PlacesUtils.asyncHistory.isURIVisited(aURI, function(unused, aIsVisited) {
|
||||
resolve(aIsVisited);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForCondition(condition, nextTest, errorMsg) {
|
||||
let tries = 0;
|
||||
let interval = setInterval(function() {
|
||||
if (tries >= 30) {
|
||||
ok(false, errorMsg);
|
||||
moveOn();
|
||||
}
|
||||
let conditionPassed;
|
||||
try {
|
||||
conditionPassed = condition();
|
||||
} catch (e) {
|
||||
ok(false, e + "\n" + e.stack);
|
||||
conditionPassed = false;
|
||||
}
|
||||
if (conditionPassed) {
|
||||
moveOn();
|
||||
}
|
||||
tries++;
|
||||
}, 200);
|
||||
function moveOn() {
|
||||
clearInterval(interval);
|
||||
nextTest();
|
||||
}
|
||||
}
|
||||
12
toolkit/components/places/tests/browser/history_post.html
Normal file
12
toolkit/components/places/tests/browser/history_post.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test post pages are not added to history</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe name="post_iframe" id="post_iframe"></iframe>
|
||||
<form method="post" action="http://example.com/tests/toolkit/components/places/tests/browser/history_post.sjs" target="post_iframe">
|
||||
<input type="submit" id="submit"/>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
6
toolkit/components/places/tests/browser/history_post.sjs
Normal file
6
toolkit/components/places/tests/browser/history_post.sjs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
function handleRequest(request, response)
|
||||
{
|
||||
response.setStatusLine("1.0", 200, "OK");
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
||||
response.write("Ciao");
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><html><body><p>Ciao!</p></body></html>
|
||||
14
toolkit/components/places/tests/browser/redirect.sjs
Normal file
14
toolkit/components/places/tests/browser/redirect.sjs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
let page = "<!DOCTYPE html><html><body><p>Redirecting...</p></body></html>";
|
||||
|
||||
response.setStatusLine(request.httpVersion, "301", "Moved Permanently");
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
response.setHeader("Content-Length", page.length + "", false);
|
||||
response.setHeader("Location", "redirect-target.html", false);
|
||||
response.write(page);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
function handleRequest(request, response) {
|
||||
response.setStatusLine("1.1", 301, "Found");
|
||||
response.setHeader("Location", "final.html", false);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
function handleRequest(request, response) {
|
||||
response.setStatusLine("1.1", 302, "Found");
|
||||
response.setHeader("Location", "redirect_once.sjs", false);
|
||||
}
|
||||
12
toolkit/components/places/tests/browser/title1.html
Normal file
12
toolkit/components/places/tests/browser/title1.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
title1.html
|
||||
</body>
|
||||
</html>
|
||||
14
toolkit/components/places/tests/browser/title2.html
Normal file
14
toolkit/components/places/tests/browser/title2.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Some title</title>
|
||||
</head>
|
||||
<body>
|
||||
title2.html
|
||||
</body>
|
||||
</html>
|
||||
|
||||
8
toolkit/components/places/tests/chrome/.eslintrc.js
Normal file
8
toolkit/components/places/tests/chrome/.eslintrc.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"../../../../../testing/mochitest/chrome.eslintrc.js",
|
||||
"../../../../../testing/mochitest/mochitest.eslintrc.js"
|
||||
]
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue