1f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp/*
2f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp * Copyright (C) 2012 Google Inc.
3f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp * Licensed to The Android Open Source Project.
4f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp *
5f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp * Licensed under the Apache License, Version 2.0 (the "License");
6f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp * you may not use this file except in compliance with the License.
7f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp * You may obtain a copy of the License at
8f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp *
9f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp *      http://www.apache.org/licenses/LICENSE-2.0
10f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp *
11f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp * Unless required by applicable law or agreed to in writing, software
12f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp * distributed under the License is distributed on an "AS IS" BASIS,
13f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp * See the License for the specific language governing permissions and
15f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp * limitations under the License.
16f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp */
17f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
18351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huangpackage com.android.mail.ui;
19f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
204ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sappersteinimport android.app.Fragment;
21f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport android.content.Loader;
22f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport android.net.Uri;
23f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport android.os.Bundle;
24f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport android.view.LayoutInflater;
25f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport android.view.View;
26f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport android.view.ViewGroup;
27934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieuximport android.webkit.WebResourceResponse;
28f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport android.webkit.WebView;
29f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
30821e578a71c7015646522e729600618f0ec16fc0Tony Mantlerimport com.android.emailcommon.mail.Address;
314ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sappersteinimport com.android.mail.browse.ConversationAccountController;
328812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.mail.browse.ConversationMessage;
33351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huangimport com.android.mail.browse.ConversationViewHeader;
34351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huangimport com.android.mail.browse.MessageCursor;
35351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huangimport com.android.mail.browse.MessageHeaderView;
36a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Caoimport com.android.mail.compose.ComposeActivity;
37c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrookimport com.android.mail.content.ObjectCursor;
38adbf3e8cadb66666f307352b72537fbac57b916fAndy Huangimport com.android.mail.providers.Account;
39f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport com.android.mail.providers.Conversation;
40f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport com.android.mail.utils.LogTag;
41f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport com.android.mail.utils.LogUtils;
424ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sappersteinimport com.google.common.collect.ImmutableList;
434ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sappersteinimport com.google.common.collect.Sets;
44f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
45f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport java.util.HashSet;
464ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sappersteinimport java.util.List;
474ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sappersteinimport java.util.Map;
484ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sappersteinimport java.util.Set;
49f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
504ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sappersteinpublic class SecureConversationViewFragment extends AbstractConversationViewFragment
514ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        implements SecureConversationViewControllerCallbacks {
52f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    private static final String LOG_TAG = LogTag.getLogTag();
53bf1d35fab89443d8e380ab48e98ac1c8cd7a6686Andrew Sapperstein
544ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    private SecureConversationViewController mViewController;
55376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein
56376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein    private class SecureConversationWebViewClient extends AbstractConversationWebViewClient {
574ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        public SecureConversationWebViewClient(Account account) {
584ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            super(account);
59376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein        }
60376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein
61ff282d0ef252dbdaf6e9f4e2a7fd640287c01e6bmindyp        @Override
62934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
63934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            // try to load the url assuming it is a cid url
64934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            final Uri uri = Uri.parse(url);
65934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            final WebResourceResponse response = loadCIDUri(uri, mViewController.getMessage());
66934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            if (response != null) {
67934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux                return response;
68934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            }
69934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux
70934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            // otherwise, attempt the default handling
71934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            return super.shouldInterceptRequest(view, url);
72934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux        }
73934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux
74934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux        @Override
75ff282d0ef252dbdaf6e9f4e2a7fd640287c01e6bmindyp        public void onPageFinished(WebView view, String url) {
76a88125e43f1d1c93b8a563597e3c4dcf706bdd44Paul Westbrook            // Ignore unsafe calls made after a fragment is detached from an activity.
77a88125e43f1d1c93b8a563597e3c4dcf706bdd44Paul Westbrook            // This method needs to, for example, get at the loader manager, which needs
78a88125e43f1d1c93b8a563597e3c4dcf706bdd44Paul Westbrook            // the fragment to be added.
79a88125e43f1d1c93b8a563597e3c4dcf706bdd44Paul Westbrook            if (!isAdded()) {
80a88125e43f1d1c93b8a563597e3c4dcf706bdd44Paul Westbrook                LogUtils.d(LOG_TAG, "ignoring SCVF.onPageFinished, url=%s fragment=%s", url,
81a88125e43f1d1c93b8a563597e3c4dcf706bdd44Paul Westbrook                        SecureConversationViewFragment.this);
82a88125e43f1d1c93b8a563597e3c4dcf706bdd44Paul Westbrook                return;
83a88125e43f1d1c93b8a563597e3c4dcf706bdd44Paul Westbrook            }
84a88125e43f1d1c93b8a563597e3c4dcf706bdd44Paul Westbrook
859d3fd92ed6091dbd0d38799222a1cf841f1c3f29Andy Huang            if (isUserVisible()) {
864d8cad5e37ade03903a23cca8ea3e782af21170fPaul Westbrook                onConversationSeen();
874d8cad5e37ade03903a23cca8ea3e782af21170fPaul Westbrook            }
884d8cad5e37ade03903a23cca8ea3e782af21170fPaul Westbrook
894ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            mViewController.dismissLoadingStatus();
904ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein
914ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            final Set<String> emailAddresses = Sets.newHashSet();
924ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            final List<Address> cacheCopy;
934ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            synchronized (mAddressCache) {
944ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein                cacheCopy = ImmutableList.copyOf(mAddressCache.values());
954ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            }
964ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            for (Address addr : cacheCopy) {
974ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein                emailAddresses.add(addr.getAddress());
984ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            }
994ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            final ContactLoaderCallbacks callbacks = getContactInfoSource();
1004ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            callbacks.setSenders(emailAddresses);
1014ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            getLoaderManager().restartLoader(CONTACT_LOADER, Bundle.EMPTY, callbacks);
102ff282d0ef252dbdaf6e9f4e2a7fd640287c01e6bmindyp        }
10337ce6077b70c94ca11063fb82c0600874d826b06Tony Mantler    }
104f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
105f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    /**
106f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp     * Creates a new instance of {@link ConversationViewFragment}, initialized
107f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp     * to display a conversation with other parameters inherited/copied from an
108f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp     * existing bundle, typically one created using {@link #makeBasicArgs}.
109f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp     */
110f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    public static SecureConversationViewFragment newInstance(Bundle existingArgs,
111f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp            Conversation conversation) {
112f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        SecureConversationViewFragment f = new SecureConversationViewFragment();
113f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        Bundle args = new Bundle(existingArgs);
114f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        args.putParcelable(ARG_CONVERSATION, conversation);
115f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        f.setArguments(args);
116f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        return f;
117f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    }
118f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
119f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    /**
120f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp     * Constructor needs to be public to handle orientation changes and activity
121f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp     * lifecycle events.
122f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp     */
123f0ea4849bf7a2c11f99ca0b42307ae8ba665b1dcPaul Westbrook    public SecureConversationViewFragment() {}
124f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
125f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    @Override
126376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein    public void onCreate(Bundle savedState) {
127376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein        super.onCreate(savedState);
128376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein
1294ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        mWebViewClient = new SecureConversationWebViewClient(mAccount);
1304ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        mViewController = new SecureConversationViewController(this);
1314ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    }
1324ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein
1334ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    @Override
1344ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public View onCreateView(LayoutInflater inflater, ViewGroup container,
1354ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein            Bundle savedInstanceState) {
1364ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        return mViewController.onCreateView(inflater, container, savedInstanceState);
137376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein    }
138376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein
139376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein    @Override
140f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    public void onActivityCreated(Bundle savedInstanceState) {
141f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        super.onActivityCreated(savedInstanceState);
1424ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        mViewController.onActivityCreated(savedInstanceState);
1434ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    }
144376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein
1454ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    // Start implementations of SecureConversationViewControllerCallbacks
146bf1d35fab89443d8e380ab48e98ac1c8cd7a6686Andrew Sapperstein
1474ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    @Override
1484ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public Fragment getFragment() {
1494ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        return this;
150f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    }
151f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
152f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    @Override
1534ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public AbstractConversationWebViewClient getWebViewClient() {
1544ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        return mWebViewClient;
1554ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    }
156376294bbb5ded471ad577fdb492875a837021d08Andrew Sapperstein
1574ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    @Override
1584ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public void setupConversationHeaderView(ConversationViewHeader headerView) {
159eb58a092961773a8da67c0e0dd5770346381d938Andrew Sapperstein        headerView.setCallbacks(this, this, getListController());
1604ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        headerView.setFolders(mConversation);
161e6bf30d6e98eb6140b7a5f301efe631ff35c9f7bAndrew Sapperstein        headerView.setSubject(mConversation.subject);
162eb58a092961773a8da67c0e0dd5770346381d938Andrew Sapperstein        headerView.setStarred(mConversation.starred);
1634ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    }
164f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
1654ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    @Override
1664ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public boolean isViewVisibleToUser() {
1674ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        return isUserVisible();
1684ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    }
169f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
1704ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    @Override
1714ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public ConversationAccountController getConversationAccountController() {
1724ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        return this;
1734ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    }
174a8d623a3676f8abdda52b9516556e52e8490dbf7Andrew Sapperstein
1754ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    @Override
1764ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public Map<String, Address> getAddressCache() {
1774ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        return mAddressCache;
1784ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    }
1794d8cad5e37ade03903a23cca8ea3e782af21170fPaul Westbrook
1804ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    @Override
1814ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public void setupMessageHeaderVeiledMatcher(MessageHeaderView messageHeaderView) {
1824ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        messageHeaderView.setVeiledMatcher(
1834ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein                ((ControllableActivity) getActivity()).getAccountController()
1844ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein                        .getVeiledAddressMatcher());
1854ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    }
1864ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein
1874ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    @Override
1884ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public void startMessageLoader() {
1894ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        getLoaderManager().initLoader(MESSAGE_LOADER, null, getMessageLoaderCallbacks());
1904ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    }
1914ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein
1924ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    @Override
1934ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public String getBaseUri() {
1944ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        return mBaseUri;
1954ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    }
196be7739bf0cebc5018c8ffb0c649fc62a74d74e69Andy Huang
1974ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    @Override
1984ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public boolean isViewOnlyMode() {
1994ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        return false;
200f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    }
201f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
2024ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    // End implementations of SecureConversationViewControllerCallbacks
2034ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein
204f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    @Override
205f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    protected void markUnread() {
206d82a31f04f2a4cce27c8023d5330ff13aad198b0Vikram Aggarwal        super.markUnread();
207d82a31f04f2a4cce27c8023d5330ff13aad198b0Vikram Aggarwal        // Ignore unsafe calls made after a fragment is detached from an activity
208f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        final ControllableActivity activity = (ControllableActivity) getActivity();
2094ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        final ConversationMessage message = mViewController.getMessage();
2104ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        if (activity == null || mConversation == null || message == null) {
211fb05201c2c5c53f58846112240a05849319317a9mindyp            LogUtils.w(LOG_TAG, "ignoring markUnread for conv=%s",
212fb05201c2c5c53f58846112240a05849319317a9mindyp                    mConversation != null ? mConversation.id : 0);
213f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp            return;
214f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        }
215d82a31f04f2a4cce27c8023d5330ff13aad198b0Vikram Aggarwal        final HashSet<Uri> uris = new HashSet<Uri>();
2164ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        uris.add(message.uri);
217f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        activity.getConversationUpdater().markConversationMessagesUnread(mConversation, uris,
218351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang                mViewState.getConversationInfo());
219f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    }
220f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
221f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    @Override
222adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang    public void onAccountChanged(Account newAccount, Account oldAccount) {
22337ce6077b70c94ca11063fb82c0600874d826b06Tony Mantler        renderMessage(getMessageCursor());
224f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    }
225f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
226f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    @Override
227f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    public void onConversationViewHeaderHeightChange(int newHeight) {
228f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        // Do nothing.
229f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    }
230f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
231f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    @Override
232f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    public void onUserVisibleHintChanged() {
233604f7716eaac3bc0989cdb2ff129c383b6dfe4d6mindyp        if (mActivity == null) {
234604f7716eaac3bc0989cdb2ff129c383b6dfe4d6mindyp            return;
235604f7716eaac3bc0989cdb2ff129c383b6dfe4d6mindyp        }
23651ad9041014920d78d9b7b3ab84ec04a7c41beaeVikram Aggarwal        if (isUserVisible()) {
23751ad9041014920d78d9b7b3ab84ec04a7c41beaeVikram Aggarwal            onConversationSeen();
238604f7716eaac3bc0989cdb2ff129c383b6dfe4d6mindyp        }
239f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    }
240f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp
241f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    @Override
242c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook    protected void onMessageCursorLoadFinished(Loader<ObjectCursor<ConversationMessage>> loader,
243c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook            MessageCursor newCursor, MessageCursor oldCursor) {
24437ce6077b70c94ca11063fb82c0600874d826b06Tony Mantler        renderMessage(newCursor);
24537ce6077b70c94ca11063fb82c0600874d826b06Tony Mantler    }
24637ce6077b70c94ca11063fb82c0600874d826b06Tony Mantler
24737ce6077b70c94ca11063fb82c0600874d826b06Tony Mantler    private void renderMessage(MessageCursor newCursor) {
248f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        // ignore cursors that are still loading results
249014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang        if (newCursor == null || !newCursor.isLoaded()) {
250f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp            LogUtils.i(LOG_TAG, "CONV RENDER: existing cursor is null, rendering from scratch");
251f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp            return;
252f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        }
2531abfcaf0ee345acee28f0b4892314119082b28a2Mark Wei        if (mActivity == null || mActivity.isFinishing()) {
2541abfcaf0ee345acee28f0b4892314119082b28a2Mark Wei            // Activity is finishing, just bail.
2551abfcaf0ee345acee28f0b4892314119082b28a2Mark Wei            return;
2561abfcaf0ee345acee28f0b4892314119082b28a2Mark Wei        }
2574ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        if (!newCursor.moveToFirst()) {
2582e57e5485504c9ea2e5b5186f22bb76ea5f7bf6dAndy Huang            LogUtils.e(LOG_TAG, "unable to open message cursor");
2592e57e5485504c9ea2e5b5186f22bb76ea5f7bf6dAndy Huang            return;
2602e57e5485504c9ea2e5b5186f22bb76ea5f7bf6dAndy Huang        }
2614ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein
2624ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        mViewController.renderMessage(newCursor.getMessage());
26326d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp    }
26426d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp
26526d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp    @Override
26626d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp    public void onConversationUpdated(Conversation conv) {
2674ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        final ConversationViewHeader headerView = mViewController.getConversationHeaderView();
26826d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp        if (headerView != null) {
26926d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp            headerView.onConversationUpdated(conv);
270f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        }
271f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp    }
2721b3cc47f54072105c161d6ed557550e0e149b8bbmindyp
2734ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    // Need this stub here
274d90639004a3551d7fb7086f318d4c576d54d2b86Scott Kennedy    @Override
2754ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    public boolean supportsMessageTransforms() {
2764ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        return false;
2774ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein    }
2785c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
2797cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux    /**
2807cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux     * Users are expected to use the Print item in the Message overflow menu to print the single
2817cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux     * message.
2827cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux     *
2837cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux     * @return {@code false} because Print and Print All menu items are never shown in EMail.
2847cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux     */
2857cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux    @Override
2867cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux    protected boolean shouldShowPrintInOverflow() {
2877cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux        return false;
2887cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux    }
2897cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux
2907cad28070b4e903e4ce05e5fc610988f71630f97James Lemieux    @Override
2915c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    protected void printConversation() {
292562c5ba7235948cf1d20a9afa40e67cd62f43cf7Andrew Sapperstein        mViewController.printMessage();
2935c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    }
294a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao
295a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao    @Override
296a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao    protected void handleReply() {
297a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao        final ConversationMessage msg = mViewController.getMessage();
298a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao        if (msg != null) {
299a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao            ComposeActivity.reply(getActivity(), mAccount, msg);
300a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao        }
301a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao    }
302a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao
303a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao    @Override
304a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao    protected void handleReplyAll() {
305a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao        final ConversationMessage msg = mViewController.getMessage();
306a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao        if (msg != null) {
307a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao            ComposeActivity.replyAll(getActivity(), mAccount, msg);
308a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao        }
309a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao    }
310f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp}
311