toolkit/identity/FirefoxAccounts.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.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 "use strict";
     7 this.EXPORTED_SYMBOLS = ["FirefoxAccounts"];
     9 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
    11 Cu.import("resource://gre/modules/Log.jsm");
    12 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    13 Cu.import("resource://gre/modules/Services.jsm");
    14 Cu.import("resource://gre/modules/identity/LogUtils.jsm");
    16 XPCOMUtils.defineLazyModuleGetter(this, "objectCopy",
    17                                   "resource://gre/modules/identity/IdentityUtils.jsm");
    19 XPCOMUtils.defineLazyModuleGetter(this, "makeMessageObject",
    20                                   "resource://gre/modules/identity/IdentityUtils.jsm");
    22 // loglevel preference should be one of: "FATAL", "ERROR", "WARN", "INFO",
    23 // "CONFIG", "DEBUG", "TRACE" or "ALL". We will be logging error messages by
    24 // default.
    25 const PREF_LOG_LEVEL = "identity.fxaccounts.loglevel";
    26 try {
    27   this.LOG_LEVEL =
    28     Services.prefs.getPrefType(PREF_LOG_LEVEL) == Ci.nsIPrefBranch.PREF_STRING
    29     && Services.prefs.getCharPref(PREF_LOG_LEVEL);
    30 } catch (e) {
    31   this.LOG_LEVEL = Log.Level.Error;
    32 }
    34 let log = Log.repository.getLogger("Identity.FxAccounts");
    35 log.level = LOG_LEVEL;
    36 log.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
    38 #ifdef MOZ_B2G
    39 XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsManager",
    40                                   "resource://gre/modules/FxAccountsManager.jsm",
    41                                   "FxAccountsManager");
    42 #else
    43 log.warn("The FxAccountsManager is only functional in B2G at this time.");
    44 var FxAccountsManager = null;
    45 #endif
    47 function FxAccountsService() {
    48   Services.obs.addObserver(this, "quit-application-granted", false);
    50   // Maintain interface parity with Identity.jsm and MinimalIdentity.jsm
    51   this.RP = this;
    53   this._rpFlows = new Map();
    55   // Enable us to mock FxAccountsManager service in testing
    56   this.fxAccountsManager = FxAccountsManager;
    57 }
    59 FxAccountsService.prototype = {
    60   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
    62   observe: function observe(aSubject, aTopic, aData) {
    63     switch (aTopic) {
    64       case "quit-application-granted":
    65         Services.obs.removeObserver(this, "quit-application-granted");
    66         break;
    67     }
    68   },
    70   /**
    71    * Register a listener for a given windowID as a result of a call to
    72    * navigator.id.watch().
    73    *
    74    * @param aCaller
    75    *        (Object)  an object that represents the caller document, and
    76    *                  is expected to have properties:
    77    *                  - id (unique, e.g. uuid)
    78    *                  - origin (string)
    79    *
    80    *                  and a bunch of callbacks
    81    *                  - doReady()
    82    *                  - doLogin()
    83    *                  - doLogout()
    84    *                  - doError()
    85    *                  - doCancel()
    86    *
    87    */
    88   watch: function watch(aRpCaller) {
    89     this._rpFlows.set(aRpCaller.id, aRpCaller);
    90     log.debug("watch: " + aRpCaller.id);
    91     log.debug("Current rp flows: " + this._rpFlows.size);
    93     // Log the user in, if possible, and then call ready().
    94     let runnable = {
    95       run: () => {
    96         this.fxAccountsManager.getAssertion(aRpCaller.audience, {silent:true}).then(
    97           data => {
    98             if (data) {
    99               this.doLogin(aRpCaller.id, data);
   100             } else {
   101               this.doLogout(aRpCaller.id);
   102             }
   103             this.doReady(aRpCaller.id);
   104           },
   105           error => {
   106             log.error("get silent assertion failed: " + JSON.stringify(error));
   107             this.doError(aRpCaller.id, error);
   108           }
   109         );
   110       }
   111     };
   112     Services.tm.currentThread.dispatch(runnable,
   113                                        Ci.nsIThread.DISPATCH_NORMAL);
   114   },
   116   /**
   117    * Delete the flow when the screen is unloaded
   118    */
   119   unwatch: function(aRpCallerId, aTargetMM) {
   120     log.debug("unwatching: " + aRpCallerId);
   121     this._rpFlows.delete(aRpCallerId);
   122   },
   124   /**
   125    * Initiate a login with user interaction as a result of a call to
   126    * navigator.id.request().
   127    *
   128    * @param aRPId
   129    *        (integer)  the id of the doc object obtained in .watch()
   130    *
   131    * @param aOptions
   132    *        (Object)  options including privacyPolicy, termsOfService
   133    */
   134   request: function request(aRPId, aOptions) {
   135     aOptions = aOptions || {};
   136     let rp = this._rpFlows.get(aRPId);
   137     if (!rp) {
   138       log.error("request() called before watch()");
   139       return;
   140     }
   142     let options = makeMessageObject(rp);
   143     objectCopy(aOptions, options);
   145     log.debug("get assertion for " + rp.audience);
   147     this.fxAccountsManager.getAssertion(rp.audience, options).then(
   148       data => {
   149         log.debug("got assertion for " + rp.audience + ": " + data);
   150         this.doLogin(aRPId, data);
   151       },
   152       error => {
   153         log.error("get assertion failed: " + JSON.stringify(error));
   154         this.doError(aRPId, error);
   155       }
   156     );
   157   },
   159   /**
   160    * Invoked when a user wishes to logout of a site (for instance, when clicking
   161    * on an in-content logout button).
   162    *
   163    * @param aRpCallerId
   164    *        (integer)  the id of the doc object obtained in .watch()
   165    *
   166    */
   167   logout: function logout(aRpCallerId) {
   168     // XXX Bug 945363 - Resolve the SSO story for FXA and implement
   169     // logout accordingly.
   170     //
   171     // For now, it makes no sense to logout from a specific RP in
   172     // Firefox Accounts, so just directly call the logout callback.
   173     if (!this._rpFlows.has(aRpCallerId)) {
   174       log.error("logout() called before watch()");
   175       return;
   176     }
   178     // Call logout() on the next tick
   179     let runnable = {
   180       run: () => {
   181         this.fxAccountsManager.signOut().then(() => {
   182           this.doLogout(aRpCallerId);
   183         });
   184       }
   185     };
   186     Services.tm.currentThread.dispatch(runnable,
   187                                        Ci.nsIThread.DISPATCH_NORMAL);
   188   },
   190   childProcessShutdown: function childProcessShutdown(messageManager) {
   191     for (let [key,] of this._rpFlows) {
   192       if (this._rpFlows.get(key)._mm === messageManager) {
   193         this._rpFlows.delete(key);
   194       }
   195     }
   196   },
   198   doLogin: function doLogin(aRpCallerId, aAssertion) {
   199     let rp = this._rpFlows.get(aRpCallerId);
   200     if (!rp) {
   201       log.warn("doLogin found no rp to go with callerId " + aRpCallerId + "\n");
   202       return;
   203     }
   205     rp.doLogin(aAssertion);
   206   },
   208   doLogout: function doLogout(aRpCallerId) {
   209     let rp = this._rpFlows.get(aRpCallerId);
   210     if (!rp) {
   211       log.warn("doLogout found no rp to go with callerId " + aRpCallerId + "\n");
   212       return;
   213     }
   215     rp.doLogout();
   216   },
   218   doReady: function doReady(aRpCallerId) {
   219     let rp = this._rpFlows.get(aRpCallerId);
   220     if (!rp) {
   221       log.warn("doReady found no rp to go with callerId " + aRpCallerId + "\n");
   222       return;
   223     }
   225     rp.doReady();
   226   },
   228   doCancel: function doCancel(aRpCallerId) {
   229     let rp = this._rpFlows.get(aRpCallerId);
   230     if (!rp) {
   231       log.warn("doCancel found no rp to go with callerId " + aRpCallerId + "\n");
   232       return;
   233     }
   235     rp.doCancel();
   236   },
   238   doError: function doError(aRpCallerId, aError) {
   239     let rp = this._rpFlows.get(aRpCallerId);
   240     if (!rp) {
   241       log.warn("doCancel found no rp to go with callerId " + aRpCallerId + "\n");
   242       return;
   243     }
   245     rp.doError(aError);
   246   }
   247 };
   249 this.FirefoxAccounts = new FxAccountsService();

mercurial