gecko/b2g/components/ContentHandler.js

146 lines
4.5 KiB
JavaScript

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