/******/ (function() { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ 70526: /***/ (function() { (function(){/* Copyright (c) 2016 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */'use strict';var n=window.Document.prototype.createElement,p=window.Document.prototype.createElementNS,aa=window.Document.prototype.importNode,ba=window.Document.prototype.prepend,ca=window.Document.prototype.append,da=window.DocumentFragment.prototype.prepend,ea=window.DocumentFragment.prototype.append,q=window.Node.prototype.cloneNode,r=window.Node.prototype.appendChild,t=window.Node.prototype.insertBefore,u=window.Node.prototype.removeChild,v=window.Node.prototype.replaceChild,w=Object.getOwnPropertyDescriptor(window.Node.prototype,"textContent"),y=window.Element.prototype.attachShadow,z=Object.getOwnPropertyDescriptor(window.Element.prototype,"innerHTML"),A=window.Element.prototype.getAttribute,B=window.Element.prototype.setAttribute,C=window.Element.prototype.removeAttribute,D=window.Element.prototype.toggleAttribute,E=window.Element.prototype.getAttributeNS,F=window.Element.prototype.setAttributeNS,G=window.Element.prototype.removeAttributeNS,H=window.Element.prototype.insertAdjacentElement,fa=window.Element.prototype.insertAdjacentHTML,ha=window.Element.prototype.prepend,ia=window.Element.prototype.append,ja=window.Element.prototype.before,ka=window.Element.prototype.after,la=window.Element.prototype.replaceWith,ma=window.Element.prototype.remove,na=window.HTMLElement,I=Object.getOwnPropertyDescriptor(window.HTMLElement.prototype,"innerHTML"),oa=window.HTMLElement.prototype.insertAdjacentElement,pa=window.HTMLElement.prototype.insertAdjacentHTML;var qa=new Set();"annotation-xml color-profile font-face font-face-src font-face-uri font-face-format font-face-name missing-glyph".split(" ").forEach(function(a){return qa.add(a);});function ra(a){var b=qa.has(a);a=/^[a-z][.0-9_a-z]*-[-.0-9_a-z]*$/.test(a);return!b&&a;}var sa=document.contains?document.contains.bind(document):document.documentElement.contains.bind(document.documentElement);function J(a){var b=a.isConnected;if(void 0!==b)return b;if(sa(a))return!0;for(;a&&!(a.__CE_isImportDocument||a instanceof Document);)a=a.parentNode||(window.ShadowRoot&&a instanceof ShadowRoot?a.host:void 0);return!(!a||!(a.__CE_isImportDocument||a instanceof Document));}function K(a){var b=a.children;if(b)return Array.prototype.slice.call(b);b=[];for(a=a.firstChild;a;a=a.nextSibling)a.nodeType===Node.ELEMENT_NODE&&b.push(a);return b;}function L(a,b){for(;b&&b!==a&&!b.nextSibling;)b=b.parentNode;return b&&b!==a?b.nextSibling:null;}function M(a,b,d){for(var f=a;f;){if(f.nodeType===Node.ELEMENT_NODE){var c=f;b(c);var e=c.localName;if("link"===e&&"import"===c.getAttribute("rel")){f=c.import;void 0===d&&(d=new Set());if(f instanceof Node&&!d.has(f))for(d.add(f),f=f.firstChild;f;f=f.nextSibling)M(f,b,d);f=L(a,c);continue;}else if("template"===e){f=L(a,c);continue;}if(c=c.__CE_shadowRoot)for(c=c.firstChild;c;c=c.nextSibling)M(c,b,d);}f=f.firstChild?f.firstChild:L(a,f);}};function N(){var a=!(null===O||void 0===O||!O.noDocumentConstructionObserver),b=!(null===O||void 0===O||!O.shadyDomFastWalk);this.m=[];this.g=[];this.j=!1;this.shadyDomFastWalk=b;this.I=!a;}function P(a,b,d,f){var c=window.ShadyDOM;if(a.shadyDomFastWalk&&c&&c.inUse){if(b.nodeType===Node.ELEMENT_NODE&&d(b),b.querySelectorAll)for(a=c.nativeMethods.querySelectorAll.call(b,"*"),b=0;b callback(), options); } return globalThis.setTimeout(() => callback(), 1); } /** * Polyfills the cancelIdleCallback API with a clearTimeout fallback. * * @param id - The ID of the idle callback to cancel. */ function cancelIdleCallbackPolyfill(id) { if ("cancelIdleCallback" in globalThis) { return globalThis.cancelIdleCallback(id); } return globalThis.clearTimeout(id); } /** * Generates a random string of characters that formatted as a custom element name. */ function generateRandomCustomElementName() { const length = Math.floor(Math.random() * 5) + 8; // Between 8 and 12 characters const numHyphens = Math.min(Math.max(Math.floor(Math.random() * 4), 1), length - 1); // At least 1, maximum of 3 hyphens const hyphenIndices = []; while (hyphenIndices.length < numHyphens) { const index = Math.floor(Math.random() * (length - 1)) + 1; if (!hyphenIndices.includes(index)) { hyphenIndices.push(index); } } hyphenIndices.sort((a, b) => a - b); let randomString = ""; let prevIndex = 0; for (let index = 0; index < hyphenIndices.length; index++) { const hyphenIndex = hyphenIndices[index]; randomString = randomString + generateRandomChars(hyphenIndex - prevIndex) + "-"; prevIndex = hyphenIndex; } randomString += generateRandomChars(length - prevIndex); return randomString; } /** * Builds a DOM element from an SVG string. * * @param svgString - The SVG string to build the DOM element from. * @param ariaHidden - Determines whether the SVG should be hidden from screen readers. */ function buildSvgDomElement(svgString, ariaHidden = true) { const domParser = new DOMParser(); const svgDom = domParser.parseFromString(svgString, "image/svg+xml"); const domElement = svgDom.documentElement; domElement.setAttribute("aria-hidden", `${ariaHidden}`); return domElement; } /** * Sends a message to the extension. * * @param command - The command to send. * @param options - The options to send with the command. */ function sendExtensionMessage(command_1) { return __awaiter(this, arguments, void 0, function* (command, options = {}) { if (typeof browser !== "undefined" && typeof browser.runtime !== "undefined" && typeof browser.runtime.sendMessage !== "undefined") { return browser.runtime.sendMessage(Object.assign({ command }, options)); } return new Promise((resolve) => chrome.runtime.sendMessage(Object.assign({ command }, options), (response) => { if (chrome.runtime.lastError) { resolve(null); } resolve(response); })); }); } /** * Sets CSS styles on an element. * * @param element - The element to set the styles on. * @param styles - The styles to set on the element. * @param priority - Determines whether the styles should be set as important. */ function setElementStyles(element, styles, priority) { if (!element || !styles || !Object.keys(styles).length) { return; } for (const styleProperty in styles) { element.style.setProperty(styleProperty.replace(/([a-z])([A-Z])/g, "$1-$2"), // Convert camelCase to kebab-case styles[styleProperty], priority ? "important" : undefined); } } /** * Sets up a long-lived connection with the extension background * and triggers an onDisconnect event if the extension context * is invalidated. * * @param callback - Callback export function to run when the extension disconnects */ function setupExtensionDisconnectAction(callback) { const port = chrome.runtime.connect({ name: AutofillPort.InjectedScript }); const onDisconnectCallback = (disconnectedPort) => { callback(disconnectedPort); port.onDisconnect.removeListener(onDisconnectCallback); }; port.onDisconnect.addListener(onDisconnectCallback); } /** * Handles setup of the extension disconnect action for the autofill init class * in both instances where the overlay might or might not be initialized. * * @param windowContext - The global window context */ function setupAutofillInitDisconnectAction(windowContext) { if (!windowContext.bitwardenAutofillInit) { return; } const onDisconnectCallback = () => { windowContext.bitwardenAutofillInit.destroy(); delete windowContext.bitwardenAutofillInit; }; setupExtensionDisconnectAction(onDisconnectCallback); } /** * Identifies whether an element is a fillable form field. * This is determined by whether the element is a form field and not a span. * * @param formFieldElement - The form field element to check. */ function elementIsFillableFormField(formFieldElement) { return !elementIsSpanElement(formFieldElement); } /** * Identifies whether an element is an instance of a specific tag name. * * @param element - The element to check. * @param tagName - The tag name to check against. */ function elementIsInstanceOf(element, tagName) { return nodeIsElement(element) && element.tagName.toLowerCase() === tagName; } /** * Identifies whether an element is a span element. * * @param element - The element to check. */ function elementIsSpanElement(element) { return elementIsInstanceOf(element, "span"); } /** * Identifies whether an element is an input field. * * @param element - The element to check. */ function elementIsInputElement(element) { return elementIsInstanceOf(element, "input"); } /** * Identifies whether an element is a select field. * * @param element - The element to check. */ function elementIsSelectElement(element) { return elementIsInstanceOf(element, "select"); } /** * Identifies whether an element is a textarea field. * * @param element - The element to check. */ function elementIsTextAreaElement(element) { return elementIsInstanceOf(element, "textarea"); } /** * Identifies whether an element is a form element. * * @param element - The element to check. */ function elementIsFormElement(element) { return elementIsInstanceOf(element, "form"); } /** * Identifies whether an element is a label element. * * @param element - The element to check. */ function elementIsLabelElement(element) { return elementIsInstanceOf(element, "label"); } /** * Identifies whether an element is a description details `dd` element. * * @param element - The element to check. */ function elementIsDescriptionDetailsElement(element) { return elementIsInstanceOf(element, "dd"); } /** * Identifies whether an element is a description term `dt` element. * * @param element - The element to check. */ function elementIsDescriptionTermElement(element) { return elementIsInstanceOf(element, "dt"); } /** * Identifies whether a node is an HTML element. * * @param node - The node to check. */ function nodeIsElement(node) { if (!node) { return false; } return (node === null || node === void 0 ? void 0 : node.nodeType) === Node.ELEMENT_NODE; } /** * Identifies whether a node is an input element. * * @param node - The node to check. */ function nodeIsInputElement(node) { return nodeIsElement(node) && elementIsInputElement(node); } /** * Identifies whether a node is a form element. * * @param node - The node to check. */ function nodeIsFormElement(node) { return nodeIsElement(node) && elementIsFormElement(node); } function nodeIsTypeSubmitElement(node) { return nodeIsElement(node) && getPropertyOrAttribute(node, "type") === "submit"; } function nodeIsButtonElement(node) { return (nodeIsElement(node) && (elementIsInstanceOf(node, "button") || getPropertyOrAttribute(node, "type") === "button")); } function nodeIsAnchorElement(node) { return nodeIsElement(node) && elementIsInstanceOf(node, "a"); } /** * Returns a boolean representing the attribute value of an element. * * @param element * @param attributeName * @param checkString */ function getAttributeBoolean(element, attributeName, checkString = false) { if (checkString) { return getPropertyOrAttribute(element, attributeName) === "true"; } return Boolean(getPropertyOrAttribute(element, attributeName)); } /** * Get the value of a property or attribute from a FormFieldElement. * * @param element * @param attributeName */ function getPropertyOrAttribute(element, attributeName) { if (attributeName in element) { return element[attributeName]; } return element.getAttribute(attributeName); } /** * Throttles a callback function to run at most once every `limit` milliseconds. * * @param callback - The callback function to throttle. * @param limit - The time in milliseconds to throttle the callback. */ function throttle(callback, limit) { let waitingDelay = false; return function (...args) { if (!waitingDelay) { callback.apply(this, args); waitingDelay = true; globalThis.setTimeout(() => (waitingDelay = false), limit); } }; } /** * Debounces a callback function to run after a delay of `delay` milliseconds. * * @param callback - The callback function to debounce. * @param delay - The time in milliseconds to debounce the callback. * @param immediate - Determines whether the callback should run immediately. */ function debounce(callback, delay, immediate) { let timeout; return function (...args) { const callImmediately = !!immediate && !timeout; if (timeout) { globalThis.clearTimeout(timeout); } timeout = globalThis.setTimeout(() => { timeout = null; if (!callImmediately) { callback.apply(this, args); } }, delay); if (callImmediately) { callback.apply(this, args); } }; } /** * Gathers and normalizes keywords from a potential submit button element. Used * to verify if the element submits a login or change password form. * * @param element - The element to gather keywords from. */ function getSubmitButtonKeywordsSet(element) { const keywords = [ element.textContent, element.getAttribute("type"), element.getAttribute("value"), element.getAttribute("aria-label"), element.getAttribute("aria-labelledby"), element.getAttribute("aria-describedby"), element.getAttribute("title"), element.getAttribute("id"), element.getAttribute("name"), element.getAttribute("class"), ]; const keywordsSet = new Set(); for (let i = 0; i < keywords.length; i++) { if (typeof keywords[i] === "string") { // Iterate over all keywords metadata and split them by non-letter characters. // This ensures we check against individual words and not the entire string. keywords[i] .toLowerCase() .replace(/[-\s]/g, "") .split(/[^\p{L}]+/gu) .forEach((keyword) => { if (keyword) { keywordsSet.add(keyword); } }); } } return keywordsSet; } /** * Generates the origin and subdomain match patterns for the URL. * * @param url - The URL of the tab */ function generateDomainMatchPatterns(url) { try { const extensionUrlPattern = /^(chrome|chrome-extension|moz-extension|safari-web-extension):\/\/\/?/; if (extensionUrlPattern.test(url)) { return []; } // Add protocol to URL if it is missing to allow for parsing the hostname correctly const urlPattern = /^(https?|file):\/\/\/?/; if (!urlPattern.test(url)) { url = `https://${url}`; } let protocolGlob = "*://"; if (url.startsWith("file:///")) { protocolGlob = "*:///"; // File URLs require three slashes to be a valid match pattern } const parsedUrl = new URL(url); const originMatchPattern = `${protocolGlob}${parsedUrl.hostname}/*`; const splitHost = parsedUrl.hostname.split("."); const domain = splitHost.slice(-2).join("."); const subDomainMatchPattern = `${protocolGlob}*.${domain}/*`; return [originMatchPattern, subDomainMatchPattern]; } catch (_a) { return []; } } /** * Determines if the status code of the web response is invalid. An invalid status code is * any status code that is not in the 200-299 range. * * @param statusCode - The status code of the web response */ function isInvalidResponseStatusCode(statusCode) { return statusCode < 200 || statusCode >= 300; } /** * Determines if the current context is within a sandboxed iframe. */ function currentlyInSandboxedIframe() { var _a, _b; if (String(self.origin).toLowerCase() === "null" || globalThis.location.hostname === "") { return true; } const sandbox = (_b = (_a = globalThis.frameElement) === null || _a === void 0 ? void 0 : _a.getAttribute) === null || _b === void 0 ? void 0 : _b.call(_a, "sandbox"); // No frameElement or sandbox attribute means not sandboxed if (sandbox === null || sandbox === undefined) { return false; } // An empty string means fully sandboxed if (sandbox === "") { return true; } const tokens = new Set(sandbox.toLowerCase().split(" ")); return !["allow-scripts", "allow-same-origin"].every((token) => tokens.has(token)); } /** * This object allows us to map a special character to a key name. The key name is used * in gathering the i18n translation of the written version of the special character. */ const specialCharacterToKeyMap = { " ": "spaceCharacterDescriptor", "~": "tildeCharacterDescriptor", "`": "backtickCharacterDescriptor", "!": "exclamationCharacterDescriptor", "@": "atSignCharacterDescriptor", "#": "hashSignCharacterDescriptor", $: "dollarSignCharacterDescriptor", "%": "percentSignCharacterDescriptor", "^": "caretCharacterDescriptor", "&": "ampersandCharacterDescriptor", "*": "asteriskCharacterDescriptor", "(": "parenLeftCharacterDescriptor", ")": "parenRightCharacterDescriptor", "-": "hyphenCharacterDescriptor", _: "underscoreCharacterDescriptor", "+": "plusCharacterDescriptor", "=": "equalsCharacterDescriptor", "{": "braceLeftCharacterDescriptor", "}": "braceRightCharacterDescriptor", "[": "bracketLeftCharacterDescriptor", "]": "bracketRightCharacterDescriptor", "|": "pipeCharacterDescriptor", "\\": "backSlashCharacterDescriptor", ":": "colonCharacterDescriptor", ";": "semicolonCharacterDescriptor", '"': "doubleQuoteCharacterDescriptor", "'": "singleQuoteCharacterDescriptor", "<": "lessThanCharacterDescriptor", ">": "greaterThanCharacterDescriptor", ",": "commaCharacterDescriptor", ".": "periodCharacterDescriptor", "?": "questionCharacterDescriptor", "/": "forwardSlashCharacterDescriptor", }; /** * Determines if the current rect values are not all 0. */ function rectHasSize(rect) { if (rect.right > 0 && rect.left > 0 && rect.top > 0 && rect.bottom > 0) { return true; } return false; } /** * Checks if all the values corresponding to the specified keys in an object are null. * If no keys are specified, checks all keys in the object. * * @param obj - The object to check. * @param keys - An optional array of keys to check in the object. Defaults to all keys. * @returns Returns true if all values for the specified keys (or all keys if none are provided) are null; otherwise, false. */ function areKeyValuesNull(obj, keys) { const keysToCheck = keys && keys.length > 0 ? keys : Object.keys(obj); return keysToCheck.every((key) => obj[key] == null); } ;// ./src/autofill/utils/svg-icons.ts const logoIcon = ''; const logoLockedIcon = ''; const globeIcon = ''; const creditCardIcon = ''; const idCardIcon = ''; const lockIcon = ''; const plusIcon = ''; const viewCipherIcon = ''; const passkeyIcon = ''; const circleCheckIcon = ''; const spinnerIcon = ''; const keyIcon = ''; const refreshIcon = ''; ;// ./src/autofill/overlay/inline-menu/pages/shared/autofill-inline-menu-page-element.ts var autofill_inline_menu_page_element_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; class AutofillInlineMenuPageElement extends HTMLElement { constructor() { super(); /** * Handles window messages from the parent window. * * @param event - The window message event */ this.handleWindowMessage = (event) => { if (!this.windowMessageHandlers) { return; } if (event.source !== globalThis.parent) { return; } if (!this.messageOrigin) { this.messageOrigin = event.origin; } if (event.origin !== this.messageOrigin) { return; } const message = event === null || event === void 0 ? void 0 : event.data; if (!(message === null || message === void 0 ? void 0 : message.command)) { return; } const isInitCommand = message.command === "initAutofillInlineMenuButton" || message.command === "initAutofillInlineMenuList"; if (isInitCommand) { if (!(message === null || message === void 0 ? void 0 : message.token)) { return; } this.token = message.token; } else { if (!this.token || !(message === null || message === void 0 ? void 0 : message.token) || message.token !== this.token) { return; } } const handler = this.windowMessageHandlers[message === null || message === void 0 ? void 0 : message.command]; if (!handler) { return; } handler({ message }); }; /** * Handles the window blur event. */ this.handleWindowBlurEvent = () => { this.postMessageToParent({ command: "autofillInlineMenuBlurred" }); }; /** * Handles the document keydown event. Facilitates redirecting the * user focus in the right direction out of the inline menu. Also facilitates * closing the inline menu when the user presses the Escape key. * * @param event - The document keydown event */ this.handleDocumentKeyDownEvent = (event) => { const listenedForKeys = new Set(["Tab", "Escape", "ArrowUp", "ArrowDown"]); if (!listenedForKeys.has(event.code)) { return; } event.preventDefault(); event.stopPropagation(); if (event.code === "Tab") { this.sendRedirectFocusOutMessage(event.shiftKey ? RedirectFocusDirection.Previous : RedirectFocusDirection.Next); return; } if (event.code === "Escape") { this.sendRedirectFocusOutMessage(RedirectFocusDirection.Current); } }; this.shadowDom = this.attachShadow({ mode: "closed" }); } /** * Initializes the inline menu page element. Facilitates ensuring that the page * is set up with the expected styles and translations. * * @param elementName - The name of the element, e.g. "button" or "list" * @param styleSheetUrl - The URL of the stylesheet to apply to the page * @param translations - The translations to apply to the page * @param portKey - Background generated key that allows the port to communicate with the background */ initAutofillInlineMenuPage(elementName, styleSheetUrl, translations, portKey) { return autofill_inline_menu_page_element_awaiter(this, void 0, void 0, function* () { this.portKey = portKey; this.translations = translations; globalThis.document.documentElement.setAttribute("lang", this.getTranslation("locale")); globalThis.document.head.title = this.getTranslation(`${elementName}PageTitle`); this.shadowDom.innerHTML = ""; const linkElement = globalThis.document.createElement("link"); linkElement.setAttribute("rel", "stylesheet"); linkElement.setAttribute("href", styleSheetUrl); return linkElement; }); } /** * Posts a window message to the parent window. * * @param message - The message to post */ postMessageToParent(message) { // never send messages containing authentication tokens without a valid token and an established messageOrigin if (!this.token || !this.messageOrigin) { return; } const messageWithAuth = Object.assign(Object.assign({ portKey: this.portKey }, message), { token: this.token }); globalThis.parent.postMessage(messageWithAuth, this.messageOrigin); } /** * Gets a translation from the translations object. * * @param key - The key of the translation to get */ getTranslation(key) { return this.translations[key] || ""; } /** * Sets up global listeners for the window message, window blur, and * document keydown events. * * @param windowMessageHandlers - The window message handlers to use */ setupGlobalListeners(windowMessageHandlers) { this.windowMessageHandlers = windowMessageHandlers; globalThis.addEventListener(EVENTS.MESSAGE, this.handleWindowMessage); globalThis.addEventListener(EVENTS.BLUR, this.handleWindowBlurEvent); globalThis.document.addEventListener(EVENTS.KEYDOWN, this.handleDocumentKeyDownEvent); } /** * Redirects the inline menu focus out to the previous element on KeyDown of the `Tab+Shift` keys. * Redirects the inline menu focus out to the next element on KeyDown of the `Tab` key. * Redirects the inline menu focus out to the current element on KeyDown of the `Escape` key. * * @param direction - The direction to redirect the focus out */ sendRedirectFocusOutMessage(direction) { this.postMessageToParent({ command: "redirectAutofillInlineMenuFocusOut", direction }); } } ;// ./src/autofill/overlay/inline-menu/pages/button/autofill-inline-menu-button.ts var autofill_inline_menu_button_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; class AutofillInlineMenuButton extends AutofillInlineMenuPageElement { constructor() { super(); this.authStatus = AuthenticationStatus.LoggedOut; this.inlineMenuButtonWindowMessageHandlers = { initAutofillInlineMenuButton: ({ message }) => this.initAutofillInlineMenuButton(message), checkAutofillInlineMenuButtonFocused: () => this.checkButtonFocused(), updateAutofillInlineMenuButtonAuthStatus: ({ message }) => this.updateAuthStatus(message.authStatus), updateAutofillInlineMenuColorScheme: ({ message }) => this.updatePageColorScheme(message), }; /** * Handles a click event on the button element. Posts a message to the * parent window indicating that the button was clicked. */ this.handleButtonElementClick = () => { this.postMessageToParent({ command: "autofillInlineMenuButtonClicked" }); }; /** * Triggers a re-check of the button's focus status when the mouse leaves the button. */ this.handleMouseOutEvent = () => { globalThis.document.removeEventListener(EVENTS.MOUSEOUT, this.handleMouseOutEvent); this.checkButtonFocused(); }; this.buttonElement = globalThis.document.createElement("button"); this.setupGlobalListeners(this.inlineMenuButtonWindowMessageHandlers); this.logoIconElement = buildSvgDomElement(logoIcon); this.logoIconElement.classList.add("inline-menu-button-svg-icon", "logo-icon"); this.logoLockedIconElement = buildSvgDomElement(logoLockedIcon); this.logoLockedIconElement.classList.add("inline-menu-button-svg-icon", "logo-locked-icon"); } /** * Initializes the inline menu button. Facilitates ensuring that the page * is set up with the expected styles and translations. * * @param authStatus - The authentication status of the user * @param styleSheetUrl - The URL of the stylesheet to apply to the page * @param translations - The translations to apply to the page * @param portKey - Background generated key that allows the port to communicate with the background */ initAutofillInlineMenuButton(_a) { return autofill_inline_menu_button_awaiter(this, arguments, void 0, function* ({ authStatus, styleSheetUrl, translations, portKey, }) { const linkElement = yield this.initAutofillInlineMenuPage("button", styleSheetUrl, translations, portKey); this.buttonElement.tabIndex = -1; this.buttonElement.type = "button"; this.buttonElement.classList.add("inline-menu-button"); this.buttonElement.setAttribute("aria-label", this.getTranslation("toggleBitwardenVaultOverlay")); this.buttonElement.addEventListener(EVENTS.CLICK, this.handleButtonElementClick); this.postMessageToParent({ command: "updateAutofillInlineMenuColorScheme" }); this.updateAuthStatus(authStatus); this.shadowDom.append(linkElement, this.buttonElement); }); } /** * Updates the authentication status of the user. This will update the icon * displayed on the button. * * @param authStatus - The authentication status of the user */ updateAuthStatus(authStatus) { this.authStatus = authStatus; this.buttonElement.innerHTML = ""; const iconElement = this.authStatus === AuthenticationStatus.Unlocked ? this.logoIconElement : this.logoLockedIconElement; this.buttonElement.append(iconElement); } /** * Handles updating the page color scheme meta tag. Ensures that the button * does not present with a non-transparent background on dark mode pages. * * @param colorScheme - The color scheme of the iframe's parent page */ updatePageColorScheme({ colorScheme }) { const colorSchemeMetaTag = globalThis.document.querySelector("meta[name='color-scheme']"); if (colorSchemeMetaTag && colorScheme) { colorSchemeMetaTag.setAttribute("content", colorScheme); } } /** * Checks if the button is focused. If it is not, then it posts a message * to the parent window indicating that the inline menu should be closed. */ checkButtonFocused() { if (globalThis.document.hasFocus()) { return; } if (this.isButtonHovered()) { globalThis.document.addEventListener(EVENTS.MOUSEOUT, this.handleMouseOutEvent); return; } this.postMessageToParent({ command: "triggerDelayedAutofillInlineMenuClosure" }); } /** * Identifies whether the button is currently hovered. */ isButtonHovered() { var _a; const hoveredElement = (_a = this.buttonElement) === null || _a === void 0 ? void 0 : _a.querySelector(":hover"); return !!(hoveredElement && (hoveredElement === this.buttonElement || this.buttonElement.contains(hoveredElement))); } } ;// ./src/autofill/overlay/inline-menu/pages/button/bootstrap-autofill-inline-menu-button.ts (function () { globalThis.customElements.define(AutofillOverlayElement.Button, AutofillInlineMenuButton); })(); }(); /******/ })() ;