Home | History | Annotate | Download | only in googleapps
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.android.googleapps;
     18 
     19 import com.google.android.googleapps.GoogleLoginCredentialsResult;
     20 import com.google.android.googleapps.LoginData;
     21 
     22 
     23 /**
     24  * Central application service used by Google apps to acquire login
     25  * credentials for all Google services.
     26  * <p>
     27  * See {@link GoogleLoginServiceHelper} and
     28  * {@link GoogleLoginServiceSynchronousHelper} for convenience wrappers
     29  * around the sequence of binding to the service and then
     30  * making API calls.
     31  */
     32 interface IGoogleLoginService {
     33     /**
     34      * Gets the list of Google Accounts the user has previously logged
     35      * in to.  Accounts are of the form "username@domain".
     36      * <p>
     37      * This method will return an empty array if the device doesn't
     38      * know about any Google accounts (yet).  In this case, if the
     39      * caller is an application (rather than a background task), the
     40      * typical next step is to call {@link #blockingGetCredentials}
     41      * with a null account; this will return an Intent that,
     42      * if run using {@link android.app.Activity#startSubActivity startSubActivity},
     43      * will prompt the user for username/password and ultimately
     44      * return an authentication token for the desired service.
     45      *
     46      * @return The accounts.  The array will be zero-length if the
     47      *         GoogleLoginService doesn't know about any accounts yet.
     48      */
     49     String[] getAccounts();
     50 
     51     /**
     52      * @deprecated
     53      *
     54      * Now equivalent to <code>getAccount(false)</code>.
     55      */
     56     String getPrimaryAccount();
     57 
     58     /**
     59      * Get the account to use on this device.
     60      *
     61      * @param requireGoogle true if you need the device's Google
     62      *        (non-hosted domain) account.
     63      *
     64      * @return username of the account
     65      */
     66     String getAccount(boolean requireGoogle);
     67 
     68     /**
     69      * Retrieves the credentials for a given account and service
     70      * <i>only if</i> the device already has a cached authentication token for that
     71      * account/service.
     72      * <p>
     73      * This method will <i>not</i> do any network I/O, even in the case
     74      * where we have no auth token for the specified service but we do
     75      * have a password for the specified account.
     76      * (Use {@link #blockingGetCredentials} if you do want to allow
     77      * the GoogleLoginService to use the network to fetch a fresh
     78      * auth token in this case.)
     79      * <p>
     80      * Note that the GoogleLoginService caches auth tokens
     81      * indefinitely, but the tokens themselves may expire over time.
     82      * Thus, the auth token returned by this method is <i>not</i>
     83      * guaranteed to be valid (since we'd need to do network I/O to
     84      * check that!)
     85      * <p>
     86      * The account and service parameters are the same as in
     87      * the {@link #blockingGetCredentials} call.
     88      *
     89      * @return An authentication token for the desired username/service,
     90      *         or null if the device doesn't have a
     91      *         cached auth token for that username/service.
     92      */
     93     String peekCredentials(String username, String service);
     94 
     95 
     96     /**
     97      * Retrieves the credentials for a given account and service.
     98      * <p>
     99      * This method will <b>either</b>
    100      * <ol>
    101      * <li> return an authentication token for the specified account/service
    102      * <p> <b>or</b>
    103      * <li> return an Intent which you (the caller) need to run
    104      *      yourself using {@link android.app.Activity#startSubActivity startSubActivity},
    105      *      which will ultimately return the desired
    106      *      auth token to your <code>onActivityResult</code> method.
    107      *      <br>
    108      *      (Generally, that Intent will bring up a UI for the user to
    109      *      enter their username and password, but the
    110      *      IGoogleLoginService interface deliberately doesn't specify
    111      *      exactly what that Intent will do.)
    112      * </ol>
    113      * The {@link GoogleLoginCredentialsResult} class encapsulates these two
    114      * possible results: either the <code>getCredentialsString</code> method will
    115      * return an auth token (in case (1) above), or the
    116      * <code>getCredentialsIntent</code> method will return the Intent you need
    117      * to run to prompt the user (in case (2)).
    118      * <p>
    119      * This method will never return a GoogleLoginCredentialsResult
    120      * object where <i>both</i> <code>getCredentialsString()</code> and
    121      * <code>getCredentialsIntent()</code> return non-null.
    122      * <p>
    123      * Other notes:
    124      * <ul>
    125      * <li> In case (1) this method may block to do network I/O!
    126      *   Use {@link #peekCredentials} instead if you need to quickly check
    127      *   whether the device has a cached auth token for a given
    128      *   account/service.
    129      * <p>
    130      * <li> In case (2), if it's appropriate to interact with the user at
    131      *   the current time, the caller should run the returned Intent as
    132      *   a sub-activity.
    133      *   When that sub-activity returns, the resulting "extras" Bundle
    134      *   (which will be returned to the caller's <code>onActivityResult</code>
    135      *   method) will contain the following two mappings <i>if</i> we
    136      *   were able to successfully log in to the specified
    137      *   account/service:
    138      *   <ul>
    139      *   <li>key   = {@link GoogleLoginServiceConstants#AUTHTOKEN_KEY
    140      *                      GoogleLoginServiceConstants.AUTHTOKEN_KEY}
    141      *   <li>value = Auth token for the specified account/service (String)
    142      *   </ul>
    143      *   and
    144      *   <ul>
    145      *   <li>key   = {@link GoogleLoginServiceConstants#AUTH_ACCOUNT_KEY
    146      *                      GoogleLoginServiceConstants.AUTH_ACCOUNT_KEY}
    147      *   <li>value = Account name used to generate the above auth token (String),
    148      *       which will probably be useful if you initially
    149      *       called <code>blockingGetCredentials</code> with a null account name.
    150      *   </ul>
    151      *   <p>
    152      *   Note: if the caller's <code>onActivityResult</code> method is called with
    153      *   a null "extras" Bundle, or a resultCode of RESULT_CANCELED,
    154      *   that means that we weren't able to authenticate.
    155      *   Either the user bailed out without entering a
    156      *   username+password at all, or there was some failure during
    157      *   the authentication process.
    158      * <p>
    159      * <li>If your application simply wants to "log into an account
    160      *   without ever prompting the user", like in the (very common)
    161      *   case of a background task or sync adapter, you can simply
    162      *   handle case (2) by not doing anything at all (other than maybe
    163      *   displaying a "couldn't log in" status somewhere in your UI.)
    164      * <p>
    165      * <li>See {@link GoogleLoginServiceHelper#getCredentials
    166      *   GoogleLoginServiceHelper.getCredentials} for a static
    167      *   convenience wrapper around this entire sequence.
    168      * </ul>
    169      *
    170      * @param account The account to obtain the credentials for.
    171      *                This should either be one of the accounts returned by
    172      *                the <code>getAccounts</code> call, or null.
    173      *                <br>
    174      *                The account will typically be null in the
    175      *                case where there the device doesn't know about
    176      *                any accounts yet, or also in the case where
    177      *                an application needs to log into a new account;
    178      *                a null account here guarantees that we'll
    179      *                need to prompt the user for username/password.
    180      *                <br>
    181      *                UI note: In the case where we return an Intent
    182      *                to prompt the user for username/password, that
    183      *                UI will automatically assume a domain name
    184      *                (usually "@gmail.com", but which may vary
    185      *                depending on the specified service) if the user
    186      *                enters a username with no domain.
    187      *
    188      * @param service The service to log in to, like "cl" (Calendar)
    189      *                or "mail" (GMail) or "blogger" (Blogger).
    190      *                (See the API documentation for your specific
    191      *                service to find out what service name to use
    192      *                here.)
    193      *                <br>
    194      *                If null, the resulting authentication token will
    195      *                be "non-compartmentalized" (and will work across
    196      *                all non-compartmentalized Google services.)
    197      *
    198      * @param notifyAuthFailure if true, we will put up a status bar
    199      *                notification if the attempt get the auth token
    200      *                over the network fails because the password is
    201      *                invalid (or because the password is blank).
    202      *
    203      * @return The results: either the requested credentials,
    204      *         or an Intent that your app can run to get them.
    205      */
    206     GoogleLoginCredentialsResult blockingGetCredentials(
    207         String username, String service, boolean notifyAuthFailure);
    208 
    209     /**
    210      * Invalidates the specified authentication token.  The next time
    211      * this token is requested it will be reauthenticated.
    212      * <p>
    213      * Background: the auth tokens returned from <code>peekCredentials()</code> or
    214      * <code>blockingGetCredentials()</code> are <i>not</i> guaranteed to be
    215      * valid, mainly because a token cached in the device's database may
    216      * have expired since we last tried to use it.  (Most auth tokens expire
    217      * after some amount of time, but the GoogleLoginService itself can't tell
    218      * when or if a given auth token will expire.  Only the Google service
    219      * your application talks to can say for sure whether a given auth token
    220      * is still valid.)
    221      * <p>
    222      * So if you do get an authentication error (from your app's service) when
    223      * using an auth token that came from the GoogleLoginService, you should
    224      * tell the GoogleLoginService about it by passing the failed token to
    225      * this method.  After doing that, you can get a fresh token by making
    226      * another <code>blockingGetCredentials()</code> call (or
    227      * <code>getCredentials()</code> if using a helper class like
    228      * <code>GoogleLoginServiceHelper</code>).
    229      *
    230      * @param authTokenToInvalidate The auth token to invalidate.
    231      */
    232     void invalidateAuthToken(String authTokenToInvalidate);
    233 
    234     /**
    235      * Returns the "Android ID", a 64-bit value unique to this device
    236      * assigned when the device is first registered with Google.
    237      *
    238      * Returns 0 if the device is not registered, or if the Android ID
    239      * is unavailable for any reason.  This call never blocks for
    240      * network activity.
    241      */
    242     long getAndroidId();
    243 
    244     // --------------------------------------------------------
    245     // methods below this point require the
    246     // com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD
    247     // permission, and will fail if the caller does not have it.
    248     // --------------------------------------------------------
    249 
    250     /**
    251      * Try logging in to a new account.
    252      *
    253      * On calling, data should contain username, password, (optional)
    254      * captcha token and answer.  flags should be 0 to allow any
    255      * account, or FLAG_GOOGLE_ACCOUNT to require a google account.
    256      *
    257      * The possible values of data.mStatus on return are described by
    258      * the {@link LoginData.Status} enum.
    259      *
    260      * If status is CAPTCHA, the captcha token, data, and mime type
    261      * fields will be filled in.
    262      */
    263     void tryNewAccount(inout LoginData data);
    264 
    265     /**
    266      * Save a new account to the database.  data should be an object
    267      * previously passed to tryNewAccount, with status SUCCESS.
    268      */
    269     void saveNewAccount(in LoginData data);
    270 
    271     /**
    272      * Store an auth token into the database.  Has no effect if
    273      * account is not in the database.
    274      */
    275     void saveAuthToken(String username, String service, String authToken);
    276 
    277     /**
    278      * Try to obtain an authtoken for the username and service in
    279      * data, using the password in data.  If successful, save the
    280      * password in the database (and return the authtoken).
    281      *
    282      * If the password in data is null, erases the password and all
    283      * authtokens for the account from the database.
    284      *
    285      * username must already exist in the database, or a status of
    286      * BAD_REQUEST will be returned.
    287      */
    288     void updatePassword(inout LoginData data);
    289 
    290     /**
    291      * Returns true if the given username/password match one stored in
    292      * the login service.  This does <i>not</i> do any network
    293      * activity; it does not check that the password is valid on
    294      * Google's servers, only that it matches what is stored on the
    295      * device.
    296      */
    297     boolean verifyStoredPassword(String username, String password);
    298 
    299     // --------------------------------------------------------
    300     // methods below this point exist primarily for automated tests.
    301     // --------------------------------------------------------
    302 
    303     /**
    304      * Add a new username/password pair to the Google Login Service.
    305      * Does not test to see if they are valid; just puts them directly
    306      * in the database.
    307      *
    308      * @param account the username (email address) of the account to add
    309      * @param password the password for this new account
    310      */
    311     void saveUsernameAndPassword(String username, String password, int flags);
    312 
    313     /**
    314      * Remove an account and all its authtokens from the database.
    315      *
    316      * @param account the account to remove
    317      */
    318     void deleteOneAccount(String username);
    319 
    320     /**
    321      * Remove all accounts and authtokens from the database.
    322      */
    323     void deleteAllAccounts();
    324 
    325     /**
    326      * Cause the device to register and get an android ID.
    327      * @return If LoginData.Status were an int we could return that.  Instead
    328      * we return:
    329      *       0  - success
    330      *       1  - login failure (caller should ask for a new password)
    331      *       2  - NOT IMPLEMENTED - CAPTCHA required?
    332      *       -1 - network or other transient failure (caller should try again, with a backoff)
    333      */
    334     int waitForAndroidId();
    335 
    336     // TODO: The aidl compiler might let you define constants (static
    337     // member variables) one of these days, rather than just letting
    338     // you declare member functions.
    339     //
    340     // When/if that happens, I should consider adding a section to
    341     // this aidl file for "Miscellaneous constants used by the
    342     // GoogleLoginService and related helper classes", containing the
    343     // constants currently found in the GoogleLoginServiceConstants
    344     // class (which can then be deleted.)
    345 }
    346