Allow JavaScript from Apple Events in Safari through Terminal Mac - bash

I'm writing a program that executes do javascript in Safari. The only problem is that I'm trying to make the app give its self permission to do it. I'm trying to locate the file that handles the Safari developer preferences so that I can do this. Does anyone have any idea where this might be or how to change these settings?

It's in Safari's preferences plist at ~/Library/Preferences/com.apple.Safari.plist. The key you want is AllowJavaScriptFromAppleEvents. You can set it using defaults:
#to turn it on
defaults write -app Safari AllowJavaScriptFromAppleEvents 1
#to turn it off
defaults write -app Safari AllowJavaScriptFromAppleEvents 0

The virtual keyboard thing did not work for me. As StarPlayr at apple's develepoer forum has found out the problem is in something else.
For me problem occurred when i tried to do that on remote mac.
For some people plugging in a keyboard and mouse to the Server allowed to turn on JavaScript Apple Events in Safari and set the password.
However, for me that wasn't an option, so the next best thing is use an accessbility scripting feature and have the machine think a user is doing the clicks, allowing you to set the password:
-- The delays can be shorter, coordinates may vary
-- Best way to get the coordinates is with Apple screen capture (command-shift-3) from upper right to lower left (the coordinates will be shown)
-- if one spends the time, the click events can be converted to Accessibility AppleScript objects by capturing them as variables, or checking the events and using the events instead of the click coordinates
tell application "System Events"
tell application "Safari"
activate
end tell
delay 1
-- click develop menu (make sure its on first)
click at {430, 12}
delay 1
-- click Allow Javascript menu from Apple Events
click at {615, 615}
delay 1
-- Click the Allow Button
click at {1010, 386}
end tell

Related

Is there a way to pause a YouTube video in Google Chrome using AppleScript?

What I'm trying is to type tell application "Google Chrome" to pause and make audio or video in Google Chrome pause. It wouldn't work, since it thinks pause is a variable.
Is there any way to either pause audio or video in all applications or just Google Chrome?
From comments:
The following example AppleScript code will play/pause a YouTube video in the active tab of the front window of Google Chrome: tell application "Google Chrome" to tell active tab of front window to execute javascript "document.getElementsByClassName('ytp-play-button ytp-button')[0].click();"
#user3439894 this one works perfectly, since I only want to pause the video in the active tab. Is there any way to check if the video is paused so it doesn't unpause a video? Also could you write this comment as an answer so I can accept it as the correct answer?
There may be an easier way using JavaScript to ascertain if the active tab of the front window in Google Chrome has a YouTube video playing, however, as I do not know the code for it, here is a way that works for me.
The following example AppleScript code, shown below, was tested in Script Editor under macOS Catalina 10.15.7 and macOS Big Sur 11.2.3 using Google Chrome (Version 90.0.4430.93 (Official Build) (x86_64)) with Language & Region settings in System Preferences set to English (US) — Primary and worked for me without issue1.
1 Assumes necessary and appropriate setting in System Preferences > Security & Privacy > Privacy have been set/addressed as needed.
Example AppleScript code:
if not running of ¬
application "Google Chrome" then return
tell application "Google Chrome"
if (window count) = 0 then return
set atx to the active tab index of its front window
end tell
tell application "System Events"
-- # macOS Big Sur System Events bug issue.
-- # If running macOS Big Sur, uncomment the next
-- # two lines if System Events reports an error.
-- run
-- delay 0.5
tell application process "Chrome"
if (the value of ¬
attribute "AXTitle" of ¬
radio button atx of ¬
tab group 1 of ¬
group 1 of ¬
the front window) ¬
does not end with "Audio playing" then return
end tell
end tell
tell application "Google Chrome" to ¬
tell the active tab of its front window to ¬
execute javascript ¬
"document.getElementsByClassName('ytp-play-button ytp-button')[0].click();"
Notes:
As coded, the execute javascript only happens if there is a YouTube video playing in the active tab of the front window of Google Chrome, thus pausing it. The code, as coded, cannot cause a paused video to play, regardless of the active tab or any tab of any window.
The -- # macOS Big Sur System Events bug issue. section in the example AppleScript code is an attempted workaround to a System Events issue in macOS Big Sur, in that the exact same code without it runs without issue in macOS Catalina and may not work or needs adjusting. I am still trying to troubleshoot the issue in general. In my experience the issue has not been reproducible at will and as such alternate methods may have to be used if issue continues and cannot be diagnosed.
Use of other than exact versions tested under may be partially to blame for some errors, especially any that involve a change in the hierarchical UI element structure in any UI Scripting scenario using System Events.
Is there any way to either pause audio or video in all applications or just Google Chrome?
Typically pressing the Play/Pause key on the keyboard should pause a video in Google Chrome, and most other apps as well.
It wouldn't work, since it thinks pause is a variable.
pause is not part of the AppleScript dictionary in Google Chrome and why it shows as a variable.
In Google Chrome, running AppleScript code containing JavaScript needs the Allow JavaScript from Apple Events menu item checked under: View > Developer -- Note that this used to be the default, however, at some time is was changed. For more information: https://support.google.com/chrome/?p=applescript
Note: The example AppleScript code is just that and sans any included error handling does not contain any additional error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors. Additionally, the use of the delay command may be necessary between events where appropriate, e.g. delay 0.5, with the value of the delay set appropriately.
This following AppleScript code will pause or play any instance of a YouTube video in any tab of any window in Google Chrome (whether visible or not).
pauseOrPlayYoutubeInChrome("ytp-play-button ytp-button", 0)
to pauseOrPlayYoutubeInChrome(theClassName, elementnum)
tell application "Google Chrome"
set youtubeTabsRef to a reference to (tabs of windows whose URL contains "youtube")
repeat with youtubeTabs in youtubeTabsRef
execute youtubeTabs javascript "document.getElementsByClassName('" & ¬
theClassName & "')[" & elementnum & "].click();"
end repeat
end tell
end pauseOrPlayYoutubeInChrome
My solution consists of running 2 AppleScript in a specific environment.
It works for me using 1 window of Brave Browser(I think it is the same for google chrome) with 2 tabs on youtube.
First script force opening Brave browser, second run keystroke "K"
tell application "Brave Browser"
if it is not running then launch
activate
end tell
tell application "System Events"
keystroke "k"
end tell
I have created a Quick Action on Automator and then I have followed this answer: https://apple.stackexchange.com/a/401262
And when trying to test it as a Keyboard Shortcut when using another Application, I was receiving an error like this "com.automator.runner.xpc is not allowed to send keystrokes", so I realised that I need to give accessibility privileges(on Security and Privacy) to all applications I want the script to work.
And After that, it works, but sometimes it gives the same error and it works again after some minutes(and never come back again) so I think this can help someone too.
This will pause or play the youtube video on the tab of the Brave Browser that is active.

AppleScript to block Safari pop-up windows

I am trying to automate the blocking of pop-up windows in Safari.
I have tried the following defaults write operation
defaults write com.apple.Safari WebKit2JavaScriptCanOpenWindowsAutomatically -boolean false
But this fails to do it. I have also tried setting it as true but even that didn't help. I am currently trying to find a way to do it using AppleScript.
This is what I have written so far -
CMD_ACTIVATE='tell application "Safari" to activate'
CMD_NEWTAB='tell application "System Events" to keystroke "," using {command down}'
osascript -e "$CMD_ACTIVATE" -e "$CMD_NEWTAB"
This opens up the preferences but then I draw a blank. Anyone with any suggestions on how to proceed? Also I don't really need a solution to this only in AppleScript any other way to do it would also be helpful.
Note: I have been using Mac OS only for a week now, and am not that well versed in the nuances of this OS, so please be a bit descriptive when answering.
Thanks.
Blocking pop-up window is done via Safari / preferences / tab Security where you need to set the correct checkbox.
This preference seems to be stored in your library / preferences file com.safari.plist which contains the flag com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically with value Yes when pop-up are blocked.
However, it may not be the only place to be changed and in any cases, it is not officially documented, so that place can be changed by Apple any time. This is not recommended to use it.
Going back to Applescript, because Safari is quite poor in terms of applescript handling events, you are forced to go via GUI scripting. That’s what you’ve started, but keep in mind that if Apple changes the layout of Safari preference window, your script must be reviewed.
When going through GUI scripting (which, again, should only be when no other solution found) you must understand structure of GUI objects. Window contains button, check box, tool bar... in a hierarchy model. For instance the preference window in Safari contains bellow the tool bar, an object "group 1" with itself contains many objects depending of the tool bar current selection. Once you understand that concept, the script below, which does what you're looking for, will be easy to understand with many comments:
tell application "Safari" to activate
tell application "System Events"
keystroke "," using {command down}
delay 0.2 -- leave sometime to open window
tell window 1 of process "Safari"
click button 6 of toolbar 1 -- Security button is number 6
delay 0.2
-- check if check box not yet set and set it.
if (value of checkbox 5 of group 1 of group 1) = 0 then click checkbox 5 of group 1 of group 1
end tell
delay 0.2
click button 1 of window 1 of process "Safari" -- click on red / close button
end tell
I am running on Safari 10.0.3. If your version is different, the preference window may be different. Then the script must be adjusted: the Security tab button may not longer be the number 6 in your version,...

OSX: Lock the screen programmatically

I'm looking for a way to lock the user screen programmatically without putting the Mac asleep.
Right now, i'm able to trigger the lock screen with the kAESleep event but it's more a hack and it put the computer asleep.
Is it possible ?
Thanks
Configure the screensaver to require a password immediately after it starts, then start the screensaver programmatically. I have it programmed to a keyboard shortcut to help my Windows folks transition to using real computers ;).
The following AppleScript will do it for you. Note that because of security limitations of OSX, AppleScript pauses for five seconds before it executes an UI function, so it takes a small while to function. I'm using Quicksilver to bind it to a hotkey.
(As a bonus, this script will also pause a couple of your music players. Feel free to remove those lines.)
#
# Tell our noisy programs to shut up
#
tell application "Spotify"
pause
end tell
tell application "iTunes"
pause
end tell
#
# Lock up the screen without going to sleep. Needs that Keychain Access
# is set up properly.
#
tell application "System Events" to tell process "SystemUIServer" to click (first menu item of menu 1 of ((click (first menu bar item whose description is "Keychain menu extra")) of menu bar 1) whose title is "Lock Screen")
You will need to set up Keychain Access so that it has the lock icon on screen though.
I was successfully able to lock the screen on macOS in python with the following
import ctypes, ctypes.util
login = ctypes.CDLL( '/System/Library/PrivateFrameworks/login.framework/login' )
login.SACLockScreenImmediate()
I discovered this by scarce information on the Internet and trial-and-error. As far as I know, Apple doesn't document the SACLockScreenImmediate() function at all.
If anyone can find the official reference documentation for the "Login Framework" library, please drop it in the comments :)
Source
The is used in the BusKill app, which locks the screen when a magnetic breakaway connection in a USB Dead Man Switch is severed:
https://github.com/BusKill/buskill-app/tree/master/src/packages/buskill

Positioning windows with applescript on dual monitors

I have 2 air applications that I wrote. They auto fullscreen after 10 seconds. Before then, they need to be sent to their proper displays. "app_1" needs to run on display 1, "app_2" needs to run on display 2.
Essentially, I have this code:
do shell script "cd /Applications/app_1.app/Contents/MacOS/ ; open app_1;"
which works for me flawlessly. Both apps are launched that way, and there is some code for ensuring that the apps weren't already open, and closing them if they were.
I tried to add in a script to position the app after it is launched:
do shell script "cd /Applications/app_1.app/Contents/MacOS/ ; open app_1;"
tell first window of application "app_1" to set bounds to {0,0,1920,1080}
This gives me an error:
app_1 got an error: Can't set bounds of window 1 to {0,0,1920,1080}
I tried adding a delay of a couple seconds before the set bounds, in case the application hadn't yet launched when the set bounds fired off, however this didn't change anything.
I also tried setting the bounds to something like {100,100,200,200} just to see if I had the screen coordinates wrong or something, but still the exact same error, only with the {100,100,200,200} instead of the original 1920x1080 coordinates.
Anyone have any insight on this? I've been trying to find the solution on google for a couple of hours now.
It sounds like your app isn't exposing the standard "window" class. I don't know if AIR apps are supposed to automatically take care of this and it's not working—if so, you'll want to debug that.
But another alternative is to use UI Scripting to control its windows externally. Instead of this:
tell first window of application "app_1" to set bounds to {0,0,1920,1080}
Do this:
tell application "System Events"
set position of first window of application process "app_1" to {0, 0}
set size of first window of application process "app_1" to {1920,1080}
end tell
However, this will only work if you've gone to the Universal Access pane of System Preferences and checked "Enable access for assistive devices" (or done the same via API, "sudo touch /var/db/.AccessibilityAPIEnabled", etc.).

How to tell if a menu item is 'checked'?

I'm building an Applescript that will scan my network every X minutes, checking for my house's Xbox360 or PS3 and enabling my Transmission BitTorrent client Speed-Limit Mode when either console is online.
Currently I can only Pause all transfers or resume all transfers using applescript, as there are separate key-commands for start/stop transfer. I want it to go into speed-limit mode though, not stop completely.
My issue is that the Speed-Limit (Turtle) mode is the same key to turn it on/off. If anyone touches the speed-limit manually, it will be out of sync and will actually turn speed-limit off when the consoles come online. Also if one console comes online, the speed-limit will come on, but then if the other console comes on, the limit will be turned off.
The menu item becomes 'checked' when the speed-limit is active, but I do not know how to test for this. There was nothing in the applescript dictionary for the transmission app.
How can I determine whether a menu item is 'checked'(It even shows an actual check-mark) in Applescript?
[Edit:] I'm currently trying to figure out how to turn the Speed-Limit on via RPC, rather than trying to script it using the GUI or keycommands, since the developers don't provide any applescript access.
http://trac.transmissionbt.com/browser/trunk/doc/rpc-spec.txt
I had the exact same issue, and finally figured out how to check if Transmission's Speed Limit menu item is checked (and you could easily modify this to check for menu items in other applications). This has been dead for almost a year now, but hopefully this helps.
tell application "Transmission" to activate
tell application "System Events"
tell process "Transmission"
set speedLimitCurrentlyOn to (value of attribute "AXMenuItemMarkChar" of menu item "Speed Limit" of menu "Transfers" of menu bar 1 as string) ≠ ""
display dialog "Speed Limit On: " & speedLimitCurrentlyOn
end tell
end tell
PS:
I adapted this from the AppleScript here: http://mac.softpedia.com/progDownload/Transmission-Auto-Speed-Limit-Download-60275.html
What information you are able to divine from any given application via AppleScript is entirely up to said application's developer. If Transmission doesn't define any way for you to determine this state, then you're not going to be able to do so with any degree of reliability.
It would make far more sense to invest $40-$50 in a router with quality of service controls that would allow you to prioritize your network traffic by port or by device.

Resources