1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-10 05:30:01 +00:00

move the call to background

This commit is contained in:
Cy Okeke
2025-03-17 12:36:30 +01:00
parent c2f2c36856
commit 319d827859
3 changed files with 78 additions and 20 deletions

View File

@@ -78,7 +78,6 @@ import { ClientType } from "@bitwarden/common/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { BulkEncryptServiceImplementation } from "@bitwarden/common/key-management/crypto/services/bulk-encrypt.service.implementation";
import { EncryptServiceImplementation } from "@bitwarden/common/key-management/crypto/services/encrypt.service.implementation";
import { FallbackBulkEncryptService } from "@bitwarden/common/key-management/crypto/services/fallback-bulk-encrypt.service";
import { MultithreadEncryptServiceImplementation } from "@bitwarden/common/key-management/crypto/services/multithread-encrypt.service.implementation";
@@ -712,7 +711,6 @@ export default class MainBackground {
this.vaultTimeoutSettingsService,
);
// Initialize phishing detection services
const phishingApiService = new PhishingApiService(this.apiService);
PhishingDetectionService.initialize(
phishingApiService,
@@ -1334,23 +1332,10 @@ export default class MainBackground {
this.commandsBackground.init();
this.contextMenusBackground?.init();
this.idleBackground.init();
this.webRequestBackground?.startListening();
await this.webRequestBackground?.startListening();
this.syncServiceListener?.listener$().subscribe();
await this.autoSubmitLoginBackground.init();
// Set up phishing detection tab event listeners
const phishingDetectionService = new PhishingDetectionService();
phishingDetectionService.setupTabEventListeners();
if (
BrowserApi.isManifestVersion(2) &&
(await this.configService.getFeatureFlag(FeatureFlag.PM4154_BulkEncryptionService))
) {
await this.bulkEncryptService.setFeatureFlagEncryptService(
new BulkEncryptServiceImplementation(this.cryptoFunctionService, this.logService),
);
}
// If the user is logged out, switch to the next account
const active = await firstValueFrom(this.accountService.activeAccount$);
if (active != null) {

View File

@@ -5,7 +5,7 @@ export class PhishingApiService implements PhishingApiServiceAbstraction {
constructor(private apiService: ApiService) {}
async getKnownPhishingDomains(): Promise<string[]> {
const response = await this.apiService.send("GET", "/phishing/domains", null, true, true);
const response = await this.apiService.send("GET", "/phishing-domains", null, false, true);
return response as string[];
}
}

View File

@@ -13,13 +13,17 @@ export class PhishingDetectionService {
private static knownPhishingDomains = new Set<string>();
private static lastUpdateTime: number = 0;
private static readonly UPDATE_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
private static readonly RETRY_INTERVAL = 5 * 60 * 1000; // 5 minutes
private static readonly MAX_RETRIES = 3;
private static readonly STORAGE_KEY = "phishing_domains_cache";
private static phishingApiService: PhishingApiServiceAbstraction;
private static logService: LogService;
private static storageService: AbstractStorageService;
private static taskSchedulerService: TaskSchedulerService;
private static updateCacheSubscription: Subscription | null = null;
private static retrySubscription: Subscription | null = null;
private static isUpdating = false;
private static retryCount = 0;
static initialize(
phishingApiService: PhishingApiServiceAbstraction,
@@ -49,13 +53,19 @@ export class PhishingDetectionService {
// Set up periodic updates every 24 hours
this.setupPeriodicUpdates();
// Set up tab listener
this.setupTabEventListeners();
}
private static setupPeriodicUpdates() {
// Clean up any existing subscription
// Clean up any existing subscriptions
if (this.updateCacheSubscription) {
this.updateCacheSubscription.unsubscribe();
}
if (this.retrySubscription) {
this.retrySubscription.unsubscribe();
}
this.updateCacheSubscription = this.taskSchedulerService.setInterval(
ScheduledTaskNames.phishingDomainUpdate,
@@ -63,6 +73,39 @@ export class PhishingDetectionService {
);
}
private static scheduleRetry() {
// If we've exceeded max retries, stop retrying
if (this.retryCount >= this.MAX_RETRIES) {
this.logService.warning(
`Max retries (${this.MAX_RETRIES}) reached for phishing domain update. Will try again in ${this.UPDATE_INTERVAL / (1000 * 60 * 60)} hours.`,
);
this.retryCount = 0;
if (this.retrySubscription) {
this.retrySubscription.unsubscribe();
this.retrySubscription = null;
}
return;
}
// Clean up existing retry subscription if any
if (this.retrySubscription) {
this.retrySubscription.unsubscribe();
}
// Increment retry count
this.retryCount++;
// Schedule a retry in 5 minutes
this.retrySubscription = this.taskSchedulerService.setInterval(
ScheduledTaskNames.phishingDomainUpdate,
this.RETRY_INTERVAL,
);
this.logService.info(
`Scheduled retry ${this.retryCount}/${this.MAX_RETRIES} for phishing domain update in ${this.RETRY_INTERVAL / (1000 * 60)} minutes`,
);
}
private static async loadCachedDomains() {
try {
const cachedData = await this.storageService.get<{ domains: string[]; timestamp: number }>(
@@ -99,7 +142,9 @@ export class PhishingDetectionService {
this.isUpdating = true;
try {
this.logService.info("Starting phishing domains update...");
const domains = await PhishingDetectionService.phishingApiService.getKnownPhishingDomains();
this.logService.info("Received phishing domains response");
// Clear old domains to prevent memory leaks
PhishingDetectionService.knownPhishingDomains.clear();
@@ -119,8 +164,31 @@ export class PhishingDetectionService {
domains: Array.from(this.knownPhishingDomains),
timestamp: this.lastUpdateTime,
});
// Reset retry count and clear retry subscription on success
this.retryCount = 0;
if (this.retrySubscription) {
this.retrySubscription.unsubscribe();
this.retrySubscription = null;
}
this.logService.info(
`Successfully updated phishing domains cache with ${this.knownPhishingDomains.size} domains`,
);
} catch (error) {
PhishingDetectionService.logService.error("Failed to update phishing domains:", error);
this.logService.error("Error details:", error);
if (
error?.message?.includes("Access token not found") ||
error?.message?.includes("Failed to decode access token")
) {
this.logService.info(
"Authentication required for phishing domain update, will retry when authenticated",
);
this.scheduleRetry();
} else {
PhishingDetectionService.logService.error("Failed to update phishing domains:", error);
throw error;
}
} finally {
this.isUpdating = false;
}
@@ -131,9 +199,14 @@ export class PhishingDetectionService {
this.updateCacheSubscription.unsubscribe();
this.updateCacheSubscription = null;
}
if (this.retrySubscription) {
this.retrySubscription.unsubscribe();
this.retrySubscription = null;
}
this.knownPhishingDomains.clear();
this.lastUpdateTime = 0;
this.isUpdating = false;
this.retryCount = 0;
}
static async getActiveUrl(): Promise<string> {
@@ -150,7 +223,7 @@ export class PhishingDetectionService {
/*
This listener will check the URL when the tab has finished loading.
*/
setupTabEventListeners(): void {
private static setupTabEventListeners(): void {
BrowserApi.addListener(chrome.tabs.onUpdated, async (tabId, changeInfo, tab) => {
if (changeInfo.status === "complete") {
const activeUrl = await PhishingDetectionService.getActiveUrl();