Skip to content
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

#7618: increase managed storage delay and link extension immediately for CWS installs #7628

Merged
merged 17 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/background/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ 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";

// 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());

void initLocator();
void initMessengerLogging();
Expand Down
2 changes: 1 addition & 1 deletion src/background/deploymentUpdater.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ describe("updateDeployments", () => {
expect(jest.mocked(uninstallAllDeployments).mock.calls).toHaveLength(0);
expect(refreshRegistriesMock.mock.calls).toHaveLength(0);
expect(saveSettingsStateMock).toHaveBeenCalledTimes(0);
});
}, 10_000);

test("do not open options page on update if restricted-version flag not set", async () => {
isLinkedMock.mockResolvedValue(true);
Expand Down
2 changes: 1 addition & 1 deletion src/background/deploymentUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ export async function updateDeployments(): Promise<void> {
sso: false,
});

void browser.runtime.openOptionsPage();
await browser.runtime.openOptionsPage();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reason for it to be void because that's the standard behavior


return;
}
Expand Down
61 changes: 53 additions & 8 deletions src/background/installer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ import { getExtensionToken, getUserData, isLinked } from "@/auth/token";
import { isCommunityControlRoom } from "@/contrib/automationanywhere/aaUtils";
import { isEmpty } from "lodash";
import { expectContext } from "@/utils/expectContext";
import { readManagedStorage } from "@/store/enterprise/managedStorage";
import {
readManagedStorage,
isInitialized as isManagedStorageInitialized,
} from "@/store/enterprise/managedStorage";
import { Events } from "@/telemetry/events";

import { DEFAULT_SERVICE_URL, UNINSTALL_URL } from "@/urlConstants";
Expand All @@ -40,6 +43,35 @@ import { getExtensionConsoleUrl } from "@/utils/extensionUtils";
*/
let _availableVersion: string | null = null;

/**
* Returns true if this appears to be a Chrome Web Store install and/or the user has an app URL where they're
* authenticated so the extension can be linked.
*/
async function isLikelyEndUserInstall(): Promise<boolean> {
// Query existing app/CWS tabs: https://developer.chrome.com/docs/extensions/reference/api/tabs#method-query
// `browser.tabs.query` supports https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns
const likelyOnboardingTabs = await browser.tabs.query({
// Can't use SERVICE_URL directly because it contains a port number during development, resulting in an
// invalid URL match pattern
url: [
// Setup page is page before sending user to the CWS
new URL("setup", DEFAULT_SERVICE_URL).href,
// Base page is extension linking page. Needs path to be a valid URL match pattern
new URL("", DEFAULT_SERVICE_URL).href,
// Known CWS URLs: https://docs.pixiebrix.com/enterprise-it-setup/network-email-firewall-configuration
"https://chromewebstore.google.com/*",
"https://chrome.google.com/webstore/*",
],
});

// The CWS install URL differs based on the extension listing slug. So instead, only match on the runtime id.
return likelyOnboardingTabs.some(
(tab) =>
tab.url.includes(DEFAULT_SERVICE_URL) ||
tab.url.includes(browser.runtime.id),
);
}

/**
* Install handler to complete authentication configuration for the extension.
*/
Expand Down Expand Up @@ -127,7 +159,7 @@ export async function openInstallPage() {
active: true,
});
} else {
// Case 3: there's no Admin Console onboarding tab open
// Case 3: there's no Admin Console onboarding tab open.
//
// Open a new Admin Console tab which will automatically "links" the extension (by passing the native PixieBrix
// token to the extension).
Expand Down Expand Up @@ -199,18 +231,31 @@ export async function handleInstall({
// XXX: under what conditions could onInstalled fire, but the extension is already linked? Is this the case during
// development/loading an update of the extension from the file system?
if (!(await isLinked())) {
// PERFORMANCE: readManagedStorageByKey waits up to 2 seconds for managed storage to be available. Shouldn't be
// notice-able for end-user relative to the extension download/install time
const { ssoUrl, partnerId, controlRoomUrl, disableLoginTab } =
await readManagedStorage();
// If an end-user appears to be installing, jump to linking directly vs. waiting for readManagedStorage because
// readManagedStorage will wait until a timeout for managed storage to be available.
if (!isManagedStorageInitialized() && (await isLikelyEndUserInstall())) {
console.debug("Skipping readManagedStorage for end-user install");

await openInstallPage();
return;
}

// Reminder: readManagedStorage waits up to 4.5 seconds for managed storage to be available
const {
ssoUrl,
partnerId,
controlRoomUrl,
disableLoginTab,
managedOrganizationId,
} = await readManagedStorage();

if (disableLoginTab) {
// IT manager has disabled the login tab
return;
}

if (ssoUrl) {
// Don't launch the SSO page automatically. The SSO flow will be launched by deploymentUpdater.ts:updateDeployments
if (ssoUrl || managedOrganizationId) {
// Don't launch the page automatically. The SSO flow will be launched by deploymentUpdater.ts:updateDeployments
return;
}

Expand Down
Loading
Loading