SecureConversationViewController.java revision 562c5ba7235948cf1d20a9afa40e67cd62f43cf7
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.getContext(), 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