Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions packages/playwright-core/src/server/webkit/webview/wvBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { httpHappyEyeballsAgent, httpsHappyEyeballsAgent } from '@utils/happyEye
import { headersArrayToObject } from '@isomorphic/headers';
import { Browser } from '../../browser';
import { helper } from '../../helper';
import * as network from '../../network';
import { perMessageDeflate } from '../../transport';
import { getUserAgent } from '../../userAgent';
import { BrowserContext } from '../../browserContext';
Expand All @@ -35,6 +36,7 @@ import { WVPage } from './wvPage';
import type { BrowserOptions, BrowserProcess } from '../../browser';
import type { SdkObject } from '../../instrumentation';
import type { InitScript, Page } from '../../page';
import type { Protocol } from './protocol';
import type { ProtocolRequest, ProtocolResponse } from '../../transport';
import type * as types from '../../types';
import type * as channels from '../../channels';
Expand Down Expand Up @@ -305,16 +307,64 @@ export class WVBrowserContext extends BrowserContext {
throw new Error('Not supported');
}

// The Page cookie commands only see cookies for the current page's domain, so
// cookie access is scoped to that page rather than the whole context.
private _cookiePage(): WVPage | undefined {
const page = this.pages()[0];
return page ? page.delegate as WVPage : undefined;
}

async doGetCookies(urls: string[]): Promise<channels.NetworkCookie[]> {
return [];
const page = this._cookiePage();
if (!page)
return [];
const cookies = await page.getCookies();
return network.filterCookies(cookies.map(c => {
const copy: channels.NetworkCookie = {
name: c.name,
value: c.value,
domain: c.domain,
path: c.path,
expires: c.session ? -1 : c.expires / 1000,
httpOnly: c.httpOnly,
secure: c.secure,
sameSite: c.sameSite,
};
return copy;
}), urls);
}

async addCookies(cookies: channels.SetNetworkCookie[]) {
throw new Error('Method not implemented.');
const page = this._cookiePage();
if (!page)
throw new Error('Cannot set cookies without an open page');
const protocolCookies = network.rewriteCookies(cookies).map(c => {
const session = c.expires === undefined || c.expires === -1;
const cookie: Protocol.Page.Cookie = {
name: c.name,
value: c.value,
domain: c.domain!,
path: c.path!,
expires: session ? 0 : c.expires! * 1000,
session,
httpOnly: !!c.httpOnly,
secure: !!c.secure,
sameSite: c.sameSite ?? 'Lax',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this default to 'Lax' or 'None'?

};
return cookie;
});
await page.setCookies(protocolCookies);
}

async doClearCookies() {
throw new Error('Method not implemented.');
const page = this._cookiePage();
if (!page)
return;
const cookies = await page.getCookies();
await page.deleteCookies(cookies.map(c => ({
cookieName: c.name,
url: `${c.secure ? 'https' : 'http'}://${c.domain.replace(/^\./, '')}${c.path}`,
})));
}

async doGrantPermissions(origin: string, permissions: string[]) {
Expand Down
15 changes: 15 additions & 0 deletions packages/playwright-core/src/server/webkit/webview/wvPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,21 @@ export class WVPage implements PageDelegate {
await this._session.send('Page.reload');
}

async getCookies(): Promise<Protocol.Page.Cookie[]> {
const { cookies } = await this._session.send('Page.getCookies');
return cookies;
}

async setCookies(cookies: Protocol.Page.Cookie[]): Promise<void> {
for (const cookie of cookies)
await this._session.send('Page.setCookie', { cookie });
}

async deleteCookies(cookies: { cookieName: string, url: string }[]): Promise<void> {
for (const { cookieName, url } of cookies)
await this._session.send('Page.deleteCookie', { cookieName, url });
}

async addInitScript(initScript: InitScript): Promise<void> {
await this._updateBootstrapScript();
}
Expand Down
2 changes: 0 additions & 2 deletions tests/webview/expectations/webkit-webview-page.txt
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,6 @@ page/page-request-fulfill.spec.ts › should fulfill with multiple set-cookie [f
page/page-request-intercept.spec.ts › should support timeout option in route.fetch [fail]
page/page-route.spec.ts › should fail navigation when aborting main resource [fail]
page/page-route.spec.ts › should not auto-intercept non-preflight OPTIONS with network interception [fail]
page/page-route.spec.ts › should not override cookie header [fail]
page/page-route.spec.ts › should send referer [fail]
page/page-screenshot.spec.ts › page screenshot animations › should capture screenshots after layoutchanges in transitionend event › make sure transition is actually running [fail]
page/page-screenshot.spec.ts › page screenshot animations › should fire transitionend for finite transitions › make sure transition is actually running [fail]
Expand Down Expand Up @@ -492,7 +491,6 @@ page/page-request-gc.spec.ts › should work [fail]
page/page-request-intercept.spec.ts › should fulfill intercepted response using alias [fail]
page/page-request-intercept.spec.ts › should intercept with url override [fail]
page/page-request-intercept.spec.ts › should not follow redirects when maxRedirects is set to 0 in route.fetch [fail]
page/page-route.spec.ts › should properly return navigation response when URL has cookies [fail]
page/page-set-input-files.spec.ts › should detect mime type [fail]
page/page-set-input-files.spec.ts › should emit input and change events [fail]
page/page-set-input-files.spec.ts › should upload a folder [fail]
Expand Down
3 changes: 3 additions & 0 deletions tests/webview/webviewTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ export const webviewTest = baseTest.extend<WebViewTestFixtures, WebViewWorkerFix
throw new Error('No Mobile Safari tab is attached');
await page.goto('about:blank').catch(() => {});
await run(page);
// The shared Mobile Safari cookie store persists across tests; clear it
// while still on the test's domain (webview cookies are domain-scoped).
await page.context().clearCookies().catch(() => {});
await browser.close();
},

Expand Down
Loading