diff --git a/apps/extensions/lib/parent/ext-browser.js b/apps/extensions/lib/parent/ext-browser.js index 85754dc..227c7f0 100644 --- a/apps/extensions/lib/parent/ext-browser.js +++ b/apps/extensions/lib/parent/ext-browser.js @@ -21,7 +21,7 @@ const lazy = lazyESModuleGetters({ class TabTracker extends TabTrackerBase { get activeTab() { const window = lazy.WindowTracker.getActiveWindow() - return window?.activeTab() + return window?.activeTab() || null } init() { @@ -50,28 +50,6 @@ class TabTracker extends TabTrackerBase { return tab } - /** - * @param {import('resource://gre/modules/Extension.sys.mjs').Extension} extension - * @param {import('@browser/tabs').WindowTab} tab - * @param {Window} window - * - * @returns {tabs__tabs.Tab} - */ - serializeTab(extension, tab, window) { - // TODO: Active tab & host permissions - const hasTabPermission = extension.hasPermission('tabs') - - return { - id: tab.view.browserId, - index: window.windowTabs().findIndex((wTab) => wTab === tab), - active: window.activeTab() === tab, - highlighted: false, // TODO - title: (hasTabPermission && tab.view.title) || undefined, - url: (hasTabPermission && tab.view.uri.asciiSpec) || undefined, - windowId: window.windowId, - } - } - /** * @param {XULBrowserElement} browser */ @@ -89,3 +67,119 @@ class TabTracker extends TabTrackerBase { /** @global */ let tabTracker = new TabTracker() Object.assign(global, { tabTracker }) + +class Tab extends TabBase { + get _favIconUrl() { + return this.nativeTab.view.iconUrl + } + + get lastAccessed() { + return undefined + } + get audible() { + return undefined + } + get autoDiscardable() { + return false + } + get browser() { + return this.nativeTab.view.browser + } + get cookieStoreId() { + return undefined + } + get discarded() { + return undefined + } + get height() { + return this.nativeTab.view.browser.clientHeight + } + get hidden() { + return false + } + get index() { + const window = this.window + return ( + window + ?.windowTabs() + .findIndex( + (tab) => tab.view.browserId == this.nativeTab.view.browserId, + ) || -1 + ) + } + get mutedInfo() { + return undefined + } + get sharingState() { + return undefined + } + get pinned() { + return false + } + get active() { + const window = this.window + return window?.activeTabId() == this.nativeTab.view.windowBrowserId + } + get highlighted() { + const window = this.window + return ( + window + ?.selectedTabIds() + .some((tab) => tab == this.nativeTab.view.windowBrowserId) ?? false + ) + } + get status() { + return this.nativeTab.view.websiteState + } + get width() { + return this.browser.clientWidth + } + get window() { + return lazy.WindowTracker.getWindowWithBrowser(this.nativeTab.view.browser) + ?.window + } + get windowId() { + return this.window?.windowId || -1 + } + get attention() { + return false + } + get isArticle() { + return false + } + get isInReaderMode() { + return false + } + get successorTabId() { + return undefined + } +} + +class TabManager extends TabManagerBase { + canAccessTab(_nativeTab) { + throw new Error('Method ') + } + get(tabId) { + const results = lazy.WindowTracker.getWindowWithBrowserId(tabId) + if (!results) return null + return this.wrapTab(results.tab) + } + /** + * @param {NativeTab} nativeTab + */ + wrapTab(nativeTab) { + return new Tab(this.extension, nativeTab, nativeTab.view.browserId || -1) + } + + /** + * @param {NativeTab} nativeTab + * @public + */ + publicWrapTab(nativeTab) { + return this.wrapTab(nativeTab) + } +} + +extensions.on('startup', (type, extension) => { + defineLazyGetter(extension, 'tabManager', () => new TabManager(extension)) +}) diff --git a/apps/extensions/lib/parent/ext-browserAction.js b/apps/extensions/lib/parent/ext-browserAction.js index e675983..7ce10e5 100644 --- a/apps/extensions/lib/parent/ext-browserAction.js +++ b/apps/extensions/lib/parent/ext-browserAction.js @@ -13,7 +13,6 @@ this.browserAction = class extends ExtensionAPIPersistent { async onManifestEntry() { const { extension } = this - /** @type {browser_action__manifest.WebExtensionManifest__extended['browser_action']} */ const options = extension.manifest.browser_action if (!options) { @@ -67,25 +66,16 @@ this.browserAction = class extends ExtensionAPIPersistent { * running extension context. */ onClicked({ fire }) { - const { extension } = this + const /** @type {Extension} */ extension = this.extension /** * @param {import("resource://app/modules/EBrowserActions.sys.mjs").IBrowserActionEvents['click']} clickInfo */ const callback = async (_name, clickInfo) => { if (fire.wakeup) await fire.wakeup() - const { tab, window } = lazy.WindowTracker.getWindowWithBrowserId( - clickInfo.tabId, - ) || { tab: null, window: null } - if (!tab || !window) { - return fire.sync(null, clickInfo.clickData) - } - - fire.sync( - tabTracker.serializeTab(extension, tab, window), - clickInfo.clickData, - ) + const tab = extension.tabManager.get(clickInfo.tabId) + fire.sync(tab.convert(), clickInfo.clickData) } this.on('click', callback) diff --git a/apps/extensions/lib/parent/ext-tabs.js b/apps/extensions/lib/parent/ext-tabs.js index ab00470..2bf80c1 100644 --- a/apps/extensions/lib/parent/ext-tabs.js +++ b/apps/extensions/lib/parent/ext-tabs.js @@ -7,66 +7,11 @@ /// /// -/** - * @param {tabs__tabs.QueryInfo} queryInfo - * @returns {[import("@browser/tabs").WindowTab, Window][]} - */ -function query(queryInfo) { - const windows = [...lazy.WindowTracker.registeredWindows.entries()] - - const urlMatchSet = - (queryInfo.url && - (Array.isArray(queryInfo.url) - ? new MatchPatternSet(queryInfo.url) - : new MatchPatternSet([queryInfo.url]))) || - null - - return windows.flatMap(([windowId, window]) => { - const tabs = window.windowTabs() - const activeTab = window.activeTab() - - return tabs - .filter((tab) => { - const active = - queryInfo.active !== null - ? queryInfo.active - ? tab === activeTab - : tab !== activeTab - : true - const title = queryInfo.title - ? queryInfo.title === tab.view.title - : true - const url = - urlMatchSet === null - ? true - : urlMatchSet.matches(tab.view.uri.asciiSpec) - const window = - queryInfo.windowId === null ? true : queryInfo.windowId === windowId - - return active && title && url && window - }) - .map( - /** @returns {[import("@browser/tabs").WindowTab, Window]} */ (tab) => [ - tab, - window, - ], - ) - }) -} - -const serialize = - (extension) => - /** - * @param {[import("@browser/tabs").WindowTab, Window]} in - * @returns {tabs__tabs.Tab} - */ - ([tab, window]) => - tabTracker.serializeTab(extension, tab, window) - this.tabs = class extends ExtensionAPIPersistent { PERSISTENT_EVENTS = {} /** + * @param {BaseContext} context * @returns {tabs__tabs.ApiGetterReturn} */ getAPI(context) { @@ -76,140 +21,90 @@ this.tabs = class extends ExtensionAPIPersistent { * @param {number} tabId */ async function get(tabId) { - const window = [...lazy.WindowTracker.registeredWindows.values()].find( - (window) => - window.windowTabs().some((tab) => tab.view.browserId === tabId), - ) + const tab = extension.tabManager.get(tabId) - if (!window) { + if (!tab) { return Promise.reject({ message: `Cannot find tab matching the id ${tabId}`, }) } - const tab = window - .windowTabs() - .find((tab) => tab.view.browserId === tabId) + return tab + } - if (!tab) { - return Promise.reject({ - message: `Cannot find tab matching the id ${tabId}`, - }) + /** + * @param {number} [tabId] + */ + async function getTabOrActive(tabId) { + /** @type {TabBase} */ + let tab + + if (tabId) { + tab = extension.tabManager.get(tabId) + } else { + const nativeTab = lazy.WindowTracker.getActiveWindow()?.activeTab() + if (!nativeTab) { + return Promise.reject({ + message: 'Could not find active tab', + }) + } + tab = extension.tabManager.publicWrapTab(nativeTab) } - return { tab, window } + return tab } return { tabs: { async get(tabId) { - const { tab, window } = await get(tabId) - return serialize(extension)([tab, window]) + const tab = await get(tabId) + return tab.convert() }, async goBack(tabId) { - let tab - - if (tabId) { - tab = await get(tabId).then((all) => all.tab) - } else { - tab = lazy.WindowTracker.getActiveWindow()?.activeTab() - if (!tab) { - return - } - } - const complete = new Promise((res) => { - /** @param {boolean} isLoading */ - function complete(isLoading) { - if (isLoading) { - return - } - tab.view.events.off('loadingChange', complete) - res(undefined) - } - - tab.view.events.on('loadingChange', complete) - }) - tab.view.browser.goBack() - return complete + const tab = await getTabOrActive(tabId) + tab.browser.goBack() }, async goForward(tabId) { - let tab - - if (tabId) { - tab = await get(tabId).then((all) => all.tab) - } else { - tab = lazy.WindowTracker.getActiveWindow()?.activeTab() - if (!tab) { - return - } - } - - const complete = new Promise((res) => { - /** @param {boolean} isLoading */ - function complete(isLoading) { - if (isLoading) { - return - } - tab.view.events.off('loadingChange', complete) - res(undefined) - } - - tab.view.events.on('loadingChange', complete) - }) - tab.view.browser.goForward() - return complete + const tab = await getTabOrActive(tabId) + tab.browser.goForward() }, async query(queryInfo) { - return query(queryInfo).map(serialize(extension)) + return Array.from(extension.tabManager.query(queryInfo, context)).map( + (tab) => tab.convert(), + ) }, - async remove(tabIds) { - const windows = [...lazy.WindowTracker.registeredWindows.entries()] - - if (typeof tabIds === 'number') { - for (const window of windows.map((w) => w[1])) { - const tabs = window.windowTabs() - for (const tab of tabs) { - if (tab.view.browserId === tabIds) { - return window.windowTabs.update((tabs) => - tabs.filter((tab) => tab.view.browserId !== tabIds), - ) - } - } - } + async remove(tabSelector) { + const tabIds = + typeof tabSelector == 'number' ? [tabSelector] : tabSelector - return - } + const windows = [...lazy.WindowTracker.registeredWindows.entries()] for (const window of windows.map((w) => w[1])) { const tabs = window.windowTabs() - for (const tab of tabs) { - if (tabIds.includes(tab.view.browserId || -1)) { - window.windowTabs.update((tabs) => - tabs.filter( - (tab) => !tabIds.includes(tab.view.browserId || -1), - ), - ) - break - } + + if (tabs.some((tab) => tabIds.includes(tab.view.browserId || -1))) { + window.windowTabs.update((tabs) => + tabs.filter( + (tab) => !tabIds.includes(tab.view.browserId || -1), + ), + ) } } }, - async reload(tabIds) { - if (typeof tabIds === 'number') { - const { tab } = await get(tabIds) - tab.view.browser.reload() - return - } + async reload(tabSelector) { + const tabIds = + typeof tabSelector == 'number' ? [tabSelector] : tabSelector - for (const id of tabIds) { - const { tab } = await get(id) - tab.view.browser.reload() - } + await Promise.all( + tabIds + .map((id) => get(id)) + .map((tab) => tab.then((tab) => tab.browser.reload())), + ) }, async update(tabId, updateProperties) { @@ -223,6 +118,7 @@ this.tabs = class extends ExtensionAPIPersistent { } let errors = null + /** @type {import("@browser/tabs").WindowTab | undefined} */ let retTab window.windowTabs.update((tabs) => @@ -267,7 +163,8 @@ this.tabs = class extends ExtensionAPIPersistent { } if (retTab) { - return serialize(extension)([retTab, window]) + const tab = extension.tabManager.getWrapper(retTab) + return tab?.convert() } return diff --git a/apps/extensions/lib/types/utils.d.ts b/apps/extensions/lib/types/utils.d.ts index 42ffd57..97b7b17 100644 --- a/apps/extensions/lib/types/utils.d.ts +++ b/apps/extensions/lib/types/utils.d.ts @@ -4,16 +4,22 @@ /* eslint-disable @typescript-eslint/ban-types */ /// -import { Module } from 'module' - import { ConduitAddress } from 'resource://gre/modules/ConduitsParent.sys.mjs' -import { Extension } from 'resource://gre/modules/Extension.sys.mjs' +import { Extension as ToolkitExtension } from 'resource://gre/modules/Extension.sys.mjs' import { SchemaRoot } from 'resource://gre/modules/Schemas.sys.mjs' import { PointConduit } from './ConduitChild' declare global { type SavedFrame = unknown + type NativeTab = import('@browser/tabs').WindowTab + type XULElement = Element + + interface Extension extends ToolkitExtension { + tabManager: TabManagerBase & { publicWrapTab(nativeTab: NativeTab): Tab } + manifest: Omit & + browser_action__manifest.WebExtensionManifest__extended + } /* eslint-disable @typescript-eslint/no-explicit-any */ function getConsole(): any @@ -168,7 +174,7 @@ declare global { extension: Extension destroy(): void onManifestEntry(entry: any): void - getAPI(context: any): void + getAPI(context: BaseContext): unknown } /** * Subclass to add APIs commonly used with persistent events. @@ -244,7 +250,7 @@ declare global { _lastError: any contextId: any unloaded: boolean - extension: any + extension: Extension manifestVersion: any jsonSandbox: any active: boolean @@ -897,9 +903,6 @@ declare global { windowId: number } - type NativeTab = any - type XULElement = any - /** * A platform-independent base class for the platform-specific TabTracker * classes, which track the opening and closing of tabs, and manage the mapping @@ -950,4 +953,614 @@ declare global { */ abstract get activeTab(): NativeTab | null } + + /** + * A platform-independent base class for the platform-specific WindowTracker + * classes, which track the opening and closing of windows, and manage the + * mapping of them between numeric IDs and native tab objects. + */ + class WindowTrackerBase extends EventEmitter { + constructor() + isBrowserWindow(window: Window): boolean + + /** + * Returns an iterator for all currently active browser windows. + * + * @param includeIncomplete If true, include browser windows which are not yet fully loaded. + * Otherwise, only include windows which are. + * + * @returns An iterator for all currently active browser windows. + */ + browserWindows(includeIncomplete?: boolean): IterableIterator + + /** + * The currently active, or topmost, browser window, or null if no + * browser window is currently open. + * @readonly + */ + get topWindow(): Window | null + + /** + * The currently active, or topmost, browser window that is not + * private browsing, or null if no browser window is currently open. + * @readonly + */ + get topNonPBWindow(): Window | null + + /** + * Returns the top window accessible by the extension. + * + * @param context The extension context for which to return the current window. + * + * @returns The top window accessible by the extension. + */ + getTopWindow(context: BaseContext): Window | null + + /** + * Returns the numeric ID for the given browser window. + * + * @param window The DOM window for which to return an ID. + * + * @returns The window's numeric ID. + */ + getId(window: Window): number + + /** + * Returns the browser window to which the given context belongs, or the top + * browser window if the context does not belong to a browser window. + * + * @param context The extension context for which to return the current window. + * + * @returns The browser window to which the given context belongs, or the top browser window. + */ + getCurrentWindow(context: BaseContext): Window | null + + /** + * Returns the browser window with the given ID. + * + * @param id The ID of the window to return. + * @param context The extension context for which the matching is being performed. + * @param strict If false, undefined will be returned instead of throwing an error in case no window exists with the given ID. + * + * @returns The browser window with the given ID. + * @throws ExtensionError If no window exists with the given ID and `strict` is true. + */ + getWindow( + id: number, + context: BaseContext, + strict?: boolean, + ): Window | undefined + + /** + * Returns true if any window open or close listeners are currently registered. + * @private + */ + get _haveListeners(): boolean + + /** + * Register the given listener function to be called whenever a new browser window is opened. + * + * @param listener The listener function to register. + */ + addOpenListener(listener: (window: Window) => void): void + /** + * Unregister a listener function registered in a previous addOpenListener call. + * + * @param listener The listener function to unregister. + */ + removeOpenListener(listener: (window: Window) => void): void + + /** + * Register the given listener function to be called whenever a browser window is closed. + * + * @param listener The listener function to register. + */ + addCloseListener(listener: (window: Window) => void): void + + /** + * Unregister a listener function registered in a previous addCloseListener call. + * + * @param listener The listener function to unregister. + */ + removeCloseListener(listener: (window: Window) => void): void + + /** + * Handles load events for recently-opened windows, and adds additional listeners which may only be safely added when the window is fully loaded. + * + * @param event A DOM event to handle. + * @private + */ + handleEvent(event: Event): void + + /** + * Observes "domwindowopened" and "domwindowclosed" events, notifies the appropriate listeners, and adds necessary additional listeners to the new windows. + * + * @param window A DOM window. + * @param topic The topic being observed. + * @private + */ + observe(window: Window, topic: string): void + + /** + * Add an event listener to be called whenever the given DOM event is received at the top level of any browser window. + * + * @param type The type of event to listen for. + * @param listener The listener to invoke in response to the given events. + */ + addListener(type: string, listener: Function | object): void + + /** + * Removes an event listener previously registered via an addListener call. + * + * @param type The type of event to stop listening for. + * @param listener The listener to remove. + */ + removeListener(type: string, listener: Function | object): void + + /** + * Adds a listener for the given event to the given window. + * + * @param window The browser window to which to add the listener. + * @param eventType The type of DOM event to listen for, or "progress" to add a tab progress listener. + * @param listener The listener to add. + * @private + */ + _addWindowListener( + window: Window, + eventType: string, + listener: Function | object, + ): void + + /** + * A private method which is called whenever a new browser window is opened, and adds the necessary listeners to it. + * + * @param window The window being opened. + * @private + */ + _handleWindowOpened(window: Window): void + + /** + * Adds a tab progress listener to the given browser window. + * + * @param _window The browser window to which to add the listener. + * @param _listener The tab progress listener to add. + * @abstract + */ + addProgressListener(_window: Window, _listener: object): void + + /** + * Removes a tab progress listener from the given browser window. + * + * @param _window The browser window from which to remove the listener. + * @param _listener The tab progress listener to remove. + * @abstract + */ + removeProgressListener(_window: Window, _listener: object): void + } + + /** + * Manages native tabs, their wrappers, and their dynamic permissions for a + * particular extension. + */ + abstract class TabManagerBase { + protected extension: Extension + + constructor(extension: Extension) + + /** + * If the extension has requested activeTab permission, grant it those permissions for the current inner window in the given native tab. + * + * @param nativeTab The native tab for which to grant permissions. + */ + addActiveTabPermission(nativeTab: NativeTab): void + + /** + * Revoke the extension's activeTab permissions for the current inner window of the given native tab. + * + * @param nativeTab The native tab for which to revoke permissions. + */ + revokeActiveTabPermission(nativeTab: NativeTab): void + + /** + * Returns true if the extension has requested activeTab permission, and has been granted permissions for the current inner window if this tab. + * + * @param nativeTab The native tab for which to check permissions. + * @returns True if the extension has activeTab permissions for this tab. + */ + hasActiveTabPermission(nativeTab: NativeTab): boolean + + /** + * Activate MV3 content scripts if the extension has activeTab or an (ungranted) host permission. + * + * @param nativeTab The native tab. + */ + activateScripts(nativeTab: NativeTab): void + + /** + * Returns true if the extension has permissions to access restricted properties of the given native tab. + * + * @param nativeTab The native tab for which to check permissions. + * @returns True if the extension has permissions for this tab. + */ + hasTabPermission(nativeTab: NativeTab): boolean + + /** + * Returns this extension's TabBase wrapper for the given native tab. + * + * @param nativeTab The tab for which to return a wrapper. + * @returns The wrapper for this tab. + */ + getWrapper(nativeTab: NativeTab): TabBase | undefined + + /** + * Determines access using extension context. + * + * @param _nativeTab The tab to check access on. + * @returns True if the extension has permissions for this tab. + */ + protected abstract canAccessTab(_nativeTab: NativeTab): boolean + + /** + * Converts the given native tab to a JSON-compatible object. + * + * @param nativeTab The native tab to convert. + * @param fallbackTabSize A geometry data if the lazy geometry data for this tab hasn't been initialized yet. + * @returns object + */ + convert(nativeTab: NativeTab, fallbackTabSize?: object): object + + /** + * Returns an iterator of TabBase objects which match the given query info. + * + * @param queryInfo An object containing properties on which to filter. + * @param context The extension context for which the matching is being performed. + */ + query( + queryInfo?: object | null, + context?: BaseContext | null, + ): Iterable + + /** + * Returns a TabBase wrapper for the tab with the given ID. + * + * @param _tabId The ID of the tab for which to return a wrapper. + * @returns TabBase + * @throws ExtensionError If no tab exists with the given ID. + */ + abstract get(_tabId: number): TabBase + + /** + * Returns a new TabBase instance wrapping the given native tab. + * + * @param _nativeTab The native tab for which to return a wrapper. + * @returns TabBase + */ + protected abstract wrapTab(_nativeTab: NativeTab): TabBase + } + + interface QueryInfo { + active?: boolean + audible?: boolean + autoDiscardable?: boolean + cookieStoreId?: string + discarded?: boolean + hidden?: boolean + highlighted?: boolean + index?: number + muted?: boolean + pinned?: boolean + status?: string + title?: string + screen?: string | boolean + camera?: boolean + microphone?: boolean + url?: MatchPattern + } + + interface Options { + frameIds?: number[] + returnResultsWithFrameIds?: boolean + } + + /** + * A platform-independent base class for extension-specific wrappers around + * native tab objects. + */ + abstract class TabBase { + protected nativeTab: NativeTab + + constructor(extension: Extension, nativeTab: NativeTab, id: number) + + /** + * Capture the visible area of this tab, and return the result as a data: URI. + * + * @param context The extension context for which to perform the capture. + * @param zoom The current zoom for the page. + * @param options The options with which to perform the capture. + * @returns Promise + */ + capture( + context: BaseContext, + zoom: number, + options?: { + format?: string + quality?: number + rect?: DOMRectInit + scale?: number + }, + ): Promise + + /** + * @property innerWindowID + * @readonly + */ + readonly innerWindowID: number | null + + /** + * @property hasTabPermission + * @readonly + */ + readonly hasTabPermission: boolean + + /** + * @property hasActiveTabPermission + * @readonly + */ + readonly hasActiveTabPermission: boolean + + /** + * @property matchesHostPermission + * @readonly + */ + readonly matchesHostPermission: boolean + + /** + * @property incognito + * @readonly + */ + readonly _incognito: boolean + + /** + * @property _url + * @readonly + */ + readonly _url: string + + /** + * @property url + * @readonly + */ + readonly url: string | undefined + + /** + * @property _uri + * @readonly + */ + readonly _uri: nsIURIType + + /** + * @property _title + * @readonly + */ + readonly _title: string + + /** + * @property title + * @readonly + */ + readonly title: nsIURIType | undefined + + /** + * @property _favIconUrl + * @readonly + * @abstract + */ + abstract readonly _favIconUrl: string | undefined + + /** + * @property faviconUrl + * @readonly + */ + readonly favIconUrl: nsIURIType | undefined + + /** + * @property lastAccessed + * @readonly + * @abstract + */ + abstract readonly lastAccessed: number | undefined + + /** + * @property audible + * @readonly + * @abstract + */ + abstract readonly audible: boolean | undefined + + /** + * @property autoDiscardable + * @readonly + * @abstract + */ + abstract readonly autoDiscardable: boolean + + /** + * @property browser + * @readonly + * @abstract + */ + abstract readonly browser: XULBrowserElement + + /** + * @property browsingContext + * @readonly + */ + readonly browsingContext: BrowsingContext + + /** + * @property frameLoader + * @readonly + */ + readonly frameLoader: FrameLoader + + /** + * @property cookieStoreId + * @readonly + * @abstract + */ + abstract readonly cookieStoreId: string | undefined + + /** + * @property openerTabId + * @readonly + */ + readonly openerTabId: number + + /** + * @property discarded + * @readonly + * @abstract + */ + abstract readonly discarded: number | undefined + + /** + * @property height + * @readonly + * @abstract + */ + abstract readonly height: number + + /** + * @property hidden + * @readonly + * @abstract + */ + abstract readonly hidden: boolean + + /** + * @property index + * @readonly + * @abstract + */ + abstract readonly index: number + + /** + * @property mutedInfo + * @readonly + * @abstract + */ + abstract readonly mutedInfo: MutedInfo + + /** + * @property sharingState + * @readonly + * @abstract + */ + abstract readonly sharingState: SharingState + + /** + * @property pinned + * @readonly + * @abstract + */ + abstract readonly pinned: boolean + + /** + * @property active + * @readonly + * @abstract + */ + abstract readonly active: boolean + + /** + * @property highlighted + * @readonly + * @abstract + */ + abstract readonly highlighted: boolean + + /** + * @property status + * @readonly + * @abstract + */ + abstract readonly status: string + + /** + * @property width + * @readonly + * @abstract + */ + abstract readonly width: number + + /** + * @property window + * @readonly + * @abstract + */ + abstract readonly window: DOMWindow + + /** + * @property windowId + * @readonly + * @abstract + */ + abstract readonly windowId: number + + /** + * @property attention + * @readonly + * @abstract + */ + abstract readonly attention: boolean + + /** + * @property isArticle + * @readonly + * @abstract + */ + abstract readonly isArticle: boolean + + /** + * @property isInReaderMode + * @readonly + * @abstract + */ + abstract readonly isInReaderMode: boolean + + /** + * @property successorTabId + * @readonly + * @abstract + */ + abstract readonly successorTabId: number | undefined + + matches(queryInfo: QueryInfo): boolean + + /** + * Converts this tab object to a JSON-compatible object containing the values + * of its properties which the extension is permitted to access, in the format + * required to be returned by WebExtension APIs. + * + * @param [fallbackTabSize] + * A geometry data if the lazy geometry data for this tab hasn't been + * initialized yet. + */ + convert(fallbackTabSize?: any): any + + queryContent(message: string, options: Options): Promise[] + + private _execute( + context: BaseContext, + details: InjectDetails, + kind: string, + method: string, + ): Promise + + executeScript(context: BaseContext, details: InjectDetails): Promise + + insertCSS(context: BaseContext, details: InjectDetails): Promise + + removeCSS(context: BaseContext, details: InjectDetails): Promise + } } diff --git a/libs/link/types/schemaTypes/index.d.ts b/libs/link/types/schemaTypes/index.d.ts index 24201db..6dfd373 100644 --- a/libs/link/types/schemaTypes/index.d.ts +++ b/libs/link/types/schemaTypes/index.d.ts @@ -1,3 +1,3 @@ -// @not-mpl +// @not-mpl /// -/// +/// \ No newline at end of file