Skip to content

Commit

Permalink
track navigations by loader id
Browse files Browse the repository at this point in the history
  • Loading branch information
sadym-chromium committed Dec 11, 2024
1 parent d3f1173 commit 6b71d29
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 66 deletions.
3 changes: 2 additions & 1 deletion src/bidiMapper/modules/context/BrowsingContextImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ export class BrowsingContextImpl {
}
this.#navigationTracker.frameNavigated(
params.frame.url + (params.frame.urlFragment ?? ''),
params.frame.loaderId,
);

// At the point the page is initialized, all the nested iframes from the
Expand Down Expand Up @@ -516,7 +517,7 @@ export class BrowsingContextImpl {
);
}
// The initial navigation is finished.
this.#navigationTracker.lifecycleEventLoad();
this.#navigationTracker.lifecycleEventLoad(params.loaderId);
this.#lifecycle.load.resolve();
break;
}
Expand Down
135 changes: 70 additions & 65 deletions src/bidiMapper/modules/context/NavigationTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ class NavigationState {
started = new Deferred<void>();
finished = new Deferred<NavigationEventName>();
url: string;
startedByUnloadHandler = false;
startedNavigating = false;
loaderId?: string;

constructor(url: string, browsingContextId: string) {
this.#browsingContextId = browsingContextId;
Expand All @@ -68,7 +67,7 @@ class NavigationState {
export class NavigationTracker {
readonly #eventManager: EventManager;
readonly #logger?: LoggerFn;
readonly #startedNavigatingLoaders = new Set<string>();
readonly #loaderIdToNavigationsMap = new Map<string, NavigationState>();

readonly #browsingContextId: string;
#currentNavigation: NavigationState;
Expand Down Expand Up @@ -105,7 +104,11 @@ export class NavigationTracker {
}

get currentNavigationId() {
return this.#currentNavigation.navigationId;
// TODO: what is expected here?
return (
this.#pendingNavigation?.navigationId ??
this.#currentNavigation.navigationId
);
}

get initialNavigation(): boolean {
Expand Down Expand Up @@ -176,7 +179,7 @@ export class NavigationTracker {
LogType.debugError,
`!!@@## Unexpectedly not started navigation ${navigation.navigationId} finished with ${eventName}`,
);
// return;
return;
}

if (
Expand Down Expand Up @@ -213,14 +216,31 @@ export class NavigationTracker {
this.#currentNavigation.url = url;
}

frameNavigated(url: string) {
frameNavigated(url: string, loaderId: string) {
this.#logger?.(LogType.debug, `Page.frameNavigated ${url}`);
this.#currentNavigation.url = url;
if (!this.#currentNavigation.started.isFinished) {
// Make sure the pending navigation is started, as `Page.frameStartedNavigating` is
// missing for `about:blank`.
this.#currentNavigation.started.resolve();

if (!this.#loaderIdToNavigationsMap.has(loaderId)) {
console.log(`!!@@## Unknown loader ${loaderId} is navigated`);
this.#logger?.(
LogType.debugError,
`!!@@## Unknown loader ${loaderId} is navigated`,
);
const navigation = this.#createNavigation(url);
this.#loaderIdToNavigationsMap.set(loaderId, navigation);
}

const navigation = this.#loaderIdToNavigationsMap.get(loaderId)!;
navigation.url = url;
// Make sure the pending navigation is started, as `Page.frameStartedNavigating` is
// missing for `about:blank`.
navigation.started.resolve();

if (navigation !== this.#currentNavigation) {
this.#currentNavigation.finished.resolve(
ChromiumBidi.BrowsingContext.EventNames.NavigationAborted,
);
}
this.#currentNavigation = navigation;
}

navigatedWithinDocument(
Expand All @@ -232,33 +252,33 @@ export class NavigationTracker {
`Page.navigatedWithinDocument ${url}, ${navigationType}`,
);

// Current navigation URL should be updated.
this.#currentNavigation.url = url;

if (navigationType !== 'fragment') {
return;
}

this.#logger?.(
LogType.debug,
`pending navigation: ${this.#pendingNavigation?.navigationId}`,
);

// Create a new pending navigation if none exists.
const pendingNavigation =
this.#pendingNavigation ?? this.createPendingNavigation(url);
const fragmentNavigation =
this.#pendingNavigation !== undefined &&
this.#pendingNavigation.loaderId === undefined
? this.#pendingNavigation
: this.#createNavigation(url);

this.#logger?.(
LogType.debug,
`pending navigation: ${pendingNavigation?.navigationId}`,
`fragmentNavigation: ${fragmentNavigation.navigationId}`,
);

// Finish ongoing navigation.
pendingNavigation.finished.resolve(
fragmentNavigation.finished.resolve(
ChromiumBidi.BrowsingContext.EventNames.FragmentNavigated,
);
// Fragment navigation should not override the cross-document and cannot be the
// current one.
this.#pendingNavigation = undefined;

if (fragmentNavigation === this.#pendingNavigation) {
// If the pending navigation was created by navigation command and en
this.#pendingNavigation = undefined;
}
}

frameRequestedNavigation(url: string) {
Expand All @@ -267,12 +287,13 @@ export class NavigationTracker {
this.createPendingNavigation(url);
}

lifecycleEventLoad() {
lifecycleEventLoad(loaderId: string) {
this.#logger?.(LogType.debug, 'lifecycleEventLoad');
this.#initialNavigation = false;
this.#currentNavigation.finished.resolve(
ChromiumBidi.BrowsingContext.EventNames.Load,
);

this.#loaderIdToNavigationsMap
.get(loaderId)
?.finished.resolve(ChromiumBidi.BrowsingContext.EventNames.Load);
}

failNavigation(navigation: NavigationState) {
Expand All @@ -288,6 +309,11 @@ export class NavigationTracker {
`finishCommandNavigation ${navigation.navigationId}, ${loaderId}`,
);

if (loaderId !== undefined) {
navigation.loaderId = loaderId;
this.#loaderIdToNavigationsMap.set(loaderId, navigation);
}

if (this.#currentNavigation !== navigation && loaderId !== undefined) {
// Missing loader ID means it's same-document navigation, so no need in starting or
// updating the current navigation.
Expand All @@ -298,54 +324,34 @@ export class NavigationTracker {
this.#initialNavigation = false;
this.#currentNavigation = navigation;
}
}

#activatePendingNavigation() {
if (this.#currentNavigation === this.#pendingNavigation) {
// TODO: remove.
console.log(`!!@@## Unexpectedly pending navigation is the current one`);
this.#logger?.(
LogType.debugError,
`!!@@## Unexpectedly pending navigation is the current one`,
);
} else {
this.#initialNavigation = false;

this.#currentNavigation.finished.resolve(
ChromiumBidi.BrowsingContext.EventNames.NavigationAborted,
);
this.#currentNavigation = this.#pendingNavigation!;
this.#currentNavigation.started.resolve();
if (this.#pendingNavigation === navigation) {
// Reset pending navigation if needed.
this.#pendingNavigation = undefined;
}
}

frameStartedNavigating(url: string, loaderId: string) {
this.#logger?.(LogType.debug, `frameStartedNavigating ${url}, ${loaderId}`);

if (this.#startedNavigatingLoaders.has(loaderId)) {
// The `frameStartedNavigating` can be duplicated due to its dependency on
// `Network.requestWillBeSent` event.
return;
}
this.#startedNavigatingLoaders.add(loaderId);

if (
this.#currentNavigation.startedByUnloadHandler &&
!this.#currentNavigation.startedNavigating
) {
// TODO
this.#currentNavigation.startedNavigating = true;
this.#currentNavigation.url = url;
if (this.#loaderIdToNavigationsMap.has(loaderId)) {
// TODO: remove.
console.log(`!!@@## frameStartedNavigating again, ${loaderId}`);
this.#logger?.(
LogType.debugError,
`!!@@## frameStartedNavigating again, ${loaderId}`,
);
return;
}

if (this.#pendingNavigation === undefined) {
this.createPendingNavigation(url);
}
this.#activatePendingNavigation();
this.#currentNavigation.startedNavigating = true;
this.#currentNavigation.url = url;

this.#pendingNavigation!.started.resolve();
this.#pendingNavigation!.url = url;

this.#pendingNavigation!.loaderId = loaderId;
this.#loaderIdToNavigationsMap.set(loaderId, this.#pendingNavigation!);
}

beforeunload() {
Expand All @@ -358,7 +364,6 @@ export class NavigationTracker {
);
return;
}
this.#activatePendingNavigation();
this.#currentNavigation.startedByUnloadHandler = true;
this.#pendingNavigation.started.resolve();
}
}

0 comments on commit 6b71d29

Please sign in to comment.