1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import {
UrlbarProvider,
UrlbarUtils,
} from "resource:///modules/UrlbarUtils.sys.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
UrlbarResult: "resource:///modules/UrlbarResult.sys.mjs",
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
UrlbarTokenizer: "resource:///modules/UrlbarTokenizer.sys.mjs",
});
const RESULT_MENU_COMMANDS = {
DISMISS: "dismiss",
};
const CLIPBOARD_IMPRESSION_LIMIT = 2;
/**
* A provider that returns a suggested url to the user based
* on a valid URL stored in the clipboard.
*/
class ProviderClipboard extends UrlbarProvider {
#previousClipboard = {
value: "",
impressionsLeft: CLIPBOARD_IMPRESSION_LIMIT,
};
constructor() {
super();
}
get name() {
return "UrlbarProviderClipboard";
}
/**
* @returns {Values<typeof UrlbarUtils.PROVIDER_TYPE>}
*/
get type() {
return UrlbarUtils.PROVIDER_TYPE.PROFILE;
}
setPreviousClipboardValue(newValue) {
this.#previousClipboard.value = newValue;
}
async isActive(queryContext, controller) {
// Return clipboard results only for empty searches.
if (
!lazy.UrlbarPrefs.get("clipboard.featureGate") ||
!lazy.UrlbarPrefs.get("suggest.clipboard") ||
queryContext.searchString ||
queryContext.searchMode
) {
return false;
}
let textFromClipboard = controller.browserWindow.readFromClipboard();
// Check for spaces in clipboard text to avoid suggesting
// clipboard content including both a url and the following text.
if (
!textFromClipboard ||
textFromClipboard.length > 2048 ||
lazy.UrlbarTokenizer.REGEXP_SPACES.test(textFromClipboard)
) {
return false;
}
textFromClipboard =
controller.input.sanitizeTextFromClipboard(textFromClipboard);
const validUrl = this.#validUrl(textFromClipboard);
if (!validUrl) {
return false;
}
if (this.#previousClipboard.value === validUrl) {
if (this.#previousClipboard.impressionsLeft <= 0) {
return false;
}
} else {
this.#previousClipboard = {
value: validUrl,
impressionsLeft: CLIPBOARD_IMPRESSION_LIMIT,
};
}
return true;
}
#validUrl(clipboardVal) {
let givenUrl = URL.parse(clipboardVal);
if (!givenUrl) {
// Not a valid URI.
return null;
}
if (givenUrl.protocol == "http:" || givenUrl.protocol == "https:") {
return givenUrl.href;
}
return null;
}
getPriority() {
// Zero-prefix suggestions have the same priority as top sites.
return 1;
}
async startQuery(queryContext, addCallback) {
// If the query was started, isActive should have cached a url already.
let result = new lazy.UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
...lazy.UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, {
fallbackTitle: [
UrlbarUtils.prepareUrlForDisplay(this.#previousClipboard.value, {
trimURL: false,
}),
UrlbarUtils.HIGHLIGHT.NONE,
],
url: [this.#previousClipboard.value, UrlbarUtils.HIGHLIGHT.NONE],
icon: "chrome://global/skin/icons/clipboard.svg",
isBlockable: true,
})
);
addCallback(this, result);
}
onEngagement(queryContext, controller, details) {
this.#previousClipboard.impressionsLeft = 0; // User has picked the suggested clipboard result
// Handle commands.
this.#handlePossibleCommand(
controller.view,
details.result,
details.selType
);
}
onImpression() {
this.#previousClipboard.impressionsLeft--;
}
#handlePossibleCommand(view, result, selType) {
switch (selType) {
case RESULT_MENU_COMMANDS.DISMISS:
view.controller.removeResult(result);
this.#previousClipboard.impressionsLeft = 0;
break;
}
}
}
const UrlbarProviderClipboard = new ProviderClipboard();
export { UrlbarProviderClipboard, CLIPBOARD_IMPRESSION_LIMIT };
|