Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permissions Configuration #615

Merged
merged 9 commits into from
Sep 26, 2023
16 changes: 16 additions & 0 deletions api/CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,22 @@ sources | |
Key | Default Value | Description
:--- | :--- | :---
root | "/" | Make root open index.html
default_index | "" | Set default 'index.html' path to open for implicit routes

# Section `permissions`

Key | Default Value | Description
:--- | :--- | :---
allow_fullscreen | true | Allow/Disallow fullscreen in application
allow_microphone | true | Allow/Disallow microphone in application
allow_camera | true | Allow/Disallow camera in application
allow_user_media | true | Allow/Disallow user media (microphone + camera) in application
allow_geolocation | true | Allow/Disallow geolocation in application
allow_notifications | true | Allow/Disallow notifications in application
allow_sensors | true | Allow/Disallow sensors in application
allow_clipboard | true | Allow/Disallow clipboard in application
allow_bluetooth | true | Allow/Disallow bluetooth in application
allow_data_access | true | Allow/Disallow data access in application
watch | false | Enable watch mode

# Section `debug`
Expand Down
28 changes: 28 additions & 0 deletions src/android/runtime.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ namespace SSC::android {
this->rootDirectory = rootDirectory;
}

bool isPermissionAllowed (const String& name) {
static const auto config = SSC::getUserConfig();
const auto permission = String("permissions_allow_") + name;

// `true` by default
if (!config.contains(permission)) {
return true;
}

return config.at(permission) != "false";
}

Runtime::~Runtime () {
this->env->DeleteGlobalRef(this->self);
}
Expand Down Expand Up @@ -149,4 +161,20 @@ extern "C" {

return true;
}

jboolean external(Runtime, isPermissionAllowed)(
JNIEnv *env,
jobject self,
jstring permission
) {
auto runtime = Runtime::from(env, self);
auto name = StringWrap(env, rootDirectory).str();

if (runtime == nullptr) {
Throw(env, RuntimeNotInitializedException);
return false;
}

return runtime->isPermissionAllowed(name);
}
}
3 changes: 3 additions & 0 deletions src/android/runtime.kt
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,7 @@ open class Runtime (

@Throws(java.lang.Exception::class)
external fun stopTimers (): Boolean;

@Throws(java.lang.Exception::class)
external fun isPermissionAllowed (permission: String): Long;
}
9 changes: 8 additions & 1 deletion src/android/window.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ open class Window (runtime: Runtime, activity: MainActivity) {
}

fun load () {
val runtime = this.runtime.get() ?: return
val isDebugEnabled = this.runtime.get()?.isDebugEnabled() ?: false
val filename = this.getPathToFileToLoad()
val activity = this.activity.get() ?: return
Expand All @@ -47,7 +48,13 @@ open class Window (runtime: Runtime, activity: MainActivity) {
activity.webview?.apply {
// features
settings.javaScriptEnabled = true
settings.domStorageEnabled = true

settings.domStorageEnabled = runtime.isPermissionAllowed("data_access")
settings.databaseEnabled = runtime.isPermissionAllowed("data_access")

settings.geolocationEnabled = runtime.isPermissionAllowed("geolocation")
settings.appCacheEnabled = true
settings.javaScriptCanOpenWindowsAutomatically = true

// allow list
settings.allowFileAccess = true
Expand Down
40 changes: 34 additions & 6 deletions src/cli/cli.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2683,6 +2683,7 @@ int main (const int argc, const char* argv[]) {
flags = "-std=c++2a -ObjC++ -v";
flags += " -framework UniformTypeIdentifiers";
flags += " -framework CoreBluetooth";
flags += " -framework CoreLocation";
flags += " -framework Network";
flags += " -framework UserNotifications";
flags += " -framework WebKit";
Expand Down Expand Up @@ -2940,6 +2941,21 @@ int main (const int argc, const char* argv[]) {

manifestContext["android_manifest_xml_permissions"] = "";

if (settings["permission_allow_geolocation"] != "false") {
manifestContext["android_manifest_xml_permissions"] += "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />\n";
manifestContext["android_manifest_xml_permissions"] += "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" />\n";
}

if (settings["permission_allow_user_media"] != "false") {
if (settings["permission_allow_camera"] != "false") {
manifestContext["android_manifest_xml_permissions"] += "<uses-permission android:name=\"android.permission.CAMERA\" />\n";
}

if (settings["permission_allow_microphone"] != "false") {
manifestContext["android_manifest_xml_permissions"] += "<uses-permission android:name=\"android.permission.CAPTURE_AUDIO_OUTPUT\" />\n";
}
}

if (settings["android_manifest_permissions"].size() > 0) {
settings["android_manifest_permissions"] = replace(settings["android_manifest_permissions"], ",", " ");
for (auto const &value: parseStringList(settings["android_manifest_permissions"])) {
Expand Down Expand Up @@ -3749,6 +3765,7 @@ int main (const int argc, const char* argv[]) {
settings["build_extensions_" + extension + "_ios_compiler_flags"] +
" -framework UniformTypeIdentifiers" +
" -framework CoreBluetooth" +
" -framework CoreLocation" +
" -framework Network" +
" -framework UserNotifications" +
" -framework WebKit" +
Expand Down Expand Up @@ -3872,6 +3889,7 @@ int main (const int argc, const char* argv[]) {
<< " -F " << iosSdkPath << "/System/Library/Frameworks/"
<< " -framework UniformTypeIdentifiers"
<< " -framework CoreBluetooth"
<< " -framework CoreLocation"
<< " -framework Foundation"
<< " -framework Network"
<< " -framework UserNotifications"
Expand Down Expand Up @@ -4643,6 +4661,7 @@ int main (const int argc, const char* argv[]) {
if (platform.mac) {
compilerFlags += " -framework UniformTypeIdentifiers";
compilerFlags += " -framework CoreBluetooth";
compilerFlags += " -framework CoreLocation";
compilerFlags += " -framework Network";
compilerFlags += " -framework UserNotifications";
compilerFlags += " -framework WebKit";
Expand Down Expand Up @@ -5476,31 +5495,40 @@ int main (const int argc, const char* argv[]) {
}
}

FileSystemWatcher* watcher = new FileSystemWatcher(sources);
auto watching = watcher->start([&](
// allow changes to 'socket.ini' to be observed
sources.push_back("socket.ini");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


FileSystemWatcher* sourcesWatcher = new FileSystemWatcher(sources);
auto watchingSources = sourcesWatcher->start([=](
const String& path,
const Vector<FileSystemWatcher::Event>& events,
const FileSystemWatcher::Context& context
) {
auto settingsForSourcesWatcher = settings;
extendMap(
settingsForSourcesWatcher,
parseINI(readFile(targetPath / "socket.ini"))
);

handleBuildPhaseForCopyMappedFiles(
settings,
settingsForSourcesWatcher,
targetPlatform,
pathResourcesRelativeToUserBuild
);

handleBuildPhaseForUserScript(
settings,
settingsForSourcesWatcher,
targetPlatform,
pathResourcesRelativeToUserBuild,
targetPath,
additionalBuildArgs,
false
);

log("file '" + path +"' did change");
log("File '" + path + "' did change");
});

if (!watching) {
if (!watchingSources) {
log("Unable to start watching");
exit(1);
}
Expand Down
74 changes: 70 additions & 4 deletions src/cli/templates.hh
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ constexpr auto gPListInfo = R"XML(<?xml version="1.0" encoding="UTF-8"?>
<string>This app needs access to the camera</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>The app would like to discover and connect to peers</string>

<key>NSLocationUsageDescription</key>
<string>{{meta_title}} would like access to your location</string>

<key>NSLocationWhenInUseUsageDescription</key>
<string>{{meta_title}} would like access to your location while open</string>

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>{{meta_title}} would like access to your location</string>

<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>LSMultipleInstancesProhibited</key>
Expand Down Expand Up @@ -317,7 +327,9 @@ constexpr auto gAndroidManifest = R"XML(
>
<activity
android:name="{{android_main_activity}}"
android:exported="true">
android:exported="true"
android:configChanges="orientation|screenSize"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Expand Down Expand Up @@ -974,12 +986,21 @@ constexpr auto gXCodePlist = R"XML(<?xml version="1.0" encoding="UTF-8"?>
</dict>
<key>NSHighResolutionCapable</key>
<true/>

<key>NSLocalNetworkUsageDescription</key>
<string>The app would like to discover and connect to peers</string>
<string>{{meta_title}} would like to discover and connect to peers</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>The app would like to discover and connect to peers</string>
<string>{{meta_title}} would like to discover and connect to peers</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>The app would like to discover and connect to peers</string>
<string>{{meta_title}} would like to discover and connect to peers</string>

<key>NSLocationUsageDescription</key>
<string>{{meta_title}} would like access to your location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>{{meta_title}} would like access to your location while open</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>{{meta_title}} would like access to your location</string>

<key>NSRequiresAquaSystemAppearance</key>
<false/>
<key>NSSupportsAutomaticGraphicsSwitching</key>
Expand Down Expand Up @@ -1426,6 +1447,51 @@ sources = "src"
; default value: "/"
root = "/"

; Set default 'index.html' path to open for implicit routes
; default value: ""
; default_index = ""

[permissions]
; Allow/Disallow fullscreen in application
; default value: true
; allow_fullscreen = true

; Allow/Disallow microphone in application
; default value: true
; allow_microphone = true

; Allow/Disallow camera in application
; default value: true
; allow_camera = true

; Allow/Disallow user media (microphone + camera) in application
; default value: true
; allow_user_media = true

; Allow/Disallow geolocation in application
; default value: true
; allow_geolocation = true

; Allow/Disallow notifications in application
; default value: true
; allow_notifications = true

; Allow/Disallow sensors in application
; default value: true
; allow_sensors = true

; Allow/Disallow clipboard in application
; default value: true
; allow_clipboard = true

; Allow/Disallow bluetooth in application
; default value: true
; allow_bluetooth = true

; Allow/Disallow data access in application
; default value: true
; allow_data_access = true

; Enable watch mode
; default value: false
watch = false
Expand Down
6 changes: 5 additions & 1 deletion src/common.hh
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,12 @@ namespace SSC {
const String& separator
) {
StringStream joined;
auto missing = vector.size();
for (const auto& item : vector) {
joined << item << separator << " ";
joined << item;
if (--missing > 0) {
joined << separator << " ";
}
}

return trim(joined.str());
Expand Down
Loading
Loading