SecureConversationViewController.java revision 234d35352eeaaa8d3928e31028be49112607bd29
1/* 2 * Copyright (C) 2013 Google Inc. 3 * Licensed to The Android Open Source Project. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.mail.ui; 19 20import android.app.Fragment; 21import android.app.FragmentManager; 22import android.content.res.Resources; 23import android.os.Bundle; 24import android.view.LayoutInflater; 25import android.view.View; 26import android.view.ViewGroup; 27import android.webkit.WebSettings; 28 29import com.android.mail.FormattedDateBuilder; 30import com.android.mail.R; 31import com.android.mail.browse.BorderView; 32import com.android.mail.browse.ConversationMessage; 33import com.android.mail.browse.ConversationViewAdapter; 34import com.android.mail.browse.ConversationViewAdapter.MessageHeaderItem; 35import com.android.mail.browse.ConversationViewHeader; 36import com.android.mail.browse.MessageFooterView; 37import com.android.mail.browse.MessageHeaderView; 38import com.android.mail.browse.MessageScrollView; 39import com.android.mail.browse.MessageWebView; 40import com.android.mail.print.PrintUtils; 41import com.android.mail.providers.Conversation; 42import com.android.mail.providers.Message; 43import com.android.mail.utils.ConversationViewUtils; 44 45/** 46 * Controller to do most of the heavy lifting for {@link SecureConversationViewFragment} 47 * and {@link com.android.mail.browse.EmlMessageViewFragment}. Currently that work is 48 * pretty much the rendering logic. 49 */ 50public class SecureConversationViewController implements 51 MessageHeaderView.MessageHeaderViewCallbacks { 52 private static final String BEGIN_HTML = 53 "<body style=\"margin: 0 %spx;\"><div style=\"margin: 16px 0; font-size: 80%%\">"; 54 private static final String END_HTML = "</div></body>"; 55 56 private final SecureConversationViewControllerCallbacks mCallbacks; 57 58 private MessageWebView mWebView; 59 private ConversationViewHeader mConversationHeaderView; 60 private MessageHeaderView mMessageHeaderView; 61 private MessageFooterView mMessageFooterView; 62 private ConversationMessage mMessage; 63 private MessageScrollView mScrollView; 64 65 private ConversationViewProgressController mProgressController; 66 private FormattedDateBuilder mDateBuilder; 67 68 private int mSideMarginInWebPx; 69 70 public SecureConversationViewController(SecureConversationViewControllerCallbacks callbacks) { 71 mCallbacks = callbacks; 72 } 73 74 public View onCreateView(LayoutInflater inflater, ViewGroup container, 75 Bundle savedInstanceState) { 76 View rootView = inflater.inflate(R.layout.secure_conversation_view, container, false); 77 mScrollView = (MessageScrollView) rootView.findViewById(R.id.scroll_view); 78 mConversationHeaderView = (ConversationViewHeader) rootView.findViewById(R.id.conv_header); 79 mMessageHeaderView = (MessageHeaderView) rootView.findViewById(R.id.message_header); 80 mMessageFooterView = (MessageFooterView) rootView.findViewById(R.id.message_footer); 81 82 // Add color backgrounds to the header and footer. 83 // Otherwise the backgrounds are grey. They can't 84 // be set in xml because that would add more overdraw 85 // in ConversationViewFragment. 86 final int color = rootView.getResources().getColor( 87 R.color.message_header_background_color); 88 mMessageHeaderView.setBackgroundColor(color); 89 mMessageFooterView.setBackgroundColor(color); 90 91 ((BorderView) rootView.findViewById(R.id.top_border)).disableCardBottomBorder(); 92 ((BorderView) rootView.findViewById(R.id.bottom_border)).disableCardTopBorder(); 93 94 mProgressController = new ConversationViewProgressController( 95 mCallbacks.getFragment(), mCallbacks.getHandler()); 96 mProgressController.instantiateProgressIndicators(rootView); 97 mWebView = (MessageWebView) rootView.findViewById(R.id.webview); 98 mWebView.setOverScrollMode(View.OVER_SCROLL_NEVER); 99 mWebView.setWebViewClient(mCallbacks.getWebViewClient()); 100 mWebView.setFocusable(false); 101 final WebSettings settings = mWebView.getSettings(); 102 103 settings.setJavaScriptEnabled(false); 104 settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); 105 106 ConversationViewUtils.setTextZoom(mCallbacks.getFragment().getResources(), settings); 107 108 settings.setSupportZoom(true); 109 settings.setBuiltInZoomControls(true); 110 settings.setDisplayZoomControls(false); 111 112 mScrollView.setInnerScrollableView(mWebView); 113 114 return rootView; 115 } 116 117 public void onActivityCreated(Bundle savedInstanceState) { 118 mCallbacks.setupConversationHeaderView(mConversationHeaderView); 119 120 final Fragment fragment = mCallbacks.getFragment(); 121 122 mDateBuilder = new FormattedDateBuilder(fragment.getActivity()); 123 mMessageHeaderView.initialize( 124 mCallbacks.getConversationAccountController(), mCallbacks.getAddressCache()); 125 mMessageHeaderView.setExpandMode(MessageHeaderView.POPUP_MODE); 126 mMessageHeaderView.setContactInfoSource(mCallbacks.getContactInfoSource()); 127 mMessageHeaderView.setCallbacks(this); 128 mMessageHeaderView.setExpandable(false); 129 mMessageHeaderView.setViewOnlyMode(mCallbacks.isViewOnlyMode()); 130 131 mCallbacks.setupMessageHeaderVeiledMatcher(mMessageHeaderView); 132 133 mMessageFooterView.initialize(fragment.getLoaderManager(), fragment.getFragmentManager()); 134 135 mCallbacks.startMessageLoader(); 136 137 mProgressController.showLoadingStatus(mCallbacks.isViewVisibleToUser()); 138 139 final Resources r = mCallbacks.getFragment().getResources(); 140 mSideMarginInWebPx = (int) (r.getDimensionPixelOffset( 141 R.dimen.conversation_message_content_margin_side) / r.getDisplayMetrics().density); 142 } 143 144 /** 145 * Populate the adapter with overlay views (message headers, super-collapsed 146 * blocks, a conversation header), and return an HTML document with spacer 147 * divs inserted for all overlays. 148 */ 149 public void renderMessage(ConversationMessage message) { 150 mMessage = message; 151 152 mWebView.getSettings().setBlockNetworkImage(!mMessage.alwaysShowImages); 153 154 // Add formatting to message body 155 // At this point, only adds margins. 156 StringBuilder dataBuilder = new StringBuilder( 157 String.format(BEGIN_HTML, mSideMarginInWebPx)); 158 dataBuilder.append(mMessage.getBodyAsHtml()); 159 dataBuilder.append(END_HTML); 160 161 mWebView.loadDataWithBaseURL(mCallbacks.getBaseUri(), dataBuilder.toString(), 162 "text/html", "utf-8", null); 163 final MessageHeaderItem item = ConversationViewAdapter.newMessageHeaderItem( 164 null, mDateBuilder, mMessage, true, mMessage.alwaysShowImages); 165 // Clear out the old info from the header before (re)binding 166 mMessageHeaderView.unbind(); 167 mMessageHeaderView.bind(item, false); 168 if (mMessage.hasAttachments) { 169 mMessageFooterView.setVisibility(View.VISIBLE); 170 mMessageFooterView.bind(item, mCallbacks.getAccountUri(), false); 171 } 172 } 173 174 public ConversationMessage getMessage() { 175 return mMessage; 176 } 177 178 public ConversationViewHeader getConversationHeaderView() { 179 return mConversationHeaderView; 180 } 181 182 public void dismissLoadingStatus() { 183 mProgressController.dismissLoadingStatus(); 184 } 185 186 public void setSubject(String subject) { 187 mConversationHeaderView.setSubject(subject); 188 } 189 190 public void printMessage() { 191 final Conversation conversation = mMessage.getConversation(); 192 PrintUtils.printMessage(mCallbacks.getFragment().getActivity(), mMessage, 193 conversation != null ? conversation.subject : mMessage.subject, 194 mCallbacks.getAddressCache(), mCallbacks.getBaseUri(), false /* useJavascript */); 195 196 } 197 198 // Start MessageHeaderViewCallbacks implementations 199 200 @Override 201 public void setMessageSpacerHeight(MessageHeaderItem item, int newSpacerHeight) { 202 // Do nothing. 203 } 204 205 @Override 206 public void setMessageExpanded(MessageHeaderItem item, int newSpacerHeight, 207 int topBorderHeight, int bottomBorderHeight) { 208 // Do nothing. 209 } 210 211 @Override 212 public void setMessageDetailsExpanded(MessageHeaderItem i, boolean expanded, int heightBefore) { 213 // Do nothing. 214 } 215 216 @Override 217 public void showExternalResources(final Message msg) { 218 mWebView.getSettings().setBlockNetworkImage(false); 219 } 220 221 @Override 222 public void showExternalResources(final String rawSenderAddress) { 223 mWebView.getSettings().setBlockNetworkImage(false); 224 } 225 226 @Override 227 public boolean supportsMessageTransforms() { 228 return false; 229 } 230 231 @Override 232 public String getMessageTransforms(final Message msg) { 233 return null; 234 } 235 236 @Override 237 public FragmentManager getFragmentManager() { 238 return mCallbacks.getFragment().getFragmentManager(); 239 } 240 241 // End MessageHeaderViewCallbacks implementations 242} 243