fix: show missing ffmpeg on persistent context / electron

This commit is contained in:
Max Schmitt 2024-12-09 17:38:31 -08:00
parent 081f455ee9
commit b65b55f840
7 changed files with 33 additions and 19 deletions

View file

@ -211,6 +211,10 @@ export class BidiBrowserContext extends BrowserContext {
return this._bidiPages().map(bidiPage => bidiPage._initializedPage).filter(Boolean) as Page[]; return this._bidiPages().map(bidiPage => bidiPage._initializedPage).filter(Boolean) as Page[];
} }
pagesOrErrors() {
return this._bidiPages().map(bidiPage => bidiPage.pageOrError());
}
async newPageDelegate(): Promise<PageDelegate> { async newPageDelegate(): Promise<PageDelegate> {
assertBrowserContextIsNotOwned(this); assertBrowserContextIsNotOwned(this);
const { context } = await this._browser._browserSession.send('browsingContext.create', { const { context } = await this._browser._browserSession.send('browsingContext.create', {

View file

@ -259,6 +259,7 @@ export abstract class BrowserContext extends SdkObject {
// BrowserContext methods. // BrowserContext methods.
abstract pages(): Page[]; abstract pages(): Page[];
abstract pagesOrErrors(): Promise<Page | Error>[];
abstract newPageDelegate(): Promise<PageDelegate>; abstract newPageDelegate(): Promise<PageDelegate>;
abstract addCookies(cookies: channels.SetNetworkCookie[]): Promise<void>; abstract addCookies(cookies: channels.SetNetworkCookie[]): Promise<void>;
abstract setGeolocation(geolocation?: types.Geolocation): Promise<void>; abstract setGeolocation(geolocation?: types.Geolocation): Promise<void>;
@ -358,29 +359,30 @@ export abstract class BrowserContext extends SdkObject {
this._timeoutSettings.setDefaultTimeout(timeout); this._timeoutSettings.setDefaultTimeout(timeout);
} }
async _loadDefaultContextAsIs(progress: Progress): Promise<Page[]> { async _loadDefaultContextAsIs(progress: Progress): Promise<Page> {
if (!this.pages().length) { if (!this.pagesOrErrors().length) {
const waitForEvent = helper.waitForEvent(progress, this, BrowserContext.Events.Page); const waitForEvent = helper.waitForEvent(progress, this, BrowserContext.Events.Page);
progress.cleanupWhenAborted(() => waitForEvent.dispose); progress.cleanupWhenAborted(() => waitForEvent.dispose);
const page = (await waitForEvent.promise) as Page; const page = await waitForEvent.promise as Page;
if (page._pageIsError) const pageOrError = await page._delegate.pageOrError();
throw page._pageIsError; if (pageOrError instanceof Error)
throw pageOrError;
} }
const pages = this.pages(); const pageOrError = await this.pagesOrErrors()[0];
if (pages[0]._pageIsError) if (pageOrError instanceof Error)
throw pages[0]._pageIsError; throw pageOrError;
await pages[0].mainFrame()._waitForLoadState(progress, 'load'); await pageOrError.mainFrame()._waitForLoadState(progress, 'load');
return pages; return pageOrError;
} }
async _loadDefaultContext(progress: Progress) { async _loadDefaultContext(progress: Progress) {
const pages = await this._loadDefaultContextAsIs(progress); const defaultPage = await this._loadDefaultContextAsIs(progress);
const browserName = this._browser.options.name; const browserName = this._browser.options.name;
if ((this._options.isMobile && browserName === 'chromium') || (this._options.locale && browserName === 'webkit')) { if ((this._options.isMobile && browserName === 'chromium') || (this._options.locale && browserName === 'webkit')) {
// Workaround for: // Workaround for:
// - chromium fails to change isMobile for existing page; // - chromium fails to change isMobile for existing page;
// - webkit fails to change locale for existing page. // - webkit fails to change locale for existing page.
const oldPage = pages[0]; const oldPage = defaultPage;
await this.newPage(progress.metadata); await this.newPage(progress.metadata);
await oldPage.close(progress.metadata); await oldPage.close(progress.metadata);
} }

View file

@ -368,6 +368,10 @@ export class CRBrowserContext extends BrowserContext {
return this._crPages().map(crPage => crPage._initializedPage).filter(Boolean) as Page[]; return this._crPages().map(crPage => crPage._initializedPage).filter(Boolean) as Page[];
} }
pagesOrErrors() {
return this._crPages().map(crPage => crPage.pageOrError());
}
async newPageDelegate(): Promise<PageDelegate> { async newPageDelegate(): Promise<PageDelegate> {
assertBrowserContextIsNotOwned(this); assertBrowserContextIsNotOwned(this);

View file

@ -432,6 +432,8 @@ class FrameSession {
this._firstNonInitialNavigationCommittedFulfill = f; this._firstNonInitialNavigationCommittedFulfill = f;
this._firstNonInitialNavigationCommittedReject = r; this._firstNonInitialNavigationCommittedReject = r;
}); });
// We do not always await this promise.
this._firstNonInitialNavigationCommittedPromise.catch(() => {});
} }
_isMainFrame(): boolean { _isMainFrame(): boolean {

View file

@ -271,6 +271,10 @@ export class FFBrowserContext extends BrowserContext {
return this._ffPages().map(ffPage => ffPage._initializedPage).filter(pageOrNull => !!pageOrNull) as Page[]; return this._ffPages().map(ffPage => ffPage._initializedPage).filter(pageOrNull => !!pageOrNull) as Page[];
} }
pagesOrErrors() {
return this._ffPages().map(ffPage => ffPage.pageOrError());
}
async newPageDelegate(): Promise<PageDelegate> { async newPageDelegate(): Promise<PageDelegate> {
assertBrowserContextIsNotOwned(this); assertBrowserContextIsNotOwned(this);
const { targetId } = await this._browser.session.send('Browser.newPage', { const { targetId } = await this._browser.session.send('Browser.newPage', {

View file

@ -164,7 +164,6 @@ export class Page extends SdkObject {
_clientRequestInterceptor: network.RouteHandler | undefined; _clientRequestInterceptor: network.RouteHandler | undefined;
_serverRequestInterceptor: network.RouteHandler | undefined; _serverRequestInterceptor: network.RouteHandler | undefined;
_ownedContext: BrowserContext | undefined; _ownedContext: BrowserContext | undefined;
_pageIsError: Error | undefined;
_video: Artifact | null = null; _video: Artifact | null = null;
_opener: Page | undefined; _opener: Page | undefined;
private _isServerSideOnly = false; private _isServerSideOnly = false;
@ -208,7 +207,7 @@ export class Page extends SdkObject {
// context/browser closure. Just ignore the page. // context/browser closure. Just ignore the page.
if (this._browserContext.isClosingOrClosed()) if (this._browserContext.isClosingOrClosed())
return; return;
this._setIsError(error); this._frameManager.createDummyMainFrameIfNeeded();
} }
this._initialized = true; this._initialized = true;
this.emitOnContext(contextEvent, this); this.emitOnContext(contextEvent, this);
@ -709,11 +708,6 @@ export class Page extends SdkObject {
await this._ownedContext.close(options); await this._ownedContext.close(options);
} }
private _setIsError(error: Error) {
this._pageIsError = error;
this._frameManager.createDummyMainFrameIfNeeded();
}
isClosed(): boolean { isClosed(): boolean {
return this._closedState === 'closed'; return this._closedState === 'closed';
} }

View file

@ -243,6 +243,10 @@ export class WKBrowserContext extends BrowserContext {
return this._wkPages().map(wkPage => wkPage._initializedPage).filter(pageOrNull => !!pageOrNull) as Page[]; return this._wkPages().map(wkPage => wkPage._initializedPage).filter(pageOrNull => !!pageOrNull) as Page[];
} }
pagesOrErrors() {
return this._wkPages().map(wkPage => wkPage.pageOrError());
}
async newPageDelegate(): Promise<PageDelegate> { async newPageDelegate(): Promise<PageDelegate> {
assertBrowserContextIsNotOwned(this); assertBrowserContextIsNotOwned(this);
const { pageProxyId } = await this._browser._browserSession.send('Playwright.createPage', { browserContextId: this._browserContextId }); const { pageProxyId } = await this._browser._browserSession.send('Playwright.createPage', { browserContextId: this._browserContextId });