Bug 896193 - Adopt Promises in mozIAsyncLivemarks. r=mak. sr=gavin.

This commit is contained in:
Asaf Romano 2013-11-20 12:00:02 +02:00
parent 4daad602d0
commit 8af98a8cd2
3 changed files with 476 additions and 366 deletions

View File

@ -12,7 +12,7 @@ interface mozILivemark;
interface nsINavHistoryResultObserver;
[scriptable, uuid(1dbf174c-696e-4d9b-af0f-350da50d2249)]
[scriptable, uuid(5B48E5A2-F07A-4E64-A935-C722A3D60B65)]
interface mozIAsyncLivemarks : nsISupports
{
/**
@ -24,12 +24,12 @@ interface mozIAsyncLivemarks : nsISupports
* @param [optional] aCallback
* Invoked when the creation process is done. In case of failure will
* receive an error code.
*
* @return {Promise}
* @throws NS_ERROR_INVALID_ARG if the supplied information is insufficient
* for the creation.
*/
void addLivemark(in jsval aLivemarkInfo,
[optional]in mozILivemarkCallback aCallback);
jsval addLivemark(in jsval aLivemarkInfo,
[optional] in mozILivemarkCallback aCallback);
/**
* Removes an existing livemark.
@ -41,10 +41,11 @@ interface mozIAsyncLivemarks : nsISupports
* Invoked when the removal process is done. In case of failure will
* receive an error code.
*
* @return {Promise}
* @throws NS_ERROR_INVALID_ARG if the id/guid is invalid.
*/
void removeLivemark(in jsval aLivemarkInfo,
[optional]in mozILivemarkCallback aCallback);
jsval removeLivemark(in jsval aLivemarkInfo,
[optional] in mozILivemarkCallback aCallback);
/**
* Gets an existing livemark.
@ -52,15 +53,16 @@ interface mozIAsyncLivemarks : nsISupports
* @param aLivemarkInfo
* mozILivemarkInfo object containing either an id or a guid of the
* livemark to retrieve.
* @param aCallback
* @param [optional] aCallback
* Invoked when the fetching process is done. In case of failure will
* receive an error code.
*
* @return {Promise}
* @throws NS_ERROR_INVALID_ARG if the id/guid is invalid or an invalid
* callback is provided.
*/
void getLivemark(in jsval aLivemarkInfo,
in mozILivemarkCallback aCallback);
jsval getLivemark(in jsval aLivemarkInfo,
[optional] in mozILivemarkCallback aCallback);
/**
* Reloads all livemarks if they are expired or if forced to do so.

View File

@ -16,6 +16,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
////////////////////////////////////////////////////////////////////////////////
//// Services
@ -49,7 +51,7 @@ function LivemarkService()
{
// Cleanup on shutdown.
Services.obs.addObserver(this, PlacesUtils.TOPIC_SHUTDOWN, true);
// Observe bookmarks and history, but don't init the services just for that.
PlacesUtils.addLazyBookmarkObserver(this, true);
@ -102,7 +104,7 @@ LivemarkService.prototype = {
let guid = row.getResultByName("guid");
livemarkSvc._livemarks[id] =
new Livemark({ id: id,
guid: guid,
guid: guid,
title: row.getResultByName("title"),
parentId: row.getResultByName("parent"),
index: row.getResultByName("position"),
@ -213,7 +215,8 @@ LivemarkService.prototype = {
// The addition is done synchronously due to the fact importExport service
// and JSON backups require that. The notification is async though.
// Once bookmarks are async, this may be properly fixed.
let result = Cr.NS_OK;
let deferred = Promise.defer();
let addLivemarkEx = null;
let livemark = null;
try {
// Disallow adding a livemark inside another livemark.
@ -246,18 +249,33 @@ LivemarkService.prototype = {
this._guids[aLivemarkInfo.guid] = livemark.id;
}
catch (ex) {
result = ex.result;
addLivemarkEx = ex;
livemark = null;
}
finally {
if (aLivemarkCallback) {
this._onCacheReady(function LS_addLivemark_ETAT() {
try {
aLivemarkCallback.onCompletion(result, livemark);
} catch(ex2) {}
}, true);
}
this._onCacheReady( () => {
if (addLivemarkEx) {
if (aLivemarkCallback) {
try {
aLivemarkCallback.onCompletion(addLivemarkEx.result, livemark);
}
catch(ex2) { }
}
deferred.reject(addLivemarkEx);
}
else {
if (aLivemarkCallback) {
try {
aLivemarkCallback.onCompletion(Cr.NS_OK, livemark);
}
catch(ex2) { }
}
deferred.resolve(livemark);
}
}, true);
}
return deferred.promise;
},
removeLivemark: function LS_removeLivemark(aLivemarkInfo, aLivemarkCallback)
@ -278,7 +296,9 @@ LivemarkService.prototype = {
if (id in this._guids) {
id = this._guids[id];
}
let result = Cr.NS_OK;
let deferred = Promise.defer();
let removeLivemarkEx = null;
try {
if (!(id in this._livemarks)) {
throw new Components.Exception("", Cr.NS_ERROR_INVALID_ARG);
@ -286,18 +306,32 @@ LivemarkService.prototype = {
this._livemarks[id].remove();
}
catch (ex) {
result = ex.result;
removeLivemarkEx = ex;
}
finally {
if (aLivemarkCallback) {
// Enqueue the notification, per interface definition.
this._onCacheReady(function LS_removeLivemark_ETAT() {
try {
aLivemarkCallback.onCompletion(result, null);
} catch(ex2) {}
});
}
this._onCacheReady( () => {
if (removeLivemarkEx) {
if (aLivemarkCallback) {
try {
aLivemarkCallback.onCompletion(removeLivemarkEx.result, null);
}
catch(ex2) { }
}
deferred.reject(removeLivemarkEx);
}
else {
if (aLivemarkCallback) {
try {
aLivemarkCallback.onCompletion(Cr.NS_OK, null);
}
catch(ex2) { }
}
deferred.resolve();
}
});
}
return deferred.promise;
},
_reloaded: [],
@ -324,15 +358,15 @@ LivemarkService.prototype = {
if (this._reloading && notWorthRestarting) {
// Ignore this call.
return;
}
}
this._onCacheReady((function LS_reloadAllLivemarks_ETAT() {
this._onCacheReady( () => {
this._forceUpdate = !!aForceUpdate;
this._reloaded = [];
// Livemarks reloads happen on a timer, and are delayed for performance
// reasons.
this._startReloadTimer();
}).bind(this));
});
},
getLivemark: function LS_getLivemark(aLivemarkInfo, aLivemarkCallback)
@ -348,22 +382,31 @@ LivemarkService.prototype = {
throw Cr.NS_ERROR_INVALID_ARG;
}
this._onCacheReady((function LS_getLivemark_ETAT() {
let deferred = Promise.defer();
this._onCacheReady( () => {
// Convert the guid to an id.
if (id in this._guids) {
id = this._guids[id];
}
if (id in this._livemarks) {
try {
aLivemarkCallback.onCompletion(Cr.NS_OK, this._livemarks[id]);
} catch (ex) {}
if (aLivemarkCallback) {
try {
aLivemarkCallback.onCompletion(Cr.NS_OK, this._livemarks[id]);
} catch (ex) {}
}
deferred.resolve(this._livemarks[id]);
}
else {
try {
aLivemarkCallback.onCompletion(Cr.NS_ERROR_INVALID_ARG, null);
} catch (ex) {}
if (aLivemarkCallback) {
try {
aLivemarkCallback.onCompletion(Cr.NS_ERROR_INVALID_ARG, null);
} catch (ex) { }
}
deferred.reject(Components.Exception("", Cr.NS_ERROR_INVALID_ARG));
}
}).bind(this));
});
return deferred.promise;
},
//////////////////////////////////////////////////////////////////////////////

View File

@ -6,201 +6,181 @@
const FEED_URI = NetUtil.newURI("http://feed.rss/");
const SITE_URI = NetUtil.newURI("http://site.org/");
function run_test()
{
run_next_test();
}
add_test(function test_addLivemark_noArguments_throws()
add_task(function test_addLivemark_noArguments_throws()
{
try {
PlacesUtils.livemarks.addLivemark();
yield PlacesUtils.livemarks.addLivemark();
do_throw("Invoking addLivemark with no arguments should throw");
} catch (ex) {
// The error is actually generated by XPConnect.
do_check_eq(ex.result, Cr.NS_ERROR_XPC_NOT_ENOUGH_ARGS);
}
run_next_test();
});
add_test(function test_addLivemark_emptyObject_throws()
add_task(function test_addLivemark_emptyObject_throws()
{
try {
PlacesUtils.livemarks.addLivemark({});
yield PlacesUtils.livemarks.addLivemark({});
do_throw("Invoking addLivemark with empty object should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_addLivemark_badParentId_throws()
add_task(function test_addLivemark_badParentId_throws()
{
try {
PlacesUtils.livemarks.addLivemark({ parentId: "test" });
yield PlacesUtils.livemarks.addLivemark({ parentId: "test" });
do_throw("Invoking addLivemark with a bad parent id should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_addLivemark_invalidParentId_throws()
add_task(function test_addLivemark_invalidParentId_throws()
{
try {
PlacesUtils.livemarks.addLivemark({ parentId: -2 });
yield PlacesUtils.livemarks.addLivemark({ parentId: -2 });
do_throw("Invoking addLivemark with an invalid parent id should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_addLivemark_noIndex_throws()
add_task(function test_addLivemark_noIndex_throws()
{
try {
PlacesUtils.livemarks.addLivemark({ parentId: PlacesUtils.unfiledBookmarksFolderId });
yield PlacesUtils.livemarks.addLivemark({
parentId: PlacesUtils.unfiledBookmarksFolderId });
do_throw("Invoking addLivemark with no index should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_addLivemark_badIndex_throws()
add_task(function test_addLivemark_badIndex_throws()
{
try {
PlacesUtils.livemarks.addLivemark({ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: "test"
});
yield PlacesUtils.livemarks.addLivemark(
{ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: "test" });
do_throw("Invoking addLivemark with a bad index should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_addLivemark_invalidIndex_throws()
add_task(function test_addLivemark_invalidIndex_throws()
{
try {
PlacesUtils.livemarks.addLivemark({ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: -2
});
yield PlacesUtils.livemarks.addLivemark(
{ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: -2
});
do_throw("Invoking addLivemark with an invalid index should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_addLivemark_noFeedURI_throws()
add_task(function test_addLivemark_noFeedURI_throws()
{
try {
PlacesUtils.livemarks.addLivemark({ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
});
yield PlacesUtils.livemarks.addLivemark(
{ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX });
do_throw("Invoking addLivemark with no feedURI should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_addLivemark_badFeedURI_throws()
add_task(function test_addLivemark_badFeedURI_throws()
{
try {
PlacesUtils.livemarks.addLivemark({ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: "test"
});
yield PlacesUtils.livemarks.addLivemark(
{ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: "test" });
do_throw("Invoking addLivemark with a bad feedURI should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_addLivemark_badSiteURI_throws()
add_task(function test_addLivemark_badSiteURI_throws()
{
try {
PlacesUtils.livemarks.addLivemark({ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, siteURI: "test"
});
yield PlacesUtils.livemarks.addLivemark(
{ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, siteURI: "test" });
do_throw("Invoking addLivemark with a bad siteURI should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_addLivemark_badGuid_throws()
add_task(function test_addLivemark_badGuid_throws()
{
try {
PlacesUtils.livemarks.addLivemark({ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, guid: "123456"
});
yield PlacesUtils.livemarks.addLivemark(
{ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, guid: "123456" });
do_throw("Invoking addLivemark with a bad guid should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_addLivemark_badCallback_throws()
add_task(function test_addLivemark_badCallback_throws()
{
try {
PlacesUtils.livemarks.addLivemark({ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
}, "test");
yield PlacesUtils.livemarks.addLivemark(
{ parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
}, "test");
do_throw("Invoking addLivemark with a bad callback should throw");
} catch (ex) {
// The error is actually generated by XPConnect.
do_check_eq(ex.result, Cr.NS_ERROR_XPC_BAD_CONVERT_JS);
}
run_next_test();
});
add_test(function test_addLivemark_noCallback_succeeds()
add_task(function test_addLivemark_noCallback_succeeds()
{
let onItemAddedCalled = false;
PlacesUtils.bookmarks.addObserver({
__proto__: NavBookmarkObserver.prototype,
onItemAdded: function onItemAdded(aItemId, aParentId, aIndex, aItemType,
aURI, aTitle)
{
onItemAddedCalled = true;
PlacesUtils.bookmarks.removeObserver(this);
do_check_eq(aParentId, PlacesUtils.unfiledBookmarksFolderId);
do_check_eq(aIndex, 0);
do_check_eq(aItemType, Ci.nsINavBookmarksService.TYPE_FOLDER);
do_check_eq(aTitle, "test");
run_next_test();
},
onBeginUpdateBatch: function onBeginUpdateBatch() {},
onEndUpdateBatch: function onEndUpdateBatch() {},
onItemRemoved: function onItemRemoved() {},
onItemChanged: function onItemChanged() {},
onItemVisited: function onItemVisited() {},
onItemMoved: function onItemMoved() {},
}
}, false);
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
});
yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI });
do_check_true(onItemAddedCalled);
});
add_test(function test_addLivemark_noSiteURI_callback_succeeds()
add_task(function test_addLivemark_noSiteURI_callback_succeeds()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
}, function (aStatus, aLivemark)
{
do_check_true(Components.isSuccessCode(aStatus));
let checkLivemark = aLivemark => {
do_check_true(aLivemark.id > 0);
do_check_valid_places_guid(aLivemark.guid);
do_check_eq(aLivemark.title, "test");
@ -209,20 +189,28 @@ add_test(function test_addLivemark_noSiteURI_callback_succeeds()
do_check_eq(aLivemark.lastModified, PlacesUtils.bookmarks.getItemLastModified(aLivemark.id));
do_check_true(aLivemark.feedURI.equals(FEED_URI));
do_check_eq(aLivemark.siteURI, null);
run_next_test();
});
};
// The deprecated callback is called before resolving the promise.
let callbackCalled = false;
let livemark = yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
},
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_true(Components.isSuccessCode(aStatus));
checkLivemark(aLivemark);
} );
do_check_true(callbackCalled);
checkLivemark(livemark);
});
add_test(function test_addLivemark_callback_succeeds()
add_task(function test_addLivemark_callback_succeeds()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, siteURI: SITE_URI
}, function (aStatus, aLivemark)
{
do_check_true(Components.isSuccessCode(aStatus));
let checkLivemark = aLivemark => {
do_check_true(aLivemark.id > 0);
do_check_valid_places_guid(aLivemark.guid);
do_check_eq(aLivemark.title, "test");
@ -231,283 +219,351 @@ add_test(function test_addLivemark_callback_succeeds()
do_check_eq(aLivemark.lastModified, PlacesUtils.bookmarks.getItemLastModified(aLivemark.id));
do_check_true(aLivemark.feedURI.equals(FEED_URI));
do_check_true(aLivemark.siteURI.equals(SITE_URI));
do_check_true(PlacesUtils.annotations
.itemHasAnnotation(aLivemark.id,
PlacesUtils.LMANNO_FEEDURI));
do_check_true(PlacesUtils.annotations
.itemHasAnnotation(aLivemark.id,
PlacesUtils.LMANNO_SITEURI));
run_next_test();
});
};
// The deprecated callback is called before resolving the promise.
let callbackCalled = false;
let livemark = yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, siteURI: SITE_URI
},
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_true(Components.isSuccessCode(aStatus));
checkLivemark(aLivemark);
} );
do_check_true(callbackCalled);
checkLivemark(livemark);
});
add_test(function test_addLivemark_bogusid_callback_succeeds()
add_task(function test_addLivemark_bogusid_callback_succeeds()
{
PlacesUtils.livemarks.addLivemark({ id: 100 // Should be ignored.
, title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, siteURI: SITE_URI
}, function (aStatus, aLivemark)
{
do_check_true(Components.isSuccessCode(aStatus));
let checkLivemark = aLivemark => {
do_check_true(aLivemark.id > 0);
do_check_neq(aLivemark.id, 100);
};
run_next_test();
});
// The deprecated callback is called before resolving the promise.
let callbackCalled = false;
let livemark = yield PlacesUtils.livemarks.addLivemark(
{ id: 100 // Should be ignored.
, title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, siteURI: SITE_URI
},
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_true(Components.isSuccessCode(aStatus));
checkLivemark(aLivemark);
} );
do_check_true(callbackCalled);
checkLivemark(livemark);
});
add_test(function test_addLivemark_bogusParent_callback_fails()
add_task(function test_addLivemark_bogusParent_callback_fails()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: 187
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
}, function (aStatus, aLivemark)
{
do_check_false(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark, null);
run_next_test();
});
// The deprecated callback is called before resolving the promise.
let callbackCalled = false;
try {
yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: 187
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
},
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_false(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark, null);
} );
do_throw("Adding a livemark with a bogus parent should fail");
}
catch(ex) {
do_check_true(callbackCalled);
}
});
add_test(function test_addLivemark_intoLivemark_callback_fails()
add_task(function test_addLivemark_intoLivemark_callback_fails()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
}, function (aStatus, aLivemark)
{
do_check_true(Components.isSuccessCode(aStatus));
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: aLivemark.id
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
}, function (aStatus, aLivemark)
{
do_check_false(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark, null);
run_next_test();
});
});
// The deprecated callback is called before resolving the promise.
let callbackCalled = false;
let livemark = yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
},
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_true(Components.isSuccessCode(aStatus));
} );
do_check_true(callbackCalled);
do_check_true(Boolean(livemark));
callbackCalled = false;
try {
yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: livemark.id
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
},
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_false(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark, null);
} );
do_throw("Adding a livemark into a livemark should fail");
}
catch(ex) {
do_check_true(callbackCalled);
}
});
add_test(function test_addLivemark_forceGuid_callback_succeeds()
add_task(function test_addLivemark_forceGuid_callback_succeeds()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, guid: "1234567890AB"
}, function (aStatus, aLivemark)
{
do_check_true(Components.isSuccessCode(aStatus));
let checkLivemark = aLivemark => {
do_check_eq(aLivemark.guid, "1234567890AB");
do_check_guid_for_bookmark(aLivemark.id, "1234567890AB");
};
run_next_test();
});
// The deprecated callback is called before resolving the promise.
let callbackCalled = false;
let livemark = yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, guid: "1234567890AB"
},
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_true(Components.isSuccessCode(aStatus));
checkLivemark(aLivemark);
} );
do_check_true(callbackCalled);
checkLivemark(livemark);
});
add_test(function test_addLivemark_lastModified_callback_succeeds()
add_task(function test_addLivemark_lastModified_callback_succeeds()
{
let now = Date.now() * 1000;
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, lastModified: now
}, function (aStatus, aLivemark)
{
do_check_true(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark.lastModified, now);
run_next_test();
});
let callbackCalled = false;
let livemark = yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, lastModified: now
},
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_true(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark.lastModified, now);
} );
do_check_true(callbackCalled);
do_check_eq(livemark.lastModified, now);
});
add_test(function test_removeLivemark_emptyObject_throws()
add_task(function test_removeLivemark_emptyObject_throws()
{
try {
PlacesUtils.livemarks.removeLivemark({});
yield PlacesUtils.livemarks.removeLivemark({});
do_throw("Invoking removeLivemark with empty object should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_removeLivemark_noValidId_throws()
add_task(function test_removeLivemark_noValidId_throws()
{
try {
PlacesUtils.livemarks.removeLivemark({ id: -10, guid: "test"});
yield PlacesUtils.livemarks.removeLivemark({ id: -10, guid: "test"});
do_throw("Invoking removeLivemark with no valid id should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_removeLivemark_nonExistent_fails()
add_task(function test_removeLivemark_nonExistent_fails()
{
PlacesUtils.livemarks.removeLivemark(
{ id: 1337 },
function (aStatus, aLivemark) {
do_check_false(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark, null);
run_next_test();
}
);
let callbackCalled = false;
try {
yield PlacesUtils.livemarks.removeLivemark(
{ id: 1337 },
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_false(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark, null);
} );
do_throw("Removing a non-existent livemark should fail");
}
catch(ex) {
do_check_true(callbackCalled);
}
});
add_test(function test_removeLivemark_guid_succeeds()
add_task(function test_removeLivemark_guid_succeeds()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, guid: "234567890ABC"
}, function (aStatus, aLivemark)
{
do_check_true(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark.guid, "234567890ABC");
// invalid id to check the guid wins.
PlacesUtils.livemarks.removeLivemark(
{ id: 789, guid: "234567890ABC" },
function (aStatus, aRemovedLivemark) {
do_check_true(Components.isSuccessCode(aStatus));
do_check_eq(PlacesUtils.bookmarks.getItemIndex(aLivemark.id), -1);
do_check_eq(aRemovedLivemark, null);
run_next_test();
}
);
let livemark = yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, guid: "234567890ABC"
});
});
add_test(function test_removeLivemark_id_succeeds()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
}, function (aStatus, aLivemark)
{
do_check_true(Components.isSuccessCode(aStatus));
PlacesUtils.livemarks.removeLivemark(
{ id: aLivemark.id },
function (aStatus, aRemovedLivemark) {
do_check_true(Components.isSuccessCode(aStatus));
do_check_eq(PlacesUtils.bookmarks.getItemIndex(aLivemark.id), -1);
do_check_eq(aRemovedLivemark, null);
run_next_test();
}
);
do_check_eq(livemark.guid, "234567890ABC");
yield PlacesUtils.livemarks.removeLivemark({
id: 789, guid: "234567890ABC"
});
do_check_eq(PlacesUtils.bookmarks.getItemIndex(livemark.id), -1);
});
add_test(function test_getLivemark_emptyObject_throws()
add_task(function test_removeLivemark_id_succeeds()
{
let livemark = yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
});
yield PlacesUtils.livemarks.removeLivemark({ id: livemark.id });
do_check_eq(PlacesUtils.bookmarks.getItemIndex(livemark.id), -1);
});
add_task(function test_getLivemark_emptyObject_throws()
{
try {
PlacesUtils.livemarks.getLivemark({}, function () {});
yield PlacesUtils.livemarks.getLivemark({});
do_throw("Invoking getLivemark with empty object should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_getLivemark_noValidId_throws()
add_task(function test_getLivemark_noValidId_throws()
{
try {
PlacesUtils.livemarks.getLivemark({ id: -10, guid: "test"}, function () {});
yield PlacesUtils.livemarks.getLivemark({ id: -10, guid: "test"});
do_throw("Invoking getLivemark with no valid id should throw");
} catch (ex) {
do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
});
add_test(function test_getLivemark_nonExistentId_fails()
add_task(function test_getLivemark_nonExistentId_fails()
{
PlacesUtils.livemarks.getLivemark({ id: 1234 },
function (aStatus, aLivemark){
do_check_false(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark, null);
run_next_test();
}
);
let callbackCalled = false;
try {
yield PlacesUtils.livemarks.getLivemark({ id: 1234 },
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_false(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark, null);
} );
do_throw("getLivemark for a non existent id should fail");
}
catch(ex) {
do_check_true(callbackCalled);
}
});
add_test(function test_getLivemark_nonExistentGUID_fails()
add_task(function test_getLivemark_nonExistentGUID_fails()
{
PlacesUtils.livemarks.getLivemark({ guid: "34567890ABCD" },
function (aStatus, aLivemark){
do_check_false(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark, null);
run_next_test();
}
);
let callbackCalled = false;
try {
yield PlacesUtils.livemarks.getLivemark({ guid: "34567890ABCD" },
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_false(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark, null);
} );
do_throw("getLivemark for a non-existent guid should fail");
}
catch(ex) {
do_check_true(callbackCalled);
}
});
add_test(function test_getLivemark_guid_succeeds()
add_task(function test_getLivemark_guid_succeeds()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, guid: "34567890ABCD"
}, function (aStatus, aLivemark)
{
do_check_true(Components.isSuccessCode(aStatus));
yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
, guid: "34567890ABCD" });
// invalid id to check the guid wins.
PlacesUtils.livemarks.getLivemark({ id: 789, guid: "34567890ABCD" },
function(aStatus, aLivemark) {
let checkLivemark = aLivemark => {
do_check_eq(aLivemark.title, "test");
do_check_eq(aLivemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
do_check_eq(aLivemark.index, PlacesUtils.bookmarks.getItemIndex(aLivemark.id));
do_check_true(aLivemark.feedURI.equals(FEED_URI));
do_check_eq(aLivemark.siteURI, null);
do_check_eq(aLivemark.guid, "34567890ABCD");
};
// invalid id to check the guid wins.
let livemark =
yield PlacesUtils.livemarks.getLivemark({ id: 789, guid: "34567890ABCD" },
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_true(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark.title, "test");
do_check_eq(aLivemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
do_check_eq(aLivemark.index, PlacesUtils.bookmarks.getItemIndex(aLivemark.id));
do_check_true(aLivemark.feedURI.equals(FEED_URI));
do_check_eq(aLivemark.siteURI, null);
do_check_eq(aLivemark.guid, "34567890ABCD");
run_next_test();
}
);
});
checkLivemark(aLivemark)
} );
do_check_true(callbackCalled);
checkLivemark(livemark);
});
add_test(function test_getLivemark_id_succeeds()
add_task(function test_getLivemark_id_succeeds()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
}, function (aStatus, aLivemark)
{
do_check_true(Components.isSuccessCode(aStatus));
let livemark = yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
});
// invalid id to check the guid wins.
PlacesUtils.livemarks.getLivemark({ id: aLivemark.id },
function(aStatus, aLivemark) {
do_check_true(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark.title, "test");
do_check_eq(aLivemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
do_check_eq(aLivemark.index, PlacesUtils.bookmarks.getItemIndex(aLivemark.id));
do_check_true(aLivemark.feedURI.equals(FEED_URI));
do_check_eq(aLivemark.siteURI, null);
do_check_guid_for_bookmark(aLivemark.id, aLivemark.guid);
run_next_test();
}
);
});
let checkLivemark = aLivemark => {
do_check_eq(aLivemark.title, "test");
do_check_eq(aLivemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
do_check_eq(aLivemark.index, PlacesUtils.bookmarks.getItemIndex(aLivemark.id));
do_check_true(aLivemark.feedURI.equals(FEED_URI));
do_check_eq(aLivemark.siteURI, null);
do_check_guid_for_bookmark(aLivemark.id, aLivemark.guid);
};
let callbackCalled = false;
livemark = yield PlacesUtils.livemarks.getLivemark(
{ id: livemark.id },
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_true(Components.isSuccessCode(aStatus));
checkLivemark(aLivemark);
} );
do_check_true(callbackCalled);
checkLivemark(livemark);
});
add_test(function test_getLivemark_removeItem_contention()
add_task(function test_getLivemark_removeItem_contention()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
@ -522,47 +578,56 @@ add_test(function test_getLivemark_removeItem_contention()
});
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId,
PlacesUtils.bookmarks.DEFAULT_INDEX);
PlacesUtils.livemarks.getLivemark(
{ id: id },
function(aStatus, aLivemark) {
do_check_true(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark.title, "test");
do_check_eq(aLivemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
do_check_eq(aLivemark.index, PlacesUtils.bookmarks.getItemIndex(aLivemark.id));
do_check_true(aLivemark.feedURI.equals(FEED_URI));
do_check_eq(aLivemark.siteURI, null);
do_check_guid_for_bookmark(aLivemark.id, aLivemark.guid);
run_next_test();
}
);
});
add_test(function test_title_change()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
}, function(aStatus, aLivemark) {
PlacesUtils.bookmarks.setItemTitle(aLivemark.id, "test2");
do_check_eq(aLivemark.title, "test2");
run_next_test();
});
});
add_test(function test_livemark_move()
{
PlacesUtils.livemarks.addLivemark({ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI
}, function(aStatus, aLivemark) {
PlacesUtils.bookmarks.moveItem(aLivemark.id,
PlacesUtils.toolbarFolderId,
PlacesUtils.bookmarks.DEFAULT_INDEX);
do_check_eq(aLivemark.parentId, PlacesUtils.toolbarFolderId);
let checkLivemark = (aLivemark) => {
do_check_eq(aLivemark.title, "test");
do_check_eq(aLivemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
do_check_eq(aLivemark.index, PlacesUtils.bookmarks.getItemIndex(aLivemark.id));
run_next_test();
});
do_check_true(aLivemark.feedURI.equals(FEED_URI));
do_check_eq(aLivemark.siteURI, null);
do_check_guid_for_bookmark(aLivemark.id, aLivemark.guid);
};
let callbackCalled = false;
let livemark = yield PlacesUtils.livemarks.getLivemark(
{ id: id },
(aStatus, aLivemark) => {
callbackCalled = true;
do_check_true(Components.isSuccessCode(aStatus));
checkLivemark(aLivemark);
} );
do_check_true(callbackCalled);
checkLivemark(livemark);
});
add_task(function test_title_change()
{
let livemark = yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI });
PlacesUtils.bookmarks.setItemTitle(livemark.id, "test2");
do_check_eq(livemark.title, "test2");
});
add_task(function test_livemark_move()
{
let livemark = yield PlacesUtils.livemarks.addLivemark(
{ title: "test"
, parentId: PlacesUtils.unfiledBookmarksFolderId
, index: PlacesUtils.bookmarks.DEFAULT_INDEX
, feedURI: FEED_URI } );
PlacesUtils.bookmarks.moveItem(livemark.id,
PlacesUtils.toolbarFolderId,
PlacesUtils.bookmarks.DEFAULT_INDEX);
do_check_eq(livemark.parentId, PlacesUtils.toolbarFolderId);
do_check_eq(livemark.index, PlacesUtils.bookmarks.getItemIndex(livemark.id));
});
function run_test() {
run_next_test();
}