| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Copyright 2017 Google Inc. All rights reserved. | 
					
						
							|  |  |  |  * Modifications copyright (c) Microsoft Corporation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-09-02 21:43:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-25 15:05:50 -08:00
										 |  |  | import { contextTest as it, expect } from '../config/browserTest'; | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | function getPermission(page, name) { | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   return page.evaluate(name => navigator.permissions.query({ name }).then(result => result.state), name); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 09:18:56 -07:00
										 |  |  | it.describe('permissions', () => { | 
					
						
							| 
									
										
										
										
											2024-07-16 09:44:38 -07:00
										 |  |  |   it.fixme(({ browserName, isWindows }) => browserName === 'webkit' && isWindows, 'Permissions API is disabled on Windows WebKit'); | 
					
						
							| 
									
										
										
										
											2021-04-05 09:18:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should be prompt by default', async ({ page, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).toBe('prompt'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should deny permission when not listed', async ({ page, context, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     await context.grantPermissions([], { origin: server.EMPTY_PAGE }); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).toBe('denied'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should fail when bad permission is given', async ({ page, context, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     let error: Error; | 
					
						
							|  |  |  |     await context.grantPermissions(['foo'], { origin: server.EMPTY_PAGE }).catch(e => error = e); | 
					
						
							|  |  |  |     expect(error.message).toContain('Unknown permission: foo'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should grant geolocation permission when origin is listed', async ({ page, context, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     await context.grantPermissions(['geolocation'], { origin: server.EMPTY_PAGE }); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).toBe('granted'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should prompt for geolocation permission when origin is not listed', async ({ page, context, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-20 14:19:27 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     await context.grantPermissions(['geolocation'], { origin: server.EMPTY_PAGE }); | 
					
						
							| 
									
										
										
										
											2022-04-22 13:42:52 +02:00
										 |  |  |     await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html'); | 
					
						
							| 
									
										
										
										
											2020-08-20 14:19:27 -07:00
										 |  |  |     expect(await getPermission(page, 'geolocation')).toBe('prompt'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should grant notifications permission when listed', async ({ page, context, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     await context.grantPermissions(['notifications'], { origin: server.EMPTY_PAGE }); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'notifications')).toBe('granted'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should accumulate when adding', async ({ page, context, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     await context.grantPermissions(['geolocation']); | 
					
						
							|  |  |  |     await context.grantPermissions(['notifications']); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).toBe('granted'); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'notifications')).toBe('granted'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should clear permissions', async ({ page, context, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     await context.grantPermissions(['geolocation']); | 
					
						
							|  |  |  |     await context.clearPermissions(); | 
					
						
							|  |  |  |     await context.grantPermissions(['notifications']); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).not.toBe('granted'); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'notifications')).toBe('granted'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should grant permission when listed for all domains', async ({ page, context, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     await context.grantPermissions(['geolocation']); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).toBe('granted'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should grant permission when creating context', async ({ server, browser }) => { | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     const context = await browser.newContext({ permissions: ['geolocation'] }); | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).toBe('granted'); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should reset permissions', async ({ page, context, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     await context.grantPermissions(['geolocation'], { origin: server.EMPTY_PAGE }); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).toBe('granted'); | 
					
						
							|  |  |  |     await context.clearPermissions(); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).toBe('prompt'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-05 13:01:37 -08:00
										 |  |  |   it('should trigger permission onchange', async ({ page, context, server, browserName, browserMajorVersion }) => { | 
					
						
							| 
									
										
										
										
											2021-04-05 09:18:56 -07:00
										 |  |  |     it.fail(browserName === 'webkit'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     await page.evaluate(() => { | 
					
						
							|  |  |  |       window['events'] = []; | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |       return navigator.permissions.query({ name: 'geolocation' }).then(function(result) { | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |         window['events'].push(result.state); | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |         result.onchange = function() { | 
					
						
							|  |  |  |           window['events'].push(result.state); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     expect(await page.evaluate(() => window['events'])).toEqual(['prompt']); | 
					
						
							|  |  |  |     await context.grantPermissions([], { origin: server.EMPTY_PAGE }); | 
					
						
							|  |  |  |     expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied']); | 
					
						
							|  |  |  |     await context.grantPermissions(['geolocation'], { origin: server.EMPTY_PAGE }); | 
					
						
							|  |  |  |     expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted']); | 
					
						
							|  |  |  |     await context.clearPermissions(); | 
					
						
							| 
									
										
										
										
											2024-08-26 18:41:58 -07:00
										 |  |  |     expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted', 'prompt']); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should isolate permissions between browser contexts', async ({ server, browser }) => { | 
					
						
							| 
									
										
										
										
											2021-04-05 09:18:56 -07:00
										 |  |  |     const context = await browser.newContext(); | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     const otherContext = await browser.newContext(); | 
					
						
							|  |  |  |     const otherPage = await otherContext.newPage(); | 
					
						
							|  |  |  |     await otherPage.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).toBe('prompt'); | 
					
						
							|  |  |  |     expect(await getPermission(otherPage, 'geolocation')).toBe('prompt'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await context.grantPermissions([], { origin: server.EMPTY_PAGE }); | 
					
						
							|  |  |  |     await otherContext.grantPermissions(['geolocation'], { origin: server.EMPTY_PAGE }); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).toBe('denied'); | 
					
						
							|  |  |  |     expect(await getPermission(otherPage, 'geolocation')).toBe('granted'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await context.clearPermissions(); | 
					
						
							|  |  |  |     expect(await getPermission(page, 'geolocation')).toBe('prompt'); | 
					
						
							|  |  |  |     expect(await getPermission(otherPage, 'geolocation')).toBe('granted'); | 
					
						
							|  |  |  |     await otherContext.close(); | 
					
						
							| 
									
										
										
										
											2021-04-05 09:18:56 -07:00
										 |  |  |     await context.close(); | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2023-10-13 09:10:35 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-14 12:20:44 +00:00
										 |  |  | it('should support clipboard read', async ({ page, context, server, browserName, isWindows, isLinux, headless, isHeadlessShell }) => { | 
					
						
							| 
									
										
										
										
											2023-10-13 09:10:35 -07:00
										 |  |  |   it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/27475' }); | 
					
						
							|  |  |  |   it.fail(browserName === 'firefox', 'No such permissions (requires flag) in Firefox'); | 
					
						
							|  |  |  |   it.fixme(browserName === 'webkit' && isWindows, 'WebPasteboardProxy::allPasteboardItemInfo not implemented for Windows.'); | 
					
						
							|  |  |  |   it.fixme(browserName === 'webkit' && isLinux && headless, 'WebPasteboardProxy::allPasteboardItemInfo not implemented for WPE.'); | 
					
						
							| 
									
										
										
										
											2024-10-03 07:59:48 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-13 09:10:35 -07:00
										 |  |  |   await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |   // There is no 'clipboard-read' permission in WebKit Web API.
 | 
					
						
							|  |  |  |   if (browserName !== 'webkit') | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     expect(await getPermission(page, 'clipboard-read')).toBe('prompt'); | 
					
						
							| 
									
										
										
										
											2024-10-03 07:59:48 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-14 12:20:44 +00:00
										 |  |  |   if (isHeadlessShell) { | 
					
						
							| 
									
										
										
										
											2024-11-13 10:52:28 +00:00
										 |  |  |     // Chromium (but not headless-shell) shows a dialog and does not resolve the promise.
 | 
					
						
							| 
									
										
										
										
											2024-10-03 07:59:48 -07:00
										 |  |  |     const error = await page.evaluate(() => navigator.clipboard.readText()).catch(e => e); | 
					
						
							|  |  |  |     expect(error.toString()).toContain('denied'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-13 09:10:35 -07:00
										 |  |  |   await context.grantPermissions(['clipboard-read']); | 
					
						
							|  |  |  |   if (browserName !== 'webkit') | 
					
						
							| 
									
										
										
										
											2020-08-18 12:48:32 -07:00
										 |  |  |     expect(await getPermission(page, 'clipboard-read')).toBe('granted'); | 
					
						
							| 
									
										
										
										
											2023-10-13 09:10:35 -07:00
										 |  |  |   // There is no 'clipboard-write' permission in WebKit Web API.
 | 
					
						
							|  |  |  |   if (browserName === 'chromium') | 
					
						
							|  |  |  |     await context.grantPermissions(['clipboard-write']); | 
					
						
							|  |  |  |   await page.evaluate(() => navigator.clipboard.writeText('test content')); | 
					
						
							|  |  |  |   expect(await page.evaluate(() => navigator.clipboard.readText())).toBe('test content'); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:18:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | it('storage access', { | 
					
						
							|  |  |  |   annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31227' } | 
					
						
							|  |  |  | }, async ({ page, context, server, browserName }) => { | 
					
						
							| 
									
										
										
										
											2024-10-04 08:22:27 -07:00
										 |  |  |   it.skip(browserName !== 'chromium', 'chromium-only api'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:18:45 -07:00
										 |  |  |   await context.grantPermissions(['storage-access']); | 
					
						
							|  |  |  |   expect(await getPermission(page, 'storage-access')).toBe('granted'); | 
					
						
							|  |  |  |   server.setRoute('/set-cookie.html', (req, res) => { | 
					
						
							|  |  |  |     res.setHeader('Set-Cookie', 'name=value; Path=/; SameSite=Strict; Secure'); | 
					
						
							|  |  |  |     res.end(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   server.setRoute('/my-frame.html', (req, res) => { | 
					
						
							|  |  |  |     res.setHeader('Content-type', 'text/html'); | 
					
						
							|  |  |  |     res.end(`<iframe src="${server.CROSS_PROCESS_PREFIX + '/empty.html'}"></iframe>`); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Navigate once to the domain as top level.
 | 
					
						
							|  |  |  |   await page.goto(server.CROSS_PROCESS_PREFIX + '/set-cookie.html'); | 
					
						
							|  |  |  |   await page.goto(server.PREFIX + '/my-frame.html'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const frame = page.frames()[1]; | 
					
						
							|  |  |  |   expect(await getPermission(frame, 'storage-access')).toBe('granted'); | 
					
						
							|  |  |  |   const access = await frame.evaluate(() => document.requestStorageAccess().then(() => true, () => false)); | 
					
						
							|  |  |  |   expect(access).toBe(true); | 
					
						
							|  |  |  |   expect(await frame.evaluate(() => document.hasStorageAccess())).toBe(true); | 
					
						
							|  |  |  | }); |