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