117250429db16553b59d5df5e358f71406dd2b322Andrew Stadler/*
217250429db16553b59d5df5e358f71406dd2b322Andrew Stadler * Copyright (C) 2009 The Android Open Source Project
317250429db16553b59d5df5e358f71406dd2b322Andrew Stadler *
417250429db16553b59d5df5e358f71406dd2b322Andrew Stadler * Licensed under the Apache License, Version 2.0 (the "License");
517250429db16553b59d5df5e358f71406dd2b322Andrew Stadler * you may not use this file except in compliance with the License.
617250429db16553b59d5df5e358f71406dd2b322Andrew Stadler * You may obtain a copy of the License at
717250429db16553b59d5df5e358f71406dd2b322Andrew Stadler *
817250429db16553b59d5df5e358f71406dd2b322Andrew Stadler *      http://www.apache.org/licenses/LICENSE-2.0
917250429db16553b59d5df5e358f71406dd2b322Andrew Stadler *
1017250429db16553b59d5df5e358f71406dd2b322Andrew Stadler * Unless required by applicable law or agreed to in writing, software
1117250429db16553b59d5df5e358f71406dd2b322Andrew Stadler * distributed under the License is distributed on an "AS IS" BASIS,
1217250429db16553b59d5df5e358f71406dd2b322Andrew Stadler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1317250429db16553b59d5df5e358f71406dd2b322Andrew Stadler * See the License for the specific language governing permissions and
1417250429db16553b59d5df5e358f71406dd2b322Andrew Stadler * limitations under the License.
1517250429db16553b59d5df5e358f71406dd2b322Andrew Stadler */
1617250429db16553b59d5df5e358f71406dd2b322Andrew Stadler
1717250429db16553b59d5df5e358f71406dd2b322Andrew Stadlerpackage com.android.email.service;
1817250429db16553b59d5df5e358f71406dd2b322Andrew Stadler
19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.activity.setup.AccountSetupBasics;
20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.AccountManagerTypes;
21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.CalendarProviderStub;
22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.EmailContent;
23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.accounts.AbstractAccountAuthenticator;
25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.accounts.Account;
26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.accounts.AccountAuthenticatorResponse;
27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.accounts.AccountManager;
28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.accounts.NetworkErrorException;
29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.app.Service;
30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.content.ContentResolver;
31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.content.Context;
32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.content.Intent;
33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.os.Bundle;
34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.os.IBinder;
35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.provider.ContactsContract;
36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
3717250429db16553b59d5df5e358f71406dd2b322Andrew Stadler/**
38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * A very basic authenticator service for EAS.  At the moment, it has no UI hooks.  When called
39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * with addAccount, it simply adds the account to AccountManager directly with a username and
40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * password.
4117250429db16553b59d5df5e358f71406dd2b322Andrew Stadler */
42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpublic class EasAuthenticatorService extends Service {
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final String OPTIONS_USERNAME = "username";
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final String OPTIONS_PASSWORD = "password";
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final String OPTIONS_CONTACTS_SYNC_ENABLED = "contacts";
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final String OPTIONS_CALENDAR_SYNC_ENABLED = "calendar";
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final String OPTIONS_EMAIL_SYNC_ENABLED = "email";
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    class EasAuthenticator extends AbstractAccountAuthenticator {
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private Context mContext;
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public EasAuthenticator(Context context) {
53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            super(context);
54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mContext = context;
55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                String authTokenType, String[] requiredFeatures, Bundle options)
60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                throws NetworkErrorException {
61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // There are two cases here:
62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // 1) We are called with a username/password; this comes from the traditional email
63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            //    app UI; we simply create the account and return the proper bundle
64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (options != null && options.containsKey(OPTIONS_PASSWORD)
65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    && options.containsKey(OPTIONS_USERNAME)) {
66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final Account account = new Account(options.getString(OPTIONS_USERNAME),
67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        AccountManagerTypes.TYPE_EXCHANGE);
68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                AccountManager.get(EasAuthenticatorService.this).addAccountExplicitly(
69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            account, options.getString(OPTIONS_PASSWORD), null);
70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // Set up contacts syncing.  ExchangeService will use info from ContentResolver
72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // to determine syncability of Contacts for Exchange
73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean syncContacts = false;
74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (options.containsKey(OPTIONS_CONTACTS_SYNC_ENABLED) &&
75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        options.getBoolean(OPTIONS_CONTACTS_SYNC_ENABLED)) {
76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    syncContacts = true;
77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY,
80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        syncContacts);
81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // Set up calendar syncing, as above
83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean syncCalendar = false;
84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (options.containsKey(OPTIONS_CALENDAR_SYNC_ENABLED) &&
85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        options.getBoolean(OPTIONS_CALENDAR_SYNC_ENABLED)) {
86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    syncCalendar = true;
87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                ContentResolver.setIsSyncable(account, CalendarProviderStub.AUTHORITY, 1);
89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                ContentResolver.setSyncAutomatically(account, CalendarProviderStub.AUTHORITY,
90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        syncCalendar);
91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // Set up email syncing, as above
93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean syncEmail = false;
94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (options.containsKey(OPTIONS_EMAIL_SYNC_ENABLED) &&
95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        options.getBoolean(OPTIONS_EMAIL_SYNC_ENABLED)) {
96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    syncEmail = true;
97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                ContentResolver.setIsSyncable(account, EmailContent.AUTHORITY, 1);
99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                ContentResolver.setSyncAutomatically(account, EmailContent.AUTHORITY,
100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        syncEmail);
101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                Bundle b = new Bundle();
103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                b.putString(AccountManager.KEY_ACCOUNT_NAME, options.getString(OPTIONS_USERNAME));
104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                b.putString(AccountManager.KEY_ACCOUNT_TYPE, AccountManagerTypes.TYPE_EXCHANGE);
105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return b;
106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // 2) The other case is that we're creating a new account from an Account manager
107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            //    activity.  In this case, we add an intent that will be used to gather the
108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            //    account information...
109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            } else {
110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                Bundle b = new Bundle();
111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                Intent intent =
112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    AccountSetupBasics.actionSetupExchangeIntent(EasAuthenticatorService.this);
113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                b.putParcelable(AccountManager.KEY_INTENT, intent);
115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return b;
116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                Bundle options) {
122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return null;
123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return null;
128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                String authTokenType, Bundle loginOptions) throws NetworkErrorException {
133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return null;
134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public String getAuthTokenLabel(String authTokenType) {
138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // null means we don't have compartmentalized authtoken types
139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return null;
140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                String[] features) throws NetworkErrorException {
145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return null;
146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
148bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
149bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
150bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                String authTokenType, Bundle loginOptions) {
151bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return null;
152bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
153bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
154bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
155bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
156bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
157bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public IBinder onBind(Intent intent) {
158bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (AccountManager.ACTION_AUTHENTICATOR_INTENT.equals(intent.getAction())) {
159bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return new EasAuthenticator(this).getIBinder();
160bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
161bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return null;
162bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
163bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
16417250429db16553b59d5df5e358f71406dd2b322Andrew Stadler}
165