1===========================
2Search Configuration Schema
3===========================
4
5.. note::
6    This configuration is currently under testing for nightly builds only, see
7    `Bug 1542235`_ for more status information.
8
9This document outlines the details of the schema and how the various sub-parts
10interact. For the full fields and descriptions, please see the `schema itself`_.
11
12.. note::
13    In the examples, only relevant properties are displayed.
14
15Overview
16========
17
18The configuration is a JSON blob which is object with a `data` property which
19is an array of engines:
20
21.. code-block:: js
22
23    {
24      data: [
25        {
26          // engine 1 details
27        },
28        {
29          // engine 2 details
30        }
31      ]
32    }
33
34Engine Objects
35==============
36
37An engine's details are located in the properties of the object associated with it.
38An engine that is deployed globally could be listed simply as:
39
40.. code-block:: js
41
42    {
43      "default": "no",
44      "telemetryId": "engine1-telem",
45      "webExtension": {
46        "id": "web@ext"
47      },
48      "appliesTo": [{
49        "included": {
50          "everywhere": true
51        }
52      }]
53    }
54
55The ``appliesTo`` section is an array of objects. At least one object is required
56to specify which regions/locales the engine is included within. If an
57``appliesTo`` object lists additional attributes then these will override any
58attributes at the top-level.
59
60For example, a more complex engine definition may be available only to users
61located specific regions or with certain locales. For example:
62
63.. code-block:: js
64
65    {
66      "webExtension": {
67        "id": "web@ext"
68      },
69      "appliesTo": [{
70        "included": {
71          "region": "us"
72        },
73        "webExtension": {
74          "id": "web-us@ext"
75        }
76      }, {
77        "included": {
78          "region": "gb"
79        },
80        "webExtension": {
81          "id": "web-gb@ext"
82        }
83      }]
84    }
85
86In this case users identified as being in the US region would use the WebExtension
87with identifier ``web-us@ext``. GB region users would get
88``web-gb@ext``, and all other users would get ``web@ext``.
89
90Special Attributes
91==================
92
93$USER_LOCALE
94------------
95
96If a ``webExtension.locales`` property contains an element with the value
97``"$USER_LOCALE"`` then the special value will be replaced in the
98configuration object with the users locale. For example:
99
100.. code-block:: js
101
102    {
103      "webExtension": {
104        "id": "web@ext"
105      },
106      "appliesTo": [{
107        "included": {
108          "locales": {
109            "matches": ["us", "gb"]
110          },
111          "webExtension": {
112            "locales": ["$USER_LOCALE"],
113          }
114        }
115      }]
116    }
117
118Will report either ``[us]`` or ``[gb]`` as the ``webExtension.locales``
119depending on the user's locale.
120
121"default"
122---------
123
124You can specify ``"default"`` as a region in the configuration if
125the engine is to be included when we do not know the user's region.
126
127"override"
128----------
129
130The `"override"` field can be set to true if you want a section to
131only override otherwise included engines. For example:
132
133.. code-block:: js
134
135    {
136      "webExtension": {
137        "id": "web@ext"
138      },
139      "appliesTo": [{
140        // Complicated and lengthy inclusion rules
141      }, {
142        "override": true,
143        "application": { "distributions": ["mydistrocode"]},
144        "params": {
145          "searchUrlGetParams": [
146            { "name": "custom", "value": "foobar" }
147          ]
148        }
149      }]
150    }
151
152Application Scoping
153===================
154
155An engine configuration may be scoped to a particular application.
156
157Name
158----
159
160One or more application names may be specified. Currently the only application
161type supported is ``firefox``. If an application name is specified, then it
162must be matched for the section to apply. If there are no application names
163specified, then the section will match any consumer of the configuration.
164
165In the following example, ``web@ext`` would be included on any consumer
166of the configuration, but ``web1@ext`` would only be included on Firefox desktop.
167
168.. code-block:: js
169
170    {
171      "webExtension": {
172        "id": "web@ext"
173      },
174      "appliesTo": [{
175        "included": {
176          "everywhere": true
177          "application": {
178            "name": []
179          }
180        }
181      ]}
182    },
183    {
184      "webExtension": {
185        "id": "web1@ext"
186      },
187      "appliesTo": [{
188        "included": {
189          "everywhere": true
190          "application": {
191            "name": ["firefox"]
192          }
193        }
194      ]}
195    }
196
197Channel
198-------
199
200One or more channels may be specified in an array to restrict a configuration
201to just those channels. The current known channels are:
202
203    - default: Self-builds of Firefox, or possibly some self-distributed versions.
204    - nightly: Firefox Nightly builds.
205    - aurora: Firefox Developer Edition
206    - beta: Firefox Beta
207    - release: The main Firefox release channel.
208    - esr: The ESR Channel. This will also match versions of Firefox where the
209      displayed version number includes ``esr``. We do this to include Linux
210      distributions and other manual builds of ESR.
211
212In the following example, ``web@ext`` would be set as default on the default
213channel only, whereas ``web1@ext`` would be set as default on release and esr
214channels.
215
216.. code-block:: js
217
218    {
219      "webExtension": {
220        "id": "web@ext"
221      },
222      "appliesTo": [{
223        "included": {
224          "everywhere": true
225          "default": "yes",
226          "application": {
227            "channel": ["default"]
228          }
229        }
230      ]}
231    },
232    {
233      "webExtension": {
234        "id": "web1@ext"
235      },
236      "appliesTo": [{
237        "included": {
238          "everywhere": true
239          "default": "yes",
240          "application": {
241            "channel": ["release", "esr"]
242          }
243        }
244      ]}
245    }
246
247Distributions
248-------------
249
250Distributions may be specified to be included or excluded in an ``appliesTo``
251section. The ``distributions`` field in the ``application`` section is an array
252of distribution identifiers. The identifiers match those supplied by the
253``distribution.id`` preference.
254
255In the following, ``web@ext`` would be included in only the ``cake``
256distribution. ``web1@ext`` would be excluded from the ``apples`` distribution
257but included in the main desktop application, and all other distributions.
258
259.. code-block:: js
260
261    {
262      "webExtension": {
263        "id": "web@ext"
264      },
265      "appliesTo": [{
266        "included": {
267          "everywhere": true
268          "application": {
269            "distributions": ["cake"]
270          }
271        }
272      ]}
273    },
274    {
275      "webExtension": {
276        "id": "web1@ext"
277      },
278      "appliesTo": [{
279        "included": {
280          "everywhere": true
281          "application": {
282            "excludedDistributions": ["apples"]
283          }
284        }
285      ]}
286    }
287
288Version
289-------
290
291Minimum and Maximum versions may be specified to restrict a configuration to
292specific ranges. These may be open-ended. Version comparison is performed
293using `the version comparator`_.
294
295Note: comparison against ``maxVersion`` is a less-than comparison. The
296``maxVersion`` won't be matched directly.
297
298In the following example, ``web@ext`` would be included for any version after
29972.0a1, whereas ``web1@ext`` would be included only between 68.0a1 and 71.x
300version.
301
302.. code-block:: js
303
304    {
305      "webExtension": {
306        "id": "web@ext"
307      },
308      "appliesTo": [{
309        "included": {
310          "everywhere": true
311          "application": {
312            "minVersion": "72.0a1"
313          }
314        }
315      ]}
316    },
317    {
318      "webExtension": {
319        "id": "web1@ext"
320      },
321      "appliesTo": [{
322        "included": {
323          "everywhere": true
324          "default": "yes",
325          "application": {
326            "minVersion": "68.0a1"
327            "maxVersion": "72.0a1"
328          }
329        }
330      ]}
331    }
332
333Experiments
334===========
335
336We can run experiments by giving sections within ``appliesTo`` a
337``experiment`` value, the Search Service can then optionally pass in a
338matching ``experiment`` value to match those sections.
339
340Sections which have a ``experiment`` will not be used unless a matching
341``experiment`` has been passed in, for example:
342
343.. code-block:: js
344
345    {
346      "webExtension": {
347        "id": "web@ext"
348      },
349      "appliesTo": [{
350        "included": {
351          "everywhere": true
352        },
353        "experiment": "nov-16",
354        "webExtension": {
355          "id": "web-experimental@ext"
356        }
357      }, {
358        "included": {
359          "everywhere": true
360        },
361        "webExtension": {
362          "id": "web-gb@ext"
363        }
364      }]
365    }
366
367Engine Defaults
368===============
369
370An engine may be specified as the default for one of two purposes:
371
372#. normal browsing mode,
373#. private browsing mode.
374
375If there is no engine specified for private browsing mode for a particular region/locale
376pair, then the normal mode engine is used.
377
378If the instance of the application does not support a separate private browsing mode engine,
379then it will only use the normal mode engine.
380
381An engine may or may not be default for particular regions/locales. The ``default``
382property is a tri-state value with states of ``yes``, ``yes-if-no-other`` and
383``no``. Here's an example of how they apply:
384
385.. code-block:: js
386
387    {
388      "webExtension": {
389        "id": "engine1@ext"
390      },
391      "appliesTo": [{
392        "included": {
393          "region": "us"
394        },
395        "default": "yes"
396      }, {
397        "excluded": {
398          "region": "us"
399        },
400        "default": "yes-if-no-other"
401      }]
402    },
403    {
404      "webExtension": {
405        "id": "engine2@ext"
406      },
407      "appliesTo": [{
408        "included": {
409          "region": "gb"
410        },
411        "default": "yes"
412      }]
413    },
414      "webExtension": {
415        "id": "engine3@ext"
416      },
417      "default": "no"
418      "appliesTo": [{
419        "included": {
420          "everywhere": true
421        },
422      }]
423    },
424    {
425      "webExtension": {
426        "id": "engine4@ext"
427      },
428      "defaultPrivate": "yes",
429      "appliesTo": [{
430        "included": {
431          "region": "fr"
432        }
433      }]
434    }
435
436In this example, for normal mode:
437
438    - engine1@ext is default in the US region, and all other regions except for GB
439    - engine2@ext is default in only the GB region
440    - engine3@ext and engine4 are never default anywhere
441
442In private browsing mode:
443
444    - engine1@ext is default in the US region, and all other regions execpt for GB and FR
445    - engine2@ext is default in only the GB region
446    - engine3@ext is never default anywhere
447    - engine4@ext is default in the FR region.
448
449Engine Ordering
450===============
451
452The ``orderHint`` field indicates the suggested ordering of an engine relative to
453other engines when displayed to the user, unless the user has customized their
454ordering.
455
456The default ordering of engines is based on a combination of if the engine is
457default, and the ``orderHint`` fields. The ordering is structured as follows:
458
459#. Default engine in normal mode
460#. Default engine in private browsing mode (if different from the normal mode engine)
461#. Other engines in order from the highest ``orderHint`` to the lowest.
462
463Example:
464
465.. code-block:: js
466
467    {
468      "webExtension": {
469        "id": "engine1@ext"
470      },
471      "orderHint": 2000,
472      "default": "no",
473    },
474    {
475      "webExtension": {
476        "id": "engine2@ext"
477      },
478      "orderHint": 1000,
479      "default": "yes"
480    },
481    {
482      "webExtension": {
483        "id": "engine3@ext"
484      },
485      "orderHint": 500,
486      "default": "no"
487    }
488
489This would result in the order: ``engine2@ext, engine1@ext, engine3@ext``.
490
491.. _Bug 1542235: https://bugzilla.mozilla.org/show_bug.cgi?id=1542235
492.. _schema itself: https://searchfox.org/mozilla-central/source/toolkit/components/search/schema/
493.. _the version comparator: https://developer.mozilla.org/en-US/docs/Mozilla/Toolkit_version_format
494