Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(firefox): implement frame.goto / frame.waitForNavigation (#3992)
Some corner cases regarding iframes being detached during navigation are not yet supported.
- Loading branch information
1 parent
f0fba56
commit 89d0f1e
Showing
6 changed files
with
234 additions
and
208 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
115 changes: 115 additions & 0 deletions
115
experimental/puppeteer-firefox/lib/NavigationWatchdog.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
const {helper} = require('./helper'); | ||
const {Events} = require('./Events'); | ||
|
||
/** | ||
* @internal | ||
*/ | ||
class NextNavigationWatchdog { | ||
constructor(session, navigatedFrame) { | ||
this._navigatedFrame = navigatedFrame; | ||
this._promise = new Promise(x => this._resolveCallback = x); | ||
this._navigation = null; | ||
this._eventListeners = [ | ||
helper.addEventListener(session, 'Page.navigationStarted', this._onNavigationStarted.bind(this)), | ||
helper.addEventListener(session, 'Page.sameDocumentNavigation', this._onSameDocumentNavigation.bind(this)), | ||
]; | ||
} | ||
|
||
promise() { | ||
return this._promise; | ||
} | ||
|
||
navigation() { | ||
return this._navigation; | ||
} | ||
|
||
_onNavigationStarted(params) { | ||
if (params.frameId === this._navigatedFrame._frameId) { | ||
this._navigation = { | ||
navigationId: params.navigationId, | ||
url: params.url, | ||
}; | ||
this._resolveCallback(); | ||
} | ||
} | ||
|
||
_onSameDocumentNavigation(params) { | ||
if (params.frameId === this._navigatedFrame._frameId) { | ||
this._navigation = { | ||
navigationId: null, | ||
}; | ||
this._resolveCallback(); | ||
} | ||
} | ||
|
||
dispose() { | ||
helper.removeEventListeners(this._eventListeners); | ||
} | ||
} | ||
|
||
/** | ||
* @internal | ||
*/ | ||
class NavigationWatchdog { | ||
constructor(session, navigatedFrame, networkManager, targetNavigationId, targetURL, firedEvents) { | ||
this._navigatedFrame = navigatedFrame; | ||
this._targetNavigationId = targetNavigationId; | ||
this._firedEvents = firedEvents; | ||
this._targetURL = targetURL; | ||
|
||
this._promise = new Promise(x => this._resolveCallback = x); | ||
this._navigationRequest = null; | ||
|
||
const check = this._checkNavigationComplete.bind(this); | ||
this._eventListeners = [ | ||
helper.addEventListener(session, 'Page.eventFired', check), | ||
helper.addEventListener(session, 'Page.frameAttached', check), | ||
helper.addEventListener(session, 'Page.frameDetached', check), | ||
helper.addEventListener(session, 'Page.navigationStarted', check), | ||
helper.addEventListener(session, 'Page.navigationCommitted', check), | ||
helper.addEventListener(session, 'Page.navigationAborted', this._onNavigationAborted.bind(this)), | ||
helper.addEventListener(networkManager, Events.NetworkManager.Request, this._onRequest.bind(this)), | ||
]; | ||
check(); | ||
} | ||
|
||
_onRequest(request) { | ||
if (request.frame() !== this._navigatedFrame || !request.isNavigationRequest()) | ||
return; | ||
this._navigationRequest = request; | ||
} | ||
|
||
navigationResponse() { | ||
return this._navigationRequest ? this._navigationRequest.response() : null; | ||
} | ||
|
||
_checkNavigationComplete() { | ||
if (this._navigatedFrame._lastCommittedNavigationId === this._targetNavigationId | ||
&& checkFiredEvents(this._navigatedFrame, this._firedEvents)) { | ||
this._resolveCallback(null); | ||
} | ||
|
||
function checkFiredEvents(frame, firedEvents) { | ||
for (const subframe of frame._children) { | ||
if (!checkFiredEvents(subframe, firedEvents)) | ||
return false; | ||
} | ||
return firedEvents.every(event => frame._firedEvents.has(event)); | ||
} | ||
} | ||
|
||
_onNavigationAborted(params) { | ||
if (params.frameId === this._navigatedFrame._frameId && params.navigationId === this._targetNavigationId) | ||
this._resolveCallback(new Error('Navigation to ' + this._targetURL + ' failed: ' + params.errorText)); | ||
} | ||
|
||
promise() { | ||
return this._promise; | ||
} | ||
|
||
dispose() { | ||
helper.removeEventListeners(this._eventListeners); | ||
} | ||
} | ||
|
||
module.exports = {NavigationWatchdog, NextNavigationWatchdog}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.