michael@0: /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ michael@0: michael@0: "use strict"; michael@0: michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: const Cr = Components.results; michael@0: const Cu = Components.utils; michael@0: michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: XPCOMUtils.defineLazyGetter(this, "cpmm", function() { michael@0: return Cc["@mozilla.org/childprocessmessagemanager;1"] michael@0: .getService(Ci.nsIMessageSender); michael@0: }); michael@0: michael@0: function debug(aMsg) { michael@0: //dump("--*-- ContentHandler: " + aMsg + "\n"); michael@0: } michael@0: michael@0: const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001; michael@0: michael@0: let ActivityContentFactory = { michael@0: createInstance: function createInstance(outer, iid) { michael@0: if (outer != null) { michael@0: throw Cr.NS_ERROR_NO_AGGREGATION; michael@0: } michael@0: return new ActivityContentHandler().QueryInterface(iid); michael@0: }, michael@0: michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) michael@0: } michael@0: michael@0: function ActivityContentHandler() { michael@0: } michael@0: michael@0: ActivityContentHandler.prototype = { michael@0: handleContent: function handleContent(aMimetype, aContext, aRequest) { michael@0: if (!(aRequest instanceof Ci.nsIChannel)) michael@0: throw NS_ERROR_WONT_HANDLE_CONTENT; michael@0: michael@0: let detail = { michael@0: "type": aMimetype, michael@0: "url": aRequest.URI.spec michael@0: }; michael@0: cpmm.sendAsyncMessage("content-handler", detail); michael@0: michael@0: aRequest.cancel(Cr.NS_BINDING_ABORTED); michael@0: }, michael@0: michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler]) michael@0: } michael@0: michael@0: function ContentHandler() { michael@0: this.classIdMap = {}; michael@0: } michael@0: michael@0: ContentHandler.prototype = { michael@0: observe: function(aSubject, aTopic, aData) { michael@0: if (aTopic == "app-startup") { michael@0: // We only want to register these from content processes. michael@0: let appInfo = Cc["@mozilla.org/xre/app-info;1"]; michael@0: if (appInfo.getService(Ci.nsIXULRuntime) michael@0: .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { michael@0: return; michael@0: } michael@0: } michael@0: michael@0: cpmm.addMessageListener("Activities:RegisterContentTypes", this); michael@0: cpmm.addMessageListener("Activities:UnregisterContentTypes", this); michael@0: cpmm.sendAsyncMessage("Activities:GetContentTypes", { }); michael@0: }, michael@0: michael@0: /** michael@0: * Do the component registration for a content type. michael@0: * We only need to register one component per content type, even if several michael@0: * apps provide it, so we keep track of the number of providers for each michael@0: * content type. michael@0: */ michael@0: registerContentHandler: function registerContentHandler(aContentType) { michael@0: debug("Registering " + aContentType); michael@0: michael@0: // We already have a provider for this content type, just increase the michael@0: // tracking count. michael@0: if (this.classIdMap[aContentType]) { michael@0: this.classIdMap[aContentType].count++; michael@0: return; michael@0: } michael@0: michael@0: let contractID = "@mozilla.org/uriloader/content-handler;1?type=" + michael@0: aContentType; michael@0: let uuidGen = Cc["@mozilla.org/uuid-generator;1"] michael@0: .getService(Ci.nsIUUIDGenerator); michael@0: let id = Components.ID(uuidGen.generateUUID().toString()); michael@0: this.classIdMap[aContentType] = { count: 1, id: id }; michael@0: let cr = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); michael@0: cr.registerFactory(Components.ID(id), "Activity Content Handler", contractID, michael@0: ActivityContentFactory); michael@0: }, michael@0: michael@0: /** michael@0: * Do the component unregistration for a content type. michael@0: */ michael@0: unregisterContentHandler: function registerContentHandler(aContentType) { michael@0: debug("Unregistering " + aContentType); michael@0: michael@0: let record = this.classIdMap[aContentType]; michael@0: if (!record) { michael@0: return; michael@0: } michael@0: michael@0: // Bail out if we still have providers left for this content type. michael@0: if (--record.count > 0) { michael@0: return; michael@0: } michael@0: michael@0: let contractID = "@mozilla.org/uriloader/content-handler;1?type=" + michael@0: aContentType; michael@0: let cr = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); michael@0: cr.unregisterFactory(record.id, ActivityContentFactory); michael@0: delete this.classIdMap[aContentType] michael@0: }, michael@0: michael@0: receiveMessage: function(aMessage) { michael@0: let data = aMessage.data; michael@0: michael@0: switch (aMessage.name) { michael@0: case "Activities:RegisterContentTypes": michael@0: data.contentTypes.forEach(this.registerContentHandler, this); michael@0: break; michael@0: case "Activities:UnregisterContentTypes": michael@0: data.contentTypes.forEach(this.unregisterContentHandler, this); michael@0: break; michael@0: } michael@0: }, michael@0: michael@0: classID: Components.ID("{d18d0216-d50c-11e1-ba54-efb18d0ef0ac}"), michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler, michael@0: Ci.nsIObserver, michael@0: Ci.nsISupportsWeakReference]) michael@0: }; michael@0: michael@0: this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentHandler]);