diff --git a/browser/components/places/PlacesUIUtils.sys.mjs b/browser/components/places/PlacesUIUtils.sys.mjs index 710f755fe986..1f5e163bae58 100644 --- a/browser/components/places/PlacesUIUtils.sys.mjs +++ b/browser/components/places/PlacesUIUtils.sys.mjs @@ -1520,48 +1520,9 @@ export var PlacesUIUtils = { let window = this.triggerNode.ownerGlobal; switch (command) { case "placesCmd_copy": { - // This is a little hacky, but there is a lot of code in Places that handles - // clipboard stuff, so it's easier to reuse. - let node = {}; - node.type = 0; - node.title = this.triggerNode.label; - node.uri = this.triggerNode.link; - - // Copied from _populateClipboard in controller.js - - // This order is _important_! It controls how this and other applications - // select data to be inserted based on type. - let contents = [ - { type: lazy.PlacesUtils.TYPE_X_MOZ_URL, entries: [] }, - { type: lazy.PlacesUtils.TYPE_HTML, entries: [] }, - { type: lazy.PlacesUtils.TYPE_PLAINTEXT, entries: [] }, - ]; - - contents.forEach(function (content) { - content.entries.push(lazy.PlacesUtils.wrapNode(node, content.type)); - }); - - let xferable = Cc[ - "@mozilla.org/widget/transferable;1" - ].createInstance(Ci.nsITransferable); - xferable.init(null); - - function addData(type, data) { - xferable.addDataFlavor(type); - xferable.setTransferData( - type, - lazy.PlacesUtils.toISupportsString(data) - ); - } - - contents.forEach(function (content) { - addData(content.type, content.entries.join(lazy.PlacesUtils.endl)); - }); - - Services.clipboard.setData( - xferable, - null, - Ci.nsIClipboard.kGlobalClipboard + lazy.BrowserUtils.copyLink( + this.triggerNode.link, + this.triggerNode.label ); break; } diff --git a/toolkit/components/places/PlacesUtils.sys.mjs b/toolkit/components/places/PlacesUtils.sys.mjs index 40870c43a79e..357363850d20 100644 --- a/toolkit/components/places/PlacesUtils.sys.mjs +++ b/toolkit/components/places/PlacesUtils.sys.mjs @@ -972,6 +972,40 @@ export var PlacesUtils = { return url.host.split("").reverse().join("") + "."; }, + /** + * Copy a single places result node, recursively if applicable. + * + * @param {Object} node + * The node to copy. If not a real places node but a single + * title/URL combination, you must set `type` to 0 (aka RESULT_TYPE_URI), + * and provide a `title` and `uri` property which should both be strings. + */ + copyNode(node) { + // This order is _important_! It controls how this and other applications + // select data to be inserted based on type. + let contentTypes = [ + this.TYPE_X_MOZ_URL, + this.TYPE_HTML, + this.TYPE_PLAINTEXT, + ]; + + let xferable = Cc["@mozilla.org/widget/transferable;1"].createInstance( + Ci.nsITransferable + ); + xferable.init(null); + for (let contentType of contentTypes) { + xferable.addDataFlavor(contentType); + let data = this.wrapNode(node, contentType); + xferable.setTransferData(contentType, this.toISupportsString(data)); + } + + Services.clipboard.setData( + xferable, + null, + Ci.nsIClipboard.kGlobalClipboard + ); + }, + /** * String-wraps a result node according to the rules of the specified * content type for copy or move operations. diff --git a/toolkit/modules/BrowserUtils.sys.mjs b/toolkit/modules/BrowserUtils.sys.mjs index d4068f284b0a..257d72c6dcf7 100644 --- a/toolkit/modules/BrowserUtils.sys.mjs +++ b/toolkit/modules/BrowserUtils.sys.mjs @@ -9,6 +9,7 @@ import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { + PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", ReaderMode: "moz-src:///toolkit/components/reader/ReaderMode.sys.mjs", Region: "resource://gre/modules/Region.sys.mjs", }); @@ -144,6 +145,24 @@ export var BrowserUtils = { ); }, + /** + * Copy a link with a text label to the clipboard. + * + * @param {string} url + * The URL we're wanting to copy to the clipboard. + * @param {string} title + * The label/title of the URL + */ + copyLink(url, title) { + // This is a little hacky, but there is a lot of code in Places that handles + // clipboard stuff, so it's easier to reuse. + let node = {}; + node.type = 0; + node.title = title; + node.uri = url; + lazy.PlacesUtils.copyNode(node); + }, + /** * Returns true if |mimeType| is text-based, or false otherwise. *