et the entitlement if not available. this.#setEntitlement(null); return { isEnrolledAndEntitled: false, error: data.error }; } this.#setEntitlement(data.entitlement); return { isEnrolledAndEntitled: true }; }; this.#runningPromise = enrollAndEntitle().finally(() => { this.#runningPromise = null; }); return this.#runningPromise; } // This method is static because we don't want to change the internal state // of the singleton. static async #maybeEnrollAndEntitle() { let isLinked = false; try { isLinked = await lazy.IPProtectionService.guardian.isLinkedToGuardian( /* only cache: */ false ); } catch (error) { // If not linked, it's not an issue. } if (isLinked) { // Linked does not mean enrolled: it could be that the link comes from a // previous MozillaVPN subscription. Let's see if `fetchUserInfo` is able // to obtain the entitlement. const { status, entitlement } = await lazy.IPProtectionService.guardian.fetchUserInfo(); if (status === 200) { return { entitlement }; } } try { const enrollment = await lazy.IPProtectionService.guardian.enroll(); if (!enrollment?.ok) { return { entitlement: null, error: enrollment?.error }; } } catch (error) { return { enrollment: null, error: error?.message }; } const { status, entitlement, error } = await lazy.IPProtectionService.guardian.fetchUserInfo(); lazy.logConsole.debug("Entitlement:", { status, entitlement, error }); // If we see an error during the READY state, let's trigger an error state. if (error || !entitlement || status != 200) { return { entitlement: null, error: error || `Status: ${status}` }; } return { entitlement }; } #setEntitlement(entitlement) { this.#entitlement = entitlement; lazy.IPPStartupCache.storeEntitlement(this.#entitlement); lazy.IPProtectionService.updateState(); this.dispatchEvent( new CustomEvent("IPPEnrollAndEntitleManager:StateChanged", { bubbles: true, composed: true, }) ); } get isEnrolledAndEntitled() { return !!this.#entitlement; } /** * Checks if a user has upgraded. * * @returns {boolean} */ get hasUpgraded() { return this.#entitlement?.subscribed; } /** * Checks if the entitlement exists and it contains a UUID */ get hasEntitlementUid() { return !!this.#entitlement?.uid; } /** * Checks if we have the entitlement */ get hasEntitlement() { return !!this.#entitlement; } /** * Checks if we're running the Alpha variant based on * available features */ get isAlpha() { return ( !this.#entitlement?.autostart && !this.#entitlement?.website_inclusion && !this.#entitlement?.location_controls ); } async refetchEntitlement() { await this.maybeEnrollAndEntitle(true); } resetEntitlement() { this.#setEntitlement(null); } } const IPPEnrollAndEntitleManager = new IPPEnrollAndEntitleManagerSingleton(); export { IPPEnrollAndEntitleManager }; PK