I have created a Chrome extension that uses the hotkeys [Alt]+[0...9] only to discover facebook uses the same hotkeys. Is there any way possible my extension could disable facebook's hotkeys so that mine fire alone? I'm fairly certain I have identified the code facebook uses to implement their [Alt]+[0...9] hotkeys:
document.documentElement.onkeydown=function(a){a=a||window.event;var b=a.target||a.srcElement;var c=a.keyCode==13&&!a.altKey&&!a.ctrlKey&&!a.metaKey&&!a.shiftKey&&CSS.hasClass...
This is in a script called from the head of the root document. I have tried the following to disable them:
//contents script:
$().ready( function() {
document.documentElement.onkeydown = '';
});
and even
$().ready( function() {
document.documentElement.onkeydown = function(e){};
});
I am guessing further that the reason neither of these attempts work is because although Chrome extension content scripts share a DOM with any webpage on which they run, perhaps they do not share coding environments? Any insight would be appreciated!
From the browser's toolbar, click the Extensions icon and select Manage extension. Click Keyboard shortcuts. Use the Type a shortcut field next to each extension to set a new keyboard shortcut. To remove a shortcut, just click X.
Chrome's Content scripts are executed in a Sandboxed environment[source]. There is no direct way to communicate with the global (window
) object.
Another common pitfall is that the developer forgets how/when the script is injected.
DOMContentLoaded
has fired, window.onload
may or may not have fired).To inject a small script, I recommend to add the code directly to the Content Script:
var actualCode = '/* Code here (see below for inspiration) */';
var script = document.createElement('script');
script.appendChild(document.createTextNode(actualCode));
(document.head || document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
If you want to make sure that the method is not going to be overwritten, you can use Object.defineProperty
, to define an immutable property:
Object.defineProperty(document.documentElement, 'onkeydown', {
value: function() {},
writable: false, /* Cannot be overwritten, default false */
configurable: false, /* Cannot be deleted, or modified */
enumerable: true /* Does not really matter. If true, it's visible in
a for-loop. If false, it's not*/
});
The previously mentioned method is supported in Firefox 4+ and at least Chrome 5+. If you want to also support Firefox 2+ and Chrome 1+, you can play with the __defineSetter__
, to prevent onkeydown
from being defined:
document.documentElement.__defineSetter__('onkeydown', function(){});
Your intuition is correct, the JavaScript that runs from a content script as part of a Chrome Extension is run in a sandbox that does not have access to the JavaScript that is executed in the containing page.
Per the Chrome doc on Content Scripts:
However, content scripts have some limitations. They cannot:
* Use chrome.* APIs (except for parts of chrome.extension)
* Use variables or functions defined by their extension's pages
* Use variables or functions defined by web pages or by other content scripts
First off, I would recommend that you consider different shortcut keys. Overriding the functionality of existing shortcut keys for your own extension could provide a jarring user experience for someone that is expecting the Facebook shortcut key. Imagine if an extension overrode the ctrl-c and ctrl-p shortcuts that are a part of the desktop OS for copy and paste - I think you would have some upset users that would probably remove the thing that changed the behavior they learned prior.
However, if you are insistent, then here is a workaround to loading JavaScript that will execute in the context of the containing page:
Edit: Updated per comment to reference JS file in a plugin instead of one hosted on the web
First, you will need to create a JavaScript file in your chrome plugin: override-fb-hotkeys.js
.
First, you will need to host a JavaScript file somewhere on the web that contains the script that you want to execute in the page, let us say you host it at: http://example.com/override-fb-hotkeys.js
.
Then, from your content script, you can insert a script tag into the DOM that references your JavaScript file, something like this:
var script = document.createElement('script');
script.setAttribute("type", "text/javascript");
script.setAttribute("async", true);
script.setAttribute("src", chrome.extension.getURL("override-fb-hotkeys.js")); //Assuming your host supports both http and https
var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
head.insertBefore(script, head.firstChild)
The JavaScript will then be fetched and executed in the context of the containing page, not the sandboxed code from the Chrome plugin.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With