- : 100 %
- : 57 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 84 %
- : 100 %
- : 100 %
- : 84 %
- : 100 %
- : 84 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 84 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 71 %
- : 100 %
- : 100 %
- : 71 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 85 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 51 %
- : 85 %
- : 71 %
- : 85 %
- : 100 %
- : 100 %
- : 85 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 89 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 89 %
- : 89 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 100 %
- : 89 %
- : 100 %
- : 84 %
- : 100 %
- : 100 %
Source code
Revision control
Copy as Markdown
Other Tools
/* 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 { SuggestProvider } from "moz-src:///browser/components/urlbar/private/SuggestFeature.sys.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
QuickSuggest: "moz-src:///browser/components/urlbar/QuickSuggest.sys.mjs",
UrlbarPrefs: "moz-src:///browser/components/urlbar/UrlbarPrefs.sys.mjs",
UrlbarResult: "moz-src:///browser/components/urlbar/UrlbarResult.sys.mjs",
UrlbarUtils: "moz-src:///browser/components/urlbar/UrlbarUtils.sys.mjs",
});
/**
* A feature that manages the dynamic Rust suggestion types defined in the
* `quickSuggestDynamicSuggestionTypes` Nimbus variable or its related pref
* `quicksuggest.dynamicSuggestionTypes`. Dynamic Rust suggestions are not
* statically typed except for a few core properties, so they can be used to
* serve many different types of suggestions without any Rust changes. They are
* also used for hidden-exposure suggestions (potential exposures).
*
* This feature only manages the types defined in the variable or pref. Other
* features can manage dynamic suggestion types that are *not* defined in the
* variable or pref by extending `SuggestProvider` as usual and overriding the
* `dynamicRustSuggestionTypes` getter. That makes it possible for a feature to
* use dynamic suggestions as an implementation detail.
*/
export class DynamicSuggestions extends SuggestProvider {
get enablingPreferences() {
return ["quicksuggest.dynamicSuggestionTypes"];
}
get shouldEnable() {
return !!this.dynamicRustSuggestionTypes.length;
}
get rustSuggestionType() {
return "Dynamic";
}
get dynamicRustSuggestionTypes() {
// UrlbarPrefs converts this pref to a `Set` of type strings.
return [...lazy.UrlbarPrefs.get("quicksuggest.dynamicSuggestionTypes")];
}
isSuggestionSponsored(suggestion) {
return !!suggestion.data?.result?.payload?.isSponsored;
}
getSuggestionTelemetryType(suggestion) {
if (suggestion.data?.result?.payload?.hasOwnProperty("telemetryType")) {
return suggestion.data.result.payload.telemetryType;
}
if (suggestion.data?.result?.isHiddenExposure) {
return "exposure";
}
return suggestion.suggestionType;
}
makeResult(queryContext, suggestion, _searchString) {
let { data } = suggestion;
if (!data || typeof data != "object") {
this.logger.warn(
"suggestion.data is falsey or not an object, ignoring suggestion"
);
return null;
}
let { result } = data;
if (!result || typeof result != "object") {
this.logger.warn(
"suggestion.data.result is falsey or not an object, ignoring suggestion"
);
return null;
}
let payload = {};
if (result.hasOwnProperty("payload")) {
if (typeof result.payload != "object") {
this.logger.warn(
"suggestion.data.result.payload is not an object, ignoring suggestion"
);
return null;
}
payload = result.payload;
}
if (result.isHiddenExposure) {
return this.#makeExposureResult(suggestion, payload);
}
// Dynamic results can set `result.bypassSuggestAll` to be shown even when
// `suggest.quicksuggest.all` is false. Typically results should not do this
// unless they aren't considered part of the Suggest brand.
if (
!result.bypassSuggestAll &&
(!lazy.UrlbarPrefs.get("suggest.quicksuggest.all") ||
(payload.isSponsored &&
!lazy.UrlbarPrefs.get("suggest.quicksuggest.sponsored")))
) {
return null;
}
payload.isManageable = true;
payload.helpUrl = lazy.QuickSuggest.HELP_URL;
let resultProperties = { ...result };
delete resultProperties.payload;
return new lazy.UrlbarResult({
type: lazy.UrlbarUtils.RESULT_TYPE.URL,
source: lazy.UrlbarUtils.RESULT_SOURCE.SEARCH,
...resultProperties,
payload,
});
}
onEngagement(_queryContext, controller, details, _searchString) {
switch (details.selType) {
case "manage":
// "manage" is handled by UrlbarInput, no need to do anything here.
break;
case "dismiss": {
let { result } = details;
lazy.QuickSuggest.dismissResult(result);
result.acknowledgeDismissalL10n = {
id: "firefox-suggest-dismissal-acknowledgment-one",
};
controller.removeResult(result);
break;
}
}
}
#makeExposureResult(suggestion, payload) {
// It doesn't really matter what kind of result we return since it won't be
// shown. Use a dynamic result since that kind of makes sense and there are
// no requirements for its payload other than `dynamicType`.
return new lazy.UrlbarResult({
type: lazy.UrlbarUtils.RESULT_TYPE.DYNAMIC,
source: lazy.UrlbarUtils.RESULT_SOURCE.SEARCH,
// Exposure suggestions should always be hidden, and it's assumed that
// exposure telemetry should be recorded for them, so as a convenience
// set `exposureTelemetry` here. Otherwise experiments would need to set
// the corresponding Nimbus variables properly. (They can still do that,
// it's just not required.)
exposureTelemetry: lazy.UrlbarUtils.EXPOSURE_TELEMETRY.HIDDEN,
payload: {
...payload,
dynamicType: "exposure",
},
});
}
}