1Dynamic Result Types
2====================
3
4This document discusses a special category of address bar results called dynamic
5result types. Dynamic result types allow you to easily add new types of results
6to the address bar and are especially useful for extensions.
7
8The intended audience for this document is developers who need to add new kinds
9of address bar results, either internally in the address bar codebase or through
10extensions.
11
12.. toctree::
13   :caption: Table of Contents
14
15   dynamic-result-types
16
17Motivation
18----------
19
20The address bar provides many different types of results in normal Firefox
21usage. For example, when you type a search term, the address bar may show you
22search suggestion results from your current search engine. It may also show you
23results from your browsing history that match your search. If you typed a
24certain phrase like "update Firefox," it will show you a tip result that lets
25you know whether Firefox is up to date.
26
27Each of these types of results is built into the address bar implementation. If
28you wanted to add a new type of result -- say, a card that shows the weather
29forecast when the user types "weather" -- one way to do so would be to add a new
30result type. You would need to update all the code paths in the address bar that
31relate to result types. For instance, you'd need to update the code path that
32handles clicks on results so that your weather card opens an appropriate
33forecast URL when clicked; you'd need to update the address bar view (the panel)
34so that your card is drawn correctly; you may need to update the keyboard
35selection behavior if your card contains elements that can be independently
36selected such as different days of the week; and so on.
37
38If you're implementing your weather card in an extension, as you might in an
39add-on experiment, then you'd need to land your new result type in
40mozilla-central so your extension can use it. Your new result type would ship
41with Firefox even though the vast majority of users would never see it, and your
42fellow address bar hackers would have to work around your code even though it
43would remain inactive most of the time, at least until your experiment
44graduated.
45
46Dynamic Result Types
47--------------------
48
49**Dynamic result types** are an alternative way of implementing new result
50types. Instead of adding a new built-in type along with all that entails, you
51add a new provider subclass and register a template that describes how the view
52should draw your result type and indicates which elements are selectable. The
53address bar takes care of everything else. (Or if you're implementing an
54extension, you add a few event handlers instead of a provider subclass, although
55we have a shim_ that abstracts away the differences between internal and
56extension address bar code.)
57
58Dynamic result types are essentially an abstraction layer: Support for them as a
59general category of results is built into the address bar, and each
60implementation of a specific dynamic result type fills in the details.
61
62In addition, dynamic result types can be added at runtime. This is important for
63extensions that implement new types of results like the weather forecast example
64above.
65
66.. _shim: https://github.com/0c0w3/dynamic-result-type-extension/blob/master/src/shim.js
67
68Getting Started
69---------------
70
71To get a feel for how dynamic result types are implemented, you can look at the
72`example dynamic result type extension <exampleExtension_>`__. The extension
73uses the recommended shim_ that makes writing address bar extension code very
74similar to writing internal address bar code, and it's therefore a useful
75example even if you intend to add a new dynamic result type internally in the
76address bar codebase in mozilla-central.
77
78The next section describes the specific steps you need to take to add a new
79dynamic result type.
80
81.. _exampleExtension: https://github.com/0c0w3/dynamic-result-type-extension/blob/master/src/background.js
82
83Implementation Steps
84--------------------
85
86This section describes how to add a new dynamic result type in either of the
87following cases:
88
89* You want to add a new dynamic result type in an extension using the
90  recommended shim_.
91* You want to add a new dynamic result type internal to the address bar codebase
92  in mozilla-central.
93
94The steps are mostly the same in both cases and are described next.
95
96If you want to add a new dynamic result type in an extension but don't want to
97use the shim, then skip ahead to `Appendix B: Using the WebExtensions API
98Directly`_.
99
1001. Register the dynamic result type
101~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
102
103First, register the new dynamic result type:
104
105.. code-block:: javascript
106
107    UrlbarResult.addDynamicResultType(name);
108
109``name`` is a string identifier for the new type. It must be unique; that is, it
110must be different from all other dynamic result type names. It will also be used
111in DOM IDs, DOM class names, and CSS selectors, so it should not contain any
112spaces or other characters that are invalid in CSS.
113
1142. Register the view template
115~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
116
117Next, add the view template for the new type:
118
119.. code-block:: javascript
120
121    UrlbarView.addDynamicViewTemplate(name, viewTemplate);
122
123``name`` is the new type's name as described in step 1.
124
125``viewTemplate`` is an object called a view template. It describes in a
126declarative manner the DOM that should be created in the view for all results of
127the new type. For providers created in extensions, it also declares the
128stylesheet that should be applied to results in the view. See `View Templates`_
129for a description of this object.
130
1313. Add the provider
132~~~~~~~~~~~~~~~~~~~
133
134As with any type of result, results for dynamic result types must be created by
135one or more providers. Make a ``UrlbarProvider`` subclass for the new provider
136and implement all the usual provider methods as you normally would:
137
138.. code-block:: javascript
139
140    class MyDynamicResultTypeProvider extends UrlbarProvider {
141      // ...
142    }
143
144The ``startQuery`` method should create ``UrlbarResult`` objects with the
145following two requirements:
146
147* Result types must be ``UrlbarUtils.RESULT_TYPE.DYNAMIC``.
148* Result payloads must have a ``dynamicType`` property whose value is the name
149  of the dynamic result type used in step 1.
150
151The results' sources, other payload properties, and other result properties
152aren't relevant to dynamic result types, and you should choose values
153appropriate to your use case.
154
155If any elements created in the view for your results can be picked with the
156keyboard or mouse, then be sure to implement your provider's ``pickResult``
157method.
158
159For help on implementing providers in general, see the address bar's
160`Architecture Overview`__.
161
162If you are creating the provider in the internal address bar implementation in
163mozilla-central, then don't forget to register it in ``UrlbarProvidersManager``.
164
165If you are creating the provider in an extension, then it's registered
166automatically, and there's nothing else you need to do.
167
168__ https://firefox-source-docs.mozilla.org/browser/urlbar/overview.html#urlbarprovider
169
1704. Implement the provider's getViewUpdate method
171~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
172
173``getViewUpdate`` is a provider method particular to dynamic result type
174providers. Its job is to update the view DOM for a specific result. It's called
175by the view for each result in the view that was created by the provider. It
176returns an object called a view update object.
177
178Recall that the view template was added earlier, in step 2. The view template
179describes how to build the DOM structure for all results of the dynamic result
180type. The view update object, in this step, describes how to fill in that
181structure for a specific result.
182
183Add the ``getViewUpdate`` method to the provider:
184
185.. code-block:: javascript
186
187    /**
188     * Returns a view update object that describes how to update the view DOM
189     * for a given result.
190     *
191     * @param {UrlbarResult} result
192     *   The view update object describes how to update the view DOM for this
193     *   particular result.
194     * @param {Map} idsByName
195     *   A map from names in the view template to the IDs of their corresponding
196     *   elements in the DOM.
197     */
198    getViewUpdate(result, idsByName) {
199      let viewUpdate = {
200        // ...
201      };
202      return viewUpdate;
203    }
204
205``result`` is the result from the provider for which the view update is being
206requested.
207
208``idsByName`` is a map from names in the view template to the IDs of their
209corresponding elements in the DOM. This is useful if parts of the view update
210depend on element IDs, as some ARIA attributes do.
211
212The return value is a view update object. It describes in a declarative manner
213the updates that should be performed on the view DOM. See `View Update Objects`_
214for a description of this object.
215
2165. Style the results
217~~~~~~~~~~~~~~~~~~~~
218
219If you are creating the provider in the internal address bar implementation in
220mozilla-central, then add styling `dynamicResults.inc.css`_.
221
222.. _dynamicResults.inc.css: https://searchfox.org/mozilla-central/source/browser/themes/shared/urlbar/dynamicResults.inc.css
223
224If you are creating the provider in an extension, then bundle a CSS file in your
225extension and declare it in the top-level ``stylesheet`` property of your view
226template, as described in `View Templates`_. Additionally, if any of your rules
227override built-in rules, then you'll need to declare them as ``!important``.
228
229The rest of this section will discuss the CSS rules you need to use to style
230your results.
231
232There are two DOM annotations that are useful for styling. The first is the
233``dynamicType`` attribute that is set on result rows, and the second is a class
234that is set on child elements created from the view template.
235
236dynamicType Row Attribute
237.........................
238
239The topmost element in the view corresponding to a result is called a
240**row**. Rows have a class of ``urlbarView-row``, and rows corresponding to
241results of a dynamic result type have an attributed called ``dynamicType``. The
242value of this attribute is the name of the dynamic result type that was chosen
243in step 1 earlier.
244
245Rows of a specific dynamic result type can therefore be selected with the
246following CSS selector, where ``TYPE_NAME`` is the name of the type:
247
248.. code-block:: css
249
250    .urlbarView-row[dynamicType=TYPE_NAME]
251
252Child Element Class
253...................
254
255As discussed in `View Templates`_, each object in the view template can have a
256``name`` property. The elements in the view corresponding to the objects in the
257view template receive a class named
258``urlbarView-dynamic-TYPE_NAME-ELEMENT_NAME``, where ``TYPE_NAME`` is the name
259of the dynamic result type, and ``ELEMENT_NAME`` is the name of the object in
260the view template.
261
262Elements in dynamic result type rows can therefore be selected with the
263following:
264
265.. code-block:: css
266
267    .urlbarView-dynamic-TYPE_NAME-ELEMENT_NAME
268
269If an object in the view template does not have a ``name`` property, then it
270won't receive the class and it therefore can't be selected using this selector.
271
272View Templates
273--------------
274
275A **view template** is a plain JS object that declaratively describes how to
276build the DOM for a dynamic result type. When a result of a particular dynamic
277result type is shown in the view, the type's view template is used to construct
278the part of the view that represents the type in general.
279
280The need for view templates arises from the fact that extensions run in a
281separate process from the chrome process and can't directly access the chrome
282DOM, where the address bar view lives. Since extensions are a primary use case
283for dynamic result types, this is an important constraint on their design.
284
285Properties
286~~~~~~~~~~
287
288A view template object is a tree-like nested structure where each object in the
289nesting represents a DOM element to be created. This tree-like structure is
290achieved using the ``children`` property described below. Each object in the
291structure may include the following properties:
292
293``{string} name``
294  The name of the object. This is required for all objects in the structure
295  except the root object and serves two important functions:
296
297  1. The element created for the object will automatically have a class named
298     ``urlbarView-dynamic-${dynamicType}-${name}``, where ``dynamicType`` is the
299     name of the dynamic result type. The element will also automatically have
300     an attribute ``name`` whose value is this name. The class and attribute
301     allow the element to be styled in CSS.
302
303  2. The name is used when updating the view, as described in `View Update
304     Objects`_.
305
306  Names must be unique within a view template, but they don't need to be
307  globally unique. In other words, two different view templates can use the same
308  names, and other unrelated DOM elements can use the same names in their IDs
309  and classes.
310
311``{string} tag``
312  The element tag name of the object. This is required for all objects in the
313  structure except the root object and declares the kind of element that will be
314  created for the object: ``span``, ``div``, ``img``, etc.
315
316``{object} [attributes]``
317  An optional mapping from attribute names to values. For each name-value pair,
318  an attribute is set on the element created for the object.
319
320  A special ``selectable`` attribute tells the view that the element is
321  selectable with the keyboard. The element will automatically participate in
322  the view's keyboard selection behavior.
323
324  Similarly, the ``role=button`` ARIA attribute will also automatically allow
325  the element to participate in keyboard selection. The ``selectable`` attribute
326  is not necessary when ``role=button`` is specified.
327
328``{array} [children]``
329  An optional list of children. Each item in the array must be an object as
330  described in this section. For each item, a child element as described by the
331  item is created and added to the element created for the parent object.
332
333``{array} [classList]``
334  An optional list of classes. Each class will be added to the element created
335  for the object by calling ``element.classList.add()``.
336
337``{string} [stylesheet]``
338  For dynamic result types created in extensions, this property should be set on
339  the root object in the view template structure, and its value should be a
340  stylesheet URL. The stylesheet will be loaded in all browser windows so that
341  the dynamic result type view may be styled. The specified URL will be resolved
342  against the extension's base URI. We recommend specifying a URL relative to
343  your extension's base directory.
344
345  For dynamic result types created internally in the address bar codebase, this
346  value should not be specified and instead styling should be added to
347  `dynamicResults.inc.css`_.
348
349Example
350~~~~~~~
351
352Let's return to the weather forecast example from `earlier <Motivation_>`__. For
353each result of our weather forecast dynamic result type, we might want to
354display a label for a city name along with two buttons for today's and
355tomorrow's forecasted high and low temperatures. The view template might look
356like this:
357
358.. code-block:: javascript
359
360    {
361      stylesheet: "style.css",
362      children: [
363        {
364          name: "cityLabel",
365          tag: "span",
366        },
367        {
368          name: "today",
369          tag: "div",
370          classList: ["day"],
371          attributes: {
372            selectable: "true",
373          },
374          children: [
375            {
376              name: "todayLabel",
377              tag: "span",
378              classList: ["dayLabel"],
379            },
380            {
381              name: "todayLow",
382              tag: "span",
383              classList: ["temperature", "temperatureLow"],
384            },
385            {
386              name: "todayHigh",
387              tag: "span",
388              classList: ["temperature", "temperatureHigh"],
389            },
390          },
391        },
392        {
393          name: "tomorrow",
394          tag: "div",
395          classList: ["day"],
396          attributes: {
397            selectable: "true",
398          },
399          children: [
400            {
401              name: "tomorrowLabel",
402              tag: "span",
403              classList: ["dayLabel"],
404            },
405            {
406              name: "tomorrowLow",
407              tag: "span",
408              classList: ["temperature", "temperatureLow"],
409            },
410            {
411              name: "tomorrowHigh",
412              tag: "span",
413              classList: ["temperature", "temperatureHigh"],
414            },
415          },
416        },
417      ],
418    }
419
420Observe that we set the special ``selectable`` attribute on the ``today`` and
421``tomorrow`` elements so they can be selected with the keyboard.
422
423View Update Objects
424-------------------
425
426A **view update object** is a plain JS object that declaratively describes how
427to update the DOM for a specific result of a dynamic result type. When a result
428of a dynamic result type is shown in the view, a view update object is requested
429from the result's provider and is used to update the DOM for that result.
430
431Note the difference between view update objects, described in this section, and
432view templates, described in the previous section. View templates are used to
433build a general DOM structure appropriate for all results of a particular
434dynamic result type. View update objects are used to fill in that structure for
435a specific result.
436
437When a result is shown in the view, first the view looks up the view template of
438the result's dynamic result type. It uses the view template to build a DOM
439subtree. Next, the view requests a view update object for the result from its
440provider. The view update object tells the view which result-specific attributes
441to set on which elements, result-specific text content to set on elements, and
442so on. View update objects cannot create new elements or otherwise modify the
443structure of the result's DOM subtree.
444
445Typically the view update object is based on the result's payload.
446
447Properties
448~~~~~~~~~~
449
450The view update object is a nested structure with two levels. It looks like
451this:
452
453.. code-block:: javascript
454
455    {
456      name1: {
457        // individual update object for name1
458      },
459      name2: {
460        // individual update object for name2
461      },
462      name3: {
463        // individual update object for name3
464      },
465      // ...
466    }
467
468The top level maps object names from the view template to individual update
469objects. The individual update objects tell the view how to update the elements
470with the specified names. If a particular element doesn't need to be updated,
471then it doesn't need an entry in the view update object.
472
473Each individual update object can have the following properties:
474
475``{object} [attributes]``
476  A mapping from attribute names to values. Each name-value pair results in an
477  attribute being set on the element.
478
479``{object} [style]``
480  A plain object that can be used to add inline styles to the element, like
481  ``display: none``. ``element.style`` is updated for each name-value pair in
482  this object.
483
484``{object} [l10n]``
485  An ``{ id, args }`` object that will be passed to
486  ``document.l10n.setAttributes()``.
487
488``{string} [textContent]``
489  A string that will be set as ``element.textContent``.
490
491Example
492~~~~~~~
493
494Continuing our weather forecast example, the view update object needs to update
495several things that we declared in our view template:
496
497* The city label
498* The "today" label
499* Today's low and high temperatures
500* The "tomorrow" label
501* Tomorrow's low and high temperatures
502
503Typically, each of these, with the possible exceptions of the "today" and
504"tomorrow" labels, would come from our results' payloads. There's an important
505connection between what's in the view and what's in the payloads: The data in
506the payloads serves the information shown in the view.
507
508Our view update object would then look something like this:
509
510.. code-block:: javascript
511
512    {
513      cityLabel: {
514        textContent: result.payload.city,
515      },
516      todayLabel: {
517        textContent: "Today",
518      },
519      todayLow: {
520        textContent: result.payload.todayLow,
521      },
522      todayHigh: {
523        textContent: result.payload.todayHigh,
524      },
525      tomorrowLabel: {
526        textContent: "Tomorrow",
527      },
528      tomorrowLow: {
529        textContent: result.payload.tomorrowLow,
530      },
531      tomorrowHigh: {
532        textContent: result.payload.tomorrowHigh,
533      },
534    }
535
536Accessibility
537-------------
538
539Just like built-in types, dynamic result types support a11y in the view, and you
540should make sure your view implementation is fully accessible.
541
542Since the views for dynamic result types are implemented using view templates
543and view update objects, in practice supporting a11y for dynamic result types
544means including appropriate `ARIA attributes <aria_>`_ in the view template and
545view update objects, using the ``attributes`` property.
546
547Many ARIA attributes depend on element IDs, and that's why the ``idsByName``
548parameter to the ``getViewUpdate`` provider method is useful.
549
550Usually, accessible address bar results require the ARIA attribute
551``role=group`` on their top-level DOM element to indicate that all the child
552elements in the result's DOM subtree form a logical group. This attribute can be
553set on the root object in the view template.
554
555.. _aria: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA
556
557Example
558~~~~~~~
559
560Continuing the weather forecast example, we'd like for screen readers to know
561that our result is labeled by the city label so that they announce the city when
562the result is selected.
563
564The relevant ARIA attribute is ``aria-labelledby``, and its value is the ID of
565the element with the label. In our ``getViewUpdate`` implementation, we can use
566the ``idsByName`` map to get the element ID that the view created for our city
567label, like this:
568
569.. code-block:: javascript
570
571    getViewUpdate(result, idsByName) {
572      return {
573        root: {
574          attributes: {
575            "aria-labelledby": idsByName.get("cityLabel"),
576          },
577        },
578        // *snipping the view update object example from earlier*
579      };
580    }
581
582Here we're using the name "root" to refer to the root object in the view
583template, so we also need to update our view template by adding the ``name``
584property to the top-level object, like this:
585
586.. code-block:: javascript
587
588    {
589      stylesheet: "style.css",
590      name: "root",
591      attributes: {
592        role: "group",
593      },
594      children: [
595        {
596          name: "cityLabel",
597          tag: "span",
598        },
599        // *snipping the view template example from earlier*
600      ],
601    }
602
603Note that we've also included the ``role=group`` ARIA attribute on the root, as
604discussed above. We could have included it in the view update object instead of
605the view template, but since it doesn't depend on a specific result or element
606ID in the ``idsByName`` map, the view template makes more sense.
607
608Mimicking Built-in Address Bar Results
609--------------------------------------
610
611Sometimes it's desirable to create a new result type that looks and behaves like
612the usual built-in address bar results. Two conveniences are available that are
613useful in this case.
614
615URL Navigation
616~~~~~~~~~~~~~~
617
618If a result's payload includes a string ``url`` property and a boolean
619``shouldNavigate: true`` property, then picking the result will navigate to the
620URL. The ``pickResult`` method of the result's provider will still be called
621before navigation.
622
623Text Highlighting
624~~~~~~~~~~~~~~~~~
625
626Most built-in address bar results emphasize occurrences of the user's search
627string in their text by boldfacing matching substrings. Search suggestion
628results do the opposite by emphasizing the portion of the suggestion that the
629user has not yet typed. This emphasis feature is called **highlighting**, and
630it's also available to the results of dynamic result types.
631
632Highlighting for dynamic result types is a fairly automated process. The text
633that you want to highlight must be present as a property in your result
634payload. Instead of setting the property to a string value as you normally
635would, set it to an array with two elements, where the first element is the text
636and the second element is a ``UrlbarUtils.HIGHLIGHT`` value, like the ``title``
637payload property in the following example:
638
639.. code-block:: javascript
640
641    let result = new UrlbarResult(
642      UrlbarUtils.RESULT_TYPE.DYNAMIC,
643      UrlbarUtils.RESULT_SOURCE.OTHER_NETWORK,
644      {
645        title: [
646          "Some result title",
647          UrlbarUtils.HIGHLIGHT.TYPED,
648        ],
649        // *more payload properties*
650      }
651    );
652
653``UrlbarUtils.HIGHLIGHT`` is defined in the extensions shim_ and is described
654below.
655
656Your view template must create an element corresponding to the payload
657property. That is, it must include an object where the value of the ``name``
658property is the name of the payload property, like this:
659
660.. code-block:: javascript
661
662    {
663      children: [
664        {
665          name: "title",
666          tag: "span",
667        },
668        // ...
669      ],
670    }
671
672In contrast, your view update objects must *not* include an update for the
673element. That is, they must not include a property whose name is the name of the
674payload property.
675
676Instead, when the view is ready to update the DOM of your results, it will
677automatically find the elements corresponding to the payload property, set their
678``textContent`` to the text value in the array, and apply the appropriate
679highlighting, as described next.
680
681There are two possible ``UrlbarUtils.HIGHLIGHT`` values. Each controls how
682highlighting is performed:
683
684``UrlbarUtils.HIGHLIGHT.TYPED``
685  Substrings in the payload text that match the user's search string will be
686  emphasized.
687
688``UrlbarUtils.HIGHLIGHT.SUGGESTED``
689  If the user's search string appears in the payload text, then the remainder of
690  the text following the matching substring will be emphasized.
691
692Appendix A: Examples
693--------------------
694
695This section lists some example and real-world consumers of dynamic result
696types.
697
698`Example Extension`__
699  This extension demonstrates a simple use of dynamic result types.
700
701`Weather Quick Suggest Extension`__
702  A real-world Firefox extension experiment that shows weather forecasts and
703  alerts when the user performs relevant searches in the address bar.
704
705`Tab-to-Search Provider`__
706  This is a built-in provider in mozilla-central that uses dynamic result types.
707
708__ https://github.com/0c0w3/dynamic-result-type-extension
709__ https://github.com/mozilla-extensions/firefox-quick-suggest-weather/blob/master/src/background.js
710__ https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarProviderTabToSearch.jsm
711
712Appendix B: Using the WebExtensions API Directly
713------------------------------------------------
714
715If you're developing an extension, the recommended way of using dynamic result
716types is to use the shim_, which abstracts away the differences between writing
717internal address bar code and extensions code. The `implementation steps`_ above
718apply to extensions as long as you're using the shim.
719
720For completeness, in this section we'll document the WebExtensions APIs that the
721shim is built on. If you don't use the shim for some reason, then follow these
722steps instead. You'll see that each step above using the shim has an analogous
723step here.
724
725The WebExtensions API schema is declared in `schema.json`_ and implemented in
726`api.js`_.
727
728.. _schema.json: https://github.com/0c0w3/dynamic-result-type-extension/blob/master/src/experiments/urlbar/schema.json
729.. _api.js: https://github.com/0c0w3/dynamic-result-type-extension/blob/master/src/experiments/urlbar/api.js
730
7311. Register the dynamic result type
732~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
733
734First, register the new dynamic result type:
735
736.. code-block:: javascript
737
738    browser.experiments.urlbar.addDynamicResultType(name, type);
739
740``name`` is a string identifier for the new type. See step 1 in `Implementation
741Steps`_ for a description, which applies here, too.
742
743``type`` is an object with metadata for the new type. Currently no metadata is
744supported, so this should be an empty object, which is the default value.
745
7462. Register the view template
747~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
748
749Next, add the view template for the new type:
750
751.. code-block:: javascript
752
753    browser.experiments.urlbar.addDynamicViewTemplate(name, viewTemplate);
754
755See step 2 above for a description of the parameters.
756
7573. Add WebExtension event listeners
758~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
759
760Add all the WebExtension event listeners you normally would in an address bar
761extension, including the two required listeners, ``onBehaviorRequested`` and
762and ``onResultsRequested``.
763
764.. code-block:: javascript
765
766    browser.urlbar.onBehaviorRequested.addListener(query => {
767      return "active";
768    }, providerName);
769
770    browser.urlbar.onResultsRequested.addListener(query => {
771      let results = [
772        // ...
773      ];
774      return results;
775    }, providerName);
776
777See the address bar extensions__ document for help on the urlbar WebExtensions
778API.
779
780__ https://firefox-source-docs.mozilla.org/browser/urlbar/experiments.html
781
7824. Add an onViewUpdateRequested event listener
783~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
784
785``onViewUpdateRequested`` is a WebExtensions event particular to dynamic result
786types. It's analogous to the ``getViewUpdate`` provider method described
787earlier.
788
789.. code-block:: javascript
790
791    browser.experiments.urlbar.onViewUpdateRequested.addListener((payload, idsByName) => {
792      let viewUpdate = {
793        // ...
794      };
795      return viewUpdate;
796    });
797
798Note that unlike ``getViewUpdate``, here the listener's first parameter is a
799result payload, not the result itself.
800
801The listener should return a view update object.
802
8035. Style the results
804~~~~~~~~~~~~~~~~~~~~
805
806This step is the same as step 5 above. Bundle a CSS file in your extension and
807declare it in the top-level ``stylesheet`` property of your view template.
808