mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1725487 - Show the Add Bookmark Dialog when dragging javascript url to create a bookmarklet. r=mak
Differential Revision: https://phabricator.services.mozilla.com/D133813
This commit is contained in:
parent
f56a316fd8
commit
960d138fc9
@ -1542,7 +1542,7 @@ var PlacesControllerDragHelper = {
|
||||
* @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
|
||||
* @param {object} [view] The view or the tree element. This allows
|
||||
* batching to take place.
|
||||
*/
|
||||
async onDrop(insertionPoint, dt, view) {
|
||||
@ -1559,6 +1559,7 @@ var PlacesControllerDragHelper = {
|
||||
// DataTransfer is only valid during the synchronous handling of the `drop`
|
||||
// event handler callback.
|
||||
let nodes = [];
|
||||
let externalDrag = false;
|
||||
for (let i = 0; i < dropCount; ++i) {
|
||||
let flavor = this.getFirstValidFlavor(dt.mozTypesAt(i));
|
||||
if (!flavor) {
|
||||
@ -1574,6 +1575,11 @@ var PlacesControllerDragHelper = {
|
||||
handled.add(data);
|
||||
}
|
||||
|
||||
// Check that the drag/drop is not internal
|
||||
if (i == 0 && !flavor.startsWith("text/x-moz-place")) {
|
||||
externalDrag = true;
|
||||
}
|
||||
|
||||
if (flavor != TAB_DROP_TYPE) {
|
||||
nodes = [...nodes, ...PlacesUtils.unwrapNodes(data, flavor)];
|
||||
} else if (
|
||||
@ -1593,6 +1599,41 @@ var PlacesControllerDragHelper = {
|
||||
}
|
||||
}
|
||||
|
||||
// If a single javascript url is being dropped from the urlbar or an external source,
|
||||
// show the bookmark dialog as a speedbump protection against malicious cases.
|
||||
if (
|
||||
nodes.length == 1 &&
|
||||
externalDrag &&
|
||||
nodes[0].uri?.startsWith("javascript")
|
||||
) {
|
||||
let uri;
|
||||
try {
|
||||
uri = Services.io.newURI(nodes[0].uri);
|
||||
} catch (ex) {
|
||||
// Invalid uri, we skip this code and the entry will be discarded later.
|
||||
}
|
||||
|
||||
if (uri) {
|
||||
let bookmarkGuid = await PlacesUIUtils.showBookmarkDialog(
|
||||
{
|
||||
action: "add",
|
||||
type: "bookmark",
|
||||
defaultInsertionPoint: insertionPoint,
|
||||
hiddenRows: ["folderPicker"],
|
||||
title: nodes[0].title,
|
||||
uri,
|
||||
},
|
||||
BrowserWindowTracker.getTopWindow() // `window` may be the Library.
|
||||
);
|
||||
|
||||
if (bookmarkGuid && view) {
|
||||
view.selectItems([bookmarkGuid], false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await PlacesUIUtils.handleTransferItems(
|
||||
nodes,
|
||||
insertionPoint,
|
||||
|
@ -129,6 +129,7 @@ skip-if = os == "linux" && (tsan || asan) # Bug 1714384
|
||||
skip-if = (os == "mac" && debug) # Bug 1467049
|
||||
[browser_sort_in_library.js]
|
||||
[browser_stayopenmenu.js]
|
||||
[browser_toolbar_drop_bookmarklet.js]
|
||||
[browser_toolbar_drop_text.js]
|
||||
skip-if = os == "linux" && (tsan || asan) # Bug 1714384
|
||||
[browser_toolbar_library_open_recent.js]
|
||||
|
@ -0,0 +1,196 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const { sinon } = ChromeUtils.import("resource://testing-common/Sinon.jsm");
|
||||
const sandbox = sinon.createSandbox();
|
||||
|
||||
const URL1 = "https://example.com/1/";
|
||||
const URL2 = "https://example.com/2/";
|
||||
const BOOKMARKLET_URL = `javascript: (() => {alert('Hello, World!');})();`;
|
||||
let bookmarks;
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
add_task(async function test() {
|
||||
// Make sure the bookmarks bar is visible and restore its state on cleanup.
|
||||
let toolbar = document.getElementById("PersonalToolbar");
|
||||
ok(toolbar, "PersonalToolbar should not be null");
|
||||
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
if (toolbar.collapsed) {
|
||||
await promiseSetToolbarVisibility(toolbar, true);
|
||||
registerCleanupFunction(function() {
|
||||
return promiseSetToolbarVisibility(toolbar, false);
|
||||
});
|
||||
}
|
||||
// Setup the node we will use to be dropped. The actual node used does not
|
||||
// matter because we will set its data, effect, and mimeType manually.
|
||||
let placesItems = document.getElementById("PlacesToolbarItems");
|
||||
Assert.ok(placesItems, "PlacesToolbarItems should not be null");
|
||||
|
||||
/**
|
||||
* Simulates a drop of a bookmarklet URI onto the bookmarks bar.
|
||||
*
|
||||
* @param {string} aEffect
|
||||
* The effect to use for the drop operation: move, copy, or link.
|
||||
* @param {string} aMimeType
|
||||
* The mime type to use for the drop operation.
|
||||
*/
|
||||
let simulateDragDrop = async function(aEffect) {
|
||||
info("Simulates drag/drop of a new javascript:URL to the bookmarks");
|
||||
await withBookmarksDialog(
|
||||
true,
|
||||
function openDialog() {
|
||||
EventUtils.synthesizeDrop(
|
||||
toolbar,
|
||||
placesItems,
|
||||
[[{ type: "text/x-moz-url", data: BOOKMARKLET_URL }]],
|
||||
aEffect,
|
||||
window
|
||||
);
|
||||
},
|
||||
async function testNameField(dialogWin) {
|
||||
info("Checks that there is a javascript:URL in ShowBookmarksDialog");
|
||||
|
||||
let location = dialogWin.document.getElementById(
|
||||
"editBMPanel_locationField"
|
||||
).value;
|
||||
|
||||
Assert.equal(
|
||||
location,
|
||||
BOOKMARKLET_URL,
|
||||
"Should have opened the ShowBookmarksDialog with the correct bookmarklet url to be bookmarked"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
info("Simulates drag/drop of a new URL to the bookmarks");
|
||||
let spy = sandbox
|
||||
.stub(PlacesUIUtils, "showBookmarkDialog")
|
||||
.returns(Promise.resolve());
|
||||
|
||||
let promise = PlacesTestUtils.waitForNotification(
|
||||
"bookmark-added",
|
||||
events => events.some(({ url }) => url == URL1),
|
||||
"places"
|
||||
);
|
||||
|
||||
EventUtils.synthesizeDrop(
|
||||
toolbar,
|
||||
placesItems,
|
||||
[[{ type: "text/x-moz-url", data: URL1 }]],
|
||||
aEffect,
|
||||
window
|
||||
);
|
||||
|
||||
await promise;
|
||||
Assert.ok(spy.notCalled, "ShowBookmarksDialog on drop not called for url");
|
||||
sandbox.restore();
|
||||
};
|
||||
|
||||
let effects = ["copy", "link"];
|
||||
for (let effect of effects) {
|
||||
await simulateDragDrop(effect);
|
||||
}
|
||||
|
||||
info("Move of existing bookmark / bookmarklet on toolbar");
|
||||
//clean previous bookmarks to ensure right ids count
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
info("Insert list of bookamrks to have bookamrks (ids) for moving");
|
||||
bookmarks = await PlacesUtils.bookmarks.insertTree({
|
||||
guid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
children: [
|
||||
{
|
||||
title: "bm1",
|
||||
url: URL1,
|
||||
},
|
||||
{
|
||||
title: "bm2",
|
||||
url: URL2,
|
||||
},
|
||||
{
|
||||
title: "bookmarklet",
|
||||
url: BOOKMARKLET_URL,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let spy = sandbox
|
||||
.stub(PlacesUIUtils, "showBookmarkDialog")
|
||||
.returns(Promise.resolve());
|
||||
|
||||
info("Moving existing Bookmark from position [1] to [0] on Toolbar");
|
||||
let urlMoveNotification = PlacesTestUtils.waitForNotification(
|
||||
"bookmark-moved",
|
||||
events =>
|
||||
events.some(
|
||||
e =>
|
||||
e.parentGuid === PlacesUtils.bookmarks.toolbarGuid &&
|
||||
e.oldParentGuid === PlacesUtils.bookmarks.toolbarGuid &&
|
||||
e.oldIndex == 1 &&
|
||||
e.index == 0
|
||||
),
|
||||
"places"
|
||||
);
|
||||
|
||||
EventUtils.synthesizeDrop(
|
||||
toolbar,
|
||||
placesItems.childNodes[0],
|
||||
[
|
||||
[
|
||||
{
|
||||
type: "text/x-moz-place",
|
||||
data: PlacesUtils.wrapNode(
|
||||
placesItems.childNodes[1]._placesNode,
|
||||
"text/x-moz-place"
|
||||
),
|
||||
},
|
||||
],
|
||||
],
|
||||
"move",
|
||||
window
|
||||
);
|
||||
|
||||
await urlMoveNotification;
|
||||
Assert.ok(spy.notCalled, "ShowBookmarksDialog not called on move for url");
|
||||
|
||||
info("Moving existing Bookmarklet from position [2] to [1] on Toolbar");
|
||||
let bookmarkletMoveNotificatio = PlacesTestUtils.waitForNotification(
|
||||
"bookmark-moved",
|
||||
events =>
|
||||
events.some(
|
||||
e =>
|
||||
e.parentGuid === PlacesUtils.bookmarks.toolbarGuid &&
|
||||
e.oldParentGuid === PlacesUtils.bookmarks.toolbarGuid &&
|
||||
e.oldIndex == 2 &&
|
||||
e.index == 1
|
||||
),
|
||||
"places"
|
||||
);
|
||||
|
||||
EventUtils.synthesizeDrop(
|
||||
toolbar,
|
||||
placesItems.childNodes[1],
|
||||
[
|
||||
[
|
||||
{
|
||||
type: "text/x-moz-place",
|
||||
data: PlacesUtils.wrapNode(
|
||||
placesItems.childNodes[2]._placesNode,
|
||||
"text/x-moz-place"
|
||||
),
|
||||
},
|
||||
],
|
||||
],
|
||||
"move",
|
||||
window
|
||||
);
|
||||
|
||||
await bookmarkletMoveNotificatio;
|
||||
Assert.ok(spy.notCalled, "ShowBookmarksDialog not called on move for url");
|
||||
sandbox.restore();
|
||||
});
|
Loading…
Reference in New Issue
Block a user