Bug 1963600: Implement VPN Suggestions r=desktop-theme-reviewers,adw,dao
Differential Revision: https://phabricator.services.mozilla.com/D247284
This commit is contained in:
committed by
dakatsuka.birchill@mozilla.com
parent
c1e56ab969
commit
c4be79e31b
@@ -265,7 +265,7 @@ class ProviderQuickSuggest extends UrlbarProvider {
|
|||||||
let { result } = details;
|
let { result } = details;
|
||||||
|
|
||||||
// Delegate to the result's feature if there is one.
|
// Delegate to the result's feature if there is one.
|
||||||
let feature = lazy.QuickSuggest.getFeatureByResult(details.result);
|
let feature = lazy.QuickSuggest.getFeatureByResult(result);
|
||||||
if (feature) {
|
if (feature) {
|
||||||
feature.onEngagement(
|
feature.onEngagement(
|
||||||
queryContext,
|
queryContext,
|
||||||
|
|||||||
@@ -117,6 +117,22 @@ export class DynamicSuggestions extends SuggestProvider {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
#makeExposureResult(suggestion, payload) {
|
||||||
// It doesn't really matter what kind of result we return since it won't be
|
// 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
|
// shown. Use a dynamic result since that kind of makes sense and there are
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ prefs = ["browser.bookmarks.testing.skipDefaultBookmarksImport=true"]
|
|||||||
|
|
||||||
["browser_quicksuggest_contextual_optin.js"]
|
["browser_quicksuggest_contextual_optin.js"]
|
||||||
|
|
||||||
|
["browser_quicksuggest_dynamicSuggestions.js"]
|
||||||
|
|
||||||
["browser_quicksuggest_fakespot.js"]
|
["browser_quicksuggest_fakespot.js"]
|
||||||
|
|
||||||
["browser_quicksuggest_indexes.js"]
|
["browser_quicksuggest_indexes.js"]
|
||||||
|
|||||||
@@ -0,0 +1,252 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test for dynamicSuggestions.
|
||||||
|
|
||||||
|
const REMOTE_SETTINGS_DATA = [
|
||||||
|
{
|
||||||
|
type: "dynamic-suggestions",
|
||||||
|
suggestion_type: "basic",
|
||||||
|
attachment: [
|
||||||
|
{
|
||||||
|
keywords: ["basic"],
|
||||||
|
data: {
|
||||||
|
result: {
|
||||||
|
payload: {
|
||||||
|
title: "basic",
|
||||||
|
url: "https://example.com/basic",
|
||||||
|
icon: "https://example.com/basic.svg",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "dynamic-suggestions",
|
||||||
|
suggestion_type: "shouldShowUrl",
|
||||||
|
attachment: [
|
||||||
|
{
|
||||||
|
keywords: ["shouldshowurl"],
|
||||||
|
data: {
|
||||||
|
result: {
|
||||||
|
payload: {
|
||||||
|
title: "shouldShowUrl",
|
||||||
|
url: "https://example.com/shouldShowUrl",
|
||||||
|
icon: "https://example.com/shouldShowUrl.svg",
|
||||||
|
shouldShowUrl: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "dynamic-suggestions",
|
||||||
|
suggestion_type: "isBlockable",
|
||||||
|
attachment: [
|
||||||
|
{
|
||||||
|
keywords: ["isblockable"],
|
||||||
|
dismissal_key: "isblockable-dismissal-key",
|
||||||
|
data: {
|
||||||
|
result: {
|
||||||
|
payload: {
|
||||||
|
title: "isBlockable",
|
||||||
|
url: "https://example.com/isBlockable",
|
||||||
|
icon: "https://example.com/isBlockable.svg",
|
||||||
|
isBlockable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "dynamic-suggestions",
|
||||||
|
suggestion_type: "rowLabel",
|
||||||
|
attachment: [
|
||||||
|
{
|
||||||
|
keywords: ["rowlabel"],
|
||||||
|
data: {
|
||||||
|
result: {
|
||||||
|
rowLabel: {
|
||||||
|
id: "urlbar-group-search-suggestions",
|
||||||
|
args: { engine: "Test" },
|
||||||
|
},
|
||||||
|
payload: {
|
||||||
|
url: "https://example.com/rowLabel",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
add_setup(async function () {
|
||||||
|
await QuickSuggestTestUtils.ensureQuickSuggestInit({
|
||||||
|
remoteSettingsRecords: REMOTE_SETTINGS_DATA,
|
||||||
|
});
|
||||||
|
await UrlbarTestUtils.initNimbusFeature({
|
||||||
|
quickSuggestDynamicSuggestionTypes:
|
||||||
|
"basic,shouldShowUrl,isBlockable,rowLabel",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait until dynamic suggestion is available.
|
||||||
|
await BrowserTestUtils.waitForCondition(async () => {
|
||||||
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||||
|
window,
|
||||||
|
value: "basic",
|
||||||
|
});
|
||||||
|
const result = UrlbarTestUtils.getResultCount(window) == 2;
|
||||||
|
await UrlbarTestUtils.promisePopupClose(window);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function basic() {
|
||||||
|
await BrowserTestUtils.withNewTab("about:blank", async () => {
|
||||||
|
info("Open urlbar with keyword");
|
||||||
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||||
|
window,
|
||||||
|
value: "basic",
|
||||||
|
});
|
||||||
|
Assert.equal(UrlbarTestUtils.getResultCount(window), 2);
|
||||||
|
|
||||||
|
info("Check the result");
|
||||||
|
const { element, result } = await UrlbarTestUtils.getDetailsOfResultAt(
|
||||||
|
window,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
Assert.equal(result.providerName, UrlbarProviderQuickSuggest.name);
|
||||||
|
Assert.equal(result.payload.provider, "Dynamic");
|
||||||
|
assertUI(
|
||||||
|
element.row,
|
||||||
|
REMOTE_SETTINGS_DATA[0].attachment[0].data.result.payload
|
||||||
|
);
|
||||||
|
|
||||||
|
info("Activate this item");
|
||||||
|
const onLoad = BrowserTestUtils.browserLoaded(
|
||||||
|
gBrowser.selectedBrowser,
|
||||||
|
false,
|
||||||
|
result.payload.url
|
||||||
|
);
|
||||||
|
EventUtils.synthesizeMouseAtCenter(element.row, {});
|
||||||
|
await onLoad;
|
||||||
|
Assert.ok(true, "Expected page is loaded");
|
||||||
|
});
|
||||||
|
|
||||||
|
await PlacesUtils.history.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function basic_learn_more() {
|
||||||
|
info("Open urlbar with keyword");
|
||||||
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||||
|
window,
|
||||||
|
value: "basic",
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Selecting Learn more item from the result menu");
|
||||||
|
let tabOpenPromise = BrowserTestUtils.waitForNewTab(
|
||||||
|
gBrowser,
|
||||||
|
QuickSuggest.HELP_URL
|
||||||
|
);
|
||||||
|
await UrlbarTestUtils.openResultMenuAndClickItem(window, "help", {
|
||||||
|
resultIndex: 1,
|
||||||
|
});
|
||||||
|
await tabOpenPromise;
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function basic_manage() {
|
||||||
|
await doManageTest({ index: 1, input: "basic" });
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function shouldShowUrl() {
|
||||||
|
await BrowserTestUtils.withNewTab("about:blank", async () => {
|
||||||
|
info("Open urlbar with keyword");
|
||||||
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||||
|
window,
|
||||||
|
value: "shouldshowurl",
|
||||||
|
});
|
||||||
|
Assert.equal(UrlbarTestUtils.getResultCount(window), 2);
|
||||||
|
|
||||||
|
info("Check the result");
|
||||||
|
const { element, result } = await UrlbarTestUtils.getDetailsOfResultAt(
|
||||||
|
window,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
Assert.equal(result.providerName, UrlbarProviderQuickSuggest.name);
|
||||||
|
Assert.equal(result.payload.provider, "Dynamic");
|
||||||
|
assertUI(
|
||||||
|
element.row,
|
||||||
|
REMOTE_SETTINGS_DATA[1].attachment[0].data.result.payload
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function isBlockable() {
|
||||||
|
await BrowserTestUtils.withNewTab("about:blank", async () => {
|
||||||
|
info("Open urlbar with keyword");
|
||||||
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||||
|
window,
|
||||||
|
value: "isblockable",
|
||||||
|
});
|
||||||
|
Assert.equal(UrlbarTestUtils.getResultCount(window), 2);
|
||||||
|
|
||||||
|
info("Check the result");
|
||||||
|
const { result } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
|
||||||
|
Assert.equal(result.providerName, UrlbarProviderQuickSuggest.name);
|
||||||
|
Assert.equal(result.payload.provider, "Dynamic");
|
||||||
|
|
||||||
|
info("Dismiss this item");
|
||||||
|
let dismissalPromise = TestUtils.topicObserved(
|
||||||
|
"quicksuggest-dismissals-changed"
|
||||||
|
);
|
||||||
|
await UrlbarTestUtils.openResultMenuAndClickItem(window, "dismiss", {
|
||||||
|
resultIndex: 1,
|
||||||
|
});
|
||||||
|
await dismissalPromise;
|
||||||
|
|
||||||
|
Assert.ok(
|
||||||
|
UrlbarTestUtils.isPopupOpen(window),
|
||||||
|
"View remains open after blocking result"
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
await QuickSuggest.isResultDismissed(result),
|
||||||
|
"Result should be dismissed"
|
||||||
|
);
|
||||||
|
|
||||||
|
await UrlbarTestUtils.promisePopupClose(window);
|
||||||
|
await QuickSuggest.clearDismissedSuggestions();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function rowLabel() {
|
||||||
|
info("Open urlbar with keyword");
|
||||||
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||||
|
window,
|
||||||
|
value: "rowlabel",
|
||||||
|
});
|
||||||
|
Assert.equal(UrlbarTestUtils.getResultCount(window), 2);
|
||||||
|
|
||||||
|
info("Check the row label");
|
||||||
|
const { element } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
|
||||||
|
Assert.equal(element.row.getAttribute("label"), "Test suggestions");
|
||||||
|
});
|
||||||
|
|
||||||
|
function assertUI(row, payload) {
|
||||||
|
const titleElement = row.querySelector(".urlbarView-title");
|
||||||
|
Assert.equal(titleElement.textContent, payload.title);
|
||||||
|
|
||||||
|
const faviconElement = row.querySelector(".urlbarView-favicon");
|
||||||
|
Assert.equal(faviconElement.src, payload.icon);
|
||||||
|
|
||||||
|
const urlElement = row.querySelector(".urlbarView-url");
|
||||||
|
const displayUrl = payload.shouldShowUrl
|
||||||
|
? payload.url.replace(/^https:\/\//, "")
|
||||||
|
: "";
|
||||||
|
Assert.equal(urlElement.textContent, displayUrl);
|
||||||
|
}
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
--urlbarView-favicon-margin-end: var(--urlbarView-icon-margin-end);
|
--urlbarView-favicon-margin-end: var(--urlbarView-icon-margin-end);
|
||||||
|
|
||||||
--urlbarView-rich-suggestion-default-icon-size: 28px;
|
--urlbarView-rich-suggestion-default-icon-size: 28px;
|
||||||
|
--urlbarView-top-pick-large-icon-box-size: 52px;
|
||||||
|
|
||||||
--urlbarView-result-button-size: 24px;
|
--urlbarView-result-button-size: 24px;
|
||||||
--urlbarView-result-button-background-opacity: 60%;
|
--urlbarView-result-button-background-opacity: 60%;
|
||||||
@@ -858,6 +859,12 @@
|
|||||||
flex-basis: 24px;
|
flex-basis: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&[icon-size="32"] {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
flex-basis: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
&[icon-size="38"] {
|
&[icon-size="38"] {
|
||||||
width: 38px;
|
width: 38px;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
@@ -938,7 +945,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.urlbarView-row:is([type$=_amo], [type$=_pocket])[icon-size="24"] > .urlbarView-row-inner > .urlbarView-favicon {
|
.urlbarView-row:is([type$=_amo], [type$=_pocket])[icon-size="24"] > .urlbarView-row-inner > .urlbarView-favicon {
|
||||||
padding: calc((52px - 24px) / 2);
|
padding: calc((var(--urlbarView-top-pick-large-icon-box-size) - 24px) / 2);
|
||||||
background-color: var(--urlbar-box-focus-bgcolor);
|
background-color: var(--urlbar-box-focus-bgcolor);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
@@ -947,6 +954,10 @@
|
|||||||
background-color: var(--urlbarView-result-button-selected-background-color);
|
background-color: var(--urlbarView-result-button-selected-background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.urlbarView-row[type$=_vpn][icon-size="32"] > .urlbarView-row-inner > .urlbarView-favicon {
|
||||||
|
padding: calc((var(--urlbarView-top-pick-large-icon-box-size) - 32px) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
.urlbarView-row[dynamicType=weather],
|
.urlbarView-row[dynamicType=weather],
|
||||||
.urlbarView-row[type=weather] {
|
.urlbarView-row[type=weather] {
|
||||||
/* Use the colors in the icon SVG files except in HCM and when the row is
|
/* Use the colors in the icon SVG files except in HCM and when the row is
|
||||||
|
|||||||
Reference in New Issue
Block a user