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