diff --git a/jslib b/jslib index 91b73fa777..64bc115109 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 91b73fa77727a12c788c00eef4f32065c23b6314 +Subproject commit 64bc115109f40ac92b42af980024e36f90df6285 diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 79ca58563e..af284dde2b 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -1807,5 +1807,11 @@ }, "personalVaultExportPolicyInEffect": { "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." } } diff --git a/src/background/contextMenus.background.ts b/src/background/contextMenus.background.ts index f690d28320..b0fa7097d2 100644 --- a/src/background/contextMenus.background.ts +++ b/src/background/contextMenus.background.ts @@ -30,7 +30,7 @@ export default class ContextMenusBackground { if (info.menuItemId === 'generate-password') { await this.generatePasswordToClipboard(); } else if (info.menuItemId === 'copy-identifier') { - await this.getClickedElement(); + await this.getClickedElement(info.frameId); } else if (info.parentMenuItemId === 'autofill' || info.parentMenuItemId === 'copy-username' || info.parentMenuItemId === 'copy-password' || @@ -47,13 +47,13 @@ export default class ContextMenusBackground { this.passwordGenerationService.addHistory(password); } - private async getClickedElement() { + private async getClickedElement(frameId: number) { const tab = await BrowserApi.getTabFromCurrentWindow(); if (tab == null) { return; } - BrowserApi.tabSendMessageData(tab, 'getClickedElement'); + BrowserApi.tabSendMessage(tab, { command: 'getClickedElement' }, { frameId: frameId }); } private async cipherAction(info: any) { diff --git a/src/background/main.background.ts b/src/background/main.background.ts index 1671946e11..4a813f191c 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -147,7 +147,8 @@ export default class MainBackground { constructor() { // Services this.messagingService = new BrowserMessagingService(); - this.platformUtilsService = new BrowserPlatformUtilsService(this.messagingService, + this.storageService = new BrowserStorageService(); + this.platformUtilsService = new BrowserPlatformUtilsService(this.messagingService, this.storageService, (clipboardValue, clearMs) => { if (this.systemService != null) { this.systemService.clearClipboard(clipboardValue, clearMs); @@ -166,7 +167,6 @@ export default class MainBackground { return promise.then(result => result.response === 'unlocked'); } }); - this.storageService = new BrowserStorageService(); this.secureStorageService = new BrowserStorageService(); this.i18nService = new I18nService(BrowserApi.getUILanguage(window)); this.cryptoFunctionService = new WebCryptoFunctionService(window, this.platformUtilsService); diff --git a/src/content/autofill.css b/src/content/autofill.css index e32a6f278e..453556777c 100644 --- a/src/content/autofill.css +++ b/src/content/autofill.css @@ -26,6 +26,10 @@ } } +span[data-bwautofill].com-bitwarden-browser-animated-fill { + display: inline-block; +} + .com-bitwarden-browser-animated-fill { animation: bitwardenfill 200ms ease-in-out 0ms 1; -webkit-animation: bitwardenfill 200ms ease-in-out 0ms 1; diff --git a/src/content/autofill.js b/src/content/autofill.js index b4aa58397b..260350a3ea 100644 --- a/src/content/autofill.js +++ b/src/content/autofill.js @@ -38,6 +38,7 @@ 5. Remove fakeTested prop. 6. Rename com.agilebits.* stuff to com.bitwarden.* 7. Remove "some useful globals" on window + 8. Add ability to autofill span[data-bwautofill] elements */ function collect(document, undefined) { @@ -103,6 +104,11 @@ return el; default: + // START MODIFICATION + if (!el.type && el.tagName.toLowerCase() === 'span') { + return el.innerText; + } + // END MODIFICATION return el.value; } } @@ -268,8 +274,16 @@ addProp(field, 'htmlClass', getElementAttrValue(el, 'class')); addProp(field, 'tabindex', getElementAttrValue(el, 'tabindex')); addProp(field, 'title', getElementAttrValue(el, 'title')); + // START MODIFICATION addProp(field, 'userEdited', !!el.dataset['com.browser.browser.userEdited']); + + var elTagName = el.tagName.toLowerCase(); + addProp(field, 'tagName', elTagName); + + if (elTagName === 'span') { + return field; + } // END MODIFICATION if ('hidden' != toLowerString(el.type)) { @@ -555,7 +569,8 @@ var els = []; try { var elsList = theDoc.querySelectorAll('input:not([type="hidden"]):not([type="submit"]):not([type="reset"])' + - ':not([type="button"]):not([type="image"]):not([type="file"]):not([data-bwignore]), select'); + ':not([type="button"]):not([type="image"]):not([type="file"]):not([data-bwignore]), select, ' + + 'span[data-bwautofill]'); els = Array.prototype.slice.call(elsList); } catch (e) { } @@ -809,6 +824,12 @@ break; default: el.value == op || doAllFillOperations(el, function (theEl) { + // START MODIFICATION + if (!theEl.type && theEl.tagName.toLowerCase() === 'span') { + theEl.innerText = op; + return; + } + // END MODIFICATION theEl.value = op; }); } @@ -932,6 +953,11 @@ currentEl = currentEl === document; } } + // START MODIFICATION + if (el && !el.type && el.tagName.toLowerCase() === 'span') { + return true; + } + // END MODIFICATION return currentEl ? -1 !== 'email text password number tel url'.split(' ').indexOf(el.type || '') : false; } @@ -942,7 +968,10 @@ return null; } try { - var elements = Array.prototype.slice.call(selectAllFromDoc('input, select, button')); + // START MODIFICATION + var elements = Array.prototype.slice.call(selectAllFromDoc('input, select, button, ' + + 'span[data-bwautofill]')); + // END MODIFICATION var filteredElements = elements.filter(function (o) { return o.opid == theOpId; }); diff --git a/src/content/contextMenuHandler.ts b/src/content/contextMenuHandler.ts index e4be3aa1a8..5d6b1c0a0b 100644 --- a/src/content/contextMenuHandler.ts +++ b/src/content/contextMenuHandler.ts @@ -1,25 +1,46 @@ const inputTags = ['input', 'textarea', 'select']; +const labelTags = ['label', 'span']; const attributes = ['id', 'name', 'label-aria', 'placeholder']; +const invalidElement = chrome.i18n.getMessage('copyCustomFieldNameInvalidElement'); +const noUniqueIdentifier = chrome.i18n.getMessage('copyCustomFieldNameNotUnique'); + let clickedEl: HTMLElement = null; // Find the best attribute to be used as the Name for an element in a custom field. function getClickedElementIdentifier() { if (clickedEl == null) { - return 'Unable to identify clicked element.'; + return invalidElement; } - if (!inputTags.includes(clickedEl.nodeName.toLowerCase())) { - return 'Invalid element type.'; + const clickedTag = clickedEl.nodeName.toLowerCase(); + let inputEl = null; + + // Try to identify the input element (which may not be the clicked element) + if (labelTags.includes(clickedTag)) { + let inputId = null; + if (clickedTag === 'label') { + inputId = clickedEl.getAttribute('for'); + } else { + inputId = clickedEl.closest('label')?.getAttribute('for'); + } + + inputEl = document.getElementById(inputId); + } else { + inputEl = clickedEl; + } + + if (inputEl == null || !inputTags.includes(inputEl.nodeName.toLowerCase())) { + return invalidElement; } for (const attr of attributes) { - const attributeValue = clickedEl.getAttribute(attr); + const attributeValue = inputEl.getAttribute(attr); const selector = '[' + attr + '="' + attributeValue + '"]'; if (!isNullOrEmpty(attributeValue) && document.querySelectorAll(selector)?.length === 1) { return attributeValue; } } - return 'No unique identifier found.'; + return noUniqueIdentifier; } function isNullOrEmpty(s: string) { diff --git a/src/models/autofillField.ts b/src/models/autofillField.ts index 0223e50c07..236fe81577 100644 --- a/src/models/autofillField.ts +++ b/src/models/autofillField.ts @@ -21,4 +21,5 @@ export default class AutofillField { autoCompleteType: string; selectInfo: any; maxLength: number; + tagName: string; } diff --git a/src/notification/bar.html b/src/notification/bar.html index 533e0deeb6..0b0b29417c 100644 --- a/src/notification/bar.html +++ b/src/notification/bar.html @@ -16,10 +16,16 @@
+<<<<<<< HEAD X +======= + +>>>>>>> a3876db30bdfb5ac42bda44ec02a728a52ae149c
diff --git a/src/popup/accounts/lock.component.html b/src/popup/accounts/lock.component.html index 173487f001..1b7da04eae 100644 --- a/src/popup/accounts/lock.component.html +++ b/src/popup/accounts/lock.component.html @@ -23,11 +23,11 @@ class="monospaced" [(ngModel)]="masterPassword" required appInputVerbatim>
- - +
@@ -38,11 +38,11 @@

- {{'logOut' | i18n}} +

diff --git a/src/popup/accounts/login.component.html b/src/popup/accounts/login.component.html index 0e760197ad..6f0434b89f 100644 --- a/src/popup/accounts/login.component.html +++ b/src/popup/accounts/login.component.html @@ -28,11 +28,11 @@ class="monospaced" [(ngModel)]="masterPassword" required appInputVerbatim>
- - +
diff --git a/src/popup/accounts/register.component.html b/src/popup/accounts/register.component.html index e9fd86bcad..4bc4ebc801 100644 --- a/src/popup/accounts/register.component.html +++ b/src/popup/accounts/register.component.html @@ -36,11 +36,11 @@ [appAutofocus]="email !== ''" appInputVerbatim (input)="updatePasswordStrength()">
- - +
@@ -64,11 +64,11 @@ appInputVerbatim>
- - +
diff --git a/src/popup/accounts/set-password.component.html b/src/popup/accounts/set-password.component.html index 8d72439088..da26956a83 100644 --- a/src/popup/accounts/set-password.component.html +++ b/src/popup/accounts/set-password.component.html @@ -43,11 +43,11 @@ (input)="updatePasswordStrength()" appInputVerbatim>
- - +
@@ -74,11 +74,11 @@ autocomplete="new-password">
- - +
diff --git a/src/popup/accounts/two-factor-options.component.html b/src/popup/accounts/two-factor-options.component.html index f9405d4837..15ad88013f 100644 --- a/src/popup/accounts/two-factor-options.component.html +++ b/src/popup/accounts/two-factor-options.component.html @@ -10,14 +10,14 @@
diff --git a/src/popup/accounts/two-factor.component.html b/src/popup/accounts/two-factor.component.html index 5eaa1c122e..7026339ac3 100644 --- a/src/popup/accounts/two-factor.component.html +++ b/src/popup/accounts/two-factor.component.html @@ -73,7 +73,7 @@

{{'webAuthnNewTab' | i18n}}

- +

- {{'useAnotherTwoStepMethod' | i18n}} +

- +

diff --git a/src/popup/accounts/update-temp-password.component.html b/src/popup/accounts/update-temp-password.component.html index 91ce4d5cbf..608e7214c8 100644 --- a/src/popup/accounts/update-temp-password.component.html +++ b/src/popup/accounts/update-temp-password.component.html @@ -36,11 +36,11 @@ appInputVerbatim (input)="updatePasswordStrength()">
- - +
@@ -62,11 +62,11 @@ appInputVerbatim>
- - +
diff --git a/src/popup/components/cipher-row.component.html b/src/popup/components/cipher-row.component.html index 818e44c1b8..91aa472d42 100644 --- a/src/popup/components/cipher-row.component.html +++ b/src/popup/components/cipher-row.component.html @@ -1,4 +1,4 @@ -
@@ -20,4 +20,4 @@ - + diff --git a/src/popup/components/password-reprompt.component.html b/src/popup/components/password-reprompt.component.html index 0033cdd286..24354cb16e 100644 --- a/src/popup/components/password-reprompt.component.html +++ b/src/popup/components/password-reprompt.component.html @@ -12,11 +12,11 @@ class="monospaced" [(ngModel)]="masterPassword" required appAutofocus>
- - +
diff --git a/src/popup/components/pop-out.component.html b/src/popup/components/pop-out.component.html index 1c34a1c762..2e8d5581c2 100644 --- a/src/popup/components/pop-out.component.html +++ b/src/popup/components/pop-out.component.html @@ -1,5 +1,5 @@ - diff --git a/src/popup/components/send-list.component.html b/src/popup/components/send-list.component.html index 7862cd640e..cbedd7fbe9 100644 --- a/src/popup/components/send-list.component.html +++ b/src/popup/components/send-list.component.html @@ -1,4 +1,4 @@ -
@@ -47,4 +47,4 @@
-
+ diff --git a/src/popup/components/set-pin.component.html b/src/popup/components/set-pin.component.html index 8513011282..c9a0126a8a 100644 --- a/src/popup/components/set-pin.component.html +++ b/src/popup/components/set-pin.component.html @@ -14,11 +14,11 @@ class="monospaced" [(ngModel)]="pin" required appInputVerbatim cdkFocusInitial>
- - +
diff --git a/src/popup/generator/password-generator-history.component.html b/src/popup/generator/password-generator-history.component.html index f2d93bc27f..26c9610888 100644 --- a/src/popup/generator/password-generator-history.component.html +++ b/src/popup/generator/password-generator-history.component.html @@ -1,6 +1,6 @@
- @@ -9,7 +9,7 @@ {{'passwordHistory' | i18n}}
-
@@ -26,10 +26,10 @@
- - +
diff --git a/src/popup/generator/password-generator.component.html b/src/popup/generator/password-generator.component.html index bb5f255231..6986210e94 100644 --- a/src/popup/generator/password-generator.component.html +++ b/src/popup/generator/password-generator.component.html @@ -19,10 +19,10 @@
- {{'regeneratePassword' | i18n}} - {{'copyPassword' | i18n}} + +
diff --git a/src/popup/scss/box.scss b/src/popup/scss/box.scss index 2bf1c5078b..d3f40f07e8 100644 --- a/src/popup/scss/box.scss +++ b/src/popup/scss/box.scss @@ -307,7 +307,8 @@ margin-top: 5px; } - > a { + > a, + > button { padding: 8px 8px 8px 4px; margin: 0; @@ -322,6 +323,12 @@ padding-left: 10px; } + &.box-content-row-newmulti { + @include themify($themes) { + color: themed('primaryColor'); + } + } + &.box-content-row-checkbox, &.box-content-row-input, &.box-content-row-slider { label, .row-label { font-size: $font-size-base; @@ -518,7 +525,6 @@ justify-content: center; align-items: center; min-width: 34px; - height: 100%; margin-left: -5px; @include themify($themes) { diff --git a/src/popup/scss/buttons.scss b/src/popup/scss/buttons.scss index 1be16c912e..e1c3b375cd 100644 --- a/src/popup/scss/buttons.scss +++ b/src/popup/scss/buttons.scss @@ -69,7 +69,8 @@ width: 100%; } - &.link { + &.link, + &.neutral { border: none !important; background: none !important; @@ -86,3 +87,15 @@ } } } + +button.box-content-row { + display: block; + width: 100%; + text-align: left; +} + +button { + border: none; + background: transparent; + color: inherit; +} \ No newline at end of file diff --git a/src/popup/scss/pages.scss b/src/popup/scss/pages.scss index f3287b1760..57b422bb39 100644 --- a/src/popup/scss/pages.scss +++ b/src/popup/scss/pages.scss @@ -50,20 +50,24 @@ app-home { color: themed('mutedColor'); } - span { - visibility: hidden; + &:not(:hover):not(:focus) { + span { + clip: rect(0 0 0 0); + clip-path: inset(50%); + height: 1px; + overflow: hidden; + position: absolute; + white-space: nowrap; + width: 1px; + } } - &:hover { + &:hover, &:focus { text-decoration: none; @include themify($themes) { color: themed('primaryColor'); } - - span { - visibility: visible; - } } } } diff --git a/src/popup/send/efflux-dates.component.html b/src/popup/send/efflux-dates.component.html index 57dc270244..b7b35f3a46 100644 --- a/src/popup/send/efflux-dates.component.html +++ b/src/popup/send/efflux-dates.component.html @@ -46,9 +46,9 @@
- +
diff --git a/src/popup/send/send-add-edit.component.html b/src/popup/send/send-add-edit.component.html index 3dcbbe1429..10499559e8 100644 --- a/src/popup/send/send-add-edit.component.html +++ b/src/popup/send/send-add-edit.component.html @@ -155,11 +155,11 @@ class="monospaced" [(ngModel)]="password" appInputVerbatim [readonly]="disableSend">
- - +
@@ -204,7 +204,7 @@ diff --git a/src/popup/send/send-groupings.component.html b/src/popup/send/send-groupings.component.html index 959ee3c37a..34bc2f1bfe 100644 --- a/src/popup/send/send-groupings.component.html +++ b/src/popup/send/send-groupings.component.html @@ -8,7 +8,7 @@
-
@@ -22,7 +22,7 @@

{{'noItemsInList' | i18n}}

-
@@ -32,22 +32,22 @@ {{'types' | i18n}}
diff --git a/src/popup/send/send-type.component.html b/src/popup/send/send-type.component.html index 7fe28aacfc..d489e5f3a5 100644 --- a/src/popup/send/send-type.component.html +++ b/src/popup/send/send-type.component.html @@ -11,7 +11,7 @@
-
@@ -24,7 +24,7 @@

{{'noItemsInList' | i18n}}

-
diff --git a/src/popup/services/services.module.ts b/src/popup/services/services.module.ts index 4c6967d154..1e6248f61c 100644 --- a/src/popup/services/services.module.ts +++ b/src/popup/services/services.module.ts @@ -63,6 +63,8 @@ import { StateService } from 'jslib-common/services/state.service'; import { PopupSearchService } from './popup-search.service'; import { PopupUtilsService } from './popup-utils.service'; +import { ThemeType } from 'jslib-common/enums/themeType'; + function getBgService(service: string) { return (): T => { const page = BrowserApi.getBackgroundPage(); @@ -96,17 +98,17 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ await stateService.save(ConstantsService.disableBadgeCounterKey, await storageService.get(ConstantsService.disableBadgeCounterKey)); - let theme = await storageService.get(ConstantsService.themeKey); - if (theme == null) { - theme = await platformUtilsService.getDefaultSystemTheme(); - - platformUtilsService.onDefaultSystemThemeChange(sysTheme => { - window.document.documentElement.classList.remove('theme_light', 'theme_dark'); - window.document.documentElement.classList.add('theme_' + sysTheme); - }); - } - window.document.documentElement.classList.add('locale_' + i18nService.translationLocale); - window.document.documentElement.classList.add('theme_' + theme); + const htmlEl = window.document.documentElement; + const theme = await platformUtilsService.getEffectiveTheme(); + htmlEl.classList.add('theme_' + theme); + platformUtilsService.onDefaultSystemThemeChange(async sysTheme => { + const bwTheme = await storageService.get(ConstantsService.themeKey); + if (bwTheme == null || bwTheme === ThemeType.System) { + htmlEl.classList.remove('theme_' + ThemeType.Light, 'theme_' + ThemeType.Dark); + htmlEl.classList.add('theme_' + sysTheme); + } + }); + htmlEl.classList.add('locale_' + i18nService.translationLocale); } }; } diff --git a/src/popup/settings/excluded-domains.component.html b/src/popup/settings/excluded-domains.component.html index 7a10449282..50bc0a856e 100644 --- a/src/popup/settings/excluded-domains.component.html +++ b/src/popup/settings/excluded-domains.component.html @@ -16,9 +16,9 @@
- +
- - +
- {{'newUri' | i18n}} - +
- - +
diff --git a/src/popup/settings/folder-add-edit.component.html b/src/popup/settings/folder-add-edit.component.html index d7e6f9ea56..9ebdeb7ab3 100644 --- a/src/popup/settings/folder-add-edit.component.html +++ b/src/popup/settings/folder-add-edit.component.html @@ -24,7 +24,7 @@ diff --git a/src/popup/settings/folders.component.html b/src/popup/settings/folders.component.html index 6b12b47d59..6becefcf38 100644 --- a/src/popup/settings/folders.component.html +++ b/src/popup/settings/folders.component.html @@ -9,7 +9,7 @@ {{'folders' | i18n}}
-
@@ -17,8 +17,8 @@
- {{f.name}} +
diff --git a/src/popup/settings/options.component.ts b/src/popup/settings/options.component.ts index 5b94c15110..8ff25e0c27 100644 --- a/src/popup/settings/options.component.ts +++ b/src/popup/settings/options.component.ts @@ -3,6 +3,7 @@ import { OnInit, } from '@angular/core'; +import { ThemeType } from 'jslib-common/enums/themeType'; import { UriMatchType } from 'jslib-common/enums/uriMatchType'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; @@ -44,10 +45,10 @@ export class OptionsComponent implements OnInit { private stateService: StateService, private totpService: TotpService, i18nService: I18nService) { this.themeOptions = [ { name: i18nService.t('default'), value: null }, - { name: i18nService.t('light'), value: 'light' }, - { name: i18nService.t('dark'), value: 'dark' }, - { name: 'Nord', value: 'nord' }, - { name: i18nService.t('solarizedDark'), value: 'solarizedDark' }, + { name: i18nService.t('light'), value: ThemeType.Light }, + { name: i18nService.t('dark'), value: ThemeType.Dark }, + { name: 'Nord', value: ThemeType.Nord }, + { name: i18nService.t('solarizedDark'), value: ThemeType.SolarizedDark }, ]; this.uriMatchOptions = [ { name: i18nService.t('baseDomain'), value: UriMatchType.Domain }, diff --git a/src/popup/settings/settings.component.html b/src/popup/settings/settings.component.html index 262b4f1a48..66df2da28f 100644 --- a/src/popup/settings/settings.component.html +++ b/src/popup/settings/settings.component.html @@ -48,16 +48,16 @@
-
{{'lockNow' | i18n}}
-
- +
@@ -70,41 +70,41 @@
-
{{'changeMasterPassword' | i18n}}
-
- + diff --git a/src/popup/vault/add-edit-custom-fields.component.html b/src/popup/vault/add-edit-custom-fields.component.html index 843fde75d0..4fe2eae422 100644 --- a/src/popup/vault/add-edit-custom-fields.component.html +++ b/src/popup/vault/add-edit-custom-fields.component.html @@ -8,9 +8,9 @@
- +
@@ -28,11 +28,11 @@
- - +
@@ -41,9 +41,9 @@
- +
- {{'newUri' | i18n}} - +
@@ -301,17 +301,17 @@
-
{{'attachments' | i18n}}
-
- +
@@ -359,7 +359,7 @@
diff --git a/src/popup/vault/attachments.component.html b/src/popup/vault/attachments.component.html index 44c776b9ef..a1fb60d8e4 100644 --- a/src/popup/vault/attachments.component.html +++ b/src/popup/vault/attachments.component.html @@ -28,7 +28,7 @@ {{a.sizeName}}
-
@@ -42,14 +42,14 @@ {{'collections' | i18n}}
@@ -58,7 +58,7 @@

{{'noItemsInList' | i18n}}

-
diff --git a/src/popup/vault/groupings.component.html b/src/popup/vault/groupings.component.html index 7474459f57..32cefbe75b 100644 --- a/src/popup/vault/groupings.component.html +++ b/src/popup/vault/groupings.component.html @@ -8,7 +8,7 @@
-
@@ -19,7 +19,7 @@

{{'noItemsInList' | i18n}}

- +
@@ -40,31 +40,31 @@ 4
@@ -81,7 +81,7 @@ {{folderCount}}
@@ -101,7 +101,7 @@ {{nestedCollections.length}}
@@ -129,7 +129,7 @@ {{deletedCount}}
diff --git a/src/popup/vault/password-history.component.html b/src/popup/vault/password-history.component.html index 6072d2613c..83eed5671c 100644 --- a/src/popup/vault/password-history.component.html +++ b/src/popup/vault/password-history.component.html @@ -20,10 +20,10 @@
- - +
diff --git a/src/popup/vault/view-custom-fields.component.html b/src/popup/vault/view-custom-fields.component.html index 2987b4e130..8c3c1853b4 100644 --- a/src/popup/vault/view-custom-fields.component.html +++ b/src/popup/vault/view-custom-fields.component.html @@ -20,17 +20,17 @@ diff --git a/src/popup/vault/view.component.html b/src/popup/vault/view.component.html index c08b0cbb83..9603f8af4a 100644 --- a/src/popup/vault/view.component.html +++ b/src/popup/vault/view.component.html @@ -29,10 +29,10 @@
- - +
@@ -54,15 +54,15 @@ - - - +
- - +
@@ -103,15 +103,15 @@ {{cipher.card.number}}
@@ -129,15 +129,15 @@ {{cipher.card.code}}
@@ -198,14 +198,14 @@ @@ -229,19 +229,19 @@ {{'attachments' | i18n}}
diff --git a/src/services/autofill.service.ts b/src/services/autofill.service.ts index 1298727b5a..d50813cc43 100644 --- a/src/services/autofill.service.ts +++ b/src/services/autofill.service.ts @@ -306,7 +306,11 @@ export default class AutofillService implements AutofillServiceInterface { }); pageDetails.fields.forEach((field: any) => { - if (filledFields.hasOwnProperty(field.opid) || !field.viewable) { + if (filledFields.hasOwnProperty(field.opid)) { + return; + } + + if (!field.viewable && field.tagName !== 'span') { return; } @@ -459,6 +463,10 @@ export default class AutofillService implements AutofillServiceInterface { const fillFields: { [id: string]: AutofillField; } = {}; pageDetails.fields.forEach((f: any) => { + if (this.forCustomFieldsOnly(f)) { + return; + } + if (this.isExcludedType(f.type, ExcludedAutofillTypes)) { return; } @@ -691,6 +699,10 @@ export default class AutofillService implements AutofillServiceInterface { const fillFields: { [id: string]: AutofillField; } = {}; pageDetails.fields.forEach((f: any) => { + if (this.forCustomFieldsOnly(f)) { + return; + } + if (this.isExcludedType(f.type, ExcludedAutofillTypes)) { return; } @@ -928,6 +940,10 @@ export default class AutofillService implements AutofillServiceInterface { mustBeEmpty: boolean, fillNewPassword: boolean) { const arr: AutofillField[] = []; pageDetails.fields.forEach(f => { + if (this.forCustomFieldsOnly(f)) { + return; + } + const isPassword = f.type === 'password'; const valueIsLikePassword = (value: string) => { if (value == null) { @@ -976,6 +992,10 @@ export default class AutofillService implements AutofillServiceInterface { let usernameField: AutofillField = null; for (let i = 0; i < pageDetails.fields.length; i++) { const f = pageDetails.fields[i]; + if (this.forCustomFieldsOnly(f)) { + continue; + } + if (f.elementNumber >= passwordField.elementNumber) { break; } @@ -1152,8 +1172,14 @@ export default class AutofillService implements AutofillServiceInterface { if (field.maxLength && value && value.length > field.maxLength) { value = value.substr(0, value.length); } - fillScript.script.push(['click_on_opid', field.opid]); - fillScript.script.push(['focus_by_opid', field.opid]); + if (field.tagName !== 'span') { + fillScript.script.push(['click_on_opid', field.opid]); + fillScript.script.push(['focus_by_opid', field.opid]); + } fillScript.script.push(['fill_by_opid', field.opid, value]); } + + private forCustomFieldsOnly(field: AutofillField): boolean { + return field.tagName === 'span'; + } } diff --git a/src/services/browserPlatformUtils.service.spec.ts b/src/services/browserPlatformUtils.service.spec.ts index a56feabb14..0d7a7a2666 100644 --- a/src/services/browserPlatformUtils.service.spec.ts +++ b/src/services/browserPlatformUtils.service.spec.ts @@ -2,6 +2,8 @@ import BrowserPlatformUtilsService from './browserPlatformUtils.service'; import { DeviceType } from 'jslib-common/enums/deviceType'; +const platformUtilsFactory = () => new BrowserPlatformUtilsService(null, null, null, null); + describe('Browser Utils Service', () => { describe('getBrowser', () => { const originalUserAgent = navigator.userAgent; @@ -27,7 +29,7 @@ describe('Browser Utils Service', () => { value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36', }); - const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null); + const browserPlatformUtilsService = platformUtilsFactory(); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.ChromeExtension); }); @@ -37,7 +39,7 @@ describe('Browser Utils Service', () => { value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0', }); - const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null); + const browserPlatformUtilsService = platformUtilsFactory(); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.FirefoxExtension); }); @@ -52,7 +54,7 @@ describe('Browser Utils Service', () => { value: {}, }); - const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null); + const browserPlatformUtilsService = platformUtilsFactory(); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.OperaExtension); }); @@ -62,7 +64,7 @@ describe('Browser Utils Service', () => { value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.74 Safari/537.36 Edg/79.0.309.43', }); - const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null); + const browserPlatformUtilsService = platformUtilsFactory(); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.EdgeExtension); }); @@ -77,7 +79,7 @@ describe('Browser Utils Service', () => { value: true, }); - const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null); + const browserPlatformUtilsService = platformUtilsFactory(); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.SafariExtension); Object.defineProperty(window, 'safariAppExtension', { @@ -92,7 +94,7 @@ describe('Browser Utils Service', () => { value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.97 Safari/537.36 Vivaldi/1.94.1008.40', }); - const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null); + const browserPlatformUtilsService = platformUtilsFactory(); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.VivaldiExtension); }); }); diff --git a/src/services/browserPlatformUtils.service.ts b/src/services/browserPlatformUtils.service.ts index 509a9c9f71..8a3a2d0cd3 100644 --- a/src/services/browserPlatformUtils.service.ts +++ b/src/services/browserPlatformUtils.service.ts @@ -2,9 +2,13 @@ import { BrowserApi } from '../browser/browserApi'; import { SafariApp } from '../browser/safariApp'; import { DeviceType } from 'jslib-common/enums/deviceType'; +import { ThemeType } from 'jslib-common/enums/themeType'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; +import { StorageService } from 'jslib-common/abstractions/storage.service'; + +import { ConstantsService } from 'jslib-common/services/constants.service'; const DialogPromiseExpiration = 600000; // 10 minutes @@ -16,7 +20,7 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService private deviceCache: DeviceType = null; private prefersColorSchemeDark = window.matchMedia('(prefers-color-scheme: dark)'); - constructor(private messagingService: MessagingService, + constructor(private messagingService: MessagingService, private storageService: StorageService, private clipboardWriteCallback: (clipboardValue: string, clearMs: number) => void, private biometricCallback: () => Promise) { } @@ -317,13 +321,22 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService return false; } - getDefaultSystemTheme(): Promise<'light' | 'dark'> { - return Promise.resolve(this.prefersColorSchemeDark.matches ? 'dark' : 'light'); + getDefaultSystemTheme(): Promise { + return Promise.resolve(this.prefersColorSchemeDark.matches ? ThemeType.Dark : ThemeType.Light); } - onDefaultSystemThemeChange(callback: ((theme: 'light' | 'dark') => unknown)) { + onDefaultSystemThemeChange(callback: ((theme: ThemeType.Light | ThemeType.Dark) => unknown)) { this.prefersColorSchemeDark.addEventListener('change', ({ matches }) => { - callback(matches ? 'dark' : 'light'); + callback(matches ? ThemeType.Dark : ThemeType.Light); }); } + + async getEffectiveTheme() { + const theme = await this.storageService.get(ConstantsService.themeKey); + if (theme == null || theme === ThemeType.System) { + return this.getDefaultSystemTheme(); + } else { + return theme; + } + } }