Created
June 26, 2025 01:38
-
-
Save smx-smx/26b340d8bc11dd9d68e59291b6743cc5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// kiosk.js | |
// forces a macOS app to be in presentation mode 3 (hide dock, hide menu bar) | |
// tracks fullscreen enter/exit and alt-tab, restoring the desired state in case it was changed by the OS | |
'use strict'; | |
console.log("Frida script starting (presentation10.js - with fullscreen hooks)..."); | |
if (ObjC.available) { | |
console.log("Objective-C runtime is available."); | |
try { | |
// --- Assume standard setup is here (NSApplication, NSNotificationCenter, NSOperationQueue, etc.) --- | |
const NSApplication = ObjC.classes.NSApplication; | |
if (!NSApplication) { throw new Error("NSApplication class not found."); } | |
const app = NSApplication.sharedApplication(); | |
if (!app || app.isNull()) { throw new Error("NSApplication.sharedApplication() is null or invalid."); } | |
const NSNotificationCenter = ObjC.classes.NSNotificationCenter; | |
if (!NSNotificationCenter) { throw new Error("NSNotificationCenter class not found."); } | |
const defaultCenter = NSNotificationCenter.defaultCenter(); | |
if (!defaultCenter || defaultCenter.isNull()) { throw new Error("NSNotificationCenter.defaultCenter() is null or invalid."); } | |
const NSOperationQueue = ObjC.classes.NSOperationQueue; | |
if (!NSOperationQueue) { throw new Error("NSOperationQueue class not found."); } | |
const mainQueue = NSOperationQueue.mainQueue(); | |
if (!mainQueue || mainQueue.isNull()) { throw new Error("NSOperationQueue.mainQueue() is null or invalid."); } | |
// --- Define Presentation Options (same as before) --- | |
const NSApplicationPresentationHideDock = (1 << 1); // 2 | |
const NSApplicationPresentationHideMenuBar = (1 << 3); // 8 | |
const desiredOptions = NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar; // 10 | |
console.log("Frida: Using desiredOptions value: " + desiredOptions); | |
// --- applyPresentationOptions function (same as before) --- | |
function applyPresentationOptions(reason) { | |
const currentApp = NSApplication.sharedApplication(); | |
if (currentApp && !currentApp.isNull()) { | |
console.log(`Frida: [applyPresentationOptions on ${reason}] Attempting: ${desiredOptions}`); | |
currentApp.setPresentationOptions_(desiredOptions); | |
const newOptions = currentApp.presentationOptions(); | |
console.log(`Frida: [applyPresentationOptions on ${reason}] Current after set: ${newOptions}`); | |
if (newOptions != desiredOptions) { | |
// Check if fullscreen is part of the new options | |
const isFullScreenActive = (newOptions & (1 << 10)) === (1 << 10); // NSApplicationPresentationFullScreen | |
// Check if our specific HideMenuBar flag is still there or got overridden | |
const isMenuBarHidden = (newOptions & NSApplicationPresentationHideMenuBar) === NSApplicationPresentationHideMenuBar; | |
console.warn(`Frida: [applyPresentationOptions on ${reason}] Options changed. Current: ${newOptions} (FullScreenActive: ${isFullScreenActive}, MenuBarExplicitlyHidden: ${isMenuBarHidden}), Desired: ${desiredOptions}`); | |
} | |
} else { | |
console.error(`Frida: [applyPresentationOptions on ${reason}] NSApplication.sharedApplication() is null.`); | |
} | |
} | |
// --- Initial application of options (same as before) --- | |
console.log("Frida: Scheduling initial applyPresentationOptions call..."); | |
ObjC.schedule(ObjC.mainQueue, function() { // Using ObjC.mainQueue (GCD) for initial call | |
console.log("Frida: [ObjC.mainQueue] Initial applyPresentationOptions call."); | |
applyPresentationOptions("initial load via ObjC.mainQueue"); | |
console.log("Frida: [ObjC.mainQueue] Initial call finished."); | |
}); | |
// --- Helper to create NSString for notification names --- | |
function getNSString(jsString) { | |
if (ObjC.classes.NSString) { | |
const cString = Memory.allocUtf8String(jsString); | |
const nsString = ObjC.classes.NSString.stringWithUTF8String_(cString); | |
if (!nsString || nsString.isNull()) { | |
throw new Error("Failed to create NSString for: " + jsString); | |
} | |
console.log("Frida: Created NSString for '" + jsString + "': " + nsString); | |
return nsString; | |
} else { | |
throw new Error("NSString class not found."); | |
} | |
} | |
// --- Helper to add an observer --- | |
function addNotificationObserver(notificationNameString, callbackReason) { | |
const nsNotificationName = getNSString(notificationNameString); | |
const callbackBlock = new ObjC.Block({ | |
retType: 'void', | |
argTypes: ['object'], // NSNotification * | |
implementation: function(notification) { | |
console.log("Frida: Received " + notificationNameString + "!"); | |
// The block is already called on the 'mainQueue' (NSOperationQueue) we specify. | |
// The notification object might contain the window, useful for debugging: | |
// console.log("Frida: Notification object: " + notification.toString()); | |
// console.log("Frida: Window from notification: " + notification.object().toString()); | |
applyPresentationOptions(callbackReason); | |
} | |
}); | |
console.log("Frida: Created ObjC.Block for " + notificationNameString); | |
defaultCenter.addObserverForName_object_queue_usingBlock_( | |
nsNotificationName, | |
null, // object: observe notifications from any sender (any window) | |
mainQueue, // queue: NSOperationQueue on which the block should be executed | |
callbackBlock | |
); | |
console.log("Frida: Subscribed to " + notificationNameString); | |
} | |
// --- Observe NSApplicationDidBecomeActiveNotification (your existing working observer) --- | |
addNotificationObserver("NSApplicationDidBecomeActiveNotification", "AppDidBecomeActive"); | |
// --- Observe Window Fullscreen Notifications --- | |
addNotificationObserver("NSWindowDidEnterFullScreenNotification", "WindowDidEnterFullscreen"); | |
addNotificationObserver("NSWindowDidExitFullScreenNotification", "WindowDidExitFullscreen"); | |
// Optional: Observe WillEnter/WillExit if DidEnter/DidExit aren't responsive enough | |
// addNotificationObserver("NSWindowWillEnterFullScreenNotification", "WindowWillEnterFullscreen"); | |
// addNotificationObserver("NSWindowWillExitFullScreenNotification", "WindowWillExitFullscreen"); | |
console.log("Frida: Script setup complete. Monitoring for activation and fullscreen events."); | |
} catch (error) { | |
console.error("Frida: Top-level script error: " + error.message + "\nStack:\n" + error.stack); | |
} | |
} else { | |
console.log("Frida: Objective-C runtime not available."); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment