diff --git a/main/common/system-permissions.js b/main/common/system-permissions.js index 2ce1bd0b1..842866af5 100644 --- a/main/common/system-permissions.js +++ b/main/common/system-permissions.js @@ -1,8 +1,7 @@ -const {systemPreferences, shell, dialog} = require('electron'); +const {systemPreferences, shell, dialog, app} = require('electron'); +const {hasScreenCapturePermission, hasPromptedForPermission} = require('mac-screen-capture-permissions'); -const getMicrophoneAccess = () => systemPreferences.getMediaAccessStatus('microphone'); - -const promptSystemPreferences = async ({hasAsked} = {}) => { +const promptSystemPreferences = options => async ({hasAsked} = {}) => { if (hasAsked) { return false; } @@ -11,19 +10,32 @@ const promptSystemPreferences = async ({hasAsked} = {}) => { type: 'warning', buttons: ['Open System Preferences', 'Cancel'], defaultId: 0, - message: 'Kap cannot access the microphone.', - detail: 'Kap requires microphone access to be able to record audio. You can grant this in the System Preferences. Afterwards, relaunch Kap for the changes to take effect.', + message: options.message, + detail: options.detail, cancelId: 1 }); if (response === 0) { - openSystemPreferences(); + await openSystemPreferences(options.systemPreferencesPath); + app.quit(); } return false; }; -const ensureMicrophonePermissions = async (fallback = promptSystemPreferences) => { +const openSystemPreferences = path => shell.openExternal(`x-apple.systempreferences:com.apple.preference.security?${path}`); + +// Microphone + +const getMicrophoneAccess = () => systemPreferences.getMediaAccessStatus('microphone'); + +const microphoneFallback = promptSystemPreferences({ + message: 'Kap cannot access the microphone.', + detail: 'Kap requires microphone access to be able to record audio. You can grant this in the System Preferences. Afterwards, launch Kap for the changes to take effect.', + systemPreferencesPath: 'Privacy_Microphone' +}); + +const ensureMicrophonePermissions = async (fallback = microphoneFallback) => { const access = getMicrophoneAccess(); if (access === 'granted') { @@ -43,12 +55,35 @@ const ensureMicrophonePermissions = async (fallback = promptSystemPreferences) = return fallback(); }; -const openSystemPreferences = () => shell.openExternal('x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone'); - const hasMicrophoneAccess = () => getMicrophoneAccess() === 'granted'; +// Screen Capture (10.15 and newer) + +const screenCaptureFallback = promptSystemPreferences({ + message: 'Kap cannot record the screen.', + detail: 'Kap requires screen capture access to be able to record the screen. You can grant this in the System Preferences. Afterwards, launch Kap for the changes to take effect.', + systemPreferencesPath: 'Privacy_ScreenCapture' +}); + +const ensureScreenCapturePermissions = (fallback = screenCaptureFallback) => { + const hadAsked = hasPromptedForPermission(); + + const hasAccess = hasScreenCapturePermission(); + + if (hasAccess) { + return true; + } + + fallback({hasAsked: !hadAsked}); + return false; +}; + +const hasScreenCaptureAccess = () => hasScreenCapturePermission(); + module.exports = { ensureMicrophonePermissions, hasMicrophoneAccess, - openSystemPreferences + openSystemPreferences, + ensureScreenCapturePermissions, + hasScreenCaptureAccess }; diff --git a/main/cropper.js b/main/cropper.js index 80244f240..43d9a682e 100644 --- a/main/cropper.js +++ b/main/cropper.js @@ -4,7 +4,7 @@ const electron = require('electron'); const delay = require('delay'); const settings = require('./common/settings'); -const {hasMicrophoneAccess, ensureMicrophonePermissions, openSystemPreferences} = require('./common/system-permissions'); +const {hasMicrophoneAccess, ensureMicrophonePermissions, openSystemPreferences, ensureScreenCapturePermissions} = require('./common/system-permissions'); const loadRoute = require('./utils/routes'); const {checkForAnyBlockingEditors} = require('./editor'); @@ -87,6 +87,10 @@ const openCropperWindow = async () => { return; } + if (!ensureScreenCapturePermissions()) { + return; + } + const recordAudio = settings.get('recordAudio'); if (recordAudio && !hasMicrophoneAccess()) { diff --git a/main/index.js b/main/index.js index a77992eff..acfa57d22 100644 --- a/main/index.js +++ b/main/index.js @@ -18,7 +18,7 @@ const {setApplicationMenu} = require('./menus'); const openFiles = require('./utils/open-files'); const {initializeExportOptions} = require('./export-options'); const settings = require('./common/settings'); -const {hasMicrophoneAccess} = require('./common/system-permissions'); +const {hasMicrophoneAccess, ensureScreenCapturePermissions} = require('./common/system-permissions'); require('./utils/sentry'); @@ -90,6 +90,7 @@ const checkForUpdates = () => { openFiles(...filesToOpen); } else if ( !app.getLoginItemSettings().wasOpenedAtLogin && + ensureScreenCapturePermissions() && (!settings.get('recordAudio') || hasMicrophoneAccess()) ) { openCropperWindow(); diff --git a/package.json b/package.json index 4acdb87a1..9284f820b 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "insight": "^0.10.3", "lodash": "^4.17.15", "mac-open-with": "^1.2.2", + "mac-screen-capture-permissions": "^1.0.2", "mac-windows": "^0.7.1", "macos-version": "^5.2.0", "make-dir": "^3.0.0", diff --git a/yarn.lock b/yarn.lock index d43245969..78c2836f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5169,6 +5169,15 @@ mac-open-with@^1.2.2: execa "^2.0.4" macos-version "^5.2.0" +mac-screen-capture-permissions@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/mac-screen-capture-permissions/-/mac-screen-capture-permissions-1.0.2.tgz#d85f6041bec0910e12694e65de00205484a0734f" + integrity sha512-foz6w6ZGJbAHfHrd56xawt3WvswfmUK4PurWlXH4LsUMq69P0XY523YJ3srR0okpUivUhVQmzIk0LOOO/u7agQ== + dependencies: + electron-util "^0.12.1" + execa "^2.0.4" + macos-version "^5.2.0" + mac-windows@^0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/mac-windows/-/mac-windows-0.7.1.tgz#3309ef0c7c508725cc3e17a3ea1687de0680c78b"