fuck this shit bro (add tabs.onReplaced notification)

This commit is contained in:
wuggy 2026-09-19 04:40:20 -07:00
commit 5ac0d5acc3
6 changed files with 108 additions and 7 deletions

View file

@ -750,9 +750,12 @@ SingletonEventManager.prototype = {
};
// Simple API for event listeners where events never fire.
function ignoreEvent(context, name) {
function ignoreEvent(context, name, warn = true) {
return {
addListener: function(callback) {
if (!warn) {
return;
}
let id = context.extension.id;
let frame = Components.stack.caller;
let msg = `In add-on ${id}, attempting to use listener "${name}", which is unimplemented.`;
@ -1095,8 +1098,8 @@ class MessageManagerProxy {
if (this.messageManager) {
return this.messageManager.sendAsyncMessage(...args);
}
/* globals uneval */
Cu.reportError(`Cannot send message: Other side disconnected: ${uneval(args)}`);
// Message senders can outlive their child process during normal teardown.
// Treat this as a dropped message instead of reporting a spurious error.
}
/**

View file

@ -321,13 +321,60 @@ function webAPIForAddon(addon) {
let result = {};
function cloneable(value, seen = new Set()) {
if (value === null || value === undefined ||
typeof value == "string" || typeof value == "number" ||
typeof value == "boolean") {
return value;
}
if (typeof value != "object") {
return undefined;
}
// Older message managers cannot structured-clone these XPCOM values.
try {
if (value instanceof Ci.nsIURI) {
return value.spec;
}
if (value instanceof Ci.nsIFile) {
return value.path;
}
} catch (e) {}
if (seen.has(value)) {
return undefined;
}
seen.add(value);
let className = Cu.getClassName(value, true);
if (className == "Array") {
return value.map(item => cloneable(item, seen));
}
if (className != "Object") {
return undefined;
}
let copy = {};
for (let key of Object.keys(value)) {
let item = cloneable(value[key], seen);
if (item !== undefined) {
copy[key] = item;
}
}
return copy;
}
// By default just pass through any plain property, the webidl will
// control access. Also filter out private properties, regular Addon
// objects are okay but MockAddon used in tests has non-serializable
// private properties.
for (let prop in addon) {
if (prop[0] != "_" && typeof(addon[prop]) != "function") {
result[prop] = addon[prop];
let value = cloneable(addon[prop]);
if (value !== undefined) {
result[prop] = value;
}
}
}

View file

@ -36,6 +36,20 @@ const CHILD_SCRIPT = "resource://gre/modules/addons/Content.js";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
function deserializeTriggeringPrincipal(principal) {
if (typeof principal != "string") {
return principal;
}
try {
return Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper)
.deserializeObject(principal)
.QueryInterface(Ci.nsIPrincipal);
} catch (e) {
return null;
}
}
var gSingleton = null;
function amManager() {
@ -219,7 +233,7 @@ amManager.prototype = {
}
return this.installAddonsFromWebpage(payload.mimetype,
aMessage.target, payload.triggeringPrincipal, payload.uris,
aMessage.target, deserializeTriggeringPrincipal(payload.triggeringPrincipal), payload.uris,
payload.hashes, payload.names, payload.icons, callback);
}

View file

@ -76,7 +76,11 @@ RemoteMediator.prototype = {
let callbackID = this._addCallback(callback, installs.uris);
installs.mimetype = XPINSTALL_MIMETYPE;
installs.triggeringPrincipal = principal;
// nsIPrincipal is an XPCOM object and cannot cross the legacy message
// manager boundary used by content processes. Serialize it explicitly.
installs.triggeringPrincipal = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper)
.serializeToString(principal);
installs.callbackID = callbackID;
if (Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {