diff --git a/src/chromium/crPage.ts b/src/chromium/crPage.ts index 270efec7d6..18857f5472 100644 --- a/src/chromium/crPage.ts +++ b/src/chromium/crPage.ts @@ -141,7 +141,7 @@ export class CRPage implements PageDelegate { if (options.userAgent || options.locale) promises.push(this._client.send('Emulation.setUserAgentOverride', { userAgent: options.userAgent || '', acceptLanguage: options.locale })); if (options.locale) - promises.push(this._client.send('Emulation.setLocaleOverride', { locale: options.locale })); + promises.push(emulateLocale(this._client, options.locale)); if (options.timezoneId) promises.push(emulateTimezone(this._client, options.timezoneId)); if (options.geolocation) @@ -608,10 +608,25 @@ function toRemoteObject(handle: js.JSHandle): Protocol.Runtime.RemoteObject { return handle._remoteObject as Protocol.Runtime.RemoteObject; } +async function emulateLocale(session: CRSession, locale: string) { + try { + await session.send('Emulation.setLocaleOverride', { locale }); + } catch (exception) { + // All pages in the same renderer share locale. All such pages belong to the same + // context and if locale is overridden for one of them its value is the same as + // we are trying to set so it's not a problem. + if (exception.message.includes('Another locale override is already in effect')) + return; + throw exception; + } +} + async function emulateTimezone(session: CRSession, timezoneId: string) { try { await session.send('Emulation.setTimezoneOverride', { timezoneId: timezoneId }); } catch (exception) { + if (exception.message.includes('Timezone override is already in effect')) + return; if (exception.message.includes('Invalid timezone')) throw new Error(`Invalid timezone ID: ${timezoneId}`); throw exception; diff --git a/test/emulation.spec.js b/test/emulation.spec.js index dac4726c51..a0928cfeee 100644 --- a/test/emulation.spec.js +++ b/test/emulation.spec.js @@ -289,6 +289,20 @@ module.exports.describe = function({testRunner, expect, playwright, headless, FF await context.close(); } }); + it('should work for multiple pages sharing same process', async({browser, server}) => { + const context = await browser.newContext({ timezoneId: 'Europe/Moscow' }); + const page = await context.newPage(); + await page.goto(server.EMPTY_PAGE); + let [popup] = await Promise.all([ + page.waitForEvent('popup'), + page.evaluate(url => { window.open(url); }, server.EMPTY_PAGE), + ]); + [popup] = await Promise.all([ + popup.waitForEvent('popup'), + popup.evaluate(url => { window.open(url); }, server.EMPTY_PAGE), + ]); + await context.close(); + }); }); describe('BrowserContext({locale})', function() { @@ -369,6 +383,20 @@ module.exports.describe = function({testRunner, expect, playwright, headless, FF expect(result).toBe('fr-CH'); await context.close(); }); + it('should work for multiple pages sharing same process', async({browser, server}) => { + const context = await browser.newContext({ locale: 'ru-RU' }); + const page = await context.newPage(); + await page.goto(server.EMPTY_PAGE); + let [popup] = await Promise.all([ + page.waitForEvent('popup'), + page.evaluate(url => { window.open(url); }, server.EMPTY_PAGE), + ]); + [popup] = await Promise.all([ + popup.waitForEvent('popup'), + popup.evaluate(url => { window.open(url); }, server.EMPTY_PAGE), + ]); + await context.close(); + }); }); describe('focus', function() {