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