From 7f9b21daa0fd98f5311d87165b4ab2fe1231ad1d Mon Sep 17 00:00:00 2001 From: John Kleinschmidt Date: Thu, 29 Oct 2020 14:22:32 -0400 Subject: [PATCH] feat: correctly identify permissions when using setPermissionRequestHandler (#26172) * fix: correctly identify clipboard read permission * Update tests for variable clipboard content * chore: add all possible permission conversions * VIDEO_CAPTURE and AUDIO_CAPTURE were already defined * Handle all PermissionTypes * use skewer case for accessibility events to match permissions api https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API --- docs/api/session.md | 1 + .../gin_converters/content_converter.cc | 44 ++++++++++++++- spec-main/chromium-spec.ts | 53 +++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) diff --git a/docs/api/session.md b/docs/api/session.md index e5d0c137e1ba..8b901bd0b933 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -487,6 +487,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => { * `handler` Function | null * `webContents` [WebContents](web-contents.md) - WebContents requesting the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin. * `permission` String - The type of requested permission. + * `clipboard-read` - Request access to read from the clipboard. * `media` - Request access to media devices such as camera, microphone and speakers. * `mediaKeySystem` - Request access to DRM protected content. * `geolocation` - Request access to user's current location. diff --git a/shell/common/gin_converters/content_converter.cc b/shell/common/gin_converters/content_converter.cc index 6ba67ea7ab9b..1cc99380fd9a 100644 --- a/shell/common/gin_converters/content_converter.cc +++ b/shell/common/gin_converters/content_converter.cc @@ -174,11 +174,41 @@ v8::Local Converter::ToV8( v8::Isolate* isolate, const content::PermissionType& val) { using PermissionType = electron::WebContentsPermissionHelper::PermissionType; + // Based on mappings from content/browser/devtools/protocol/browser_handler.cc + // Not all permissions are currently used by Electron but this will future + // proof these conversions. switch (val) { + case content::PermissionType::ACCESSIBILITY_EVENTS: + return StringToV8(isolate, "accessibility-events"); + case content::PermissionType::AR: + return StringToV8(isolate, "ar"); + case content::PermissionType::BACKGROUND_FETCH: + return StringToV8(isolate, "background-fetch"); + case content::PermissionType::BACKGROUND_SYNC: + return StringToV8(isolate, "background-sync"); + case content::PermissionType::CLIPBOARD_READ_WRITE: + return StringToV8(isolate, "clipboard-read"); + case content::PermissionType::CLIPBOARD_SANITIZED_WRITE: + return StringToV8(isolate, "clipboard-sanitized-write"); + case content::PermissionType::FLASH: + return StringToV8(isolate, "flash"); + case content::PermissionType::CAMERA_PAN_TILT_ZOOM: + case content::PermissionType::FONT_ACCESS: + return StringToV8(isolate, "font-access"); + case content::PermissionType::IDLE_DETECTION: + return StringToV8(isolate, "idle-detection"); case content::PermissionType::MIDI_SYSEX: return StringToV8(isolate, "midiSysex"); + case content::PermissionType::NFC: + return StringToV8(isolate, "nfc"); case content::PermissionType::NOTIFICATIONS: return StringToV8(isolate, "notifications"); + case content::PermissionType::PAYMENT_HANDLER: + return StringToV8(isolate, "payment-handler"); + case content::PermissionType::PERIODIC_BACKGROUND_SYNC: + return StringToV8(isolate, "periodic-background-sync"); + case content::PermissionType::DURABLE_STORAGE: + return StringToV8(isolate, "persistent-storage"); case content::PermissionType::GEOLOCATION: return StringToV8(isolate, "geolocation"); case content::PermissionType::AUDIO_CAPTURE: @@ -188,7 +218,19 @@ v8::Local Converter::ToV8( return StringToV8(isolate, "mediaKeySystem"); case content::PermissionType::MIDI: return StringToV8(isolate, "midi"); - default: + case content::PermissionType::WAKE_LOCK_SCREEN: + return StringToV8(isolate, "screen-wake-lock"); + case content::PermissionType::SENSORS: + return StringToV8(isolate, "sensors"); + case content::PermissionType::STORAGE_ACCESS_GRANT: + return StringToV8(isolate, "storage-access"); + case content::PermissionType::VR: + return StringToV8(isolate, "vr"); + case content::PermissionType::WAKE_LOCK_SYSTEM: + return StringToV8(isolate, "system-wake-lock"); + case content::PermissionType::WINDOW_PLACEMENT: + return StringToV8(isolate, "window-placement"); + case content::PermissionType::NUM: break; } diff --git a/spec-main/chromium-spec.ts b/spec-main/chromium-spec.ts index 9e49262c74c9..f534fca6717a 100644 --- a/spec-main/chromium-spec.ts +++ b/spec-main/chromium-spec.ts @@ -1503,3 +1503,56 @@ describe('navigator.serial', () => { expect(port).to.equal('[object SerialPort]'); }); }); + +describe('navigator.clipboard', () => { + let w: BrowserWindow; + before(async () => { + w = new BrowserWindow({ + show: false, + webPreferences: { + enableBlinkFeatures: 'Serial' + } + }); + await w.loadFile(path.join(fixturesPath, 'pages', 'blank.html')); + }); + + const readClipboard: any = () => { + return w.webContents.executeJavaScript(` + navigator.clipboard.read().then(clipboard => clipboard.toString()).catch(err => err.message); + `, true); + }; + + after(closeAllWindows); + afterEach(() => { + session.defaultSession.setPermissionRequestHandler(null); + }); + + it('returns clipboard contents when a PermissionRequestHandler is not defined', async () => { + const clipboard = await readClipboard(); + expect(clipboard).to.not.equal('Read permission denied.'); + }); + + it('returns an error when permission denied', async () => { + session.defaultSession.setPermissionRequestHandler((wc, permission, callback) => { + if (permission === 'clipboard-read') { + callback(false); + } else { + callback(true); + } + }); + const clipboard = await readClipboard(); + expect(clipboard).to.equal('Read permission denied.'); + }); + + it('returns clipboard contents when permission is granted', async () => { + session.defaultSession.setPermissionRequestHandler((wc, permission, callback) => { + if (permission === 'clipboard-read') { + callback(true); + } else { + callback(false); + } + }); + const clipboard = await readClipboard(); + expect(clipboard).to.not.equal('Read permission denied.'); + }); +});