feat: enable subscription connections in web and dev
This commit is contained in:
@@ -30,6 +30,7 @@ const { attachChatGPTChild, trustedSender, chatGPTControl } = require("./chatgpt
|
||||
const { createSubscriptions, loadSubscriptionSDK } = require("./subscriptions.cjs");
|
||||
const { attachSubscriptionChild, subscriptionControl } = require("./subscription-ipc.cjs");
|
||||
const { desktopAPIHeaders } = require("./desktop-api.cjs");
|
||||
const { openWebSubscriptionBrowser } = require("./web-subscription-browser.cjs");
|
||||
const { randomBytes } = require("node:crypto");
|
||||
const { spawn } = require("node:child_process");
|
||||
const fs = require("node:fs");
|
||||
@@ -315,6 +316,7 @@ function createWindow(url) {
|
||||
contextIsolation: true,
|
||||
sandbox: true,
|
||||
nodeIntegration: false,
|
||||
...(process.env.LH_DEV_URL ? { additionalArguments: ["--lh-web-subscriptions"] } : {}),
|
||||
preload: path.join(__dirname, "preload.cjs"),
|
||||
},
|
||||
// Live-resize + first-paint flash (owner, 2026-09-17): during a resize
|
||||
@@ -700,6 +702,13 @@ async function main() {
|
||||
return subscriptionControl(command, subscriptions);
|
||||
});
|
||||
|
||||
// The dev shell has no browser tabs. Only a one-use action on its own
|
||||
// Next server may be resolved here; never accept an arbitrary external URL.
|
||||
ipcMain.handle("lh:subscriptions:web-browser", async (event, action) => {
|
||||
if (!devUrl || !trustedAppWindows.has(BrowserWindow.fromWebContents(event.sender)) || !trustedSender(event, new URL(url).origin, BrowserWindow)) throw new Error("Untrusted development request.");
|
||||
await openWebSubscriptionBrowser(action, new URL(url).origin, { openExternal: (target) => shell.openExternal(target) });
|
||||
});
|
||||
|
||||
installMenu();
|
||||
|
||||
// Auto-update (Wave C): wire the updater before the window so the
|
||||
|
||||
@@ -40,6 +40,10 @@ ipcRenderer.on("lh:open-settings", (_event, section) => {
|
||||
|
||||
contextBridge.exposeInMainWorld("lh", {
|
||||
platform: process.platform,
|
||||
...(process.argv?.includes("--lh-web-subscriptions") ? {
|
||||
subscriptionTransport: "web",
|
||||
openSubscriptionBrowser: (action) => ipcRenderer.invoke("lh:subscriptions:web-browser", action),
|
||||
} : {}),
|
||||
chatgpt: {
|
||||
status: () => ipcRenderer.invoke("lh:chatgpt:control", { op: "status" }),
|
||||
login: (id) => ipcRenderer.invoke("lh:chatgpt:control", { op: "login", id }),
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
/** Desktop-dev has no tabs. Resolve only an opaque action on its own Next
|
||||
* server, then open the owner-validated provider page outside the renderer.
|
||||
* The caller must authenticate its trusted app main frame first. */
|
||||
async function openWebSubscriptionBrowser(action, origin, { fetch: request = globalThis.fetch, openExternal }) {
|
||||
if (typeof action !== "string" || !/^\/api\/subscriptions\/browser\?id=[0-9a-f-]{36}$/.test(action)) throw new Error("Invalid sign-in action.");
|
||||
const response = await request(new URL(action, origin), {
|
||||
method: "POST", redirect: "manual", credentials: "omit",
|
||||
headers: { origin, "x-learnharness-subscriptions": "1" },
|
||||
signal: AbortSignal.timeout(15000),
|
||||
});
|
||||
const target = response.headers.get("location");
|
||||
if (response.status !== 303 || !target) throw new Error("Sign-in action expired.");
|
||||
const parsed = new URL(target);
|
||||
if (parsed.protocol !== "https:" || parsed.username || parsed.password) throw new Error("Invalid provider page.");
|
||||
await openExternal(target);
|
||||
}
|
||||
module.exports = { openWebSubscriptionBrowser };
|
||||
Reference in New Issue
Block a user