Skip to content

Commit

Permalink
feat(core): add keepalive message and cli
Browse files Browse the repository at this point in the history
  • Loading branch information
blakebyrnes committed Aug 30, 2021
1 parent 2761689 commit 44caf22
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 13 deletions.
55 changes: 52 additions & 3 deletions client/lib/CoreSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { IJsPath } from 'awaited-dom/base/AwaitedPath';
import { loggerSessionIdNames } from '@ulixee/commons/lib/Logger';
import IHeroMeta from '@ulixee/hero-interfaces/IHeroMeta';
import IJsPathResult from '@ulixee/hero-interfaces/IJsPathResult';
import * as readline from 'readline';
import ShutdownHandler from '@ulixee/commons/lib/ShutdownHandler';
import CoreCommandQueue from './CoreCommandQueue';
import CoreEventHeap from './CoreEventHeap';
import CoreTab from './CoreTab';
Expand Down Expand Up @@ -38,7 +40,10 @@ export default class CoreSession implements IJsPathEventTarget {
private readonly connectionToCore: ConnectionToCore;
private commandId = 0;

constructor(sessionMeta: ISessionMeta & { sessionName: string }, connectionToCore: ConnectionToCore) {
constructor(
sessionMeta: ISessionMeta & { sessionName: string },
connectionToCore: ConnectionToCore,
) {
const { sessionId, sessionName } = sessionMeta;
this.sessionId = sessionId;
this.sessionName = sessionName;
Expand Down Expand Up @@ -100,7 +105,11 @@ export default class CoreSession implements IJsPathEventTarget {
meta: ISessionMeta;
prefetchedJsPaths: IJsPathResult[];
}>('Session.detachTab', tab.tabId, callSitePath, key);
const coreTab = new CoreTab({ ...meta, sessionName: this.sessionName }, this.connectionToCore, this);
const coreTab = new CoreTab(
{ ...meta, sessionName: this.sessionName },
this.connectionToCore,
this,
);
this.frozenTabsById.set(meta.tabId, coreTab);
return {
coreTab,
Expand All @@ -117,7 +126,12 @@ export default class CoreSession implements IJsPathEventTarget {
for (const tab of this.frozenTabsById.values()) {
await tab.flush();
}
await this.commandQueue.run('Session.close');
const result = await this.commandQueue.run<{ didKeepAlive: boolean; message: string }>(
'Session.close',
);
if (result?.didKeepAlive === true) {
await this.showSessionKeepAlivePrompt(result.message);
}
} finally {
process.nextTick(() => this.connectionToCore.closeSession(this));
loggerSessionIdNames.delete(this.sessionId);
Expand Down Expand Up @@ -148,4 +162,39 @@ export default class CoreSession implements IJsPathEventTarget {
await this.eventHeap.removeListener(jsPath, eventType, listenerFn);
}
}

private showSessionKeepAlivePrompt(message: string): Promise<void> {
if (/yes|1|true/i.test(process.env.HERO_CLI_NOPROMPT)) return;

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

readline.emitKeypressEvents(process.stdin);
process.stdin.setEncoding('utf8');
if (process.stdin.isTTY) process.stdin.setRawMode(true);

process.stdout.write(`\n\n${message}\n\nPress Q or kill the CLI to exit and close Chrome:`);

ShutdownHandler.register(() => this.terminate());

return new Promise<void>(resolve => {
process.stdin.on('keypress', async (chunk, key) => {
if (key.name.toLowerCase() === 'q') {
await this.terminate();
rl.close();
resolve();
}
});
process.once('beforeExit', () => {
rl.close();
resolve();
});
});
}

private terminate(): Promise<void> {
return this.commandQueue.run('Session.terminate');
}
}
21 changes: 17 additions & 4 deletions core/connections/ConnectionToClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export default class ConnectionToClient extends TypedEventEmitter<{
['Core.logUnhandledError', 'logUnhandledError'],
['Session.create', 'createSession'],
['Session.close', 'closeSession'],
['Session.terminate', 'terminateSession'],
['Session.configure', 'configure'],
['Session.detachTab', 'detachTab'],
['Session.flush', 'flush'],
Expand Down Expand Up @@ -232,16 +233,28 @@ export default class ConnectionToClient extends TypedEventEmitter<{
return this.getSessionMeta(tab);
}

public async closeSession(sessionMeta: ISessionMeta): Promise<void> {
public async closeSession(
sessionMeta: ISessionMeta,
): Promise<{ didKeepAlive: boolean; message?: string }> {
const result = { didKeepAlive: false, message: null };
const session = Session.get(sessionMeta.sessionId);
if (!session) return;
if (!session) return result;

// if this session is set to keep alive and core is closing,
if (session.options.sessionKeepAlive && !Core.isClosing) {
session.emit('kept-alive');
result.message = `This session has the "sessionKeepAlive" variable active. Your Chrome session will remain open until you terminate this Hero instance.`;
result.didKeepAlive = true;
session.emit('kept-alive', result);
removeEventListeners(this.sessionIds.get(session.id) ?? []);
return;
} else {
await session.close();
}
return result;
}

public async terminateSession(sessionMeta: ISessionMeta): Promise<void> {
const session = Session.get(sessionMeta.sessionId);
if (!session) return;

await session.close();
}
Expand Down
2 changes: 1 addition & 1 deletion core/lib/Session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default class Session extends TypedEventEmitter<{
closing: void;
closed: void;
resumed: void;
'kept-alive': void;
'kept-alive': { message: string };
'tab-created': { tab: Tab };
'all-tabs-closed': void;
'awaited-event': ICoreEventPayload;
Expand Down
5 changes: 4 additions & 1 deletion core/test/sessionResume.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,13 @@ describe('sessionResume tests when resume location is currentLocation', () => {
);
expect(playInteractionSpy).toHaveBeenCalledTimes(1);
await connectionToClient.closeSession({ sessionId });
if (i === 4) {
await connectionToClient.terminateSession({ sessionId });
}
}

expect(sessionCreatedFn).toHaveBeenCalledTimes(1);
expect(sessionClosedFn).toHaveBeenCalledTimes(0);
expect(sessionClosedFn).toHaveBeenCalledTimes(1);
expect(sessionKeptAliveFn).toHaveBeenCalledTimes(5);
expect(sessionResumedFn).toHaveBeenCalledTimes(4);

Expand Down
8 changes: 5 additions & 3 deletions mitm/lib/Http2SessionBinding.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Http2Session } from 'http2';
import { Log } from '@ulixee/commons/lib/Logger';
import logger from '@ulixee/commons/lib/Logger';
import { IBoundLog } from '@ulixee/commons/interfaces/ILog';
import { bindFunctions } from '@ulixee/commons/lib/utils';

const { log } = logger(module);

export default class Http2SessionBinding {
private logger: IBoundLog;

Expand All @@ -11,7 +13,7 @@ export default class Http2SessionBinding {
readonly serverSession: Http2Session,
logData: { sessionId: string } & any,
) {
this.logger = new Log(module, logData) as IBoundLog;
this.logger = log.createChild(module, logData);
bindFunctions(this);
this.bind();
}
Expand Down Expand Up @@ -80,7 +82,7 @@ export default class Http2SessionBinding {
this.logger.stats('Http2.goaway', {
code,
lastStreamID,
opaqueData,
opaqueData: opaqueData ? Buffer.from(opaqueData).toString() : undefined,
});
if (!this.clientSession || this.clientSession.destroyed) return;
this.clientSession.goaway(code);
Expand Down
12 changes: 11 additions & 1 deletion plugins/default-browser-emulator/lib/helpers/setScreensize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default async function setScreensize(
left: viewport.positionX,
top: viewport.positionY,
width: viewport.screenWidth,
height: viewport.screenHeight + 20,
height: viewport.screenHeight,
windowState: 'normal',
},
});
Expand All @@ -51,5 +51,15 @@ export default async function setScreensize(
}),
);
}
if (viewport.width === 0 || viewport.height === 0) {
promises.push(
devtools.send('Page.getLayoutMetrics').then(x => {
viewport.height = x.visualViewport.clientHeight;
viewport.width = x.visualViewport.clientWidth;
viewport.deviceScaleFactor = x.visualViewport.scale;
return viewport;
}),
);
}
await Promise.all(promises);
}

0 comments on commit 44caf22

Please sign in to comment.