[Pkg-mozext-commits] [gcontactsync] 14/31: Issue #2: Switch to OAuth2 for authentication

David Prévot taffit at moszumanska.debian.org
Sun Feb 22 21:34:33 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository gcontactsync.

commit 784ed83637b4145eead2f7094c4ce82f5a6c4dd2
Author: Josh Geenen <joshgeenen at gmail.com>
Date:   Fri Nov 28 09:54:54 2014 -0600

    Issue #2: Switch to OAuth2 for authentication
---
 src/content/AccountSetupWizard.js       | 117 +++++++++++++++++++++-----------
 src/content/AccountSetupWizard.xul      |  46 +++++++------
 src/content/GHttpRequest.js             |  41 +++++++++--
 src/content/HttpRequest.js              |  49 ++++++++++---
 src/content/LoginManager.js             |   4 +-
 src/content/Sync.js                     |  58 ++++++++++++----
 src/content/gdata.js                    |  28 +++++---
 src/content/synonyms.js                 |  14 ++++
 src/locale/en-US/AccountSetupWizard.dtd |   6 +-
 9 files changed, 259 insertions(+), 104 deletions(-)

diff --git a/src/content/AccountSetupWizard.js b/src/content/AccountSetupWizard.js
index ed91f75..196149a 100644
--- a/src/content/AccountSetupWizard.js
+++ b/src/content/AccountSetupWizard.js
@@ -34,6 +34,8 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
 if (!com) {var com = {};} // A generic wrapper variable
 // A wrapper for all GCS functions and variables
 if (!com.gContactSync) {com.gContactSync = {};}
@@ -42,7 +44,6 @@ window.addEventListener("load",
   /** Initializes the AccountSetupWizard class when the window has finished loading */
   function gCS_AccountSetupWizardLoadListener(e) {
     com.gContactSync.AccountSetupWizard.init();
-    window.sizeToContent();
   },
 false);
 
@@ -50,7 +51,7 @@ false);
  * Provides helper functions for the new account wizard.
  */
 com.gContactSync.AccountSetupWizard = {
-  NEW_ACCOUNT_IDS:      ["emailLabel", "email", "passwordLabel", "password"],
+  NEW_ACCOUNT_IDS:      ["emailLabel", "email"],
   EXISTING_ACCOUNT_IDS: ["existingAccountList"],
   mAuthToken:           "",
   mEmailAddress:        "",
@@ -122,6 +123,76 @@ com.gContactSync.AccountSetupWizard = {
     }
   },
   /**
+   * Loads the OAuth2 page and adds a listener that handles successful authentication.
+   */
+  loadOAuthPage: function AccountSetupWizard_loadOAuthPage() {
+
+    var wizard = document.getElementById("newAccountWizard");
+
+    var url = com.gContactSync.gdata.OAUTH_URL +
+              "?response_type=" + com.gContactSync.gdata.RESPONSE_TYPE +
+              "&client_id=" + com.gContactSync.gdata.CLIENT_ID +
+              "&redirect_uri=" + com.gContactSync.gdata.REDIRECT_URI +
+              "&scope=" + com.gContactSync.gdata.SCOPE +
+              "&login_hint=" + this.mEmailAddress;
+
+    var browser = document.getElementById("browser");
+    browser.setAttribute("src", url);
+    browser.addProgressListener(com.gContactSync.AccountSetupWizard.listener);
+    wizard.canAdvance = false;
+  },
+
+  /**
+   * Notify that an authorization code was received.  Sends a token request using the code.
+   *
+   * @param aCode {string} The authorization code.
+   */
+  onCodeReceived: function AccountSetupWizard_onCodeReceived(aCode) {
+    com.gContactSync.LOGGER.LOG("Received an authorization code");
+    var browser = document.getElementById("browser");
+    browser.removeProgressListener(com.gContactSync.AccountSetupWizard.listener);
+    browser.setAttribute("src", "");
+    var request = new com.gContactSync.GHttpRequest("TOKEN_REQUEST", aCode);
+    request.mOnSuccess = com.gContactSync.AccountSetupWizard.onTokenReceived;
+    request.mOnError = function onTokenError(aHttpReq) {
+      com.gContactSync.alertError(aHttpReq.responseText);
+    };
+    request.send();
+  },
+  /**
+   * Notify that an access token was received.  Saves the refresh token and advances the wizard.
+   *
+   * @param aHttpReq {XmlHttpRequest} The HTTP request.
+   */
+  onTokenReceived: function AccountSetupWizard_onTokenReceived(aHttpReq) {
+    com.gContactSync.LOGGER.LOG("Received an access token");
+    var response = JSON.parse(aHttpReq.responseText);
+    com.gContactSync.LoginManager.addAuthToken(com.gContactSync.AccountSetupWizard.mEmailAddress, response.refresh_token);
+    var wizard = document.getElementById("newAccountWizard");
+    wizard.canAdvance = true;
+    wizard.advance();
+  },
+  /**
+   * A nsIWebProgressListener that listens for a location change to the redirect URI.
+   * Notifies the AccountSetupWizard.
+   */
+  listener: {
+
+    QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIWebProgressListener,
+                                           Components.interfaces.nsISupportsWeakReference]),
+
+    onLocationChange: function (aWebProgress, aRequest, aLocation) {
+      if (aLocation.spec.indexOf(com.gContactSync.gdata.REDIRECT_URI) === 0) {
+        var code = com.gContactSync.parseURLParameters(aLocation.spec)["code"];
+        com.gContactSync.AccountSetupWizard.onCodeReceived(code);
+      }
+    },
+    onStateChange: function () {},
+    onProgressChange: function () {},
+    onStatusChange: function () {},
+    onSecurityChange: function () {},
+  },
+  /**
    * Gets an auth token for the selected username if necessary (and possible), then returns whether the page may
    * advance now.  If this function must get an auth token it will advance the page upon successful completion
    * of the HTTP request.
@@ -130,13 +201,9 @@ com.gContactSync.AccountSetupWizard = {
   advanceAccountPage: function AccountSetupWizard_advancedAccountPage() {
 
     // Try to get a token for the account
-    // If there's already a token it was advanced by a successful authentication.
-    if (this.mAuthToken !== "") {
-      return true;
-    }
 
     var option = document.getElementById("accountOption");
-    var password = "";
+    var nextPage = "oauthPage";
 
     com.gContactSync.LOGGER.VERBOSE_LOG("Advancing account page using a(n) " + option.value + " account.");
 
@@ -146,14 +213,11 @@ com.gContactSync.AccountSetupWizard = {
       if ("token" in this.mAccounts[index]) {
         com.gContactSync.LOGGER.VERBOSE_LOG(" * Already have a token");
         this.mAuthToken = this.mAccounts[index].token;
-        return true;
+        nextPage = "settingsPage";
       }
-      password = this.mAccounts[index].password;
     } else {
       var emailElem    = document.getElementById("email");
-      var passwordElem = document.getElementById("password");
       this.mEmailAddress = emailElem.value;
-      password = passwordElem.value;
       // This is a primitive way of validating an e-mail address, but Google takes
       // care of the rest.  It seems to allow getting an auth token w/ only the
       // username, but returns an error when trying to do anything w/ that token
@@ -164,35 +228,10 @@ com.gContactSync.AccountSetupWizard = {
       }
     }
 
-    com.gContactSync.LOGGER.VERBOSE_LOG(" * Requesting a token for " + this.mEmailAddress);
+    com.gContactSync.LOGGER.VERBOSE_LOG(" * Selected e-mail address: " + this.mEmailAddress);
+    document.getElementById("accountPage").setAttribute("next", nextPage);
 
-    var body    = com.gContactSync.gdata.makeAuthBody(this.mEmailAddress, password);
-    var httpReq = new com.gContactSync.GHttpRequest("authenticate", null, null, body);
-    // Move to the next page in the wizard upon successful authentication
-    httpReq.mOnSuccess = function authSuccess(httpReq) {
-      com.gContactSync.LOGGER.VERBOSE_LOG(httpReq.responseText);
-      com.gContactSync.AccountSetupWizard.mAuthToken = httpReq.responseText.split("\n")[2];
-      com.gContactSync.LoginManager.addAuthToken(com.gContactSync.AccountSetupWizard.mEmailAddress,
-		                                 'GoogleLogin ' + com.gContactSync.AccountSetupWizard.mAuthToken);
-      document.getElementById("newAccountWizard").advance();
-    };
-    // if it fails, alert the user and prompt them to try again
-    httpReq.mOnError = function authError(httpReq) {
-      com.gContactSync.alertError(com.gContactSync.StringBundle.getStr('authErr'));
-      com.gContactSync.LOGGER.LOG_ERROR('Authentication Error - ' +
-                                        httpReq.status,
-                                        httpReq.responseText);
-    };
-    // if the user is offline, alert them and quit
-    httpReq.mOnOffline = function authOffline(httpReq) {
-      com.gContactSync.alertError(com.gContactSync.StringBundle.getStr('offlineStatusText'));
-      com.gContactSync.LOGGER.LOG_ERROR('Authentication Error (offline) - ' +
-                                        httpReq.status,
-                                        httpReq.responseText);
-    };
-    httpReq.send();
-    // Don't let the page advance until a successful response is returned.
-    return false;
+    return true;
   },
   /**
    * Initializes the account settings (address books and groups) and selects the AB with
diff --git a/src/content/AccountSetupWizard.xul b/src/content/AccountSetupWizard.xul
index b6fb72c..f6a9dd9 100644
--- a/src/content/AccountSetupWizard.xul
+++ b/src/content/AccountSetupWizard.xul
@@ -38,7 +38,7 @@
 <?xml-stylesheet href="chrome://gcontactsync/skin/Accounts.css" type="text/css"?>
 
 <!--<?xml-stylesheet href="chrome://gcontactsync/skin/AccountSetupWizard.css" type="text/css"?>-->
-<!DOCTYPE window [
+<!DOCTYPE wizard [
   <!ENTITY % initialSetupDTD SYSTEM "chrome://gcontactsync/locale/AccountSetupWizard.dtd">
   %initialSetupDTD;
   <!ENTITY % accountsDTD SYSTEM "chrome://gcontactsync/locale/Accounts.dtd">
@@ -49,7 +49,9 @@
 
 <wizard id="newAccountWizard" title="&title.label;"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        onwizardfinish="com.gContactSync.AccountSetupWizard.finish();">
+        onwizardfinish="com.gContactSync.AccountSetupWizard.finish();"
+        height="740px"
+        width="700px">
   <script type="application/x-javascript"
           src="chrome://gcontactsync/content/synonyms.js"/>
   <script type="application/x-javascript"
@@ -92,8 +94,11 @@
     <stringbundle id="gContactSyncStringBundle"
                   src="chrome://gContactSync/locale/gcontactsync.properties"/>
   </stringbundleset>
+
   <wizardpage onpageadvanced="return com.gContactSync.AccountSetupWizard.advanceAccountPage();"
-              id="accountPage">
+              pageid="accountPage"
+              id="accountPage"
+              next="oauthPage">
     <description>
       &account.description;
     </description>
@@ -110,28 +115,27 @@
       </menulist>
       <spacer height="5px"/>
       <radio id="newAccount" label="&newAccount.label;" accesskey="&newAccount.accesskey;" value="new"/>
-      <grid flex="1" id="newAccountGrid">
-        <columns>
-          <column/>
-          <column/>
-        </columns>
-        <rows>
-          <row align="center">
-            <label id="emailLabel" value="&email.value;" control="email" accesskey="&email.accesskey;"/>
-            <textbox id="email"/>
-          </row>
-          <row align="center">
-            <label id="passwordLabel" value="&password.value;" control="password" accesskey="&password.accesskey;"/>
-            <textbox id="password" type="password"/>
-          </row>
-        </rows>
-      </grid>
+        <vbox>
+          <label id="emailLabel" value="&email.value;" control="email" accesskey="&email.accesskey;"/>
+          <textbox id="email"/>
+        </vbox>
     </radiogroup>
   </wizardpage>
-
+  <wizardpage description="&accountSettings.description;"
+              onpagerewound="document.getElementById('newAccountWizard').canAdvance = true;"
+              onpageshow="com.gContactSync.AccountSetupWizard.loadOAuthPage();"
+              pageid="oauthPage"
+              id="oauthPage"
+              next="settingsPage">
+    <hbox flex="1">
+      <browser id="browser" type="content" src="" flex="1" />
+    </hbox>
+  </wizardpage>
   <wizardpage description="&accountSettings.description;"
               onpagerewound="com.gContactSync.AccountSetupWizard.mAuthToken='';"
-              onpageshow="com.gContactSync.AccountSetupWizard.setupAccountSettings();">
+              onpageshow="com.gContactSync.AccountSetupWizard.setupAccountSettings();"
+              id="settingsPage"
+              pageid="settingsPage">
     <label control="abName" value="&abName.value;" accesskey="&abName.accesskey;"/>
     <hbox>
       <menulist id="abName">
diff --git a/src/content/GHttpRequest.js b/src/content/GHttpRequest.js
index d5a1783..20e3f5d 100644
--- a/src/content/GHttpRequest.js
+++ b/src/content/GHttpRequest.js
@@ -15,7 +15,7 @@
  *
  * The Initial Developer of the Original Code is
  * Josh Geenen <gcontactsync at pirules.org>.
- * Portions created by the Initial Developer are Copyright (C) 2008-2009
+ * Portions created by the Initial Developer are Copyright (C) 2008-2014
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
@@ -34,9 +34,9 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
-if (!com) var com = {}; // A generic wrapper variable
+if (!com) {var com = {};} // A generic wrapper variable
 // A wrapper for all GCS functions and variables
-if (!com.gContactSync) com.gContactSync = {};
+if (!com.gContactSync) {com.gContactSync = {};}
 
 /**
  * Sets up an HTTP request to send to Google.
@@ -64,8 +64,9 @@ com.gContactSync.GHttpRequest = function gCS_GHttpRequest(aType, aAuth, aUrl, aB
   com.gContactSync.HttpRequest.call(this);  // call the superclass' constructor
   this.mBody = aBody;
   // all urls in gdata use SSL.  If a URL is supplied, make sure it uses SSL
-  if (aUrl && aUrl.indexOf("https://") < 0)
+  if (aUrl && aUrl.indexOf("https://") < 0) {
     aUrl = aUrl.replace("http://", "https://");
+  }
   switch (aType) {
   case "AUTH_SUB_SESSION":
   case "authsubsession":
@@ -73,6 +74,27 @@ com.gContactSync.GHttpRequest = function gCS_GHttpRequest(aType, aAuth, aUrl, aB
     this.mUrl         = com.gContactSync.gdata.AUTH_SUB_SESSION_URL;
     this.mType        = com.gContactSync.gdata.AUTH_SUB_SESSION_TYPE;
     break;
+  case "TOKEN_REQUEST":
+  case "tokenrequest":
+    this.mContentType = this.CONTENT_TYPES.URL_ENC;
+    this.mUrl         = com.gContactSync.gdata.TOKEN_REQUEST_URL;
+    this.mType        = com.gContactSync.gdata.TOKEN_REQUEST_TYPE;
+    this.addParameter("code", aAuth);
+    this.addParameter("client_id", com.gContactSync.gdata.CLIENT_ID);
+    this.addParameter("client_secret", com.gContactSync.gdata.CLIENT_SECRET);
+    this.addParameter("redirect_uri", com.gContactSync.gdata.REDIRECT_URI);
+    this.addParameter("grant_type", com.gContactSync.gdata.TOKEN_REQUEST_GRANT_TYPE);
+    break;
+  case "REFRESH_REQUEST":
+  case "tokenrequest":
+    this.mContentType = this.CONTENT_TYPES.URL_ENC;
+    this.mUrl         = com.gContactSync.gdata.REFRESH_REQUEST_URL;
+    this.mType        = com.gContactSync.gdata.REFRESH_REQUEST_TYPE;
+    this.addParameter("refresh_token", aAuth);
+    this.addParameter("client_id", com.gContactSync.gdata.CLIENT_ID);
+    this.addParameter("client_secret", com.gContactSync.gdata.CLIENT_SECRET);
+    this.addParameter("grant_type", com.gContactSync.gdata.REFRESH_REQUEST_GRANT_TYPE);
+    break;
   case "AUTHENTICATE":
   case "authenticate":
     this.mContentType = this.CONTENT_TYPES.URL_ENC;
@@ -151,16 +173,19 @@ com.gContactSync.GHttpRequest = function gCS_GHttpRequest(aType, aAuth, aUrl, aB
   this.addHeaderItem("GData-Version", "3");
   // handle Token Expired errors
   this.mOn401 = com.gContactSync.handle401;
-  if (!this.mUrl)
+  if (!this.mUrl) {
     throw "Error - no URL was found for the HTTP Request";
-  if (aUsername && this.mUrl)
+  }
+  if (aUsername && this.mUrl) {
     this.mUrl = this.mUrl.replace("default",
                                   encodeURIComponent(com.gContactSync.fixUsername(aUsername)));
+  }
 };
 
 // get the superclass' prototype
 com.gContactSync.GHttpRequest.prototype = new com.gContactSync.HttpRequest();
 
+// TODO - rewrite, need to request a refresh_token
 /**
  * Handles 'Token Expired' errors.
  * If a sync is in progress:
@@ -172,6 +197,7 @@ com.gContactSync.GHttpRequest.prototype = new com.gContactSync.HttpRequest();
  */
 com.gContactSync.handle401 = function gCS_handle401(httpRequest) {
   com.gContactSync.LOGGER.LOG("***Found an expired token***");
+  /*
   // If there is a synchronization in process
   if (com.gContactSync.Preferences.mSyncPrefs.synchronizing.value) {
     // Get the current username
@@ -229,6 +255,7 @@ com.gContactSync.handle401 = function gCS_handle401(httpRequest) {
     };
     httpReq.send();
   }
+  */
 };
 
 /**
@@ -239,6 +266,7 @@ com.gContactSync.handle401 = function gCS_handle401(httpRequest) {
 com.gContactSync.finish401 = function gCS_finish401(aUsername, aAuthToken) {
   com.gContactSync.LOGGER.VERBOSE_LOG(" * finish401 called: " + aUsername +
                                       " - " + aAuthToken);
+  /*
   if (aUsername && aAuthToken) {
     // Remove the auth token if it wasn't already
     if (com.gContactSync.LoginManager.mAuthTokens[aUsername]) {
@@ -254,4 +282,5 @@ com.gContactSync.finish401 = function gCS_finish401(aUsername, aAuthToken) {
     else
       com.gContactSync.Sync.getContacts();
   }
+  */
 };
diff --git a/src/content/HttpRequest.js b/src/content/HttpRequest.js
index 659776a..794ea35 100644
--- a/src/content/HttpRequest.js
+++ b/src/content/HttpRequest.js
@@ -15,7 +15,7 @@
  *
  * The Initial Developer of the Original Code is
  * Josh Geenen <gcontactsync at pirules.org>.
- * Portions created by the Initial Developer are Copyright (C) 2008-2009
+ * Portions created by the Initial Developer are Copyright (C) 2008-2014
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
@@ -34,9 +34,9 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
-if (!com) var com = {}; // A generic wrapper variable
+if (!com) {var com = {};} // A generic wrapper variable
 // A wrapper for all GCS functions and variables
-if (!com.gContactSync) com.gContactSync = {};
+if (!com.gContactSync) {com.gContactSync = {};}
 
 /**
  * Sets up an HTTP request.<br>
@@ -75,11 +75,16 @@ if (!com.gContactSync) com.gContactSync = {};
  * @class
  */
 com.gContactSync.HttpRequest = function gCS_HttpRequest() {
-  if (window.XMLHttpRequest)
+  if (window.XMLHttpRequest) {
     this.mHttpRequest = new XMLHttpRequest();
-  if (!this.mHttpRequest)
+  }
+
+  if (!this.mHttpRequest) {
     throw "Error - could not create an XMLHttpRequest" +
           com.gContactSync.StringBundle.getStr("pleaseReport");
+  }
+
+  this.mParameters = [];
 };
 
 com.gContactSync.HttpRequest.prototype = {
@@ -125,18 +130,42 @@ com.gContactSync.HttpRequest.prototype = {
     this.mHeaderValues.push(aValue);
   },
   /**
+   * Adds a parameter/value pair to the request.
+   * @param aParameter {string} The parameter.
+   * @param aValue {string} The value.
+   */
+  addParameter: function HttpRequest_addParameter(aLabel, aValue) {
+    if (aValue) {
+      this.mParameters.push(aLabel + "=" + encodeURIComponent(aValue));
+    } else {
+      this.mParameters.push(aLabel);
+    }
+  },
+  /**
    * Sends the HTTP Request with the information stored in the object.<br>
    * Note: Setup everything, including the callbacks for different statuses
    *       including mOnSuccess, mOnError, mOnFail, and mOnCreated first.<br>
    * See the class documentation for a sample request.
    */
   send: function HttpRequest_send() {
+
+    var params = this.mParameters.join("&");
+
     // log the basic info for debugging purposes
     com.gContactSync.LOGGER.VERBOSE_LOG("HTTP Request being formed");
     com.gContactSync.LOGGER.VERBOSE_LOG(" * Caller is: " + this.send.caller.name);
     com.gContactSync.LOGGER.VERBOSE_LOG(" * URL: " + this.mUrl);
     com.gContactSync.LOGGER.VERBOSE_LOG(" * Type: " + this.mType);
     com.gContactSync.LOGGER.VERBOSE_LOG(" * Content-Type: " + this.mContentType);
+
+    if (params.length) {
+      com.gContactSync.LOGGER.VERBOSE_LOG(" * Parameters: " + params);
+      if (this.mType === "POST") {
+        this.mBody = this.mBody ? params + this.mBody : params;
+      } else {
+        this.mUrl = this.mUrl + "?" + params;
+      }
+    }
     
     this.mHttpRequest.open(this.mType, this.mUrl, true); // open the request
 
@@ -164,8 +193,7 @@ com.gContactSync.HttpRequest.prototype = {
     httpReq.timeout = com.gContactSync.Preferences.mSyncPrefs.httpRequestTimeout.value;
 
     httpReq.onreadystatechange = function httpReq_readyState() {
-      var callback = [],
-          i;
+      var callback = [];
       // if the request is done then check the status
       if (httpReq.readyState === 4) {
         // this may be called after the address book window is closed
@@ -204,7 +232,12 @@ com.gContactSync.HttpRequest.prototype = {
         }
       } // end of readyState
     };
-    this.mHttpRequest.send(this.mBody); // send the request
+    try {
+      this.mHttpRequest.send(this.mBody); // send the request
+    } catch (e) {
+      com.gContactSync.LOGGER.LOG_ERROR(" * Error sending request", e);
+      this.mOnError(this.mHttpRequest);
+    }
     com.gContactSync.LOGGER.VERBOSE_LOG(" * Request Sent");
   }
 };
diff --git a/src/content/LoginManager.js b/src/content/LoginManager.js
index 0f8a1b3..08cc929 100644
--- a/src/content/LoginManager.js
+++ b/src/content/LoginManager.js
@@ -45,9 +45,9 @@ if (!com.gContactSync) {com.gContactSync = {};}
  */
 com.gContactSync.LoginManager = {
   /** The hostname used in the login manager */
-  mHostname:      "chrome://gContactSync",
+  mHostname:      "chrome://gContactSync/oauth",
   /** The URL in the login manager */
-  mSubmitURL:     "User Auth Token",
+  mSubmitURL:     "User Refresh Token",
   /** The HTTP realm */
   mHttpRealm:     null,
   /** The username field */
diff --git a/src/content/Sync.js b/src/content/Sync.js
index 8c96ebb..16e2a4e 100644
--- a/src/content/Sync.js
+++ b/src/content/Sync.js
@@ -34,9 +34,9 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
-if (!com) var com = {}; // A generic wrapper variable
+if (!com) {var com = {};} // A generic wrapper variable
 // A wrapper for all GCS functions and variables
-if (!com.gContactSync) com.gContactSync = {};
+if (!com.gContactSync) {com.gContactSync = {};}
 
 /**
  * Synchronizes a Thunderbird Address Book with Google Contacts.
@@ -101,6 +101,10 @@ com.gContactSync.Sync = {
   mManualSync:    false,
   /** Stores a snapshot of the error count from synchronization up to, not including, the current AB */
   mPrevErrorCount: 0,
+  /** The access token */
+  mAccessToken: {},
+  /** The access token type */
+  mTokenType: {},
   /**
    * Performs the first steps of the sync process.
    * @param aManualSync {boolean} Set this to true if the sync was run manually.
@@ -188,7 +192,7 @@ com.gContactSync.Sync = {
     com.gContactSync.LOGGER.LOG("Starting synchronization for " + com.gContactSync.Sync.mCurrentUsername +
                                 " at: " + new Date().getTime() + " (" + Date() + ")\n");
     com.gContactSync.Sync.mCurrentAb        = obj.ab;
-    com.gContactSync.Sync.mCurrentAuthToken = com.gContactSync.LoginManager.getAuthTokens()[com.gContactSync.Sync.mCurrentUsername];
+    var refreshToken                        = com.gContactSync.LoginManager.getAuthTokens()[com.gContactSync.Sync.mCurrentUsername];
     com.gContactSync.Sync.mContactsUrl      = null;
     com.gContactSync.Sync.mBackup           = false;
     com.gContactSync.LOGGER.VERBOSE_LOG("Found Address Book with name: " +
@@ -203,9 +207,11 @@ com.gContactSync.Sync = {
     }
     // If an authentication token cannot be found for this username then
     // offer to let the user login with that account
-    if (!com.gContactSync.Sync.mCurrentAuthToken) {
+    if (!refreshToken) {
+      // TODO FIXME
       com.gContactSync.LOGGER.LOG_WARNING("Unable to find the auth token for: " +
                                           com.gContactSync.Sync.mCurrentUsername);
+      /*
       if (com.gContactSync.confirm(com.gContactSync.StringBundle.getStr("noTokenFound") +
                   ": " + com.gContactSync.Sync.mCurrentUsername +
                   "\n" + com.gContactSync.StringBundle.getStr("ab") +
@@ -262,6 +268,8 @@ com.gContactSync.Sync = {
       }
       else
         com.gContactSync.Sync.syncNextUser();
+        */
+      com.gContactSync.Sync.syncNextUser();
       return;
     }
     var lastBackup = parseInt(obj.ab.mPrefs.lastBackup, 10),
@@ -277,16 +285,38 @@ com.gContactSync.Sync = {
                                            prefix,
                                            ".bak");
     }
-    // getGroups must be called if the myContacts pref is set so it can find the
-    // proper group URL
-    if (com.gContactSync.Sync.mCurrentAb.mPrefs.syncGroups === "true" ||
-        (com.gContactSync.Sync.mCurrentAb.mPrefs.myContacts !== "false" &&
-         com.gContactSync.Sync.mCurrentAb.mPrefs.myContactsName !== "false")) {
-      com.gContactSync.Sync.getGroups();
-    }
-    else {
-      com.gContactSync.Sync.getContacts();
-    }
+    com.gContactSync.Sync.getAccessToken(refreshToken);
+  },
+  /**
+   * Exchanges the refresh token for an access token.  On success, continues synchronization.
+   *
+   * @param aRefreshToken {string} A refresh token.
+   */
+  getAccessToken: function Sync_getAccessToken(aRefreshToken) {
+    com.gContactSync.LOGGER.VERBOSE_LOG("Requesting access token");
+    // Fetch an access token from the refresh token
+    var request = new com.gContactSync.GHttpRequest("REFRESH_REQUEST", aRefreshToken);
+    request.mOnSuccess = function getAccessTokenSuccess(aHttpRequest) {
+      var response = JSON.parse(aHttpRequest.responseText);
+      com.gContactSync.Sync.mCurrentAuthToken = response.token_type + " " + response.access_token;
+      // getGroups must be called if the myContacts pref is set so it can find the
+      // proper group URL
+      if (com.gContactSync.Sync.mCurrentAb.mPrefs.syncGroups === "true" ||
+          (com.gContactSync.Sync.mCurrentAb.mPrefs.myContacts !== "false" &&
+           com.gContactSync.Sync.mCurrentAb.mPrefs.myContactsName !== "false")) {
+        com.gContactSync.Sync.getGroups();
+      }
+      else {
+        com.gContactSync.Sync.getContacts();
+      }
+    };
+    request.mOnError = function getAccessTokenError(httpReq) {
+      com.gContactSync.LOGGER.LOG_ERROR(httpReq.responseText);
+      com.gContactSync.Sync.syncNextUser(httpReq.responseText);
+    };
+    request.mOnOffline = com.gContactSync.Sync.mOfflineFunction;
+    request.mOn503 = com.gContactSync.Sync.m503Function;
+    request.send();
   },
   /**
    * Sends an HTTP Request to Google for a feed of all of the user's groups.
diff --git a/src/content/gdata.js b/src/content/gdata.js
index d087262..a515d3a 100644
--- a/src/content/gdata.js
+++ b/src/content/gdata.js
@@ -52,16 +52,24 @@ false);
  * @class
  */
 com.gContactSync.gdata = {
-  AUTH_URL:              "https://www.google.com/accounts/ClientLogin",
-  AUTH_REQUEST_TYPE:     "POST",
-  AUTH_SUB_SESSION_URL:  "https://www.google.com/accounts/AuthSubSessionToken",
-  AUTH_SUB_SESSION_TYPE: "GET",
-  AUTH_SUB_REVOKE_URL:   "https://www.google.com/accounts/AuthSubRevokeToken",
-  AUTH_SUB_REVOKE_TYPE:  "GET",
-  O_AUTH_URL:            "https://www.google.com/accounts/AuthSubRequest?scope=https%3A%" +
-                         "2F%2Fwww.google.com%2Fm8%2Ffeeds%2F&session=1&secure=0&next=" +
-                         "http%3A%2F%2Fpirules.org%2Ftools%2Fgcs%2Findex.php",
-  O_AUTH_TYPE:           "GET",
+  CLIENT_ID:                  "874495714229-5m7jmsjebv6nrf61q14siutq43bi1gvt.apps.googleusercontent.com",
+  CLIENT_SECRET:              "vayAK3lt9f4tMcMK1HZ4XZqG",
+  REDIRECT_URI:               "http://localhost",
+  RESPONSE_TYPE:              "code",
+  SCOPE:                      "https://www.google.com/m8/feeds",
+  OAUTH_URL:                  "https://accounts.google.com/o/oauth2/auth",
+  TOKEN_REQUEST_URL:          "https://accounts.google.com/o/oauth2/token",
+  TOKEN_REQUEST_TYPE:         "POST",
+  TOKEN_REQUEST_GRANT_TYPE:   "authorization_code",
+  REFRESH_REQUEST_URL:        "https://accounts.google.com/o/oauth2/token",
+  REFRESH_REQUEST_TYPE:       "POST",
+  REFRESH_REQUEST_GRANT_TYPE: "refresh_token",
+  AUTH_URL:                   "https://www.google.com/accounts/ClientLogin",
+  AUTH_REQUEST_TYPE:          "POST",
+  AUTH_SUB_SESSION_URL:       "https://www.google.com/accounts/AuthSubSessionToken",
+  AUTH_SUB_SESSION_TYPE:      "GET",
+  AUTH_SUB_REVOKE_URL:        "https://www.google.com/accounts/AuthSubRevokeToken",
+  AUTH_SUB_REVOKE_TYPE:       "GET",
   /**
    * Sets up the body for an authentication request given the e-mail address
    * and password.
diff --git a/src/content/synonyms.js b/src/content/synonyms.js
index 4c796fa..3470fda 100644
--- a/src/content/synonyms.js
+++ b/src/content/synonyms.js
@@ -677,3 +677,17 @@ com.gContactSync.version04Upgrade = function gCS_version04Upgrade() {
   com.gContactSync.Preferences.setSyncPref("v04RCUpgradeNeeded", false);
 };
 
+/**
+ * Parses the parameters in the given URL and returns them in a map.
+ *
+ * @param aURL {string} The URL to parse.
+ */
+com.gContactSync.parseURLParameters = function gCS_parseURLParameters(aURL) {
+  var ret = {};
+  var params = aURL.split("?")[1].split("&");
+  for (var i in params) {
+    var param = params[i].split("=");
+    ret[param[0]] = param[1];
+  }
+  return ret;
+};
diff --git a/src/locale/en-US/AccountSetupWizard.dtd b/src/locale/en-US/AccountSetupWizard.dtd
index 50f0b32..c429257 100644
--- a/src/locale/en-US/AccountSetupWizard.dtd
+++ b/src/locale/en-US/AccountSetupWizard.dtd
@@ -6,12 +6,10 @@
 <!ENTITY existingAccount.accesskey   "a">
 <!ENTITY newAccount.label            "Use a new account">
 <!ENTITY newAccount.accesskey        "w">
+
+<!ENTITY accountSettings.description "gContactSync Settings">
 <!ENTITY email.value                 "E-mail Address:">
 <!ENTITY email.accesskey             "m">
-<!ENTITY password.value              "Password:">
-<!ENTITY password.accesskey          "P">
-
-<!ENTITY accountSettings.description "Account Settings">
 <!ENTITY newABButton.label           "New">
 <!ENTITY newABButton.accesskey       "N">
 <!ENTITY finish.value                "Click Finish to add the account and synchronize.">

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/gcontactsync.git



More information about the Pkg-mozext-commits mailing list