MessageList.java revision 2127964d0f73df889460b23c81d463bbc871efed
1/*
2 * Copyright (C) 2009 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
17package com.android.email.activity;
18
19import com.android.email.Controller;
20import com.android.email.ControllerResultUiThreadWrapper;
21import com.android.email.Email;
22import com.android.email.R;
23import com.android.email.Utility;
24import com.android.email.activity.setup.AccountSecurity;
25import com.android.email.activity.setup.AccountSettings;
26import com.android.email.mail.AuthenticationFailedException;
27import com.android.email.mail.CertificateValidationException;
28import com.android.email.mail.MessagingException;
29import com.android.email.provider.EmailContent;
30import com.android.email.provider.EmailContent.Account;
31import com.android.email.provider.EmailContent.AccountColumns;
32import com.android.email.provider.EmailContent.Mailbox;
33import com.android.email.provider.EmailContent.MailboxColumns;
34import com.android.email.service.MailService;
35
36import android.app.Activity;
37import android.app.NotificationManager;
38import android.content.ContentResolver;
39import android.content.Context;
40import android.content.Intent;
41import android.database.Cursor;
42import android.net.Uri;
43import android.os.AsyncTask;
44import android.os.Bundle;
45import android.os.Handler;
46import android.view.Menu;
47import android.view.MenuItem;
48import android.view.View;
49import android.view.View.OnClickListener;
50import android.view.animation.Animation;
51import android.view.animation.Animation.AnimationListener;
52import android.view.animation.AnimationUtils;
53import android.widget.Button;
54import android.widget.ProgressBar;
55import android.widget.TextView;
56
57public class MessageList extends Activity implements OnClickListener,
58        AnimationListener, MessageListFragment.Callback {
59    // Intent extras (internal to this activity)
60    private static final String EXTRA_ACCOUNT_ID = "com.android.email.activity._ACCOUNT_ID";
61    private static final String EXTRA_MAILBOX_TYPE = "com.android.email.activity.MAILBOX_TYPE";
62    private static final String EXTRA_MAILBOX_ID = "com.android.email.activity.MAILBOX_ID";
63
64    private static final int REQUEST_SECURITY = 0;
65
66    // UI support
67    private MessageListFragment mListFragment;
68    private View mMultiSelectPanel;
69    private Button mReadUnreadButton;
70    private Button mFavoriteButton;
71    private Button mDeleteButton;
72    private TextView mErrorBanner;
73
74    private final Controller mController = Controller.getInstance(getApplication());
75    private ControllerResultUiThreadWrapper<ControllerResults> mControllerCallback;
76
77    private TextView mLeftTitle;
78    private ProgressBar mProgressIcon;
79
80    // DB access
81    private ContentResolver mResolver;
82    private SetTitleTask mSetTitleTask;
83
84    private MailboxFinder mMailboxFinder;
85    private MailboxFinderCallback mMailboxFinderCallback = new MailboxFinderCallback();
86
87    private static final int MAILBOX_NAME_COLUMN_ID = 0;
88    private static final int MAILBOX_NAME_COLUMN_ACCOUNT_KEY = 1;
89    private static final int MAILBOX_NAME_COLUMN_TYPE = 2;
90    private static final String[] MAILBOX_NAME_PROJECTION = new String[] {
91            MailboxColumns.DISPLAY_NAME, MailboxColumns.ACCOUNT_KEY,
92            MailboxColumns.TYPE};
93
94    private static final int ACCOUNT_DISPLAY_NAME_COLUMN_ID = 0;
95    private static final String[] ACCOUNT_NAME_PROJECTION = new String[] {
96            AccountColumns.DISPLAY_NAME };
97
98    private static final String ID_SELECTION = EmailContent.RECORD_ID + "=?";
99
100    /* package */ MessageListFragment getListFragmentForTest() {
101        return mListFragment;
102    }
103
104    /**
105     * Open a specific mailbox.
106     *
107     * TODO This should just shortcut to a more generic version that can accept a list of
108     * accounts/mailboxes (e.g. merged inboxes).
109     *
110     * @param context
111     * @param id mailbox key
112     */
113    public static void actionHandleMailbox(Context context, long id) {
114        context.startActivity(createIntent(context, -1, id, -1));
115    }
116
117    /**
118     * Open a specific mailbox by account & type
119     *
120     * @param context The caller's context (for generating an intent)
121     * @param accountId The account to open
122     * @param mailboxType the type of mailbox to open (e.g. @see EmailContent.Mailbox.TYPE_INBOX)
123     */
124    public static void actionHandleAccount(Context context, long accountId, int mailboxType) {
125        context.startActivity(createIntent(context, accountId, -1, mailboxType));
126    }
127
128    /**
129     * Open the inbox of the account with a UUID.  It's used to handle old style
130     * (Android <= 1.6) desktop shortcut intents.
131     */
132    public static void actionOpenAccountInboxUuid(Context context, String accountUuid) {
133        Intent i = createIntent(context, -1, -1, Mailbox.TYPE_INBOX);
134        i.setData(Account.getShortcutSafeUriFromUuid(accountUuid));
135        context.startActivity(i);
136    }
137
138    /**
139     * Return an intent to open a specific mailbox by account & type.
140     *
141     * @param context The caller's context (for generating an intent)
142     * @param accountId The account to open, or -1
143     * @param mailboxId the ID of the mailbox to open, or -1
144     * @param mailboxType the type of mailbox to open (e.g. @see Mailbox.TYPE_INBOX) or -1
145     */
146    public static Intent createIntent(Context context, long accountId, long mailboxId,
147            int mailboxType) {
148        Intent intent = new Intent(context, MessageList.class);
149        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
150        if (accountId != -1) intent.putExtra(EXTRA_ACCOUNT_ID, accountId);
151        if (mailboxId != -1) intent.putExtra(EXTRA_MAILBOX_ID, mailboxId);
152        if (mailboxType != -1) intent.putExtra(EXTRA_MAILBOX_TYPE, mailboxType);
153        return intent;
154    }
155
156    /**
157     * Create and return an intent for a desktop shortcut for an account.
158     *
159     * @param context Calling context for building the intent
160     * @param account The account of interest
161     * @param mailboxType The folder name to open (typically Mailbox.TYPE_INBOX)
162     * @return an Intent which can be used to view that account
163     */
164    public static Intent createAccountIntentForShortcut(Context context, Account account,
165            int mailboxType) {
166        Intent i = createIntent(context, -1, -1, mailboxType);
167        i.setData(account.getShortcutSafeUri());
168        return i;
169    }
170
171    @Override
172    public void onCreate(Bundle icicle) {
173        super.onCreate(icicle);
174        setContentView(R.layout.message_list);
175
176        mControllerCallback = new ControllerResultUiThreadWrapper<ControllerResults>(
177                new Handler(), new ControllerResults());
178        mListFragment = (MessageListFragment) findFragmentById(R.id.message_list_fragment);
179        mMultiSelectPanel = findViewById(R.id.footer_organize);
180        mReadUnreadButton = (Button) findViewById(R.id.btn_read_unread);
181        mFavoriteButton = (Button) findViewById(R.id.btn_multi_favorite);
182        mDeleteButton = (Button) findViewById(R.id.btn_multi_delete);
183        mLeftTitle = (TextView) findViewById(R.id.title_left_text);
184        mProgressIcon = (ProgressBar) findViewById(R.id.title_progress_icon);
185        mErrorBanner = (TextView) findViewById(R.id.connection_error_text);
186
187        mReadUnreadButton.setOnClickListener(this);
188        mFavoriteButton.setOnClickListener(this);
189        mDeleteButton.setOnClickListener(this);
190        ((Button) findViewById(R.id.account_title_button)).setOnClickListener(this);
191
192        mListFragment.setCallback(this);
193
194        mResolver = getContentResolver();
195
196        // Show the appropriate account/mailbox specified by an {@link Intent}.
197        selectAccountAndMailbox(getIntent());
198    }
199
200    /**
201     * Show the appropriate account/mailbox specified by an {@link Intent}.
202     */
203    private void selectAccountAndMailbox(Intent intent) {
204        long mailboxId = intent.getLongExtra(EXTRA_MAILBOX_ID, -1);
205        if (mailboxId != -1) {
206            // Specific mailbox ID was provided - go directly to it
207            mSetTitleTask = new SetTitleTask(mailboxId);
208            mSetTitleTask.execute();
209            mListFragment.openMailbox(mailboxId);
210        } else {
211            int mailboxType = intent.getIntExtra(EXTRA_MAILBOX_TYPE, Mailbox.TYPE_INBOX);
212            Uri uri = intent.getData();
213            // TODO Possible ANR.  getAccountIdFromShortcutSafeUri accesses DB.
214            long accountId = (uri == null) ? -1
215                    : Account.getAccountIdFromShortcutSafeUri(this, uri);
216            if (accountId == -1) {
217                accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1);
218            }
219            if (accountId == -1) {
220                launchWelcomeAndFinish();
221                return;
222            }
223            mMailboxFinder = new MailboxFinder(this, accountId, mailboxType,
224                    mMailboxFinderCallback);
225            mMailboxFinder.startLookup();
226        }
227        // TODO set title to "account > mailbox (#unread)"
228    }
229
230    @Override
231    public void onPause() {
232        super.onPause();
233        mController.removeResultCallback(mControllerCallback);
234    }
235
236    @Override
237    public void onResume() {
238        super.onResume();
239        mController.addResultCallback(mControllerCallback);
240
241        // clear notifications here
242        NotificationManager notificationManager = (NotificationManager)
243                getSystemService(Context.NOTIFICATION_SERVICE);
244        notificationManager.cancel(MailService.NOTIFICATION_ID_NEW_MESSAGES);
245
246        // Exit immediately if the accounts list has changed (e.g. externally deleted)
247        if (Email.getNotifyUiAccountsChanged()) {
248            Welcome.actionStart(this);
249            finish();
250            return;
251        }
252    }
253
254    @Override
255    protected void onDestroy() {
256        super.onDestroy();
257
258        if (mMailboxFinder != null) {
259            mMailboxFinder.close();
260            mMailboxFinder = null;
261        }
262        Utility.cancelTaskInterrupt(mSetTitleTask);
263        mSetTitleTask = null;
264    }
265
266
267    private void launchWelcomeAndFinish() {
268        Welcome.actionStart(this);
269        finish();
270    }
271
272    /**
273     * Called when the list fragment can't find mailbox/account.
274     */
275    public void onMailboxNotFound() {
276        finish();
277    }
278
279    @Override
280    public void onMessageOpen(long messageId, long messageMailboxId, long listMailboxId, int type) {
281        if (type == MessageListFragment.Callback.TYPE_DRAFT) {
282            MessageCompose.actionEditDraft(this, messageId);
283        } else {
284            final boolean disableReply = (type == MessageListFragment.Callback.TYPE_TRASH);
285            // WARNING: here we pass "listMailboxId", which can be the negative id of
286            // a compound mailbox, instead of the mailboxId of the particular message that
287            // is opened.  This is to support the next/prev buttons on the message view
288            // properly even for combined mailboxes.
289            MessageView.actionView(this, messageId, listMailboxId, disableReply);
290        }
291    }
292
293    public void onClick(View v) {
294        switch (v.getId()) {
295            case R.id.btn_read_unread:
296                mListFragment.onMultiToggleRead();
297                break;
298            case R.id.btn_multi_favorite:
299                mListFragment.onMultiToggleFavorite();
300                break;
301            case R.id.btn_multi_delete:
302                mListFragment.onMultiDelete();
303                break;
304            case R.id.account_title_button:
305                onAccounts();
306                break;
307        }
308    }
309
310    public void onAnimationEnd(Animation animation) {
311        // TODO: If the button panel hides the only selected item, scroll the list to make it
312        // visible again.
313    }
314
315    public void onAnimationRepeat(Animation animation) {
316    }
317
318    public void onAnimationStart(Animation animation) {
319    }
320
321    @Override
322    public boolean onPrepareOptionsMenu(Menu menu) {
323        // Re-create menu every time.  (We may not know the mailbox id yet)
324        menu.clear();
325        if (mListFragment.isMagicMailbox()) {
326            getMenuInflater().inflate(R.menu.message_list_option_smart_folder, menu);
327        } else {
328            getMenuInflater().inflate(R.menu.message_list_option, menu);
329        }
330        boolean showDeselect = mListFragment.getSelectedCount() > 0;
331        menu.setGroupVisible(R.id.deselect_all_group, showDeselect);
332        return true;
333    }
334
335    @Override
336    public boolean onOptionsItemSelected(MenuItem item) {
337        switch (item.getItemId()) {
338            case R.id.refresh:
339                mListFragment.onRefresh();
340                return true;
341            case R.id.folders:
342                onFolders();
343                return true;
344            case R.id.accounts:
345                onAccounts();
346                return true;
347            case R.id.compose:
348                onCompose();
349                return true;
350            case R.id.account_settings:
351                onEditAccount();
352                return true;
353            case R.id.deselect_all:
354                mListFragment.onDeselectAll();
355                return true;
356            default:
357                return super.onOptionsItemSelected(item);
358        }
359    }
360
361    private void onFolders() {
362        if (!mListFragment.isMagicMailbox()) { // Magic boxes don't have "folders" option.
363            // TODO smaller projection
364            Mailbox mailbox = Mailbox.restoreMailboxWithId(this, mListFragment.getMailboxId());
365            if (mailbox != null) {
366                MailboxList.actionHandleAccount(this, mailbox.mAccountKey);
367                finish();
368            }
369        }
370    }
371
372    private void onAccounts() {
373        AccountFolderList.actionShowAccounts(this);
374        finish();
375    }
376
377    private void onCompose() {
378        MessageCompose.actionCompose(this, mListFragment.getAccountId());
379    }
380
381    private void onEditAccount() {
382        if (!mListFragment.isMagicMailbox()) { // Magic boxes don't have "accout settings" option.
383            AccountSettings.actionSettings(this, mListFragment.getAccountId());
384        }
385    }
386
387    /**
388     * Show multi-selection panel, if one or more messages are selected.   Button labels will be
389     * updated too.
390     *
391     * @deprecated not used any longer.  remove them.
392     */
393    public void onSelectionChanged() {
394        showMultiPanel(mListFragment.getSelectedCount() > 0);
395    }
396
397    /**
398     * @deprecated not used any longer.  remove them.  (with associated resources, strings,
399     * members, etc)
400     */
401    private void updateFooterButtonNames () {
402        // Show "unread_action" when one or more read messages are selected.
403        if (mListFragment.doesSelectionContainReadMessage()) {
404            mReadUnreadButton.setText(R.string.unread_action);
405        } else {
406            mReadUnreadButton.setText(R.string.read_action);
407        }
408        // Show "set_star_action" when one or more un-starred messages are selected.
409        if (mListFragment.doesSelectionContainNonStarredMessage()) {
410            mFavoriteButton.setText(R.string.set_star_action);
411        } else {
412            mFavoriteButton.setText(R.string.remove_star_action);
413        }
414    }
415
416    /**
417     * Show or hide the panel of multi-select options
418     *
419     * @deprecated not used any longer.  remove them.
420     */
421    private void showMultiPanel(boolean show) {
422        if (show && mMultiSelectPanel.getVisibility() != View.VISIBLE) {
423            mMultiSelectPanel.setVisibility(View.VISIBLE);
424            Animation animation = AnimationUtils.loadAnimation(this, R.anim.footer_appear);
425            animation.setAnimationListener(this);
426            mMultiSelectPanel.startAnimation(animation);
427        } else if (!show && mMultiSelectPanel.getVisibility() != View.GONE) {
428            mMultiSelectPanel.setVisibility(View.GONE);
429            mMultiSelectPanel.startAnimation(
430                        AnimationUtils.loadAnimation(this, R.anim.footer_disappear));
431        }
432        if (show) {
433            updateFooterButtonNames();
434        }
435    }
436
437    /**
438     * Handle the eventual result from the security update activity
439     *
440     * Note, this is extremely coarse, and it simply returns the user to the Accounts list.
441     * Anything more requires refactoring of this Activity.
442     */
443    @Override
444    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
445        switch (requestCode) {
446            case REQUEST_SECURITY:
447                onAccounts();
448        }
449        super.onActivityResult(requestCode, resultCode, data);
450    }
451
452    private class SetTitleTask extends AsyncTask<Void, Void, Object[]> {
453
454        private long mMailboxKey;
455
456        public SetTitleTask(long mailboxKey) {
457            mMailboxKey = mailboxKey;
458        }
459
460        @Override
461        protected Object[] doInBackground(Void... params) {
462            // Check special Mailboxes
463            int resIdSpecialMailbox = 0;
464            if (mMailboxKey == Mailbox.QUERY_ALL_INBOXES) {
465                resIdSpecialMailbox = R.string.account_folder_list_summary_inbox;
466            } else if (mMailboxKey == Mailbox.QUERY_ALL_FAVORITES) {
467                resIdSpecialMailbox = R.string.account_folder_list_summary_starred;
468            } else if (mMailboxKey == Mailbox.QUERY_ALL_DRAFTS) {
469                resIdSpecialMailbox = R.string.account_folder_list_summary_drafts;
470            } else if (mMailboxKey == Mailbox.QUERY_ALL_OUTBOX) {
471                resIdSpecialMailbox = R.string.account_folder_list_summary_outbox;
472            }
473            if (resIdSpecialMailbox != 0) {
474                return new Object[] {null, getString(resIdSpecialMailbox), 0};
475            }
476
477            String accountName = null;
478            String mailboxName = null;
479            String accountKey = null;
480            Cursor c = MessageList.this.mResolver.query(Mailbox.CONTENT_URI,
481                    MAILBOX_NAME_PROJECTION, ID_SELECTION,
482                    new String[] { Long.toString(mMailboxKey) }, null);
483            try {
484                if (c.moveToFirst()) {
485                    mailboxName = Utility.FolderProperties.getInstance(MessageList.this)
486                            .getDisplayName(c.getInt(MAILBOX_NAME_COLUMN_TYPE));
487                    if (mailboxName == null) {
488                        mailboxName = c.getString(MAILBOX_NAME_COLUMN_ID);
489                    }
490                    accountKey = c.getString(MAILBOX_NAME_COLUMN_ACCOUNT_KEY);
491                }
492            } finally {
493                c.close();
494            }
495            if (accountKey != null) {
496                c = MessageList.this.mResolver.query(Account.CONTENT_URI,
497                        ACCOUNT_NAME_PROJECTION, ID_SELECTION, new String[] { accountKey },
498                        null);
499                try {
500                    if (c.moveToFirst()) {
501                        accountName = c.getString(ACCOUNT_DISPLAY_NAME_COLUMN_ID);
502                    }
503                } finally {
504                    c.close();
505                }
506            }
507            int nAccounts = EmailContent.count(MessageList.this, Account.CONTENT_URI, null, null);
508            return new Object[] {accountName, mailboxName, nAccounts};
509        }
510
511        @Override
512        protected void onPostExecute(Object[] result) {
513            if (result == null) {
514                return;
515            }
516
517            final int nAccounts = (Integer) result[2];
518            if (result[0] != null) {
519                setTitleAccountName((String) result[0], nAccounts > 1);
520            }
521
522            if (result[1] != null) {
523                mLeftTitle.setText((String) result[1]);
524            }
525        }
526    }
527
528    private void setTitleAccountName(String accountName, boolean showAccountsButton) {
529        TextView accountsButton = (TextView) findViewById(R.id.account_title_button);
530        TextView textPlain = (TextView) findViewById(R.id.title_right_text);
531        if (showAccountsButton) {
532            accountsButton.setVisibility(View.VISIBLE);
533            textPlain.setVisibility(View.GONE);
534            accountsButton.setText(accountName);
535        } else {
536            accountsButton.setVisibility(View.GONE);
537            textPlain.setVisibility(View.VISIBLE);
538            textPlain.setText(accountName);
539        }
540    }
541
542    private void showProgressIcon(boolean show) {
543        int visibility = show ? View.VISIBLE : View.GONE;
544        mProgressIcon.setVisibility(visibility);
545        mListFragment.showProgressIcon(show);
546    }
547
548    private void showErrorBanner(String message) {
549        boolean isVisible = mErrorBanner.getVisibility() == View.VISIBLE;
550        if (message != null) {
551            mErrorBanner.setText(message);
552            if (!isVisible) {
553                mErrorBanner.setVisibility(View.VISIBLE);
554                mErrorBanner.startAnimation(
555                        AnimationUtils.loadAnimation(
556                                MessageList.this, R.anim.header_appear));
557            }
558        } else {
559            if (isVisible) {
560                mErrorBanner.setVisibility(View.GONE);
561                mErrorBanner.startAnimation(
562                        AnimationUtils.loadAnimation(
563                                MessageList.this, R.anim.header_disappear));
564            }
565        }
566    }
567
568    /**
569     * Controller results listener.  We wrap it with {@link ControllerResultUiThreadWrapper},
570     * so all methods are called on the UI thread.
571     */
572    private class ControllerResults extends Controller.Result {
573
574        // This is used to alter the connection banner operation for sending messages
575        private MessagingException mSendMessageException;
576
577        // TODO check accountKey and only react to relevant notifications
578        @Override
579        public void updateMailboxCallback(MessagingException result, long accountKey,
580                long mailboxKey, int progress, int numNewMessages) {
581            updateBanner(result, progress, mailboxKey);
582            if (result != null || progress == 100) {
583                Email.updateMailboxRefreshTime(mailboxKey);
584            }
585            updateProgress(result, progress);
586        }
587
588        /**
589         * We alter the updateBanner hysteresis here to capture any failures and handle
590         * them just once at the end.  This callback is overly overloaded:
591         *  result == null, messageId == -1, progress == 0:     start batch send
592         *  result == null, messageId == xx, progress == 0:     start sending one message
593         *  result == xxxx, messageId == xx, progress == 0;     failed sending one message
594         *  result == null, messageId == -1, progres == 100;    finish sending batch
595         */
596        @Override
597        public void sendMailCallback(MessagingException result, long accountId, long messageId,
598                int progress) {
599            if (mListFragment.isOutbox()) {
600                // reset captured error when we start sending one or more messages
601                if (messageId == -1 && result == null && progress == 0) {
602                    mSendMessageException = null;
603                }
604                // capture first exception that comes along
605                if (result != null && mSendMessageException == null) {
606                    mSendMessageException = result;
607                }
608                // if we're completing the sequence, change the banner state
609                if (messageId == -1 && progress == 100) {
610                    updateBanner(mSendMessageException, progress, mListFragment.getMailboxId());
611                }
612                // always update the spinner, which has less state to worry about
613                updateProgress(result, progress);
614            }
615        }
616
617        private void updateProgress(MessagingException result, int progress) {
618            showProgressIcon(result == null && progress < 100);
619        }
620
621        /**
622         * Show or hide the connection error banner, and convert the various MessagingException
623         * variants into localizable text.  There is hysteresis in the show/hide logic:  Once shown,
624         * the banner will remain visible until some progress is made on the connection.  The
625         * goal is to keep it from flickering during retries in a bad connection state.
626         *
627         * @param result
628         * @param progress
629         */
630        private void updateBanner(MessagingException result, int progress, long mailboxKey) {
631            if (mailboxKey != mListFragment.getMailboxId()) {
632                return;
633            }
634            if (result != null) {
635                int id = R.string.status_network_error;
636                if (result instanceof AuthenticationFailedException) {
637                    id = R.string.account_setup_failed_dlg_auth_message;
638                } else if (result instanceof CertificateValidationException) {
639                    id = R.string.account_setup_failed_dlg_certificate_message;
640                } else {
641                    switch (result.getExceptionType()) {
642                        case MessagingException.IOERROR:
643                            id = R.string.account_setup_failed_ioerror;
644                            break;
645                        case MessagingException.TLS_REQUIRED:
646                            id = R.string.account_setup_failed_tls_required;
647                            break;
648                        case MessagingException.AUTH_REQUIRED:
649                            id = R.string.account_setup_failed_auth_required;
650                            break;
651                        case MessagingException.GENERAL_SECURITY:
652                            id = R.string.account_setup_failed_security;
653                            break;
654                        // TODO Generate a unique string for this case, which is the case
655                        // where the security policy needs to be updated.
656                        case MessagingException.SECURITY_POLICIES_REQUIRED:
657                            id = R.string.account_setup_failed_security;
658                            break;
659                    }
660                }
661                showErrorBanner(getString(id));
662            } else if (progress > 0) {
663                showErrorBanner(null);
664            }
665        }
666    }
667
668    private class MailboxFinderCallback implements MailboxFinder.Callback {
669        @Override
670        public void onMailboxFound(long accountId, long mailboxId) {
671            mSetTitleTask = new SetTitleTask(mailboxId);
672            mSetTitleTask.execute();
673            mListFragment.openMailbox(mailboxId);
674        }
675
676        @Override
677        public void onAccountNotFound() {
678            // Let the Welcome activity show the default screen.
679            launchWelcomeAndFinish();
680        }
681
682        @Override
683        public void onMailboxNotFound(long accountId) {
684            // Let the Welcome activity show the default screen.
685            launchWelcomeAndFinish();
686        }
687
688        @Override
689        public void onAccountSecurityHold(long accountId) {
690            // launch the security setup activity
691            Intent i = AccountSecurity.actionUpdateSecurityIntent(
692                    MessageList.this, accountId);
693            MessageList.this.startActivityForResult(i, REQUEST_SECURITY);
694        }
695    }
696}
697