tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

overview.rst (15634B)


      1 Architecture Overview
      2 =====================
      3 
      4 The address bar is implemented as a *model-view-controller* (MVC) system. One of
      5 the scopes of this architecture is to allow easy replacement of its components,
      6 for easier experimentation.
      7 
      8 Each search is represented by a unique object, the *UrlbarQueryContext*. This
      9 object, created by the *View*, describes the search and is passed through all of
     10 the components, along the way it gets augmented with additional information.
     11 The *UrlbarQueryContext* is passed to the *Controller*, and finally to the
     12 *Model*.  The model appends results to a property of *UrlbarQueryContext* in
     13 chunks, it sorts them through a *Muxer* and then notifies the *Controller*.
     14 
     15 See the specific components below, for additional details about each one's tasks
     16 and responsibilities.
     17 
     18 
     19 The UrlbarQueryContext
     20 ----------------------
     21 
     22 The *UrlbarQueryContext* object describes a single instance of a search.
     23 It is augmented as it progresses through the system, with various information:
     24 
     25 .. code:: JavaScript
     26 
     27  UrlbarQueryContext {
     28    allowAutofill; // {boolean} If true, providers are allowed to return
     29                   // autofill results.  Even if true, it's up to providers
     30                   // whether to include autofill results, but when false, no
     31                   // provider should include them.
     32    isPrivate; // {boolean} Whether the search started in a private context.
     33    maxResults; // {integer} The maximum number of results requested. It is
     34                // possible to request more results than the shown ones, and
     35                // do additional filtering at the View level.
     36    searchString; // {string} The user typed string.
     37    userContextId; // {integer} The user context ID (containers feature).
     38 
     39    // Optional properties.
     40    muxer; // {string} Name of a registered muxer. Muxers can be registered
     41           // through the UrlbarProvidersManager.
     42    providers; // {array} List of registered provider names. Providers can be
     43               // registered through the UrlbarProvidersManager.
     44    sources: {array} list of accepted UrlbarUtils.RESULT_SOURCE for the context.
     45            // This allows to switch between different search modes. If not
     46            // provided, a default will be generated by the Model, depending on
     47            // the search string.
     48    engineName: // {string} if sources is restricting to just SEARCH, this
     49                // property can be used to pick a specific search engine, by
     50                // setting it to the name under which the engine is registered
     51                // with the search service.
     52    currentPage: // {string} url of the page that was loaded when the search
     53                 // began.
     54    prohibitRemoteResults:
     55      // {boolean} This provides a short-circuit override for
     56      // context.allowRemoteResults(). If it's false, then allowRemoteResults()
     57      // will do its usual checks to determine whether remote results are
     58      // allowed. If it's true, then allowRemoteResults() will immediately
     59      // return false. Defaults to false.
     60 
     61    // Properties added by the Model.
     62    results; // {array} list of UrlbarResult objects.
     63    tokens; // {array} tokens extracted from the searchString, each token is an
     64            // object in the form {type, value, lowerCaseValue}.
     65  }
     66 
     67 
     68 The Model
     69 ---------
     70 
     71 The *Model* is the component responsible for retrieving search results based on
     72 the user's input, and sorting them accordingly to their importance.
     73 At the core is the `UrlbarProvidersManager <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarProvidersManager.sys.mjs>`_,
     74 a component tracking all the available search providers, and managing searches
     75 across them.
     76 
     77 The *UrlbarProvidersManager* is a singleton, it registers internal providers on
     78 startup and can register/unregister providers on the fly.
     79 It can manage multiple concurrent queries, and tracks them internally as
     80 separate *Query* objects.
     81 
     82 The *Controller* starts and stops queries through the *UrlbarProvidersManager*.
     83 It's possible to wait for the promise returned by *startQuery* to know when no
     84 more results will be returned, it is not mandatory though.
     85 Queries can be canceled.
     86 
     87 .. note::
     88 
     89  Canceling a query will issue an interrupt() on the database connection,
     90  terminating any running and future SQL query, unless a query is running inside
     91  a *runInCriticalSection* task.
     92 
     93 The *searchString* gets tokenized by the `UrlbarTokenizer <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarTokenizer.sys.mjs>`_
     94 component into tokens, some of these tokens have a special meaning and can be
     95 used by the user to restrict the search to specific result type (See the
     96 *UrlbarTokenizer::TYPE* enum).
     97 
     98 .. caution::
     99 
    100  The tokenizer uses heuristics to determine each token's type, as such the
    101  consumer may want to check the value before applying filters.
    102 
    103 .. code:: JavaScript
    104 
    105  UrlbarProvidersManager {
    106    registerProvider(providerObj);
    107    unregisterProvider(providerObj);
    108    registerMuxer(muxerObj);
    109    unregisterMuxer(muxerObjOrName);
    110    async startQuery(queryContext);
    111    cancelQuery(queryContext);
    112    // Can be used by providers to run uninterruptible queries.
    113    runInCriticalSection(taskFn);
    114  }
    115 
    116 UrlbarProvider
    117 ~~~~~~~~~~~~~~
    118 
    119 A provider is specialized into searching and returning results from different
    120 information sources. Internal providers are usually implemented in separate
    121 *sys.mjs* modules with a *UrlbarProvider* name prefix. External providers can be
    122 registered as *Objects* through the *UrlbarProvidersManager*.
    123 Each provider is independent and must satisfy a base API, while internal
    124 implementation details may vary deeply among different providers.
    125 
    126 .. important::
    127 
    128  Providers are singleton, and must track concurrent searches internally, for
    129  example mapping them by UrlbarQueryContext.
    130 
    131 .. note::
    132 
    133  Internal providers can access the Places database through the
    134  *PlacesUtils.promiseLargeCacheDBConnection* utility.
    135 
    136 .. code:: JavaScript
    137 
    138  class UrlbarProvider {
    139    /**
    140     * Unique name for the provider, used by the context to filter on providers.
    141     * Not using a unique name will cause the newest registration to win.
    142     * @abstract
    143     */
    144    get name() {
    145      return "UrlbarProviderBase";
    146    }
    147    /**
    148     * The type of the provider, must be one of UrlbarUtils.PROVIDER_TYPE.
    149     *
    150     * @returns {Values<typeof UrlbarUtils.PROVIDER_TYPE>}
    151     * @abstract
    152     */
    153    get type() {
    154      throw new Error("Trying to access the base class, must be overridden");
    155    }
    156    /**
    157     * Whether this provider should be invoked for the given context.
    158     * If this method returns false, the providers manager won't start a query
    159     * with this provider, to save on resources.
    160     *
    161     * @param {UrlbarQueryContext} queryContext
    162     *   The query context object
    163     * @param {UrlbarController} controller
    164     *   The current controller.
    165     * @returns {Promise<boolean>}
    166     *   Whether this provider should be invoked for the search.
    167     * @abstract
    168     */
    169    isActive(queryContext) {
    170      throw new Error("Trying to access the base class, must be overridden");
    171    }
    172    /**
    173     * Gets the provider's priority.  Priorities are numeric values starting at
    174     * zero and increasing in value.  Smaller values are lower priorities, and
    175     * larger values are higher priorities.  For a given query, `startQuery` is
    176     * called on only the active and highest-priority providers.
    177     * @param {UrlbarQueryContext} queryContext The query context object
    178     * @returns {number} The provider's priority for the given query.
    179     * @abstract
    180     */
    181    getPriority(queryContext) {
    182      // By default, all providers share the lowest priority.
    183      return 0;
    184    }
    185    /**
    186     * Starts querying.
    187     * @param {UrlbarQueryContext} queryContext The query context object
    188     * @param {function} addCallback Callback invoked by the provider to add a new
    189     *        result. A UrlbarResult should be passed to it.
    190     * @note Extended classes should return a Promise resolved when the provider
    191     *       is done searching AND returning results.
    192     * @abstract
    193     */
    194    startQuery(queryContext, addCallback) {
    195      throw new Error("Trying to access the base class, must be overridden");
    196    }
    197    /**
    198     * Cancels a running query,
    199     * @param {UrlbarQueryContext} queryContext The query context object to cancel
    200     *        query for.
    201     * @abstract
    202     */
    203    cancelQuery(queryContext) {
    204      throw new Error("Trying to access the base class, must be overridden");
    205    }
    206  }
    207 
    208 UrlbarMuxer
    209 ~~~~~~~~~~~
    210 
    211 The *Muxer* is responsible for sorting results based on their importance and
    212 additional rules that depend on the UrlbarQueryContext. The muxer to use is
    213 indicated by the UrlbarQueryContext.muxer property.
    214 
    215 .. caution::
    216 
    217  The Muxer is a replaceable component, as such what is described here is a
    218  reference for the default View, but may not be valid for other implementations.
    219 
    220 .. code:: JavaScript
    221 
    222  class UrlbarMuxer {
    223    /**
    224     * Unique name for the muxer, used by the context to sort results.
    225     * Not using a unique name will cause the newest registration to win.
    226     * @abstract
    227     */
    228    get name() {
    229      return "UrlbarMuxerBase";
    230    }
    231    /**
    232     * Sorts UrlbarQueryContext results in-place.
    233     * @param {UrlbarQueryContext} queryContext the context to sort results for.
    234     * @param {Array} unsortedResults
    235     *   The array of UrlbarResult that is not sorted yet.
    236     * @abstract
    237     */
    238    sort(queryContext, unsortedResults) {
    239      throw new Error("Trying to access the base class, must be overridden");
    240    }
    241  }
    242 
    243 
    244 The Controller
    245 --------------
    246 
    247 `UrlbarController <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarController.sys.mjs>`_
    248 is the component responsible for reacting to user's input, by communicating
    249 proper course of action to the Model (e.g. starting/stopping a query) and the
    250 View (e.g. showing/hiding a panel). It is also responsible for reporting Telemetry.
    251 
    252 .. note::
    253 
    254  Each *View* has a different *Controller* instance.
    255 
    256 .. code:: JavaScript
    257 
    258  UrlbarController {
    259    async startQuery(queryContext);
    260    cancelQuery(queryContext);
    261    // Invoked by the ProvidersManager when results are available.
    262    receiveResults(queryContext);
    263    // Used by the View to listen for results.
    264    addListener(listener);
    265    removeListener(listener);
    266  }
    267 
    268 
    269 The View
    270 --------
    271 
    272 The View is the component responsible for presenting search results to the
    273 user and handling their input.
    274 
    275 .. caution
    276 
    277  The View is a replaceable component, as such what is described here is a
    278  reference for the default View, but may not be valid for other implementations.
    279 
    280 `UrlbarInput.sys.mjs <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarInput.sys.mjs>`_
    281 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    282 
    283 Implements an input box *View*, owns an *UrlbarView*.
    284 
    285 .. code:: JavaScript
    286 
    287  UrlbarInput {
    288    constructor(options = { textbox, panel });
    289    // Uses UrlbarValueFormatter to highlight the base host, search aliases
    290    // and to keep the host visible on overflow.
    291    formatValue(val);
    292    openResults();
    293    // Converts an internal URI (e.g. a URI with a username or password) into
    294    // one which we can expose to the user.
    295    makeURIReadable(uri);
    296    // Handles an event which would cause a url or text to be opened.
    297    handleCommand();
    298    // Called by the view when a result is selected.
    299    resultsSelected();
    300    // The underlying textbox
    301    textbox;
    302    // The results panel.
    303    panel;
    304    // The containing window.
    305    window;
    306    // The containing document.
    307    document;
    308    // An UrlbarController instance.
    309    controller;
    310    // An UrlbarView instance.
    311    view;
    312    // Whether the current value was typed by the user.
    313    valueIsTyped;
    314    // Whether the context is in Private Browsing mode.
    315    isPrivate;
    316    // Whether the input box is focused.
    317    focused;
    318    // The go button element.
    319    goButton;
    320    // The current value, can also be set.
    321    value;
    322  }
    323 
    324 `UrlbarView.sys.mjs <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarView.sys.mjs>`_
    325 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    326 
    327 Represents the base *View* implementation, communicates with the *Controller*.
    328 
    329 .. code:: JavaScript
    330 
    331  UrlbarView {
    332    // Manage View visibility.
    333    open();
    334    close();
    335    // Invoked when the query starts.
    336    onQueryStarted(queryContext);
    337    // Invoked when new results are available.
    338    onQueryResults(queryContext);
    339    // Invoked when the query has been canceled.
    340    onQueryCancelled(queryContext);
    341    // Invoked when the query is done. This is invoked in any case, even if the
    342    // query was canceled earlier.
    343    onQueryFinished(queryContext);
    344    // Invoked when the view opens.
    345    onViewOpen();
    346    // Invoked when the view closes.
    347    onViewClose();
    348  }
    349 
    350 
    351 UrlbarResult
    352 ------------
    353 
    354 An `UrlbarResult <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarResult.sys.mjs>`_
    355 instance represents a single search result with a result type, that
    356 identifies specific kind of results.
    357 Each kind has its own properties, that the *View* may support, and a few common
    358 properties, supported by all of the results.
    359 
    360 .. note::
    361 
    362  Result types are also enumerated by *UrlbarUtils.RESULT_TYPE*.
    363 
    364 .. code-block:: JavaScript
    365 
    366  UrlbarResult {
    367    constructor(resultType, payload);
    368 
    369    type: {integer} One of UrlbarUtils.RESULT_TYPE.
    370    source: {integer} One of UrlbarUtils.RESULT_SOURCE.
    371    title: {string} A title that may be used as a label for this result.
    372    icon: {string} Url of an icon for this result.
    373    payload: {object} Object containing properties for the specific RESULT_TYPE.
    374    autofill: {object} An object describing the text that should be
    375              autofilled in the input when the result is selected, if any.
    376    autofill.value: {string} The autofill value.
    377    autofill.selectionStart: {integer} The first index in the autofill
    378                             selection.
    379    autofill.selectionEnd: {integer} The last index in the autofill selection.
    380    suggestedIndex: {integer} Suggest a preferred position for this result
    381                    within the result set. Undefined if none.
    382    isSuggestedIndexRelativeToGroup: {boolean} Whether the suggestedIndex
    383                                     property is relative to the result's group
    384                                     instead of the entire result set.
    385  }
    386 
    387 The following RESULT_TYPEs are supported:
    388 
    389 .. code:: JavaScript
    390 
    391    // An open tab.
    392    // Payload: { icon, url, userContextId }
    393    TAB_SWITCH: 1,
    394    // A search suggestion or engine.
    395    // Payload: { icon, suggestion, keyword, query, providesSearchMode, inPrivateWindow, isPrivateEngine }
    396    SEARCH: 2,
    397    // A common url/title tuple, may be a bookmark with tags.
    398    // Payload: { icon, url, title, tags }
    399    URL: 3,
    400    // A bookmark keyword.
    401    // Payload: { icon, url, keyword, postData }
    402    KEYWORD: 4,
    403    // A WebExtension Omnibox result.
    404    // Payload: { icon, keyword, title, content }
    405    OMNIBOX: 5,
    406    // A tab from another synced device.
    407    // Payload: { icon, url, device, title }
    408    REMOTE_TAB: 6,
    409    // An actionable message to help the user with their query.
    410    // Payload: { buttons, helpL10n, helpUrl, icon, titleL10n, type }
    411    TIP: 7,
    412    // A type of result which layout is defined at runtime.
    413    // Payload: { dynamicType }
    414    DYNAMIC: 8,