Skip to content

Commit d733e92

Browse files
authored
feat: BrowserContext.setStorageState (#36875)
1 parent 454a02a commit d733e92

File tree

11 files changed

+263
-13
lines changed

11 files changed

+263
-13
lines changed

docs/src/api/class-browsercontext.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,6 +1495,29 @@ its geolocation.
14951495

14961496
Whether to emulate network being offline for the browser context.
14971497

1498+
1499+
## async method: BrowserContext.setStorageState
1500+
* since: v1.55
1501+
1502+
Resets storage state in the context by clearing cookies, cache and storage, and then applying the new storage state.
1503+
1504+
### param: BrowserContext.setStorageState.storageState = %%-js-python-context-option-storage-state-%%
1505+
* since: v1.55
1506+
1507+
### param: BrowserContext.setStorageState.storageState = %%-csharp-java-context-option-storage-state-%%
1508+
* since: v1.55
1509+
1510+
1511+
## async method: BrowserContext.setStorageStatePath
1512+
* since: v1.55
1513+
* langs: csharp, java
1514+
1515+
Resets storage state in the context by clearing cookies, cache and storage, and then applying the new storage state from a file.
1516+
1517+
### param: BrowserContext.setStorageStatePath.storageStatePath = %%-csharp-java-context-option-storage-state-path-%%
1518+
* since: v1.55
1519+
1520+
14981521
## async method: BrowserContext.storageState
14991522
* since: v1.8
15001523
- returns: <[Object]>

packages/playwright-client/types/types.d.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9273,6 +9273,64 @@ export interface BrowserContext {
92739273
*/
92749274
setOffline(offline: boolean): Promise<void>;
92759275

9276+
/**
9277+
* Resets storage state in the context by clearing cookies, cache and storage, and then applying the new storage
9278+
* state.
9279+
* @param storageState Learn more about [storage state and auth](https://playwright.dev/docs/auth).
9280+
*
9281+
* Populates context with given storage state. This option can be used to initialize context with logged-in
9282+
* information obtained via
9283+
* [browserContext.storageState([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state).
9284+
*/
9285+
setStorageState(storageState: string|{
9286+
/**
9287+
* Cookies to set for context
9288+
*/
9289+
cookies: Array<{
9290+
name: string;
9291+
9292+
value: string;
9293+
9294+
/**
9295+
* Domain and path are required. For the cookie to apply to all subdomains as well, prefix domain with a dot, like
9296+
* this: ".example.com"
9297+
*/
9298+
domain: string;
9299+
9300+
/**
9301+
* Domain and path are required
9302+
*/
9303+
path: string;
9304+
9305+
/**
9306+
* Unix time in seconds.
9307+
*/
9308+
expires: number;
9309+
9310+
httpOnly: boolean;
9311+
9312+
secure: boolean;
9313+
9314+
/**
9315+
* sameSite flag
9316+
*/
9317+
sameSite: "Strict"|"Lax"|"None";
9318+
}>;
9319+
9320+
origins: Array<{
9321+
origin: string;
9322+
9323+
/**
9324+
* localStorage to set for context
9325+
*/
9326+
localStorage: Array<{
9327+
name: string;
9328+
9329+
value: string;
9330+
}>;
9331+
}>;
9332+
}): Promise<void>;
9333+
92769334
/**
92779335
* Returns storage state for this browser context, contains current cookies, local storage snapshot and IndexedDB
92789336
* snapshot.

packages/playwright-core/src/client/browserContext.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import { urlMatchesEqual } from '../utils/isomorphic/urlMatch';
4141
import { isRegExp, isString } from '../utils/isomorphic/rtti';
4242
import { rewriteErrorMessage } from '../utils/isomorphic/stackTrace';
4343

44-
import type { BrowserContextOptions, Headers, StorageState, WaitForEventOptions } from './types';
44+
import type { BrowserContextOptions, Headers, SetStorageState, StorageState, WaitForEventOptions } from './types';
4545
import type * as structs from '../../types/structs';
4646
import type * as api from '../../types/types';
4747
import type { URLMatch } from '../utils/isomorphic/urlMatch';
@@ -455,6 +455,10 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
455455
return state;
456456
}
457457

458+
async setStorageState(storageState: string | SetStorageState) {
459+
await this._channel.setStorageState({ storageState: await prepareStorageState(this._platform, storageState) });
460+
}
461+
458462
backgroundPages(): Page[] {
459463
return [...this._backgroundPages];
460464
}
@@ -527,13 +531,13 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
527531
}
528532
}
529533

530-
async function prepareStorageState(platform: Platform, options: BrowserContextOptions): Promise<channels.BrowserNewContextParams['storageState']> {
531-
if (typeof options.storageState !== 'string')
532-
return options.storageState as any;
534+
async function prepareStorageState(platform: Platform, storageState: string | SetStorageState): Promise<NonNullable<channels.BrowserNewContextParams['storageState']>> {
535+
if (typeof storageState !== 'string')
536+
return storageState as any;
533537
try {
534-
return JSON.parse(await platform.fs().promises.readFile(options.storageState, 'utf8'));
538+
return JSON.parse(await platform.fs().promises.readFile(storageState, 'utf8'));
535539
} catch (e) {
536-
rewriteErrorMessage(e, `Error reading storage state from ${options.storageState}:\n` + e.message);
540+
rewriteErrorMessage(e, `Error reading storage state from ${storageState}:\n` + e.message);
537541
throw e;
538542
}
539543
}
@@ -548,7 +552,7 @@ export async function prepareBrowserContextParams(platform: Platform, options: B
548552
viewport: options.viewport === null ? undefined : options.viewport,
549553
noDefaultViewport: options.viewport === null,
550554
extraHTTPHeaders: options.extraHTTPHeaders ? headersObjectToArray(options.extraHTTPHeaders) : undefined,
551-
storageState: await prepareStorageState(platform, options),
555+
storageState: options.storageState ? await prepareStorageState(platform, options.storageState) : undefined,
552556
serviceWorkers: options.serviceWorkers,
553557
colorScheme: options.colorScheme === null ? 'no-override' : options.colorScheme,
554558
reducedMotion: options.reducedMotion === null ? 'no-override' : options.reducedMotion,

packages/playwright-core/src/protocol/validator.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,13 @@ scheme.BrowserContextStorageStateResult = tObject({
10711071
cookies: tArray(tType('NetworkCookie')),
10721072
origins: tArray(tType('OriginStorage')),
10731073
});
1074+
scheme.BrowserContextSetStorageStateParams = tObject({
1075+
storageState: tObject({
1076+
cookies: tOptional(tArray(tType('SetNetworkCookie'))),
1077+
origins: tOptional(tArray(tType('SetOriginStorage'))),
1078+
}),
1079+
});
1080+
scheme.BrowserContextSetStorageStateResult = tOptional(tObject({}));
10741081
scheme.BrowserContextPauseParams = tOptional(tObject({}));
10751082
scheme.BrowserContextPauseResult = tOptional(tObject({}));
10761083
scheme.BrowserContextEnableRecorderParams = tObject({

packages/playwright-core/src/server/browserContext.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ export abstract class BrowserContext extends SdkObject {
213213
await progress.race(this.setUserAgent(this._options.userAgent));
214214
await progress.race(this.doUpdateDefaultEmulatedMedia());
215215
await progress.race(this.doUpdateDefaultViewport());
216-
await this.setStorageState(progress, this._options.storageState, 'reset');
216+
await this.setStorageState(progress, this._options.storageState, 'resetForReuse');
217217

218218
await page?.resetForReuse(progress);
219219
}
@@ -612,11 +612,11 @@ export abstract class BrowserContext extends SdkObject {
612612
return this._creatingStorageStatePage;
613613
}
614614

615-
async setStorageState(progress: Progress, state: channels.BrowserNewContextParams['storageState'], mode: 'initial' | 'reset') {
615+
async setStorageState(progress: Progress, state: channels.BrowserNewContextParams['storageState'], mode: 'initial' | 'resetForReuse' | 'update') {
616616
let page: Page | undefined;
617617
let interceptor: network.RouteHandler | undefined;
618618
try {
619-
if (mode === 'reset') {
619+
if (mode !== 'initial') {
620620
await progress.race(this.clearCache());
621621
await progress.race(this.doClearCookies());
622622
}
@@ -627,11 +627,11 @@ export abstract class BrowserContext extends SdkObject {
627627
const newOrigins = new Map(state?.origins?.map(p => [p.origin, p]) || []);
628628
const allOrigins = new Set([...this._origins, ...newOrigins.keys()]);
629629
if (allOrigins.size) {
630-
if (mode === 'reset')
630+
if (mode === 'resetForReuse')
631631
page = this.pages()[0];
632632
if (!page) {
633633
try {
634-
this._creatingStorageStatePage = mode === 'initial';
634+
this._creatingStorageStatePage = mode !== 'resetForReuse';
635635
page = await this.newPage(progress, this._creatingStorageStatePage);
636636
} finally {
637637
this._creatingStorageStatePage = false;
@@ -660,7 +660,7 @@ export abstract class BrowserContext extends SdkObject {
660660
rewriteErrorMessage(error, `Error setting storage state:\n` + error.message);
661661
throw error;
662662
} finally {
663-
if (mode === 'initial')
663+
if (mode !== 'resetForReuse')
664664
await page?.close();
665665
else if (interceptor)
666666
await page?.removeRequestInterceptor(interceptor);

packages/playwright-core/src/server/dispatchers/browserContextDispatcher.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,10 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
330330
return await progress.race(this._context.storageState(progress, params.indexedDB));
331331
}
332332

333+
async setStorageState(params: channels.BrowserContextSetStorageStateParams, progress: Progress): Promise<channels.BrowserContextSetStorageStateResult> {
334+
await this._context.setStorageState(progress, params.storageState, 'update');
335+
}
336+
333337
async close(params: channels.BrowserContextCloseParams, progress: Progress): Promise<void> {
334338
progress.metadata.potentiallyClosesScope = true;
335339
await this._context.close(params);

packages/playwright-core/src/utils/isomorphic/protocolMetainfo.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export const methodMetainfo = new Map<string, { internal?: boolean, title?: stri
8282
['BrowserContext.setWebSocketInterceptionPatterns', { internal: true, }],
8383
['BrowserContext.setOffline', { title: 'Set offline mode', }],
8484
['BrowserContext.storageState', { title: 'Get storage state', }],
85+
['BrowserContext.setStorageState', { title: 'Set storage state', }],
8586
['BrowserContext.pause', { title: 'Pause', }],
8687
['BrowserContext.enableRecorder', { internal: true, }],
8788
['BrowserContext.disableRecorder', { internal: true, }],

packages/playwright-core/types/types.d.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9273,6 +9273,64 @@ export interface BrowserContext {
92739273
*/
92749274
setOffline(offline: boolean): Promise<void>;
92759275

9276+
/**
9277+
* Resets storage state in the context by clearing cookies, cache and storage, and then applying the new storage
9278+
* state.
9279+
* @param storageState Learn more about [storage state and auth](https://playwright.dev/docs/auth).
9280+
*
9281+
* Populates context with given storage state. This option can be used to initialize context with logged-in
9282+
* information obtained via
9283+
* [browserContext.storageState([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state).
9284+
*/
9285+
setStorageState(storageState: string|{
9286+
/**
9287+
* Cookies to set for context
9288+
*/
9289+
cookies: Array<{
9290+
name: string;
9291+
9292+
value: string;
9293+
9294+
/**
9295+
* Domain and path are required. For the cookie to apply to all subdomains as well, prefix domain with a dot, like
9296+
* this: ".example.com"
9297+
*/
9298+
domain: string;
9299+
9300+
/**
9301+
* Domain and path are required
9302+
*/
9303+
path: string;
9304+
9305+
/**
9306+
* Unix time in seconds.
9307+
*/
9308+
expires: number;
9309+
9310+
httpOnly: boolean;
9311+
9312+
secure: boolean;
9313+
9314+
/**
9315+
* sameSite flag
9316+
*/
9317+
sameSite: "Strict"|"Lax"|"None";
9318+
}>;
9319+
9320+
origins: Array<{
9321+
origin: string;
9322+
9323+
/**
9324+
* localStorage to set for context
9325+
*/
9326+
localStorage: Array<{
9327+
name: string;
9328+
9329+
value: string;
9330+
}>;
9331+
}>;
9332+
}): Promise<void>;
9333+
92769334
/**
92779335
* Returns storage state for this browser context, contains current cookies, local storage snapshot and IndexedDB
92789336
* snapshot.

packages/protocol/src/channels.d.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,7 @@ export interface BrowserContextChannel extends BrowserContextEventTarget, EventT
16121612
setWebSocketInterceptionPatterns(params: BrowserContextSetWebSocketInterceptionPatternsParams, progress?: Progress): Promise<BrowserContextSetWebSocketInterceptionPatternsResult>;
16131613
setOffline(params: BrowserContextSetOfflineParams, progress?: Progress): Promise<BrowserContextSetOfflineResult>;
16141614
storageState(params: BrowserContextStorageStateParams, progress?: Progress): Promise<BrowserContextStorageStateResult>;
1615+
setStorageState(params: BrowserContextSetStorageStateParams, progress?: Progress): Promise<BrowserContextSetStorageStateResult>;
16151616
pause(params?: BrowserContextPauseParams, progress?: Progress): Promise<BrowserContextPauseResult>;
16161617
enableRecorder(params: BrowserContextEnableRecorderParams, progress?: Progress): Promise<BrowserContextEnableRecorderResult>;
16171618
disableRecorder(params?: BrowserContextDisableRecorderParams, progress?: Progress): Promise<BrowserContextDisableRecorderResult>;
@@ -1862,6 +1863,16 @@ export type BrowserContextStorageStateResult = {
18621863
cookies: NetworkCookie[],
18631864
origins: OriginStorage[],
18641865
};
1866+
export type BrowserContextSetStorageStateParams = {
1867+
storageState: {
1868+
cookies?: SetNetworkCookie[],
1869+
origins?: SetOriginStorage[],
1870+
},
1871+
};
1872+
export type BrowserContextSetStorageStateOptions = {
1873+
1874+
};
1875+
export type BrowserContextSetStorageStateResult = void;
18651876
export type BrowserContextPauseParams = {};
18661877
export type BrowserContextPauseOptions = {};
18671878
export type BrowserContextPauseResult = void;

packages/protocol/src/protocol.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,6 +1327,19 @@ BrowserContext:
13271327
type: array
13281328
items: OriginStorage
13291329

1330+
setStorageState:
1331+
title: Set storage state
1332+
parameters:
1333+
storageState:
1334+
type: object
1335+
properties:
1336+
cookies:
1337+
type: array?
1338+
items: SetNetworkCookie
1339+
origins:
1340+
type: array?
1341+
items: SetOriginStorage
1342+
13301343
pause:
13311344
title: Pause
13321345

0 commit comments

Comments
 (0)