I need to filter out certain characters when a user pastes from the clipboard. (I don't actually want to modify what's in the clipboard.) I already have this working in IE. Sigh...
tl;dr: capability.policy
items in user.js make it into prefs.js but aren't taking effect.
FYI, I can reasonably have all users install user.js. But none of us have admin access to our machines, so that's about all I can do regarding configuration.
Thanks for any help!
Note:
- For the purposes of this question, I do not want to "get around" accessing the clipboard --
E.g., I do not want to operate on the value of the DOM element after a paste occurs - I do not want a solution that requires a framework/library (like jQuery, Dojo, Prototype, YUI, ...)
Steps followed
- Determined location of my profile folder by going to URL about:support => Profile Directory => Open Containing Folder
- Tried to enable clipboard in Firefox by creating user.js with the following lines:
user_pref("just.mike", "test to see if user.js works."); user_pref("capability.policy.policynames", "allowclipboard"); user_pref("capability.policy.allowclipboard.sites", "https://my-site.com"); user_pref("capability.policy.allowclipboard.Clipboard.cutcopy", "allAccess"); user_pref("capability.policy.allowclipboard.Clipboard.paste", "allAccess");
Note: https://my-site.com isn't the real site. - As it turns out, the
capability.policy
items are not visible using about:config -- due to Bugzilla Bug 284673 - about:config hides "capability.policy" preferences. However, I do think these user.js items "worked" and that the file is in the correct folder, because afterwards:- about:config showed the
just.mike
entry - prefs.js contained all the new lines but in a different order -- alphabetized:
user_pref("capability.policy.allowclipboard.Clipboard.cutcopy", "allAccess"); user_pref("capability.policy.allowclipboard.Clipboard.paste", "allAccess"); user_pref("capability.policy.allowclipboard.sites", "https://my-site.com"); user_pref("capability.policy.policynames", "allowclipboard"); ... user_pref("just.mike", "test to see if user.js works.");
Zallowclipboard
everywhere so that thepolicynames
line came first due to alphabetization, but that didn't work either.) - about:config showed the
- Attempted to read the clipboard in Firefox after an
onpaste
event with the following:var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"].getService(Components.interfaces.nsIClipboard); if (!clipboard) { throw new Error('internal error -- could not create clipboard object'); } var transferable = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable); if (!transferable) { throw new Error('internal error -- could not create transferable object'); } transferable.addDataFlavor("text/unicode"); clipboard.getData(transferable, clipboard.kGlobalClipboard); var clipboard_data = new Object(); var clipboard_length = new Object(); transferable.getTransferData("text/unicode", clipboard_data, clipboard_length); var clipboard_text = ''; if (!!clipboard_data) { var clipboard_nsISupportsString = clipboard_data.value.QueryInterface(Components.interfaces.nsISupportsString); clipboard_text = clipboard_nsISupportsString.data.substring(0, clipboard_length.value / 2); } return(clipboard_text);
- The code fails on the first line, returning this error in the Firebug console:
Permission denied for <https://my-site.com> to get property XPCComponents.classes
Note: I am actually running it on the real URL, which does get shown in the error message -- I've just changed it to a dummy name here. - I also saw some other examples where
createInstance
was used on the first line instead ofgetService
, but the first line still generates the same error text:var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"].createInstance(Components.interfaces.nsIClipboard); // ...
Environment (This is out of my control)
- No admin access to computer
- Windows Vista
- Mozilla Firefox 10
References
In short, I don't think it's possible to do what you want to do how you want to do it. Mozilla (and most modern browsers) limit clipboard access for security reasons. That you seem to have easily gotten around this restriction in IE is not a comforting thought.
That being said, plugins have different restrictions than web pages, and you may be able to get around this limitation by writing one (or maybe even leveraging flash). Even with a plugin, though, I suspect that the only way for you to block someone from pasting something into a web form (or whatever) would be to preemptively scrub their clipboard.
If all you want to do is prevent certain strings from being entered into a text box, you're best bet is to monitor events on the text box itself.
If I'm reading you right, though, it sounds like you want to force your users to type (and only type) something into a form, and I can't think of a trivial way of doing this. A couple non-trivial options:
- Set the textbox to
readonly
, and pop-up a virtual keyboard to force the user to "type" into the box using their mouse. (You'd have to build the keyboard yourself out of HTML and JavaScript, or find a suitable solution somewhere.) - Monitor the
oninput
event; if the textbox changes more quickly then what a person could reasonably be expected to type, reject the changes.
Neither of those are exactly pretty, but if you want to create solutions using open web technologies, then you have to accept the limitations of the system you're building on top of, as well as its benefits.
Grubby but crossbrowser way is to compare value of current input with previous on onchange event.
If it's length increased or value differs too much (not only reduсed but have a lot of new chars) -- probably something is pasted from clipboard. Something like this:
$('input, textarea').change(function(){
var prev = $(this).data('prev-val'),
current = $(this).val();
if (is_big_changes(prev,current)) {
$(this).val(my_filter_func(current));
}
if (!prev) {
$(this).data('prev-val', current);
}
})
(it's only proof of concept, so I used jQuery to avoid a lot of coding)
Where is_big_changes and my_filter_func -- functions you need to implement.
Warning A lot of evil bugs is potentially possible with this approach and I know, it looks extremely ugly. My deal is to propound.
Can we say, what you alternative want is detecting a clipboard paste? Since when you know what was before in there, you know what has been changed.
So why not simply hook onchange? All character identical from beginning and end of the content are not pasted. If you want to differ this from simple keystrokes, listen to keydown/keypress as well, then you know, which changes come from "elsewhere".
来源:https://stackoverflow.com/questions/10640036/how-do-you-configure-firefox-to-allow-javascript-to-intercept-a-value-pasted-fro