Bug 1031609 - Observer service shims (r=mconley)

This commit is contained in:
Bill McCloskey 2014-07-14 22:10:06 -07:00
Родитель 26513758b2
Коммит a0b866406e
2 изменённых файлов: 103 добавлений и 0 удалений

Просмотреть файл

@ -150,6 +150,34 @@ let ContentPolicyChild = {
};
ContentPolicyChild.init();
// This code registers observers in the child whenever an add-on in
// the parent asks for notifications on the given topic.
let ObserverChild = {
init: function() {
NotificationTracker.watch("observer", (path, count) => this.track(path, count));
},
track: function(path, count) {
let topic = path[1];
if (count) {
Services.obs.addObserver(this, topic, false);
} else {
Services.obs.removeObserver(this, topic);
}
},
observe: function(subject, topic, data) {
let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(Ci.nsISyncMessageSender);
cpmm.sendRpcMessage("Addons:Observer:Run", {}, {
topic: topic,
subject: subject,
data: data
});
}
};
ObserverChild.init();
let RemoteAddonsChild = {
init: function(global) {
},

Просмотреть файл

@ -172,6 +172,80 @@ CategoryManagerInterposition.methods.deleteCategoryEntry =
target.deleteCategoryEntry(category, entry, persist);
};
// This object manages add-on observers that might fire in the child
// process. Rather than managing the observers itself, it uses the
// parent's observer service. When an add-on listens on topic T,
// ObserverParent asks the child process to listen on T. It also adds
// an observer in the parent for the topic e10s-T. When the T observer
// fires in the child, the parent fires all the e10s-T observers,
// passing them CPOWs for the subject and data. We don't want to use T
// in the parent because there might be non-add-on T observers that
// won't expect to get notified in this case.
let ObserverParent = {
init: function() {
let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
.getService(Ci.nsIMessageBroadcaster);
ppmm.addMessageListener("Addons:Observer:Run", this);
},
addObserver: function(observer, topic, ownsWeak) {
Services.obs.addObserver(observer, "e10s-" + topic, ownsWeak);
NotificationTracker.add(["observer", topic]);
},
removeObserver: function(observer, topic) {
Services.obs.removeObserver(observer, "e10s-" + topic);
NotificationTracker.remove(["observer", topic]);
},
receiveMessage: function(msg) {
switch (msg.name) {
case "Addons:Observer:Run":
this.notify(msg.objects.subject, msg.objects.topic, msg.objects.data);
break;
}
},
notify: function(subject, topic, data) {
let e = Services.obs.enumerateObservers("e10s-" + topic);
while (e.hasMoreElements()) {
let obs = e.getNext().QueryInterface(Ci.nsIObserver);
try {
obs.observe(subject, topic, data);
} catch (e) {
Cu.reportError(e);
}
}
}
};
ObserverParent.init();
// We only forward observers for these topics.
let TOPIC_WHITELIST = ["content-document-global-created",
"document-element-inserted",];
// This interposition listens for
// nsIObserverService.{add,remove}Observer.
let ObserverInterposition = new Interposition();
ObserverInterposition.methods.addObserver =
function(addon, target, observer, topic, ownsWeak) {
if (TOPIC_WHITELIST.indexOf(topic) >= 0) {
ObserverParent.addObserver(observer, topic);
}
target.addObserver(observer, topic, ownsWeak);
};
ObserverInterposition.methods.removeObserver =
function(addon, target, observer, topic) {
if (TOPIC_WHITELIST.indexOf(topic) >= 0) {
ObserverParent.removeObserver(observer, topic);
}
target.removeObserver(observer, topic);
};
let RemoteAddonsParent = {
init: function() {
},
@ -184,6 +258,7 @@ let RemoteAddonsParent = {
}
register(Ci.nsICategoryManager, CategoryManagerInterposition);
register(Ci.nsIObserverService, ObserverInterposition);
return result;
},