I'm trying to create an extension for Chrome to control playback using global hotkeys. I've faced such problem: somewhere the <audio/>
elements are not attached to DOM. These elements are audible, but I can't get them with document.querySelector('audio')
(because it iterates over attached DOM elements only).
Using DevTools I can see these elements:
> queryObjects(HTMLAudioElement)
< undefined
(3) [audio, audio, audio]
But it's impossible to use this function outside DevTools (it doesn't even return result - this func just prints result to the console).
I'm looking a way to get unattached audio elements from the content_script (or background) of my extension.
I've tried:
document.getElementsByTagName('audio')
document.querySelectorAll('audio')
document.evaluate('//audio', ...
document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, ...
HTMLAudioElement
and document.createElement
(failed: extension has its own window
and linked document
)'play'
and 'pause'
events - they don't bubbleHave any other ideas? Maybe there are some extension-specific capabilities?
Thanks to @wOxxOm
I've followed my idea #5: redefine constructor of HTMLAudioElement
Audio
and document.createElement
var instances = [];
document.createElement = (function () {
var _createElement = document.createElement;
return function createElement() {
var result = _createElement.apply(document, Array.prototype.slice.call(arguments, 0));
if (result.tagName === 'AUDIO') {
instances.push(result);
}
return result;
};
})();
window.Audio = (function () {
var _Audio = window.Audio;
function Audio() {
var result = new _Audio();
instances.push(result);
return result;
};
Audio.prototype = Object.create(_Audio);
Audio.prototype.constructor = Audio;
return Audio;
})();
// further code (dom-event-based communication, misc functions etc)...
var injected = document.createElement('script');
injected.src = chrome.extension.getURL('inject.js');
(document.head || document.documentElement).appendChild(injected);
{
"manifest_version": 2
, "content_scripts": [{
"matches": ["<all_urls>"]
, "js": ["content.js"]
, "run_at": "document_start" // <-- important
, "all_frames": true
}]
, "web_accessible_resources": [
"inject.js"
]
// ...
}
It's harmful to store all instances in an array, but this is the only way that I see: WeakSet
is non-iterable.