-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#7784: skip waiting for managed storage after initial wait #7790
Changes from 11 commits
c48d40b
8dcf1dc
f2d1f7c
ea5e847
7196816
d23a4a0
dc1a0e0
f9dec79
185ca73
067213f
1884d36
671709f
009cdbf
5453e13
700b1fc
517a06e
9787f65
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,23 +47,13 @@ import { initRuntimeLogging } from "@/development/runtimeLogging"; | |
import initWalkthroughModalTrigger from "@/background/walkthroughModalTrigger"; | ||
import { initSidePanel } from "./sidePanel"; | ||
import initRestrictUnauthenticatedUrlAccess from "@/background/restrictUnauthenticatedUrlAccess"; | ||
import { | ||
initManagedStorage, | ||
watchDelayedStorageInitialization, | ||
} from "@/store/enterprise/managedStorage"; | ||
import { setPlatform } from "@/platform/platformContext"; | ||
import backgroundPlatform from "@/background/backgroundPlatform"; | ||
|
||
// The background "platform" currently is used to execute API requests from Google Sheets/Automation Anywhere. | ||
// In the future, it might also run other background tasks from mods (e.g., background intervals) | ||
setPlatform(backgroundPlatform); | ||
|
||
// Try to initialize managed storage as early as possible because it impacts background behavior | ||
// Call watchDelayedStorageInitialization to handle case where storage is not immediately available within timeout. | ||
// We might consider putting watchStorageInitialization in initManagedStorage, but having a non-terminating | ||
// interval complicates testing. | ||
void initManagedStorage().then(async () => watchDelayedStorageInitialization()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved to installer |
||
|
||
void initLocator(); | ||
void initMessengerLogging(); | ||
void initRuntimeLogging(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,15 +27,17 @@ import { isCommunityControlRoom } from "@/contrib/automationanywhere/aaUtils"; | |
import { isEmpty } from "lodash"; | ||
import { expectContext } from "@/utils/expectContext"; | ||
import { | ||
readManagedStorage, | ||
initManagedStorage, | ||
isInitialized as isManagedStorageInitialized, | ||
readManagedStorage, | ||
resetInitializationTimestamp as resetManagedStorageInitializationState, | ||
watchForDelayedStorageInitialization, | ||
} from "@/store/enterprise/managedStorage"; | ||
import { Events } from "@/telemetry/events"; | ||
|
||
import { DEFAULT_SERVICE_URL, UNINSTALL_URL } from "@/urlConstants"; | ||
|
||
import { CONTROL_ROOM_TOKEN_INTEGRATION_ID } from "@/integrations/constants"; | ||
import { getExtensionConsoleUrl } from "@/utils/extensionUtils"; | ||
import { oncePerSession } from "@/mv3/SessionStorage"; | ||
|
||
/** | ||
* The latest version of PixieBrix available in the Chrome Web Store, or null if the version hasn't been fetched. | ||
|
@@ -213,7 +215,7 @@ export async function requirePartnerAuth(): Promise<void> { | |
} | ||
|
||
// Exported for testing | ||
export async function handleInstall({ | ||
export async function showInstallPage({ | ||
reason, | ||
previousVersion, | ||
}: Runtime.OnInstalledDetailsType): Promise<void> { | ||
|
@@ -291,7 +293,9 @@ export async function handleInstall({ | |
} | ||
} | ||
|
||
function onUpdateAvailable({ version }: Runtime.OnUpdateAvailableDetailsType) { | ||
function setAvailableVersion({ | ||
version, | ||
}: Runtime.OnUpdateAvailableDetailsType): void { | ||
_availableVersion = version; | ||
} | ||
|
||
|
@@ -320,10 +324,38 @@ async function setUninstallURL(): Promise<void> { | |
await browser.runtime.setUninstallURL(url.href); | ||
} | ||
|
||
function initInstaller() { | ||
browser.runtime.onUpdateAvailable.addListener(onUpdateAvailable); | ||
browser.runtime.onInstalled.addListener(handleInstall); | ||
browser.runtime.onStartup.addListener(initTelemetry); | ||
// Using our own session value vs. webext-events because onExtensionStart has a 100ms delay | ||
// https://github.com/fregante/webext-events/blob/main/source/on-extension-start.ts#L56 | ||
// eslint-disable-next-line local-rules/persistBackgroundData -- using SessionMp via oncePerSession | ||
const initManagedStorageOnce = oncePerSession( | ||
"initManagedStorage", | ||
import.meta.url, | ||
async () => { | ||
await resetManagedStorageInitializationState(); | ||
await initManagedStorage(); | ||
void watchForDelayedStorageInitialization(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice. Very readable now |
||
}, | ||
); | ||
|
||
// eslint-disable-next-line local-rules/persistBackgroundData -- using SessionMp via oncePerSession | ||
const initTelemetryOnce = oncePerSession( | ||
"initTelemetry", | ||
import.meta.url, | ||
async () => { | ||
if (await isLinked()) { | ||
// Init telemetry is a no-op if not linked. So calling without being linked just delays the throttle | ||
await initTelemetry(); | ||
} | ||
}, | ||
); | ||
|
||
function initInstaller(): void { | ||
void initManagedStorageOnce(); | ||
void initTelemetryOnce(); | ||
|
||
browser.runtime.onInstalled.addListener(showInstallPage); | ||
browser.runtime.onUpdateAvailable.addListener(setAvailableVersion); | ||
|
||
dntConfig.onChanged(() => { | ||
void setUninstallURL(); | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,6 @@ | |
|
||
import { type JsonObject } from "type-fest"; | ||
import { compact, debounce, throttle, uniq } from "lodash"; | ||
import { isLinked } from "@/auth/authStorage"; | ||
import { getModComponentState } from "@/store/extensionsStorage"; | ||
import { | ||
getLinkedApiClient, | ||
|
@@ -305,8 +304,9 @@ async function collectUserSummary(): Promise<UserSummary> { | |
} | ||
|
||
async function init(): Promise<void> { | ||
if ((await isLinked()) && (await allowsTrack())) { | ||
const client = await getLinkedApiClient(); | ||
const client = await maybeGetLinkedApiClient(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix race condition |
||
|
||
if (client && (await allowsTrack())) { | ||
await client.post("/api/identify/", { | ||
uid: await getUUID(), | ||
data: await collectUserSummary(), | ||
|
@@ -321,7 +321,7 @@ export const initTelemetry = throttle(init, 30 * 60 * 1000, { | |
}); | ||
|
||
/** | ||
* @deprecated Only allowed in @/background files. Otherwise use: `import reportEvent from "@/telemetry/reportEvent"` | ||
* @deprecated Only allowed in @/background files. Otherwise, use: `import reportEvent from "@/telemetry/reportEvent"` | ||
*/ | ||
export async function recordEvent({ | ||
event, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,7 @@ import { expectContext } from "@/utils/expectContext"; | |
import { type OmitIndexSignature, type JsonValue } from "type-fest"; | ||
import { type ManualStorageKey } from "@/utils/storageUtils"; | ||
import { once } from "lodash"; | ||
import pMemoize from "p-memoize"; | ||
|
||
// Just like chrome.storage.session, this must be "global" | ||
// eslint-disable-next-line local-rules/persistBackgroundData -- MV2-only | ||
|
@@ -58,6 +59,19 @@ export class SessionMap<Value extends JsonValue> { | |
return `${this.key}::${this.url}::${secondaryKey}` as ManualStorageKey; | ||
} | ||
|
||
async has(secondaryKey: string): Promise<boolean> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
this.validateContext(); | ||
const rawStorageKey = this.getRawStorageKey(secondaryKey); | ||
if (!hasSession) { | ||
return storage.has(rawStorageKey); | ||
} | ||
|
||
const result = await browser.storage.session.get(rawStorageKey); | ||
// OK to use `undefined` because undefined is not a valid storage value | ||
// eslint-disable-next-line security/detect-object-injection -- `getRawStorageKey` ensures the format | ||
return result[rawStorageKey] !== undefined; | ||
} | ||
|
||
async get(secondaryKey: string): Promise<Value | undefined> { | ||
this.validateContext(); | ||
const rawStorageKey = this.getRawStorageKey(secondaryKey); | ||
|
@@ -113,3 +127,19 @@ export class SessionValue<Value extends OmitIndexSignature<JsonValue>> { | |
await this.map.set("#value", value); | ||
} | ||
} | ||
|
||
/** | ||
* Helper to run a method at most once per session from the background page. | ||
* @param key the SessionMap key | ||
* @param url the ImportMeta.url of the file | ||
* @param fn the function to run once per session | ||
*/ | ||
export const oncePerSession = ( | ||
key: string, | ||
url: string, | ||
fn: () => Promise<unknown>, | ||
) => | ||
pMemoize(fn, { | ||
// `fn` has no arguments, so only one value is stored | ||
cache: new SessionMap(key, url), | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accidentally left this in the other PR