This does a few things:
* Unify the view implementations of rich suggestions, Firefox Suggest sponsored
results, and best match. I did this by using the best match implementation
and extending it to rich suggestions and Suggest sponsored.
* Use the unified implementation for Pocket suggestions too.
* Add a bottom-text concept since Pocket suggestions shown as top picks need to
show both a description and some text below it. (The actual bottom text per
result is added in D182632 since I didn't want to make this patch bigger than
necessary)
I have a couple motivations for these changes:
* I'm implementing Pocket suggestions, which need to show some text below the
suggestion title as well as the URL. I was going to just use the Firefox
Suggest sponsored approach, where the action text is wrapped below the title,
but that doesn't work because it can't show both the wrapped action text and
the URL.
* IMO we should use rich suggestions as the basis for all rows going forward,
i.e., unify the different row implementations around rich suggestions.
The reason I chose the best match implementation instead of the rich suggestions
implementation is because the grid-based approach of rich suggestions doesn't
work well when the URL also needs to be shown. The URL should be
baseline-aligned with the row title, which isn't easy to do when the URL is
outside the grid. The rich suggestions implementation also doesn't wrap the URL.
Other details:
* The `rich-suggestion=no-icon` attribute value is only used for styling, so we
can replace it with `@supports -moz-bool-pref()`. That lets us make the
`rich-suggestion` attribute a simple boolean.
* I kept the `isBestMatch` property for results since
`searchEngagementTelemetryGroup()` uses it to return "top_pick", and the view
also uses it to create the "Top pick" row/group label. It still has semantic
meaning so I think that's OK. It's no longer used by the view to create
different DOM or styling.
* Move `isRichSuggestion` from the payload to the result itself, since it's no
longer used for only one type of result. It's like `isBestMatch`, which is
also on the result.
* Add `richSuggestionIconSize` to the result too. The best match icon size
is 52. The Pocket best match icon size is 24 (but will have added padding and
a background color to make it appear 52px). IMO this is better than adding
rules for each type of suggestion to the CSS. It's cleaner and also indicates
what the "standard" icon sizes are.
Depends on D182580
Differential Revision: https://phabricator.services.mozilla.com/D182537
This keeps the current behavior where Firefox shows a suggestion as a top pick
when `is_top_pick` is true, but in addition the two best-match prefs must also
be true.
I cp'ed test_quicksuggest_bestMatch.js to test_quicksuggest_topPicks.js so that
we have a test specifically for top picks, and I added tasks for all preference
combinations. The terms "best match" and "top picks" are overloaded and I tried
to explain what they mean in the code comments I added.
Depends on D176114
Differential Revision: https://phabricator.services.mozilla.com/D177712
This change adds support for exposure based experiments by allowing
a Nimbus variable/pref to specify the urlbar provider that should
trigger an exposure event as well as a secondary boolean variable/pref
that controls the visibility of the exposed result. The exposure should
be registered when a result 'can be added' but may or may not be shown
based on the value of the `displayExposureProvider` variable.
* Add exposure event to metrics.yaml
* Add new Nimbus variable (`exposureProvider`) to specify the urlbar
providers that should trigger exposure events .
* Add new Nimbus variable (`displayExposureProvider`) that controls the visibility
of the provider results that matched the `exposureProvider` variable.
Differential Revision: https://phabricator.services.mozilla.com/D174209
This removes `UrlbarProvider.pickResult()` and `blockResult()` in favor of
handling picks and dismissals through `onEngagement()`. A number of providers
use those two methods, so this revision touches a lot of files.
Handling dismissals through `onEngagement()` means `UrlbarInput.pickResult()`
can no longer tell whether a result is successfully dismissed, so it can't
remove the result anymore. (Maybe `onEngagement()` could return some value
indicating it dismissed the result, but I don't want to go down that road.)
Instead, I split `UrlbarController.handleDeleteEntry()` into two methods: a
public one that removes the result and notifies listeners, and a private one
that handles dismissing the selected result internally in
UrlbarController. Providers that have dismissable results should now implement
`onEngagement()` and call `controller.removeResult()`.
I made some other improvements to engagement handling. There's still room for
more but this patch is big enough already.
Other notable changes:
Include the engaged result in engagement notifications so providers have easy
access to it and can respond to clicks and dismissals more easily. That also
lets us stop passing `selIndex` and `provider` to `engagementEvent.record()`
since now it can compute those from the passed-in result.
Add the concept of `isSessionOngoing` to engagement notifications so providers
can tell whether an engagement ended the search session. Right now, providers
like quick suggest that record a bunch of provider-specific legacy telemetry
assume that `onEngagement()` ends the session, but that's no longer true.
Unify result buttons and result menu commands by setting
`element.dataset.command` on buttons (hopefully we can remove buttons soon, at
least the ones that aren't tip buttons)
Make sure we always notify providers on engagement even on dismissals or
when skipping legacy telemetry
Move dismissal of restyled search suggestions and history results from
`UrlbarController.handleDeleteEntry()` to the Places provider
Move dismissal of form history results from
`UrlbarController.handleDeleteEntry()` to the search suggestions provider
In the Places provider, remove the unused `_addSearchEngineMatch()` method. Also
remove the code in the "searchengine" case that creates a non-search-history
result. This code is unreached because the only time the provider creates a
"searchengine" match it also sets `isSearchHistory` to true.
In `UrlbarTestUtils.promiseAutocompleteResultPopup()`, change the default value
of the `fireInputEvent` param from false to true. This is necessary because
without a starting input event, the start event info in `engagementEvent` will
be null, so when `engagementEvent.record()` is called at the end of the
engagement, it will bail, and providers will not be notified of the engagement.
IMO true is a better default value anyway because input events will typically be
fired when the user performs a search.
Differential Revision: https://phabricator.services.mozilla.com/D174941
This adds a new pref, `browser.urlbar.weather.zeroPrefix`. When true, weather
suggestions are shown on "zero prefix" like they are now, which means they're
shown when the user focuses the urlbar and before they type anything. When the
pref is false, the weather provider will show suggestions only if the search
string matches a keyword in a set of keywords managed by `QuickSuggest.weather`.
My plan is to store the keywords in the quick suggest config object in remote
settings. Nan suggested this too. Currently the config does not contain any
keywords, but this patch can be tested by setting the pref to false, running the
following in the browser console, and then typing "weather" in the urlbar:
```lang=js
ChromeUtils.importESModule("resource:///modules/QuickSuggest.sys.mjs")
.QuickSuggest.remoteSettings._test_setConfig({
weather_keywords: ["weather"],
});
```
Other changes:
* It's possible for a keyword to match both the weather suggestion and a quick
suggest suggestion. Only the weather suggestion should be shown. This patch
modifies to the muxer for that.
* This modifies `UrlbarView.#rowLabel()` to show the "Top pick" (a.k.a. best
match) label for keyword-based weather suggestions, in addition to zero-prefix
suggestions like we currently do.
* This modifies the remote settings client so it becomes enabled when keyword-
based weather suggestions are enabled, so that the config can be accessed.
Depends on D168738
Differential Revision: https://phabricator.services.mozilla.com/D168757
`QuickSuggestTestUtils.ensureQuickSuggestInit()` was written before Merino, so
it assumes the suggestion objects passed in are remote settings suggestions.
This revision modifies it so Merino and remote settings suggestions can both be
passed in. That makes it a little nicer for tests that need to test Merino
suggestions in particular, like navigational suggestions, dynamic Wikipedia,
etc.
Another motivation for this change is that it makes it clear which type of
suggestion is being passed to `ensureQuickSuggestInit()`. Unfortunately Merino
suggestion objects are slightly different from remote settings result objects
(`block_id` vs. `id` for example), which are both different from UrlbarResult
objects, and it can be confusing when reading tests. Since "result" is the name
of remote settings objects used internally in the remote settings client, I've
used that term here, and I've updated all callers to use it instead of
"suggestion".
This also makes `MerinoTestUtils` and `QuickSuggestTestUtils` singletons.
Otherwise the new `MerinoTestUtils` instance used inside `QuickSuggestTestUtils`
isn't the same as the one used in the test that calls into
`QuickSuggestTestUtils`, which is very confusing. This made me realize it's a
good idea for these test utils objects to be singletons.
Finally I removed `is_top_pick` handling from the remote settings client and
remote settings suggestions, since the related test is now using Merino. I also
removed `_test_is_best_match` since only one test was using it and it's not
necessary.
Depends on D166019
Differential Revision: https://phabricator.services.mozilla.com/D166050
This is a follow up to D161866 and effectively reverts and replaces it with a
different approach. Please see bug 1800810 for background. In short, engagement
telemetry should be based on the result that's visible in the view, not on the
result the provider added last.
D161866 fixed the case where the last-added result is in the view but hidden.
There's another case we need to handle, when the last-added result is not in the
view at all. That can happen when you type something and hit enter really
quickly, before the view can update. I was able to trigger it several times.
When that happens, there are two possibilities:
* No quick suggest result is visible in the view. `result.rowIndex` is its
initial value of -1, so we record an engagement for a result that is not
visible and that doesn't have a valid index.
* A quick suggest result from a previous query is visible in the view. Here
again, `result.rowIndex` is -1 so we record an engagement for a result that is
not visible and that doesn't have a valid index, and we miss recording an
engagement for the result that's actually visible.
Right now it's not easy to fix this inside the provider because providers don't
know anything about the view(s). I could record this telemetry in the view but
that's not its role. I think it makes sense to include the view in the query
context, so that's what this does. I added `view.visibleResults` to make getting
the visible results easy.
Daisuke's new Glean telemetry in D160193 uses `context.results`, which has this
same problem of not being based on actually visible results. We'll need to use
`context.view.visibleResults` there too, and there may be other existing cases
as well.
Depends on D161866
Differential Revision: https://phabricator.services.mozilla.com/D162182
This moves the help URL const out of UrlbarProviderQuickSuggest in order to make
UrlbarProviderQuickSuggest focused on being a urlbar provider.
It also changes how QuickSuggestTestUtils is initialized to be more similar to
MerinoTestUtils. There's no need for a separate `init()` method when the
constructor will do. I'd like to make this change in a different revision but I
did it here because I want to include all changes to about:preferences in one
revision for easier review.
Please see bug 1798595 for details.
Depends on D160984
Differential Revision: https://phabricator.services.mozilla.com/D160985
This factors out the Merino client code from UrlbarProviderQuickSuggest into
MerinoClient. It also adds MerinoTestUtils.
There are a few reasons for this:
1. Weather suggestions will be prefetched from Merino, and it may make sense to
do the prefetching outside of UrlbarProviderQuickSuggest, I'm not sure
yet.
2. Weather suggestions will be fetched from a slightly different URL from other
suggestions. They'll need to include `providers=weather` as a search param.
In the future there may be other types of suggestions that also require
different parameters or whole new endpoints. Supporting options like this is
a little nicer with a dedicated Merino client class.
3. In general this code is substantial enough that it makes sense to encapsulate
it in its own file and class, even if the provider is the only thing that
will use it.
This is a large patch but a lot of it moves code around. Summary of changes:
* Factor out Merino client code into MerinoClient
* Also include some new useful helpers in MerinoClient
* Consolidate and factor out Merino test code into MerinoTestUtils
* Also include some new useful helpers in MerinoTestUtils and make other improvements
* Add a MockMerinoServer class (in MerinoTestUtils.sys.mjs) to help with setting up a mock Merino server
* Add test_merinoClient.js to test the client in isolation. This file started as a copy of test_quicksuggest_merino.js because it's so similar, and some of the tests in the latter are moved to the former.
* Add test_merinoClient_sessions.js to test Merino sessions in isolation. Similar to the previous point, this file started as a copy of test_quicksuggest_merinoSessions.js.
* Modify existing Merino tests so they use MerinoTestUtils
Differential Revision: https://phabricator.services.mozilla.com/D160449