|
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ |
|
3 |
|
4 "use strict"; |
|
5 |
|
6 const Cc = Components.classes; |
|
7 const Ci = Components.interfaces; |
|
8 const Cr = Components.results; |
|
9 const Cu = Components.utils; |
|
10 |
|
11 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
12 Cu.import("resource://gre/modules/Services.jsm"); |
|
13 |
|
14 XPCOMUtils.defineLazyGetter(this, "cpmm", function() { |
|
15 return Cc["@mozilla.org/childprocessmessagemanager;1"] |
|
16 .getService(Ci.nsIMessageSender); |
|
17 }); |
|
18 |
|
19 function debug(aMsg) { |
|
20 //dump("--*-- ContentHandler: " + aMsg + "\n"); |
|
21 } |
|
22 |
|
23 const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001; |
|
24 |
|
25 let ActivityContentFactory = { |
|
26 createInstance: function createInstance(outer, iid) { |
|
27 if (outer != null) { |
|
28 throw Cr.NS_ERROR_NO_AGGREGATION; |
|
29 } |
|
30 return new ActivityContentHandler().QueryInterface(iid); |
|
31 }, |
|
32 |
|
33 QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) |
|
34 } |
|
35 |
|
36 function ActivityContentHandler() { |
|
37 } |
|
38 |
|
39 ActivityContentHandler.prototype = { |
|
40 handleContent: function handleContent(aMimetype, aContext, aRequest) { |
|
41 if (!(aRequest instanceof Ci.nsIChannel)) |
|
42 throw NS_ERROR_WONT_HANDLE_CONTENT; |
|
43 |
|
44 let detail = { |
|
45 "type": aMimetype, |
|
46 "url": aRequest.URI.spec |
|
47 }; |
|
48 cpmm.sendAsyncMessage("content-handler", detail); |
|
49 |
|
50 aRequest.cancel(Cr.NS_BINDING_ABORTED); |
|
51 }, |
|
52 |
|
53 QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler]) |
|
54 } |
|
55 |
|
56 function ContentHandler() { |
|
57 this.classIdMap = {}; |
|
58 } |
|
59 |
|
60 ContentHandler.prototype = { |
|
61 observe: function(aSubject, aTopic, aData) { |
|
62 if (aTopic == "app-startup") { |
|
63 // We only want to register these from content processes. |
|
64 let appInfo = Cc["@mozilla.org/xre/app-info;1"]; |
|
65 if (appInfo.getService(Ci.nsIXULRuntime) |
|
66 .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { |
|
67 return; |
|
68 } |
|
69 } |
|
70 |
|
71 cpmm.addMessageListener("Activities:RegisterContentTypes", this); |
|
72 cpmm.addMessageListener("Activities:UnregisterContentTypes", this); |
|
73 cpmm.sendAsyncMessage("Activities:GetContentTypes", { }); |
|
74 }, |
|
75 |
|
76 /** |
|
77 * Do the component registration for a content type. |
|
78 * We only need to register one component per content type, even if several |
|
79 * apps provide it, so we keep track of the number of providers for each |
|
80 * content type. |
|
81 */ |
|
82 registerContentHandler: function registerContentHandler(aContentType) { |
|
83 debug("Registering " + aContentType); |
|
84 |
|
85 // We already have a provider for this content type, just increase the |
|
86 // tracking count. |
|
87 if (this.classIdMap[aContentType]) { |
|
88 this.classIdMap[aContentType].count++; |
|
89 return; |
|
90 } |
|
91 |
|
92 let contractID = "@mozilla.org/uriloader/content-handler;1?type=" + |
|
93 aContentType; |
|
94 let uuidGen = Cc["@mozilla.org/uuid-generator;1"] |
|
95 .getService(Ci.nsIUUIDGenerator); |
|
96 let id = Components.ID(uuidGen.generateUUID().toString()); |
|
97 this.classIdMap[aContentType] = { count: 1, id: id }; |
|
98 let cr = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
|
99 cr.registerFactory(Components.ID(id), "Activity Content Handler", contractID, |
|
100 ActivityContentFactory); |
|
101 }, |
|
102 |
|
103 /** |
|
104 * Do the component unregistration for a content type. |
|
105 */ |
|
106 unregisterContentHandler: function registerContentHandler(aContentType) { |
|
107 debug("Unregistering " + aContentType); |
|
108 |
|
109 let record = this.classIdMap[aContentType]; |
|
110 if (!record) { |
|
111 return; |
|
112 } |
|
113 |
|
114 // Bail out if we still have providers left for this content type. |
|
115 if (--record.count > 0) { |
|
116 return; |
|
117 } |
|
118 |
|
119 let contractID = "@mozilla.org/uriloader/content-handler;1?type=" + |
|
120 aContentType; |
|
121 let cr = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
|
122 cr.unregisterFactory(record.id, ActivityContentFactory); |
|
123 delete this.classIdMap[aContentType] |
|
124 }, |
|
125 |
|
126 receiveMessage: function(aMessage) { |
|
127 let data = aMessage.data; |
|
128 |
|
129 switch (aMessage.name) { |
|
130 case "Activities:RegisterContentTypes": |
|
131 data.contentTypes.forEach(this.registerContentHandler, this); |
|
132 break; |
|
133 case "Activities:UnregisterContentTypes": |
|
134 data.contentTypes.forEach(this.unregisterContentHandler, this); |
|
135 break; |
|
136 } |
|
137 }, |
|
138 |
|
139 classID: Components.ID("{d18d0216-d50c-11e1-ba54-efb18d0ef0ac}"), |
|
140 QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler, |
|
141 Ci.nsIObserver, |
|
142 Ci.nsISupportsWeakReference]) |
|
143 }; |
|
144 |
|
145 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentHandler]); |