зеркало из https://github.com/mozilla/pjs.git
Bug 613588 (Sync) - Load-on-demand livemarks.
r=rnewman
This commit is contained in:
Родитель
5753121d84
Коммит
5b017180f8
|
@ -47,23 +47,6 @@ const Cc = Components.classes;
|
|||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const ALLBOOKMARKS_ANNO = "AllBookmarks";
|
||||
const DESCRIPTION_ANNO = "bookmarkProperties/description";
|
||||
const SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
|
||||
const FEEDURI_ANNO = "livemark/feedURI";
|
||||
const SITEURI_ANNO = "livemark/siteURI";
|
||||
const MOBILEROOT_ANNO = "mobile/bookmarksRoot";
|
||||
const MOBILE_ANNO = "MobileBookmarks";
|
||||
const EXCLUDEBACKUP_ANNO = "places/excludeFromBackup";
|
||||
const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
|
||||
const PARENT_ANNO = "sync/parent";
|
||||
const ORGANIZERQUERY_ANNO = "PlacesOrganizer/OrganizerQuery";
|
||||
const ANNOS_TO_TRACK = [DESCRIPTION_ANNO, SIDEBAR_ANNO,
|
||||
FEEDURI_ANNO, SITEURI_ANNO];
|
||||
|
||||
const SERVICE_NOT_SUPPORTED = "Service not supported on this platform";
|
||||
const FOLDER_SORTINDEX = 1000000;
|
||||
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://services-sync/engines.js");
|
||||
|
@ -74,6 +57,21 @@ Cu.import("resource://services-sync/constants.js");
|
|||
|
||||
Cu.import("resource://services-sync/main.js"); // For access to Service.
|
||||
|
||||
const ALLBOOKMARKS_ANNO = "AllBookmarks";
|
||||
const DESCRIPTION_ANNO = "bookmarkProperties/description";
|
||||
const SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
|
||||
const MOBILEROOT_ANNO = "mobile/bookmarksRoot";
|
||||
const MOBILE_ANNO = "MobileBookmarks";
|
||||
const EXCLUDEBACKUP_ANNO = "places/excludeFromBackup";
|
||||
const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
|
||||
const PARENT_ANNO = "sync/parent";
|
||||
const ORGANIZERQUERY_ANNO = "PlacesOrganizer/OrganizerQuery";
|
||||
const ANNOS_TO_TRACK = [DESCRIPTION_ANNO, SIDEBAR_ANNO,
|
||||
PlacesUtils.LMANNO_FEEDURI, PlacesUtils.LMANNO_SITEURI];
|
||||
|
||||
const SERVICE_NOT_SUPPORTED = "Service not supported on this platform";
|
||||
const FOLDER_SORTINDEX = 1000000;
|
||||
|
||||
function PlacesItem(collection, id, type) {
|
||||
CryptoWrapper.call(this, collection, id);
|
||||
this.type = type || "item";
|
||||
|
@ -633,14 +631,17 @@ BookmarksStore.prototype = {
|
|||
|
||||
switch (type) {
|
||||
case bms.TYPE_FOLDER:
|
||||
if (PlacesUtils.itemIsLivemark(itemId))
|
||||
if (PlacesUtils.annotations
|
||||
.itemHasAnnotation(itemId, PlacesUtils.LMANNO_FEEDURI)) {
|
||||
return "livemark";
|
||||
}
|
||||
return "folder";
|
||||
|
||||
case bms.TYPE_BOOKMARK:
|
||||
let bmkUri = bms.getBookmarkURI(itemId).spec;
|
||||
if (bmkUri.search(/^place:/) == 0)
|
||||
if (bmkUri.indexOf("place:") == 0) {
|
||||
return "query";
|
||||
}
|
||||
return "bookmark";
|
||||
|
||||
case bms.TYPE_SEPARATOR:
|
||||
|
@ -718,7 +719,8 @@ BookmarksStore.prototype = {
|
|||
this._log.debug("No feed URI: skipping livemark record " + record.id);
|
||||
return;
|
||||
}
|
||||
if (PlacesUtils.itemIsLivemark(record._parent)) {
|
||||
if (PlacesUtils.annotations
|
||||
.itemHasAnnotation(record._parent, PlacesUtils.LMANNO_FEEDURI)) {
|
||||
this._log.debug("Invalid parent: skipping livemark record " + record.id);
|
||||
return;
|
||||
}
|
||||
|
@ -726,14 +728,31 @@ BookmarksStore.prototype = {
|
|||
if (record.siteUri != null)
|
||||
siteURI = Utils.makeURI(record.siteUri);
|
||||
|
||||
// Use createLivemarkFolderOnly, not createLivemark, to avoid it
|
||||
// automatically updating during a sync.
|
||||
newId = PlacesUtils.livemarks.createLivemarkFolderOnly(
|
||||
record._parent, record.title, siteURI, Utils.makeURI(record.feedUri),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
this._log.debug("Created livemark " + newId + " under " + record._parent +
|
||||
" as " + record.title + ", " + record.siteUri + ", " +
|
||||
record.feedUri + ", GUID " + record.id);
|
||||
// Until this engine can handle asynchronous error reporting, we need to
|
||||
// detect errors on creation synchronously.
|
||||
let spinningCb = Async.makeSpinningCallback();
|
||||
|
||||
let livemarkObj = {title: record.title,
|
||||
parentId: record._parent,
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
feedURI: Utils.makeURI(record.feedUri),
|
||||
siteURI: siteURI,
|
||||
guid: record.id};
|
||||
PlacesUtils.livemarks.addLivemark(livemarkObj,
|
||||
function (aStatus, aLivemark) {
|
||||
spinningCb(null, [aStatus, aLivemark]);
|
||||
});
|
||||
|
||||
let [status, livemark] = spinningCb.wait();
|
||||
if (!Components.isSuccessCode(status)) {
|
||||
throw status;
|
||||
}
|
||||
|
||||
this._log.debug("Created livemark " + livemark.id + " under " +
|
||||
livemark.parentId + " as " + livemark.title +
|
||||
", " + livemark.siteURI.spec + ", " +
|
||||
livemark.feedURI.spec + ", GUID " +
|
||||
livemark.guid);
|
||||
break;
|
||||
case "separator":
|
||||
newId = PlacesUtils.bookmarks.insertSeparator(
|
||||
|
@ -748,8 +767,12 @@ BookmarksStore.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
this._log.trace("Setting GUID of new item " + newId + " to " + record.id);
|
||||
this._setGUID(newId, record.id);
|
||||
if (newId) {
|
||||
// Livemarks can set the GUID through the API, so there's no need to
|
||||
// do that here.
|
||||
this._log.trace("Setting GUID of new item " + newId + " to " + record.id);
|
||||
this._setGUID(newId, record.id);
|
||||
}
|
||||
},
|
||||
|
||||
// Factored out of `remove` to avoid redundant DB queries when the Places ID
|
||||
|
@ -859,12 +882,6 @@ BookmarksStore.prototype = {
|
|||
itemId, SMART_BOOKMARKS_ANNO, val, 0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
break;
|
||||
case "siteUri":
|
||||
PlacesUtils.livemarks.setSiteURI(itemId, Utils.makeURI(val));
|
||||
break;
|
||||
case "feedUri":
|
||||
PlacesUtils.livemarks.setFeedURI(itemId, Utils.makeURI(val));
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -973,7 +990,7 @@ BookmarksStore.prototype = {
|
|||
switch (PlacesUtils.bookmarks.getItemType(placeId)) {
|
||||
case PlacesUtils.bookmarks.TYPE_BOOKMARK:
|
||||
let bmkUri = PlacesUtils.bookmarks.getBookmarkURI(placeId).spec;
|
||||
if (bmkUri.search(/^place:/) == 0) {
|
||||
if (bmkUri.indexOf("place:") == 0) {
|
||||
record = new BookmarkQuery(collection, id);
|
||||
|
||||
// Get the actual tag name instead of the local itemId
|
||||
|
@ -1013,14 +1030,14 @@ BookmarksStore.prototype = {
|
|||
break;
|
||||
|
||||
case PlacesUtils.bookmarks.TYPE_FOLDER:
|
||||
if (PlacesUtils.itemIsLivemark(placeId)) {
|
||||
if (PlacesUtils.annotations
|
||||
.itemHasAnnotation(placeId, PlacesUtils.LMANNO_FEEDURI)) {
|
||||
record = new Livemark(collection, id);
|
||||
|
||||
let siteURI = PlacesUtils.livemarks.getSiteURI(placeId);
|
||||
if (siteURI != null)
|
||||
record.siteUri = siteURI.spec;
|
||||
record.feedUri = PlacesUtils.livemarks.getFeedURI(placeId).spec;
|
||||
|
||||
let as = PlacesUtils.annotations;
|
||||
record.feedUri = as.getItemAnnotation(placeId, PlacesUtils.LMANNO_FEEDURI);
|
||||
try {
|
||||
record.siteUri = as.getItemAnnotation(placeId, PlacesUtils.LMANNO_SITEURI);
|
||||
} catch (ex) {}
|
||||
} else {
|
||||
record = new BookmarkFolder(collection, id);
|
||||
}
|
||||
|
@ -1181,8 +1198,7 @@ BookmarksStore.prototype = {
|
|||
node = this._getNode(nodeID);
|
||||
}
|
||||
|
||||
if (node.type == node.RESULT_TYPE_FOLDER &&
|
||||
!PlacesUtils.itemIsLivemark(node.itemId)) {
|
||||
if (node.type == node.RESULT_TYPE_FOLDER) {
|
||||
node.QueryInterface(Ci.nsINavHistoryQueryResultNode);
|
||||
node.containerOpen = true;
|
||||
try {
|
||||
|
@ -1312,8 +1328,7 @@ BookmarksTracker.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Determine if a change should be ignored: we're ignoring everything or the
|
||||
* folder is for livemarks.
|
||||
* Determine if a change should be ignored.
|
||||
*
|
||||
* @param itemId
|
||||
* Item under consideration to ignore
|
||||
|
@ -1339,10 +1354,6 @@ BookmarksTracker.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
// Ignore livemark children.
|
||||
if (PlacesUtils.itemIsLivemark(folder))
|
||||
return true;
|
||||
|
||||
// Ignore changes to tags (folders under the tags folder).
|
||||
let tags = kSpecialIds.tags;
|
||||
if (folder == tags)
|
||||
|
@ -1423,8 +1434,7 @@ BookmarksTracker.prototype = {
|
|||
|
||||
// This method is oddly structured, but the idea is to return as quickly as
|
||||
// possible -- this handler gets called *every time* a bookmark changes, for
|
||||
// *each change*. That's particularly bad when a bunch of livemarks are
|
||||
// updated.
|
||||
// *each change*.
|
||||
onItemChanged: function BMT_onItemChanged(itemId, property, isAnno, value,
|
||||
lastModified, itemType, parentId,
|
||||
guid, parentGuid) {
|
||||
|
|
|
@ -356,7 +356,8 @@ add_test(function test_mismatched_types() {
|
|||
let oldID = store.idForGUID(oldR.id);
|
||||
_("Old ID: " + oldID);
|
||||
do_check_eq(bms.getItemType(oldID), bms.TYPE_FOLDER);
|
||||
do_check_false(PlacesUtils.livemarks.isLivemark(oldID));
|
||||
do_check_false(PlacesUtils.annotations
|
||||
.itemHasAnnotation(oldID, PlacesUtils.LMANNO_FEEDURI));
|
||||
|
||||
store.applyIncoming(newR);
|
||||
let newID = store.idForGUID(newR.id);
|
||||
|
@ -364,7 +365,8 @@ add_test(function test_mismatched_types() {
|
|||
|
||||
_("Applied new. It's a livemark.");
|
||||
do_check_eq(bms.getItemType(newID), bms.TYPE_FOLDER);
|
||||
do_check_true(PlacesUtils.livemarks.isLivemark(newID));
|
||||
do_check_true(PlacesUtils.annotations
|
||||
.itemHasAnnotation(newID, PlacesUtils.LMANNO_FEEDURI));
|
||||
|
||||
} finally {
|
||||
store.wipe();
|
||||
|
|
|
@ -50,7 +50,7 @@ const CU = Components.utils;
|
|||
CU.import("resource://tps/logger.jsm");
|
||||
CU.import("resource://gre/modules/Services.jsm");
|
||||
CU.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
|
||||
CU.import("resource://services-sync/async.js");
|
||||
|
||||
var DumpBookmarks = function TPS_Bookmarks__DumpBookmarks() {
|
||||
let writer = {
|
||||
|
@ -801,12 +801,26 @@ Livemark.prototype = {
|
|||
let siteURI = null;
|
||||
if (this.props.siteUri != null)
|
||||
siteURI = Services.io.newURI(this.props.siteUri, null, null);
|
||||
this.props.item_id = PlacesUtils.livemarks.createLivemark(
|
||||
this.props.folder_id,
|
||||
this.props.livemark,
|
||||
siteURI,
|
||||
Services.io.newURI(this.props.feedUri, null, null),
|
||||
-1);
|
||||
let livemarkObj = {parentId: this.props.folder_id,
|
||||
title: this.props.livemark,
|
||||
siteURI: siteURI,
|
||||
feedURI: Services.io.newURI(this.props.feedUri, null, null),
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX};
|
||||
|
||||
// Until this can handle asynchronous creation, we need to spin.
|
||||
let spinningCb = Async.makeSpinningCallback();
|
||||
|
||||
PlacesUtils.livemarks.addLivemark(livemarkObj,
|
||||
function (aStatus, aLivemark) {
|
||||
spinningCb(null, [aStatus, aLivemark]);
|
||||
});
|
||||
|
||||
let [status, livemark] = spinningCb.wait();
|
||||
if (!Components.isSuccessCode(status)) {
|
||||
throw status;
|
||||
}
|
||||
|
||||
this.props.item_id = livemark.id;
|
||||
return this.props.item_id;
|
||||
},
|
||||
|
||||
|
@ -828,26 +842,31 @@ Livemark.prototype = {
|
|||
this.props.folder_id,
|
||||
CI.nsINavHistoryResultNode.RESULT_TYPE_FOLDER,
|
||||
this.props.livemark);
|
||||
if (!PlacesUtils.livemarks.isLivemark(this.props.item_id)) {
|
||||
if (!PlacesUtils.annotations
|
||||
.itemHasAnnotation(this.props.item_id, PlacesUtils.LMANNO_FEEDURI)) {
|
||||
Logger.logPotentialError("livemark folder found, but it's just a regular folder, for " +
|
||||
this.toString());
|
||||
this.props.item_id = -1;
|
||||
return -1;
|
||||
}
|
||||
let feedURI = Services.io.newURI(this.props.feedUri, null, null);
|
||||
let lmFeedURI = PlacesUtils.livemarks.getFeedURI(this.props.item_id);
|
||||
if (feedURI.spec != lmFeedURI.spec) {
|
||||
let lmFeedURISpec =
|
||||
PlacesUtils.annotations.getItemAnnotation(this.props.item_id,
|
||||
PlacesUtils.LMANNO_FEEDURI);
|
||||
if (feedURI.spec != lmFeedURISpec) {
|
||||
Logger.logPotentialError("livemark feed uri not correct, expected: " +
|
||||
this.props.feedUri + ", actual: " + lmFeedURI.spec +
|
||||
this.props.feedUri + ", actual: " + lmFeedURISpec +
|
||||
" for " + this.toString());
|
||||
return -1;
|
||||
}
|
||||
if (this.props.siteUri != null) {
|
||||
let siteURI = Services.io.newURI(this.props.siteUri, null, null);
|
||||
let lmSiteURI = PlacesUtils.livemarks.getSiteURI(this.props.item_id);
|
||||
if (siteURI.spec != lmSiteURI.spec) {
|
||||
let lmSiteURISpec =
|
||||
PlacesUtils.annotations.getItemAnnotation(this.props.item_id,
|
||||
PlacesUtils.LMANNO_SITEURI);
|
||||
if (siteURI.spec != lmSiteURISpec) {
|
||||
Logger.logPotentialError("livemark site uri not correct, expected: " +
|
||||
this.props.siteUri + ", actual: " + lmSiteURI.spec + " for " +
|
||||
this.props.siteUri + ", actual: " + lmSiteURISpec + " for " +
|
||||
this.toString());
|
||||
return -1;
|
||||
}
|
||||
|
@ -859,36 +878,6 @@ Livemark.prototype = {
|
|||
return this.props.item_id;
|
||||
},
|
||||
|
||||
/**
|
||||
* SetSiteUri
|
||||
*
|
||||
* Sets the siteURI property for this livemark.
|
||||
*
|
||||
* @param siteUri the URI to set; if null, no changes are made
|
||||
* @return nothing
|
||||
*/
|
||||
SetSiteUri: function(siteUri) {
|
||||
if (siteUri) {
|
||||
let siteURI = Services.io.newURI(siteUri, null, null);
|
||||
PlacesUtils.livemarks.setSiteURI(this.props.item_id, siteURI);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* SetFeedUri
|
||||
*
|
||||
* Sets the feedURI property for this livemark.
|
||||
*
|
||||
* @param feedUri the URI to set; if null, no changes are made
|
||||
* @return nothing
|
||||
*/
|
||||
SetFeedUri: function(feedUri) {
|
||||
if (feedUri) {
|
||||
let feedURI = Services.io.newURI(feedUri, null, null);
|
||||
PlacesUtils.livemarks.setFeedURI(this.props.item_id, feedURI);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update
|
||||
*
|
||||
|
@ -902,8 +891,6 @@ Livemark.prototype = {
|
|||
"Invalid item_id during Update");
|
||||
this.SetLocation(this.updateProps.location);
|
||||
this.SetPosition(this.updateProps.position);
|
||||
this.SetSiteUri(this.updateProps.siteUri);
|
||||
this.SetFeedUri(this.updateProps.feedUri);
|
||||
this.SetTitle(this.updateProps.livemark);
|
||||
return true;
|
||||
},
|
||||
|
|
Загрузка…
Ссылка в новой задаче