--- a/browser/components/places/PlacesUIUtils.jsm
+++ b/browser/components/places/PlacesUIUtils.jsm
@@ -252,71 +252,16 @@ var PlacesUIUtils = {
});
},
getString: function PUIU_getString(key) {
return bundle.GetStringFromName(key);
},
/**
- * Constructs a Places Transaction for the drop or paste of a blob of data
- * into a container.
- *
- * @param aData
- * The unwrapped data blob of dropped or pasted data.
- * @param aNewParentGuid
- * GUID of the container the data was dropped or pasted into.
- * @param aIndex
- * The index within the container the item was dropped or pasted at.
- * @param aCopy
- * The drag action was copy, so don't move folders or links.
- *
- * @return a Places Transaction that can be transacted for performing the
- * move/insert command.
- */
- getTransactionForData(aData, aNewParentGuid, aIndex, aCopy) {
- if (!this.SUPPORTED_FLAVORS.includes(aData.type))
- throw new Error(`Unsupported '${aData.type}' data type`);
-
- if ("itemGuid" in aData && "instanceId" in aData &&
- aData.instanceId == PlacesUtils.instanceId) {
- if (!this.PLACES_FLAVORS.includes(aData.type))
- throw new Error(`itemGuid unexpectedly set on ${aData.type} data`);
-
- let info = { guid: aData.itemGuid,
- newParentGuid: aNewParentGuid,
- newIndex: aIndex };
- if (aCopy) {
- info.excludingAnnotation = "Places/SmartBookmark";
- return PlacesTransactions.Copy(info);
- }
- return PlacesTransactions.Move(info);
- }
-
- // Since it's cheap and harmless, we allow the paste of separators and
- // bookmarks from builds that use legacy transactions (i.e. when itemGuid
- // was not set on PLACES_FLAVORS data). Containers are a different story,
- // and thus disallowed.
- if (aData.type == PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER)
- throw new Error("Can't copy a container from a legacy-transactions build");
-
- if (aData.type == PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR) {
- return PlacesTransactions.NewSeparator({ parentGuid: aNewParentGuid,
- index: aIndex });
- }
-
- let title = aData.type != PlacesUtils.TYPE_UNICODE ? aData.title
- : aData.uri;
- return PlacesTransactions.NewBookmark({ url: Services.io.newURI(aData.uri),
- title,
- parentGuid: aNewParentGuid,
- index: aIndex });
- },
-
- /**
* Shows the bookmark dialog corresponding to the specified info.
*
* @param aInfo
* Describes the item to be edited/added in the dialog.
* See documentation at the top of bookmarkProperties.js
* @param aWindow
* Owner window for the new dialog.
*
@@ -1242,19 +1187,130 @@ var PlacesUIUtils = {
try {
await functionToWrap();
} finally {
if (itemsBeingChanged > ITEM_CHANGED_BATCH_NOTIFICATION_THRESHOLD) {
resultNode.onEndUpdateBatch();
}
}
},
+
+ /**
+ * Constructs a Places Transaction for the drop or paste of a blob of data
+ * into a container.
+ *
+ * @param aData
+ * The unwrapped data blob of dropped or pasted data.
+ * @param aNewParentGuid
+ * GUID of the container the data was dropped or pasted into.
+ * @param aIndex
+ * The index within the container the item was dropped or pasted at.
+ * @param aCopy
+ * The drag action was copy, so don't move folders or links.
+ *
+ * @return a Places Transaction that can be transacted for performing the
+ * move/insert command.
+ */
+ getTransactionForData(aData, aNewParentGuid, aIndex, aCopy) {
+ if (!this.SUPPORTED_FLAVORS.includes(aData.type))
+ throw new Error(`Unsupported '${aData.type}' data type`);
+
+ if ("itemGuid" in aData && "instanceId" in aData &&
+ aData.instanceId == PlacesUtils.instanceId) {
+ if (!this.PLACES_FLAVORS.includes(aData.type))
+ throw new Error(`itemGuid unexpectedly set on ${aData.type} data`);
+
+ let info = { guid: aData.itemGuid,
+ newParentGuid: aNewParentGuid,
+ newIndex: aIndex };
+ if (aCopy) {
+ info.excludingAnnotation = "Places/SmartBookmark";
+ return PlacesTransactions.Copy(info);
+ }
+ return PlacesTransactions.Move(info);
+ }
+
+ // Since it's cheap and harmless, we allow the paste of separators and
+ // bookmarks from builds that use legacy transactions (i.e. when itemGuid
+ // was not set on PLACES_FLAVORS data). Containers are a different story,
+ // and thus disallowed.
+ if (aData.type == PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER)
+ throw new Error("Can't copy a container from a legacy-transactions build");
+
+ if (aData.type == PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR) {
+ return PlacesTransactions.NewSeparator({ parentGuid: aNewParentGuid,
+ index: aIndex });
+ }
+
+ let title = aData.type != PlacesUtils.TYPE_UNICODE ? aData.title
+ : aData.uri;
+ return PlacesTransactions.NewBookmark({ url: Services.io.newURI(aData.uri),
+ title,
+ parentGuid: aNewParentGuid,
+ index: aIndex });
+ },
+
+ /**
+ * Processes a set of transfer items that have been dropped or pasted.
+ * Batching will be applied where necessary.
+ *
+ * @param {Array} items A list of unwrapped nodes to process.
+ * @param {Object} insertionPoint The requested point for insertion.
+ * @param {Boolean} doCopy Set to true to copy the items, false will move them
+ * if possible.
+ * @paramt {Object} view The view that should be used for batching.
+ * @return {Array} Returns an empty array when the insertion point is a tag, else
+ * returns an array of copied or moved guids.
+ */
+ async handleTransferItems(items, insertionPoint, doCopy, view) {
+ let transactions;
+ let itemsCount;
+ if (insertionPoint.isTag) {
+ let urls = items.filter(item => "uri" in item).map(item => item.uri);
+ itemsCount = urls.length;
+ transactions = [PlacesTransactions.Tag({ urls, tag: insertionPoint.tagName })];
+ } else {
+ let insertionIndex = await insertionPoint.getIndex();
+ itemsCount = items.length;
+ transactions = await getTransactionsForTransferItems(
+ items, insertionIndex, insertionPoint.guid, doCopy);
+ }
+
+ // Check if we actually have something to add, if we don't it probably wasn't
+ // valid, or it was moving to the same location, so just ignore it.
+ if (!transactions.length) {
+ return [];
+ }
+
+ let guidsToSelect = [];
+ let resultForBatching = getResultForBatching(view);
+
+ // If we're inserting into a tag, we don't get the guid, so we'll just
+ // pass the transactions direct to the batch function.
+ let batchingItem = transactions;
+ if (!insertionPoint.isTag) {
+ // If we're not a tag, then we need to get the ids of the items to select.
+ batchingItem = async () => {
+ for (let transaction of transactions) {
+ let guid = await transaction.transact();
+ if (guid) {
+ guidsToSelect.push(guid);
+ }
+ }
+ };
+ }
+
+ await this.batchUpdatesForNode(resultForBatching, itemsCount, async () => {
+ await PlacesTransactions.batch(batchingItem);
+ });
+
+ return guidsToSelect;
+ },
};
-
PlacesUIUtils.PLACES_FLAVORS = [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
PlacesUtils.TYPE_X_MOZ_PLACE];
PlacesUIUtils.URI_FLAVORS = [PlacesUtils.TYPE_X_MOZ_URL,
TAB_DROP_TYPE,
PlacesUtils.TYPE_UNICODE],
@@ -1267,8 +1323,122 @@ XPCOMUtils.defineLazyGetter(PlacesUIUtil
});
XPCOMUtils.defineLazyPreferenceGetter(PlacesUIUtils, "loadBookmarksInBackground",
PREF_LOAD_BOOKMARKS_IN_BACKGROUND, false);
XPCOMUtils.defineLazyPreferenceGetter(PlacesUIUtils, "loadBookmarksInTabs",
PREF_LOAD_BOOKMARKS_IN_TABS, false);
XPCOMUtils.defineLazyPreferenceGetter(PlacesUIUtils, "openInTabClosesMenu",
"browser.bookmarks.openInTabClosesMenu", false);
+
+/**
+ * Determines if an unwrapped node can be moved.
+ *
+ * @param unwrappedNode
+ * A node unwrapped by PlacesUtils.unwrapNodes().
+ * @return True if the node can be moved, false otherwise.
+ */
+function canMoveUnwrappedNode(unwrappedNode) {
+ if ((unwrappedNode.concreteGuid && PlacesUtils.isRootItem(unwrappedNode.concreteGuid)) ||
+ unwrappedNode.id <= 0 || PlacesUtils.isRootItem(unwrappedNode.id)) {
+ return false;
+ }
+
+ let parentGuid = unwrappedNode.parentGuid;
+ // If there's no parent Guid, this was likely a virtual query that returns
+ // bookmarks, such as a tags query.
+ if (!parentGuid ||
+ parentGuid == PlacesUtils.bookmarks.rootGuid) {
+ return false;
+ }
+ // leftPaneFolderId and allBookmarksFolderId are lazy getters running
+ // at least a synchronous DB query. Therefore we don't want to invoke
+ // them first, especially because isCommandEnabled may be called way
+ // before the left pane folder is even necessary.
+ if (typeof Object.getOwnPropertyDescriptor(PlacesUIUtils, "leftPaneFolderId").get != "function" &&
+ (unwrappedNode.parent == PlacesUIUtils.leftPaneFolderId)) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * This gets the most appropriate item for using for batching. In the case of multiple
+ * views being related, the method returns the most expensive result to batch.
+ * For example, if it detects the left-hand library pane, then it will look for
+ * and return the reference to the right-hand pane.
+ *
+ * @param {Object} viewOrElement The item to check.
+ * @return {Object} Will return the best result node to batch, or null
+ * if one could not be found.
+ */
+function getResultForBatching(viewOrElement) {
+ if (viewOrElement && viewOrElement instanceof Ci.nsIDOMElement &&
+ viewOrElement.id === "placesList") {
+ // Note: fall back to the existing item if we can't find the right-hane pane.
+ viewOrElement = viewOrElement.ownerDocument.getElementById("placeContent") || viewOrElement;
+ }
+
+ if (viewOrElement && viewOrElement.result) {
+ return viewOrElement.result;
+ }
+
+ return null;
+}
+
+/**
+ * Processes a set of transfer items and returns transactions to insert or
+ * move them.
+ *
+ * @param {Array} items A list of unwrapped nodes to get transactions for.
+ * @param {Integer} insertionIndex The requested index for insertion.
+ * @param {String} insertionParentGuid The guid of the parent folder to insert
+ * or move the items to.
+ * @param {Boolean} doCopy Set to true to copy the items, false will move them
+ * if possible.
+ * @return {Array} Returns an array of created PlacesTransactions.
+ */
+async function getTransactionsForTransferItems(items, insertionIndex,
+ insertionParentGuid, doCopy) {
+ let transactions = [];
+ let index = insertionIndex;
+
+ for (let item of items) {
+ if (index != -1 && item.itemGuid) {
+ // Note: we use the parent from the existing bookmark as the sidebar
+ // gives us an unwrapped.parent that is actually a query and not the real
+ // parent.
+ let existingBookmark = await PlacesUtils.bookmarks.fetch(item.itemGuid);
+
+ // If we're dropping on the same folder, then we may need to adjust
+ // the index to insert at the correct place.
+ if (existingBookmark && insertionParentGuid == existingBookmark.parentGuid) {
+ if (index > existingBookmark.index) {
+ // If we're dragging down, we need to go one lower to insert at
+ // the real point as moving the element changes the index of
+ // everything below by 1.
+ index--;
+ } else if (index == existingBookmark.index) {
+ // This isn't moving so we skip it.
+ continue;
+ }
+ }
+ }
+
+ // If this is not a copy, check for safety that we can move the
+ // source, otherwise report an error and fallback to a copy.
+ if (!doCopy && !canMoveUnwrappedNode(item)) {
+ Components.utils.reportError("Tried to move an unmovable Places " +
+ "node, reverting to a copy operation.");
+ doCopy = true;
+ }
+ transactions.push(
+ PlacesUIUtils.getTransactionForData(item,
+ insertionParentGuid,
+ index,
+ doCopy));
+
+ if (index != -1 && item.itemGuid) {
+ index++;
+ }
+ }
+ return transactions;
+}
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -212,17 +212,17 @@ PlacesViewBase.prototype = {
tagName = container.title;
// TODO (Bug 1160193): properly support dropping on a tag root.
if (!tagName)
return null;
}
}
}
- if (PlacesControllerDragHelper.disallowInsertion(container, this))
+ if (this.controller.disallowInsertion(container))
return null;
return new PlacesInsertionPoint({
parentId: PlacesUtils.getConcreteItemId(container),
parentGuid: PlacesUtils.getConcreteItemGuid(container),
index, orientation, tagName
});
},
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -1201,17 +1201,17 @@ PlacesController.prototype = {
type = type.value;
items = PlacesUtils.unwrapNodes(data, type);
} catch (ex) {
// No supported data exists or nodes unwrap failed, just bail out.
return;
}
let doCopy = action == "copy";
- let itemsToSelect = await handleTransferItems(items, ip, doCopy, this._view);
+ let itemsToSelect = await PlacesUIUtils.handleTransferItems(items, ip, doCopy, this._view);
// Cut/past operations are not repeatable, so clear the clipboard.
if (action == "cut") {
this._clearClipboard();
}
if (itemsToSelect.length > 0)
this._view.selectItems(itemsToSelect, false);
@@ -1244,17 +1244,51 @@ PlacesController.prototype = {
* Returns the cached livemark info for a node, if set by cacheLivemarkInfo,
* null otherwise.
* @param aNode
* a places result node.
* @return the mozILivemarkInfo object for aNode, if set, null otherwise.
*/
getCachedLivemarkInfo: function PC_getCachedLivemarkInfo(aNode) {
return this._cachedLivemarkInfoObjects.get(aNode, null);
- }
+ },
+
+ /**
+ * Checks if we can insert into a container.
+ * @param container
+ * The container were we are want to drop
+ */
+ disallowInsertion(container) {
+ NS_ASSERT(container, "empty container");
+ // Allow dropping into Tag containers and editable folders.
+ return !PlacesUtils.nodeIsTagQuery(container) &&
+ (!PlacesUtils.nodeIsFolder(container) ||
+ PlacesUIUtils.isFolderReadOnly(container, this._view));
+ },
+
+ /**
+ * Determines if a node can be moved.
+ *
+ * @param aNode
+ * A nsINavHistoryResultNode node.
+ * @return True if the node can be moved, false otherwise.
+ */
+ canMoveNode(node) {
+ // Only bookmark items are movable.
+ if (node.itemId == -1)
+ return false;
+
+ // Once tags and bookmarked are divorced, the tag-query check should be
+ // removed.
+ let parentNode = node.parent;
+ return parentNode != null &&
+ PlacesUtils.nodeIsFolder(parentNode) &&
+ !PlacesUIUtils.isFolderReadOnly(parentNode, this._view) &&
+ !PlacesUtils.nodeIsTagQuery(parentNode);
+ },
};
/**
* Handles drag and drop operations for views. Note that this is view agnostic!
* You should not use PlacesController._view within these methods, since
* the view that the item(s) have been dropped on was not necessarily active.
* Drop functions are passed the view that is being dropped on.
*/
@@ -1367,72 +1401,16 @@ var PlacesControllerDragHelper = {
}
}
}
}
return true;
},
/**
- * Determines if an unwrapped node can be moved.
- *
- * @param unwrappedNode
- * A node unwrapped by PlacesUtils.unwrapNodes().
- * @return True if the node can be moved, false otherwise.
- */
- canMoveUnwrappedNode(unwrappedNode) {
- if ((unwrappedNode.concreteGuid && PlacesUtils.isRootItem(unwrappedNode.concreteGuid)) ||
- unwrappedNode.id <= 0 || PlacesUtils.isRootItem(unwrappedNode.id)) {
- return false;
- }
-
- let parentGuid = unwrappedNode.parentGuid;
- // If there's no parent Guid, this was likely a virtual query that returns
- // bookmarks, such as a tags query.
- if (!parentGuid ||
- parentGuid == PlacesUtils.bookmarks.rootGuid) {
- return false;
- }
- // leftPaneFolderId and allBookmarksFolderId are lazy getters running
- // at least a synchronous DB query. Therefore we don't want to invoke
- // them first, especially because isCommandEnabled may be called way
- // before the left pane folder is even necessary.
- if (typeof Object.getOwnPropertyDescriptor(PlacesUIUtils, "leftPaneFolderId").get != "function" &&
- (unwrappedNode.parent == PlacesUIUtils.leftPaneFolderId)) {
- return false;
- }
- return true;
- },
-
- /**
- * Determines if a node can be moved.
- *
- * @param aNode
- * A nsINavHistoryResultNode node.
- * @param aView
- * The view originating the request
- * @param [optional] aDOMNode
- * A XUL DOM node.
- * @return True if the node can be moved, false otherwise.
- */
- canMoveNode(aNode, aView) {
- // Only bookmark items are movable.
- if (aNode.itemId == -1)
- return false;
-
- // Once tags and bookmarked are divorced, the tag-query check should be
- // removed.
- let parentNode = aNode.parent;
- return parentNode != null &&
- PlacesUtils.nodeIsFolder(parentNode) &&
- !PlacesUIUtils.isFolderReadOnly(parentNode, aView) &&
- !PlacesUtils.nodeIsTagQuery(parentNode);
- },
-
- /**
* Handles the drop of one or more items onto a view.
*
* @param {Object} insertionPoint The insertion point where the items should
* be dropped.
* @param {Object} dt The dataTransfer information for the drop.
* @param {Object} view The view or the tree element. This allows
* batching to take place.
*/
@@ -1474,170 +1452,15 @@ var PlacesControllerDragHelper = {
title: data.label,
type: PlacesUtils.TYPE_X_MOZ_URL
});
} else {
throw new Error("bogus data was passed as a tab");
}
}
- await handleTransferItems(nodes, insertionPoint, doCopy, view);
+ await PlacesUIUtils.handleTransferItems(nodes, insertionPoint, doCopy, view);
},
-
- /**
- * Checks if we can insert into a container.
- * @param aContainer
- * The container were we are want to drop
- * @param aView
- * The view generating the request
- */
- disallowInsertion(aContainer, aView) {
- NS_ASSERT(aContainer, "empty container");
- // Allow dropping into Tag containers and editable folders.
- return !PlacesUtils.nodeIsTagQuery(aContainer) &&
- (!PlacesUtils.nodeIsFolder(aContainer) ||
- PlacesUIUtils.isFolderReadOnly(aContainer, aView));
- }
};
-
XPCOMUtils.defineLazyServiceGetter(PlacesControllerDragHelper, "dragService",
"@mozilla.org/widget/dragservice;1",
"nsIDragService");
-
-/**
- * This gets the most appropriate item for using for batching. In the case of multiple
- * views being related, the method returns the most expensive result to batch.
- * For example, if it detects the left-hand library pane, then it will look for
- * and return the reference to the right-hand pane.
- *
- * @param {Object} viewOrElement The item to check.
- * @return {Object} Will return the best result node to batch, or null
- * if one could not be found.
- */
-function getResultForBatching(viewOrElement) {
- if (viewOrElement && viewOrElement instanceof Ci.nsIDOMElement &&
- viewOrElement.id === "placesList") {
- // Note: fall back to the existing item if we can't find the right-hane pane.
- viewOrElement = document.getElementById("placeContent") || viewOrElement;
- }
-
- if (viewOrElement && viewOrElement.result) {
- return viewOrElement.result;
- }
-
- return null;
-}
-
-/**
- * Processes a set of transfer items that have been dropped or pasted.
- * Batching will be applied where necessary.
- *
- * @param {Array} items A list of unwrapped nodes to process.
- * @param {Object} insertionPoint The requested point for insertion.
- * @param {Boolean} doCopy Set to true to copy the items, false will move them
- * if possible.
- * @return {Array} Returns an empty array when the insertion point is a tag, else
- * returns an array of copied or moved guids.
- */
-async function handleTransferItems(items, insertionPoint, doCopy, view) {
- let transactions;
- let itemsCount;
- if (insertionPoint.isTag) {
- let urls = items.filter(item => "uri" in item).map(item => item.uri);
- itemsCount = urls.length;
- transactions = [PlacesTransactions.Tag({ urls, tag: insertionPoint.tagName })];
- } else {
- let insertionIndex = await insertionPoint.getIndex();
- itemsCount = items.length;
- transactions = await getTransactionsForTransferItems(
- items, insertionIndex, insertionPoint.guid, doCopy);
- }
-
- // Check if we actually have something to add, if we don't it probably wasn't
- // valid, or it was moving to the same location, so just ignore it.
- if (!transactions.length) {
- return [];
- }
-
- let guidsToSelect = [];
- let resultForBatching = getResultForBatching(view);
-
- // If we're inserting into a tag, we don't get the guid, so we'll just
- // pass the transactions direct to the batch function.
- let batchingItem = transactions;
- if (!insertionPoint.isTag) {
- // If we're not a tag, then we need to get the ids of the items to select.
- batchingItem = async () => {
- for (let transaction of transactions) {
- let guid = await transaction.transact();
- if (guid) {
- guidsToSelect.push(guid);
- }
- }
- };
- }
-
- await PlacesUIUtils.batchUpdatesForNode(resultForBatching, itemsCount, async () => {
- await PlacesTransactions.batch(batchingItem);
- });
-
- return guidsToSelect;
-}
-
-/**
- * Processes a set of transfer items and returns transactions to insert or
- * move them.
- *
- * @param {Array} items A list of unwrapped nodes to get transactions for.
- * @param {Integer} insertionIndex The requested index for insertion.
- * @param {String} insertionParentGuid The guid of the parent folder to insert
- * or move the items to.
- * @param {Boolean} doCopy Set to true to copy the items, false will move them
- * if possible.
- * @return {Array} Returns an array of created PlacesTransactions.
- */
-async function getTransactionsForTransferItems(items, insertionIndex,
- insertionParentGuid, doCopy) {
- let transactions = [];
- let index = insertionIndex;
-
- for (let item of items) {
- if (index != -1 && item.itemGuid) {
- // Note: we use the parent from the existing bookmark as the sidebar
- // gives us an unwrapped.parent that is actually a query and not the real
- // parent.
- let existingBookmark = await PlacesUtils.bookmarks.fetch(item.itemGuid);
-
- // If we're dropping on the same folder, then we may need to adjust
- // the index to insert at the correct place.
- if (existingBookmark && insertionParentGuid == existingBookmark.parentGuid) {
- if (index > existingBookmark.index) {
- // If we're dragging down, we need to go one lower to insert at
- // the real point as moving the element changes the index of
- // everything below by 1.
- index--;
- } else if (index == existingBookmark.index) {
- // This isn't moving so we skip it.
- continue;
- }
- }
- }
-
- // If this is not a copy, check for safety that we can move the
- // source, otherwise report an error and fallback to a copy.
- if (!doCopy && !PlacesControllerDragHelper.canMoveUnwrappedNode(item)) {
- Cu.reportError("Tried to move an unmovable Places " +
- "node, reverting to a copy operation.");
- doCopy = true;
- }
- transactions.push(
- PlacesUIUtils.getTransactionForData(item,
- insertionParentGuid,
- index,
- doCopy));
-
- if (index != -1 && item.itemGuid) {
- index++;
- }
- }
- return transactions;
-}
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -345,17 +345,17 @@
let elt = event.target;
if (!elt._placesNode)
return;
let draggedElt = elt._placesNode;
// Force a copy action if parent node is a query or we are dragging a
// not-removable node.
- if (!PlacesControllerDragHelper.canMoveNode(draggedElt, this._rootView))
+ if (!this._rootView.controller.canMoveNode(draggedElt))
event.dataTransfer.effectAllowed = "copyLink";
// Activate the view and cache the dragged element.
this._rootView._draggedElt = draggedElt;
this._rootView.controller.setDataTransfer(event);
this.setAttribute("dragstart", "true");
event.stopPropagation();
]]></handler>
--- a/browser/components/places/content/tree.xml
+++ b/browser/components/places/content/tree.xml
@@ -502,17 +502,17 @@
container = lastSelected.parent;
// See comment in the treeView.js's copy of this method
if (!container || !container.containerOpen)
return null;
// Avoid the potentially expensive call to getChildIndex
// if we know this container doesn't allow insertion
- if (PlacesControllerDragHelper.disallowInsertion(container, this))
+ if (this.controller.disallowInsertion(container))
return null;
var queryOptions = PlacesUtils.asQuery(result.root).queryOptions;
if (queryOptions.sortingMode !=
Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
// If we are within a sorted view, insert at the end
index = -1;
} else if (queryOptions.excludeItems ||
@@ -525,17 +525,17 @@
dropNearNode = lastSelected;
} else {
var lsi = container.getChildIndex(lastSelected);
index = orientation == Ci.nsITreeView.DROP_BEFORE ? lsi : lsi + 1;
}
}
}
- if (PlacesControllerDragHelper.disallowInsertion(container, this))
+ if (this.controller.disallowInsertion(container))
return null;
// TODO (Bug 1160193): properly support dropping on a tag root.
let tagName = null;
if (PlacesUtils.nodeIsTagQuery(container)) {
tagName = container.title;
if (!tagName)
return null;
@@ -757,17 +757,17 @@
if (!node.parent) {
event.preventDefault();
event.stopPropagation();
return;
}
// If this node is child of a readonly container (e.g. a livemark)
// or cannot be moved, we must force a copy.
- if (!PlacesControllerDragHelper.canMoveNode(node, this)) {
+ if (!this.controller.canMoveNode(node)) {
event.dataTransfer.effectAllowed = "copyLink";
break;
}
}
this._controller.setDataTransfer(event);
event.stopPropagation();
]]></handler>
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -1431,17 +1431,17 @@ PlacesTreeView.prototype = {
// container here. However, we can simply bail out when this happens,
// because we would then be back here in less than a millisecond, when
// the container had been reopened.
if (!container || !container.containerOpen)
return null;
// Avoid the potentially expensive call to getChildIndex
// if we know this container doesn't allow insertion.
- if (PlacesControllerDragHelper.disallowInsertion(container, this._tree.element))
+ if (this._controller.disallowInsertion(container))
return null;
let queryOptions = PlacesUtils.asQuery(this._result.root).queryOptions;
if (queryOptions.sortingMode !=
Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
// If we are within a sorted view, insert at the end.
index = -1;
} else if (queryOptions.excludeItems ||
@@ -1454,17 +1454,17 @@ PlacesTreeView.prototype = {
dropNearNode = lastSelected;
} else {
let lsi = container.getChildIndex(lastSelected);
index = orientation == Ci.nsITreeView.DROP_BEFORE ? lsi : lsi + 1;
}
}
}
- if (PlacesControllerDragHelper.disallowInsertion(container, this._tree.element))
+ if (this._controller.disallowInsertion(container))
return null;
// TODO (Bug 1160193): properly support dropping on a tag root.
let tagName = null;
if (PlacesUtils.nodeIsTagQuery(container)) {
tagName = container.title;
if (!tagName)
return null;
--- a/browser/components/places/tests/browser/browser_bookmark_folder_moveability.js
+++ b/browser/components/places/tests/browser/browser_bookmark_folder_moveability.js
@@ -23,32 +23,32 @@ add_task(async function() {
title: "",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
});
let folderId = await PlacesUtils.promiseItemId(folder.guid);
tree.selectItems([folder.guid]);
Assert.equal(tree.selectedNode.bookmarkGuid, folder.guid,
"Selected the expected node");
Assert.equal(tree.selectedNode.type, 6, "node is a folder");
- Assert.ok(PlacesControllerDragHelper.canMoveNode(tree.selectedNode, tree),
+ Assert.ok(tree.controller.canMoveNode(tree.selectedNode),
"can move regular folder node");
info("Test a folder shortcut");
let shortcut = await PlacesUtils.bookmarks.insert({
parentGuid: root.guid,
title: "bar",
url: `place:folder=${folderId}`
});
tree.selectItems([shortcut.guid]);
Assert.equal(tree.selectedNode.bookmarkGuid, shortcut.guid,
"Selected the expected node");
Assert.equal(tree.selectedNode.type, 9, "node is a folder shortcut");
Assert.equal(PlacesUtils.getConcreteItemGuid(tree.selectedNode),
folder.guid, "shortcut node guid and concrete guid match");
- Assert.ok(PlacesControllerDragHelper.canMoveNode(tree.selectedNode, tree),
+ Assert.ok(tree.controller.canMoveNode(tree.selectedNode),
"can move folder shortcut node");
info("Test a query");
let bookmark = await PlacesUtils.bookmarks.insert({
parentGuid: root.guid,
title: "",
url: "http://foo.com",
});
@@ -58,53 +58,53 @@ add_task(async function() {
let query = await PlacesUtils.bookmarks.insert({
parentGuid: root.guid,
title: "bar",
url: `place:terms=foo`
});
tree.selectItems([query.guid]);
Assert.equal(tree.selectedNode.bookmarkGuid, query.guid,
"Selected the expected node");
- Assert.ok(PlacesControllerDragHelper.canMoveNode(tree.selectedNode, tree),
+ Assert.ok(tree.controller.canMoveNode(tree.selectedNode),
"can move query node");
info("Test a tag container");
PlacesUtils.tagging.tagURI(Services.io.newURI(bookmark.url.href), ["bar"]);
// Add the tags root query.
let tagsQuery = await PlacesUtils.bookmarks.insert({
parentGuid: root.guid,
title: "",
url: "place:type=" + Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY,
});
tree.selectItems([tagsQuery.guid]);
PlacesUtils.asQuery(tree.selectedNode).containerOpen = true;
Assert.equal(tree.selectedNode.childCount, 1, "has tags");
let tagNode = tree.selectedNode.getChild(0);
- Assert.ok(!PlacesControllerDragHelper.canMoveNode(tagNode, tree),
+ Assert.ok(!tree.controller.canMoveNode(tagNode),
"should not be able to move tag container node");
tree.selectedNode.containerOpen = false;
info("Test that special folders and cannot be moved but other shortcuts can.");
let roots = [
PlacesUtils.bookmarks.menuGuid,
PlacesUtils.bookmarks.unfiledGuid,
PlacesUtils.bookmarks.toolbarGuid,
];
for (let guid of roots) {
tree.selectItems([guid]);
- Assert.ok(!PlacesControllerDragHelper.canMoveNode(tree.selectedNode, tree),
+ Assert.ok(!tree.controller.canMoveNode(tree.selectedNode),
"shouldn't be able to move default shortcuts to roots");
let id = await PlacesUtils.promiseItemId(guid);
let s = await PlacesUtils.bookmarks.insert({
parentGuid: root.guid,
title: "bar",
url: `place:folder=${id}`,
});
tree.selectItems([s.guid]);
Assert.equal(tree.selectedNode.bookmarkGuid, s.guid,
"Selected the expected node");
- Assert.ok(PlacesControllerDragHelper.canMoveNode(tree.selectedNode, tree),
+ Assert.ok(tree.controller.canMoveNode(tree.selectedNode),
"should be able to move user-created shortcuts to roots");
}
});
});