1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/b2g/components/ContentHandler.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,145 @@ 1.4 +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ 1.6 + 1.7 +"use strict"; 1.8 + 1.9 +const Cc = Components.classes; 1.10 +const Ci = Components.interfaces; 1.11 +const Cr = Components.results; 1.12 +const Cu = Components.utils; 1.13 + 1.14 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.15 +Cu.import("resource://gre/modules/Services.jsm"); 1.16 + 1.17 +XPCOMUtils.defineLazyGetter(this, "cpmm", function() { 1.18 + return Cc["@mozilla.org/childprocessmessagemanager;1"] 1.19 + .getService(Ci.nsIMessageSender); 1.20 +}); 1.21 + 1.22 +function debug(aMsg) { 1.23 + //dump("--*-- ContentHandler: " + aMsg + "\n"); 1.24 +} 1.25 + 1.26 +const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001; 1.27 + 1.28 +let ActivityContentFactory = { 1.29 + createInstance: function createInstance(outer, iid) { 1.30 + if (outer != null) { 1.31 + throw Cr.NS_ERROR_NO_AGGREGATION; 1.32 + } 1.33 + return new ActivityContentHandler().QueryInterface(iid); 1.34 + }, 1.35 + 1.36 + QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) 1.37 +} 1.38 + 1.39 +function ActivityContentHandler() { 1.40 +} 1.41 + 1.42 +ActivityContentHandler.prototype = { 1.43 + handleContent: function handleContent(aMimetype, aContext, aRequest) { 1.44 + if (!(aRequest instanceof Ci.nsIChannel)) 1.45 + throw NS_ERROR_WONT_HANDLE_CONTENT; 1.46 + 1.47 + let detail = { 1.48 + "type": aMimetype, 1.49 + "url": aRequest.URI.spec 1.50 + }; 1.51 + cpmm.sendAsyncMessage("content-handler", detail); 1.52 + 1.53 + aRequest.cancel(Cr.NS_BINDING_ABORTED); 1.54 + }, 1.55 + 1.56 + QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler]) 1.57 +} 1.58 + 1.59 +function ContentHandler() { 1.60 + this.classIdMap = {}; 1.61 +} 1.62 + 1.63 +ContentHandler.prototype = { 1.64 + observe: function(aSubject, aTopic, aData) { 1.65 + if (aTopic == "app-startup") { 1.66 + // We only want to register these from content processes. 1.67 + let appInfo = Cc["@mozilla.org/xre/app-info;1"]; 1.68 + if (appInfo.getService(Ci.nsIXULRuntime) 1.69 + .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { 1.70 + return; 1.71 + } 1.72 + } 1.73 + 1.74 + cpmm.addMessageListener("Activities:RegisterContentTypes", this); 1.75 + cpmm.addMessageListener("Activities:UnregisterContentTypes", this); 1.76 + cpmm.sendAsyncMessage("Activities:GetContentTypes", { }); 1.77 + }, 1.78 + 1.79 + /** 1.80 + * Do the component registration for a content type. 1.81 + * We only need to register one component per content type, even if several 1.82 + * apps provide it, so we keep track of the number of providers for each 1.83 + * content type. 1.84 + */ 1.85 + registerContentHandler: function registerContentHandler(aContentType) { 1.86 + debug("Registering " + aContentType); 1.87 + 1.88 + // We already have a provider for this content type, just increase the 1.89 + // tracking count. 1.90 + if (this.classIdMap[aContentType]) { 1.91 + this.classIdMap[aContentType].count++; 1.92 + return; 1.93 + } 1.94 + 1.95 + let contractID = "@mozilla.org/uriloader/content-handler;1?type=" + 1.96 + aContentType; 1.97 + let uuidGen = Cc["@mozilla.org/uuid-generator;1"] 1.98 + .getService(Ci.nsIUUIDGenerator); 1.99 + let id = Components.ID(uuidGen.generateUUID().toString()); 1.100 + this.classIdMap[aContentType] = { count: 1, id: id }; 1.101 + let cr = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); 1.102 + cr.registerFactory(Components.ID(id), "Activity Content Handler", contractID, 1.103 + ActivityContentFactory); 1.104 + }, 1.105 + 1.106 + /** 1.107 + * Do the component unregistration for a content type. 1.108 + */ 1.109 + unregisterContentHandler: function registerContentHandler(aContentType) { 1.110 + debug("Unregistering " + aContentType); 1.111 + 1.112 + let record = this.classIdMap[aContentType]; 1.113 + if (!record) { 1.114 + return; 1.115 + } 1.116 + 1.117 + // Bail out if we still have providers left for this content type. 1.118 + if (--record.count > 0) { 1.119 + return; 1.120 + } 1.121 + 1.122 + let contractID = "@mozilla.org/uriloader/content-handler;1?type=" + 1.123 + aContentType; 1.124 + let cr = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); 1.125 + cr.unregisterFactory(record.id, ActivityContentFactory); 1.126 + delete this.classIdMap[aContentType] 1.127 + }, 1.128 + 1.129 + receiveMessage: function(aMessage) { 1.130 + let data = aMessage.data; 1.131 + 1.132 + switch (aMessage.name) { 1.133 + case "Activities:RegisterContentTypes": 1.134 + data.contentTypes.forEach(this.registerContentHandler, this); 1.135 + break; 1.136 + case "Activities:UnregisterContentTypes": 1.137 + data.contentTypes.forEach(this.unregisterContentHandler, this); 1.138 + break; 1.139 + } 1.140 + }, 1.141 + 1.142 + classID: Components.ID("{d18d0216-d50c-11e1-ba54-efb18d0ef0ac}"), 1.143 + QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler, 1.144 + Ci.nsIObserver, 1.145 + Ci.nsISupportsWeakReference]) 1.146 +}; 1.147 + 1.148 +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentHandler]);