Skip to content

Instantly share code, notes, and snippets.

@jernoble
Last active May 23, 2023 17:19
Show Gist options
  • Save jernoble/00571440f2df24053a58f603affd6d0d to your computer and use it in GitHub Desktop.
Save jernoble/00571440f2df24053a58f603affd6d0d to your computer and use it in GitHub Desktop.
/*
* The Inspector Bootstrap Script is guaranteed to be the first script evaluated in any page, as well as any sub-frames.
* It is evaluated immediately after the global object is created, before any other content has loaded.
*
* Modifications made here will take effect on the next load of any page or sub-frame.
* The contents and enabled state will be preserved across Web Inspector sessions.
*
* Some examples of ways to use this script include (but are not limited to):
* - overriding built-in functions to log call traces or add `debugger` statements
* - ensuring that common debugging functions are available on every page via the Console
*
* More information is available at <https://webkit.org/web-inspector/inspector-bootstrap-script/>.
*/
(function() {
function swizzleProperty(object, name, options) {
if (!object)
return;
let originalProperty = Object.getOwnPropertyDescriptor(object.prototype, name);
if (!originalProperty) {
console.log(`Failed to swizzle property ${name}`);
return;
}
Object.defineProperty(object.prototype, name, {
configurable: originalProperty.configurable,
get: function() {
let result = originalProperty.get.apply(this, arguments);
if (options.get)
options.get.apply(this, [result]);
return result;
},
set: function() {
if (options.set)
options.set.apply(this, arguments);
return originalProperty.set.apply(this, arguments);
}
});
}
function swizzleFunction(object, name, func) {
if (!object)
return;
if (!object[name]) {
console.log(`Failed to swizzle function ${name}`);
return;
}
let originalFunction = object[name];
object[name] = function() {
return func.apply(this, [originalFunction, arguments]);
};
}
swizzleFunction(HTMLMediaElement.prototype, 'play', function(originalPlay) {
console.log('JER: play()');
let mediaElement = this;
let playPromise = originalPlay.apply(this);
playPromise.then(() => {
console.log('JER: play() resolved');
}).catch(error => {
console.log(`JER: play() rejected with ${error}`);
});
return playPromise;
});
swizzleFunction(HTMLMediaElement.prototype, 'pause', function(originalPause) {
console.log('JER: pause()');
return originalPause.apply(this);
});
swizzleFunction(HTMLMediaElement.prototype, 'load', function(originalLoad) {
console.log('JER: load()');
return originalLoad.apply(this);
});
swizzleFunction(HTMLMediaElement.prototype, 'setAttribute', function(originalSetAttribute, originalArguments) {
let key = originalArguments[0] ?? null;
let value = originalArguments[1] ?? null;
console.log(`JER: setAttribute(${key}, ${value})`);
return originalSetAttribute.apply(this, originalArguments);
});
swizzleFunction(HTMLMediaElement.prototype, 'canPlayType', function(originalCanPlayType, originalArguments) {
let answer = originalCanPlayType.apply(this, originalArguments);
let type = originalArguments[0] ?? null;
if (type.includes('av01')) debugger;
console.log(`JER: canPlayType(${type} == "${answer}")`);
return answer;
});
swizzleProperty(HTMLMediaElement, 'src', {
set: url => console.log(`JER: set url("${url}")`)
});
swizzleFunction(MediaCapabilities.prototype, 'decodingInfo', function(origininalDecodingInfo, originalArguments) {
let configuration = originalArguments[0] ?? null;
console.log(`JER: decodingInfo(${JSON.stringify(configuration)})`);
let promise = origininalDecodingInfo.apply(this, originalArguments);
promise.then((results) => {
console.log(`JER: decodingInfo() resolved: ${JSON.stringify(results)}`);
}).catch(error => {
console.log(`JER: decodingInfo() rejected with ${error}`);
});
return promise;
});
swizzleFunction(MediaSource, 'isTypeSupported', function(originalIsTypeSupported, originalArguments) {
let result = originalIsTypeSupported.apply(this, originalArguments);
console.log(`JER: isTypeSupported(${originalArguments[0]}) == ${result}`);
return result;
});
swizzleFunction(Document.prototype, 'exitPictureInPicture', function(originalExitPictureInPicture, originalArguments) {
console.log(`JER: exitPictureInPicture`);
let promise = originalExitPictureInPicture.apply(this, originalArguments);
promise.then((results) => {
console.log(`JER: exitPictureInPicture() resolved`);
}).catch(error => {
console.log(`JER: exitPictureInPicture() rejected with ${error}`);
});
return result;
});
// swizzleProperty(HTMLVideoElement, 'videoWidth', {
// get: width => console.log(`JER: videoWidth - ${width}`)
// });
// swizzleProperty(HTMLVideoElement, 'videoHeight', {
// get: height => console.log(`JER: videoHeight - ${height}`)
// });
swizzleProperty(TextTrack, 'mode', {
set: mode => console.log(`JER: set track mode("${mode}")`)
});
// let originalCreateObjectURL = URL.createObjectURL;
// URL.createObjectURL = function(param) {
// console.log('JER: createObjectURL(:)');
// param = param.slice(0, param.size, "application/x-mpegURL")
// return originalCreateObjectURL.apply(this, [param]);
// }
// let originalAppendChild = Node.prototype.appendChild;
// Node.prototype.appendChild = function(child) {
// console.log(`JER: appendChild(${child})`);
// return originalAppendChild.apply(this, [child]);
// };
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment