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