Bug 1360872 - Return empty strings for `null` bookmark titles. r=mak

MozReview-Commit-ID: Dd2sEfYvnBt

--HG--
extra : rebase_source : bea2d2589b2a09ba70a5c8e2b50ceee21acf3f0b
This commit is contained in:
Kit Cambridge 2017-06-06 14:37:22 -07:00
Родитель 4122fb100d
Коммит e80441db92
17 изменённых файлов: 153 добавлений и 96 удалений

Просмотреть файл

@ -1131,15 +1131,15 @@ this.PlacesUIUtils = {
"Tags": { title: this.getString("OrganizerQueryTags") },
"AllBookmarks": { title: this.getString("OrganizerQueryAllBookmarks") },
"BookmarksToolbar":
{ title: null,
{ title: "",
concreteTitle: PlacesUtils.getString("BookmarksToolbarFolderTitle"),
concreteId: PlacesUtils.toolbarFolderId },
"BookmarksMenu":
{ title: null,
{ title: "",
concreteTitle: PlacesUtils.getString("BookmarksMenuFolderTitle"),
concreteId: PlacesUtils.bookmarksMenuFolderId },
"UnfiledBookmarks":
{ title: null,
{ title: "",
concreteTitle: PlacesUtils.getString("OtherBookmarksFolderTitle"),
concreteId: PlacesUtils.unfiledBookmarksFolderId },
};

Просмотреть файл

@ -34,7 +34,7 @@ add_task(async function() {
"Root title is correct");
// Check the shortcut's title.
let bookmark = await PlacesUtils.bookmarks.fetch(tree.selectedNode.bookmarkGuid);
is(bookmark.title, null,
is(bookmark.title, "",
"Shortcut title is null");
}
);

Просмотреть файл

@ -103,7 +103,7 @@ add_test(function test_bookmark_create() {
do_check_eq(PlacesUtils.bookmarks.getItemType(id),
PlacesUtils.bookmarks.TYPE_BOOKMARK);
do_check_true(PlacesUtils.bookmarks.getBookmarkURI(id).equals(tburi));
do_check_eq(PlacesUtils.bookmarks.getItemTitle(id), null);
do_check_eq(PlacesUtils.bookmarks.getItemTitle(id), "");
let error;
try {
PlacesUtils.annotations.getItemAnnotation(id, "bookmarkProperties/description");
@ -147,7 +147,7 @@ add_test(function test_bookmark_update() {
PlacesUtils.annotations.getItemAnnotation(
bmk1_id, "bookmarkProperties/description");
}, Cr.NS_ERROR_NOT_AVAILABLE);
do_check_eq(PlacesUtils.bookmarks.getItemTitle(bmk1_id), null);
do_check_eq(PlacesUtils.bookmarks.getItemTitle(bmk1_id), "");
do_check_eq(PlacesUtils.bookmarks.getKeywordForBookmark(bmk1_id), null);
} finally {
_("Clean up.");

Просмотреть файл

@ -35,8 +35,7 @@
*
* - title (string)
* The item's title, if any. Empty titles and null titles are considered
* the same, and the property is unset on retrieval in such a case.
* Titles longer than DB_TITLE_LENGTH_MAX will be truncated.
* the same. Titles longer than DB_TITLE_LENGTH_MAX will be truncated.
*
* The following properties are only valid for URLs:
*
@ -191,7 +190,8 @@ var Bookmarks = Object.freeze({
url: { requiredIf: b => b.type == this.TYPE_BOOKMARK,
validIf: b => b.type == this.TYPE_BOOKMARK },
parentGuid: { required: true },
title: { validIf: b => [ this.TYPE_BOOKMARK,
title: { defaultValue: "",
validIf: b => [ this.TYPE_BOOKMARK,
this.TYPE_FOLDER ].includes(b.type) },
dateAdded: { defaultValue: addedTime },
lastModified: { defaultValue: modTime,
@ -224,7 +224,7 @@ var Bookmarks = Object.freeze({
let isTagging = parent._parentId == PlacesUtils.tagsFolderId;
let isTagsFolder = parent._id == PlacesUtils.tagsFolderId;
notify(observers, "onItemAdded", [ itemId, parent._id, item.index,
item.type, uri, item.title || null,
item.type, uri, item.title,
PlacesUtils.toPRTime(item.dateAdded), item.guid,
item.parentGuid, item.source ],
{ isTagging: isTagging || isTagsFolder });
@ -351,7 +351,8 @@ var Bookmarks = Object.freeze({
url: { requiredIf: b => b.type == TYPE_BOOKMARK,
validIf: b => b.type == TYPE_BOOKMARK },
parentGuid: { required: true },
title: { validIf: b => [ TYPE_BOOKMARK,
title: { defaultValue: "",
validIf: b => [ TYPE_BOOKMARK,
TYPE_FOLDER ].includes(b.type) },
dateAdded: { defaultValue: time,
validIf: b => !b.lastModified ||
@ -469,8 +470,8 @@ var Bookmarks = Object.freeze({
parentId = itemIdMap.get(item.parentGuid);
}
notify(observers, "onItemAdded", [ itemId, parentId, item.index,
item.type, uri, item.title || null,
notify(observers, "onItemAdded", [ itemId, parent._id, item.index,
item.type, uri, item.title,
PlacesUtils.toPRTime(item.dateAdded), item.guid,
item.parentGuid, item.source ],
{ isTagging: false });
@ -1154,7 +1155,8 @@ function updateBookmark(info, item, newParent) {
let tuples = new Map();
tuples.set("lastModified", { value: PlacesUtils.toPRTime(info.lastModified) });
if (info.hasOwnProperty("title"))
tuples.set("title", { value: info.title });
tuples.set("title", { value: info.title,
fragment: `title = NULLIF(:title, "")` });
if (info.hasOwnProperty("dateAdded"))
tuples.set("dateAdded", { value: PlacesUtils.toPRTime(info.dateAdded) });
@ -1294,10 +1296,6 @@ function updateBookmark(info, item, newParent) {
let updatedItem = mergeIntoNewObject(item, info, additionalParentInfo);
// Don't return an empty title to the caller.
if (updatedItem.hasOwnProperty("title") && updatedItem.title === null)
delete updatedItem.title;
return updatedItem;
});
}
@ -1341,8 +1339,8 @@ function insertBookmark(item, parent) {
dateAdded, lastModified, guid,
syncChangeCounter, syncStatus)
VALUES (CASE WHEN :url ISNULL THEN NULL ELSE (SELECT id FROM moz_places WHERE url_hash = hash(:url) AND url = :url) END,
:type, :parent, :index, :title, :date_added, :last_modified,
:guid, :syncChangeCounter, :syncStatus)
:type, :parent, :index, NULLIF(:title, ""), :date_added,
:last_modified, :guid, :syncChangeCounter, :syncStatus)
`, { url: item.hasOwnProperty("url") ? item.url.href : null,
type: item.type, parent: parent._id, index: item.index,
title: item.title, date_added: PlacesUtils.toPRTime(item.dateAdded),
@ -1376,10 +1374,6 @@ function insertBookmark(item, parent) {
updateFrecency(db, [item.url]).catch(Cu.reportError);
}
// Don't return an empty title to the caller.
if (item.hasOwnProperty("title") && item.title === null)
delete item.title;
return item;
});
}
@ -1420,7 +1414,7 @@ function insertBookmarkTree(items, source, parent, urls, lastAddedForParent) {
VALUES (CASE WHEN :url ISNULL THEN NULL ELSE (SELECT id FROM moz_places WHERE url_hash = hash(:url) AND url = :url) END, :type,
(SELECT id FROM moz_bookmarks WHERE guid = :parentGuid),
IFNULL(:index, (SELECT count(*) FROM moz_bookmarks WHERE parent = :rootId)),
:title, :date_added, :last_modified, :guid,
NULLIF(:title, ""), :date_added, :last_modified, :guid,
:syncChangeCounter, :syncStatus)`, items);
await setAncestorsLastModified(db, parent.guid, lastAddedForParent,
@ -1566,8 +1560,8 @@ async function queryBookmarks(info) {
// hence setting them to NULL
let rows = await db.executeCached(
`SELECT b.guid, IFNULL(p.guid, "") AS parentGuid, b.position AS 'index',
b.dateAdded, b.lastModified, b.type, b.title,
h.url AS url, b.parent, p.parent,
b.dateAdded, b.lastModified, b.type,
IFNULL(b.title, "") AS title, h.url AS url, b.parent, p.parent,
NULL AS _id,
NULL AS _childCount,
NULL AS _grandParentId,
@ -1591,8 +1585,8 @@ async function fetchBookmark(info, concurrent) {
let query = async function(db) {
let rows = await db.executeCached(
`SELECT b.guid, IFNULL(p.guid, "") AS parentGuid, b.position AS 'index',
b.dateAdded, b.lastModified, b.type, b.title, h.url AS url,
b.id AS _id, b.parent AS _parentId,
b.dateAdded, b.lastModified, b.type, IFNULL(b.title, "") AS title,
h.url AS url, b.id AS _id, b.parent AS _parentId,
(SELECT count(*) FROM moz_bookmarks WHERE parent = b.id) AS _childCount,
p.parent AS _grandParentId, b.syncStatus AS _syncStatus
FROM moz_bookmarks b
@ -1616,8 +1610,8 @@ async function fetchBookmarkByPosition(info, concurrent) {
let index = info.index == Bookmarks.DEFAULT_INDEX ? null : info.index;
let rows = await db.executeCached(
`SELECT b.guid, IFNULL(p.guid, "") AS parentGuid, b.position AS 'index',
b.dateAdded, b.lastModified, b.type, b.title, h.url AS url,
b.id AS _id, b.parent AS _parentId,
b.dateAdded, b.lastModified, b.type, IFNULL(b.title, "") AS title,
h.url AS url, b.id AS _id, b.parent AS _parentId,
(SELECT count(*) FROM moz_bookmarks WHERE parent = b.id) AS _childCount,
p.parent AS _grandParentId, b.syncStatus AS _syncStatus
FROM moz_bookmarks b
@ -1645,8 +1639,8 @@ async function fetchBookmarksByURL(info, concurrent) {
let rows = await db.executeCached(
`/* do not warn (bug no): not worth to add an index */
SELECT b.guid, IFNULL(p.guid, "") AS parentGuid, b.position AS 'index',
b.dateAdded, b.lastModified, b.type, b.title, h.url AS url,
b.id AS _id, b.parent AS _parentId,
b.dateAdded, b.lastModified, b.type, IFNULL(b.title, "") AS title,
h.url AS url, b.id AS _id, b.parent AS _parentId,
NULL AS _childCount, /* Unused for now */
p.parent AS _grandParentId, b.syncStatus AS _syncStatus
FROM moz_bookmarks b
@ -1674,8 +1668,9 @@ function fetchRecentBookmarks(numberOfItems) {
let tagsFolderId = await promiseTagsFolderId();
let rows = await db.executeCached(
`SELECT b.guid, IFNULL(p.guid, "") AS parentGuid, b.position AS 'index',
b.dateAdded, b.lastModified, b.type, b.title, h.url AS url,
NULL AS _id, NULL AS _parentId, NULL AS _childCount, NULL AS _grandParentId,
b.dateAdded, b.lastModified, b.type,
IFNULL(b.title, "") AS title, h.url AS url, NULL AS _id,
NULL AS _parentId, NULL AS _childCount, NULL AS _grandParentId,
NULL AS _syncStatus
FROM moz_bookmarks b
JOIN moz_bookmarks p ON p.id = b.parent
@ -1703,8 +1698,8 @@ function fetchBookmarksByParent(info) {
let rows = await db.executeCached(
`SELECT b.guid, IFNULL(p.guid, "") AS parentGuid, b.position AS 'index',
b.dateAdded, b.lastModified, b.type, b.title, h.url AS url,
b.id AS _id, b.parent AS _parentId,
b.dateAdded, b.lastModified, b.type, IFNULL(b.title, "") AS title,
h.url AS url, b.id AS _id, b.parent AS _parentId,
(SELECT count(*) FROM moz_bookmarks WHERE parent = b.id) AS _childCount,
p.parent AS _grandParentId, b.syncStatus AS _syncStatus
FROM moz_bookmarks b
@ -1988,17 +1983,21 @@ function removeSameValueProperties(dest, src) {
function rowsToItemsArray(rows) {
return rows.map(row => {
let item = {};
for (let prop of ["guid", "index", "type"]) {
for (let prop of ["guid", "index", "type", "title"]) {
item[prop] = row.getResultByName(prop);
}
for (let prop of ["dateAdded", "lastModified"]) {
item[prop] = PlacesUtils.toDate(row.getResultByName(prop));
}
for (let prop of ["title", "parentGuid", "url" ]) {
let val = row.getResultByName(prop);
if (val)
item[prop] = prop === "url" ? new URL(val) : val;
let parentGuid = row.getResultByName("parentGuid");
if (parentGuid) {
item.parentGuid = parentGuid;
}
let url = row.getResultByName("url");
if (url) {
item.url = new URL(url);
}
for (let prop of ["_id", "_parentId", "_childCount", "_grandParentId",
"_syncStatus"]) {
let val = row.getResultByName(prop);
@ -2166,8 +2165,9 @@ async function(db, folderGuids, options) {
)
SELECT b.id AS _id, b.parent AS _parentId, b.position AS 'index',
b.type, url, b.guid, p.guid AS parentGuid, b.dateAdded,
b.lastModified, b.title, p.parent AS _grandParentId,
NULL AS _childCount, b.syncStatus AS _syncStatus
b.lastModified, IFNULL(b.title, "") AS title,
p.parent AS _grandParentId, NULL AS _childCount,
b.syncStatus AS _syncStatus
FROM descendants
JOIN moz_bookmarks b ON did = b.id
JOIN moz_bookmarks p ON p.id = b.parent

Просмотреть файл

@ -292,6 +292,9 @@ IsValidGUID(const nsACString& aGUID)
void
TruncateTitle(const nsACString& aTitle, nsACString& aTrimmed)
{
if (aTitle.IsVoid()) {
return;
}
aTrimmed = aTitle;
if (aTitle.Length() > TITLE_LENGTH_MAX) {
aTrimmed = StringHead(aTitle, TITLE_LENGTH_MAX);

Просмотреть файл

@ -230,10 +230,13 @@ const BOOKMARK_VALIDATORS = Object.freeze({
PlacesUtils.bookmarks.TYPE_FOLDER,
PlacesUtils.bookmarks.TYPE_SEPARATOR ].includes(v)),
title: v => {
simpleValidateFunc(val => val === null || typeof(val) == "string").call(this, v);
if (!v)
return null;
return v.slice(0, DB_TITLE_LENGTH_MAX);
if (v === null) {
return "";
}
if (typeof(v) == "string") {
return v.slice(0, DB_TITLE_LENGTH_MAX);
}
throw new Error("Invalid title");
},
url: v => {
simpleValidateFunc(val => (typeof(val) == "string" && val.length <= DB_URL_LENGTH_MAX) ||
@ -1947,8 +1950,8 @@ this.PlacesUtils = {
FROM moz_bookmarks b2
JOIN descendants ON b2.parent = descendants.id AND b2.id <> :tags_folder)
SELECT d.level, d.id, d.guid, d.parent, d.parentGuid, d.type,
d.position AS [index], d.title, d.dateAdded, d.lastModified,
h.url, (SELECT icon_url FROM moz_icons i
d.position AS [index], IFNULL(d.title, "") AS title, d.dateAdded,
d.lastModified, h.url, (SELECT icon_url FROM moz_icons i
JOIN moz_icons_to_pages ON icon_id = i.id
JOIN moz_pages_w_icons pi ON page_id = pi.id
WHERE pi.page_url_hash = hash(h.url) AND pi.page_url = h.url

Просмотреть файл

@ -471,8 +471,7 @@ nsNavBookmarks::InsertBookmarkInDB(int64_t aPlaceId,
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("item_index"), aIndex);
NS_ENSURE_SUCCESS(rv, rv);
// Support NULL titles.
if (aTitle.IsVoid())
if (aTitle.IsEmpty())
rv = stmt->BindNullByName(NS_LITERAL_CSTRING("item_title"));
else
rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("item_title"), aTitle);
@ -555,10 +554,7 @@ nsNavBookmarks::InsertBookmarkInDB(int64_t aPlaceId,
BookmarkData bookmark;
bookmark.id = *_itemId;
bookmark.guid.Assign(_guid);
if (aTitle.IsVoid()) {
bookmark.title.SetIsVoid(true);
}
else {
if (!aTitle.IsEmpty()) {
bookmark.title.Assign(aTitle);
}
bookmark.position = aIndex;
@ -937,10 +933,9 @@ nsNavBookmarks::InsertSeparator(int64_t aParent,
}
*aNewItemId = -1;
// Set a NULL title rather than an empty string.
nsAutoCString guid(aGUID);
PRTime dateAdded = RoundedPRNow();
rv = InsertBookmarkInDB(-1, SEPARATOR, aParent, index, NullCString(), dateAdded,
rv = InsertBookmarkInDB(-1, SEPARATOR, aParent, index, EmptyCString(), dateAdded,
0, folderGuid, grandParentId, nullptr, aSource,
aNewItemId, guid);
NS_ENSURE_SUCCESS(rv, rv);
@ -951,7 +946,7 @@ nsNavBookmarks::InsertSeparator(int64_t aParent,
NOTIFY_BOOKMARKS_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
DontSkip,
OnItemAdded(*aNewItemId, aParent, index, TYPE_SEPARATOR,
nullptr, NullCString(), dateAdded, guid,
nullptr, EmptyCString(), dateAdded, guid,
folderGuid, aSource));
return NS_OK;
@ -1532,13 +1527,11 @@ nsNavBookmarks::FetchItemInfo(int64_t aItemId,
_bookmark.id = aItemId;
rv = stmt->GetUTF8String(1, _bookmark.url);
NS_ENSURE_SUCCESS(rv, rv);
bool isNull;
rv = stmt->GetIsNull(2, &isNull);
NS_ENSURE_SUCCESS(rv, rv);
if (isNull) {
_bookmark.title.SetIsVoid(true);
}
else {
if (!isNull) {
rv = stmt->GetUTF8String(2, _bookmark.title);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -1981,7 +1974,7 @@ nsNavBookmarks::SetItemTitle(int64_t aItemId, const nsACString& aTitle,
// transaction for non-tags.
mozStorageTransaction transaction(mDB->MainConn(), false);
rv = SetItemTitleInternal(bookmark, aTitle, syncChangeDelta);
rv = SetItemTitleInternal(bookmark, title, syncChangeDelta);
NS_ENSURE_SUCCESS(rv, rv);
rv = AddSyncChangesForBookmarksInFolder(bookmark.id, syncChangeDelta);
@ -2025,9 +2018,8 @@ nsNavBookmarks::SetItemTitleInternal(BookmarkData& aBookmark,
NS_ENSURE_STATE(statement);
mozStorageStatementScoper scoper(statement);
// Support setting a null title, we support this in insertBookmark.
nsresult rv;
if (aTitle.IsVoid()) {
if (aTitle.IsEmpty()) {
rv = statement->BindNullByName(NS_LITERAL_CSTRING("item_title"));
}
else {

Просмотреть файл

@ -3789,8 +3789,13 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow,
// title
nsAutoCString title;
rv = aRow->GetUTF8String(kGetInfoIndex_Title, title);
bool isNull;
rv = aRow->GetIsNull(kGetInfoIndex_Title, &isNull);
NS_ENSURE_SUCCESS(rv, rv);
if (!isNull) {
rv = aRow->GetUTF8String(kGetInfoIndex_Title, title);
NS_ENSURE_SUCCESS(rv, rv);
}
uint32_t accessCount = aRow->AsInt32(kGetInfoIndex_VisitCount);
PRTime time = aRow->AsInt64(kGetInfoIndex_VisitDate);
@ -3965,9 +3970,9 @@ nsNavHistory::QueryRowToResult(int64_t itemId,
resultNode->mBookmarkGuid = aBookmarkGuid;
resultNode->GetAsFolder()->mTargetFolderGuid = targetFolderGuid;
// Use the query item title, unless it's void (in that case use the
// Use the query item title, unless it's empty (in that case use the
// concrete folder title).
if (!aTitle.IsVoid()) {
if (!aTitle.IsEmpty()) {
resultNode->mTitle = aTitle;
}
}

Просмотреть файл

@ -122,7 +122,7 @@ add_task(async function fetch_bookmar_empty_title() {
Assert.deepEqual(bm1, bm2);
Assert.equal(bm2.index, 0);
Assert.ok(!("title" in bm2));
Assert.strictEqual(bm2.title, "");
await PlacesUtils.bookmarks.remove(bm1.guid);
});
@ -158,7 +158,7 @@ add_task(async function fetch_folder_empty_title() {
Assert.deepEqual(bm1, bm2);
Assert.equal(bm2.index, 0);
Assert.ok(!("title" in bm2));
Assert.strictEqual(bm2.title, "");
await PlacesUtils.bookmarks.remove(bm1.guid);
});
@ -177,7 +177,7 @@ add_task(async function fetch_separator() {
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_SEPARATOR);
Assert.ok(!("url" in bm2));
Assert.ok(!("title" in bm2));
Assert.strictEqual(bm2.title, "");
await PlacesUtils.bookmarks.remove(bm1.guid);
});

Просмотреть файл

@ -117,7 +117,7 @@ add_task(async function create_separator() {
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");
Assert.strictEqual(bm.title, "");
});
add_task(async function create_separator_w_title_fail() {
@ -149,7 +149,7 @@ add_task(async function create_separator_given_guid() {
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");
Assert.strictEqual(bm.title, "");
});
add_task(async function create_item_given_guid_no_type_fail() {
@ -168,7 +168,7 @@ add_task(async function create_separator_big_index() {
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");
Assert.strictEqual(bm.title, "");
});
add_task(async function create_separator_given_dateAdded() {
@ -189,7 +189,7 @@ add_task(async function create_folder() {
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");
Assert.strictEqual(bm.title, "");
// And then create a nested folder.
let parentGuid = bm.guid;
@ -231,7 +231,7 @@ add_task(async function create_bookmark() {
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");
Assert.strictEqual(bm.title, "");
});
add_task(async function create_bookmark_frecency() {

Просмотреть файл

@ -129,7 +129,7 @@ add_task(async function create_separator() {
Assert.equal(bm.index, 0);
Assert.equal(bm.dateAdded, bm.lastModified);
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_SEPARATOR);
Assert.ok(!("title" in bm), "title should not be set");
Assert.strictEqual(bm.title, "");
});
add_task(async function create_plain_bm() {

Просмотреть файл

@ -9,7 +9,7 @@ add_task(async function insert_separator_notification() {
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
observer.check([ { name: "onItemAdded",
arguments: [ itemId, parentId, bm.index, bm.type,
null, null, bm.dateAdded * 1000,
null, "", bm.dateAdded * 1000,
bm.guid, bm.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
]);
@ -34,11 +34,12 @@ add_task(async function insert_folder_notitle_notification() {
let observer = expectNotifications();
let bm = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
strictEqual(bm.title, "", "Should return empty string for untitled folder");
let itemId = await PlacesUtils.promiseItemId(bm.guid);
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
observer.check([ { name: "onItemAdded",
arguments: [ itemId, parentId, bm.index, bm.type,
null, null, bm.dateAdded * 1000,
null, "", bm.dateAdded * 1000,
bm.guid, bm.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
]);
@ -65,11 +66,12 @@ add_task(async function insert_bookmark_notitle_notification() {
let bm = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: new URL("http://example.com/") });
strictEqual(bm.title, "", "Should return empty string for untitled bookmark");
let itemId = await PlacesUtils.promiseItemId(bm.guid);
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
observer.check([ { name: "onItemAdded",
arguments: [ itemId, parentId, bm.index, bm.type,
bm.url, null, bm.dateAdded * 1000,
bm.url, "", bm.dateAdded * 1000,
bm.guid, bm.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
]);
@ -94,7 +96,7 @@ add_task(async function insert_bookmark_tag_notification() {
observer.check([ { name: "onItemAdded",
arguments: [ tagId, tagParentId, tag.index, tag.type,
tag.url, null, tag.dateAdded * 1000,
tag.url, "", tag.dateAdded * 1000,
tag.guid, tag.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
{ name: "onItemChanged",
@ -490,6 +492,54 @@ add_task(async function reorder_notification() {
observer.check(expectedNotifications);
});
add_task(async function update_notitle_notification() {
let toolbarBmURI = Services.io.newURI("https://example.com");
let toolbarBmId =
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId,
toolbarBmURI, 0, "Bookmark");
let toolbarBmGuid = await PlacesUtils.promiseItemGuid(toolbarBmId);
let menuFolder = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.menuGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 0,
title: "Folder"
});
let menuFolderId = await PlacesUtils.promiseItemId(menuFolder.guid);
let observer = expectNotifications();
PlacesUtils.bookmarks.setItemTitle(toolbarBmId, null);
strictEqual(PlacesUtils.bookmarks.getItemTitle(toolbarBmId), "",
"Legacy API should return empty string for untitled bookmark");
let updatedMenuBm = await PlacesUtils.bookmarks.update({
guid: menuFolder.guid,
title: null,
});
strictEqual(updatedMenuBm.title, "",
"Async API should return empty string for untitled bookmark");
let toolbarBmModified =
PlacesUtils.toDate(PlacesUtils.bookmarks.getItemLastModified(toolbarBmId));
observer.check([{
name: "onItemChanged",
arguments: [toolbarBmId, "title", false, "", toolbarBmModified * 1000,
PlacesUtils.bookmarks.TYPE_BOOKMARK,
PlacesUtils.toolbarFolderId, toolbarBmGuid,
PlacesUtils.bookmarks.toolbarGuid,
"", PlacesUtils.bookmarks.SOURCES.DEFAULT],
}, {
name: "onItemChanged",
arguments: [menuFolderId, "title", false, "",
updatedMenuBm.lastModified * 1000,
PlacesUtils.bookmarks.TYPE_FOLDER,
PlacesUtils.bookmarksMenuFolderId, menuFolder.guid,
PlacesUtils.bookmarks.menuGuid,
"", PlacesUtils.bookmarks.SOURCES.DEFAULT],
}]);
});
function expectNotifications() {
let notifications = [];
let observer = new Proxy(NavBookmarkObserver, {
@ -505,8 +555,6 @@ function expectNotifications() {
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, arguments: args });

Просмотреть файл

@ -165,7 +165,7 @@ add_task(async function remove_bookmark_empty_title() {
Assert.deepEqual(bm1, bm2);
Assert.equal(bm2.index, 0);
Assert.ok(!("title" in bm2));
Assert.strictEqual(bm2.title, "");
});
add_task(async function remove_folder() {
@ -243,7 +243,7 @@ add_task(async function remove_folder_empty_title() {
Assert.deepEqual(bm1, bm2);
Assert.equal(bm2.index, 0);
Assert.ok(!("title" in bm2));
Assert.strictEqual(bm2.title, "");
});
add_task(async function remove_separator() {
@ -260,7 +260,7 @@ add_task(async function remove_separator() {
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_SEPARATOR);
Assert.ok(!("url" in bm2));
Assert.ok(!("title" in bm2));
Assert.strictEqual(bm2.title, "");
});
add_task(async function test_nested_content_fails_when_not_allowed() {

Просмотреть файл

@ -194,10 +194,10 @@ add_task(async function update_lastModified() {
bm = await PlacesUtils.bookmarks.update({ guid: bm.guid,
title: "" });
Assert.ok(!("title" in bm));
Assert.strictEqual(bm.title, "");
bm = await PlacesUtils.bookmarks.fetch(bm.guid);
Assert.ok(!("title" in bm));
Assert.strictEqual(bm.title, "");
});
add_task(async function update_url() {

Просмотреть файл

@ -164,7 +164,7 @@ add_task(async function onItemAdded_separator() {
{ 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: "title", check: v => v === "" },
{ 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) },
@ -259,7 +259,7 @@ add_task(async function onItemChanged_tags_bookmark() {
{ 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: "title", check: v => v === "" },
{ 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) },

Просмотреть файл

@ -20,6 +20,7 @@ var testData = [
// Add a bookmark that should be in the results
{ isBookmark: true,
uri: "http://bookmarked.com/",
title: "",
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
isInQuery: true },
@ -27,6 +28,7 @@ var testData = [
// Add a bookmark that should not be in the results
{ isBookmark: true,
uri: "http://bookmarked-elsewhere.com/",
title: "",
parentGuid: PlacesUtils.bookmarks.menuGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
isInQuery: false },
@ -34,6 +36,7 @@ var testData = [
// Add an un-bookmarked visit
{ isVisit: true,
uri: "http://notbookmarked.com/",
title: "",
isInQuery: false }
];
@ -68,6 +71,7 @@ add_task(async function test_onlyBookmarked() {
// Add a bookmark that should show up
{ isBookmark: true,
uri: "http://bookmarked2.com/",
title: "",
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
isInQuery: true },
@ -75,6 +79,7 @@ add_task(async function test_onlyBookmarked() {
// Add a bookmark that should not show up
{ isBookmark: true,
uri: "http://bookmarked-elsewhere2.com/",
title: "",
parentGuid: PlacesUtils.bookmarks.menuGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
isInQuery: false }

Просмотреть файл

@ -5,7 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Both SetItemtitle and insertBookmark should allow for null titles.
* Both SetItemtitle and insertBookmark should default to the empty string
* for null titles.
*/
const bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
@ -23,8 +24,8 @@ function run_test() {
do_check_eq(bs.getItemTitle(itemId), "");
// Set title to null.
bs.setItemTitle(itemId, null);
// Check returned title is null.
do_check_eq(bs.getItemTitle(itemId), null);
// Check returned title defaults to an empty string.
do_check_eq(bs.getItemTitle(itemId), "");
// Cleanup.
bs.removeItem(itemId);
@ -33,8 +34,8 @@ function run_test() {
uri(TEST_URL),
bs.DEFAULT_INDEX,
null);
// Check returned title is null.
do_check_eq(bs.getItemTitle(itemId), null);
// Check returned title defaults to an empty string.
do_check_eq(bs.getItemTitle(itemId), "");
// Set title to an empty string.
bs.setItemTitle(itemId, "");
// Check returned title is an empty string.