Firefox Extension API - permissions.request may only be called from a user input handler? - firefox

I'm using the Firefox permissions API documented HERE
I'm having a problem with the request method, wherein all of my permissions requests result in:
Error: permissions.request may only be called from a user input handler
You can produce this in firefox by debugging any addon or extension and entering browser.permissions.request({origins: ["https://google.com/*"]}) into the console.
I find it hard to swallow that a permissions request must always have a user input event callback in the parent stack trace. I'm using Vue.js, and my Permissions are due to user interaction, but my user interactions are decoupled from the events they trigger.
What counts as a user input handler?
Why does it work like this?
Is there a good work-around?

Is there a good work-around"
I'd like to add onto Andrew's answer with some code examples.
As it turns out, promise chains destroy the browser's notion of what is and isn't triggered by a user input handler. Take the code below, for example:
document.getElementById('foo').addEventListener('click', event => {
browser.permissions.request({origins: ["https://google.com/*"]})
})
This code works as expected. I originally assumed that it was Vue.js's unique event handling framework that was eating my "browser events", such as when you do <div #click="somefunc"></div>. This actually works just fine, as long as you put your permissions request in somefunc.
Now it gets fun. If you replace your permissions request with a promise that resolves and then does a permissions request, VIOLA!
Promise.resolve('foobar').then(foobar => {
browser.permissions.request({origins: ["https://google.com/*"]})
})
Results in:
Error: permissions.request may only be called from a user input handler
Why does this happen?
I'm going to guess it has to do with stack traces. Firefox can't detect that a permission came from a stack with a user input event at the root if the permissions request happens in a promise chain.
I consider this to be a pretty egregious design choice. My app is large (>4K LoC) and to keep it simple I rely on promise chains to keep the spaghetti away. This has crippled my ability to write clean code, and as a result, I've moved from asking for optional_permissions and then prompting the user for permissions only when needed to just being overly permissive at the time of installation.
GG, Firefox.

What counts as a user input handler?
A DOM event handler that corresponds to user input (e.g., target.addEventHandler("click", ...) or a WebExtension event listener that corresponds to user input (e.g., browser.browserAction.onClicked.addListener(...)
Why does it work like this?
Partly for basic UX (if a user is not directly interacting with an extension and a prompt for the extension suddenly prompts up, it can easily confuse them), but also to avoid clickjacking attacks where the prompt is put up at a carefully chosen moment when the user is likely to be expecting some unrelated prompt.
Is there a good work-around?
I think just organizing your code so that you request permissions from a user input handler is probably your best bet.

Related

How to make a Finder Sync Extension change badges in response to outside events

I have a Finder Sync Extension that will display a badge on a file based on the state of a local database. It's straightforward enough to query this database in the requestBadgeIdentifierForURL function, but what if I want the badge to change for a Finder item that's already visible if the state of that database has changed (which can be via a notification through any variety of mechanisms). The documentation (https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Finder.html) would seem to imply this is possible with this statement:
You might also want to track these URLs, in order to update their
badges whenever their state changes.
The only ways I can imagine this would be possible (and most seem wrong) would be:
call setBadgeIdentifier:forURL from another application that is aware of the change
Launch a thread in the init function of my extension which listens for notifications and calls setBadgeIdentifier:forURL when it receives them
Call some OS API that prompts Finder that the extension should be triggered via requestBadgeIdentifierForURL.
Only the last one seems feasible, and could be managed via the extension informing the outside resource what needs refreshing via the beginObservingDirectoryAtURL/endObservingDirectoryAtURL callbacks, but i don't know what mechanism could do this.

Microsoft Edge browser how to read Clipboard data

I am unable to read clipboard data in Microsoft Edge browser. i am using the below javascript.
if (window.clipboardData && window.clipboardData.getData) { // IE
pastedText = window.clipboardData.getData('Text');
} else if (e.clipboardData && e.clipboardData.getData) { //non-IE
pastedText = e.clipboardData.getData('text/plain');
}
Non of the if/elseif block is executed in Edge. I tried using
e.originalEvent.clipboardData.getData('text/plain');
But I am getting 'Access is denied.' error.
Let me know, if anybody know how to fix this issue.
Edge does not currently support the clipboard api, but it is under consideration and likely to be added in near future.
I do not have edge, but it seems that you are not authorized to access the clipboard data. Is this on a website or are you calling this from within a JavaScript script executed locally?
Make sure the website is in the trusted sites.
See https://w3c.github.io/clipboard-apis/#clipboard-event-interfaces, or more precisely:
12.1 Privacy concerns
Untrusted scripts should not get uncontrolled access to a user's clipboard data. This specification assumes that granting access to the current clipboard data when a user explicitly initiates a paste operation from the user agent's trusted chrome is acceptable. However, implementors must proceed carefully, and as a minimum implement the precautions below:
Objects implementing the DataTransfer interface to return clipboard data must not be available outside the ClipboardEvent event handler.
If a script stores a reference to an object implementing the DataTransfer interface to use from outside the ClipboardEvent event handler, all methods must be no-ops when called outside the expected context.
Implementations must not let scripts create synthetic clipboard events to get access to real clipboard data except if configured to do so.
Implementations should not let scripts call document.execCommand('paste') unless the user has explicitly allowed it.
Implementations may choose to further limit the functionality provided by the DataTransfer interface. For example, an implementation may allow the user to disable this API, or configure which web sites should be granted access to it.

AutoUnlock a Windows User Session

Recently, I have been working on a CredentialProvider in order to unlock automatically (the trigger can be any event, so let’s say the end of a timer) a Windows Vista (or more recent version) user session.
For that I read some useful articles on the subject, the change between GINA and this new architecture. http://msdn.microsoft.com/en-us/magazine/cc163489.aspx.
I think, like everyone in the process of creating a custom CredentialProvider, I didn’t start from scratch but from the sample code provided by Microsoft. And then I tried to change the behaviour (things like logging) in the different functions.
So in the end I can use the custom CredentialProvider, enter the SetUsageScenario methods but still I cannot reach the Set or GetSerialization method. From what I’ve understood in the technical documentation on CredentialProvider (still provided by Microsoft) theses two methods should be called automatically. Is there something I missed ?
Also, my original idea was to get an authentication package using Kerberos in order to perform an implicit user authentication. I got this idea by seeking information on other SO or MSDN threads like
Is this approach the good one ?
Thank you very much for your time answering my questions. Any clarifications are welcomed, even if they don’t directly resolve my problems :-)
First of all - you need to set autologon flag to true in your implementation of the ICredentialProviderCredential::SetSelected(BOOL *pbAutoLogon) and ICredentialProvider::GetCredentialCount methods.
Next, you need to call ICredentialProviderEvents::CredentialsChanged when your timer is hit.
LogonUI will recreate your credentials, and because autologon is set to true it will call your GetSerialization() method.
SetSerialization and GetSerialization functions are called from your provider by LogonUI. After user enters username/password and presses ENTER button, LogonUI calls GetSerialization function and provides a pointer, as one of the four parameters, that will point in future to CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION structure created and filled by you, and then this structure will be sent from LogonUI to Winlogon to perform authentication. I don't know how to make LogonUI to call GetSerialization from your credential provider code and as far as I know you can't call GetSerialization by your own because where will you pass your filled CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION structure if no one requested it, but only LogonUI can path it to Winlogon?
There is a document called "Credential Provider Technical Reference", there you can read some details about credential providers. In the Shell samples folder there is a strange folder called "Autologon", maybe it will help you! Good Luck!

In CakePHP 1.3 is there any advantage of using $this->Controller->Session over $this->Session in a component?

I'm using a modified version of Felix Geisendörfer's SimpleAuth/SimpleAcl components that I've combined into a single Component, Simple_Authable.
I changed his startup() function to initialize() to not clutter the beforeFilter function in my app_controller.
One of the things that this component does is check who the active user is and if that user can't be found it either looks him up based on the primary User.id or uses 'guest'. Either way, the component uses $this->Controller->Session->write() to save the active user or guest information.
I'm also using Felix's Authsome plugin instead of the default CakePHP Auth component.
When I'm logging in, the active user is guest, obviously.
After I've submitted the form, the active user is still guest because the component's initialize() function is firing before everything else. Then, the Authsome plugin comes into play and validates my user as "root" and also calls $this->SimpleAuthable->setActiveUser($id, true); to force SimpleAuthable to update the active user information it is storing via $this->Controller->Session; Then I am redirected and my simple Session information and DebugKit's Session tab reflect that I am indeed the root user.
However, when I try to navigate to an 'admin' page, let's say /admin/users/index, lo and behold SimpleAuthable thinks I'm still a 'guest' user because when it performs a $this->Controller->Session->read() call to the key holding my user id, it is getting an empty response, i.e., the data stored on the previous page didn't persist.
Maybe there is something funky happening between Authsome & SimpleAuthable, but things look pretty straightforward and to my mind, $this->Controller->Session should be saving and persisting the data written to it.
So, I'm looking at refactoring all the calls to $this->Controller->Session and replacing them with $this->Session but first I wanted to throw this out to the community and see if anybody has seen anything similar and if so how did they resolve it.
Sincerely,
Christopher.
I found the problem... I'm also using Joshua McNeese's Permissionable plugin and I needed to disable it for the $this->Controller->{$this->userModel}->findById($id); in my SimpleAuthable component when I try to lookup the current active user.
Note to self: I would have caught this faster if I had some unit testing in place :(.

Session 0 Isolation

Vista puts out a new security preventing Session 0 from accessing hardware like the video card, and the user no longer logs into session 0. I know this means that I cannot show the user a GUI, however, does that also mean I can't show one at all? The way my code is set up right now, it would be more work to make it command line only, however if I can use my existing code and just programmatically manage the GUI it would take a lot less code.
Is this possible?
The article from MSDN says this:
• A service attempts to create a user interface (UI), such as a dialog box, in Session 0. Because the user is not running in Session 0, he or she never sees the UI and therefore cannot provide the input that the service is looking for. The service appears to stop functioning because it is waiting for a user response that does not occur.
Which makes me think it is possible to have an automated UI, but someone told me that you couldn't use SendKeys with a service because it was disabled in Session 0.
EDIT: I don't actually need to show the user the GUI
You can show one; it just doesn't show up.
There is a little notification in the taskbar about there being a GUI window and a way to switch to it.
Anyway, there actually is a TerminalServices API command to switch active session that you could call if you really needed it to show up.
You can write a separate process which provides the UI for your service process. The communication between your UI and service process can be done in various ways (search the web for "inter process communication" or "IPC").
Your service can have a GUI. It's simply that no human will ever see it. As the MSDN quote suggests, a service can display a dialog box. The call to MessageBox won't fail; it just won't ever return — there won't be anyone to press its buttons.
I'm not sure what you mean by wanting to "manage the GUI." Do you actually mean pretending to send input to the controls, as with SendInput? I see no reason that it wouldn't be possible; you'd be injecting input into your own program's queue, after all, and SendInput's Vista-specific warnings don't say anything about that. But I think you'd be making things much more complicated than they need to be. Revisit the idea to alter your program to have no UI at all. (That's not the same as having a console program. Consoles are UI.)
Instead of simulating the mouse messages necessary to click a button, for instance, eliminate the middle-man and simply call directly the function that the button-click event would have called.

Resources