Commit 1b1cc4ae authored by Drew Willcoxon's avatar Drew Willcoxon
Browse files

Bug 1799363 - Add weather suggestions to quick suggest. r=daisuke

This adds a weather feature to quick suggest. It periodically fetches a weather
suggestion from Merino. UrlbarProviderQuickSuggest shows the suggestion when the
search string is empty ("zero prefix").

The implementation of the UrlbarResult returned by UrlbarProviderQuickSuggest is
only temporary. Mandy is working on the final UI in
[SNT-323](https://mozilla-hub.atlassian.net/browse/SNT-323). Landing a temporary
implementation allows Mandy to base her patch on it and trigger real weather
suggestions from Merino to test her implementation against. It also lets people
on the team test weather suggestions without having to wait for the final UI to
land.

I added the following prefs and Nimbus variable to control the feature. It will
initially be rolled out in an experiment, so we need a Nimbus variable. In the
initial experiment, users will be able to dismiss the suggestion but not toggle
a checkbox in about:preferences.

* `weatherFeatureGate` - Nimbus variable that controls the whole feature
* `browser.urlbar.weather.featureGate` - Fallback pref for the Nimbus variable
* `browser.urlbar.suggest.weather` - When the feature gate pref is true, this
  determines whether the suggestion should be shown. In a future patch, we'll
  flip this to false when users dismiss the suggestion.

I set the fetch interval to 30 minutes. That seems reasonable considering that
the suggestion contains the current temperature and weather. Merino will set
caching headers appropriately so that Firefox won't actually make a new network
request if the previously fetched suggestion is new enough.

Depends on D161368

Differential Revision: https://phabricator.services.mozilla.com/D161410
parent f1469f45
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -404,6 +404,13 @@ pref("browser.urlbar.suggest.calculator", false);
  pref("browser.urlbar.quickactions.showInZeroPrefix", true);
#endif

// Feature gate pref for weather suggestions in the urlbar.
pref("browser.urlbar.weather.featureGate", false);

// If `browser.urlbar.weather.featureGate` is true, this controls whether
// weather suggestions are turned on.
pref("browser.urlbar.suggest.weather", true);

// When `browser.urlbar.bestMatch.enabled` is true, this controls whether best
// match results are shown in the urlbar. This pref is exposed to the user in
// the UI, and it's sticky so that its user-branch value persists regardless of
+9 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ const FEATURES = {
  ImpressionCaps: "resource:///modules/urlbar/private/ImpressionCaps.sys.mjs",
  RemoteSettingsClient:
    "resource:///modules/urlbar/private/RemoteSettingsClient.sys.mjs",
  Weather: "resource:///modules/urlbar/private/Weather.sys.mjs",
};

const TIMESTAMP_TEMPLATE = "%YYYYMMDDHH%";
@@ -121,6 +122,14 @@ class _QuickSuggest {
    return this.#features.ImpressionCaps;
  }

  /**
   * @returns {Weather}
   *   A feature that periodically fetches weather suggestions from Merino.
   */
  get weather() {
    return this.#features.Weather;
  }

  get logger() {
    if (!this._logger) {
      this._logger = lazy.UrlbarUtils.getLogger({ prefix: "QuickSuggest" });
+7 −0
Original line number Diff line number Diff line
@@ -261,6 +261,10 @@ const PREF_URLBAR_DEFAULTS = new Map([
  // Whether results will include top sites and the view will open on focus.
  ["suggest.topsites", true],

  // If `browser.urlbar.weather.featureGate` is true, this controls whether
  // weather suggestions are turned on.
  ["suggest.weather", true],

  // JSON'ed array of blocked quick suggest URL digests.
  ["quicksuggest.blockedDigests", ""],

@@ -377,6 +381,9 @@ const PREF_URLBAR_DEFAULTS = new Map([
  //  1 - Show search history
  //  2 - Show search and browsing history
  ["update2.emptySearchBehavior", 0],

  // Feature gate pref for weather suggestions in the urlbar.
  ["weather.featureGate", false],
]);
const PREF_OTHER_DEFAULTS = new Map([
  ["browser.fixup.dns_first_for_single_words", false],
+82 −11
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
  MerinoClient: "resource:///modules/MerinoClient.sys.mjs",
  QuickSuggest: "resource:///modules/QuickSuggest.sys.mjs",
  UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
  UrlbarProviderTopSites: "resource:///modules/UrlbarProviderTopSites.sys.mjs",
  UrlbarResult: "resource:///modules/UrlbarResult.sys.mjs",
});

@@ -78,6 +79,14 @@ class ProviderQuickSuggest extends UrlbarProvider {
    return { ...TELEMETRY_SCALARS };
  }

  getPriority(context) {
    if (!context.searchString) {
      // Zero-prefix suggestions have the same priority as top sites.
      return lazy.UrlbarProviderTopSites.PRIORITY;
    }
    return super.getPriority(context);
  }

  /**
   * Whether this provider should be invoked for the given context.
   * If this method returns false, the providers manager won't start a query
@@ -98,14 +107,26 @@ class ProviderQuickSuggest extends UrlbarProvider {
    ) {
      return false;
    }

    if (
      !lazy.UrlbarPrefs.get("quickSuggestEnabled") ||
      queryContext.isPrivate ||
      queryContext.searchMode
    ) {
      return false;
    }

    // Trim only the start of the search string because a trailing space can
    // affect the suggestions.
    this._searchString = queryContext.searchString.trimStart();

    if (!this._searchString) {
      return !!lazy.QuickSuggest.weather.suggestion;
    }
    return (
      queryContext.trimmedSearchString &&
      !queryContext.searchMode &&
      !queryContext.isPrivate &&
      lazy.UrlbarPrefs.get("quickSuggestEnabled") &&
      (lazy.UrlbarPrefs.get("suggest.quicksuggest.nonsponsored") ||
      lazy.UrlbarPrefs.get("suggest.quicksuggest.nonsponsored") ||
      lazy.UrlbarPrefs.get("suggest.quicksuggest.sponsored") ||
        lazy.UrlbarPrefs.get("quicksuggest.dataCollection.enabled"))
      lazy.UrlbarPrefs.get("quicksuggest.dataCollection.enabled")
    );
  }

@@ -120,10 +141,16 @@ class ProviderQuickSuggest extends UrlbarProvider {
   */
  async startQuery(queryContext, addCallback) {
    let instance = this.queryInstance;
    let searchString = this._searchString;

    // Trim only the start of the search string because a trailing space can
    // affect the suggestions.
    let searchString = queryContext.searchString.trimStart();
    if (!searchString) {
      let result = this._makeWeatherResult();
      if (result) {
        addCallback(this, result);
        this._resultFromLastQuery = result;
      }
      return;
    }

    // There are two sources for quick suggest: remote settings and Merino.
    let promises = [];
@@ -543,7 +570,7 @@ class ProviderQuickSuggest extends UrlbarProvider {
   */
  async _fetchMerinoSuggestions(queryContext, searchString) {
    if (!this._merino) {
      this._merino = new lazy.MerinoClient();
      this._merino = new lazy.MerinoClient(this.name);
    }

    let providers;
@@ -565,6 +592,50 @@ class ProviderQuickSuggest extends UrlbarProvider {
    return suggestions;
  }

  /**
   * Returns a UrlbarResult for the current prefetched weather suggestion if
   * there is one.
   *
   * @returns {UrlbarResult}
   *   A result or null if there's no weather suggestion.
   */
  _makeWeatherResult() {
    let { suggestion } = lazy.QuickSuggest.weather;
    if (!suggestion) {
      return null;
    }

    let unit = Services.locale.appLocaleAsBCP47 == "en-US" ? "f" : "c";
    let result = new lazy.UrlbarResult(
      UrlbarUtils.RESULT_TYPE.URL,
      UrlbarUtils.RESULT_SOURCE.OTHER_NETWORK,
      {
        title:
          suggestion.city_name +
          "" +
          suggestion.current_conditions.temperature[unit] +
          "° " +
          suggestion.current_conditions.summary +
          "" +
          suggestion.forecast.summary +
          " • H " +
          suggestion.forecast.high[unit] +
          "° • L " +
          suggestion.forecast.low[unit] +
          "°",
        url: suggestion.url,
        icon: "chrome://global/skin/icons/highlights.svg",
        helpUrl: lazy.QuickSuggest.HELP_URL,
        helpL10nId: "firefox-suggest-urlbar-learn-more",
        requestId: suggestion.request_id,
        source: suggestion.source,
      }
    );

    result.suggestedIndex = 0;
    return result;
  }

  /**
   * Returns whether a given suggestion can be added for a query, assuming the
   * provider itself should be active.
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ EXTRA_JS_MODULES["urlbar/private"] += [
    "private/BlockedSuggestions.sys.mjs",
    "private/ImpressionCaps.sys.mjs",
    "private/RemoteSettingsClient.sys.mjs",
    "private/Weather.sys.mjs",
]

TESTING_JS_MODULES += [
Loading