Bug 376004 - Places Transactions must not live in the window global scope. patch by Steve Won and me.

This commit is contained in:
mozilla.mano%sent.com 2007-07-15 09:44:58 +00:00
Родитель d994a56024
Коммит f0cb98ced8
11 изменённых файлов: 1566 добавлений и 884 удалений

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

@ -710,7 +710,7 @@ var BookmarkPropertiesPanel = {
*/
_getEditTitleTransaction:
function BPP__getEditTitleTransaction(aItemId, aNewTitle) {
return new PlacesEditItemTitleTransaction(aItemId, aNewTitle);
return PlacesUtils.ptm.editItemTitle(aItemId, aNewTitle);
},
/**
@ -806,13 +806,13 @@ var BookmarkPropertiesPanel = {
// location
var url = PlacesUtils._uri(this._element("editURLBar").value);
if (!this._bookmarkURI.equals(url))
transactions.push(new PlacesEditBookmarkURITransaction(itemId, url));
transactions.push(PlacesUtils.ptm.editBookmarkURI(itemId, url));
// keyword transactions
var newKeyword = this._element("keywordTextfield").value;
if (newKeyword != this._bookmarkKeyword) {
transactions.push(
new PlacesEditBookmarkKeywordTransaction(itemId, newKeyword));
transactions.push(PlacesUtils.ptm.
editBookmarkKeyword(itemId, newKeyword));
}
// microsummaries
@ -828,15 +828,14 @@ var BookmarkPropertiesPanel = {
(newMicrosummary != null &&
!this._mss.isMicrosummary(itemId, newMicrosummary))) {
transactions.push(
new PlacesEditBookmarkMicrosummaryTransaction(itemId,
newMicrosummary));
PlacesUtils.ptm.editBookmarkMicrosummary(itemId, newMicrosummary));
}
// load in sidebar
var loadInSidebarChecked = this._element("loadInSidebarCheckbox").checked;
if (loadInSidebarChecked != this._loadBookmarkInSidebar) {
transactions.push(
new PlacesSetLoadInSidebarTransaction(itemId, loadInSidebarChecked));
PlacesUtils.ptm.setLoadInSidebar(itemId, loadInSidebarChecked));
}
}
else if (this._itemType == LIVEMARK_CONTAINER) {
@ -844,7 +843,7 @@ var BookmarkPropertiesPanel = {
var feedURI = PlacesUtils._uri(feedURIString);
if (!this._feedURI.equals(feedURI)) {
transactions.push(
new PlacesEditLivemarkFeedURITransaction(this._folderId, feedURI));
PlacesUtils.ptm.editLivemarkFeedURI(this._folderId, feedURI));
}
// Site Location is empty, we can set its URI to null
@ -856,7 +855,7 @@ var BookmarkPropertiesPanel = {
if ((!newSiteURI && this._siteURI) ||
(newSiteURI && (!this._siteURI || !this._siteURI.equals(newSiteURI)))) {
transactions.push(
new PlacesEditLivemarkSiteURITransaction(this._folderId, newSiteURI));
PlacesUtils.ptm.editLivemarkSiteURI(this._folderId, newSiteURI));
}
}
@ -865,7 +864,7 @@ var BookmarkPropertiesPanel = {
if (transactions.length > 0) {
window.arguments[0].performed = true;
var aggregate =
new PlacesAggregateTransaction(this._getDialogTitle(), transactions);
PlacesUtils.ptm.aggregateTransactions(this._getDialogTitle(), transactions);
this._tm.doTransaction(aggregate);
}
},
@ -911,20 +910,20 @@ var BookmarkPropertiesPanel = {
var microsummary = this._element("namePicker").selectedItem.microsummary;
if (microsummary) {
childTransactions.push(
new PlacesEditBookmarkMicrosummaryTransaction(-1, microsummary));
PlacesUtils.ptm.editBookmarkMicrosummary(-1, microsummary));
}
var transactions = [new PlacesCreateItemTransaction(uri, aContainer, aIndex,
var transactions = [PlacesUtils.ptm.createItem(uri, aContainer, aIndex,
title, keyword,
annotations,
childTransactions)];
if (this._postData) {
transactions.push(new PlacesEditURIPostDataTransaction(uri,
this._postData));
transactions.push(
PlacesUtils.ptm.editURIPostData(uri, this._postData));
}
return new PlacesAggregateTransaction(this._getDialogTitle(),
transactions);
return PlacesUtils.ptm.aggregateTransactions(this._getDialogTitle(), transactions);
},
/**
@ -936,7 +935,7 @@ var BookmarkPropertiesPanel = {
for (var i = 0; i < this._URIList.length; ++i) {
var uri = this._URIList[i];
var title = this._getURITitleFromHistory(uri);
transactions.push(new PlacesCreateItemTransaction(uri, -1, -1, title));
transactions.push(PlacesUtils.ptm.createItem(uri, -1, -1, title));
}
return transactions;
},
@ -956,9 +955,8 @@ var BookmarkPropertiesPanel = {
if (description)
annotations.push(this._getDescriptionAnnotation(description));
return new PlacesCreateFolderTransaction(folderName, aContainer, aIndex,
annotations,
childItemsTransactions);
return PlacesUtils.ptm.createFolder(folderName, aContainer, aIndex,
annotations, childItemsTransactions);
},
/**
@ -976,9 +974,8 @@ var BookmarkPropertiesPanel = {
siteURI = PlacesUtils._uri(siteURIString);
var name = this._element("namePicker").value;
return new PlacesCreateLivemarkTransaction(feedURI, siteURI,
name, aContainer,
aIndex);
return PlacesUtils.ptm.createLivemark(feedURI, siteURI, name,
aContainer, aIndex);
},
/**

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

@ -993,8 +993,8 @@ PlacesController.prototype = {
var ip = this._view.insertionPoint;
if (!ip)
throw Cr.NS_ERROR_NOT_AVAILABLE;
var txn = new PlacesCreateSeparatorTransaction(ip.itemId, ip.index);
PlacesUtils.tm.doTransaction(txn);
var txn = PlacesUtils.ptm.createSeparator(ip.itemId, ip.index);
PlacesUtils.ptm.commitTransaction(txn);
},
/**
@ -1011,9 +1011,9 @@ PlacesController.prototype = {
*/
sortFolderByName: function PC_sortFolderByName() {
var selectedNode = this._view.selectedNode;
var txn = new PlacesSortFolderByNameTransaction(selectedNode.itemId,
var txn = PlacesUtils.ptm.sortFolderByName(selectedNode.itemId,
selectedNode.bookmarkIndex);
PlacesUtils.tm.doTransaction(txn);
PlacesUtils.ptm.commitTransaction(txn);
},
/**
@ -1021,11 +1021,11 @@ PlacesController.prototype = {
*/
setBookmarksToolbarFolder: function PC_setBookmarksToolbarFolder() {
if (!this._view.hasSingleSelection)
return false;
return;
var selectedNode = this._view.selectedNode;
var txn = new PlacesSetBookmarksToolbarTransaction(selectedNode.itemId);
PlacesUtils.tm.doTransaction(txn);
return true;
var txn = PlacesUtils.ptm.setBookmarksToolbar(selectedNode.itemId);
PlacesUtils.ptm.commitTransaction(txn);
},
@ -1068,14 +1068,13 @@ PlacesController.prototype = {
/**
* Creates a set of transactions for the removal of a range of items.
* A range is an array of adjacent nodes in a view.
* @param range
* @param [in] range
* An array of nodes to remove. Should all be adjacent.
* @param transactions
* @param [out] transactions
* An array of transactions.
*/
_removeRange: function PC__removeRange(range, transactions) {
NS_ASSERT(transactions instanceof Array, "Must pass a transactions array");
var index = PlacesUtils.getIndexOfNode(range[0]);
var removedFolders = [];
@ -1084,28 +1083,10 @@ PlacesController.prototype = {
if (this._shouldSkipNode(node, removedFolders))
continue;
if (PlacesUtils.nodeIsFolder(node)) {
// TODO -- node.parent might be a query and not a folder. See bug 324948
var folder = node;
removedFolders.push(folder);
transactions.push(new PlacesRemoveFolderTransaction(folder.itemId));
}
else if (PlacesUtils.nodeIsSeparator(node)) {
// A Bookmark separator.
transactions.push(new PlacesRemoveSeparatorTransaction(node.itemId,
node.parent.itemId, index));
}
else if (PlacesUtils.nodeIsFolder(node.parent)) {
// A Bookmark in a Bookmark Folder.
transactions.push(new PlacesRemoveItemTransaction(node.itemId,
PlacesUtils._uri(node.uri), node.parent.itemId, index));
}
else if (PlacesUtils.nodeIsBookmark(node)) {
// A Bookmark in a query.
var folderId = PlacesUtils.bookmarks.getFolderIdForItem(node.itemId);
transactions.push(new PlacesRemoveItemTransaction(node.itemId,
PlacesUtils._uri(node.uri), folderId, index));
}
if (PlacesUtils.nodeIsFolder(node))
removedFolders.push(node);
transactions.push(PlacesUtils.ptm.removeItem(node.itemId));
}
},
@ -1122,8 +1103,8 @@ PlacesController.prototype = {
for (var i = ranges.length - 1; i >= 0 ; --i)
this._removeRange(ranges[i], transactions);
if (transactions.length > 0) {
var txn = new PlacesAggregateTransaction(txnName, transactions);
PlacesUtils.tm.doTransaction(txn);
var txn = PlacesUtils.ptm.aggregateTransactions(txnName, transactions);
PlacesUtils.ptm.commitTransaction(txn);
}
},
@ -1379,8 +1360,8 @@ PlacesController.prototype = {
var transactions = getTransactions([PlacesUtils.TYPE_X_MOZ_PLACE,
PlacesUtils.TYPE_X_MOZ_URL,
PlacesUtils.TYPE_UNICODE]);
var txn = new PlacesAggregateTransaction("Paste", transactions);
PlacesUtils.tm.doTransaction(txn);
var txn = PlacesUtils.ptm.aggregateTransactions("Paste", transactions);
PlacesUtils.ptm.commitTransaction(txn);
}
};
@ -1513,781 +1494,8 @@ var PlacesControllerDragHelper = {
insertionPoint.index, copy));
}
var txn = new PlacesAggregateTransaction("DropItems", transactions);
PlacesUtils.tm.doTransaction(txn);
}
};
/**
* Method and utility stubs for Place Edit Transactions
*/
function PlacesBaseTransaction() {
}
PlacesBaseTransaction.prototype = {
utils: PlacesUtils,
bookmarks: Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService),
_livemarks: null,
get livemarks() {
if (!this._livemarks) {
this._livemarks =
Cc["@mozilla.org/browser/livemark-service;2"].
getService(Ci.nsILivemarkService);
}
return this._livemarks;
},
// The minimum amount of transactions we should tell our observers to begin
// batching (rather than letting them do incremental drawing).
MIN_TRANSACTIONS_FOR_BATCH: 5,
LOG: LOG,
redoTransaction: function PIT_redoTransaction() {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
get isTransient() {
return false;
},
merge: function PIT_merge(transaction) {
return false;
}
};
/**
* Performs several Places Transactions in a single batch.
*/
function PlacesAggregateTransaction(name, transactions) {
this._transactions = transactions;
this._name = name;
this.container = -1;
this.redoTransaction = this.doTransaction;
}
PlacesAggregateTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PAT_doTransaction() {
this.LOG("== " + this._name + " (Aggregate) ==============");
if (this._transactions.length >= this.MIN_TRANSACTIONS_FOR_BATCH) {
var callback = {
_self: this,
runBatched: function() {
this._self.commit(false);
}
};
this.utils.bookmarks.runInBatchMode(callback, null);
}
else
this.commit(false);
this.LOG("== " + this._name + " (Aggregate Ends) =========");
},
undoTransaction: function PAT_undoTransaction() {
this.LOG("== UN" + this._name + " (UNAggregate) ============");
if (this._transactions.length >= this.MIN_TRANSACTIONS_FOR_BATCH) {
var callback = {
_self: this,
runBatched: function() {
this._self.commit(true);
}
};
this.utils.bookmarks.runInBatchMode(callback, null);
}
else
this.commit(true);
this.LOG("== UN" + this._name + " (UNAggregate Ends) =======");
},
commit: function PAT_commit(aUndo) {
for (var i = 0; i < this._transactions.length; ++i) {
var txn = this._transactions[i];
if (this.container > -1)
txn.container = this.container;
if (aUndo)
txn.undoTransaction();
else
txn.doTransaction();
}
}
};
/**
* Transaction for creating a new folder item.
*
* @param aName
* the name of the new folder
* @param aContainer
* the identifier of the folder in which the new folder should be
* added.
* @param [optional] aIndex
* the index of the item in aContainer, pass -1 or nothing to create
* the item at the end of aContainer.
* @param [optional] aAnnotations
* the annotations to set for the new folder.
* @param [optional] aChildItemsTransactions
* array of transactions for items to be created under the new folder.
*/
function PlacesCreateFolderTransaction(aName, aContainer, aIndex,
aAnnotations, aChildItemsTransactions) {
this._name = aName;
this._container = aContainer;
this._index = typeof(aIndex) == "number" ? aIndex : -1;
this._annotations = aAnnotations;
this._id = null;
this._childItemsTransactions = aChildItemsTransactions || [];
this.redoTransaction = this.doTransaction;
}
PlacesCreateFolderTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
// childItemsTransaction support
get container() { return this._container; },
set container(val) { return this._container = val; },
doTransaction: function PCFT_doTransaction() {
var bookmarks = this.utils.bookmarks;
this._id = bookmarks.createFolder(this._container, this._name, this._index);
if (this._annotations.length > 0)
this.utils.setAnnotationsForItem(this._id, this._annotations);
for (var i = 0; i < this._childItemsTransactions.length; ++i) {
var txn = this._childItemsTransactions[i];
txn.container = this._id;
txn.doTransaction();
}
},
undoTransaction: function PCFT_undoTransaction() {
this.bookmarks.removeFolder(this._id);
for (var i = 0; i < this._childItemsTransactions.length; ++i) {
var txn = this.childItemsTransactions[i];
txn.undoTransaction();
}
}
};
/**
* Transaction for creating a new bookmark item
*
* @param aURI
* the uri of the new bookmark (nsIURI)
* @param aContainer
* the identifier of the folder in which the bookmark should be added.
* @param [optional] aIndex
* the index of the item in aContainer, pass -1 or nothing to create
* the item at the end of aContainer.
* @param [optional] aTitle
* the title of the new bookmark.
* @param [optional] aKeyword
* the keyword of the new bookmark.
* @param [optional] aAnnotations
* the annotations to set for the new bookmark.
* @param [optional] aChildTransactions
* child transactions to commit after creating the bookmark. Prefer
* using any of the arguments above if possible. In general, a child
* transations should be used only if the change it does has to be
* reverted manually when removing the bookmark item.
* a child transaction must support setting its bookmark-item
* identifier via an "id" js setter.
*/
function PlacesCreateItemTransaction(aURI, aContainer, aIndex, aTitle,
aKeyword, aAnnotations,
aChildTransactions) {
this._uri = aURI;
this._container = aContainer;
this._index = typeof(aIndex) == "number" ? aIndex : -1;
this._title = aTitle;
this._keyword = aKeyword;
this._annotations = aAnnotations;
this._childTransactions = aChildTransactions || [];
this.redoTransaction = this.doTransaction;
}
PlacesCreateItemTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
// childItemsTransactions support for the create-folder transaction
get container() { return this._container; },
set container(val) { return this._container = val; },
doTransaction: function PCIT_doTransaction() {
var bookmarks = this.utils.bookmarks;
this._id = bookmarks.insertBookmark(this.container, this._uri, this._index,
this._title);
if (this._keyword)
bookmarks.setKeywordForBookmark(this._id, this._keyword);
if (this._annotations && this._annotations.length > 0)
this.utils.setAnnotationsForItem(this._id, this._annotations);
for (var i = 0; i < this._childTransactions.length; ++i) {
var txn = this._childTransactions[i];
txn.id = this._id;
txn.doTransaction();
}
},
undoTransaction: function PCIT_undoTransaction() {
this.utils.bookmarks.removeItem(this._id);
for (var i = 0; i < this._childTransactions.length; ++i) {
var txn = this._childTransactions[i];
txn.undoTransaction();
}
}
};
/**
* Transaction for creating a new separator item
*
* @param aContainer
* the identifier of the folder in which the separator should be
* added.
* @param [optional] aIndex
* the index of the item in aContainer, pass -1 or nothing to create
* the separator at the end of aContainer.
*/
function PlacesCreateSeparatorTransaction(aContainer, aIndex) {
this._container = aContainer;
this._index = typeof(aIndex) == "number" ? aIndex : -1;
this._id = null;
}
PlacesCreateSeparatorTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
// childItemsTransaction support
get container() { return this._container; },
set container(val) { return this._container = val; },
doTransaction: function PCST_doTransaction() {
this.LOG("Create separator in: " + this.container + "," + this._index);
this._id = this.bookmarks.insertSeparator(this.container, this._index);
},
undoTransaction: function PCST_undoTransaction() {
this.LOG("UNCreate separator from: " + this.container + "," + this._index);
this.bookmarks.removeChildAt(this.container, this._index);
}
};
/**
* Transaction for creating a new live-bookmark item.
*
* @see nsILivemarksService::createLivemark for documentation regarding the
* first three arguments.
*
* @param aContainer
* the identifier of the folder in which the live-bookmark should be
* added.
* @param [optional] aIndex
* the index of the item in aContainer, pass -1 or nothing to create
* the item at the end of aContainer.
* @param [optional] aAnnotations
* the annotations to set for the new live-bookmark.
*/
function PlacesCreateLivemarkTransaction(aFeedURI, aSiteURI, aName,
aContainer, aIndex, aAnnotations) {
this._feedURI = aFeedURI;
this._siteURI = aSiteURI;
this._name = aName;
this._container = aContainer;
this._index = typeof(aIndex) == "number" ? aIndex : -1;
this._annotations = aAnnotations;
}
PlacesCreateLivemarkTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
// childItemsTransaction support
get container() { return this._container; },
set container(val) { return this._container = val; },
doTransaction: function PCLT_doTransaction() {
this._id = this.utils.livemarks
.createLivemark(this._container, this._name, this._siteURI,
this._feedURI, this._index);
if (this._annotations)
this.utils.setAnnotationsForItem(this._id, this._annotations);
},
undoTransaction: function PCLT_undoTransaction() {
this.bookmarks.removeFolder(this._id);
}
};
/**
* Move an Item
*/
function PlacesMoveItemTransaction(aItemId, aNewContainer, aNewIndex) {
NS_ASSERT(!isNaN(aItemId + aNewContainer + aNewIndex), "Parameter is NaN!");
NS_ASSERT(aNewIndex >= -1, "invalid insertion index");
this._id = aItemId;
this._oldContainer = this.utils.bookmarks.getFolderIdForItem(this._id);
this._oldIndex = this.utils.bookmarks.getItemIndex(this._id);
NS_ASSERT(this._oldContainer > 0 && this._oldIndex >= 0, "invalid item");
this._newContainer = aNewContainer;
this._newIndex = aNewIndex;
this.redoTransaction = this.doTransaction;
}
PlacesMoveItemTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PMIT_doTransaction() {
this.bookmarks.moveItem(this._id, this._newContainer, this._newIndex);
},
undoTransaction: function PMIT_undoTransaction() {
this.bookmarks.moveItem(this._id, this._oldContainer, this._oldIndex);
}
};
/**
* Remove a Folder
* This is a little complicated. When we remove a container we need to remove
* all of its children. We can't just repurpose our existing transactions for
* this since they cache their parent container id. Since the folder structure
* is being removed, this id is being destroyed and when it is re-created will
* likely have a different id.
*/
function PlacesRemoveFolderTransaction(id) {
this._removeTxn = this.bookmarks.getRemoveFolderTransaction(id);
this._id = id;
this._transactions = []; // A set of transactions to remove content.
this.redoTransaction = this.doTransaction;
}
PlacesRemoveFolderTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
/**
* Create a flat, ordered list of transactions for a depth-first recreation
* of items within this folder.
*/
_saveFolderContents: function PRFT__saveFolderContents() {
this._transactions = [];
var contents = this.utils.getFolderContents(this._id, false, false).root;
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
for (var i = 0; i < contents.childCount; ++i) {
var child = contents.getChild(i);
var txn;
if (child.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER) {
txn = new PlacesRemoveFolderTransaction(child.itemId);
}
else if (child.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
txn = new PlacesRemoveSeparatorTransaction(child.itemId, this._id, i);
}
else {
txn = new PlacesRemoveItemTransaction(child.itemId,
ios.newURI(child.uri, null, null),
this._id, i);
}
this._transactions.push(txn);
}
},
doTransaction: function PRFT_doTransaction() {
this._title = this.bookmarks.getItemTitle(this._id);
this._annotations = this.utils.getAnnotationsForItem(this._id);
this.LOG("Remove Folder: " + this._title);
this._saveFolderContents();
// Remove children backwards to preserve parent-child relationships.
for (var i = this._transactions.length - 1; i >= 0; --i)
this._transactions[i].doTransaction();
// Remove this folder itself.
this._removeTxn.doTransaction();
},
undoTransaction: function PRFT_undoTransaction() {
this._removeTxn.undoTransaction();
this.LOG("UNRemove Folder: " + this._title);
// Repopulate annotations
if (this._annotations && this._annotations.length > 0)
this.utils.setAnnotationsForItem(this._id, this._annotations);
// Create children forwards to preserve parent-child relationships.
for (var i = 0; i < this._transactions.length; ++i)
this._transactions[i].undoTransaction();
}
};
/**
* Remove an Item
*/
function PlacesRemoveItemTransaction(id, uri, oldContainer, oldIndex) {
this._id = id;
this._uri = uri;
this._oldContainer = oldContainer;
this._oldIndex = oldIndex;
this._annotations = [];
this.redoTransaction = this.doTransaction;
}
PlacesRemoveItemTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PRIT_doTransaction() {
this.LOG("Remove Item: " + this._uri.spec + " from: " + this._oldContainer + "," + this._oldIndex);
this._title = this.bookmarks.getItemTitle(this._id);
this._annotations = this.utils.getAnnotationsForItem(this._id);
this.utils.bookmarks.removeItem(this._id);
},
undoTransaction: function PRIT_undoTransaction() {
this.LOG("UNRemove Item: " + this._uri.spec + " from: " + this._oldContainer + "," + this._oldIndex);
this._id = this.bookmarks.insertBookmark(this._oldContainer, this._uri,
this._oldIndex, this._title);
this.utils.setAnnotationsForItem(this._id, this._annotations);
}
};
/**
* Remove a separator
*/
function PlacesRemoveSeparatorTransaction(id, oldContainer, oldIndex) {
this._id = id;
this._oldContainer = oldContainer;
this._oldIndex = oldIndex;
this.redoTransaction = this.doTransaction;
}
PlacesRemoveSeparatorTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PRST_doTransaction() {
this.LOG("Remove Separator from: " + this._oldContainer + "," + this._oldIndex);
this.utils.bookmarks.removeItem(this._id);
},
undoTransaction: function PRST_undoTransaction() {
this.LOG("UNRemove Separator from: " + this._oldContainer + "," + this._oldIndex);
this.bookmarks.insertSeparator(this._oldContainer, this._oldIndex);
}
};
/**
* Edit a bookmark's title.
*/
function PlacesEditItemTitleTransaction(id, newTitle) {
this._id = id;
this._newTitle = newTitle;
this._oldTitle = "";
this.redoTransaction = this.doTransaction;
}
PlacesEditItemTitleTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PEITT_doTransaction() {
this._oldTitle = this.bookmarks.getItemTitle(this._id);
this.bookmarks.setItemTitle(this._id, this._newTitle);
},
undoTransaction: function PEITT_undoTransaction() {
this.bookmarks.setItemTitle(this._id, this._oldTitle);
}
};
/**
* Edit a bookmark's uri.
*/
function PlacesEditBookmarkURITransaction(aBookmarkId, aNewURI) {
this._id = aBookmarkId;
this._newURI = aNewURI;
this.redoTransaction = this.doTransaction;
}
PlacesEditBookmarkURITransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PEBUT_doTransaction() {
this._oldURI = this.bookmarks.getBookmarkURI(this._id);
this.bookmarks.changeBookmarkURI(this._id, this._newURI);
},
undoTransaction: function PEBUT_undoTransaction() {
this.bookmarks.changeBookmarkURI(this._id, this._oldURI);
}
};
/**
* Set/Unset Load-in-sidebar annotation
*/
function PlacesSetLoadInSidebarTransaction(aBookmarkId, aLoadInSidebar) {
this.id = aBookmarkId;
this._loadInSidebar = aLoadInSidebar;
this.redoTransaction = this.doTransaction;
}
PlacesSetLoadInSidebarTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
_anno: {
name: LOAD_IN_SIDEBAR_ANNO,
type: Ci.nsIAnnotationService.TYPE_INT32,
value: 1,
flags: 0,
expires: Ci.nsIAnnotationService.EXPIRE_NEVER
},
doTransaction: function PSLIST_doTransaction() {
this._wasSet = this.utils.annotations
.itemHasAnnotation(this.id, this._anno.name);
if (this._loadInSidebar) {
this.utils.setAnnotationsForItem(this.id, [this._anno]);
}
else {
try {
this.utils.annotations.removeItemAnnotation(this.id, this._anno.name);
} catch(ex) { }
}
},
undoTransaction: function PSLIST_undoTransaction() {
if (this._wasSet != this._loadInSidebar) {
this._loadInSidebar = !this._loadInSidebar;
this.doTransaction();
}
}
};
/**
* Edit a the description of a bookmark or a folder
*
*/
function PlacesEditItemDescriptionTransaction(aItemId, aDescription) {
this.id = aItemId;
this._newDescription = aDescription;
this.redoTransaction = this.doTransaction;
}
PlacesEditItemDescriptionTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
_oldDescription: "",
DESCRIPTION_ANNO: DESCRIPTION_ANNO,
nsIAnnotationService: Components.interfaces.nsIAnnotationService,
doTransaction: function PSLIST_doTransaction() {
const annos = this.utils.annotations;
if (annos.itemHasAnnotation(this.id, this.DESCRIPTION_ANNO)) {
this._oldDescription =
annos.getItemAnnotation(this.id, this.DESCRIPTION_ANNO);
}
if (this._newDescription) {
annos.setItemAnnotation(this.id, this.DESCRIPTION_ANNO,
this._newDescription, 0,
this.nsIAnnotationService.EXPIRE_NEVER);
}
else if (this._oldDescription)
annos.removeItemAnnotation(this.id, this.DESCRIPTION_ANNO);
},
undoTransaction: function PSLIST_undoTransaction() {
const annos = this.utils.annotations;
if (this._oldDescription) {
annos.setItemAnnotation(this.id, this.DESCRIPTION_ANNO,
this._oldDescription, 0,
this.nsIAnnotationService.EXPIRE_NEVER);
}
else if (annos.itemHasAnnotation(this.id, this.DESCRIPTION_ANNO))
annos.removeItemAnnotation(this.id, this.DESCRIPTION_ANNO);
}
};
/**
* Edit a bookmark's keyword.
*/
function PlacesEditBookmarkKeywordTransaction(id, newKeyword) {
this.id = id;
this._newKeyword = newKeyword;
this._oldKeyword = "";
this.redoTransaction = this.doTransaction;
}
PlacesEditBookmarkKeywordTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PEBKT_doTransaction() {
this._oldKeyword = this.bookmarks.getKeywordForBookmark(this.id);
this.bookmarks.setKeywordForBookmark(this.id, this._newKeyword);
},
undoTransaction: function PEBKT_undoTransaction() {
this.bookmarks.setKeywordForBookmark(this.id, this._oldKeyword);
}
};
/**
* Edit the post data associated with a URI
*/
function PlacesEditURIPostDataTransaction(aURI, aPostData) {
this._uri = aURI;
this._newPostData = aPostData;
this._oldPostData = null;
this.redoTransaction = this.doTransaction;
}
PlacesEditURIPostDataTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PEUPDT_doTransaction() {
this._oldPostData = this.utils.getPostDataForURI(this._uri);
this.utils.setPostDataForURI(this._uri, this._newPostData);
},
undoTransaction: function PEUPDT_undoTransaction() {
this.utils.setPostDataForURI(this._uri, this._oldPostData);
}
};
/**
* Edit a live bookmark's site URI.
*/
function PlacesEditLivemarkSiteURITransaction(folderId, uri) {
this._folderId = folderId;
this._newURI = uri;
this._oldURI = null;
this.redoTransaction = this.doTransaction;
}
PlacesEditLivemarkSiteURITransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PELSUT_doTransaction() {
this._oldURI = this.livemarks.getSiteURI(this._folderId);
this.livemarks.setSiteURI(this._folderId, this._newURI);
},
undoTransaction: function PELSUT_undoTransaction() {
this.livemarks.setSiteURI(this._folderId, this._oldURI);
}
};
/**
* Edit a live bookmark's feed URI.
*/
function PlacesEditLivemarkFeedURITransaction(folderId, uri) {
this._folderId = folderId;
this._newURI = uri;
this._oldURI = null;
this.redoTransaction = this.doTransaction;
}
PlacesEditLivemarkFeedURITransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PELFUT_doTransaction() {
this._oldURI = this.livemarks.getFeedURI(this._folderId);
this.livemarks.setFeedURI(this._folderId, this._newURI);
this.livemarks.reloadLivemarkFolder(this._folderId);
},
undoTransaction: function PELFUT_undoTransaction() {
this.livemarks.setFeedURI(this._folderId, this._oldURI);
this.livemarks.reloadLivemarkFolder(this._folderId);
}
};
/**
* Edit a bookmark's microsummary.
*/
function PlacesEditBookmarkMicrosummaryTransaction(aID, newMicrosummary) {
this.id = aID;
this._newMicrosummary = newMicrosummary;
this._oldMicrosummary = null;
this.redoTransaction = this.doTransaction;
}
PlacesEditBookmarkMicrosummaryTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
mss: PlacesUtils.microsummaries,
doTransaction: function PEBMT_doTransaction() {
this._oldMicrosummary = this.mss.getMicrosummary(this.id);
if (this._newMicrosummary)
this.mss.setMicrosummary(this.id, this._newMicrosummary);
else
this.mss.removeMicrosummary(this.id);
},
undoTransaction: function PEBMT_undoTransaction() {
if (this._oldMicrosummary)
this.mss.setMicrosummary(this.id, this._oldMicrosummary);
else
this.mss.removeMicrosummary(this.id);
}
};
/**
* Sort a folder by name
*/
function PlacesSortFolderByNameTransaction(aFolderId, aFolderIndex) {
this._folderId = aFolderId;
this._folderIndex = aFolderIndex;
this._oldOrder = null,
this.redoTransaction = this.doTransaction;
}
PlacesSortFolderByNameTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PSSFBN_doTransaction() {
this._oldOrder = [];
var contents = this.utils.getFolderContents(this._folderId, false, false).root;
var count = contents.childCount;
// sort between separators
var newOrder = [];
var preSep = []; // temporary array for sorting each group of items
var sortingMethod =
function (a, b) { return a.title.localeCompare(b.title); };
for (var i = 0; i < count; ++i) {
var item = contents.getChild(i);
this._oldOrder[item.itemId] = i;
if (this.utils.nodeIsSeparator(item)) {
if (preSep.length > 0) {
preSep.sort(sortingMethod);
newOrder = newOrder.concat(preSep);
preSep.splice(0);
}
newOrder.push(item);
}
else
preSep.push(item);
}
if (preSep.length > 0) {
preSep.sort(sortingMethod);
newOrder = newOrder.concat(preSep);
}
// set the nex indexs
for (var i = 0; i < count; ++i) {
this.bookmarks.setItemIndex(newOrder[i].itemId, i);
}
},
undoTransaction: function PSSFBN_undoTransaction() {
for (item in this._oldOrder)
this.bookmarks.setItemIndex(item, this._oldOrder[item]);
}
};
/**
* Set the bookmarks toolbar folder.
*/
function PlacesSetBookmarksToolbarTransaction(aFolderId) {
this._folderId = aFolderId;
this._oldFolderId = this.utils.toolbarFolder;
this.redoTransaction = this.doTransaction;
}
PlacesSetBookmarksToolbarTransaction.prototype = {
__proto__: PlacesBaseTransaction.prototype,
doTransaction: function PSBTT_doTransaction() {
this.utils.bookmarks.toolbarFolder = this._folderId;
},
undoTransaction: function PSBTT_undoTransaction() {
this.utils.bookmarks.toolbarFolder = this._oldFolderId;
var txn = PlacesUtils.ptm.aggregateTransactions("DropItems", transactions);
PlacesUtils.ptm.commitTransaction(txn);
}
};

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

@ -20,6 +20,7 @@
*
* Contributor(s):
* Asaf Romano <mano@mozilla.com>
* Sungjoon Steve Won <stevewon@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -72,11 +73,11 @@ var gMoveBookmarksDialog = {
continue;
transactions.push(new
PlacesMoveItemTransaction(this._nodes[i].itemId, selectedFolderID, -1));
PlacesUtils.txn.moveItem(this._nodes[i].itemId, selectedFolderId, -1));
}
if (transactions.length != 0) {
var txn = new PlacesAggregateTransaction("Move Items", transactions);
var txn = PlacesUtils.ptm.aggregateTransactions("Move Items", transactions);
this._tm.doTransaction(txn);
}
},

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

@ -22,6 +22,7 @@
* Ben Goodger <beng@google.com>
* Myk Melez <myk@mozilla.org>
* Asaf Romano <mano@mozilla.com>
* Sungjoon Steve Won <stevewon@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -164,16 +165,17 @@ var PlacesUtils = {
return this._localStore;
},
/**
* The Transaction Manager for this window.
*/
_tm: null,
get tm() {
if (!this._tm) {
this._tm = Cc["@mozilla.org/transactionmanager;1"].
createInstance(Ci.nsITransactionManager);
return this.ptm.transactionManager;
},
_ptm: null,
get ptm() {
if (!this._ptm) {
this._ptm = Cc["@mozilla.org/browser/placesTransactionsService;1"].
getService(Components.interfaces.nsIPlacesTransactionsService);
}
return this._tm;
return this._ptm;
},
/**
@ -628,9 +630,8 @@ var PlacesUtils = {
* @returns A nsITransaction object that performs the copy.
*/
_getURIItemCopyTransaction: function (aData, aContainer, aIndex) {
var itemURL = this._uri(aData.uri);
return new PlacesCreateItemTransaction(itemURL, aContainer,
aIndex, aData.title);
return this.ptm.createItem(this._uri(aData.uri), aContainer, aIndex,
aData.title, "");
},
/**
@ -661,10 +662,8 @@ var PlacesUtils = {
});
}
var createTxn =
new PlacesCreateItemTransaction(itemURL, aContainer, aIndex, itemTitle,
keyword, annos);
return createTxn;
return this.ptm.createItem(itemURL, aContainer, aIndex, itemTitle, keyword,
annos);
},
/**
@ -701,18 +700,18 @@ var PlacesUtils = {
var annos = node.folder.annos;
var folderItemsTransactions =
getChildItemsTransactions(node.children);
txn = new PlacesCreateFolderTransaction(title, -1, index, annos,
txn = this.ptm.createFolder(title, -1, aIndex, annos,
folderItemsTransactions);
}
else { // node is a livemark
var feedURI = self._uri(node.uri.feed);
var siteURI = self._uri(node.uri.site);
txn = new PlacesCreateLivemarkTransaction(feedURI, siteURI,
node.title, aContainer, index, node.annos);
txn = this.ptm.createLivemark(feedURI, siteURI, node.title,
aContainer, index, node.annos);
}
}
else if (node.type == self.TYPE_X_MOZ_PLACE_SEPARATOR)
txn = new PlacesCreateSeparatorTransaction(-1, index);
txn = this.ptm.createSeparator(-1, aIndex);
else if (node.type == self.TYPE_X_MOZ_PLACE)
txn = self._getBookmarkItemCopyTransaction(node, -1, index);
@ -726,10 +725,8 @@ var PlacesUtils = {
var title = aData.folder.title;
var annos = aData.folder.annos;
var createTxn =
new PlacesCreateFolderTransaction(title, aContainer, aIndex, annos,
return this.ptm.createFolder(title, aContainer, aIndex, annos,
getChildItemsTransactions(aData.children));
return createTxn;
},
/**
@ -811,8 +808,8 @@ var PlacesUtils = {
// Place is a Livemark Container, should be reinstantiated
var feedURI = this._uri(data.uri.feed);
var siteURI = this._uri(data.uri.site);
return new PlacesCreateLivemarkTransaction(feedURI, siteURI,
data.title, container, index, data.annos);
return this.ptm.createLivemark(feedURI, siteURI, data.title, container,
index, data.annos);
}
break;
case this.TYPE_X_MOZ_PLACE:
@ -832,27 +829,23 @@ var PlacesUtils = {
if (copy) {
// There is no data in a separator, so copying it just amounts to
// inserting a new separator.
return new PlacesCreateSeparatorTransaction(container, index);
return this.ptm.createSeparator(container, index);
}
break;
default:
if (type == this.TYPE_X_MOZ_URL || type == this.TYPE_UNICODE) {
var title = (type == this.TYPE_X_MOZ_URL) ? data.title : data.uri;
var url = this._uri(data.uri);
var createTxn =
new PlacesCreateItemTransaction(url, container, index, title);
return createTxn;
return this.ptm.createItem(this._uri(data.uri), container, index,
title);
}
else {
return null;
}
}
if (data.id <= 0)
return null;
// Move the item otherwise
var id = data.folder ? data.folder.id : data.id;
return new PlacesMoveItemTransaction(id, container, index);
return this.ptm.moveItem(id, container, index);
},
/**

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

@ -46,6 +46,8 @@ include $(DEPTH)/config/autoconf.mk
MODULE = browserplaces
XPIDL_MODULE = browserplaces
XPIDLSRCS = nsIPlacesImportExportService.idl
XPIDLSRCS = nsIPlacesImportExportService.idl \
nsIPlacesTransactionsService.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,323 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Places.
*
* The Initial Developer of the Original Code is Mozilla Corporation
*
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Sungjoon Steve Won <stevewon@gmail.com> (Original Author)
* Asaf Romano <mano@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIVariant;
interface nsIURI;
interface nsIInputStream;
interface nsIMicrosummary;
interface nsITransactionManager;
interface nsITransaction;
/**
* nsIPlacesTransactionService is a service designed to handle
* nsITransactions that correspond to changes in Places. It is here as a
* service so that we can keep the transactions around without holding onto
* the global scope of a js window.
*/
[scriptable, uuid(224f6833-762b-43ba-8911-020b589b2da3)]
interface nsIPlacesTransactionsService : nsISupports
{
/**
* Performs a transaction.
*
* @param aTransaction
* a transaction object for a transaction
*/
void commitTransaction(in nsITransaction aTransaction);
/**
* Transaction for performing several Places Transactions in a single batch.
*
* @param aName
* title of the aggregate transactions
* @param aTransactions
* an array of transactions to perform
* @returns nsITransaction object
*/
nsITransaction aggregateTransactions(in AString aName,
in nsIVariant aTransactions);
/**
* Transaction for creating a new folder item.
*
* @param aName
* the name of the new folder
* @param aContainer
* the identifier of the folder in which the new folder should be
* added.
* @param [optional] aIndex
* the index of the item in aContainer, pass -1 or nothing to create
* the item at the end of aContainer.
* @param [optional] aAnnotations
* the annotations to set for the new folder.
* @param [optional] aChildItemsTransactions
* array of transactions for items to be created under the new folder.
* @returns nsITransaction object
*/
nsITransaction createFolder(in AString aName, in long long aContainer,
[optional] in long long aIndex,
[optional] in nsIVariant aAnnotations,
[optional] in nsIVariant aChildItemsTransactions);
/**
* Transaction for creating a new bookmark item
*
* @param aURI
* the uri of the new bookmark (nsIURI)
* @param aContainer
* the identifier of the folder in which the bookmark should be added.
* @param [optional] aIndex
* the index of the item in aContainer, pass -1 or nothing to create
* the item at the end of aContainer.
* @param [optional] aTitle
* the title of the new bookmark.
* @param [optional] aKeyword
* the keyword of the new bookmark.
* @param [optional] aAnnotations
* the annotations to set for the new bookmark.
* @param [optional] aChildTransactions
* child transactions to commit after creating the bookmark. Prefer
* using any of the arguments above if possible. In general, a child
* transations should be used only if the change it does has to be
* reverted manually when removing the bookmark item.
* a child transaction must support setting its bookmark-item
* identifier via an "id" js setter.
* @returns nsITransaction object
*/
nsITransaction createItem(in nsIURI aURI, in long long aContainer,
[optional] in long long aIndex,
[optional] in AString aTitle,
[optional] in AString aKeyword,
[optional] in nsIVariant aAnnotations,
[optional] in nsIVariant aChildTransactions);
/**
* Transaction for creating a new separator item
*
* @param aContainer
* the identifier of the folder in which the separator should be
* added.
* @param [optional] aIndex
* the index of the item in aContainer, pass -1 or nothing to create
* the separator at the end of aContainer.
* @returns nsITransaction object
*/
nsITransaction createSeparator(in long long aContainer,
[optional] in long long aIndex);
/**
* Transaction for creating a new live-bookmark item.
*
* @see nsILivemarksService::createLivemark for documentation regarding the
* first three arguments.
*
* @param aContainer
* the identifier of the folder in which the live-bookmark should be
* added.
* @param [optional] aIndex
* the index of the item in aContainer, pass -1 or nothing to create
* the item at the end of aContainer.
* @param [optional] aAnnotations
* the annotations to set for the new live-bookmark.
* @returns nsITransaction object
*/
nsITransaction createLivemark(in nsIURI aFeedURI,
in nsIURI aSiteURI,
in AString aName,
in long long aContainer,
[optional] in long long aIndex,
[optional] in nsIVariant aAnnotations);
/**
* Transaction for moving an Item.
*
* @param aItemId
* the id of the item to move
* @param aNewContainer
* id of the new container to move to
* @param aNewIndex
* index of the new position to move to
* @returns nsITransaction object
*/
nsITransaction moveItem(in long long aItemId,
in long long aNewContainer,
in long long aNewIndex);
/**
* Transaction for removing an Item
*
* @param aItemId
* id of the item to remove
* @returns nsITransaction object
*/
nsITransaction removeItem(in long long aItemId);
/**
* Transaction for editting a bookmark's title.
*
* @param id
* id of the item to edit
* @param newTitle
* new title for the item to edit
* @returns nsITransaction object
*/
nsITransaction editItemTitle(in long long id, in AString newTitle);
/**
* Transaction for editting a bookmark's uri.
*
* @param aBookmarkId
* id of the bookmark to edit
* @param aNewURI
* new uri for the bookmark
* @returns nsITransaction object
*/
nsITransaction editBookmarkURI(in long long aBookmarkId, in nsIURI aNewURI);
/**
* Transaction for setting/unsetting Load-in-sidebar annotation
*
* @param aBookmarkId
* id of the selected bookmark
* @param aLoadInSidebar
* boolean value
* @returns nsITransaction object
*/
nsITransaction setLoadInSidebar(in long long aBookmarkId,
in boolean aLoadInSidebar);
/**
* Transaction for editting a the description of a bookmark or a folder
*
* @param aItemId
* id of the item to edit
* @param aDescription
* new description
* @returns nsITransaction object
*/
nsITransaction editItemDescription(in long long aItemId,
in AString aDescription);
/**
* Transaction for editting a bookmark's keyword.
*
* @param id
* id of the bookmark to edit
* @param newKeyword
* new keyword for the bookmark
* @returns nsITransaction object
*/
nsITransaction editBookmarkKeyword(in long long id,
in AString newKeyword);
/**
* Transaction for editting the post data associated with a URI
*
* @param aURI
* uri to edit
* @param aPostData
* post data
* @returns nsITransaction object
*/
nsITransaction editURIPostData(in nsIURI aURI,
in nsIInputStream aPostData);
/**
* Transaction for editting a live bookmark's site URI.
*
* @param aFolderId
* id of the livemark
* @param aURI
* new site uri
* @returns nsITransaction object
*/
nsITransaction editLivemarkSiteURI(in long long aFolderId, in nsIURI aURI);
/**
* Transaction for editting a live bookmark's feed URI.
*
* @param folderId
* id of the livemark
* @param uri
* new feed uri
* @returns nsITransaction object
*/
nsITransaction editLivemarkFeedURI(in long long folderId, in nsIURI uri);
/**
* Transaction for editting a bookmark's microsummary.
*
* @param aItemId
* id of the bookmark to edit
* @param aNewMicrosummary
* new microsummary for the bookmark
* @returns nsITransaction object
*/
nsITransaction editBookmarkMicrosummary(in long long aItemId,
in nsIMicrosummary aNewMicrosummary);
/**
* Transaction for sorting a folder by name
*
* @param aFolderId
* id of the folder to sort
* @oaram aFolderIndex
* index of the folder to sort
* @returns nsITransaction object
*/
nsITransaction sortFolderByName(in long long aFolderId,
in long long aFolderIndex);
/**
* Transaction for set the bookmarks toolbar folder.
*
* @param aFolderId
* id of the folder to set as toolbar folder
* @returns nsITransaction object
*/
nsITransaction setBookmarksToolbar(in long long aFolderId);
/**
* A reference to the transaction manager
*/
readonly attribute nsITransactionManager transactionManager;
};

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

@ -66,4 +66,6 @@ REQUIRES = \
CPPSRCS = nsPlacesImportExportService.cpp
EXTRA_COMPONENTS = nsPlacesTransactionsService.js
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,770 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Places Command Controller.
*
* The Initial Developer of the Original Code is Google Inc.
*
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Sungjoon Steve Won <stevewon@gmail.com> (Original Author)
* Asaf Romano <mano@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
const Cu = Components.utils;
const loadInSidebarAnno = "bookmarkProperties/loadInSidebar";
const descriptionAnno = "bookmarkProperties/description";
const CLASS_ID = Components.ID("bec866cc-9dd0-42a0-a196-6fdaa16021c4");
const CONTRACT_ID = "@mozilla.org/browser/placesTransactionsService;1";
var toolbarFolder = null;
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].
getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://global/content/debug.js");
loader.loadSubScript("chrome://browser/content/places/utils.js");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function LOG(str) {
dump("*** " + str + "\n");
};
// The minimum amount of transactions we should tell our observers to begin
// batching (rather than letting them do incremental drawing).
const MIN_TRANSACTIONS_FOR_BATCH = 5;
function placesTransactionsService() {
this.mTransactionManager = Cc["@mozilla.org/transactionmanager;1"].
createInstance(Ci.nsITransactionManager);
}
placesTransactionsService.prototype = {
classDescription: "Places Transaction Manager",
classID: CLASS_ID,
contractID: CONTRACT_ID,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPlacesTransactionsService,
Ci.nsISupports]),
aggregateTransactions: function placesAggrTransactions(name, transactions) {
return new placesAggregateTransactions(name, transactions);
},
createFolder: function placesCrtFldr(aName, aContainer, aIndex,
aAnnotations, aChildItemsTransactions) {
return new placesCreateFolderTransactions(aName, aContainer, aIndex,
aAnnotations, aChildItemsTransactions);
},
createItem: function placesCrtItem(aURI, aContainer, aIndex, aTitle,
aKeyword, aAnnotations, aChildTransactions) {
return new placesCreateItemTransactions(aURI, aContainer, aIndex, aTitle,
aKeyword, aAnnotations, aChildTransactions);
},
createSeparator: function placesCrtSpr(aContainer, aIndex) {
return new placesCreateSeparatorTransactions(aContainer, aIndex);
},
createLivemark: function placesCrtLivemark(aFeedURI, aSiteURI, aName,
aContainer, aIndex, aAnnotations) {
return new placesCreateLivemarkTransactions(aFeedURI, aSiteURI, aName,
aContainer, aIndex, aAnnotations);
},
moveItem: function placesMvItem(aItemId, aNewContainer, aNewIndex) {
return new placesMoveItemTransactions(aItemId, aNewContainer, aNewIndex);
},
removeItem: function placesRmItem(id) {
return new placesRemoveItemTransaction(id);
},
editItemTitle: function placesEditItmTitle(id, newTitle) {
return new placesEditItemTitleTransactions(id, newTitle);
},
editBookmarkURI: function placesEditBkmkURI(aBookmarkId, aNewURI) {
return new placesEditBookmarkURITransactions(aBookmarkId, aNewURI);
},
setLoadInSidebar: function placesSetLdInSdbar(aBookmarkId, aLoadInSidebar) {
return new placesSetLoadInSidebarTransactions(aBookmarkId, aLoadInSidebar);
},
editItemDescription: function placesEditItmDesc(aItemId, aDescription) {
return new placesEditItemDescriptionTransactions(aItemId, aDescription);
},
editBookmarkKeyword: function placesEditBkmkKwd(id, newKeyword) {
return new placesEditBookmarkKeywordTransactions(id, newKeyword);
},
editURIPostData: function placesEditURIPdata(aURI, aPostData) {
return new placesEditURIPostDataTransactions(aURI, aPostData);
},
editLivemarkSiteURI: function placesEditLvmkSiteURI(folderId, uri) {
return new placesEditLivemarkSiteURITransactions(folderId, uri);
},
editLivemarkFeedURI: function placesEditLvmkFeedURI(folderId, uri) {
return new placesEditLivemarkFeedURITransactions(folderId, uri);
},
editBookmarkMicrosummary: function placesEditBkmkMicrosummary(aID, newMicrosummary) {
return new placesEditBookmarkMicrosummaryTransactions(aID, newMicrosummary);
},
sortFolderByName: function placesSortFldrByName(aFolderId, aFolderIndex) {
return new placesSortFolderByNameTransactions(aFolderId, aFolderIndex);
},
setBookmarksToolbar: function placesSetBkmkToolbar(aFolderId) {
return new placesSetBookmarksToolbarTransactions(aFolderId);
},
commitTransaction: function placesCommitTxn(txn) {
this.mTransactionManager.doTransaction(txn);
},
get transactionManager() {
return this.mTransactionManager;
}
};
/**
* Method and utility stubs for Places Edit Transactions
*/
function placesBaseTransaction() {
}
placesBaseTransaction.prototype = {
redoTransaction: function PIT_redoTransaction() {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
get isTransient() {
return false;
},
merge: function mergeFunc(transaction) {
return false;
},
_ifaces: [Ci.nsITransaction, Ci.nsIClassInfo, Ci.nsISupports],
// nsIClassInfo, allows setting expando properties on transactions
flags: Ci.nsIClassInfo.DOM_OBJECT,
classDescription: "Places Transaction",
getInterface: function(aCount) {
aCount.value = this._ifaces.length;
return this._ifaces;
},
QueryInterface: XPCOMUtils.generateQI(this._ifaces),
};
function placesAggregateTransactions(name, transactions) {
this._transactions = transactions;
this._name = name;
this.container = -1;
this.redoTransaction = this.doTransaction;
}
placesAggregateTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PAT_doTransaction() {
if (this._transactions.length >= MIN_TRANSACTIONS_FOR_BATCH) {
var callback = {
_self: this,
runBatched: function() {
this._self.commit(false);
}
};
PlacesUtils.bookmarks.runInBatchMode(callback, null);
}
else
this.commit(false);
},
undoTransaction: function PAT_undoTransaction() {
if (this._transactions.length >= MIN_TRANSACTIONS_FOR_BATCH) {
var callback = {
_self: this,
runBatched: function() {
this._self.commit(true);
}
};
PlacesUtils.bookmarks.runInBatchMode(callback, null);
}
else
this.commit(true);
},
commit: function PAT_commit(aUndo) {
for (var i = this._transactions.length - 1; i >= 0; --i) {
var txn = this._transactions[i];
if (this.container > -1)
txn.container = this.container;
if (aUndo)
txn.undoTransaction();
else
txn.doTransaction();
}
}
};
function placesCreateFolderTransactions(aName, aContainer, aIndex,
aAnnotations,
aChildItemsTransactions) {
this._name = aName;
this._container = aContainer;
this._index = typeof(aIndex) == "number" ? aIndex : -1;
this._annotations = aAnnotations;
this._id = null;
this._childItemsTransactions = aChildItemsTransactions || [];
this.redoTransaction = this.doTransaction;
}
placesCreateFolderTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
// childItemsTransaction support
get container() { return this._container; },
set container(val) { return this._container = val; },
doTransaction: function PCFT_doTransaction() {
this._id = PlacesUtils.bookmarks.createFolder(this._container,
this._name, this._index);
if ((this._annotations != null) && (this._annotations.length > 0))
PlacesUtils.setAnnotationsForItem(this.id, this._annotations);
for (var i = 0; i < this._childItemsTransactions.length; ++i) {
var txn = this._childItemsTransactions[i];
txn.container = this._id;
txn.doTransaction();
}
},
undoTransaction: function PCFT_undoTransaction() {
PlacesUtils.bookmarks.removeFolder(this._id);
for (var i = 0; i < this._childItemsTransactions.length; ++i) {
var txn = this.childItemsTransactions[i];
txn.undoTransaction();
}
}
};
function placesCreateItemTransactions(aURI, aContainer, aIndex, aTitle,
aKeyword, aAnnotations,
aChildTransactions) {
this._uri = aURI;
this._container = aContainer;
this._index = typeof(aIndex) == "number" ? aIndex : -1;
this._title = aTitle;
this._keyword = aKeyword;
this._annotations = aAnnotations;
this._childTransactions = aChildTransactions || [];
this.redoTransaction = this.doTransaction;
}
placesCreateItemTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
// childItemsTransactions support for the create-folder transaction
get container() { return this._container; },
set container(val) { return this._container = val; },
doTransaction: function PCIT_doTransaction() {
this._id = PlacesUtils.bookmarks.insertBookmark(this.container, this._uri,
this._index, this._title);
if (this._keyword)
PlacesUtils.bookmarks.setKeywordForBookmark(this._id, this._keyword);
if (this._annotations && this._annotations.length > 0)
PlacesUtils.setAnnotationsForItem(this._id, this._annotations);
for (var i = 0; i < this._childTransactions.length; ++i) {
var txn = this._childTransactions[i];
txn.id = this._id;
txn.doTransaction();
}
},
undoTransaction: function PCIT_undoTransaction() {
PlacesUtils.bookmarks.removeItem(this._id);
for (var i = 0; i < this._childTransactions.length; ++i) {
var txn = this._childTransactions[i];
txn.undoTransaction();
}
}
};
function placesCreateSeparatorTransactions(aContainer, aIndex) {
this._container = aContainer;
this._index = typeof(aIndex) == "number" ? aIndex : -1;
this._id = null;
}
placesCreateSeparatorTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
// childItemsTransaction support
get container() { return this._container; },
set container(val) { return this._container = val;clear },
doTransaction: function PCST_doTransaction() {
this._id = PlacesUtils.bookmarks
.insertSeparator(this.container, this._index);
},
undoTransaction: function PCST_undoTransaction() {
PlacesUtils.bookmarks.removeChildAt(this.container, this._index);
}
};
function placesCreateLivemarkTransactions(aFeedURI, aSiteURI, aName,
aContainer, aIndex,
aAnnotations) {
this._feedURI = aFeedURI;
this._siteURI = aSiteURI;
this._name = aName;
this._container = aContainer;
this._index = typeof(aIndex) == "number" ? aIndex : -1;
this._annotations = aAnnotations;
}
placesCreateLivemarkTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
// childItemsTransaction support
get container() { return this._container; },
set container(val) { return this._container = val; },
doTransaction: function PCLT_doTransaction() {
this._id = PlacesUtils.livemarks.createLivemark(this._container, this._name,
this._siteURI, this._feedURI,
this._index);
if (this._annotations)
PlacesUtils.setAnnotationsForItem(this._id, this._annotations);
},
undoTransaction: function PCLT_undoTransaction() {
PlacesUtils.bookmarks.removeFolder(this._id);
}
};
function placesMoveItemTransactions(aItemId, aNewContainer, aNewIndex) {
NS_ASSERT(aNewIndex >= -1, "invalid insertion index");
this._id = aItemId;
this._oldContainer = PlacesUtils.bookmarks.getFolderIdForItem(this._id);
this._oldIndex = PlacesUtils.bookmarks.getItemIndex(this._id);
NS_ASSERT(this._oldContainer > 0 && this._oldIndex >= 0, "invalid item");
this._newContainer = aNewContainer;
this._newIndex = aNewIndex;
this.redoTransaction = this.doTransaction;
}
placesMoveItemTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PMIT_doTransaction() {
PlacesUtils.bookmarks.moveItem(this._id, this._newContainer, this._newIndex);
},
undoTransaction: function PMIT_undoTransaction() {
PlacesUtils.bookmarks.moveItem(this._id, this._oldContainer, this._oldIndex);
}
};
function placesRemoveItemTransaction(aItemId) {
this.redoTransaction = this.doTransaction;
this._id = aItemId;
this._itemType = PlacesUtils.bookmarks.getItemType(this._id);
if (this._itemType == Ci.nsINavBookmarksService.TYPE_FOLDER) {
this._transactions = [];
this._removeTxn = PlacesUtils.bookmarks
.getRemoveFolderTransaction(this._id);
}
}
placesRemoveItemTransaction.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PRIT_doTransaction() {
this._oldContainer = PlacesUtils.bookmarks.getFolderIdForItem(this._id);
this._oldIndex = PlacesUtils.bookmarks.getItemIndex(this._id);
this._title = PlacesUtils.bookmarks.getItemTitle(this._id);
this._annotations = PlacesUtils.getAnnotationsForItem(this._id);
if (this._itemType == Ci.nsINavBookmarksService.TYPE_FOLDER) {
this._saveFolderContents();
// Remove children backwards to preserve parent-child relationships.
for (var i = this._transactions.length - 1; i >= 0; --i)
this._transactions[i].doTransaction();
// Remove this folder itself.
this._removeTxn.doTransaction();
}
else {
if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK)
this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._id);
PlacesUtils.bookmarks.removeItem(this._id);
}
},
undoTransaction: function PRIT_undoTransaction() {
if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {
this._id = PlacesUtils.bookmarks.insertBookmark(this._oldContainer,
this._uri,
this._oldIndex,
this._title);
}
else if (this._itemType == Ci.nsINavBookmarksService.TYPE_FOLDER) {
this._removeTxn.undoTransaction();
// Create children forwards to preserve parent-child relationships.
for (var i = 0; i < this._transactions.length; ++i)
this._transactions[i].undoTransaction();
}
else // TYPE_SEPARATOR
PlacesUtils.bookmarks.insertSeparator(this._oldContainer, this._oldIndex);
PlacesUtils.setAnnotationsForItem(this._id, this._annotations);
},
/**
* Create a flat, ordered list of transactions for a depth-first recreation
* of items within this folder.
*/
_saveFolderContents: function PRIT__saveFolderContents() {
this._transactions = [];
var contents = PlacesUtils.getFolderContents(this._id, false, false).root;
for (var i = 0; i < contents.childCount; ++i) {
this._transactions
.push(new placesRemoveItemTransaction(contents.getChild(i).itemId));
}
}
};
function placesEditItemTitleTransactions(id, newTitle) {
this._id = id;
this._newTitle = newTitle;
this._oldTitle = "";
this.redoTransaction = this.doTransaction;
}
placesEditItemTitleTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PEITT_doTransaction() {
this._oldTitle = PlacesUtils.bookmarks.getItemTitle(this._id);
PlacesUtils.bookmarks.setItemTitle(this._id, this._newTitle);
},
undoTransaction: function PEITT_undoTransaction() {
PlacesUtils.bookmarks.setItemTitle(this._id, this._oldTitle);
}
};
function placesEditBookmarkURITransactions(aBookmarkId, aNewURI) {
this._id = aBookmarkId;
this._newURI = aNewURI;
this.redoTransaction = this.doTransaction;
}
placesEditBookmarkURITransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PEBUT_doTransaction() {
this._oldURI = PlacesUtils.bookmarks.getBookmarkURI(this._id);
PlacesUtils.bookmarks.changeBookmarkURI(this._id, this._newURI);
},
undoTransaction: function PEBUT_undoTransaction() {
PlacesUtils.bookmarks.changeBookmarkURI(this._id, this._oldURI);
}
};
function placesSetLoadInSidebarTransactions(aBookmarkId, aLoadInSidebar) {
this.id = aBookmarkId;
this._loadInSidebar = aLoadInSidebar;
this.redoTransaction = this.doTransaction;
}
placesSetLoadInSidebarTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
_anno: {
name: loadInSidebarAnno,
type: Ci.nsIAnnotationService.TYPE_INT32,
value: 1,
flags: 0,
expires: Ci.nsIAnnotationService.EXPIRE_NEVER
},
doTransaction: function PSLIST_doTransaction() {
this._wasSet = PlacesUtils.annotations.itemHasAnnotation(this.id, this._anno.name);
if (this._loadInSidebar) {
PlacesUtils.setAnnotationsForItem(this.id, [this._anno]);
}
else {
try {
PlacesUtils.annotations.removeItemAnnotation(this.id, this._anno.name);
} catch(ex) { }
}
},
undoTransaction: function PSLIST_undoTransaction() {
if (this._wasSet != this._loadInSidebar) {
this._loadInSidebar = !this._loadInSidebar;
this.doTransaction();
}
}
};
function placesEditItemDescriptionTransactions(aItemId, aDescription) {
this.id = aItemId;
this._newDescription = aDescription;
this.redoTransaction = this.doTransaction;
}
placesEditItemDescriptionTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
_oldDescription: "",
doTransaction: function PSLIST_doTransaction() {
const annos = PlacesUtils.annotations;
if (annos.itemHasAnnotation(this.id, descriptionAnno))
this._oldDescription = annos.getItemAnnotation(this.id, descriptionAnno);
if (this._newDescription) {
annos.setItemAnnotation(this.id, descriptionAnno,
this._newDescription, 0,
annos.EXPIRE_NEVER);
}
else if (this._oldDescription)
annos.removeItemAnnotation(this.id, descriptionAnno);
},
undoTransaction: function PSLIST_undoTransaction() {
const annos = PlacesUtils.annotations;
if (this._oldDescription) {
annos.setItemAnnotationString(this.id, descriptionAnno,
this._oldDescription, 0,
annos.EXPIRE_NEVER);
}
else if (annos.itemHasAnnotation(this.id, descriptionAnno))
annos.removeItemAnnotation(this.id, descriptionAnno);
}
};
function placesEditBookmarkKeywordTransactions(id, newKeyword) {
this.id = id;
this._newKeyword = newKeyword;
this._oldKeyword = "";
this.redoTransaction = this.doTransaction;
}
placesEditBookmarkKeywordTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PEBKT_doTransaction() {
this._oldKeyword = PlacesUtils.bookmarks.getKeywordForBookmark(this.id);
PlacesUtils.bookmarks.setKeywordForBookmark(this.id, this._newKeyword);
},
undoTransaction: function PEBKT_undoTransaction() {
PlacesUtils.bookmarks.setKeywordForBookmark(this.id, this._oldKeyword);
}
};
function placesEditURIPostDataTransactions(aURI, aPostData) {
this._uri = aURI;
this._newPostData = aPostData;
this._oldPostData = null;
this.redoTransaction = this.doTransaction;
}
placesEditURIPostDataTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PEUPDT_doTransaction() {
this._oldPostData = PlacesUtils.getPostDataForURI(this._uri);
PlacesUtils.setPostDataForURI(this._uri, this._newPostData);
},
undoTransaction: function PEUPDT_undoTransaction() {
PlacesUtils.setPostDataForURI(this._uri, this._oldPostData);
}
};
function placesEditLivemarkSiteURITransactions(folderId, uri) {
this._folderId = folderId;
this._newURI = uri;
this._oldURI = null;
this.redoTransaction = this.doTransaction;
}
placesEditLivemarkSiteURITransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PELSUT_doTransaction() {
this._oldURI = PlacesUtils.livemarks.getSiteURI(this._folderId);
PlacesUtils.livemarks.setSiteURI(this._folderId, this._newURI);
},
undoTransaction: function PELSUT_undoTransaction() {
PlacesUtils.livemarks.setSiteURI(this._folderId, this._oldURI);
}
};
function placesEditLivemarkFeedURITransactions(folderId, uri) {
this._folderId = folderId;
this._newURI = uri;
this._oldURI = null;
this.redoTransaction = this.doTransaction;
}
placesEditLivemarkFeedURITransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PELFUT_doTransaction() {
this._oldURI = PlacesUtils.livemarks.getFeedURI(this._folderId);
PlacesUtils.livemarks.setFeedURI(this._folderId, this._newURI);
PlacesUtils.livemarks.reloadLivemarkFolder(this._folderId);
},
undoTransaction: function PELFUT_undoTransaction() {
PlacesUtils.livemarks.setFeedURI(this._folderId, this._oldURI);
PlacesUtils.livemarks.reloadLivemarkFolder(this._folderId);
}
};
function placesEditBookmarkMicrosummaryTransactions(aID, newMicrosummary) {
this.id = aID;
this._mss = Cc["@mozilla.org/microsummary/service;1"].
getService(Ci.nsIMicrosummaryService);
this._newMicrosummary = newMicrosummary;
this._oldMicrosummary = null;
this.redoTransaction = this.doTransaction;
}
placesEditBookmarkMicrosummaryTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PEBMT_doTransaction() {
this._oldMicrosummary = this._mss.getMicrosummary(this.id);
if (this._newMicrosummary)
this._mss.setMicrosummary(this.id, this._newMicrosummary);
else
this._mss.removeMicrosummary(this.id);
},
undoTransaction: function PEBMT_undoTransaction() {
if (this._oldMicrosummary)
this._mss.setMicrosummary(this.id, this._oldMicrosummary);
else
this._mss.removeMicrosummary(this.id);
}
};
function placesSortFolderByNameTransactions(aFolderId, aFolderIndex) {
this._folderId = aFolderId;
this._folderIndex = aFolderIndex;
this._oldOrder = null,
this.redoTransaction = this.doTransaction;
}
placesSortFolderByNameTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PSSFBN_doTransaction() {
this._oldOrder = [];
var contents = PlacesUtils.getFolderContents(this._folderId, false, false).root;
var count = contents.childCount;
// sort between separators
var newOrder = [];
var preSep = []; // temporary array for sorting each group of items
var sortingMethod =
function (a, b) { return a.title.localeCompare(b.title); };
for (var i = 0; i < count; ++i) {
var item = contents.getChild(i);
this._oldOrder[item.itemId] = i;
if (PlacesUtils.nodeIsSeparator(item)) {
if (preSep.length > 0) {
preSep.sort(sortingMethod);
newOrder = newOrder.concat(preSep);
preSep.splice(0);
}
newOrder.push(item);
}
else
preSep.push(item);
}
if (preSep.length > 0) {
preSep.sort(sortingMethod);
newOrder = newOrder.concat(preSep);
}
// set the nex indexs
for (var i = 0; i < count; ++i)
PlacesUtils.bookmarks.setItemIndex(newOrder[i].itemId, i);
},
undoTransaction: function PSSFBN_undoTransaction() {
for (item in this._oldOrder)
PlacesUtils.bookmarks.setItemIndex(item, this._oldOrder[item]);
}
};
function placesSetBookmarksToolbarTransactions(aFolderId) {
this._folderId = aFolderId;
this.redoTransaction = this.doTransaction;
this._oldFolderId = PlacesUtils.bookmarks.toolbarFolder;
}
placesSetBookmarksToolbarTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PSBTT_doTransaction() {
PlacesUtils.bookmarks.toolbarFolder = this._folderId;
},
undoTransaction: function PSBTT_undoTransaction() {
PlacesUtils.bookmarks.toolbarFolder = this._oldFolderId;
}
};
function NSGetModule(aCompMgr, aFileSpec) {
return XPCOMUtils.generateModule([placesTransactionsService]);
}

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

@ -0,0 +1,384 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is example Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Sungjoon Steve Won <stevewon@gmail.com> (Original Author)
* Asaf Romano <mano@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// Get bookmark service
try {
var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].getService(Ci.nsINavBookmarksService);
} catch(ex) {
do_throw("Could not get nav-bookmarks-service\n");
}
// Get livemark service
try {
var lmsvc = Cc["@mozilla.org/browser/livemark-service;2"].getService(Ci.nsILivemarkService);
} catch(ex) {
do_throw("Could not get livemark-service\n");
}
// Get microsummary service
try {
var mss = Cc["@mozilla.org/microsummary/service;1"].getService(Ci.nsIMicrosummaryService);
} catch(ex) {
do_throw("Could not get microsummary-service\n");
}
// Get Places Transaction Manager Service
try {
var ptSvc =
Cc["@mozilla.org/browser/placesTransactionsService;1"].
getService(Ci.nsIPlacesTransactionsService);
} catch(ex) {
do_throw("Could not get Places Transactions Service\n");
}
// create and add bookmarks observer
var observer = {
onBeginUpdateBatch: function() {
this._beginUpdateBatch = true;
},
onEndUpdateBatch: function() {
this._endUpdateBatch = true;
},
onItemAdded: function(id, folder, index) {
this._itemAddedId = id;
this._itemAddedParent = folder;
this._itemAddedIndex = index;
},
onItemRemoved: function(id, folder, index) {
this._itemRemovedId = id;
this._itemRemovedFolder = folder;
this._itemRemovedIndex = index;
},
onItemChanged: function(id, property, isAnnotationProperty, value) {
this._itemChangedId = id;
this._itemChangedProperty = property;
this._itemChanged_isAnnotationProperty = isAnnotationProperty;
this._itemChangedValue = value;
},
onItemVisited: function(id, visitID, time) {
this._itemVisitedId = id;
this._itemVisitedVistId = visitID;
this._itemVisitedTime = time;
},
onItemMoved: function(id, oldParent, oldIndex, newParent, newIndex) {
this._itemMovedId = id
this._itemMovedOldParent = oldParent;
this._itemMovedOldIndex = oldIndex;
this._itemMovedNewParent = newParent;
this._itemMovedNewIndex = newIndex;
},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsINavBookmarkObserver) ||
iid.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
},
};
bmsvc.addObserver(observer, false);
// get bookmarks root index
var root = bmsvc.bookmarksRoot;
// index at which items should begin
var bmStartIndex = 1;
// main
function run_test() {
//Test creating a folder
var txn1 = ptSvc.createFolder("Testing folder", root, bmStartIndex);
txn1.doTransaction();
var folderId = bmsvc.getChildFolder(root, "Testing folder");
do_check_eq(observer._itemAddedIndex, bmStartIndex);
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedId, folderId);
txn1.undoTransaction();
do_check_eq(observer._itemRemovedId, folderId);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, bmStartIndex);
// Test creating an item
// Create to Root
var txn2 = ptSvc.createItem(uri("http://www.example.com"), root, bmStartIndex, "Testing1");
ptSvc.commitTransaction(txn2); //Also testing commitTransaction
var b = (bmsvc.getBookmarkIdsForURI(uri("http://www.example.com"), {}))[0];
do_check_eq(observer._itemAddedId, b);
do_check_eq(observer._itemAddedIndex, bmStartIndex);
do_check_true(bmsvc.isBookmarked(uri("http://www.example.com")));
txn2.undoTransaction();
do_check_eq(observer._itemRemovedId, b);
do_check_eq(observer._itemRemovedIndex, bmStartIndex);
// Create to a folder
var txn2a = ptSvc.createFolder("Folder", root, bmStartIndex);
var fldrId = bmsvc.getChildFolder(root, "Folder");
var txn2b = ptSvc.createItem(uri("http://www.example.com"), fldrId, bmStartIndex, "Testing1b");
ptSvc.commitTransaction(txn2);
var b2 = (bmsvc.getBookmarkIdsForURI(uri("http://www.example.com"), {}))[0];
do_check_eq(observer._itemAddedId, b2);
do_check_eq(observer._itemAddedIndex, bmStartIndex);
do_check_true(bmsvc.isBookmarked(uri("http://www.example.com")));
txn2.undoTransaction();
do_check_eq(observer._itemRemovedId, b2);
do_check_eq(observer._itemRemovedIndex, bmStartIndex);
// Testing moving an item
ptSvc.commitTransaction(ptSvc.createItem(uri("http://www.example.com"), root, -1, "Testing2"));
ptSvc.commitTransaction(ptSvc.createItem(uri("http://www.example.com"), root, -1, "Testing3"));
ptSvc.commitTransaction(ptSvc.createItem(uri("http://www.example.com"), fldrId, -1, "Testing4"));
var bkmkIds = bmsvc.getBookmarkIdsForURI(uri("http://www.example.com"), {});
var bkmk1Id = bkmkIds[0];
var bkmk2Id = bkmkIds[1];
var bkmk3Id = bkmkIds[2];
var txn3 = ptSvc.moveItem(bkmk1Id, root, -1);
txn3.doTransaction();
// Moving items between the same folder
do_check_eq(observer._itemMovedId, bkmk1Id);
do_check_eq(observer._itemMovedOldParent, root);
do_check_eq(observer._itemMovedOldIndex, 1);
do_check_eq(observer._itemMovedNewParent, root);
do_check_eq(observer._itemMovedNewIndex, 2);
txn3.undoTransaction();
do_check_eq(observer._itemMovedId, bkmk1Id);
do_check_eq(observer._itemMovedOldParent, root);
do_check_eq(observer._itemMovedOldIndex, 2);
do_check_eq(observer._itemMovedNewParent, root);
do_check_eq(observer._itemMovedNewIndex, 1);
// Moving items between different folders
var txn3b = ptSvc.moveItem(bkmk1Id, fldrId, -1);
txn3b.doTransaction();
do_check_eq(observer._itemMovedId, bkmk1Id);
do_check_eq(observer._itemMovedOldParent, root);
do_check_eq(observer._itemMovedOldIndex, 1);
do_check_eq(observer._itemMovedNewParent, fldrId);
do_check_eq(observer._itemMovedNewIndex, 2);
txn3.undoTransaction();
do_check_eq(observer._itemMovedId, bkmk1Id);
do_check_eq(observer._itemMovedOldParent, fldrId);
do_check_eq(observer._itemMovedOldIndex, 2);
do_check_eq(observer._itemMovedNewParent, root);
do_check_eq(observer._itemMovedNewIndex, 1);
// Test Removing a Folder
ptSvc.commitTransaction(ptSvc.createFolder("Folder2", root, -1));
var fldrId2 = bmsvc.getChildFolder(root, "Folder2");
var txn4 = ptSvc.removeItem(fldrId2);
txn4.doTransaction();
do_check_eq(observer._itemRemovedId, fldrId2);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, 3);
txn4.undoTransaction();
do_check_eq(observer._itemAddedId, fldrId2);
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedIndex, 3);
// Test removing an item
var txn5 = ptSvc.removeItem(bkmk2Id);
txn5.doTransaction();
do_check_eq(observer._itemRemovedId, bkmk2Id);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, 1);
txn5.undoTransaction();
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedIndex, 1);
// Test creating a separator
var txn6 = ptSvc.createSeparator(root, 1);
txn6.doTransaction();
var sepId = observer._itemAddedId;
do_check_eq(observer._itemAddedIndex, 1);
do_check_eq(observer._itemAddedParent, root);
txn6.undoTransaction();
do_check_eq(observer._itemRemovedId, sepId);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, 1);
// Test removing a separator
ptSvc.commitTransaction(ptSvc.createSeparator(root, 1));
var sepId2 = observer._itemAddedId;
var txn7 = ptSvc.removeItem(sepId2);
txn7.doTransaction();
do_check_eq(observer._itemRemovedId, sepId2);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, 1);
txn7.undoTransaction();
do_check_eq(observer._itemAddedId, sepId2); //New separator created
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedIndex, 1);
// Test editing item title
var txn8 = ptSvc.editItemTitle(bkmk1Id, "Testing2_mod");
txn8.doTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "title");
do_check_eq(observer._itemChangedValue, "Testing2_mod");
txn8.undoTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "title");
do_check_eq(observer._itemChangedValue, "Testing2");
// Test editing item uri
var txn9 = ptSvc.editBookmarkURI(bkmk1Id, uri("http://newuri.com"));
txn9.doTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "uri");
do_check_eq(observer._itemChangedValue, "http://newuri.com/");
txn9.undoTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "uri");
do_check_eq(observer._itemChangedValue, "http://www.example.com/");
// Test edit item description
var txn10 = ptSvc.editItemDescription(bkmk1Id, "Description1");
txn10.doTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "bookmarkProperties/description");
// Testing edit keyword
var txn11 = ptSvc.editBookmarkKeyword(bkmk1Id, "kw1");
txn11.doTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "keyword");
do_check_eq(observer._itemChangedValue, "kw1");
txn11.undoTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "keyword");
do_check_eq(observer._itemChangedValue, "");
var txn12 = ptSvc.createLivemark(uri("http://feeduri.com"), uri("http://siteuri.com"), "Livemark1", root);
txn12.doTransaction();
// Funky stuff going on here.
// In placesCreateLivemarkTxn, livemarks.createLivemark actually returns observer._itemAddedId -1
// instead of observer._itemAddedId. Check w. someone.
do_check_true(lmsvc.isLivemark(observer._itemAddedId-1));
do_check_eq(lmsvc.getSiteURI(observer._itemAddedId-1).spec, "http://siteuri.com/");
do_check_eq(lmsvc.getFeedURI(observer._itemAddedId-1).spec, "http://feeduri.com/");
var lvmkId = observer._itemAddedId-1;
// editLivemarkSiteURI
var txn13 = ptSvc.editLivemarkSiteURI(lvmkId, uri("http://NEWsiteuri.com/"));
txn13.doTransaction();
do_check_eq(observer._itemChangedId, lvmkId);
do_check_eq(observer._itemChangedProperty, "livemark/siteURI");
txn13.undoTransaction();
do_check_eq(observer._itemChangedId, lvmkId);
do_check_eq(observer._itemChangedProperty, "livemark/siteURI");
do_check_eq(observer._itemChangedValue, "");
// editLivemarkFeedURI
var txn14 = ptSvc.editLivemarkFeedURI(lvmkId, uri("http://NEWfeeduri.com/"));
txn14.doTransaction();
do_check_eq(observer._itemChangedId, lvmkId);
do_check_eq(observer._itemChangedProperty, "livemark/feedURI");
txn14.undoTransaction();
do_check_eq(observer._itemChangedId, lvmkId);
do_check_eq(observer._itemChangedProperty, "livemark/feedURI");
do_check_eq(observer._itemChangedValue, "");
// setBookmarksToolbar
ptSvc.commitTransaction(ptSvc.createFolder("Testing toolbar folder", root, bmStartIndex));
var tmpFolderId = bmsvc.getChildFolder(root, "Testing toolbar folder");
var txn15 = ptSvc.setBookmarksToolbar(tmpFolderId);
txn15.doTransaction();
do_check_eq(observer._itemChangedId, tmpFolderId);
do_check_eq(observer._itemChangedProperty, "became_toolbar_folder");
txn15.undoTransaction();
// Test setLoadInSidebar
var txn16 = ptSvc.setLoadInSidebar(bkmk1Id, true);
txn16.doTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "bookmarkProperties/loadInSidebar");
do_check_eq(observer._itemChanged_isAnnotationProperty, true);
txn16.undoTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "bookmarkProperties/loadInSidebar");
do_check_eq(observer._itemChanged_isAnnotationProperty, true);
// sortFolderByName
ptSvc.commitTransaction(ptSvc.createFolder("Sorting folder", root, bmStartIndex, [], null));
var srtFldId = bmsvc.getChildFolder(root, "Sorting folder");
ptSvc.commitTransaction(ptSvc.createItem(uri("http://www.sortingtest.com"), srtFldId, -1, "c"));
ptSvc.commitTransaction(ptSvc.createItem(uri("http://www.sortingtest.com"), srtFldId, -1, "b"));
ptSvc.commitTransaction(ptSvc.createItem(uri("http://www.sortingtest.com"), srtFldId, -1, "a"));
var b = bmsvc.getBookmarkIdsForURI(uri("http://www.sortingtest.com"), {});
var b1 = b[0];
var b2 = b[1];
var b3 = b[2];
do_check_eq(0, bmsvc.getItemIndex(b1));
do_check_eq(1, bmsvc.getItemIndex(b2));
do_check_eq(2, bmsvc.getItemIndex(b3));
var txn17 = ptSvc.sortFolderByName(srtFldId, 1);
txn17.doTransaction();
do_check_eq(2, bmsvc.getItemIndex(b1));
do_check_eq(1, bmsvc.getItemIndex(b2));
do_check_eq(0, bmsvc.getItemIndex(b3));
txn17.undoTransaction();
do_check_eq(0, bmsvc.getItemIndex(b1));
do_check_eq(1, bmsvc.getItemIndex(b2));
do_check_eq(2, bmsvc.getItemIndex(b3));
// editBookmarkMicrosummary
var tmpMs = mss.createMicrosummary(uri("http://testmicro.com"),
uri("http://dietrich.ganx4.com/mozilla/test-microsummary.xml"));
ptSvc.commitTransaction(
ptSvc.createItem(uri("http://dietrich.ganx4.com/mozilla/test-microsummary-content.php"),
root, -1, "micro test", null, null, null));
var bId = (bmsvc.getBookmarkIdsForURI(uri("http://dietrich.ganx4.com/mozilla/test-microsummary-content.php"),{}))[0];
do_check_true(!mss.hasMicrosummary(bId));
var txn18 = ptSvc.editBookmarkMicrosummary(bId, tmpMs);
txn18.doTransaction();
do_check_eq(observer._itemChangedId, bId);
do_check_eq(observer._itemChangedProperty, "bookmarks/generatedTitle");
do_check_true(mss.hasMicrosummary(bId));
txn18.undoTransaction();
do_check_eq(observer._itemChangedId, bId);
do_check_eq(observer._itemChangedProperty, "bookmarks/generatedTitle");
do_check_true(!mss.hasMicrosummary(bId));
// Testing edit Post Data...
// mmm.. cant figure out a good way to test this.
}

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

@ -198,6 +198,7 @@ bin/components/nsBrowserContentHandler.js
bin/components/nsBrowserGlue.js
bin/components/nsSetDefaultBrowser.js
bin/components/nsMicrosummaryService.js
bin/components/nsPlacesTransactionsService.js
bin/components/nsSearchService.js
bin/components/nsSearchSuggestions.js
bin/components/nsLoginInfo.js

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

@ -213,6 +213,7 @@ bin\components\nsXmlRpcClient.js
bin\components\nsExtensionManager.js
bin\components\nsUpdateService.js
bin\components\nsMicrosummaryService.js
bin\components\nsPlacesTransactionsService.js
bin\components\nsPostUpdateWin.js
bin\components\nsLoginInfo.js
bin\components\nsLoginManager.js