Detect removal of restriction of devices - javascript

Using getUserMedia to let user select microphone. Further I use enumerateDevices to create a select with devices so that user can change device from UI.
I am on Firefox and have not checked how others browsers fare, but at least for FF I have not found a solution.
If user selects to not allow access when asked one do not get to ask again[ 1 ] until user removes the restriction:
Question is if there is a way to detect when user removes the restriction?
Scenario is typically:
User loads page and are asked to select input device
User rejects
UI disables device selector + hide various stuff
User removes restriction (as per picture above)
UI enables device selector + unhide various stuff
There is (obviously) not a way to reset the block from client side by Java Script, but is there a way to detect that user revokes the block? (Or is there? Sounds like something that could be exploited to keep looping a request for access.)
One could do a loop where one keep trying for the lifetime of the page, but would like to avoid that. Looking for an event for this.
In that regard, ondevicechange, does not trigger an event when block is removed - which is logical in a way as there is not a change in the available devices, in a way :P.
[ 1 ] That is: one can ask, but it result in a:
MediaStreamError
message: The request is not allowed by the user agent or the platform in the current context.
name: NotAllowedError
​

You should be able to detect this change from the Permissions API.
The PermissionStatus object returned by Permissions.prototype.query() has an onchange event handler. So a query to the "camera" or "microphone" will fire its change event when the user changes their setting.
const camera_perm = await navigator.permissions.query( { name: 'camera' } );
camera_perm.onchange = (evt) => {
const allowed = camera_perm.state === "granted";
if( allowed ) {
// ...
}
else {
}
};
This currently works in Chrome, but Firefox still doesn't support neither the "camera" nor the "microphone" members of PermissionDescriptor.
So for that browser, the closest we can have is through polling, as explained in this Q/A: Event listener that "camera and microphone blocked" is allowed .

Related

Delete USB history (regedit) with script

I have a javascript and Powershell script allowing to detect a usb plug, and which shows me a pop up. Indeed, my script only detects new usb keys that have not yet been plugged into the system. That's why I would like to delete the usb key history from my computer, like USB OBLIVION does, in order to have as a new connection to each usb plug.
I don't see what I need to add to my script... I have already tried deleting the content of:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB
Thanks
You could try these, but don't forget to wipe the from them other 3 paths as well
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\SWD\WPDBUSENUM
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Portable Devices\Devices\
You could also consider using WMI Event subscriptions, this works whatever the usb key is already known or not, but do not clear the registry :
to detect usb plug :
Register-CIMIndicationEvent –Query `
"Select * From __InstanceCreationEvent Within 1 Where TargetInstance IsA 'Win32_LogicalDisk'" `
–SourceIdentifier "WMIInsert" –Action { Write-Host `
"$($Event.SourceEventArgs.NewEvent.TargetInstance.Name) plugged!`n" }
to detect usb ejection :
Register-CIMIndicationEvent –Query `
"Select * From __InstanceDeletionEvent Within 1 Where TargetInstance IsA 'Win32_LogicalDisk'" `
–SourceIdentifier "WMIEject" –Action { Write-Host `
"$($Event.SourceEventArgs.NewEvent.TargetInstance.Name) ejected!`n" }
Within 1 means to detect every one second. Depending on your needs, you can configure Within 30 for example to look it for every 30 seconds (every plug or ejection in the meantime are captured as well).
the -Action parameter let you do whatever you want since this is a scriptblock (In the example I provided the event is only displayed to the console).
And do not forget that StackOverflow is not a free coding service, so next time, please share the piece of code where you have got a problem or a bug.

Chrome, allow autoconnect for HID device

So I'm trying to read out a USB-scale thats connected to my pc. I use chrome's experimental HID api.
I use Tampermonekey as userscript injector to extend a website's functionality.
The script I inject looks like this:
navigator.hid.requestDevice({ filters: [{ vendorId: 0x0922, productId: 0x8003}] }).then((devices) => {
if (devices.length == 0) return;
devices[0].open().then(() => {
if(disconnected) {
disconnected = false
}
console.log("Opened device: " + devices[0].productName);
devices[0].addEventListener("inputreport", handleInputReport);
devices[0].sendReport(outputReportId, outputReport).then(() => {
console.log("Sent output report " + outputReportId);
});
});
});
When I run it just like this(inline) I get the message in chrome:
DOMException: Failed to execute 'requestDevice' on 'HID': Must be handling a user gesture to show a permission request.
Basically, the code needs to be inside an event listener and the listener needs to be triggered by user input to run.
Al fine and dandy, except that this has to be initialized hundreds of times a day. I tried running this code in edge and here it just works without user input.
Is there a way I can disable this security feature(completely or only for the site im using it on) in chrome? I know edge is based on chromium so I expect it to be possible, but am unable to find how/where
You can use HID.getDevices() to retrieve an HID device that the user has already granted access to.
My suggestion would be to check for the device you want with getDevices first. If you can't find the device, then make something the user can interact with that will allow you to use requestDevice to connect to the device.

Why does jquery return different values than the values submitted?

Update:
Please see the answer noted below as, ultimately, the problem had nothing to do with jsquery.
=============
Issue:
I submit an object to jquery to convert into a serialized string that will become part of a "POST" request to a server, and the data returned from the serialization request is different than the data sent on many occasions.
An example:
The JavaScript code that implements the server POST request:
function send_data(gpg_data) {
var query_string;
query_string = '?' + $.param(gpg_data, traditional = true);
console.log('gpg_data =', gpg_data)
console.log('query_string =', query_string);
$.post(server_address + query_string);
return;
}
This is the structure sent to the jquery param() function.
(copied from the browser console in developer mode.)
gpg_data =
{controller_status: 'Connected', motion_state: 'Stopped', angle_dir: 'Stopped', time_stamp: 21442, x_axis: 0, …}
angle_dir: "Stopped"
controller_status: "Connected"
force: 0
head_enable: 0
head_x_axis: 0
head_y_axis: 0
motion_state: "Stopped"
time_stamp: 21490
trigger_1: 0
trigger_2: 0
x_axis: 0
y_axis: "0.00"
. . . and the returned "query string" was:
query_string = ?controller_status=Connected&motion_state=Stopped&angle_dir=Stopped&time_stamp=21282&x_axis=0&y_axis=0.00&head_x_axis=0&head_y_axis=0&force=0&trigger_1=1&trigger_2=1&head_enable=0
The data received by the server is:
ImmutableMultiDict([('controller_status', 'Connected'), ('motion_state', 'Stopped'), ('angle_dir', 'Stopped'), ('time_stamp', '21282'), ('x_axis', '0'), ('y_axis', '0.00'), ('head_x_axis', '0'), ('head_y_axis', '0'), ('force', '0'), ('trigger_1', '1'), ('trigger_2', '1'), ('head_enable', '0')])
For example, note that "trigger_1" returns 1 when the data sent to it is a zero.
I have tried setting the query to "traditional = true" to revert to an earlier style of query handling as some articles suggested - which did not work.  I tried this with jquery 3.2 and 3.6.
I am not sure exactly how jquery manages to munge the data so I have no idea where to look.
I have looked at my script and at the unpacked jquery code, and I can make no sense out of why or how it does what it does.
Any help understanding this would be appreciated.
P.S.
web searches on "troubleshooting jquery" returned very complex replies that had more to do with editing e-commerce web pages with fancy buttons and logins than with simply serializing data.
P.P.S.
I am tempted to just chuck the jquery and write my own serialization routine. (grrrr!)
===================
Update:
As requested, a link to the browser-side context.
To run: unpack the zip file in a folder somewhere and attach an analog joystick/gamepad to any USB port, then launch index.html in a local browser.  Note that a purely digital gamepad - with buttons only or with a joystick that acts like four buttons - won't work.
You will want to try moving joystick axes 1 and 2, (programmatically axes 0 and 1) and use the first (0th) trigger button.
You will get a zillion CORS errors and it will complain bitterly that it cannot reach the server, but the server side context requires a GoPiGo-3 robot running GoPiGo O/S 3.0.1, so I did not include it.
Note: This does not work in Firefox as Firefox absolutely requires a "secure context" to use the Gamepad API.  It does work in the current version of Chrome, (Version 97.0.4692.99 (Official Build) (64-bit)), but throws warnings about requiring a secure context.
Please also note that I have made every attempt I know how to try to troubleshoot the offending JavaScript, but trying to debug code that depends on real-time event handling in a browser is something I have not figured out how to do - despite continuous searching and efforts.  Any advice on how to do this would be appreciated!
======================
Update:
Researching debugging JavaScript in Chrome disclosed an interesting tidbit:
Including the line // #ts-check as the first line in the JavaScript code turns on additional "linting" (?) or other checks that, (mostly) were a question of adding "var" to the beginning of variable declarations.
However. . . .
There was one comment it made:
gopigo3_joystick.x_axis = Number.parseFloat((jsdata.axes[0]).toFixed(2));
gopigo3_joystick.y_axis = Number.parseFloat(jsdata.axes[1]).toFixed(2);
I could not assign gopigo3_joystick.y_axis to a string object, (or something like that), and I was scratching my head - that was one of the pesky problems I was trying to solve!
If you look closely at that second line, you will notice I forgot a pair of parenthesis, and that second line should look like this:
gopigo3_joystick.y_axis = Number.parseFloat((jsdata.axes[1]).toFixed(2));
Problem solved - at least with respect to that problem.
I figured it out and it had nothing to do with jquery.
Apparently two things are true:
The state of the gpg_data object's structure is "computed", (snapshot taken), the first time the JavaScript engine sees the structure and that is the state that is saved, (even though the value may change later on). In other words, that value is likely totally bogus.
Note: This may only be true for Chrome. Previous experiments with Firefox showed that these structures were updated each time they were encountered and the values seen in the console were valid. Since Firefox now absolutely requires a secure context to use the gamepad API, I could not use Firefox for debugging.
I was trying to be "too clever". Given the following code snippet:
function is_something_happening(old_time, gopigo3_joystick) {
if (gopigo3_joystick.trigger_1 == 1 || gopigo3_joystick.head_enable == 1) {
if (old_time != Number.parseFloat((gopigo3_joystick.time_stamp).toFixed(0))) {
send_data(gopigo3_joystick)
old_time = gopigo3_joystick.time_stamp
}
}
return;
}
The idea behind this particular construction was to determine if "something interesting" is happening, where "something interesting" is defined as:
A keypress, (handled separately)
A joystick movement if either the primary trigger or the pinky trigger is pressed.
Movement without any trigger pressed is ignored so that if the user accidentally bumps against the joystick, the robot doesn't go running around.
Therefore the joystick data only gets updated if the trigger is pressed. In other words, trigger "release" events - the trigger is now = 0 - are not recorded.
The combination of these two events - Chrome taking a "snapshot" of object variables once and once only, (or not keeping them current) - and the trigger value persisting, lead me to believe that jquery was the problem since the values appeared to be different on each side of the jquery call.

Problems in playing Fairplay Encrypted content on Safari browser

We are trying to write player in Javascript which should play fairplay encrypted content on safari browser. We figured 'encrypted' event is not supported on Safari browser and we added event listener for 'WebKitNeedKey' event. We coded the flow as below.
addEventListener('webkitneedkey, onWebKitNeedKey);
onWebKitNeedKey(evt) {
videoElement = document.getElementById('videoID');
if (videoElement.webkitKeys) {
videoElement.webkitSetMediaKeys(new WebKitMediaKeys('com.apple.fps.2_0'));
}
const session = videoElement.webkitKeys.createSession('video/mp4', event.initData);
session.addEventListener('webkitkeymessage', onWebKitKeyMessage);
session.addEventListener('webkitkeyerror', onWebKitKeyError);
session.addEventListener('webkitkeyadded', onWebKitKeyAdded);
}
onWebKitKeyMessage(evt) {
console.log(`received webkit key message : ${evt}`);
}
onWebKitKeyError(evt) {
console.log(`received webkit key error : ${evt}`);
}
onWebKitKeyAdded(evt) {
console.log(`received webkit key added : ${evt}`);
}
Now I am getting the webkitneedkey event and after setting the keys, I am getting webkitkeymessage event. I am planning to implement the logic of contacting the server for the license as per https://github.com/WebPlatformForEmbedded/WPEWebKit/blob/master/LayoutTests/http/tests/media/clearkey/clear-key-hls-aes128.html
I have following questions. Can any one please help me to resolve the below questions?
1) Do we need to set the source to '.m3u8'? Is it mandatory? I am getting the events even without setting the source to .m3u8
2) Is my approach correct in onWebKitNeedKey? Can I send evt.initData directly to webkitSetMediaKeys without modifying? Do I need to extract the content ID from evt.initData if I use key as 'com.apple.fps.2_0' instead of 'com.apple.fps.1_0'?

How to programmatically trigger presentation mode in JavaScript add-in for PowerPoint?

We have a method to check current state of the PowerPoint document: https://msdn.microsoft.com/EN-US/library/office/dn482495.aspx
Document.getActiveViewAsync
I can also listen to changes of the state: https://msdn.microsoft.com/EN-US/library/office/dn482501.aspx
ActiveViewChanged event
And I'm already using is as follows:
var _hideArrowInPresentationMode = function(e) {
var presentationMode = (e.activeView === "read"); // can inline variable but I find 'presentationMode' more descriptive
if (presentationMode) {
$("#left").hide();
} else {
$("#left").show();
}
};
Office.context.document.addHandlerAsync(Office.EventType.ActiveViewChanged, _hideArrowInPresentationMode);
Is there an API method allowing me to trigger presentation mode?
For some reason I cannot find it in the docs.
Why do I want to trigger presentation mode? When user presses F5 it by default goes to presentation mode. However, if the focus is in the add-in, it refreshes the add-in. I'm listening for F5 key and preventing refresh but I'd like to go into presentation mode to ensure consistent behaviour.
There is currently no API in PowerPoint to enter presentation mode. Feel free to request this API on the Office Developer Platform's Uservoice!

Categories

Resources