diff --git a/apps/browser/index.html b/apps/browser/index.html
new file mode 100644
index 00000000000..14df9466a05
--- /dev/null
+++ b/apps/browser/index.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Bitwarden
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/browser/performance-mark.js b/apps/browser/performance-mark.js
new file mode 100644
index 00000000000..910c7a4b19c
--- /dev/null
+++ b/apps/browser/performance-mark.js
@@ -0,0 +1,2 @@
+console.log("html-loaded");
+performance.mark("html-loaded");
diff --git a/apps/browser/src/popup/main.ts b/apps/browser/src/popup/main.ts
index dadd7917b99..6a79f7e1dfd 100644
--- a/apps/browser/src/popup/main.ts
+++ b/apps/browser/src/popup/main.ts
@@ -23,6 +23,7 @@ if (process.env.ENV === "production") {
}
function init() {
+ performance.mark("angular-bootstrap-start");
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
platformBrowserDynamic().bootstrapModule(AppModule, { preserveWhitespaces: true });
diff --git a/apps/browser/src/popup/services/init.service.ts b/apps/browser/src/popup/services/init.service.ts
index 069ebf4020d..5c2c6a3af2f 100644
--- a/apps/browser/src/popup/services/init.service.ts
+++ b/apps/browser/src/popup/services/init.service.ts
@@ -28,6 +28,7 @@ export class InitService {
) {}
init() {
+ performance.mark("init-start");
return async () => {
await this.sdkLoadService.load();
await this.stateService.init({ runMigrations: false }); // Browser background is responsible for migrations
@@ -56,6 +57,7 @@ export class InitService {
}
this.setupVaultPopupHeartbeat();
+ performance.mark("init-end");
};
}
diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts
index 12952a69c79..d9318322df7 100644
--- a/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts
+++ b/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts
@@ -100,6 +100,7 @@ export class VaultV2Component implements OnInit, AfterViewInit, OnDestroy {
private cipherService: CipherService,
private dialogService: DialogService,
) {
+ performance.mark("vault-v2-ctor-start");
combineLatest([
this.vaultPopupItemsService.emptyVault$,
this.vaultPopupItemsService.noFilteredResults$,
diff --git a/apps/browser/src/vault/popup/services/vault-popup-items.service.ts b/apps/browser/src/vault/popup/services/vault-popup-items.service.ts
index 8e0711abb1e..83ba14b9369 100644
--- a/apps/browser/src/vault/popup/services/vault-popup-items.service.ts
+++ b/apps/browser/src/vault/popup/services/vault-popup-items.service.ts
@@ -177,6 +177,8 @@ export class VaultPopupItemsService {
shareReplay({ refCount: false, bufferSize: 1 }),
);
+ hasMarked = false;
+
/**
* List of all remaining ciphers that are not currently suggested for autofill or marked as favorite.
* Ciphers are sorted by name.
@@ -193,6 +195,18 @@ export class VaultPopupItemsService {
(cipher) => !autoFillCiphers.includes(cipher) && !favoriteCiphers.includes(cipher),
),
),
+ tap((ciphers) => {
+ if (ciphers.length === 0 || this.hasMarked) {
+ return;
+ }
+
+ if (!this.hasMarked) {
+ this.hasMarked = true;
+ }
+
+ performance.mark("vault-v2-ciphers-available");
+ console.log("Ciphers available", ciphers);
+ }),
shareReplay({ refCount: false, bufferSize: 1 }),
);
diff --git a/console.log.js b/console.log.js
new file mode 100644
index 00000000000..c2594e49086
--- /dev/null
+++ b/console.log.js
@@ -0,0 +1,24 @@
+console.log(
+ `Popup triggered -> HTML loaded: ${Math.round(
+ performance.measure("", {}, "html-loaded").duration,
+ )} ms\n` +
+ `Popup triggered -> Angular bootstrap start: ${Math.round(
+ performance.measure("", {}, "angular-bootstrap-start").duration,
+ )} ms\n` +
+ `Popup triggered -> InitService start: ${Math.round(
+ performance.measure("", {}, "init-start").duration,
+ )} ms\n` +
+ // `Popup triggered -> cipher decryption start: ${Math.round(
+ // performance.measure("", {}, "cipher-decryption-start").duration
+ // )} ms\n` +
+ // `Popup triggered -> cipher decryption end: ${Math.round(
+ // performance.measure("", {}, "cipher-decryption-end").duration
+ // )} ms\n` +
+ `Popup triggered -> VaultV2Component constructor start: ${Math.round(
+ performance.measure("", {}, "vault-v2-ctor-start").duration,
+ )} ms\n` +
+ `Popup triggered -> VaultPopupItemsService first emission: ${Math.round(
+ performance.measure("", {}, "vault-v2-ciphers-available").duration,
+ )} ms\n` +
+ ``,
+);
diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts
index da205cb2b0e..35460726204 100644
--- a/libs/common/src/vault/services/cipher.service.ts
+++ b/libs/common/src/vault/services/cipher.service.ts
@@ -406,6 +406,10 @@ export class CipherService implements CipherServiceAbstraction {
return await this.getDecryptedCiphers();
}
+ // if (!(window as any).markedCipherDecryptionStart) {
+ // performance.mark("cipher-decryption-start");
+ // (window as any).markedCipherDecryptionStart = true;
+ // }
const activeUserId = await firstValueFrom(this.stateProvider.activeUserId$);
if (activeUserId == null) {
@@ -420,6 +424,11 @@ export class CipherService implements CipherServiceAbstraction {
await this.setDecryptedCipherCache(newDecCiphers, activeUserId);
await this.setFailedDecryptedCiphers(failedCiphers, activeUserId);
+ // if (!(window as any).markedCipherDecryptionEnd) {
+ // performance.mark("cipher-decryption-end");
+ // (window as any).markedCipherDecryptionEnd = true;
+ // }
+
return newDecCiphers;
}