| /* |
| * Copyright (C) 2012 Google Inc. |
| * Licensed to The Android Open Source Project. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.mail.ui; |
| |
| import android.app.Fragment; |
| import android.content.Loader; |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.webkit.WebView; |
| |
| import com.android.emailcommon.mail.Address; |
| import com.android.mail.browse.ConversationAccountController; |
| import com.android.mail.browse.ConversationMessage; |
| import com.android.mail.browse.ConversationViewHeader; |
| import com.android.mail.browse.MessageCursor; |
| import com.android.mail.browse.MessageHeaderView; |
| import com.android.mail.content.ObjectCursor; |
| import com.android.mail.providers.Account; |
| import com.android.mail.providers.Conversation; |
| import com.android.mail.utils.LogTag; |
| import com.android.mail.utils.LogUtils; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Sets; |
| |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| public class SecureConversationViewFragment extends AbstractConversationViewFragment |
| implements SecureConversationViewControllerCallbacks { |
| private static final String LOG_TAG = LogTag.getLogTag(); |
| |
| private SecureConversationViewController mViewController; |
| |
| private class SecureConversationWebViewClient extends AbstractConversationWebViewClient { |
| public SecureConversationWebViewClient(Account account) { |
| super(account); |
| } |
| |
| @Override |
| public void onPageFinished(WebView view, String url) { |
| // Ignore unsafe calls made after a fragment is detached from an activity. |
| // This method needs to, for example, get at the loader manager, which needs |
| // the fragment to be added. |
| if (!isAdded()) { |
| LogUtils.d(LOG_TAG, "ignoring SCVF.onPageFinished, url=%s fragment=%s", url, |
| SecureConversationViewFragment.this); |
| return; |
| } |
| |
| if (isUserVisible()) { |
| onConversationSeen(); |
| } |
| |
| mViewController.dismissLoadingStatus(); |
| |
| final Set<String> emailAddresses = Sets.newHashSet(); |
| final List<Address> cacheCopy; |
| synchronized (mAddressCache) { |
| cacheCopy = ImmutableList.copyOf(mAddressCache.values()); |
| } |
| for (Address addr : cacheCopy) { |
| emailAddresses.add(addr.getAddress()); |
| } |
| final ContactLoaderCallbacks callbacks = getContactInfoSource(); |
| callbacks.setSenders(emailAddresses); |
| getLoaderManager().restartLoader(CONTACT_LOADER, Bundle.EMPTY, callbacks); |
| } |
| } |
| |
| /** |
| * Creates a new instance of {@link ConversationViewFragment}, initialized |
| * to display a conversation with other parameters inherited/copied from an |
| * existing bundle, typically one created using {@link #makeBasicArgs}. |
| */ |
| public static SecureConversationViewFragment newInstance(Bundle existingArgs, |
| Conversation conversation) { |
| SecureConversationViewFragment f = new SecureConversationViewFragment(); |
| Bundle args = new Bundle(existingArgs); |
| args.putParcelable(ARG_CONVERSATION, conversation); |
| f.setArguments(args); |
| return f; |
| } |
| |
| /** |
| * Constructor needs to be public to handle orientation changes and activity |
| * lifecycle events. |
| */ |
| public SecureConversationViewFragment() {} |
| |
| @Override |
| public void onCreate(Bundle savedState) { |
| super.onCreate(savedState); |
| |
| mWebViewClient = new SecureConversationWebViewClient(mAccount); |
| mViewController = new SecureConversationViewController(this); |
| } |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| return mViewController.onCreateView(inflater, container, savedInstanceState); |
| } |
| |
| @Override |
| public void onActivityCreated(Bundle savedInstanceState) { |
| super.onActivityCreated(savedInstanceState); |
| mViewController.onActivityCreated(savedInstanceState); |
| } |
| |
| @Override |
| public void onDestroyView() { |
| super.onDestroyView(); |
| mViewController.onDestroyView(); |
| } |
| |
| // Start implementations of SecureConversationViewControllerCallbacks |
| |
| @Override |
| public Fragment getFragment() { |
| return this; |
| } |
| |
| @Override |
| public AbstractConversationWebViewClient getWebViewClient() { |
| return mWebViewClient; |
| } |
| |
| @Override |
| public void setupConversationHeaderView(ConversationViewHeader headerView) { |
| headerView.setCallbacks(this, this); |
| headerView.setFolders(mConversation); |
| headerView.setSubject(mConversation.subject); |
| } |
| |
| @Override |
| public boolean isViewVisibleToUser() { |
| return isUserVisible(); |
| } |
| |
| @Override |
| public ConversationAccountController getConversationAccountController() { |
| return this; |
| } |
| |
| @Override |
| public Map<String, Address> getAddressCache() { |
| return mAddressCache; |
| } |
| |
| @Override |
| public void setupMessageHeaderVeiledMatcher(MessageHeaderView messageHeaderView) { |
| messageHeaderView.setVeiledMatcher( |
| ((ControllableActivity) getActivity()).getAccountController() |
| .getVeiledAddressMatcher()); |
| } |
| |
| @Override |
| public void startMessageLoader() { |
| getLoaderManager().initLoader(MESSAGE_LOADER, null, getMessageLoaderCallbacks()); |
| } |
| |
| @Override |
| public String getBaseUri() { |
| return mBaseUri; |
| } |
| |
| @Override |
| public boolean isViewOnlyMode() { |
| return false; |
| } |
| |
| // End implementations of SecureConversationViewControllerCallbacks |
| |
| @Override |
| protected void markUnread() { |
| super.markUnread(); |
| // Ignore unsafe calls made after a fragment is detached from an activity |
| final ControllableActivity activity = (ControllableActivity) getActivity(); |
| final ConversationMessage message = mViewController.getMessage(); |
| if (activity == null || mConversation == null || message == null) { |
| LogUtils.w(LOG_TAG, "ignoring markUnread for conv=%s", |
| mConversation != null ? mConversation.id : 0); |
| return; |
| } |
| final HashSet<Uri> uris = new HashSet<Uri>(); |
| uris.add(message.uri); |
| activity.getConversationUpdater().markConversationMessagesUnread(mConversation, uris, |
| mViewState.getConversationInfo()); |
| } |
| |
| @Override |
| public void onAccountChanged(Account newAccount, Account oldAccount) { |
| renderMessage(getMessageCursor()); |
| } |
| |
| @Override |
| public void onConversationViewHeaderHeightChange(int newHeight) { |
| // Do nothing. |
| } |
| |
| @Override |
| public void onUserVisibleHintChanged() { |
| if (mActivity == null) { |
| return; |
| } |
| if (isUserVisible()) { |
| onConversationSeen(); |
| } |
| } |
| |
| @Override |
| protected void onMessageCursorLoadFinished(Loader<ObjectCursor<ConversationMessage>> loader, |
| MessageCursor newCursor, MessageCursor oldCursor) { |
| renderMessage(newCursor); |
| } |
| |
| private void renderMessage(MessageCursor newCursor) { |
| // ignore cursors that are still loading results |
| if (newCursor == null || !newCursor.isLoaded()) { |
| LogUtils.i(LOG_TAG, "CONV RENDER: existing cursor is null, rendering from scratch"); |
| return; |
| } |
| if (mActivity == null || mActivity.isFinishing()) { |
| // Activity is finishing, just bail. |
| return; |
| } |
| if (!newCursor.moveToFirst()) { |
| LogUtils.e(LOG_TAG, "unable to open message cursor"); |
| return; |
| } |
| |
| mViewController.renderMessage(newCursor.getMessage()); |
| } |
| |
| @Override |
| public void onConversationUpdated(Conversation conv) { |
| final ConversationViewHeader headerView = mViewController.getConversationHeaderView(); |
| if (headerView != null) { |
| headerView.onConversationUpdated(conv); |
| headerView.setSubject(conv.subject); |
| } |
| } |
| |
| // Need this stub here |
| @Override |
| public boolean supportsMessageTransforms() { |
| return false; |
| } |
| |
| /** |
| * Users are expected to use the Print item in the Message overflow menu to print the single |
| * message. |
| * |
| * @return {@code false} because Print and Print All menu items are never shown in EMail. |
| */ |
| @Override |
| protected boolean shouldShowPrintInOverflow() { |
| return false; |
| } |
| |
| @Override |
| protected void printConversation() { |
| mViewController.printMessage(); |
| } |
| } |