Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
soundofspace committed Sep 10, 2024
1 parent 88ca082 commit 6aae3b9
Show file tree
Hide file tree
Showing 19 changed files with 531 additions and 56 deletions.
3 changes: 3 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
source_url "https://raw.githubusercontent.com/cachix/devenv/95f329d49a8a5289d31e0982652f7058a189bfca/direnvrc" "sha256-d+8cBpDfDBj41inrADaJt+bDWhOktwslgoP5YiGJ1v0="

use devenv
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@ browserstack.err
agent/mitm-socket/dist
connect
/real-user-agents/local.log
# Devenv
.devenv*
devenv.local.nix

# direnv
.direnv

# pre-commit
.pre-commit-config.yaml
8 changes: 5 additions & 3 deletions agent/main/injected-scripts/PaintEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ declare global {
}
}

declare const runtimeFunction: string;
// callback binding
const eventsCallback = window[runtimeFunction] as unknown as (data: string) => void;
declare const callbackName: string;
declare const callback: (name: string, data: string) => void;
const eventsCallback = (data: string) => {
callback(callbackName, data);
};

class PaintEvents {
onEventCallbackFn: (event: IDomPaintEvent, timestamp: number, url: string) => void;
Expand Down
5 changes: 4 additions & 1 deletion agent/main/lib/Agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import { IHooksProvider } from '@ulixee/unblocked-specification/agent/hooks/IHoo
import IEmulationProfile, {
IEmulationOptions,
} from '@ulixee/unblocked-specification/plugin/IEmulationProfile';
import { IUnblockedPluginClass, PluginConfigs } from '@ulixee/unblocked-specification/plugin/IUnblockedPlugin';
import {
IUnblockedPluginClass,
PluginConfigs,
} from '@ulixee/unblocked-specification/plugin/IUnblockedPlugin';
import { nanoid } from 'nanoid';
import env from '../env';
import ICommandMarker from '../interfaces/ICommandMarker';
Expand Down
6 changes: 6 additions & 0 deletions agent/main/lib/BrowserContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import FrameOutOfProcess from './FrameOutOfProcess';
import CookieParam = Protocol.Network.CookieParam;
import TargetInfo = Protocol.Target.TargetInfo;
import CreateBrowserContextRequest = Protocol.Target.CreateBrowserContextRequest;
import { WebsocketSession } from './WebsocketSession';

const { log } = Log(module);

Expand Down Expand Up @@ -68,6 +69,7 @@ export default class BrowserContext
}

public isIncognito = true;
public readonly websocketSession: WebsocketSession;

public readonly idTracker = {
navigationId: 0,
Expand All @@ -87,6 +89,7 @@ export default class BrowserContext

private readonly events = new EventSubscriber();


constructor(browser: Browser, isIncognito: boolean, options?: IBrowserContextCreateOptions) {
super();
this.browser = browser;
Expand All @@ -102,6 +105,7 @@ export default class BrowserContext
this.devtoolsSessionLogger.subscribeToDevtoolsMessages(this.browser.devtoolsSession, {
sessionType: 'browser',
});
this.websocketSession = new WebsocketSession();
}

public async open(): Promise<void> {
Expand All @@ -125,6 +129,7 @@ export default class BrowserContext
this.logger = this.logger.createChild(module, {
browserContextId,
});
await this.websocketSession.initialize();
}

async newPage(options?: IPageCreateOptions): Promise<Page> {
Expand Down Expand Up @@ -344,6 +349,7 @@ export default class BrowserContext
this.resources.cleanup();
this.events.close();
this.emit('close');
this.websocketSession.close();
this.devtoolsSessionLogger.close();
this.removeAllListeners();
this.cleanup();
Expand Down
2 changes: 1 addition & 1 deletion agent/main/lib/BrowserProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default class BrowserProcess extends TypedEventEmitter<{ close: void }> {
private processEnv?: NodeJS.ProcessEnv,
) {
super();

bindFunctions(this);
this.launchedProcess = this.launch();
this.bindProcessEvents();
Expand Down
61 changes: 52 additions & 9 deletions agent/main/lib/Frame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ export default class Frame extends TypedEventEmitter<IFrameEvents> implements IF
private closedWithError: Error;
private isClosing = false;
private defaultContextCreated: Resolvable<void>;
private shouldRefreshContextIds = false;
private hasCreatedIsolate = false;
private readonly checkIfAttached: () => boolean;
private inPageCounter = 0;
private events = new EventSubscriber();
Expand Down Expand Up @@ -173,6 +175,7 @@ export default class Frame extends TypedEventEmitter<IFrameEvents> implements IF
activeContextIds: Set<number>,
): Promise<void> {
if (this.devtoolsSession === devtoolsSession) return;
this.shouldRefreshContextIds = true;

this.devtoolsSession = devtoolsSession;
this.activeContextIds = activeContextIds;
Expand Down Expand Up @@ -227,6 +230,17 @@ export default class Frame extends TypedEventEmitter<IFrameEvents> implements IF
this.waitForActiveContextId(false),
]);

// const [isolatedContextId, defaultContextId] = await Promise.all([
// this.#framesManager.getExecutionContextId({ frameId: this.id, type: 'isolated' }),
// this.#framesManager.getExecutionContextId({ frameId: this.id, type: 'default' }),
// ]);

// const [isolatedContextId, defaultContextId] =
// await this.#framesManager.getExecutionContextIds([
// { frameId: this.id, type: 'isolated' },
// { frameId: this.id, type: 'default' },
// ]);

if (this.closedWithError || !this.devtoolsSession.isConnected()) return;

await Promise.all(
Expand Down Expand Up @@ -278,6 +292,8 @@ export default class Frame extends TypedEventEmitter<IFrameEvents> implements IF
const startOrigin = this.securityOrigin;
const isolateFromWebPageEnvironment = options?.isolateFromWebPageEnvironment ?? false;
const contextId = await this.waitForActiveContextId(isolateFromWebPageEnvironment);

// contextId = 67890;
try {
if (!contextId) {
const notFound: any = new Error('Could not find a valid context for this request');
Expand Down Expand Up @@ -691,9 +707,15 @@ export default class Frame extends TypedEventEmitter<IFrameEvents> implements IF
const hasLoaderError = await this.navigationLoadersById[loaderId]?.navigationResolver;
if (hasLoaderError instanceof Error) throw hasLoaderError;

if (!this.getActiveContextId(false)) {
await this.waitForDefaultContext();
}
// if (!this.getActiveContextId(false)) {
// await this.waitForDefaultContext();
// }

await this.#framesManager.getExecutionContextId({
frameId: this.id,
type: 'default',
refresh: this.shouldRefreshContextIds,
});
}

public onLifecycleEvent(name: string, timestamp?: number, pageLoaderId?: string): void {
Expand Down Expand Up @@ -786,18 +808,34 @@ export default class Frame extends TypedEventEmitter<IFrameEvents> implements IF
public async waitForActiveContextId(isolatedContext = true): Promise<number> {
if (!this.isAttached) throw new Error('Execution Context is not available in detached frame');

const existing = this.getActiveContextId(isolatedContext);
if (existing) return existing;

if (isolatedContext) {
if (isolatedContext && !this.hasCreatedIsolate) {
this.hasCreatedIsolate = true;
const context = await this.createIsolatedWorld();
// give one task to set up
await new Promise(setImmediate);
return context;
}

await this.waitForDefaultContext();
return this.getActiveContextId(isolatedContext);
const contextId = await this.#framesManager.getExecutionContextId({
frameId: this.id,
type: isolatedContext ? 'isolated' : 'default',
refresh: this.shouldRefreshContextIds,
});

this.shouldRefreshContextIds = false;
return contextId;
// const existing = this.getActiveContextId(isolatedContext);
// if (existing) return existing;

// if (isolatedContext) {
// const context = await this.createIsolatedWorld();
// // give one task to set up
// await new Promise(setImmediate);
// return context;
// }

// await this.waitForDefaultContext();
// return this.getActiveContextId(isolatedContext);
}

public canEvaluate(isolatedFromWebPageEnvironment: boolean): boolean {
Expand Down Expand Up @@ -883,6 +921,11 @@ export default class Frame extends TypedEventEmitter<IFrameEvents> implements IF
if (this.getActiveContextId(false)) return;

this.defaultContextCreated = new Resolvable<void>();

await Promise.all([
this.devtoolsSession.send('Runtime.enable'),
this.devtoolsSession.send('Runtime.disable'),
]);
// don't time out this event, we'll just wait for the page to shut down
await this.defaultContextCreated.promise.catch(err => {
if (err instanceof CanceledPromiseError) return;
Expand Down
Loading

0 comments on commit 6aae3b9

Please sign in to comment.