1
Cu.import("resource://services-sync/engines/bookmarks.js");
2
Cu.import("resource://services-sync/engines.js");
3
Cu.import("resource://services-sync/util.js");
4
Cu.import("resource://gre/modules/PlacesUtils.jsm");
6
Engines.register(BookmarksEngine);
7
let engine = Engines.get("bookmarks");
8
let store = engine._store;
11
function test_copying_places() {
14
if (store._haveGUIDColumn) {
15
_("We have a GUID column; not testing anno GUID fixing.");
20
// Copied and simplified from PlacesUIUtils, to which we don't have easy
26
ptm = Components.classes["@mozilla.org/browser/placesTransactionsService;1"]
27
.getService(Ci.nsIPlacesTransactionsService);
29
_("Can't test transactions -- not running with a browser context.");
33
function getBookmarkItemCopyTransaction(aData, aContainer, aIndex,
34
aExcludeAnnotations) {
35
var itemURL = PlacesUtils._uri(aData.uri);
36
var itemTitle = aData.title;
37
var keyword = aData.keyword || null;
38
var annos = aData.annos || [];
39
// always exclude GUID when copying any item
40
var excludeAnnos = [PlacesUtils.GUID_ANNO];
41
if (aExcludeAnnotations)
42
excludeAnnos = excludeAnnos.concat(aExcludeAnnotations);
43
annos = annos.filter(function(aValue, aIndex, aArray) {
44
return excludeAnnos.indexOf(aValue.name) == -1;
48
childTxns.push(ptm.editItemDateAdded(null, aData.dateAdded));
49
if (aData.lastModified)
50
childTxns.push(ptm.editItemLastModified(null, aData.lastModified));
52
var tags = aData.tags.split(", ");
53
var storedTags = PlacesUtils.tagging.getTagsForURI(itemURL, {});
54
tags = tags.filter(function (aTag) {
55
return (storedTags.indexOf(aTag) == -1);
58
childTxns.push(ptm.tagURI(itemURL, tags));
61
return ptm.createItem(itemURL, aContainer, aIndex, itemTitle, keyword,
65
function getFolderCopyTransaction(aData, aContainer, aIndex) {
66
function getChildItemsTransactions(aChildren) {
67
var childItemsTransactions = [];
68
var cc = aChildren.length;
70
for (var i = 0; i < cc; ++i) {
72
var node = aChildren[i];
74
// Make sure that items are given the correct index, this will be
75
// passed by the transaction manager to the backend for the insertion.
76
// Insertion behaves differently if index == DEFAULT_INDEX (append)
77
if (aIndex != PlacesUtils.bookmarks.DEFAULT_INDEX)
80
if (node.type == PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER)
81
txn = getFolderCopyTransaction(node, aContainer, index);
82
else // (node.type == PlacesUtils.TYPE_X_MOZ_PLACE)
83
txn = getBookmarkItemCopyTransaction(node, -1, index);
86
childItemsTransactions.push(txn);
88
return childItemsTransactions;
91
// tag folders use tag transactions
92
if (aContainer == PlacesUtils.tagsFolderId) {
95
aData.children.forEach(function(aChild) {
96
txns.push(ptm.tagURI(PlacesUtils._uri(aChild.uri), [aData.title]));
99
return ptm.aggregateTransactions("addTags", txns);
102
var childItems = getChildItemsTransactions(aData.children);
104
childItems.push(ptm.editItemDateAdded(null, aData.dateAdded));
105
if (aData.lastModified)
106
childItems.push(ptm.editItemLastModified(null, aData.lastModified));
108
var annos = aData.annos || [];
109
annos = annos.filter(function(aAnno) {
110
// always exclude GUID when copying any item
111
return aAnno.name != PlacesUtils.GUID_ANNO;
113
return ptm.createFolder(aData.title, aContainer, aIndex, annos, childItems);
118
// End simplified PlacesUIUtils code.
121
let tracker = engine._tracker;
122
tracker.clearChangedIDs();
125
_("Test copying using Places transactions.");
126
Svc.Obs.notify("weave:engine:start-tracking");
128
_("Set up source and destination folders.");
129
let f1 = Svc.Bookmark.createFolder(PlacesUtils.toolbarFolderId, "Folder One",
130
Svc.Bookmark.DEFAULT_INDEX);
131
let f2 = Svc.Bookmark.createFolder(PlacesUtils.toolbarFolderId, "Folder Two",
132
Svc.Bookmark.DEFAULT_INDEX);
134
let b1 = Svc.Bookmark.insertBookmark(f1,
135
Utils.makeURI("http://example.com/"),
136
Svc.Bookmark.DEFAULT_INDEX,
139
_("F1: " + f1 + "; F2: " + f2 + "; B1: " + b1);
141
_("Fetch GUIDs so our anno exists.");
142
let f1GUID = store.GUIDForId(f1);
143
let f2GUID = store.GUIDForId(f2);
144
let b1GUID = store.GUIDForId(b1);
145
do_check_true(!!f1GUID);
146
do_check_true(!!f2GUID);
147
do_check_true(!!b1GUID);
149
_("Make sure the destination folder is empty.");
150
do_check_eq(PlacesUtils.getFolderContents(f2, false, true).root.childCount, 0);
152
let f1Node = PlacesUtils.getFolderContents(f1, false, false);
153
_("Node to copy: " + f1Node.root.itemId);
155
let serialized = PlacesUtils.wrapNode(f1Node.root, PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER);
156
_("Serialized to " + serialized);
158
let raw = PlacesUtils.unwrapNodes(serialized, PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER).shift();
159
let transaction = getFolderCopyTransaction(raw, f2, Svc.Bookmark.DEFAULT_INDEX, true);
161
_("Run the copy transaction.");
162
ptm.doTransaction(transaction);
164
_("Verify that items have been copied.");
165
let f2Node = PlacesUtils.getFolderContents(f2, false, true);
166
do_check_eq(f2Node.root.childCount, 1);
168
_("Verify that the copied folder has different GUIDs.");
169
let c0 = f2Node.root.getChild(0);
170
do_check_eq(c0.title, "Folder One");
171
do_check_neq(c0.itemId, f1);
172
do_check_neq(store.GUIDForId(c0.itemId), f1GUID);
174
_("Verify that this copied folder contains a copied bookmark with different GUIDs.");
175
c0 = c0.QueryInterface(Ci.nsINavHistoryContainerResultNode);
176
c0.containerOpen = true;
178
do_check_eq(c0.childCount, 1);
179
let b0 = c0.getChild(0);
181
do_check_eq(b0.title, "Example!");
182
do_check_eq(b0.uri, "http://example.com/");
183
do_check_neq(b0.itemId, b1);
184
do_check_neq(store.GUIDForId(b0.itemId), b1GUID);
187
tracker.clearChangedIDs();
188
Svc.Obs.notify("weave:engine:stop-tracking");
192
function test_tracking() {
193
_("Verify we've got an empty tracker to work with.");
194
let tracker = engine._tracker;
195
do_check_eq([id for (id in tracker.changedIDs)].length, 0);
197
let folder = Svc.Bookmark.createFolder(Svc.Bookmark.bookmarksMenuFolder,
199
Svc.Bookmark.DEFAULT_INDEX);
200
function createBmk() {
201
return Svc.Bookmark.insertBookmark(folder,
202
Utils.makeURI("http://getfirefox.com"),
203
Svc.Bookmark.DEFAULT_INDEX,
208
_("Create bookmark. Won't show because we haven't started tracking yet");
210
do_check_eq([id for (id in tracker.changedIDs)].length, 0);
212
_("Tell the tracker to start tracking changes.");
213
Svc.Obs.notify("weave:engine:start-tracking");
215
// We expect two changed items because the containing folder
216
// changed as well (new child).
217
do_check_eq([id for (id in tracker.changedIDs)].length, 2);
219
_("Notifying twice won't do any harm.");
220
Svc.Obs.notify("weave:engine:start-tracking");
222
do_check_eq([id for (id in tracker.changedIDs)].length, 3);
224
_("Let's stop tracking again.");
225
tracker.clearChangedIDs();
226
Svc.Obs.notify("weave:engine:stop-tracking");
228
do_check_eq([id for (id in tracker.changedIDs)].length, 0);
230
_("Notifying twice won't do any harm.");
231
Svc.Obs.notify("weave:engine:stop-tracking");
233
do_check_eq([id for (id in tracker.changedIDs)].length, 0);
238
tracker.clearChangedIDs();
239
Svc.Obs.notify("weave:engine:stop-tracking");
243
function test_onItemChanged() {
244
// Anno that's in ANNOS_TO_TRACK.
245
const GENERATOR_ANNO = "microsummary/generatorURI";
247
_("Verify we've got an empty tracker to work with.");
248
let tracker = engine._tracker;
249
do_check_eq([id for (id in tracker.changedIDs)].length, 0);
252
Svc.Obs.notify("weave:engine:stop-tracking");
253
let folder = Svc.Bookmark.createFolder(Svc.Bookmark.bookmarksMenuFolder,
255
Svc.Bookmark.DEFAULT_INDEX);
256
_("Track changes to annos.");
257
let b = Svc.Bookmark.insertBookmark(folder,
258
Utils.makeURI("http://getfirefox.com"),
259
Svc.Bookmark.DEFAULT_INDEX,
261
let bGUID = engine._store.GUIDForId(b);
262
_("New item is " + b);
265
Svc.Obs.notify("weave:engine:start-tracking");
266
Svc.Annos.setItemAnnotation(b, GENERATOR_ANNO, "http://foo.bar/", 0,
267
Svc.Annos.EXPIRE_NEVER);
268
do_check_true(tracker.changedIDs[bGUID] > 0);
273
tracker.clearChangedIDs();
274
Svc.Obs.notify("weave:engine:stop-tracking");
278
function run_test() {
279
initTestLogging("Trace");
281
Log4Moz.repository.getLogger("Engine.Bookmarks").level = Log4Moz.Level.Trace;
282
Log4Moz.repository.getLogger("Store.Bookmarks").level = Log4Moz.Level.Trace;
283
Log4Moz.repository.getLogger("Tracker.Bookmarks").level = Log4Moz.Level.Trace;
285
test_onItemChanged();
286
test_copying_places();