source: trunk/athena/lib/firefox-extension/components/athenaService.js @ 25519

Revision 25519, 7.0 KB checked in by jdreed, 12 years ago (diff)
In firefox-extension: * Sync extension version number with package version number * Support Gecko 2.0, because apparently the XPCOM component hasn't worked since Firefox 3.x * Switch to XPCOMUtils.jsm for the XPCOM scaffolding (break compatibility with Firefox 2 and earlier)
Line 
1/*
2 * XPCOM component for the MIT Athena Firefox extension.
3 */
4
5// XPCOM component scaffolding
6
7const SERVICE_NAME="Athena Service";
8const SERVICE_ID="{2276de48-911b-4acd-8b16-ef017b3eecad}";
9const SERVICE_CONTRACT_ID = "@mit.edu/athena-service;1";
10const SERVICE_CONSTRUCTOR=AthenaService;
11
12const SERVICE_CID = Components.ID(SERVICE_ID);
13
14Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
15
16// Class constructor
17function AthenaService()
18{
19}
20
21// Class definition
22AthenaService.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
202if (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
Note: See TracBrowser for help on using the repository browser.