Skip to content

Commit 79943e0

Browse files
authored
Feature/141/permission handling (#143)
* (#141) Switch to more fine-grained permission checks on macOS via node-mac-permissions * (#141) Refined output in failed permission check setup * (#141) Moved node-mac-permissions back to dependencies array * (#141) Revert last commit
1 parent 686b999 commit 79943e0

File tree

6 files changed

+159
-78
lines changed

6 files changed

+159
-78
lines changed

index.js

+37-32
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,50 @@
1-
const libnut = require("bindings")("libnut");
1+
let libnut;
2+
if (process.platform === 'darwin') {
3+
libnut = require("./permissionCheck");
4+
} else {
5+
libnut = require("bindings")("libnut");
6+
}
27

38
module.exports = libnut;
49

510
module.exports.screen = {};
611

712
function bitmap(width, height, byteWidth, bitsPerPixel, bytesPerPixel, image) {
8-
this.width = width;
9-
this.height = height;
10-
this.byteWidth = byteWidth;
11-
this.bitsPerPixel = bitsPerPixel;
12-
this.bytesPerPixel = bytesPerPixel;
13-
this.image = image;
13+
this.width = width;
14+
this.height = height;
15+
this.byteWidth = byteWidth;
16+
this.bitsPerPixel = bitsPerPixel;
17+
this.bytesPerPixel = bytesPerPixel;
18+
this.image = image;
1419
}
1520

16-
module.exports.screen.highlight = function(x, y, width, height, duration, opacity) {
17-
let highlightOpacity = (opacity < 0) ? 0 : opacity;
18-
highlightOpacity = (highlightOpacity > 1) ? 1 : highlightOpacity;
19-
const highlightDuration = (duration < 0) ? 0 : duration;
21+
module.exports.screen.highlight = function (x, y, width, height, duration, opacity) {
22+
let highlightOpacity = (opacity < 0) ? 0 : opacity;
23+
highlightOpacity = (highlightOpacity > 1) ? 1 : highlightOpacity;
24+
const highlightDuration = (duration < 0) ? 0 : duration;
2025

21-
libnut.highlight(x, y, width, height, highlightDuration, highlightOpacity);
26+
libnut.highlight(x, y, width, height, highlightDuration, highlightOpacity);
2227
}
2328

24-
module.exports.screen.capture = function(x, y, width, height) {
25-
//If coords have been passed, use them.
26-
if (
27-
typeof x !== "undefined" &&
28-
typeof y !== "undefined" &&
29-
typeof width !== "undefined" &&
30-
typeof height !== "undefined"
31-
) {
32-
b = libnut.captureScreen(x, y, width, height);
33-
} else {
34-
b = libnut.captureScreen();
35-
}
29+
module.exports.screen.capture = function (x, y, width, height) {
30+
//If coords have been passed, use them.
31+
if (
32+
typeof x !== "undefined" &&
33+
typeof y !== "undefined" &&
34+
typeof width !== "undefined" &&
35+
typeof height !== "undefined"
36+
) {
37+
b = libnut.captureScreen(x, y, width, height);
38+
} else {
39+
b = libnut.captureScreen();
40+
}
3641

37-
return new bitmap(
38-
b.width,
39-
b.height,
40-
b.byteWidth,
41-
b.bitsPerPixel,
42-
b.bytesPerPixel,
43-
b.image
44-
);
42+
return new bitmap(
43+
b.width,
44+
b.height,
45+
b.byteWidth,
46+
b.bitsPerPixel,
47+
b.bytesPerPixel,
48+
b.image
49+
);
4550
};

package-lock.json

+45-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@
3737
"dependencies": {
3838
"bindings": "1.5.0",
3939
"cmake-js": "6.1.0",
40-
"node-addon-api": "3.2.1"
40+
"node-addon-api": "5.0.0"
41+
},
42+
"optionalDependencies": {
43+
"node-mac-permissions": "2.2.1"
4144
},
4245
"engines": {
4346
"node": ">=10.15.3"

permissionCheck.js

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
const libnut = require("bindings")("libnut");
2+
3+
try {
4+
const permissions = require("node-mac-permissions");
5+
6+
const wrapWithWarning = (message, nativeFunction) => (...args) => {
7+
console.warn(message);
8+
return nativeFunction(...args);
9+
};
10+
11+
const askForAccessibility = (nativeFunction, functionName) => {
12+
if (process.platform !== 'darwin') {
13+
return nativeFunction;
14+
}
15+
const accessibilityStatus = permissions.getAuthStatus("accessibility");
16+
17+
if (accessibilityStatus === 'authorized') {
18+
return nativeFunction;
19+
} else if (accessibilityStatus === 'not determined' || accessibilityStatus === 'denied') {
20+
permissions.askForAccessibilityAccess();
21+
return wrapWithWarning(`##### WARNING! The application running this script tries to access accessibility features to execute ${functionName}! Please grant requested access and visit https://github.com/nut-tree/nut.js#macos for further information. #####`, nativeFunction);
22+
}
23+
}
24+
const askForScreenRecording = (nativeFunction, functionName) => {
25+
if (process.platform !== 'darwin') {
26+
return nativeFunction;
27+
}
28+
const screenCaptureStatus = permissions.getAuthStatus("screen");
29+
30+
if (screenCaptureStatus === 'authorized') {
31+
return nativeFunction;
32+
} else if (screenCaptureStatus === 'not determined' || screenCaptureStatus === 'denied') {
33+
permissions.askForScreenCaptureAccess();
34+
return wrapWithWarning(`##### WARNING! The application running this script tries to access accessibility features to execute ${functionName}! Please grant the requested access and visit https://github.com/nut-tree/nut.js#macos for further information. #####`, nativeFunction);
35+
}
36+
}
37+
38+
const accessibilityAccess = [
39+
"dragMouse",
40+
"moveMouse",
41+
"getMousePos",
42+
"mouseClick",
43+
"mouseToggle",
44+
"scrollMouse",
45+
"setMouseDelay",
46+
"keyTap",
47+
"keyToggle",
48+
"typeString",
49+
"setKeyboardDelay",
50+
"getScreenSize",
51+
"highlight",
52+
"captureScreen",
53+
"getWindows",
54+
"getActiveWindow",
55+
"getWindowRect",
56+
"getWindowTitle",
57+
];
58+
const screenCaptureAccess = [
59+
"getWindowTitle",
60+
];
61+
62+
for (const functionName of accessibilityAccess) {
63+
libnut[functionName] = askForAccessibility(libnut[functionName], functionName);
64+
}
65+
for (const functionName of screenCaptureAccess) {
66+
libnut[functionName] = askForScreenRecording(libnut[functionName], functionName);
67+
}
68+
} catch (e) {
69+
console.warn(`Encountered error establishing macOS permission checks:`, e.message);
70+
console.warn(`Returning original module.`);
71+
} finally {
72+
module.exports = libnut;
73+
}

src/main.cc

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include "screen.h"
99
#include "screengrab.h"
1010
#include "window_manager.h"
11-
#include "startup.h"
1211

1312
int mouseDelay = 10;
1413
int keyboardDelay = 10;

src/startup.h

-34
This file was deleted.

0 commit comments

Comments
 (0)