303 lines
10 KiB
JavaScript
303 lines
10 KiB
JavaScript
var content = function() {
|
|
"use strict";var __defProp = Object.defineProperty;
|
|
var __defProps = Object.defineProperties;
|
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
var __spreadValues = (a, b) => {
|
|
for (var prop in b || (b = {}))
|
|
if (__hasOwnProp.call(b, prop))
|
|
__defNormalProp(a, prop, b[prop]);
|
|
if (__getOwnPropSymbols)
|
|
for (var prop of __getOwnPropSymbols(b)) {
|
|
if (__propIsEnum.call(b, prop))
|
|
__defNormalProp(a, prop, b[prop]);
|
|
}
|
|
return a;
|
|
};
|
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
var __objRest = (source, exclude) => {
|
|
var target = {};
|
|
for (var prop in source)
|
|
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
target[prop] = source[prop];
|
|
if (source != null && __getOwnPropSymbols)
|
|
for (var prop of __getOwnPropSymbols(source)) {
|
|
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
target[prop] = source[prop];
|
|
}
|
|
return target;
|
|
};
|
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
var __async = (__this, __arguments, generator) => {
|
|
return new Promise((resolve, reject) => {
|
|
var fulfilled = (value) => {
|
|
try {
|
|
step(generator.next(value));
|
|
} catch (e) {
|
|
reject(e);
|
|
}
|
|
};
|
|
var rejected = (value) => {
|
|
try {
|
|
step(generator.throw(value));
|
|
} catch (e) {
|
|
reject(e);
|
|
}
|
|
};
|
|
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
step((generator = generator.apply(__this, __arguments)).next());
|
|
});
|
|
};
|
|
|
|
var _a, _b;
|
|
function defineContentScript(definition2) {
|
|
return definition2;
|
|
}
|
|
const definition = defineContentScript({
|
|
matches: ["*://*.google.com/*"],
|
|
main() {
|
|
}
|
|
});
|
|
content;
|
|
const browser$1 = ((_b = (_a = globalThis.browser) == null ? void 0 : _a.runtime) == null ? void 0 : _b.id) ? globalThis.browser : globalThis.chrome;
|
|
const browser = browser$1;
|
|
function print$1(method, ...args) {
|
|
return;
|
|
}
|
|
const logger$1 = {
|
|
debug: (...args) => print$1(console.debug, ...args),
|
|
log: (...args) => print$1(console.log, ...args),
|
|
warn: (...args) => print$1(console.warn, ...args),
|
|
error: (...args) => print$1(console.error, ...args)
|
|
};
|
|
const _WxtLocationChangeEvent = class _WxtLocationChangeEvent extends Event {
|
|
constructor(newUrl, oldUrl) {
|
|
super(_WxtLocationChangeEvent.EVENT_NAME, {});
|
|
this.newUrl = newUrl;
|
|
this.oldUrl = oldUrl;
|
|
}
|
|
};
|
|
__publicField(_WxtLocationChangeEvent, "EVENT_NAME", getUniqueEventName("wxt:locationchange"));
|
|
let WxtLocationChangeEvent = _WxtLocationChangeEvent;
|
|
function getUniqueEventName(eventName) {
|
|
var _a2;
|
|
return `${(_a2 = browser == null ? void 0 : browser.runtime) == null ? void 0 : _a2.id}:${"content"}:${eventName}`;
|
|
}
|
|
function createLocationWatcher(ctx) {
|
|
let interval;
|
|
let oldUrl;
|
|
return {
|
|
/**
|
|
* Ensure the location watcher is actively looking for URL changes. If it's already watching,
|
|
* this is a noop.
|
|
*/
|
|
run() {
|
|
if (interval != null) return;
|
|
oldUrl = new URL(location.href);
|
|
interval = ctx.setInterval(() => {
|
|
let newUrl = new URL(location.href);
|
|
if (newUrl.href !== oldUrl.href) {
|
|
window.dispatchEvent(new WxtLocationChangeEvent(newUrl, oldUrl));
|
|
oldUrl = newUrl;
|
|
}
|
|
}, 1e3);
|
|
}
|
|
};
|
|
}
|
|
const _ContentScriptContext = class _ContentScriptContext {
|
|
constructor(contentScriptName, options) {
|
|
__publicField(this, "isTopFrame", window.self === window.top);
|
|
__publicField(this, "abortController");
|
|
__publicField(this, "locationWatcher", createLocationWatcher(this));
|
|
__publicField(this, "receivedMessageIds", /* @__PURE__ */ new Set());
|
|
this.contentScriptName = contentScriptName;
|
|
this.options = options;
|
|
this.abortController = new AbortController();
|
|
if (this.isTopFrame) {
|
|
this.listenForNewerScripts({ ignoreFirstEvent: true });
|
|
this.stopOldScripts();
|
|
} else {
|
|
this.listenForNewerScripts();
|
|
}
|
|
}
|
|
get signal() {
|
|
return this.abortController.signal;
|
|
}
|
|
abort(reason) {
|
|
return this.abortController.abort(reason);
|
|
}
|
|
get isInvalid() {
|
|
if (browser.runtime.id == null) {
|
|
this.notifyInvalidated();
|
|
}
|
|
return this.signal.aborted;
|
|
}
|
|
get isValid() {
|
|
return !this.isInvalid;
|
|
}
|
|
/**
|
|
* Add a listener that is called when the content script's context is invalidated.
|
|
*
|
|
* @returns A function to remove the listener.
|
|
*
|
|
* @example
|
|
* browser.runtime.onMessage.addListener(cb);
|
|
* const removeInvalidatedListener = ctx.onInvalidated(() => {
|
|
* browser.runtime.onMessage.removeListener(cb);
|
|
* })
|
|
* // ...
|
|
* removeInvalidatedListener();
|
|
*/
|
|
onInvalidated(cb) {
|
|
this.signal.addEventListener("abort", cb);
|
|
return () => this.signal.removeEventListener("abort", cb);
|
|
}
|
|
/**
|
|
* Return a promise that never resolves. Useful if you have an async function that shouldn't run
|
|
* after the context is expired.
|
|
*
|
|
* @example
|
|
* const getValueFromStorage = async () => {
|
|
* if (ctx.isInvalid) return ctx.block();
|
|
*
|
|
* // ...
|
|
* }
|
|
*/
|
|
block() {
|
|
return new Promise(() => {
|
|
});
|
|
}
|
|
/**
|
|
* Wrapper around `window.setInterval` that automatically clears the interval when invalidated.
|
|
*/
|
|
setInterval(handler, timeout) {
|
|
const id = setInterval(() => {
|
|
if (this.isValid) handler();
|
|
}, timeout);
|
|
this.onInvalidated(() => clearInterval(id));
|
|
return id;
|
|
}
|
|
/**
|
|
* Wrapper around `window.setTimeout` that automatically clears the interval when invalidated.
|
|
*/
|
|
setTimeout(handler, timeout) {
|
|
const id = setTimeout(() => {
|
|
if (this.isValid) handler();
|
|
}, timeout);
|
|
this.onInvalidated(() => clearTimeout(id));
|
|
return id;
|
|
}
|
|
/**
|
|
* Wrapper around `window.requestAnimationFrame` that automatically cancels the request when
|
|
* invalidated.
|
|
*/
|
|
requestAnimationFrame(callback) {
|
|
const id = requestAnimationFrame((...args) => {
|
|
if (this.isValid) callback(...args);
|
|
});
|
|
this.onInvalidated(() => cancelAnimationFrame(id));
|
|
return id;
|
|
}
|
|
/**
|
|
* Wrapper around `window.requestIdleCallback` that automatically cancels the request when
|
|
* invalidated.
|
|
*/
|
|
requestIdleCallback(callback, options) {
|
|
const id = requestIdleCallback((...args) => {
|
|
if (!this.signal.aborted) callback(...args);
|
|
}, options);
|
|
this.onInvalidated(() => cancelIdleCallback(id));
|
|
return id;
|
|
}
|
|
addEventListener(target, type, handler, options) {
|
|
var _a2;
|
|
if (type === "wxt:locationchange") {
|
|
if (this.isValid) this.locationWatcher.run();
|
|
}
|
|
(_a2 = target.addEventListener) == null ? void 0 : _a2.call(
|
|
target,
|
|
type.startsWith("wxt:") ? getUniqueEventName(type) : type,
|
|
handler,
|
|
__spreadProps(__spreadValues({}, options), {
|
|
signal: this.signal
|
|
})
|
|
);
|
|
}
|
|
/**
|
|
* @internal
|
|
* Abort the abort controller and execute all `onInvalidated` listeners.
|
|
*/
|
|
notifyInvalidated() {
|
|
this.abort("Content script context invalidated");
|
|
logger$1.debug(
|
|
`Content script "${this.contentScriptName}" context invalidated`
|
|
);
|
|
}
|
|
stopOldScripts() {
|
|
window.postMessage(
|
|
{
|
|
type: _ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE,
|
|
contentScriptName: this.contentScriptName,
|
|
messageId: Math.random().toString(36).slice(2)
|
|
},
|
|
"*"
|
|
);
|
|
}
|
|
verifyScriptStartedEvent(event) {
|
|
var _a2, _b2, _c;
|
|
const isScriptStartedEvent = ((_a2 = event.data) == null ? void 0 : _a2.type) === _ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE;
|
|
const isSameContentScript = ((_b2 = event.data) == null ? void 0 : _b2.contentScriptName) === this.contentScriptName;
|
|
const isNotDuplicate = !this.receivedMessageIds.has((_c = event.data) == null ? void 0 : _c.messageId);
|
|
return isScriptStartedEvent && isSameContentScript && isNotDuplicate;
|
|
}
|
|
listenForNewerScripts(options) {
|
|
let isFirst = true;
|
|
const cb = (event) => {
|
|
if (this.verifyScriptStartedEvent(event)) {
|
|
this.receivedMessageIds.add(event.data.messageId);
|
|
const wasFirst = isFirst;
|
|
isFirst = false;
|
|
if (wasFirst && (options == null ? void 0 : options.ignoreFirstEvent)) return;
|
|
this.notifyInvalidated();
|
|
}
|
|
};
|
|
addEventListener("message", cb);
|
|
this.onInvalidated(() => removeEventListener("message", cb));
|
|
}
|
|
};
|
|
__publicField(_ContentScriptContext, "SCRIPT_STARTED_MESSAGE_TYPE", getUniqueEventName(
|
|
"wxt:content-script-started"
|
|
));
|
|
let ContentScriptContext = _ContentScriptContext;
|
|
function initPlugins() {
|
|
}
|
|
function print(method, ...args) {
|
|
return;
|
|
}
|
|
const logger = {
|
|
debug: (...args) => print(console.debug, ...args),
|
|
log: (...args) => print(console.log, ...args),
|
|
warn: (...args) => print(console.warn, ...args),
|
|
error: (...args) => print(console.error, ...args)
|
|
};
|
|
const result = (() => __async(null, null, function* () {
|
|
try {
|
|
initPlugins();
|
|
const _a2 = definition, { main } = _a2, options = __objRest(_a2, ["main"]);
|
|
const ctx = new ContentScriptContext("content", options);
|
|
return yield main(ctx);
|
|
} catch (err) {
|
|
logger.error(
|
|
`The content script "${"content"}" crashed on startup!`,
|
|
err
|
|
);
|
|
throw err;
|
|
}
|
|
}))();
|
|
return result;
|
|
}();
|
|
content;
|