{"version":3,"sources":["jsdelivr-header.js","/npm/electron-extended-webextensions@0.0.11/index.js"],"names":[],"mappings":"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","file":"/npm/electron-extended-webextensions@0.0.11/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/electron-extended-webextensions@0.0.11/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","const EventEmtiter = require('events')\nconst { join } = require('path')\n\nconst {\n  ipcMain,\n  MenuItem,\n  app,\n  webContents: WebContents\n} = require('electron')\n\nconst PRELOAD_PATH = join(__dirname, 'preloads.js')\n\nconst {\n  spec,\n  FUNCTION,\n  EVENT,\n  makeEvent\n} = require('./apiSpecs')\n\nconst TAB_QUERY_PROPERTIES = ['url', 'active', 'status', 'title']\n\nconst FORBIDDEN_PROTOCOLS = ['chrome-extension:', 'devtools:']\n\nclass WebNavigation extends EventEmtiter {\n  constructor ({ tabs }) {\n    super()\n    this.tabs = tabs\n\n    // Listen to new tabs\n    this.tabs.on('created', (webContents) => this.listenTab(webContents))\n    // Listen to existing tabs\n    for (const webContents of this.tabs) {\n      this.listenTab(webContents)\n    }\n  }\n\n  listenTab (webContents) {\n    // Listen for destroy to stop listening\n    webContents.on('will-navigate', (event, url) => {\n      const details = { url }\n      this.dispatchOnBeforeNavigate(webContents, event, details)\n    })\n    webContents.on('did-start-navigation', (event, url, isInPlace, isMainFrame, frameProcessId, frameRoutingId) => {\n      const details = { url, isInPlace, isMainFrame, frameProcessId, frameRoutingId }\n      this.dispatchOnCommitted(webContents, event, details)\n    })\n    webContents.on('did-frame-finish-load', (event, isMainFrame, frameProcessId, frameRoutingId) => {\n      // Same as dom load\n      // Is it the same as onCompleted? Can't find a better event for it\n      const details = { isMainFrame, frameProcessId, frameRoutingId }\n      this.dispatchOnDOMContentLoaded(webContents, event, details)\n      this.dispatchOnCompleted(webContents, event, details)\n    })\n    webContents.on('did-fail-load', (event, code, description, url, isMainFrame, frameProcessId, frameRoutingId) => {\n      const details = { url, isMainFrame, frameProcessId, frameRoutingId }\n      const error = { code, description }\n      this.dispatchOnErrorOccured(webContents, event, details, error)\n    })\n  }\n\n  mainFrameToFrameData (frame) {\n    const frameId = frame.routingId\n    const parentFrameId = frame.parent ? frame.parent.routingId : -1\n    const url = frame.url\n\n    return {\n      frameId,\n      parentFrameId,\n      url\n    }\n  }\n\n  /* Invoked by extension APIs */\n\n  async getAllFrames ({ extensionId } = {}, { tabId } = {}) {\n    const webContents = await this.tabs.getRaw(tabId)\n    // TODO: Check for permissions?\n    const allFrames = webContents.mainFrame.framesInSubtree\n\n    return allFrames.map((frame) => this.mainFrameToFrameData(frame))\n  }\n\n  async getFrame (invoker, { tabId, frameId } = {}) {\n    const webContents = await this.tabs.getRaw(tabId)\n\n    if (frameId) {\n      const frame = webContents.mainFrame.framesInSubtree\n        .find(({ routingId }) => routingId === frameId)\n      if (!frame) throw new Error('Frame ID not found')\n      return this.mainFrameToFrameData(frame)\n    } else {\n      return this.mainFrameToFrameData(webContents.mainFrame)\n    }\n  }\n\n  async onBeforeNavigate ({ extensionId } = {}, handler, filter = {}) {\n    // TODO: Filter by URLs\n    this.on('onBeforeNavigate', handler)\n    return () => this.removeListener('onBeforeNavigate', handler)\n  }\n\n  async onCommitted ({ extensionId } = {}, handler, filter = {}) {\n    // TODO: Filter by URLs\n    this.on('onCommitted', handler)\n    return () => this.removeListener('onCommitted', handler)\n  }\n\n  async onDOMContentLoaded ({ extensionId } = {}, handler, filter = {}) {\n    // TODO: Filter by URLs\n    this.on('onDOMContentLoaded', handler)\n    return () => this.removeListener('onDOMContentLoaded', handler)\n  }\n\n  async onCompleted ({ extensionId } = {}, handler, filter = {}) {\n    // TODO: Filter by URLs\n    this.on('onCompleted', handler)\n    return () => this.removeListener('onCompleted', handler)\n  }\n\n  async onErrorOccured ({ extensionId } = {}, handler, filter = {}) {\n    // TODO: Filter by URLs\n    this.on('onErrorOccured', handler)\n    return () => this.removeListener('onErrorOccured', handler)\n  }\n\n  async onCreatedNavigationTarget ({ extensionId } = {}, handler, filter = {}) {\n    // TODO: Filter by URLs\n    this.on('onCreatedNavigationTarget', handler)\n    return () => this.removeListener('onCreatedNavigationTarget', handler)\n  }\n\n  async dispatchOnBeforeNavigate (webContents, event, { url }) {\n    try {\n      const frame = this.mainFrameToFrameData(webContents.mainFrame)\n      const tabId = webContents.id\n      const timeStamp = Date.now()\n      const details = { ...frame, url, tabId, timeStamp }\n      this.emit('onBeforeNavigate', details)\n    } catch {\n      // it was not fate\n    }\n  }\n\n  async dispatchOnCommitted (webContents, event, { url, frameRoutingId: frameId }) {\n    try {\n      const tabId = webContents.id\n      const frame = await this.getFrame(null, { tabId, frameId })\n      const timeStamp = Date.now()\n      const details = { ...frame, url, tabId, timeStamp }\n      this.emit('onCommitted', details)\n    } catch {\n      // it was not fate\n    }\n  }\n\n  async dispatchOnDOMContentLoaded (webContents, event, { frameRoutingId: frameId }) {\n    try {\n      const tabId = webContents.id\n      const frame = await this.getFrame(null, { tabId, frameId })\n      const timeStamp = Date.now()\n      const details = { ...frame, tabId, timeStamp }\n      this.emit('onDOMContentLoaded', details)\n    } catch {\n      // it was not fate\n    }\n  }\n\n  async dispatchOnCompleted (webContents, event, { frameRoutingId: frameId }) {\n    try {\n      const tabId = webContents.id\n      const frame = await this.getFrame(null, { tabId, frameId })\n      const timeStamp = Date.now()\n      const details = { ...frame, tabId, timeStamp }\n      this.emit('onCompleted', details)\n    } catch {\n      // it was not fate\n    }\n  }\n\n  async dispatchOnErrorOccured (webContents, event, { url, frameRoutingId: frameId }, { code, description }) {\n    try {\n      const tabId = webContents.id\n      const frame = await this.getFrame(null, { tabId, frameId })\n      const timeStamp = Date.now()\n      const error = `${code}: ${description}`\n      const details = { ...frame, url, tabId, timeStamp, error }\n      this.emit('onErrorOccured', details)\n    } catch {\n      // it was not fate\n    }\n  }\n\n  async dispatchOnCreatedNavigationTarget (webContents) {\n    try {\n      const parent = webContents.hostWebContents\n      const tabId = webContents.id\n      const timeStamp = Date.now()\n      const url = webContents.getURL()\n      let sourceFrameId = webContents.mainFrame.routingId\n      let sourceTabId = webContents.id\n\n      if (parent && webContents.id !== parent.id) {\n        sourceFrameId = parent.mainFrame.routingId\n        sourceTabId = parent.id\n      }\n\n      const details = {\n        sourceFrameId,\n        sourceTabId,\n        tabId,\n        timeStamp,\n        url\n      }\n\n      this.emit('onCreatedNavigationTarget', details)\n    } catch {\n      // it was not fate\n    }\n  }\n}\n\nclass ContextMenus extends EventEmtiter {\n  constructor ({ tabs }) {\n    super()\n    this.tabs = tabs\n    /*\n      Map extension IDs to Maps of context menu item IDs to context Menu Items\n      [extensionId]: {\n        [menuItemId] {\n          extensionId,\n          id,\n          title,\n          type: \"normal\" | \"separator\",\n          visible: true,\n          enabled: true,\n          contexts: [\"all\", \"page\", \"frame\", \"selection\", \"link\", \"editable\", \"image\", \"video\", \"audio\", \"browser_action\"]\n        }\n      }\n\n    */\n    this.items = new Map()\n  }\n\n  /* Invoked by application */\n\n  getForEvent (webContents, event, params, { isBrowserAction = false, isLauncher = false } = {}) {\n    const {\n      linkURL,\n      srcURL,\n      pageURL,\n      frame,\n      frameURL,\n      mediaType,\n      isEditable,\n      selectionText,\n      inputFieldType\n    } = params\n\n    let context = 'page'\n\n    if (isLauncher) context = 'launcher'\n    else if (isBrowserAction) context = 'browser_action'\n    else if (inputFieldType === 'password') context = 'password'\n    else if (mediaType === 'image' || mediaType === 'canvas') context = 'image'\n    else if (mediaType === 'video') context = 'video'\n    else if (mediaType === 'audio') context = 'audio'\n    else if (selectionText) context = 'selection'\n    else if (isEditable) context = 'editable'\n    else if (linkURL) context = 'link'\n\n    const items = this.getForContext(context)\n\n    const onClickData = {\n      editable: isEditable,\n      frameId: frame.routingId,\n      frameURL,\n      linkURL,\n      pageURL,\n      srcURL,\n      selectionText,\n      mediaType\n    }\n    // Also add the `menuItemId` per item\n\n    // TODO: Filter based on targetURLPatterns\n    return items.map(({ extensionId, id, title, type, enabled }) => {\n      return new MenuItem({\n        label: title,\n        type,\n        enabled,\n        click: () => this.click(extensionId, id, onClickData, webContents)\n      })\n    })\n  }\n\n  click (extensionId, menuItemId, onClickData = {}, webContents) {\n    this.dispatchOnClicked({ extensionId }, { ...onClickData, menuItemId }, webContents)\n  }\n\n  getForContext (context) {\n    return [...this].filter(({ visible, contexts }) => {\n      // TODO: Handle Document URL Patterns\n      if (visible === false) return false\n      if (contexts.includes('all')) return true\n      return contexts.includes(context)\n    })\n  }\n\n  * [Symbol.iterator] () {\n    const extensionMaps = this.items.values()\n    for (const items of extensionMaps) {\n      yield * items.values()\n    }\n  }\n\n  /* Invoked by extension APIs */\n  async create ({ extensionId } = {}, createProperties = {}) {\n    const {\n      id,\n      type = 'normal',\n      title = id,\n      contexts = ['page'],\n      enabled = true,\n      visible = true\n    } = createProperties\n\n    const menuItem = {\n      extensionId,\n      id,\n      type,\n      title,\n      contexts,\n      enabled,\n      visible\n    }\n\n    if (!this.items.has(extensionId)) {\n      this.items.set(extensionId, new Map())\n    }\n\n    this.items.get(extensionId).set(id, menuItem)\n\n    return id\n  }\n\n  async remove ({ extensionId } = {}, menuItemId) {\n    if (!this.items.has(extensionId)) return\n    this.items.get(extensionId).delete(menuItemId)\n  }\n\n  async removeAll ({ extensionId } = {}) {\n    this.items.delete(extensionId)\n  }\n\n  async update ({ extensionId } = {}, menuItemId, updateProperties) {\n    const {\n      type,\n      title,\n      contexts,\n      visible,\n      enabled\n    } = updateProperties\n\n    if (!this.items.has(extensionId)) {\n      console.warn('Tried to update non-existing extension menu item')\n      return\n    }\n    const extensionItems = this.items.get(extensionId)\n\n    if (extensionItems.has(menuItemId)) {\n      console.warn('Tried to update non-existing extension menu item')\n      return\n    }\n\n    const finalUpdates = {}\n    if (type !== undefined) finalUpdates.type = type\n    if (title !== undefined) finalUpdates.title = title\n    if (contexts !== undefined) finalUpdates.contexts = contexts\n    if (visible !== undefined) finalUpdates.visible = visible\n    if (enabled !== undefined) finalUpdates.enabled = enabled\n\n    const existing = this.items.get(extensionId).get(menuItemId)\n\n    extensionItems.set(menuItemId, { ...existing, ...finalUpdates })\n  }\n\n  async onClicked ({ extensionId } = {}, handler) {\n    this.on(`${extensionId}-onClicked`, handler)\n    return () => this.removeListener(`${extensionId}-onClicked`, handler)\n  }\n\n  dispatchOnClicked ({ extensionId } = {}, onClickData, webContents) {\n    const tab = webContents ? webContentsToTab(webContents) : null\n    this.emit(`${extensionId}-onClicked`, onClickData, tab)\n  }\n}\n\nclass BrowserActions extends EventEmtiter {\n  constructor ({ tabs }) {\n    super()\n    this.tabs = tabs\n    // Map extension id to browser action\n    /*\n    Actions look like:\n\n    [extensionId] : {\n      extensionId: 0,\n      extensionURL: `chrome-extension://whatever`\n      enabled: true,\n      title: \"Hello World\",\n      popup: \"hello\" or null,\n      badge: \"0\" or \"\",\n      icon: `chrome-extension://whatever/whatever.png`\n\n      tabs: {\n        [tabId]: {\n        [property]: newValue\n      }\n    }\n\n    */\n    this.actions = new Map()\n  }\n\n  registerExtension ({ id, manifest, url, path }) {\n    if (!manifest.browser_action) return\n    const manifestData = manifest.browser_action\n\n    const extensionURL = url\n    const extensionId = id\n    const icon = actionIcon(path, manifestData.default_icon)\n    const title = manifestData.default_title\n    const popup = manifestData.default_popup\n\n    this.actions.set(extensionId, {\n      extensionId,\n      extensionURL,\n      enabled: true,\n      title,\n      popup,\n      badge: '',\n      badgeBackground: '',\n      badgeColor: '',\n      icon,\n      tabs: {}\n    })\n  }\n\n  unregisterExtension (extensionId) {\n    this.actions.delete(extensionId)\n    this.dispatchOnChange()\n  }\n\n  async click (extensionId, tabId) {\n    const action = await this.get(extensionId, tabId)\n    if (action.popup) {\n      return this.openPopup({ extensionId }, { tabId })\n    } else {\n      return this.dispatchOnClicked({ extensionId }, tabId)\n    }\n  }\n\n  get (extensionId, tabId) {\n    const action = this.actions.get(extensionId)\n    if (tabId && action.tabs[tabId]) {\n      const updates = action.tabs[tabId]\n      const updated = { ...action, ...updates }\n      return updated\n    } else {\n      // Don't return mutable references\n      return { ...action }\n    }\n  }\n\n  getProperty (extensionId, property, tabId) {\n    const action = this.get(extensionId, tabId)\n    if (action) return action[property]\n  }\n\n  list (tabId) {\n    return [...this.actions.entries()]\n      .map(([extensionId, action]) => {\n        const combined = { ...action, extensionId }\n        if (tabId && action.tabs[tabId]) {\n          const updates = action.tabs[tabId]\n          return { ...combined, ...updates }\n        } else {\n          return combined\n        }\n      })\n  }\n\n  update (extensionId, name, value, tabId) {\n    const action = this.get(extensionId)\n    if (tabId) {\n      const existing = action.tabs[tabId] || {}\n      if (existing[name] === value) return\n\n      const updated = { ...existing, [name]: value }\n      action.tabs[tabId] = updated\n\n      this.dispatchOnChangeTab(tabId)\n    } else {\n      if (action[name] === value) return\n\n      const updated = { ...action, [name]: value }\n      this.actions.set(extensionId, updated)\n\n      this.dispatchOnChange()\n    }\n  }\n\n  async getTitle ({ extensionId } = {}, { tabId } = {}) {\n    return this.getProperty(extensionId, 'title', tabId)\n  }\n\n  async setTitle ({ extensionId } = {}, { title, tabId } = {}) {\n    return this.update(extensionId, 'title', title, tabId)\n  }\n\n  async setIcon ({ extensionId } = {}, { imageData, path, tabId } = {}) {\n    const extensionURL = await this.getProperty(extensionId, 'extensionURL', tabId)\n    const icon = actionIcon(extensionURL, path || imageData)\n    return this.update(extensionId, 'icon', icon, tabId)\n  }\n\n  async getPopup ({ extensionId } = {}, { tabId } = {}) {\n    return this.getProperty(extensionId, 'popup', tabId)\n  }\n\n  async setPopup ({ extensionId } = {}, { popup, tabId } = {}) {\n    return this.update(extensionId, 'popup', popup, tabId)\n  }\n\n  async openPopup ({ extensionId } = {}, { tabId } = {}) {\n    const action = this.get(extensionId, tabId)\n    const { popup, extensionURL } = action\n\n    await this.tabs.create({ extensionId }, {\n      url: new URL(popup, extensionURL).href,\n      popup: true,\n      openerTabId: tabId\n    })\n  }\n\n  async getBadgeText ({ extensionId } = {}, { tabId } = {}) {\n    return this.getProperty(extensionId, 'badge', tabId)\n  }\n\n  async setBadgeText ({ extensionId } = {}, { text, tabId } = {}) {\n    return this.update(extensionId, 'badge', text, tabId)\n  }\n\n  async setBadgeBackgroundColor ({ extensionId } = {}, { color, tabId } = {}) {\n    return this.update(extensionId, 'badgeBackground', color, tabId)\n  }\n\n  async getBadgeBackgroundColor ({ extensionId } = {}, { tabId } = {}) {\n    return this.getProperty(extensionId, 'badgeBackground', tabId)\n  }\n\n  async setBadgeTextColor ({ extensionId } = {}, { color, tabId } = {}) {\n    return this.update(extensionId, 'badgeColor', color, tabId)\n  }\n\n  async getBadgeTextColor ({ extensionId } = {}, { tabId } = {}) {\n    return this.getProperty(extensionId, 'badgeColor', tabId)\n  }\n\n  async disable ({ extensionId } = {}, { tabId } = {}) {\n    return this.update(extensionId, 'enabled', false, tabId)\n  }\n\n  async enable ({ extensionId } = {}, { tabId } = {}) {\n    return this.update(extensionId, 'enabled', true, tabId)\n  }\n\n  async isEnabled ({ extensionId } = {}, { tabId } = {}) {\n    return this.getProperty(extensionId, 'enabled', tabId)\n  }\n\n  async onClicked ({ extensionId } = {}, handler) {\n    this.on(`${extensionId}-onClicked`, handler)\n    return () => this.removeListener(`${extensionId}-onClicked`, handler)\n  }\n\n  dispatchOnChange () {\n    this.emit('change', this.list())\n  }\n\n  dispatchOnChangeTab (tabId) {\n    this.emit('change-tab', tabId, this.list(tabId))\n  }\n\n  async dispatchOnClicked ({ extensionId } = {}, tabId) {\n    const tab = await this.tabs.get({ extensionId }, tabId)\n    this.emit(`${extensionId}-onClicked`, tab)\n  }\n}\n\nclass Debugger extends EventEmtiter {\n  constructor ({ tabs, session }) {\n    super()\n    this.tabs = tabs\n    this.session = session\n  }\n\n  async attach ({ extensionId } = {}, { tabId }, requiredVersion = '1.1') {\n    // This will throw if it's not a tracked tab\n    const webContents = await this.tabs.getRaw(tabId)\n\n    const onDetach = (event, reason) => {\n      this.dispatchOnDetach({ extensionId }, { tabId }, reason)\n    }\n    const onEvent = (event, method, ...args) => {\n      this.dispatchOnEvent({ extensionId }, { tabId }, method, ...args)\n    }\n\n    webContents.debugger.on('detach', onDetach)\n    webContents.debugger.on('message', onEvent)\n\n    webContents.debugger.attach(requiredVersion)\n\n    const cleanup = () => {\n      webContents.debugger.removeListener('detach', onDetach)\n      webContents.debugger.removeListener('message', onEvent)\n    }\n\n    webContents.debugger.once('detach', cleanup)\n  }\n\n  async detach ({ extensionId } = {}, { tabId }) {\n    // This will throw if it's not a tracked tab\n    const webContents = await this.tabs.getRaw(tabId)\n\n    webContents.debugger.detach()\n  }\n\n  async getTargets ({ extensionId } = {}) {\n    return [...this.tabs].map((webContents) => {\n      const attached = webContents.debugger.isAttached()\n      const tabId = webContents.id\n      const id = tabId\n      const type = 'page'\n      const title = webContents.getTitle()\n      const url = webContents.getURL()\n\n      return { attached, tabId, id, type, title, url }\n    })\n  }\n\n  async sendCommand ({ extensionId } = {}, { tabId }, method, ...args) {\n    const webContents = await this.tabs.getRaw(tabId)\n\n    const result = await webContents.debugger.sendCommand(method, ...args)\n\n    return result\n  }\n\n  onDetach ({ extensionId } = {}, handler) {\n    this.on(`${extensionId}-onDetach`, handler)\n    return () => this.removeListener(`${extensionId}-onDetach`, handler)\n  }\n\n  onEvent ({ extensionId } = {}, handler) {\n    this.on(`${extensionId}-onEvent`, handler)\n    return () => this.removeListener(`${extensionId}-onEvent`, handler)\n  }\n\n  async dispatchOnDetach ({ extensionId } = {}, target, reason) {\n    this.emit(`${extensionId}-onDetach`, target, reason)\n  }\n\n  async dispatchOnEvent ({ extensionId } = {}, target, method, ...args) {\n    this.emit(`${extensionId}-onEvent`, target, method, ...args)\n  }\n}\n\nclass Tabs extends EventEmtiter {\n  constructor (extensions) {\n    super()\n    this.tabs = new Map()\n    this.extensions = extensions\n    this.lastFocused = null\n  }\n\n  /* Invoked by application */\n  async trackTab (webContents) {\n    const tabId = webContents.id\n    this.tabs.set(tabId, webContents)\n\n    webContents.on('destroyed', () => {\n      this.tabs.delete(tabId)\n      this.dispatchOnRemoved(webContents)\n    })\n    webContents.on('focus', () => {\n      const currentURL = webContents.getURL()\n      if (!currentURL) return\n      const { protocol } = new URL(currentURL)\n      // Don't track focus for extension popups or devtools\n      if (FORBIDDEN_PROTOCOLS.includes(protocol)) return\n      this.dispatchOnActivated(webContents)\n    })\n    webContents.on('did-start-navigation', (e, url, isInPlace, isMainFrame) => {\n      // Only listen for navigation changes in the main frame\n      if (!isMainFrame && isInPlace) return\n      this.dispatchOnUpdated(webContents)\n    })\n    this.dispatchOnCreated(webContents)\n  }\n\n  async getRaw (tabId) {\n    if (!this.tabs.has(tabId)) throw new Error('Tab Not Found')\n    return this.tabs.get(tabId)\n  }\n\n  /* Invoked by extension APIs */\n  async create ({ extensionId } = {}, options = {}) {\n    // TODO: check permissions for extension ID\n    const webContents = await this.extensions.onCreateTab(options)\n    this.trackTab(webContents)\n    return webContentsToTab(webContents)\n  }\n\n  async executeScript ({ extensionId } = {}, tabId, { code, allFrames = false, frameId, file } = {}) {\n    if (file) throw new Error('File injection not supported')\n    const webContents = await this.getRaw(tabId)\n    if (allFrames && frameId) throw new Error('allFrames and frameId are mutually exclusive')\n    if (allFrames) {\n      return Promise.all(webContents.mainFrame.framesInSubtree.map((frame) => {\n        return frame.executeJavaScript(code)\n      }))\n    } else if (frameId) {\n      for (const frame of webContents.mainFrame.framesInSubtree) {\n        if (frame.routingId !== frameId) continue\n        return frame.executeJavaScript(code)\n      }\n    } else {\n      return webContents.mainFrame.executeJavaScript(code)\n    }\n  }\n\n  async get ({ extensionId } = {}, tabId) {\n    const webContents = await this.getRaw(tabId)\n    return webContentsToTab(webContents)\n  }\n\n  async getCurrent ({ extensionId, sender } = {}) {\n    return webContentsToTab(sender)\n  }\n\n  async query ({ extensionId } = {}, query) {\n    return [...this.tabs.values()].filter((webContents) => {\n      const tab = webContentsToTab(webContents)\n      if (tab.id === this.lastFocused) {\n        tab.active = true\n      }\n      // TODO: Support match patterns for tab URLs\n      // Use this for pattern matching: https://github.com/kong0107/url-match-pattern\n      for (const key of TAB_QUERY_PROPERTIES) {\n        if (key in query && tab[key] !== query[key]) return false\n      }\n      return true\n    }).map(webContentsToTab)\n  }\n\n  async remove ({ extensionId } = {}, tabIds) {\n    for (const tabId of [].concat(tabIds)) {\n      if (!this.tabs.has(tabId)) continue\n      const webContents = this.tabs.getRaw(tabId)\n      webContents.destroy()\n    }\n  }\n\n  async reload ({ extensionId } = {}, tabId) {\n    if (!this.tabs.has(tabId)) throw new Error('Not Found')\n    const webContents = this.tabs.getRaw(tabId)\n    webContents.reload()\n  }\n\n  [Symbol.iterator] () {\n    return this.tabs.values()\n  }\n\n  onActivated ({ extensionId } = {}, handler) {\n    this.on('onActivated', handler)\n    return () => this.removeListener('onActivated', handler)\n  }\n\n  onCreated ({ extensionId } = {}, handler) {\n    this.on('onCreated', handler)\n    return () => this.removeListener('onCreated', handler)\n  }\n\n  onRemoved ({ extensionId } = {}, handler) {\n    this.on('onRemoved', handler)\n    return () => this.removeListener('onRemoved', handler)\n  }\n\n  onUpdated ({ extensionId } = {}, handler) {\n    // TODO: Add support for filters\n    this.on('onUpdated', handler)\n    return () => this.removeListener('onUpdated')\n  }\n\n  onFocusChanged ({ extensionId } = {}, handler) {\n    this.on('onFocusChanged', handler)\n    return () => this.removeListener('onFocusChanged')\n  }\n\n  async dispatchOnActivated ({ id: tabId }) {\n    this.lastFocused = tabId\n    this.emit('onActivated', { tabId })\n    this.emit('onFocusChanged', { windowId: tabId })\n  }\n\n  async dispatchOnCreated (webContents) {\n    const tab = webContentsToTab(webContents)\n    this.emit('onCreated', tab)\n    this.emit('created', webContents)\n  }\n\n  async dispatchOnRemoved ({ id: tabId }) {\n    this.emit('onRemoved', { tabId, removeInfo: {} })\n  }\n\n  dispatchOnUpdated (webContents, property = 'url') {\n    // Only URL changes supported for now\n    const tabId = webContents.id\n    const tab = webContentsToTab(webContents)\n    const changeInfo = {}\n    if (property === 'url') {\n      changeInfo.url = webContents.getURL()\n    }\n    this.emit('onUpdated', tabId, changeInfo, tab)\n  }\n}\n\nasync function DEFAULT_ON_CREATE_TAB (options) {\n  throw new Error('Unable to create tabs, not implemented')\n}\n\nclass ExtendedExtensions {\n  constructor (session, {\n    onCreateTab = DEFAULT_ON_CREATE_TAB,\n    preloadPath = PRELOAD_PATH\n  } = {}) {\n    this.onDestroy = []\n    this.extensions = new Map()\n\n    // Register the session related callbacks?\n    this.session = session\n\n    if (onCreateTab === DEFAULT_ON_CREATE_TAB) {\n      console.warn('ExtendedExtensions: onCreateTab was not supplied, some extension features will be unavailable')\n    }\n\n    this.onCreateTab = onCreateTab\n\n    const preloads = session.getPreloads()\n    session.setPreloads([...preloads, preloadPath])\n\n    this.tabs = new Tabs(this)\n    this.debugger = new Debugger(this)\n    this.browserActions = new BrowserActions(this)\n    this.contextMenus = new ContextMenus(this)\n    this.webNavigation = new WebNavigation(this)\n\n    this.attachAPI(this.tabs, 'tabs')\n    this.attachAPI(this.tabs, 'windows')\n    this.attachAPI(this.debugger, 'debugger')\n    this.attachAPI(this.browserActions, 'browserAction')\n    this.attachAPI(this.contextMenus, 'contextMenus')\n    this.attachAPI(this.webNavigation, 'webNavigation')\n\n    const handleContentsCreated = (event, webContents) => {\n      if (webContents.session !== this.session) return\n      this.tabs.trackTab(webContents)\n    }\n\n    app.on('web-contents-created', handleContentsCreated)\n    this.onDestroy.push(() => {\n      app.removeListener('web-contents-created', handleContentsCreated)\n    })\n  }\n\n  async loadExtension (extensionPath) {\n    const extension = await this.session.loadExtension(extensionPath)\n    const { id } = extension\n\n    this.extensions.set(id, extension)\n\n    this.browserActions.registerExtension(extension)\n\n    return extension\n  }\n\n  async get (id) {\n    if (!this.extensions.has(id)) throw new Error('Extension not registered')\n    return this.extensions.get(id)\n  }\n\n  async unloadExtension (id) {\n    if (!this.extensions.has(id)) return\n\n    this.browserActions.unregisterExtension(id)\n\n    await this.session.unloadExtension(id)\n    this.extensions.delete(id)\n  }\n\n  async getBackgroundPage (id) {\n    // iterate through web contents\n    // Filter for web contents that are:\n    // - The URL of the background page for the extension\n    // - The session this extension was registered for\n    // - It is the background page?\n    const extension = await this.get(id)\n    return WebContents.getAllWebContents().find((webContents) => {\n      const url = webContents.getURL()\n      if (webContents.session !== this.session) return false\n      if (!url.startsWith(extension.url)) return false\n      // TODO: How do we know if it's the background page?\n      // Likely the background page will be created before any other extension pages?\n      return true\n    })\n  }\n\n  attachAPI (implementation, type) {\n    for (const [name, apiKind] of Object.entries(spec[type])) {\n      if (apiKind === FUNCTION) {\n        this.attachFunctionAPI(implementation, type, name)\n      } else if (apiKind === EVENT) {\n        this.attachListenerAPI(implementation, type, name)\n      } else {\n        throw new TypeError(`Invalid API Kind: ${apiKind}`)\n      }\n    }\n  }\n\n  attachListenerAPI (implementation, type, name) {\n    const event = makeEvent(type, name)\n    const listeners = new Map()\n\n    const onAdd = async (e, extensionId, listenerId) => {\n      const { frameId, sender } = e\n      if (sender.session !== this.session) return\n      // TODO: Check if extension has permission for this page URL\n      const key = `${frameId}-${extensionId}-${listenerId}`\n\n      function handler (...args) {\n        e.reply(event, extensionId, listenerId, ...args)\n      }\n\n      if (!implementation[name]) throw new TypeError(`${type}.${name} is not defined`)\n\n      const removeListener = await implementation[name]({ extensionId, sender }, handler)\n      listeners.set(key, cleanup)\n\n      sender.once('did-navigate', navigateListener)\n\n      function navigateListener () {\n        cleanup()\n        sender.removeListener('did-navigate', navigateListener)\n      }\n\n      function cleanup () {\n        removeListener()\n        listeners.delete(key)\n      }\n    }\n\n    const onRemove = (e, extensionId, listenerId) => {\n      const { frameId, sender } = e\n      // Only respond to sessions we're listening on\n      if (sender.session !== this.session) return\n      const key = `${frameId}-${extensionId}-${listenerId}`\n      const cleanup = listeners.get(key)\n      if (!cleanup) return\n      cleanup()\n    }\n\n    const listenEvent = event + '-add'\n    const removeEvent = event + '-remove'\n\n    ipcMain.on(listenEvent, onAdd)\n    ipcMain.on(removeEvent, onRemove)\n\n    this.onDestroy.push(() => {\n      for (const cleanup of listeners.values()) {\n        cleanup()\n      }\n      ipcMain.removeListener(listenEvent, onAdd)\n      ipcMain.removeListener(removeEvent, onRemove)\n    })\n  }\n\n  attachFunctionAPI (implementation, type, name) {\n    const event = makeEvent(type, name)\n    const onInvoke = async (e, extensionId, ...args) => {\n      const { sender } = e\n      // Only respond to sessions we're listening on\n      if (sender.session !== this.session) return\n      if (!implementation[name]) throw new TypeError(`${type}.${name} is not defined`)\n      return implementation[name]({ extensionId, sender }, ...args)\n    }\n    // TODO: Register handlers globally and have extensions instances attach/detach from there\n    ipcMain.handle(event, onInvoke)\n\n    this.onDestroy.push(() => {\n      ipcMain.removeHandler(event, onInvoke)\n    })\n  }\n\n  async destroy () {\n    for (const id of this.extensions.keys()) {\n      await this.unloadExtension(id)\n    }\n    for (const onDestroy of this.onDestroy) {\n      await onDestroy()\n    }\n  }\n}\n\nfunction webContentsToTab (webContents) {\n  const active = webContents.isFocused()\n  const id = webContents.id\n  const status = webContents.isLoading() ? 'complete' : 'loading'\n  const url = webContents.getURL()\n  const title = webContents.getTitle()\n\n  return {\n    active,\n    id,\n    status,\n    title,\n    url\n  }\n}\n\nfunction actionIcon (extensionPath, iconMapOrPath) {\n  const type = typeof iconMapOrPath\n  if (type === 'string') {\n    return join(extensionPath, iconMapOrPath)\n  } else if (type === 'object') {\n    const imageKey = Object.keys(iconMapOrPath).sort().at(-1)\n    const imagePath = iconMapOrPath[imageKey]\n    return join(extensionPath, imagePath)\n  }\n  return ''\n}\n\nmodule.exports = {\n  ExtendedExtensions,\n  Tabs\n}\n"]}