SecureConversationViewController.java revision 8ec43e877a9c1925514f066655984e21fbd255e8
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.InlineAttachmentViewIntentBuilderCreator; 37import com.android.mail.browse.InlineAttachmentViewIntentBuilderCreatorHolder; 38import com.android.mail.browse.MessageFooterView; 39import com.android.mail.browse.MessageHeaderView; 40import com.android.mail.browse.MessageScrollView; 41import com.android.mail.browse.MessageWebView; 42import com.android.mail.browse.WebViewContextMenu; 43import com.android.mail.print.PrintUtils; 44import com.android.mail.providers.Conversation; 45import com.android.mail.providers.Message; 46import com.android.mail.utils.ConversationViewUtils; 47 48/** 49 * Controller to do most of the heavy lifting for {@link SecureConversationViewFragment} 50 * and {@link com.android.mail.browse.EmlMessageViewFragment}. Currently that work is 51 * pretty much the rendering logic. 52 */ 53public class SecureConversationViewController implements 54 MessageHeaderView.MessageHeaderViewCallbacks { 55 private static final String BEGIN_HTML = 56 "<body style=\"margin: 0 %spx;\"><div style=\"margin: 16px 0; font-size: 80%%\">"; 57 private static final String END_HTML = "</div></body>"; 58 59 private final SecureConversationViewControllerCallbacks mCallbacks; 60 61 private MessageWebView mWebView; 62 private ConversationViewHeader mConversationHeaderView; 63 private MessageHeaderView mMessageHeaderView; 64 private MessageFooterView mMessageFooterView; 65 private ConversationMessage mMessage; 66 private MessageScrollView mScrollView; 67 68 private ConversationViewProgressController mProgressController; 69 private FormattedDateBuilder mDateBuilder; 70 71 private int mSideMarginInWebPx; 72 73 public SecureConversationViewController(SecureConversationViewControllerCallbacks callbacks) { 74 mCallbacks = callbacks; 75 } 76 77 public View onCreateView(LayoutInflater inflater, ViewGroup container, 78 Bundle savedInstanceState) { 79 View rootView = inflater.inflate(R.layout.secure_conversation_view, container, false); 80 mScrollView = (MessageScrollView) rootView.findViewById(R.id.scroll_view); 81 mConversationHeaderView = (ConversationViewHeader) rootView.findViewById(R.id.conv_header); 82 mMessageHeaderView = (MessageHeaderView) rootView.findViewById(R.id.message_header); 83 mMessageFooterView = (MessageFooterView) rootView.findViewById(R.id.message_footer); 84 85 // Add color backgrounds to the header and footer. 86 // Otherwise the backgrounds are grey. They can't 87 // be set in xml because that would add more overdraw 88 // in ConversationViewFragment. 89 final int color = rootView.getResources().getColor( 90 R.color.message_header_background_color); 91 mMessageHeaderView.setBackgroundColor(color); 92 mMessageFooterView.setBackgroundColor(color); 93 94 ((BorderView) rootView.findViewById(R.id.top_border)).disableCardBottomBorder(); 95 ((BorderView) rootView.findViewById(R.id.bottom_border)).disableCardTopBorder(); 96 97 mProgressController = new ConversationViewProgressController( 98 mCallbacks.getFragment(), mCallbacks.getHandler()); 99 mProgressController.instantiateProgressIndicators(rootView); 100 mWebView = (MessageWebView) rootView.findViewById(R.id.webview); 101 mWebView.setOverScrollMode(View.OVER_SCROLL_NEVER); 102 mWebView.setWebViewClient(mCallbacks.getWebViewClient()); 103 final InlineAttachmentViewIntentBuilderCreator creator = 104 InlineAttachmentViewIntentBuilderCreatorHolder. 105 getInlineAttachmentViewIntentCreator(); 106 mWebView.setOnCreateContextMenuListener(new WebViewContextMenu( 107 mCallbacks.getFragment().getActivity(), 108 creator.createInlineAttachmentViewIntentBuilder(null, null, -1))); 109 mWebView.setFocusable(false); 110 final WebSettings settings = mWebView.getSettings(); 111 112 settings.setJavaScriptEnabled(false); 113 settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); 114 115 ConversationViewUtils.setTextZoom(mCallbacks.getFragment().getResources(), settings); 116 117 settings.setSupportZoom(true); 118 settings.setBuiltInZoomControls(true); 119 settings.setDisplayZoomControls(false); 120 121 mScrollView.setInnerScrollableView(mWebView); 122 123 return rootView; 124 } 125 126 public void onActivityCreated(Bundle savedInstanceState) { 127 mCallbacks.setupConversationHeaderView(mConversationHeaderView); 128 129 final Fragment fragment = mCallbacks.getFragment(); 130 131 mDateBuilder = new FormattedDateBuilder(fragment.getActivity()); 132 mMessageHeaderView.initialize( 133 mCallbacks.getConversationAccountController(), mCallbacks.getAddressCache()); 134 mMessageHeaderView.setContactInfoSource(mCallbacks.getContactInfoSource()); 135 mMessageHeaderView.setCallbacks(this); 136 mMessageHeaderView.setExpandable(false); 137 mMessageHeaderView.setViewOnlyMode(mCallbacks.isViewOnlyMode()); 138 139 mCallbacks.setupMessageHeaderVeiledMatcher(mMessageHeaderView); 140 141 mMessageFooterView.initialize(fragment.getLoaderManager(), fragment.getFragmentManager()); 142 143 mCallbacks.startMessageLoader(); 144 145 mProgressController.showLoadingStatus(mCallbacks.isViewVisibleToUser()); 146 147 final Resources r = mCallbacks.getFragment().getResources(); 148 mSideMarginInWebPx = (int) (r.getDimensionPixelOffset( 149 R.dimen.conversation_message_content_margin_side) / r.getDisplayMetrics().density); 150 } 151 152 /** 153 * Populate the adapter with overlay views (message headers, super-collapsed 154 * blocks, a conversation header), and return an HTML document with spacer 155 * divs inserted for all overlays. 156 */ 157 public void renderMessage(ConversationMessage message) { 158 mMessage = message; 159 160 final boolean alwaysShowImages = mCallbacks.shouldAlwaysShowImages(); 161 mWebView.getSettings().setBlockNetworkImage( 162 !alwaysShowImages && !mMessage.alwaysShowImages); 163 164 // Add formatting to message body 165 // At this point, only adds margins. 166 StringBuilder dataBuilder = new StringBuilder( 167 String.format(BEGIN_HTML, mSideMarginInWebPx)); 168 dataBuilder.append(mMessage.getBodyAsHtml()); 169 dataBuilder.append(END_HTML); 170 171 mWebView.loadDataWithBaseURL(mCallbacks.getBaseUri(), dataBuilder.toString(), 172 "text/html", "utf-8", null); 173 final MessageHeaderItem item = ConversationViewAdapter.newMessageHeaderItem( 174 null, mDateBuilder, mMessage, true, mMessage.alwaysShowImages); 175 // Clear out the old info from the header before (re)binding 176 mMessageHeaderView.unbind(); 177 mMessageHeaderView.bind(item, false); 178 if (mMessage.hasAttachments) { 179 mMessageFooterView.setVisibility(View.VISIBLE); 180 mMessageFooterView.bind(item, mCallbacks.getAccountUri(), false); 181 } 182 } 183 184 public ConversationMessage getMessage() { 185 return mMessage; 186 } 187 188 public ConversationViewHeader getConversationHeaderView() { 189 return mConversationHeaderView; 190 } 191 192 public void dismissLoadingStatus() { 193 mProgressController.dismissLoadingStatus(); 194 } 195 196 public void setSubject(String subject) { 197 mConversationHeaderView.setSubject(subject); 198 } 199 200 public void printMessage() { 201 final Conversation conversation = mMessage.getConversation(); 202 PrintUtils.printMessage(mCallbacks.getFragment().getActivity(), mMessage, 203 conversation != null ? conversation.subject : mMessage.subject, 204 mCallbacks.getAddressCache(), mCallbacks.getBaseUri(), false /* useJavascript */); 205 206 } 207 208 // Start MessageHeaderViewCallbacks implementations 209 210 @Override 211 public void setMessageSpacerHeight(MessageHeaderItem item, int newSpacerHeight) { 212 // Do nothing. 213 } 214 215 @Override 216 public void setMessageExpanded(MessageHeaderItem item, int newSpacerHeight, 217 int topBorderHeight, int bottomBorderHeight) { 218 // Do nothing. 219 } 220 221 @Override 222 public void setMessageDetailsExpanded(MessageHeaderItem i, boolean expanded, int heightBefore) { 223 // Do nothing. 224 } 225 226 @Override 227 public void showExternalResources(final Message msg) { 228 mWebView.getSettings().setBlockNetworkImage(false); 229 } 230 231 @Override 232 public void showExternalResources(final String rawSenderAddress) { 233 mWebView.getSettings().setBlockNetworkImage(false); 234 } 235 236 @Override 237 public boolean supportsMessageTransforms() { 238 return false; 239 } 240 241 @Override 242 public String getMessageTransforms(final Message msg) { 243 return null; 244 } 245 246 @Override 247 public FragmentManager getFragmentManager() { 248 return mCallbacks.getFragment().getFragmentManager(); 249 } 250 251 // End MessageHeaderViewCallbacks implementations 252} 253