toolkit/identity/MinimalIdentity.jsm

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
michael@0 2 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 /*
michael@0 8 * This alternate implementation of IdentityService provides just the
michael@0 9 * channels for navigator.id, leaving the certificate storage to a
michael@0 10 * server-provided app.
michael@0 11 *
michael@0 12 * On b2g, the messages identity-controller-watch, -request, and
michael@0 13 * -logout, are observed by the component SignInToWebsite.jsm.
michael@0 14 */
michael@0 15
michael@0 16 "use strict";
michael@0 17
michael@0 18 this.EXPORTED_SYMBOLS = ["IdentityService"];
michael@0 19
michael@0 20 const Cu = Components.utils;
michael@0 21 const Ci = Components.interfaces;
michael@0 22 const Cc = Components.classes;
michael@0 23 const Cr = Components.results;
michael@0 24
michael@0 25 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 26 Cu.import("resource://gre/modules/Services.jsm");
michael@0 27 Cu.import("resource://gre/modules/identity/LogUtils.jsm");
michael@0 28
michael@0 29 XPCOMUtils.defineLazyModuleGetter(this, "objectCopy",
michael@0 30 "resource://gre/modules/identity/IdentityUtils.jsm");
michael@0 31
michael@0 32 XPCOMUtils.defineLazyModuleGetter(this, "makeMessageObject",
michael@0 33 "resource://gre/modules/identity/IdentityUtils.jsm");
michael@0 34
michael@0 35 function log(...aMessageArgs) {
michael@0 36 Logger.log.apply(Logger, ["minimal core"].concat(aMessageArgs));
michael@0 37 }
michael@0 38 function reportError(...aMessageArgs) {
michael@0 39 Logger.reportError.apply(Logger, ["core"].concat(aMessageArgs));
michael@0 40 }
michael@0 41
michael@0 42 function IDService() {
michael@0 43 Services.obs.addObserver(this, "quit-application-granted", false);
michael@0 44
michael@0 45 // simplify, it's one object
michael@0 46 this.RP = this;
michael@0 47 this.IDP = this;
michael@0 48
michael@0 49 // keep track of flows
michael@0 50 this._rpFlows = {};
michael@0 51 this._authFlows = {};
michael@0 52 this._provFlows = {};
michael@0 53 }
michael@0 54
michael@0 55 IDService.prototype = {
michael@0 56 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
michael@0 57
michael@0 58 observe: function observe(aSubject, aTopic, aData) {
michael@0 59 switch (aTopic) {
michael@0 60 case "quit-application-granted":
michael@0 61 this.shutdown();
michael@0 62 break;
michael@0 63 }
michael@0 64 },
michael@0 65
michael@0 66 shutdown: function() {
michael@0 67 Services.obs.removeObserver(this, "quit-application-granted");
michael@0 68 },
michael@0 69
michael@0 70 /**
michael@0 71 * Parse an email into username and domain if it is valid, else return null
michael@0 72 */
michael@0 73 parseEmail: function parseEmail(email) {
michael@0 74 var match = email.match(/^([^@]+)@([^@^/]+.[a-z]+)$/);
michael@0 75 if (match) {
michael@0 76 return {
michael@0 77 username: match[1],
michael@0 78 domain: match[2]
michael@0 79 };
michael@0 80 }
michael@0 81 return null;
michael@0 82 },
michael@0 83
michael@0 84 /**
michael@0 85 * Register a listener for a given windowID as a result of a call to
michael@0 86 * navigator.id.watch().
michael@0 87 *
michael@0 88 * @param aCaller
michael@0 89 * (Object) an object that represents the caller document, and
michael@0 90 * is expected to have properties:
michael@0 91 * - id (unique, e.g. uuid)
michael@0 92 * - loggedInUser (string or null)
michael@0 93 * - origin (string)
michael@0 94 *
michael@0 95 * and a bunch of callbacks
michael@0 96 * - doReady()
michael@0 97 * - doLogin()
michael@0 98 * - doLogout()
michael@0 99 * - doError()
michael@0 100 * - doCancel()
michael@0 101 *
michael@0 102 */
michael@0 103 watch: function watch(aRpCaller) {
michael@0 104 // store the caller structure and notify the UI observers
michael@0 105 this._rpFlows[aRpCaller.id] = aRpCaller;
michael@0 106
michael@0 107 log("flows:", Object.keys(this._rpFlows).join(', '));
michael@0 108
michael@0 109 let options = makeMessageObject(aRpCaller);
michael@0 110 log("sending identity-controller-watch:", options);
michael@0 111 Services.obs.notifyObservers({wrappedJSObject: options},"identity-controller-watch", null);
michael@0 112 },
michael@0 113
michael@0 114 /*
michael@0 115 * The RP has gone away; remove handles to the hidden iframe.
michael@0 116 * It's probable that the frame will already have been cleaned up.
michael@0 117 */
michael@0 118 unwatch: function unwatch(aRpId, aTargetMM) {
michael@0 119 let rp = this._rpFlows[aRpId];
michael@0 120 if (!rp) {
michael@0 121 return;
michael@0 122 }
michael@0 123
michael@0 124 let options = makeMessageObject({
michael@0 125 id: aRpId,
michael@0 126 origin: rp.origin,
michael@0 127 messageManager: aTargetMM
michael@0 128 });
michael@0 129 log("sending identity-controller-unwatch for id", options.id, options.origin);
michael@0 130 Services.obs.notifyObservers({wrappedJSObject: options}, "identity-controller-unwatch", null);
michael@0 131
michael@0 132 // Stop sending messages to this window
michael@0 133 delete this._rpFlows[aRpId];
michael@0 134 },
michael@0 135
michael@0 136 /**
michael@0 137 * Initiate a login with user interaction as a result of a call to
michael@0 138 * navigator.id.request().
michael@0 139 *
michael@0 140 * @param aRPId
michael@0 141 * (integer) the id of the doc object obtained in .watch()
michael@0 142 *
michael@0 143 * @param aOptions
michael@0 144 * (Object) options including privacyPolicy, termsOfService
michael@0 145 */
michael@0 146 request: function request(aRPId, aOptions) {
michael@0 147 let rp = this._rpFlows[aRPId];
michael@0 148 if (!rp) {
michael@0 149 reportError("request() called before watch()");
michael@0 150 return;
michael@0 151 }
michael@0 152
michael@0 153 // Notify UX to display identity picker.
michael@0 154 // Pass the doc id to UX so it can pass it back to us later.
michael@0 155 let options = makeMessageObject(rp);
michael@0 156 objectCopy(aOptions, options);
michael@0 157 Services.obs.notifyObservers({wrappedJSObject: options}, "identity-controller-request", null);
michael@0 158 },
michael@0 159
michael@0 160 /**
michael@0 161 * Invoked when a user wishes to logout of a site (for instance, when clicking
michael@0 162 * on an in-content logout button).
michael@0 163 *
michael@0 164 * @param aRpCallerId
michael@0 165 * (integer) the id of the doc object obtained in .watch()
michael@0 166 *
michael@0 167 */
michael@0 168 logout: function logout(aRpCallerId) {
michael@0 169 let rp = this._rpFlows[aRpCallerId];
michael@0 170 if (!rp) {
michael@0 171 reportError("logout() called before watch()");
michael@0 172 return;
michael@0 173 }
michael@0 174
michael@0 175 let options = makeMessageObject(rp);
michael@0 176 Services.obs.notifyObservers({wrappedJSObject: options}, "identity-controller-logout", null);
michael@0 177 },
michael@0 178
michael@0 179 childProcessShutdown: function childProcessShutdown(messageManager) {
michael@0 180 Object.keys(this._rpFlows).forEach(function(key) {
michael@0 181 if (this._rpFlows[key]._mm === messageManager) {
michael@0 182 log("child process shutdown for rp", key, "- deleting flow");
michael@0 183 delete this._rpFlows[key];
michael@0 184 }
michael@0 185 }, this);
michael@0 186 },
michael@0 187
michael@0 188 /*
michael@0 189 * once the UI-and-display-logic components have received
michael@0 190 * notifications, they call back with direct invocation of the
michael@0 191 * following functions (doLogin, doLogout, or doReady)
michael@0 192 */
michael@0 193
michael@0 194 doLogin: function doLogin(aRpCallerId, aAssertion, aInternalParams) {
michael@0 195 let rp = this._rpFlows[aRpCallerId];
michael@0 196 if (!rp) {
michael@0 197 log("WARNING: doLogin found no rp to go with callerId " + aRpCallerId);
michael@0 198 return;
michael@0 199 }
michael@0 200
michael@0 201 rp.doLogin(aAssertion, aInternalParams);
michael@0 202 },
michael@0 203
michael@0 204 doLogout: function doLogout(aRpCallerId) {
michael@0 205 let rp = this._rpFlows[aRpCallerId];
michael@0 206 if (!rp) {
michael@0 207 log("WARNING: doLogout found no rp to go with callerId " + aRpCallerId);
michael@0 208 return;
michael@0 209 }
michael@0 210
michael@0 211 // Logout from every site with the same origin
michael@0 212 let origin = rp.origin;
michael@0 213 Object.keys(this._rpFlows).forEach(function(key) {
michael@0 214 let rp = this._rpFlows[key];
michael@0 215 if (rp.origin === origin) {
michael@0 216 rp.doLogout();
michael@0 217 }
michael@0 218 }.bind(this));
michael@0 219 },
michael@0 220
michael@0 221 doReady: function doReady(aRpCallerId) {
michael@0 222 let rp = this._rpFlows[aRpCallerId];
michael@0 223 if (!rp) {
michael@0 224 log("WARNING: doReady found no rp to go with callerId " + aRpCallerId);
michael@0 225 return;
michael@0 226 }
michael@0 227
michael@0 228 rp.doReady();
michael@0 229 },
michael@0 230
michael@0 231 doCancel: function doCancel(aRpCallerId) {
michael@0 232 let rp = this._rpFlows[aRpCallerId];
michael@0 233 if (!rp) {
michael@0 234 log("WARNING: doCancel found no rp to go with callerId " + aRpCallerId);
michael@0 235 return;
michael@0 236 }
michael@0 237
michael@0 238 rp.doCancel();
michael@0 239 }
michael@0 240 };
michael@0 241
michael@0 242 this.IdentityService = new IDService();

mercurial