mirror of
https://github.com/VSCodium/policy-watcher.git
synced 2025-12-10 21:07:21 -06:00
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
60643232ab
14
.vscode/c_cpp_properties.json
vendored
14
.vscode/c_cpp_properties.json
vendored
@ -13,7 +13,21 @@
|
|||||||
"cStandard": "c17",
|
"cStandard": "c17",
|
||||||
"cppStandard": "c++17",
|
"cppStandard": "c++17",
|
||||||
"intelliSenseMode": "windows-msvc-x64"
|
"intelliSenseMode": "windows-msvc-x64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mac",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"${workspaceFolder}/node_modules/node-addon-api",
|
||||||
|
"${default}"
|
||||||
|
],
|
||||||
|
"defines": ["_DEBUG", "MACOS"],
|
||||||
|
"compilerPath": "/usr/bin/clang++",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++17",
|
||||||
|
"intelliSenseMode": "macos-clang-x64"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 4
|
"version": 4
|
||||||
}
|
}
|
||||||
|
|
||||||
12
.vscode/launch.json
vendored
Normal file
12
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Launch Program",
|
||||||
|
"program": "${workspaceFolder}/index.js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
16
.vscode/settings.json
vendored
16
.vscode/settings.json
vendored
@ -67,6 +67,18 @@
|
|||||||
"xstring": "cpp",
|
"xstring": "cpp",
|
||||||
"xtr1common": "cpp",
|
"xtr1common": "cpp",
|
||||||
"xtree": "cpp",
|
"xtree": "cpp",
|
||||||
"xutility": "cpp"
|
"xutility": "cpp",
|
||||||
}
|
"__bit_reference": "cpp",
|
||||||
|
"__locale": "cpp",
|
||||||
|
"__split_buffer": "cpp",
|
||||||
|
"__threading_support": "cpp",
|
||||||
|
"__verbose_abort": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"execution": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"variant": "cpp",
|
||||||
|
"bitset": "cpp",
|
||||||
|
"print": "cpp"
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,9 @@
|
|||||||
['OS=="mac"', {
|
['OS=="mac"', {
|
||||||
"sources": [
|
"sources": [
|
||||||
"src/macos/PolicyWatcher.cc",
|
"src/macos/PolicyWatcher.cc",
|
||||||
|
"src/macos/StringPolicy.cc",
|
||||||
|
"src/macos/NumberPolicy.cc",
|
||||||
|
"src/macos/BooleanPolicy.cc"
|
||||||
],
|
],
|
||||||
"defines": [
|
"defines": [
|
||||||
"MACOS",
|
"MACOS",
|
||||||
@ -38,7 +41,8 @@
|
|||||||
"sources": [
|
"sources": [
|
||||||
"src/windows/PolicyWatcher.cc",
|
"src/windows/PolicyWatcher.cc",
|
||||||
"src/windows/StringPolicy.cc",
|
"src/windows/StringPolicy.cc",
|
||||||
"src/windows/NumberPolicy.cc"
|
"src/windows/NumberPolicy.cc",
|
||||||
|
"src/windows/BooleanPolicy.cc"
|
||||||
],
|
],
|
||||||
"defines": [
|
"defines": [
|
||||||
"WINDOWS"
|
"WINDOWS"
|
||||||
|
|||||||
7
index.d.ts
vendored
7
index.d.ts
vendored
@ -9,9 +9,10 @@ interface Watcher {
|
|||||||
|
|
||||||
type StringPolicy = { type: "string" };
|
type StringPolicy = { type: "string" };
|
||||||
type NumberPolicy = { type: "number" };
|
type NumberPolicy = { type: "number" };
|
||||||
|
type BooleanPolicy = { type: "boolean" };
|
||||||
|
|
||||||
export interface Policies {
|
export interface Policies {
|
||||||
[policyName: string]: StringPolicy | NumberPolicy;
|
[policyName: string]: StringPolicy | NumberPolicy | BooleanPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PolicyUpdate<T extends Policies> = {
|
export type PolicyUpdate<T extends Policies> = {
|
||||||
@ -19,9 +20,11 @@ export type PolicyUpdate<T extends Policies> = {
|
|||||||
| undefined
|
| undefined
|
||||||
| (T[K] extends StringPolicy
|
| (T[K] extends StringPolicy
|
||||||
? string
|
? string
|
||||||
|
: (T[K] extends BooleanPolicy
|
||||||
|
? boolean
|
||||||
: T[K] extends NumberPolicy
|
: T[K] extends NumberPolicy
|
||||||
? number
|
? number
|
||||||
: never);
|
: never));
|
||||||
};
|
};
|
||||||
|
|
||||||
export function createWatcher<T extends Policies>(
|
export function createWatcher<T extends Policies>(
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@vscodium/policy-watcher",
|
"name": "@vscodium/policy-watcher",
|
||||||
"version": "1.1.8",
|
"version": "1.3.0-2503241459",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@vscodium/policy-watcher",
|
"name": "@vscodium/policy-watcher",
|
||||||
"version": "1.1.8",
|
"version": "1.3.0-2503241459",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bindings": "^1.5.0",
|
"bindings": "^1.5.0",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vscodium/policy-watcher",
|
"name": "@vscodium/policy-watcher",
|
||||||
"version": "1.1.10-2503041159",
|
"version": "1.3.0-2503241459",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@ -10,11 +10,18 @@
|
|||||||
|
|
||||||
using namespace Napi;
|
using namespace Napi;
|
||||||
|
|
||||||
|
enum class PolicyRefreshResult {
|
||||||
|
Updated,
|
||||||
|
Unchanged,
|
||||||
|
Removed,
|
||||||
|
NotSet
|
||||||
|
};
|
||||||
|
|
||||||
class Policy
|
class Policy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Policy() {}
|
virtual ~Policy() {}
|
||||||
virtual bool refresh() = 0;
|
virtual PolicyRefreshResult refresh() = 0;
|
||||||
virtual Value getValue(Env env) const = 0;
|
virtual Value getValue(Env env) const = 0;
|
||||||
const std::string name;
|
const std::string name;
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,11 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MACOS
|
||||||
|
#define Boolean CFBoolean
|
||||||
|
#include <CoreServices/CoreServices.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace Napi;
|
using namespace Napi;
|
||||||
|
|
||||||
class PolicyWatcher : public AsyncProgressQueueWorker<const Policy *>
|
class PolicyWatcher : public AsyncProgressQueueWorker<const Policy *>
|
||||||
@ -24,6 +29,7 @@ public:
|
|||||||
|
|
||||||
void AddStringPolicy(const std::string name);
|
void AddStringPolicy(const std::string name);
|
||||||
void AddNumberPolicy(const std::string name);
|
void AddNumberPolicy(const std::string name);
|
||||||
|
void AddBooleanPolicy(const std::string name);
|
||||||
|
|
||||||
void OnExecute(Napi::Env env);
|
void OnExecute(Napi::Env env);
|
||||||
void Execute(const ExecutionProgress &progress);
|
void Execute(const ExecutionProgress &progress);
|
||||||
@ -38,6 +44,13 @@ protected:
|
|||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
HANDLE handles[4];
|
HANDLE handles[4];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MACOS
|
||||||
|
FSEventStreamRef stream;
|
||||||
|
dispatch_semaphore_t sem;
|
||||||
|
bool disposed;
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -20,6 +20,7 @@ PolicyWatcher::~PolicyWatcher()
|
|||||||
|
|
||||||
void PolicyWatcher::AddStringPolicy(const std::string name) {}
|
void PolicyWatcher::AddStringPolicy(const std::string name) {}
|
||||||
void PolicyWatcher::AddNumberPolicy(const std::string name) {}
|
void PolicyWatcher::AddNumberPolicy(const std::string name) {}
|
||||||
|
void PolicyWatcher::AddBooleanPolicy(const std::string name) {}
|
||||||
void PolicyWatcher::OnExecute(Napi::Env env) {}
|
void PolicyWatcher::OnExecute(Napi::Env env) {}
|
||||||
void PolicyWatcher::Execute(const ExecutionProgress &progress) {}
|
void PolicyWatcher::Execute(const ExecutionProgress &progress) {}
|
||||||
void PolicyWatcher::OnProgress(const Policy *const *policies, size_t count) {}
|
void PolicyWatcher::OnProgress(const Policy *const *policies, size_t count) {}
|
||||||
|
|||||||
36
src/macos/BooleanPolicy.cc
Normal file
36
src/macos/BooleanPolicy.cc
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "BooleanPolicy.hh"
|
||||||
|
|
||||||
|
using namespace Napi;
|
||||||
|
|
||||||
|
BooleanPolicy::BooleanPolicy(const std::string name, const std::string &productName)
|
||||||
|
: PreferencesPolicy(name, productName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Value BooleanPolicy::getJSValue(Env env, bool value) const
|
||||||
|
{
|
||||||
|
return Napi::Boolean::New(env, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<bool> BooleanPolicy::read() const
|
||||||
|
{
|
||||||
|
auto pref = CFPreferencesCopyAppValue(key, appID);
|
||||||
|
|
||||||
|
if (pref == NULL)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
if (CFGetTypeID(pref) != CFBooleanGetTypeID())
|
||||||
|
{
|
||||||
|
CFRelease(pref);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool value = (pref == kCFBooleanTrue);
|
||||||
|
CFRelease(pref);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
24
src/macos/BooleanPolicy.hh
Normal file
24
src/macos/BooleanPolicy.hh
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef MAC_BOOLEAN_POLICY_H
|
||||||
|
#define MAC_BOOLEAN_POLICY_H
|
||||||
|
|
||||||
|
#include <napi.h>
|
||||||
|
#include "PreferencesPolicy.hh"
|
||||||
|
|
||||||
|
using namespace Napi;
|
||||||
|
|
||||||
|
class BooleanPolicy : public PreferencesPolicy<bool>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BooleanPolicy(const std::string name, const std::string &productName);
|
||||||
|
std::optional<bool> read() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Value getJSValue(Env env, bool value) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
42
src/macos/NumberPolicy.cc
Normal file
42
src/macos/NumberPolicy.cc
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "NumberPolicy.hh"
|
||||||
|
|
||||||
|
using namespace Napi;
|
||||||
|
|
||||||
|
NumberPolicy::NumberPolicy(const std::string name, const std::string &productName)
|
||||||
|
: PreferencesPolicy(name, productName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Value NumberPolicy::getJSValue(Env env, long long value) const
|
||||||
|
{
|
||||||
|
return Number::New(env, static_cast<double>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<long long> NumberPolicy::read() const
|
||||||
|
{
|
||||||
|
auto pref = CFPreferencesCopyAppValue(key, appID);
|
||||||
|
|
||||||
|
if (pref == NULL)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
if (CFGetTypeID(pref) != CFNumberGetTypeID())
|
||||||
|
{
|
||||||
|
CFRelease(pref);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long value;
|
||||||
|
if (CFNumberGetValue((CFNumberRef)pref, kCFNumberLongLongType, &value))
|
||||||
|
{
|
||||||
|
CFRelease(pref);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(pref);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
24
src/macos/NumberPolicy.hh
Normal file
24
src/macos/NumberPolicy.hh
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef MAC_NUMBER_POLICY_H
|
||||||
|
#define MAC_NUMBER_POLICY_H
|
||||||
|
|
||||||
|
#include <napi.h>
|
||||||
|
#include "PreferencesPolicy.hh"
|
||||||
|
|
||||||
|
using namespace Napi;
|
||||||
|
|
||||||
|
class NumberPolicy : public PreferencesPolicy<long long>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NumberPolicy(const std::string name, const std::string &productName);
|
||||||
|
std::optional<long long> read() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Value getJSValue(Env env, long long value) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -4,23 +4,136 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "../PolicyWatcher.hh"
|
#include "../PolicyWatcher.hh"
|
||||||
|
#include "StringPolicy.hh"
|
||||||
|
#include "NumberPolicy.hh"
|
||||||
|
#include "BooleanPolicy.hh"
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
using namespace Napi;
|
using namespace Napi;
|
||||||
|
|
||||||
|
static void fsevents_callback(ConstFSEventStreamRef streamRef,
|
||||||
|
void *clientCallBackInfo,
|
||||||
|
size_t numEvents,
|
||||||
|
void *eventPaths,
|
||||||
|
const FSEventStreamEventFlags eventFlags[],
|
||||||
|
const FSEventStreamEventId eventIds[])
|
||||||
|
{
|
||||||
|
dispatch_semaphore_t *sem = (dispatch_semaphore_t *)clientCallBackInfo;
|
||||||
|
dispatch_semaphore_signal(*sem);
|
||||||
|
}
|
||||||
|
|
||||||
PolicyWatcher::PolicyWatcher(std::string vendorName, std::string productName, const Function &okCallback)
|
PolicyWatcher::PolicyWatcher(std::string vendorName, std::string productName, const Function &okCallback)
|
||||||
: AsyncProgressQueueWorker(okCallback),
|
: AsyncProgressQueueWorker(okCallback),
|
||||||
vendorName(vendorName),
|
vendorName(vendorName),
|
||||||
productName(productName)
|
productName(productName),
|
||||||
|
stream(nullptr),
|
||||||
|
sem(nullptr),
|
||||||
|
disposed(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyWatcher::~PolicyWatcher()
|
PolicyWatcher::~PolicyWatcher()
|
||||||
{
|
{
|
||||||
|
if (stream) {
|
||||||
|
FSEventStreamStop(stream);
|
||||||
|
FSEventStreamInvalidate(stream);
|
||||||
|
FSEventStreamRelease(stream);
|
||||||
|
}
|
||||||
|
if (sem) {
|
||||||
|
dispatch_release(sem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolicyWatcher::AddStringPolicy(const std::string name) {}
|
void PolicyWatcher::AddStringPolicy(const std::string name)
|
||||||
void PolicyWatcher::AddNumberPolicy(const std::string name) {}
|
{
|
||||||
void PolicyWatcher::OnExecute(Napi::Env env) {}
|
policies.push_back(std::make_unique<StringPolicy>(name, productName));
|
||||||
void PolicyWatcher::Execute(const ExecutionProgress &progress) {}
|
}
|
||||||
void PolicyWatcher::OnProgress(const Policy *const *policies, size_t count) {}
|
void PolicyWatcher::AddNumberPolicy(const std::string name)
|
||||||
void PolicyWatcher::Dispose() {}
|
{
|
||||||
|
policies.push_back(std::make_unique<NumberPolicy>(name, productName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyWatcher::AddBooleanPolicy(const std::string name)
|
||||||
|
{
|
||||||
|
policies.push_back(std::make_unique<BooleanPolicy>(name, productName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyWatcher::OnExecute(Napi::Env env)
|
||||||
|
{
|
||||||
|
AsyncProgressQueueWorker::OnExecute(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyWatcher::Execute(const ExecutionProgress &progress)
|
||||||
|
{
|
||||||
|
std::vector<const Policy *> updatedPolicies;
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
// Watch for changes
|
||||||
|
CFStringRef path = CFSTR("/Library/Managed Preferences/");
|
||||||
|
sem = dispatch_semaphore_create(0);
|
||||||
|
FSEventStreamContext context = {0, &sem, NULL, NULL, NULL};
|
||||||
|
stream = FSEventStreamCreate(NULL,
|
||||||
|
&fsevents_callback,
|
||||||
|
&context,
|
||||||
|
CFArrayCreate(NULL, (const void **)&path, 1, NULL),
|
||||||
|
kFSEventStreamEventIdSinceNow,
|
||||||
|
1.0,
|
||||||
|
kCFStreamEventNone);
|
||||||
|
|
||||||
|
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||||
|
FSEventStreamSetDispatchQueue(stream, queue);
|
||||||
|
FSEventStreamStart(stream);
|
||||||
|
|
||||||
|
while (!disposed)
|
||||||
|
{
|
||||||
|
updatedPolicies.clear();
|
||||||
|
bool update = false;
|
||||||
|
for (auto &policy : policies)
|
||||||
|
{
|
||||||
|
switch(policy->refresh())
|
||||||
|
{
|
||||||
|
case PolicyRefreshResult::Updated:
|
||||||
|
updatedPolicies.push_back(policy.get());
|
||||||
|
update = true;
|
||||||
|
break;
|
||||||
|
case PolicyRefreshResult::Unchanged:
|
||||||
|
updatedPolicies.push_back(policy.get());
|
||||||
|
break;
|
||||||
|
case PolicyRefreshResult::Removed:
|
||||||
|
update = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first || update)
|
||||||
|
progress.Send(&updatedPolicies[0], updatedPolicies.size());
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyWatcher::OnProgress(const Policy *const *policies, size_t count)
|
||||||
|
{
|
||||||
|
HandleScope scope(Env());
|
||||||
|
auto result = Object::New(Env());
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
Callback().Call(Receiver().Value(), {result});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
result.Set(policies[i]->name, policies[i]->getValue(Env()));
|
||||||
|
|
||||||
|
Callback().Call(Receiver().Value(), {result});
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyWatcher::Dispose()
|
||||||
|
{
|
||||||
|
disposed = true;
|
||||||
|
if (sem) {
|
||||||
|
dispatch_semaphore_signal(sem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
72
src/macos/PreferencesPolicy.hh
Normal file
72
src/macos/PreferencesPolicy.hh
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef PREFERENCES_POLICY_H
|
||||||
|
#define PREFERENCES_POLICY_H
|
||||||
|
|
||||||
|
#include <napi.h>
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include "../Policy.hh"
|
||||||
|
|
||||||
|
using namespace Napi;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class PreferencesPolicy : public Policy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PreferencesPolicy(const std::string name, const std::string &productName)
|
||||||
|
: Policy(name),
|
||||||
|
appID(CFStringCreateWithCString(NULL, productName.c_str(), kCFStringEncodingUTF8)),
|
||||||
|
key(CFStringCreateWithCString(NULL, name.c_str(), kCFStringEncodingUTF8))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~PreferencesPolicy()
|
||||||
|
{
|
||||||
|
CFRelease(appID);
|
||||||
|
CFRelease(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
PolicyRefreshResult refresh()
|
||||||
|
{
|
||||||
|
auto newValue = read();
|
||||||
|
|
||||||
|
// Check for no value or removal
|
||||||
|
if (!newValue.has_value())
|
||||||
|
{
|
||||||
|
if (!value.has_value())
|
||||||
|
return PolicyRefreshResult::NotSet;
|
||||||
|
|
||||||
|
value.reset();
|
||||||
|
return PolicyRefreshResult::Removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the value updated?
|
||||||
|
if (value != newValue)
|
||||||
|
{
|
||||||
|
value = newValue;
|
||||||
|
return PolicyRefreshResult::Updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PolicyRefreshResult::Unchanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value getValue(Env env) const
|
||||||
|
{
|
||||||
|
if (!value.has_value())
|
||||||
|
return env.Undefined();
|
||||||
|
return getJSValue(env, *value); // value.value() is only supported after macOS 10.13
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::optional<T> value;
|
||||||
|
const CFStringRef appID;
|
||||||
|
const CFStringRef key;
|
||||||
|
virtual Value getJSValue(Env env, T value) const = 0;
|
||||||
|
virtual std::optional<T> read() const = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
#endif
|
||||||
46
src/macos/StringPolicy.cc
Normal file
46
src/macos/StringPolicy.cc
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "StringPolicy.hh"
|
||||||
|
|
||||||
|
using namespace Napi;
|
||||||
|
|
||||||
|
StringPolicy::StringPolicy(const std::string name, const std::string &productName)
|
||||||
|
: PreferencesPolicy(name, productName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Value StringPolicy::getJSValue(Env env, std::string value) const
|
||||||
|
{
|
||||||
|
return String::New(env, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> StringPolicy::read() const
|
||||||
|
{
|
||||||
|
auto pref = CFPreferencesCopyAppValue(key, appID);
|
||||||
|
|
||||||
|
if (pref == NULL)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
if (CFGetTypeID(pref) != CFStringGetTypeID())
|
||||||
|
{
|
||||||
|
CFRelease(pref);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFIndex length = CFStringGetLength((CFStringRef)pref);
|
||||||
|
CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
|
||||||
|
std::vector<char> buffer(maxSize);
|
||||||
|
|
||||||
|
if (CFStringGetCString((CFStringRef)pref, buffer.data(), maxSize, kCFStringEncodingUTF8))
|
||||||
|
{
|
||||||
|
std::string result(buffer.data());
|
||||||
|
CFRelease(pref);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(pref);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
23
src/macos/StringPolicy.hh
Normal file
23
src/macos/StringPolicy.hh
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef STRING_POLICY_H
|
||||||
|
#define STRING_POLICY_H
|
||||||
|
|
||||||
|
#include <napi.h>
|
||||||
|
#include "PreferencesPolicy.hh"
|
||||||
|
|
||||||
|
using namespace Napi;
|
||||||
|
|
||||||
|
class StringPolicy : public PreferencesPolicy<std::string>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StringPolicy(const std::string name, const std::string &productName);
|
||||||
|
protected:
|
||||||
|
Value getJSValue(Env env, std::string value) const override;
|
||||||
|
std::optional<std::string> read() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
13
src/main.cc
13
src/main.cc
@ -22,7 +22,7 @@ Value CreateWatcher(const CallbackInfo &info)
|
|||||||
{
|
{
|
||||||
auto env = info.Env();
|
auto env = info.Env();
|
||||||
|
|
||||||
#ifndef WINDOWS
|
#if !defined(WINDOWS) && !defined(MACOS)
|
||||||
throw TypeError::New(env, "Unsupported platform");
|
throw TypeError::New(env, "Unsupported platform");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -57,18 +57,23 @@ Value CreateWatcher(const CallbackInfo &info)
|
|||||||
|
|
||||||
auto policyType = std::string(rawPolicyType.As<String>());
|
auto policyType = std::string(rawPolicyType.As<String>());
|
||||||
|
|
||||||
if (policyType == "string")
|
if (policyType == "string") {
|
||||||
watcher->AddStringPolicy(rawPolicyName.As<String>());
|
watcher->AddStringPolicy(rawPolicyName.As<String>());
|
||||||
else if (policyType == "number")
|
}
|
||||||
|
else if (policyType == "number") {
|
||||||
watcher->AddNumberPolicy(rawPolicyName.As<String>());
|
watcher->AddNumberPolicy(rawPolicyName.As<String>());
|
||||||
else
|
} else if (policyType == "boolean") {
|
||||||
|
watcher->AddBooleanPolicy(rawPolicyName.As<String>());
|
||||||
|
} else {
|
||||||
throw TypeError::New(env, "Unknown policy type '" + policyType + "'");
|
throw TypeError::New(env, "Unknown policy type '" + policyType + "'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watcher->Queue();
|
watcher->Queue();
|
||||||
|
|
||||||
auto result = Object::New(env);
|
auto result = Object::New(env);
|
||||||
result.Set(String::New(env, "dispose"), Function::New(env, DisposeWatcher, "disposeWatcher", watcher));
|
result.Set(String::New(env, "dispose"), Function::New(env, DisposeWatcher, "disposeWatcher", watcher));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
src/windows/BooleanPolicy.cc
Normal file
28
src/windows/BooleanPolicy.cc
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "BooleanPolicy.hh"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace Napi;
|
||||||
|
|
||||||
|
BooleanPolicy::BooleanPolicy(const std::string& name, const std::string& productName)
|
||||||
|
: RegistryPolicy(name, productName, {REG_DWORD}) {}
|
||||||
|
|
||||||
|
bool BooleanPolicy::parseRegistryValue(LPBYTE buffer, DWORD bufferSize, DWORD type) const
|
||||||
|
{
|
||||||
|
if (type != REG_DWORD || bufferSize != sizeof(DWORD))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD value = *reinterpret_cast<DWORD*>(buffer);
|
||||||
|
return (value != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value BooleanPolicy::getJSValue(Env env, bool value) const
|
||||||
|
{
|
||||||
|
return Boolean::New(env, value);
|
||||||
|
}
|
||||||
25
src/windows/BooleanPolicy.hh
Normal file
25
src/windows/BooleanPolicy.hh
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef BOOLEAN_POLICY_H
|
||||||
|
#define BOOLEAN_POLICY_H
|
||||||
|
|
||||||
|
#include <napi.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include "RegistryPolicy.hh"
|
||||||
|
|
||||||
|
using namespace Napi;
|
||||||
|
|
||||||
|
class BooleanPolicy : public RegistryPolicy<bool>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BooleanPolicy(const std::string& name, const std::string &productName);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool parseRegistryValue(LPBYTE buffer, DWORD bufferSize, DWORD type) const;
|
||||||
|
Value getJSValue(Env env, bool value) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -8,6 +8,7 @@
|
|||||||
#include "../PolicyWatcher.hh"
|
#include "../PolicyWatcher.hh"
|
||||||
#include "StringPolicy.hh"
|
#include "StringPolicy.hh"
|
||||||
#include "NumberPolicy.hh"
|
#include "NumberPolicy.hh"
|
||||||
|
#include "BooleanPolicy.hh"
|
||||||
|
|
||||||
using namespace Napi;
|
using namespace Napi;
|
||||||
|
|
||||||
@ -38,6 +39,11 @@ void PolicyWatcher::AddNumberPolicy(const std::string name)
|
|||||||
policies.push_back(std::make_unique<NumberPolicy>(name, vendorName, productName));
|
policies.push_back(std::make_unique<NumberPolicy>(name, vendorName, productName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PolicyWatcher::AddBooleanPolicy(const std::string name)
|
||||||
|
{
|
||||||
|
policies.push_back(std::make_unique<BooleanPolicy>(name, productName));
|
||||||
|
}
|
||||||
|
|
||||||
void PolicyWatcher::OnExecute(Napi::Env env)
|
void PolicyWatcher::OnExecute(Napi::Env env)
|
||||||
{
|
{
|
||||||
if ((handles[0] = CreateEvent(NULL, false, false, NULL)) == NULL)
|
if ((handles[0] = CreateEvent(NULL, false, false, NULL)) == NULL)
|
||||||
@ -64,15 +70,26 @@ void PolicyWatcher::Execute(const ExecutionProgress &progress)
|
|||||||
{
|
{
|
||||||
std::vector<const Policy *> updatedPolicies;
|
std::vector<const Policy *> updatedPolicies;
|
||||||
|
|
||||||
|
bool update = false;
|
||||||
|
updatedPolicies.clear();
|
||||||
for (auto &policy : policies)
|
for (auto &policy : policies)
|
||||||
{
|
{
|
||||||
if (policy->refresh())
|
switch (policy->refresh())
|
||||||
{
|
{
|
||||||
|
case PolicyRefreshResult::Updated:
|
||||||
updatedPolicies.push_back(policy.get());
|
updatedPolicies.push_back(policy.get());
|
||||||
|
update = true;
|
||||||
|
break;
|
||||||
|
case PolicyRefreshResult::Unchanged:
|
||||||
|
updatedPolicies.push_back(policy.get());
|
||||||
|
break;
|
||||||
|
case PolicyRefreshResult::Removed:
|
||||||
|
update = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first || updatedPolicies.size() > 0)
|
if (first || update)
|
||||||
progress.Send(&updatedPolicies[0], updatedPolicies.size());
|
progress.Send(&updatedPolicies[0], updatedPolicies.size());
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
|
|||||||
@ -24,7 +24,7 @@ public:
|
|||||||
registryKey("Software\\Policies\\" + vendorName + "\\" + productName),
|
registryKey("Software\\Policies\\" + vendorName + "\\" + productName),
|
||||||
supportedTypes(types) {}
|
supportedTypes(types) {}
|
||||||
|
|
||||||
bool refresh()
|
PolicyRefreshResult refresh()
|
||||||
{
|
{
|
||||||
auto machine = read(HKEY_LOCAL_MACHINE);
|
auto machine = read(HKEY_LOCAL_MACHINE);
|
||||||
|
|
||||||
@ -33,21 +33,31 @@ public:
|
|||||||
if (value != machine)
|
if (value != machine)
|
||||||
{
|
{
|
||||||
value = machine;
|
value = machine;
|
||||||
return true;
|
return PolicyRefreshResult::Updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return PolicyRefreshResult::Unchanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto user = read(HKEY_CURRENT_USER);
|
auto user = read(HKEY_CURRENT_USER);
|
||||||
|
|
||||||
|
// Check for no value or removal
|
||||||
|
if (!user.has_value())
|
||||||
|
{
|
||||||
|
if (!value.has_value())
|
||||||
|
return PolicyRefreshResult::NotSet;
|
||||||
|
|
||||||
|
value.reset();
|
||||||
|
return PolicyRefreshResult::Removed;
|
||||||
|
}
|
||||||
|
|
||||||
if (value != user)
|
if (value != user)
|
||||||
{
|
{
|
||||||
value = user;
|
value = user;
|
||||||
return true;
|
return PolicyRefreshResult::Updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return PolicyRefreshResult::Unchanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value getValue(Env env) const
|
Value getValue(Env env) const
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user