/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { SearchModeSwitcher } from "chrome://browser/content/urlbar/SearchModeSwitcher.mjs"; import { UrlbarChildController } from "chrome://browser/content/urlbar/UrlbarChildController.mjs"; import { UrlbarEventBufferer } from "chrome://browser/content/urlbar/UrlbarEventBufferer.mjs"; import * as UrlbarContentUtils from "chrome://browser/content/urlbar/UrlbarContentUtils.mjs"; import UrlbarPrefs from "chrome://browser/content/urlbar/UrlbarContentPrefs.mjs"; import { UrlbarQueryContext } from "chrome://browser/content/urlbar/UrlbarQueryContext.mjs"; import { UrlbarView } from "chrome://browser/content/urlbar/UrlbarView.mjs"; import { UrlbarShared } from "chrome://browser/content/urlbar/UrlbarShared.mjs"; /** * @import { UrlbarSearchOneOffs } from "moz-src:///browser/components/urlbar/UrlbarSearchOneOffs.sys.mjs" * @import { SearchEngine } from "moz-src:///toolkit/components/search/SearchEngine.sys.mjs" * @import { SuggestBackendMerino } from "moz-src:///browser/components/urlbar/private/SuggestBackendMerino.sys.mjs" * @import { PartialSearchEngine } from "chrome://browser/content/urlbar/SearchEngineStore.mjs" * @import { BrowserSearchTelemetry } from "moz-src:///browser/components/search/BrowserSearchTelemetry.sys.mjs" * @import { UrlbarLoadRequest } from "chrome://browser/content/urlbar/UrlbarShared.mjs" */ /** * The current window mode. * * @typedef {"classic" | "private" | "smartwindow"} WindowMode */ /** * @typedef {object} AutofillPlaceholder * @property {string} value * The autofill value. * @property {"origin" | "url" | "adaptive_url" | "adaptive_origin"} type * The autofill type. * @property {string} adaptiveHistoryInput * If the type is "adaptive_url" or "adaptive_origin", this is the matching * input value from adaptive history. * @property {number} selectionStart * The selectionStart at the time of autofill. * @property {number} selectionEnd * The selectionEnd at the time of autofill. * @property {string} [untrimmedValue] * The untrimmed value including the protocol. */ const lazy = typeof ChromeUtils != "undefined" ? {} : null; if (lazy) { const { XPCOMUtils } = ChromeUtils.importESModule( "resource://gre/modules/XPCOMUtils.sys.mjs" ); ChromeUtils.defineESModuleGetters(lazy, { AIWindow: "moz-src:///browser/components/aiwindow/ui/modules/AIWindow.sys.mjs", BrowserUIUtils: "resource:///modules/BrowserUIUtils.sys.mjs", CustomizableUI: "moz-src:///browser/components/customizableui/CustomizableUI.sys.mjs", ExtensionSearchHandler: "resource://gre/modules/ExtensionSearchHandler.sys.mjs", ExtensionUtils: "resource://gre/modules/ExtensionUtils.sys.mjs", QuickSuggest: "moz-src:///browser/components/urlbar/QuickSuggest.sys.mjs", ReaderMode: "moz-src:///toolkit/components/reader/ReaderMode.sys.mjs", SharingUtils: "moz-src:///browser/components/sharing/SharingUtils.sys.mjs", SearchUIUtils: "moz-src:///browser/components/search/SearchUIUtils.sys.mjs", UrlbarTokenizer: "moz-src:///browser/components/urlbar/UrlbarTokenizer.sys.mjs", UrlbarSearchUtils: "moz-src:///browser/components/urlbar/UrlbarSearchUtils.sys.mjs", UrlbarUtils: "moz-src:///browser/components/urlbar/UrlbarUtils.sys.mjs", UrlbarValueFormatter: "moz-src:///browser/components/urlbar/UrlbarValueFormatter.sys.mjs", UrlbarSearchTermsPersistence: "moz-src:///browser/components/urlbar/UrlbarSearchTermsPersistence.sys.mjs", UrlUtils: "resource://gre/modules/UrlUtils.sys.mjs", }); XPCOMUtils.defineLazyServiceGetters(lazy, { ClipboardHelper: [ "@mozilla.org/widget/clipboardhelper;1", Ci.nsIClipboardHelper, ], QueryStringStripper: [ "@mozilla.org/url-query-string-stripper;1", Ci.nsIURLQueryStringStripper, ], }); } const logger = () => UrlbarShared.getLogger({ prefix: "Input" }); const UNLIMITED_MAX_RESULTS = 99; // `nsILoadInfo.SchemelessInputTypeSchemeful` and `SchemelessInputTypeSchemeless`, // which a content realm has no `Ci` to read them from. const SCHEMELESS_INPUT_SCHEMEFUL = 1; const SCHEMELESS_INPUT_SCHEMELESS = 2; let getBoundsWithoutFlushing = UrlbarShared.getBoundsWithoutFlushing; // `promiseDocumentFlushed` is chrome-only. A frame does instead, since the // measurements it guards flush layout themselves in a content document. let promiseLayoutFlushed = typeof ChromeUtils != "undefined" ? win => win.promiseDocumentFlushed(() => {}) : win => new Promise(resolve => win.requestAnimationFrame(resolve)); // `getBoxQuads` is gated on a pref for a content caller, and the transform it // ignores is the toolbar's. let getUntransformedTop = typeof ChromeUtils != "undefined" ? element => element.getBoxQuads({ ignoreTransforms: true, flush: false })[0].p1.y : element => element.getBoundingClientRect().top; let px = number => number.toFixed(2) + "px"; const XHTML_NS = "http://www.w3.org/1999/xhtml"; /** * Parses an input's markup into a fragment. The markup is XML in the XHTML * namespace. * * @param {string} markup * The markup to parse. * @returns {DocumentFragment} */ function parseMarkupToFragment(markup) { let parser = new DOMParser(); // A template's contents stay inert until they are imported into a document. let doc = parser.parseFromString( ``, "application/xml" ); if (doc.documentElement.localName == "parsererror") { throw new Error("not well-formed XML"); } let fragment = doc.documentElement.content; // The markup is indented, and keeping the whitespace between elements as text // nodes changes the accessibility tree the input exposes. let walker = doc.createTreeWalker(fragment, NodeFilter.SHOW_TEXT); let blank = []; while (walker.nextNode()) { if (!walker.currentNode.data.trim()) { blank.push(walker.currentNode); } } blank.forEach(node => node.remove()); return fragment; } /** * Implements the text input part of the address bar UI. */ export class UrlbarInputBase extends HTMLElement { static get #markup() { return `