--- a/toolkit/components/places/BookmarkJSONUtils.jsm
+++ b/toolkit/components/places/BookmarkJSONUtils.jsm
@@ -450,17 +450,17 @@ function translateTreeTypes(node) {
if (node.dateAdded) {
node.dateAdded = PlacesUtils.toDate(node.dateAdded);
}
if (node.lastModified) {
let lastModified = PlacesUtils.toDate(node.lastModified);
// Ensure we get a last modified date that's later or equal to the dateAdded
// so that we don't upset the Bookmarks API.
- if (lastModified >= node.dataAdded) {
+ if (lastModified >= node.dateAdded) {
node.lastModified = lastModified;
} else {
delete node.lastModified;
}
}
if (node.tags) {
// Separate any tags into an array, and ignore any that are too long.
--- a/toolkit/components/places/Bookmarks.jsm
+++ b/toolkit/components/places/Bookmarks.jsm
@@ -1501,33 +1501,37 @@ async function insertLivemarkData(items)
if (item.lastModified) {
item.lastModified = PlacesUtils.toPRTime(item.lastModified);
}
let livemark = await PlacesUtils.livemarks.addLivemark(item);
let id = livemark.id;
if (item.annos && item.annos.length) {
+ // Note: for annotations, we intentionally skip updating the last modified
+ // value for the bookmark, to avoid a second update of the added bookmark.
PlacesUtils.setAnnotationsForItem(id, item.annos,
- item.source);
+ item.source, true);
}
}
}
}
/**
* Handles special data on a bookmark, e.g. annotations, keywords, tags, charsets,
* inserting the data into the appropriate place.
*
* @param {Integer} itemId The ID of the item within the bookmarks database.
* @param {Object} item The bookmark item with possible special data to be inserted.
*/
async function handleBookmarkItemSpecialData(itemId, item) {
if (item.annos && item.annos.length) {
- PlacesUtils.setAnnotationsForItem(itemId, item.annos, item.source)
+ // Note: for annotations, we intentionally skip updating the last modified
+ // value for the bookmark, to avoid a second update of the added bookmark.
+ PlacesUtils.setAnnotationsForItem(itemId, item.annos, item.source, true)
}
if ("keyword" in item && item.keyword) {
// POST data could be set in 2 ways:
// 1. new backups have a postData property
// 2. old backups have an item annotation
let postDataAnno = item.annos &&
item.annos.find(anno => anno.name == PlacesUtils.POST_DATA_ANNO);
let postData = item.postData || (postDataAnno && postDataAnno.value);
--- a/toolkit/components/places/PlacesTransactions.jsm
+++ b/toolkit/components/places/PlacesTransactions.jsm
@@ -988,18 +988,16 @@ function createItemsFromBookmarksTree(tr
if ("keyword" in item) {
let { uri: url, keyword, postData } = item;
await PlacesUtils.keywords.insert({ url, keyword, postData });
}
if ("tags" in item) {
PlacesUtils.tagging.tagURI(Services.io.newURI(item.uri),
item.tags.split(","));
- if (restoring)
- shouldResetLastModified = true;
}
break;
}
case PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER: {
// Either a folder or a livemark
let feedURI, siteURI;
[feedURI, siteURI, annos] = extractLivemarkDetails(annos);
if (!feedURI) {
@@ -1036,19 +1034,18 @@ function createItemsFromBookmarksTree(tr
}
if (annos.length > 0) {
if (!restoring && excludingAnnotations.length > 0) {
annos = annos.filter(a => !excludingAnnotations.includes(a.name));
}
if (annos.length > 0) {
let itemId = await PlacesUtils.promiseItemId(guid);
- PlacesUtils.setAnnotationsForItem(itemId, annos);
- if (restoring)
- shouldResetLastModified = true;
+ PlacesUtils.setAnnotationsForItem(itemId, annos,
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT, true);
}
}
if (shouldResetLastModified) {
let lastModified = PlacesUtils.toDate(item.lastModified);
await PlacesUtils.bookmarks.update({ guid, lastModified });
}
@@ -1087,17 +1084,18 @@ PT.NewBookmark.prototype = Object.seal({
.getTagsForURI(Services.io.newURI(url.href));
tags = tags.filter(t => !currentTags.includes(t));
}
async function createItem() {
info = await PlacesUtils.bookmarks.insert(info);
if (annotations.length > 0) {
let itemId = await PlacesUtils.promiseItemId(info.guid);
- PlacesUtils.setAnnotationsForItem(itemId, annotations);
+ PlacesUtils.setAnnotationsForItem(itemId, annotations,
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT, true);
}
if (tags.length > 0) {
PlacesUtils.tagging.tagURI(Services.io.newURI(url.href), tags);
}
}
await createItem();
@@ -1106,20 +1104,16 @@ PT.NewBookmark.prototype = Object.seal({
// which could be affected by any annotation we set in createItem.
await PlacesUtils.bookmarks.remove(info);
if (tags.length > 0) {
PlacesUtils.tagging.untagURI(Services.io.newURI(url.href), tags);
}
};
this.redo = async function() {
await createItem();
- // CreateItem will update the lastModified value if tags or annotations
- // are present, but we don't care to restore it. The likely of a user
- // creating a bookmark, undoing and redoing that, and still caring
- // about lastModified is basically non-existant.
};
return info.guid;
}
});
/**
* Transaction for creating a folder.
*
@@ -1160,28 +1154,27 @@ PT.NewFolder.prototype = Object.seal({
// therefore we update the bookmark manually afterwards.
if (index != PlacesUtils.bookmarks.DEFAULT_INDEX) {
bmInfo[0].index = index;
bmInfo = await PlacesUtils.bookmarks.update(bmInfo[0]);
}
if (annotations.length > 0) {
let itemId = await PlacesUtils.promiseItemId(folderGuid);
- PlacesUtils.setAnnotationsForItem(itemId, annotations);
+ PlacesUtils.setAnnotationsForItem(itemId, annotations,
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT, true);
}
}
await createItem();
this.undo = async function() {
await PlacesUtils.bookmarks.remove(folderGuid);
};
this.redo = async function() {
await createItem();
- // See the reasoning in CreateItem for why we don't care
- // about precisely resetting the lastModified value.
};
return folderGuid;
}
});
/**
* Transaction for creating a separator.
*
@@ -1219,17 +1212,18 @@ PT.NewLivemark.prototype = Object.seal({
let livemarkInfo = { title,
feedURI: Services.io.newURI(feedUrl.href),
siteURI: siteUrl ? Services.io.newURI(siteUrl.href) : null,
index,
parentGuid};
let createItem = async function() {
let livemark = await PlacesUtils.livemarks.addLivemark(livemarkInfo);
if (annotations.length > 0) {
- PlacesUtils.setAnnotationsForItem(livemark.id, annotations);
+ PlacesUtils.setAnnotationsForItem(livemark.id, annotations,
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT, true);
}
return livemark;
};
let livemark = await createItem();
livemarkInfo.guid = livemark.guid;
livemarkInfo.dateAdded = livemark.dateAdded;
livemarkInfo.lastModified = livemark.lastModified;
--- a/toolkit/components/places/PlacesUtils.jsm
+++ b/toolkit/components/places/PlacesUtils.jsm
@@ -1165,28 +1165,28 @@ this.PlacesUtils = {
* Annotate an item with a batch of annotations.
* @param aItemId
* The identifier of the item for which annotations are to be set
* @param aAnnotations
* Array of objects, each containing the following properties:
* name, flags, expires.
* If the value for an annotation is not set it will be removed.
*/
- setAnnotationsForItem: function PU_setAnnotationsForItem(aItemId, aAnnos, aSource) {
+ setAnnotationsForItem: function PU_setAnnotationsForItem(aItemId, aAnnos, aSource, aDontUpdateLastModified) {
var annosvc = this.annotations;
aAnnos.forEach(function(anno) {
if (anno.value === undefined || anno.value === null) {
annosvc.removeItemAnnotation(aItemId, anno.name, aSource);
} else {
let flags = ("flags" in anno) ? anno.flags : 0;
let expires = ("expires" in anno) ?
anno.expires : Ci.nsIAnnotationService.EXPIRE_NEVER;
annosvc.setItemAnnotation(aItemId, anno.name, anno.value, flags,
- expires, aSource);
+ expires, aSource, aDontUpdateLastModified);
}
});
},
// Identifier getters for special folders.
// You should use these everywhere PlacesUtils is available to avoid XPCOM
// traversal just to get roots' ids.
get placesRootId() {
--- a/toolkit/components/places/nsAnnotationService.cpp
+++ b/toolkit/components/places/nsAnnotationService.cpp
@@ -259,17 +259,18 @@ nsAnnotationService::SetPageAnnotation(n
NS_IMETHODIMP
nsAnnotationService::SetItemAnnotation(int64_t aItemId,
const nsACString& aName,
nsIVariant* aValue,
int32_t aFlags,
uint16_t aExpiration,
- uint16_t aSource)
+ uint16_t aSource,
+ bool aDontUpdateLastModified)
{
AUTO_PROFILER_LABEL("nsAnnotationService::SetItemAnnotation", OTHER);
NS_ENSURE_ARG_MIN(aItemId, 1);
NS_ENSURE_ARG(aValue);
if (aExpiration == EXPIRE_WITH_HISTORY)
return NS_ERROR_INVALID_ARG;
@@ -285,59 +286,63 @@ nsAnnotationService::SetItemAnnotation(i
case nsIDataType::VTYPE_UINT16:
case nsIDataType::VTYPE_INT32:
case nsIDataType::VTYPE_UINT32:
case nsIDataType::VTYPE_BOOL: {
int32_t valueInt;
rv = aValue->GetAsInt32(&valueInt);
if (NS_SUCCEEDED(rv)) {
NS_ENSURE_SUCCESS(rv, rv);
- rv = SetItemAnnotationInt32(aItemId, aName, valueInt, aFlags, aExpiration, aSource);
+ rv = SetItemAnnotationInt32(aItemId, aName, valueInt, aFlags,
+ aExpiration, aSource, aDontUpdateLastModified);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// Fall through int64_t case otherwise.
MOZ_FALLTHROUGH;
}
case nsIDataType::VTYPE_INT64:
case nsIDataType::VTYPE_UINT64: {
int64_t valueLong;
rv = aValue->GetAsInt64(&valueLong);
if (NS_SUCCEEDED(rv)) {
NS_ENSURE_SUCCESS(rv, rv);
- rv = SetItemAnnotationInt64(aItemId, aName, valueLong, aFlags, aExpiration, aSource);
+ rv = SetItemAnnotationInt64(aItemId, aName, valueLong, aFlags,
+ aExpiration, aSource, aDontUpdateLastModified);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// Fall through double case otherwise.
MOZ_FALLTHROUGH;
}
case nsIDataType::VTYPE_FLOAT:
case nsIDataType::VTYPE_DOUBLE: {
double valueDouble;
rv = aValue->GetAsDouble(&valueDouble);
NS_ENSURE_SUCCESS(rv, rv);
- rv = SetItemAnnotationDouble(aItemId, aName, valueDouble, aFlags, aExpiration, aSource);
+ rv = SetItemAnnotationDouble(aItemId, aName, valueDouble, aFlags,
+ aExpiration, aSource, aDontUpdateLastModified);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
case nsIDataType::VTYPE_CHAR:
case nsIDataType::VTYPE_WCHAR:
case nsIDataType::VTYPE_DOMSTRING:
case nsIDataType::VTYPE_CHAR_STR:
case nsIDataType::VTYPE_WCHAR_STR:
case nsIDataType::VTYPE_STRING_SIZE_IS:
case nsIDataType::VTYPE_WSTRING_SIZE_IS:
case nsIDataType::VTYPE_UTF8STRING:
case nsIDataType::VTYPE_CSTRING:
case nsIDataType::VTYPE_ASTRING: {
nsAutoString stringValue;
rv = aValue->GetAsAString(stringValue);
NS_ENSURE_SUCCESS(rv, rv);
- rv = SetItemAnnotationString(aItemId, aName, stringValue, aFlags, aExpiration, aSource);
+ rv = SetItemAnnotationString(aItemId, aName, stringValue, aFlags,
+ aExpiration, aSource, aDontUpdateLastModified);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
}
return NS_ERROR_NOT_IMPLEMENTED;
}
@@ -362,28 +367,29 @@ nsAnnotationService::SetPageAnnotationSt
NS_IMETHODIMP
nsAnnotationService::SetItemAnnotationString(int64_t aItemId,
const nsACString& aName,
const nsAString& aValue,
int32_t aFlags,
uint16_t aExpiration,
- uint16_t aSource)
+ uint16_t aSource,
+ bool aDontUpdateLastModified)
{
NS_ENSURE_ARG_MIN(aItemId, 1);
if (aExpiration == EXPIRE_WITH_HISTORY)
return NS_ERROR_INVALID_ARG;
nsresult rv = SetAnnotationStringInternal(nullptr, aItemId, aName, aValue,
aFlags, aExpiration);
NS_ENSURE_SUCCESS(rv, rv);
- NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName, aSource));
+ NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName, aSource, aDontUpdateLastModified));
return NS_OK;
}
nsresult
nsAnnotationService::SetAnnotationInt32Internal(nsIURI* aURI,
int64_t aItemId,
@@ -433,28 +439,29 @@ nsAnnotationService::SetPageAnnotationIn
NS_IMETHODIMP
nsAnnotationService::SetItemAnnotationInt32(int64_t aItemId,
const nsACString& aName,
int32_t aValue,
int32_t aFlags,
uint16_t aExpiration,
- uint16_t aSource)
+ uint16_t aSource,
+ bool aDontUpdateLastModified)
{
NS_ENSURE_ARG_MIN(aItemId, 1);
if (aExpiration == EXPIRE_WITH_HISTORY)
return NS_ERROR_INVALID_ARG;
nsresult rv = SetAnnotationInt32Internal(nullptr, aItemId, aName, aValue,
aFlags, aExpiration);
NS_ENSURE_SUCCESS(rv, rv);
- NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName, aSource));
+ NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName, aSource, aDontUpdateLastModified));
return NS_OK;
}
nsresult
nsAnnotationService::SetAnnotationInt64Internal(nsIURI* aURI,
int64_t aItemId,
@@ -504,28 +511,29 @@ nsAnnotationService::SetPageAnnotationIn
NS_IMETHODIMP
nsAnnotationService::SetItemAnnotationInt64(int64_t aItemId,
const nsACString& aName,
int64_t aValue,
int32_t aFlags,
uint16_t aExpiration,
- uint16_t aSource)
+ uint16_t aSource,
+ bool aDontUpdateLastModified)
{
NS_ENSURE_ARG_MIN(aItemId, 1);
if (aExpiration == EXPIRE_WITH_HISTORY)
return NS_ERROR_INVALID_ARG;
nsresult rv = SetAnnotationInt64Internal(nullptr, aItemId, aName, aValue,
aFlags, aExpiration);
NS_ENSURE_SUCCESS(rv, rv);
- NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName, aSource));
+ NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName, aSource, aDontUpdateLastModified));
return NS_OK;
}
nsresult
nsAnnotationService::SetAnnotationDoubleInternal(nsIURI* aURI,
int64_t aItemId,
@@ -575,28 +583,29 @@ nsAnnotationService::SetPageAnnotationDo
NS_IMETHODIMP
nsAnnotationService::SetItemAnnotationDouble(int64_t aItemId,
const nsACString& aName,
double aValue,
int32_t aFlags,
uint16_t aExpiration,
- uint16_t aSource)
+ uint16_t aSource,
+ bool aDontUpdateLastModified)
{
NS_ENSURE_ARG_MIN(aItemId, 1);
if (aExpiration == EXPIRE_WITH_HISTORY)
return NS_ERROR_INVALID_ARG;
nsresult rv = SetAnnotationDoubleInternal(nullptr, aItemId, aName, aValue,
aFlags, aExpiration);
NS_ENSURE_SUCCESS(rv, rv);
- NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName, aSource));
+ NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName, aSource, aDontUpdateLastModified));
return NS_OK;
}
NS_IMETHODIMP
nsAnnotationService::GetPageAnnotationString(nsIURI* aURI,
const nsACString& aName,
nsAString& _retval)
@@ -1634,17 +1643,17 @@ nsAnnotationService::CopyItemAnnotations
rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("name_id"), annoNameID);
NS_ENSURE_SUCCESS(rv, rv);
rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("date"), PR_Now());
NS_ENSURE_SUCCESS(rv, rv);
rv = copyStmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
- NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aDestItemId, annoName, aSource));
+ NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aDestItemId, annoName, aSource, false));
}
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
--- a/toolkit/components/places/nsIAnnotationService.idl
+++ b/toolkit/components/places/nsIAnnotationService.idl
@@ -15,17 +15,18 @@ interface nsIAnnotationObserver : nsISup
/**
* Called when an annotation value is set. It could be a new annotation,
* or it could be a new value for an existing annotation.
*/
void onPageAnnotationSet(in nsIURI aPage,
in AUTF8String aName);
void onItemAnnotationSet(in long long aItemId,
in AUTF8String aName,
- in unsigned short aSource);
+ in unsigned short aSource,
+ in boolean aDontUpdateLastModified);
/**
* Called when an annotation is deleted. If aName is empty, then ALL
* annotations for the given URI have been deleted. This is not called when
* annotations are expired (normally happens when the app exits).
*/
void onPageAnnotationRemoved(in nsIURI aURI,
in AUTF8String aName);
@@ -35,30 +36,30 @@ interface nsIAnnotationObserver : nsISup
};
[scriptable, uuid(D4CDAAB1-8EEC-47A8-B420-AD7CB333056A)]
interface nsIAnnotationService : nsISupports
{
/**
* Valid values for aExpiration, which sets the expiration policy for your
* annotation. The times for the days, weeks and months policies are
- * measured since the last visit date of the page in question. These
+ * measured since the last visit date of the page in question. These
* will not expire so long as the user keeps visiting the page from time
* to time.
*/
// For temporary data that can be discarded when the user exits.
// Removed at application exit.
const unsigned short EXPIRE_SESSION = 0;
// NOTE: 1 is skipped due to its temporary use as EXPIRE_NEVER in bug #319455.
// For general page settings, things the user is interested in seeing
// if they come back to this page some time in the near future.
- // Removed at 30 days.
+ // Removed at 30 days.
const unsigned short EXPIRE_WEEKS = 2;
// Something that the user will be interested in seeing in their
// history like favicons. If they haven't visited a page in a couple
// of months, they probably aren't interested in many other annotations,
// the positions of things, or other stuff you create, so put that in
// the weeks policy.
// Removed at 180 days.
@@ -126,32 +127,34 @@ interface nsIAnnotationService : nsISupp
in nsIVariant aValue,
in long aFlags,
in unsigned short aExpiration);
void setItemAnnotation(in long long aItemId,
in AUTF8String aName,
in nsIVariant aValue,
in long aFlags,
in unsigned short aExpiration,
- [optional] in unsigned short aSource);
+ [optional] in unsigned short aSource,
+ [optional] in bool aDontUpdateLastModified);
/**
* @throws NS_ERROR_ILLEGAL_VALUE if the page or the bookmark doesn't exist.
*/
[noscript] void setPageAnnotationString(in nsIURI aURI,
in AUTF8String aName,
in AString aValue,
in long aFlags,
in unsigned short aExpiration);
[noscript] void setItemAnnotationString(in long long aItemId,
in AUTF8String aName,
in AString aValue,
in long aFlags,
in unsigned short aExpiration,
- [optional] in unsigned short aSource);
+ [optional] in unsigned short aSource,
+ [optional] in bool aDontUpdateLastModified);
/**
* Sets an annotation just like setAnnotationString, but takes an Int32 as
* input.
*
* @throws NS_ERROR_ILLEGAL_VALUE if the page or the bookmark doesn't exist.
*/
[noscript] void setPageAnnotationInt32(in nsIURI aURI,
@@ -159,17 +162,18 @@ interface nsIAnnotationService : nsISupp
in long aValue,
in long aFlags,
in unsigned short aExpiration);
[noscript] void setItemAnnotationInt32(in long long aItemId,
in AUTF8String aName,
in long aValue,
in long aFlags,
in unsigned short aExpiration,
- [optional] in unsigned short aSource);
+ [optional] in unsigned short aSource,
+ [optional] in bool aDontUpdateLastModified);
/**
* Sets an annotation just like setAnnotationString, but takes an Int64 as
* input.
*
* @throws NS_ERROR_ILLEGAL_VALUE if the page or the bookmark doesn't exist.
*/
[noscript] void setPageAnnotationInt64(in nsIURI aURI,
@@ -177,17 +181,18 @@ interface nsIAnnotationService : nsISupp
in long long aValue,
in long aFlags,
in unsigned short aExpiration);
[noscript] void setItemAnnotationInt64(in long long aItemId,
in AUTF8String aName,
in long long aValue,
in long aFlags,
in unsigned short aExpiration,
- [optional] in unsigned short aSource);
+ [optional] in unsigned short aSource,
+ [optional] in bool aDontUpdateLastModified);
/**
* Sets an annotation just like setAnnotationString, but takes a double as
* input.
*
* @throws NS_ERROR_ILLEGAL_VALUE if the page or the bookmark doesn't exist.
*/
[noscript] void setPageAnnotationDouble(in nsIURI aURI,
@@ -195,17 +200,18 @@ interface nsIAnnotationService : nsISupp
in double aValue,
in long aFlags,
in unsigned short aExpiration);
[noscript] void setItemAnnotationDouble(in long long aItemId,
in AUTF8String aName,
in double aValue,
in long aFlags,
in unsigned short aExpiration,
- [optional] in unsigned short aSource);
+ [optional] in unsigned short aSource,
+ [optional] in boolean aDontUpdateLastModified);
/**
* Retrieves the value of a given annotation. Throws an error if the
* annotation does not exist. C++ consumers may use the type-specific
* methods.
*
* The type-specific methods throw if the given annotation is set in
* a different type.
--- a/toolkit/components/places/nsNavBookmarks.cpp
+++ b/toolkit/components/places/nsNavBookmarks.cpp
@@ -3314,26 +3314,28 @@ NS_IMETHODIMP
nsNavBookmarks::OnPageAnnotationSet(nsIURI* aPage, const nsACString& aName)
{
return NS_OK;
}
NS_IMETHODIMP
nsNavBookmarks::OnItemAnnotationSet(int64_t aItemId, const nsACString& aName,
- uint16_t aSource)
+ uint16_t aSource, bool aDontUpdateLastModified)
{
BookmarkData bookmark;
nsresult rv = FetchItemInfo(aItemId, bookmark);
NS_ENSURE_SUCCESS(rv, rv);
- bookmark.lastModified = RoundedPRNow();
- rv = SetItemDateInternal(LAST_MODIFIED, DetermineSyncChangeDelta(aSource),
- bookmark.id, bookmark.lastModified);
- NS_ENSURE_SUCCESS(rv, rv);
+ if (!aDontUpdateLastModified) {
+ bookmark.lastModified = RoundedPRNow();
+ rv = SetItemDateInternal(LAST_MODIFIED, DetermineSyncChangeDelta(aSource),
+ bookmark.id, bookmark.lastModified);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavBookmarkObserver,
OnItemChanged(bookmark.id,
aName,
true,
EmptyCString(),
bookmark.lastModified,
@@ -3355,12 +3357,12 @@ nsNavBookmarks::OnPageAnnotationRemoved(
NS_IMETHODIMP
nsNavBookmarks::OnItemAnnotationRemoved(int64_t aItemId, const nsACString& aName,
uint16_t aSource)
{
// As of now this is doing the same as OnItemAnnotationSet, so just forward
// the call.
- nsresult rv = OnItemAnnotationSet(aItemId, aName, aSource);
+ nsresult rv = OnItemAnnotationSet(aItemId, aName, aSource, false);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
--- a/toolkit/components/places/tests/unit/bookmarks.json
+++ b/toolkit/components/places/tests/unit/bookmarks.json
@@ -263,13 +263,24 @@
"guid": "OCyeUO5uu9FW",
"title": "Example.tld",
"id": 14,
"parent": 5,
"dateAdded": 1361551979401846,
"lastModified": 1361551979402952,
"type": "text/x-moz-place",
"uri": "http://example.tld/"
+ },
+ {
+ "guid": "Cfkety492Afk",
+ "title": "test tagged bookmark",
+ "id": 15,
+ "parent": 5,
+ "dateAdded": 1507025843703345,
+ "lastModified": 1507025844703124,
+ "type": "text/x-moz-place",
+ "uri": "http://example.tld/tagged",
+ "tags": "foo"
}
]
}
]
}
--- a/toolkit/components/places/tests/unit/test_bookmarks_json.js
+++ b/toolkit/components/places/tests/unit/test_bookmarks_json.js
@@ -43,23 +43,23 @@ var test_bookmarks = {
guid: "OCyeUO5uu9FK",
type: Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR
},
{
guid: "OCyeUO5uu9FL",
title: "test",
description: "folder test comment",
dateAdded: 1177541020000000,
- // lastModified: 1177541050000000,
+ lastModified: 1177541050000000,
children: [
{ guid: "OCyeUO5uu9GX",
title: "test post keyword",
description: "item description",
dateAdded: 1177375336000000,
- // lastModified: 1177375423000000,
+ lastModified: 1177375423000000,
keyword: "test",
sidebar: true,
postData: "hidden1%3Dbar&text1%3D%25s",
charset: "ISO-8859-1"
}
]
}
],
@@ -71,22 +71,30 @@ var test_bookmarks = {
},
{ guid: "OCyeUO5uu9FR",
title: "Latest Headlines",
url: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
feedUrl: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
// Note: date gets truncated to milliseconds, whereas the value in bookmarks.json
// has full microseconds.
dateAdded: 1361551979451000,
+ lastModified: 1361551979457000,
}
],
unfiled: [
{ guid: "OCyeUO5uu9FW",
title: "Example.tld",
url: "http://example.tld/"
+ },
+ { guid: "Cfkety492Afk",
+ title: "test tagged bookmark",
+ dateAdded: 1507025843703000,
+ lastModified: 1507025844703000,
+ url: "http://example.tld/tagged",
+ tags: ["foo"],
}
]
};
// Exported bookmarks file pointer.
var bookmarksExportedFile;
add_task(async function test_import_bookmarks() {
@@ -204,17 +212,17 @@ async function checkItem(aExpected, aNod
id, LOAD_IN_SIDEBAR_ANNO), aExpected.sidebar);
break;
case "postData": {
let entry = await PlacesUtils.keywords.fetch({ url: aNode.uri });
Assert.equal(entry.postData, aExpected.postData);
break;
}
case "charset":
- let testURI = NetUtil.newURI(aNode.uri);
+ let testURI = Services.io.newURI(aNode.uri);
do_check_eq((await PlacesUtils.getCharsetForURI(testURI)), aExpected.charset);
break;
case "feedUrl":
let livemark = await PlacesUtils.livemarks.getLivemark({ id });
do_check_eq(livemark.siteURI.spec, aExpected.url);
do_check_eq(livemark.feedURI.spec, aExpected.feedUrl);
break;
case "children":
@@ -224,13 +232,18 @@ async function checkItem(aExpected, aNod
do_check_eq(folder.childCount, aExpected.children.length);
for (let index = 0; index < aExpected.children.length; index++) {
await checkItem(aExpected.children[index], folder.getChild(index));
}
folder.containerOpen = false;
break;
+ case "tags":
+ let uri = Services.io.newURI(aNode.uri);
+ Assert.deepEqual(PlacesUtils.tagging.getTagsForURI(uri), aExpected.tags,
+ "should have the expected tags");
+ break;
default:
throw new Error("Unknown property");
}
}
}