diff options
Diffstat (limited to '')
-rw-r--r-- | browser/components/urlbar/docs/overview.rst | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/browser/components/urlbar/docs/overview.rst b/browser/components/urlbar/docs/overview.rst new file mode 100644 index 0000000000..0ff1ee5ad7 --- /dev/null +++ b/browser/components/urlbar/docs/overview.rst @@ -0,0 +1,413 @@ +Architecture Overview +===================== + +The address bar is implemented as a *model-view-controller* (MVC) system. One of +the scopes of this architecture is to allow easy replacement of its components, +for easier experimentation. + +Each search is represented by a unique object, the *UrlbarQueryContext*. This +object, created by the *View*, describes the search and is passed through all of +the components, along the way it gets augmented with additional information. +The *UrlbarQueryContext* is passed to the *Controller*, and finally to the +*Model*. The model appends results to a property of *UrlbarQueryContext* in +chunks, it sorts them through a *Muxer* and then notifies the *Controller*. + +See the specific components below, for additional details about each one's tasks +and responsibilities. + + +The UrlbarQueryContext +---------------------- + +The *UrlbarQueryContext* object describes a single instance of a search. +It is augmented as it progresses through the system, with various information: + +.. highlight:: JavaScript +.. code:: + + UrlbarQueryContext { + allowAutofill; // {boolean} If true, providers are allowed to return + // autofill results. Even if true, it's up to providers + // whether to include autofill results, but when false, no + // provider should include them. + isPrivate; // {boolean} Whether the search started in a private context. + maxResults; // {integer} The maximum number of results requested. It is + // possible to request more results than the shown ones, and + // do additional filtering at the View level. + searchString; // {string} The user typed string. + userContextId; // {integer} The user context ID (containers feature). + + // Optional properties. + muxer; // {string} Name of a registered muxer. Muxers can be registered + // through the UrlbarProvidersManager. + providers; // {array} List of registered provider names. Providers can be + // registered through the UrlbarProvidersManager. + sources: {array} list of accepted UrlbarUtils.RESULT_SOURCE for the context. + // This allows to switch between different search modes. If not + // provided, a default will be generated by the Model, depending on + // the search string. + engineName: // {string} if sources is restricting to just SEARCH, this + // property can be used to pick a specific search engine, by + // setting it to the name under which the engine is registered + // with the search service. + currentPage: // {string} url of the page that was loaded when the search + // began. + prohibitRemoteResults: + // {boolean} This provides a short-circuit override for + // context.allowRemoteResults(). If it's false, then allowRemoteResults() + // will do its usual checks to determine whether remote results are + // allowed. If it's true, then allowRemoteResults() will immediately + // return false. Defaults to false. + + // Properties added by the Model. + results; // {array} list of UrlbarResult objects. + tokens; // {array} tokens extracted from the searchString, each token is an + // object in the form {type, value, lowerCaseValue}. + } + + +The Model +--------- + +The *Model* is the component responsible for retrieving search results based on +the user's input, and sorting them accordingly to their importance. +At the core is the `UrlbarProvidersManager <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarProvidersManager.jsm>`_, +a component tracking all the available search providers, and managing searches +across them. + +The *UrlbarProvidersManager* is a singleton, it registers internal providers on +startup and can register/unregister providers on the fly. +It can manage multiple concurrent queries, and tracks them internally as +separate *Query* objects. + +The *Controller* starts and stops queries through the *UrlbarProvidersManager*. +It's possible to wait for the promise returned by *startQuery* to know when no +more results will be returned, it is not mandatory though. +Queries can be canceled. + +.. note:: + + Canceling a query will issue an interrupt() on the database connection, + terminating any running and future SQL query, unless a query is running inside + a *runInCriticalSection* task. + +The *searchString* gets tokenized by the `UrlbarTokenizer <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarTokenizer.jsm>`_ +component into tokens, some of these tokens have a special meaning and can be +used by the user to restrict the search to specific result type (See the +*UrlbarTokenizer::TYPE* enum). + +.. caution:: + + The tokenizer uses heuristics to determine each token's type, as such the + consumer may want to check the value before applying filters. + +.. highlight:: JavaScript +.. code:: + + UrlbarProvidersManager { + registerProvider(providerObj); + unregisterProvider(providerObj); + registerMuxer(muxerObj); + unregisterMuxer(muxerObjOrName); + async startQuery(queryContext); + cancelQuery(queryContext); + // Can be used by providers to run uninterruptible queries. + runInCriticalSection(taskFn); + } + +UrlbarProvider +~~~~~~~~~~~~~~ + +A provider is specialized into searching and returning results from different +information sources. Internal providers are usually implemented in separate +*jsm* modules with a *UrlbarProvider* name prefix. External providers can be +registered as *Objects* through the *UrlbarProvidersManager*. +Each provider is independent and must satisfy a base API, while internal +implementation details may vary deeply among different providers. + +.. important:: + + Providers are singleton, and must track concurrent searches internally, for + example mapping them by UrlbarQueryContext. + +.. note:: + + Internal providers can access the Places database through the + *PlacesUtils.promiseLargeCacheDBConnection* utility. + +.. highlight:: JavaScript +.. code:: + + class UrlbarProvider { + /** + * Unique name for the provider, used by the context to filter on providers. + * Not using a unique name will cause the newest registration to win. + * @abstract + */ + get name() { + return "UrlbarProviderBase"; + } + /** + * The type of the provider, must be one of UrlbarUtils.PROVIDER_TYPE. + * @abstract + */ + get type() { + throw new Error("Trying to access the base class, must be overridden"); + } + /** + * Whether this provider should be invoked for the given context. + * If this method returns false, the providers manager won't start a query + * with this provider, to save on resources. + * @param {UrlbarQueryContext} queryContext The query context object + * @returns {boolean} Whether this provider should be invoked for the search. + * @abstract + */ + isActive(queryContext) { + throw new Error("Trying to access the base class, must be overridden"); + } + /** + * Gets the provider's priority. Priorities are numeric values starting at + * zero and increasing in value. Smaller values are lower priorities, and + * larger values are higher priorities. For a given query, `startQuery` is + * called on only the active and highest-priority providers. + * @param {UrlbarQueryContext} queryContext The query context object + * @returns {number} The provider's priority for the given query. + * @abstract + */ + getPriority(queryContext) { + // By default, all providers share the lowest priority. + return 0; + } + /** + * Starts querying. + * @param {UrlbarQueryContext} queryContext The query context object + * @param {function} addCallback Callback invoked by the provider to add a new + * result. A UrlbarResult should be passed to it. + * @note Extended classes should return a Promise resolved when the provider + * is done searching AND returning results. + * @abstract + */ + startQuery(queryContext, addCallback) { + throw new Error("Trying to access the base class, must be overridden"); + } + /** + * Cancels a running query, + * @param {UrlbarQueryContext} queryContext The query context object to cancel + * query for. + * @abstract + */ + cancelQuery(queryContext) { + throw new Error("Trying to access the base class, must be overridden"); + } + } + +UrlbarMuxer +~~~~~~~~~~~ + +The *Muxer* is responsible for sorting results based on their importance and +additional rules that depend on the UrlbarQueryContext. The muxer to use is +indicated by the UrlbarQueryContext.muxer property. + +.. caution:: + + The Muxer is a replaceable component, as such what is described here is a + reference for the default View, but may not be valid for other implementations. + +.. highlight:: JavaScript +.. code:: + + class UrlbarMuxer { + /** + * Unique name for the muxer, used by the context to sort results. + * Not using a unique name will cause the newest registration to win. + * @abstract + */ + get name() { + return "UrlbarMuxerBase"; + } + /** + * Sorts UrlbarQueryContext results in-place. + * @param {UrlbarQueryContext} queryContext the context to sort results for. + * @abstract + */ + sort(queryContext) { + throw new Error("Trying to access the base class, must be overridden"); + } + } + + +The Controller +-------------- + +`UrlbarController <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarController.jsm>`_ +is the component responsible for reacting to user's input, by communicating +proper course of action to the Model (e.g. starting/stopping a query) and the +View (e.g. showing/hiding a panel). It is also responsible for reporting Telemetry. + +.. note:: + + Each *View* has a different *Controller* instance. + +.. highlight:: JavaScript +.. code:: + + UrlbarController { + async startQuery(queryContext); + cancelQuery(queryContext); + // Invoked by the ProvidersManager when results are available. + receiveResults(queryContext); + // Used by the View to listen for results. + addQueryListener(listener); + removeQueryListener(listener); + } + + +The View +-------- + +The View is the component responsible for presenting search results to the +user and handling their input. + +.. caution + + The View is a replaceable component, as such what is described here is a + reference for the default View, but may not be valid for other implementations. + +`UrlbarInput.jsm <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarInput.jsm>`_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Implements an input box *View*, owns an *UrlbarView*. + +.. highlight:: JavaScript +.. code:: + + UrlbarInput { + constructor(options = { textbox, panel }); + // Uses UrlbarValueFormatter to highlight the base host, search aliases + // and to keep the host visible on overflow. + formatValue(val); + openResults(); + // Converts an internal URI (e.g. a URI with a username or password) into + // one which we can expose to the user. + makeURIReadable(uri); + // Handles an event which would cause a url or text to be opened. + handleCommand(); + // Called by the view when a result is selected. + resultsSelected(); + // The underlying textbox + textbox; + // The results panel. + panel; + // The containing window. + window; + // The containing document. + document; + // An UrlbarController instance. + controller; + // An UrlbarView instance. + view; + // Whether the current value was typed by the user. + valueIsTyped; + // Whether the context is in Private Browsing mode. + isPrivate; + // Whether the input box is focused. + focused; + // The go button element. + goButton; + // The current value, can also be set. + value; + } + +`UrlbarView.jsm <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarView.jsm>`_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Represents the base *View* implementation, communicates with the *Controller*. + +.. highlight:: JavaScript +.. code:: + + UrlbarView { + // Manage View visibility. + open(); + close(); + // Invoked when the query starts. + onQueryStarted(queryContext); + // Invoked when new results are available. + onQueryResults(queryContext); + // Invoked when the query has been canceled. + onQueryCancelled(queryContext); + // Invoked when the query is done. This is invoked in any case, even if the + // query was canceled earlier. + onQueryFinished(queryContext); + // Invoked when the view opens. + onViewOpen(); + // Invoked when the view closes. + onViewClose(); + } + + +UrlbarResult +------------ + +An `UrlbarResult <https://searchfox.org/mozilla-central/source/browser/components/urlbar/UrlbarResult.jsm>`_ +instance represents a single search result with a result type, that +identifies specific kind of results. +Each kind has its own properties, that the *View* may support, and a few common +properties, supported by all of the results. + +.. note:: + + Result types are also enumerated by *UrlbarUtils.RESULT_TYPE*. + +.. code-block:: + + UrlbarResult { + constructor(resultType, payload); + + type: {integer} One of UrlbarUtils.RESULT_TYPE. + source: {integer} One of UrlbarUtils.RESULT_SOURCE. + title: {string} A title that may be used as a label for this result. + icon: {string} Url of an icon for this result. + payload: {object} Object containing properties for the specific RESULT_TYPE. + autofill: {object} An object describing the text that should be + autofilled in the input when the result is selected, if any. + autofill.value: {string} The autofill value. + autofill.selectionStart: {integer} The first index in the autofill + selection. + autofill.selectionEnd: {integer} The last index in the autofill selection. + suggestedIndex: {integer} Suggest a preferred position for this result + within the result set. Undefined if none. + isSuggestedIndexRelativeToGroup: {boolean} Whether the suggestedIndex + property is relative to the result's group + instead of the entire result set. + } + +The following RESULT_TYPEs are supported: + +.. highlight:: JavaScript +.. code:: + + // An open tab. + // Payload: { icon, url, userContextId } + TAB_SWITCH: 1, + // A search suggestion or engine. + // Payload: { icon, suggestion, keyword, query, providesSearchMode, inPrivateWindow, isPrivateEngine } + SEARCH: 2, + // A common url/title tuple, may be a bookmark with tags. + // Payload: { icon, url, title, tags } + URL: 3, + // A bookmark keyword. + // Payload: { icon, url, keyword, postData } + KEYWORD: 4, + // A WebExtension Omnibox result. + // Payload: { icon, keyword, title, content } + OMNIBOX: 5, + // A tab from another synced device. + // Payload: { icon, url, device, title } + REMOTE_TAB: 6, + // An actionable message to help the user with their query. + // Payload: { buttons, helpL10n, helpUrl, icon, titleL10n, type } + TIP: 7, + // A type of result created at runtime, for example by an extension. + // Payload: { dynamicType } + DYNAMIC: 8, |