1 | /* |
---|
2 | * XPCOM component for the MIT Athena Firefox extension. |
---|
3 | */ |
---|
4 | |
---|
5 | // XPCOM component scaffolding |
---|
6 | |
---|
7 | const SERVICE_NAME="Athena Service"; |
---|
8 | const SERVICE_ID="{2276de48-911b-4acd-8b16-ef017b3eecad}"; |
---|
9 | const SERVICE_CONTRACT_ID = "@mit.edu/athena-service;1"; |
---|
10 | const SERVICE_CONSTRUCTOR=AthenaService; |
---|
11 | |
---|
12 | const SERVICE_CID = Components.ID(SERVICE_ID); |
---|
13 | |
---|
14 | Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
---|
15 | |
---|
16 | // Class constructor |
---|
17 | function AthenaService() |
---|
18 | { |
---|
19 | } |
---|
20 | |
---|
21 | // Class definition |
---|
22 | AthenaService.prototype = { |
---|
23 | |
---|
24 | // classDescription and contractID needed for Gecko 1.9 only |
---|
25 | classDescription: SERVICE_NAME, |
---|
26 | classID: SERVICE_CID, |
---|
27 | contractID: SERVICE_CONTRACT_ID, |
---|
28 | QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver]), |
---|
29 | properties: null, |
---|
30 | |
---|
31 | // Needed for Gecko 1.9 only. categories are specified in |
---|
32 | // chrome.manifest for Gecko 2.0 |
---|
33 | _xpcom_categories: [ { category: "app-startup", service: true } ], |
---|
34 | |
---|
35 | // nsIObserver implementation |
---|
36 | observe: function(subject, topic, data) |
---|
37 | { |
---|
38 | const propertiesURI = "chrome://athena/content/athena.properties"; |
---|
39 | switch (topic) { |
---|
40 | case "app-startup": |
---|
41 | // Set up to receive notifications when the profile changes |
---|
42 | // (including when it is set at startup) and at XPCOM shutdown. |
---|
43 | // Only used in Gecko 1.9 |
---|
44 | var observerService = |
---|
45 | Components.classes['@mozilla.org/observer-service;1'] |
---|
46 | .getService(Components.interfaces.nsIObserverService); |
---|
47 | observerService.addObserver(this, "profile-after-change", false); |
---|
48 | observerService.addObserver(this, "xpcom-shutdown", false); |
---|
49 | |
---|
50 | break; |
---|
51 | |
---|
52 | case "xpcom-shutdown": |
---|
53 | // The application is exiting. Remove observers added in |
---|
54 | // "app-startup". |
---|
55 | // Only used in Gecko 1.9 |
---|
56 | var observerService = |
---|
57 | Components.classes['@mozilla.org/observer-service;1'] |
---|
58 | .getService(Components.interfaces.nsIObserverService); |
---|
59 | observerService.removeObserver(this, "xpcom-shutdown"); |
---|
60 | observerService.removeObserver(this, "profile-after-change"); |
---|
61 | break; |
---|
62 | |
---|
63 | case "profile-after-change": |
---|
64 | // This is called when the profile is set at startup, and when |
---|
65 | // a profile change is requested. Perform our customizations. |
---|
66 | var stringBundleService = |
---|
67 | Components.classes["@mozilla.org/intl/stringbundle;1"] |
---|
68 | .getService(Components.interfaces.nsIStringBundleService); |
---|
69 | properties = stringBundleService.createBundle(propertiesURI); |
---|
70 | this.customize(); |
---|
71 | break; |
---|
72 | |
---|
73 | default: |
---|
74 | throw Components.Exception("Unknown topic: " + topic); |
---|
75 | } |
---|
76 | }, |
---|
77 | |
---|
78 | customize: function() |
---|
79 | { |
---|
80 | this.setLocalDiskCache(); |
---|
81 | this.addCert(); |
---|
82 | }, |
---|
83 | |
---|
84 | // If the profile directory is in AFS, set the disk cache to be on |
---|
85 | // local disk (by a default preference). |
---|
86 | setLocalDiskCache: function() |
---|
87 | { |
---|
88 | // We will test if the normalized profile directory path begins with |
---|
89 | // "/afs/". |
---|
90 | const AFSPathRE = /^\/afs\//; |
---|
91 | var prefbranch = |
---|
92 | Components.classes["@mozilla.org/preferences-service;1"] |
---|
93 | .getService(Components.interfaces.nsIPrefBranch); |
---|
94 | |
---|
95 | // Get the profile directory. |
---|
96 | var profileDirectory; |
---|
97 | try { |
---|
98 | profileDirectory = |
---|
99 | Components.classes["@mozilla.org/file/directory_service;1"] |
---|
100 | .getService(Components.interfaces.nsIProperties) |
---|
101 | .get("ProfD", Components.interfaces.nsIFile); |
---|
102 | } catch(e) { |
---|
103 | Components.utils.reportError(e); |
---|
104 | return; |
---|
105 | } |
---|
106 | |
---|
107 | // Resolve symlinks. |
---|
108 | profileDirectory.normalize(); |
---|
109 | |
---|
110 | if (AFSPathRE.test(profileDirectory.path)) { |
---|
111 | // The profile dir is in AFS. Set the default cache directory |
---|
112 | // to be under /var/tmp. Generate a unique directory name based |
---|
113 | // on the user name and profile directory leaf. |
---|
114 | const parentDir = "/var/tmp"; |
---|
115 | var parent = Components.classes["@mozilla.org/file/local;1"] |
---|
116 | .createInstance(Components.interfaces.nsILocalFile); |
---|
117 | parent.initWithPath(parentDir); |
---|
118 | if (parent.isDirectory()) { |
---|
119 | var userInfo = |
---|
120 | Components.classes["@mozilla.org/userinfo;1"] |
---|
121 | .getService(Components.interfaces.nsIUserInfo); |
---|
122 | var userName = userInfo.username; |
---|
123 | if (userName && userName.length) { |
---|
124 | var localCacheDir = parentDir + "/Mozilla-Firefox-" + userName |
---|
125 | + "/" + profileDirectory.leafName; |
---|
126 | var pref = |
---|
127 | Components.classes["@mozilla.org/preferences;1"] |
---|
128 | .getService(Components.interfaces.nsIPref); |
---|
129 | pref.SetDefaultCharPref("browser.cache.disk.parent_directory", |
---|
130 | localCacheDir); |
---|
131 | } |
---|
132 | } |
---|
133 | } |
---|
134 | }, |
---|
135 | |
---|
136 | addCert: function() |
---|
137 | { |
---|
138 | var certDB = |
---|
139 | Components.classes["@mozilla.org/security/x509certdb;1"] |
---|
140 | .getService(Components.interfaces.nsIX509CertDB2); |
---|
141 | |
---|
142 | // Loop over all certficates specified in the properties file. |
---|
143 | for (var i = 1; ; i++) { |
---|
144 | try { |
---|
145 | certName = properties.GetStringFromName("Cert" + i); |
---|
146 | } catch(e) { |
---|
147 | // End of list. |
---|
148 | break; |
---|
149 | } |
---|
150 | // Treat any null setting as the end of list. |
---|
151 | if (!(certName && certName.length)) |
---|
152 | break; |
---|
153 | |
---|
154 | // Set up to read the certificate. |
---|
155 | var ioService = |
---|
156 | Components.classes["@mozilla.org/network/io-service;1"] |
---|
157 | .getService(Components.interfaces.nsIIOService); |
---|
158 | var channel = ioService.newChannel("chrome://athena/content/" + |
---|
159 | certName, |
---|
160 | null, null); |
---|
161 | var input = channel.open(); |
---|
162 | var stream = |
---|
163 | Components.classes["@mozilla.org/scriptableinputstream;1"] |
---|
164 | .getService(Components.interfaces.nsIScriptableInputStream); |
---|
165 | stream.init(input); |
---|
166 | |
---|
167 | // Read the certificate as a Base 64 string; remove header/trailer |
---|
168 | // and newlines. |
---|
169 | var certBase64 = stream.read(input.available()); |
---|
170 | stream.close(); |
---|
171 | input.close(); |
---|
172 | certBase64 = certBase64.replace(/-----BEGIN CERTIFICATE-----/, ""); |
---|
173 | certBase64 = certBase64.replace(/-----END CERTIFICATE-----/, ""); |
---|
174 | certBase64 = certBase64.replace(/[\r\n]/g, ""); |
---|
175 | |
---|
176 | // Get the trust setting for this cert; default is to trust |
---|
177 | // for all purposes. Note that there is a bug in firefox 1.5.0.2 |
---|
178 | // where the addCertFromBase64() method ignores the trust setting |
---|
179 | // passed to it. See: |
---|
180 | // https://bugzilla.mozilla.org/show_bug.cgi?id=333767 |
---|
181 | try { |
---|
182 | certTrust = properties.GetStringFromName("CertTrust" + i); |
---|
183 | } |
---|
184 | catch(e) { |
---|
185 | certTrust = "C,C,C"; |
---|
186 | } |
---|
187 | |
---|
188 | // Add the cert to the database. Note that the addCertFromBase64() |
---|
189 | // implementation currently checks whether the cert already exists; |
---|
190 | // there does not seem to be a good way to check for that here. |
---|
191 | certDB.addCertFromBase64(certBase64, certTrust, ""); |
---|
192 | } |
---|
193 | }, |
---|
194 | |
---|
195 | // For debugging |
---|
196 | get wrappedJSObject() { |
---|
197 | return this; |
---|
198 | } |
---|
199 | |
---|
200 | } |
---|
201 | |
---|
202 | if (XPCOMUtils.generateNSGetFactory) { |
---|
203 | // Gecko 2.0 (FF 4 and higher) |
---|
204 | var NSGetFactory = XPCOMUtils.generateNSGetFactory([AthenaService]); |
---|
205 | } else { |
---|
206 | // Gecko 1.9 (FF 3) |
---|
207 | var NSGetModule = XPCOMUtils.generateNSGetModule([AthenaService]); |
---|
208 | } |
---|
209 | |
---|