Share progress logic between secure and regular conversation view.

Fixes part of b/6383847 Implement secure/sanitized conversation view for unsanitized message content from IMAP and POP server

Change-Id: Ia2ba1185997c46952221f4ee7a57f3f198a749de
diff --git a/res/layout/conversation_load_spinner.xml b/res/layout/conversation_load_spinner.xml
new file mode 100644
index 0000000..0e19b2f
--- /dev/null
+++ b/res/layout/conversation_load_spinner.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012 Google Inc.
+     Licensed to The Android Open Source Project.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/background_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center"
+    android:background="@android:color/white"
+    android:visibility="gone">
+    <RelativeLayout
+        android:id="@+id/info_view"
+        android:layout_width="match_parent"
+        android:layout_height="70sp"
+        android:layout_marginLeft="@dimen/info_view_margin"
+        android:layout_marginRight="@dimen/info_view_margin"
+        android:paddingLeft="8dip"
+        android:paddingRight="16dip"
+        android:gravity="center"
+        android:visibility="gone">
+        <ProgressBar
+            android:id="@+id/progress_bar"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="6dip"
+            android:layout_marginRight="8dip"
+            android:indeterminate="true"
+            android:layout_centerVertical="true" />
+        <RelativeLayout
+            android:layout_centerVertical="true"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_toRightOf="@id/progress_bar">
+            <TextView
+                android:id="@+id/senders_view"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:textSize="@dimen/senders_font_size"
+                android:layout_alignParentTop="true"/>
+            <TextView
+                android:id="@+id/info_subject_view"
+                style="@style/SwipeSubjectStyle"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/senders_view"/>
+        </RelativeLayout>
+    </RelativeLayout>
+
+    <com.android.mail.MinTimeProgressView
+        android:id="@+id/loading_progress"
+        style="?android:attr/progressBarStyleLarge"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:indeterminate="true"
+        android:indeterminateBehavior="repeat"
+        android:layout_gravity="center"
+        android:visibility="gone" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/conversation_view.xml b/res/layout/conversation_view.xml
index 6a2efec..9c286d6 100644
--- a/res/layout/conversation_view.xml
+++ b/res/layout/conversation_view.xml
@@ -56,61 +56,5 @@
         </FrameLayout>
 
     </com.android.mail.browse.ConversationContainer>
-    <RelativeLayout
-        android:id="@+id/background_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:gravity="center"
-        android:background="@android:color/white"
-        android:visibility="gone">
-        <RelativeLayout
-            android:id="@+id/info_view"
-            android:layout_width="match_parent"
-            android:layout_height="70sp"
-            android:layout_marginLeft="@dimen/info_view_margin"
-            android:layout_marginRight="@dimen/info_view_margin"
-            android:paddingLeft="8dip"
-            android:paddingRight="16dip"
-            android:gravity="center"
-            android:visibility="gone">
-            <ProgressBar
-                android:id="@+id/progress_bar"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="6dip"
-                android:layout_marginRight="8dip"
-                android:indeterminate="true"
-                android:layout_centerVertical="true" />
-            <RelativeLayout
-                android:layout_centerVertical="true"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_toRightOf="@id/progress_bar">
-                <TextView
-                    android:id="@+id/senders_view"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:singleLine="true"
-                    android:textSize="@dimen/senders_font_size"
-                    android:layout_alignParentTop="true"/>
-                <TextView
-                    android:id="@+id/info_subject_view"
-                    style="@style/SwipeSubjectStyle"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_below="@id/senders_view"/>
-            </RelativeLayout>
-        </RelativeLayout>
-
-        <com.android.mail.MinTimeProgressView
-            android:id="@+id/loading_progress"
-            style="?android:attr/progressBarStyleLarge"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:indeterminate="true"
-            android:indeterminateBehavior="repeat"
-            android:layout_gravity="center"
-            android:visibility="gone" />
-
-    </RelativeLayout>
+    <include layout="@layout/conversation_load_spinner"/>
 </FrameLayout>
diff --git a/res/layout/secure_conversation_view.xml b/res/layout/secure_conversation_view.xml
index 3fa0702..8f0f75c 100644
--- a/res/layout/secure_conversation_view.xml
+++ b/res/layout/secure_conversation_view.xml
@@ -49,15 +49,6 @@
             <!-- TODO: scroll indicators go HERE on top of all other layers -->
         </FrameLayout>
     </RelativeLayout>
-
-    <com.android.mail.MinTimeProgressView
-        android:id="@+id/loading_progress"
-        style="?android:attr/progressBarStyleLarge"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:indeterminate="true"
-        android:indeterminateBehavior="repeat"
-        android:layout_gravity="center"
-        android:visibility="gone" />
+    <include layout="@layout/conversation_load_spinner"/>
 
 </FrameLayout>
diff --git a/src/com/android/mail/browse/SecureConversationViewFragment.java b/src/com/android/mail/browse/SecureConversationViewFragment.java
index 46b0677..9405890 100644
--- a/src/com/android/mail/browse/SecureConversationViewFragment.java
+++ b/src/com/android/mail/browse/SecureConversationViewFragment.java
@@ -28,6 +28,7 @@
 import android.webkit.WebSettings;
 import android.webkit.WebSettings.LayoutAlgorithm;
 import android.webkit.WebView;
+import android.webkit.WebViewClient;
 
 import com.android.mail.R;
 import com.android.mail.browse.ConversationViewAdapter.MessageHeaderItem;
@@ -53,6 +54,12 @@
     private ConversationViewHeader mConversationHeaderView;
     private MessageHeaderView mMessageHeaderView;
     private ConversationMessage mMessage;
+    private WebViewClient mWebViewClient = new WebViewClient() {
+        @Override
+        public void onPageFinished(WebView view, String url) {
+            dismissLoadingStatus();
+        }
+    };
 
     /**
      * Creates a new instance of {@link ConversationViewFragment}, initialized
@@ -92,6 +99,7 @@
         mMessageHeaderView.setCallbacks(this);
         mMessageHeaderView.setExpandable(false);
         getLoaderManager().initLoader(MESSAGE_LOADER, null, getMessageLoaderCallbacks());
+        showLoadingStatus();
     }
 
     @Override
@@ -100,7 +108,9 @@
         View rootView = inflater.inflate(R.layout.secure_conversation_view, container, false);
         mConversationHeaderView = (ConversationViewHeader) rootView.findViewById(R.id.conv_header);
         mMessageHeaderView = (MessageHeaderView) rootView.findViewById(R.id.message_header);
+        instantiateProgressIndicators(rootView);
         mWebView = (WebView) rootView.findViewById(R.id.webview);
+        mWebView.setWebViewClient(mWebViewClient);
         final WebSettings settings = mWebView.getSettings();
 
         settings.setJavaScriptEnabled(false);
diff --git a/src/com/android/mail/ui/AbstractConversationViewFragment.java b/src/com/android/mail/ui/AbstractConversationViewFragment.java
index 9a97fdd..6a2c85d 100644
--- a/src/com/android/mail/ui/AbstractConversationViewFragment.java
+++ b/src/com/android/mail/ui/AbstractConversationViewFragment.java
@@ -17,20 +17,32 @@
 
 package com.android.mail.ui;
 
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.Animator.AnimatorListener;
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.LoaderManager;
 import android.content.Context;
 import android.content.CursorLoader;
 import android.content.Loader;
+import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.DataSetObservable;
 import android.database.DataSetObserver;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+import android.text.style.ForegroundColorSpan;
+import android.util.AttributeSet;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
 
 import com.android.mail.ContactInfo;
 import com.android.mail.ContactInfoSource;
@@ -70,6 +82,9 @@
     private static final String LOG_TAG = LogTag.getLogTag();
     protected static final int MESSAGE_LOADER = 0;
     protected static final int CONTACT_LOADER = 1;
+    private static int sSubjectColor = Integer.MIN_VALUE;
+    private static int sSnippetColor = Integer.MIN_VALUE;
+    private static long sMinDelay = -1;
     protected ControllableActivity mActivity;
     private final MessageLoaderCallbacks mMessageLoaderCallbacks = new MessageLoaderCallbacks();
     protected FormattedDateBuilder mDateBuilder;
@@ -84,6 +99,26 @@
     private MessageCursor mCursor;
     private Context mContext;
     public boolean mUserVisible;
+    private View mProgressView;
+    private View mBackgroundView;
+    private View mInfoView;
+    private final Handler mHandler = new Handler();
+    private Runnable mDelayedShow = new Runnable() {
+        @Override
+        public void run() {
+            mBackgroundView.setVisibility(View.VISIBLE);
+            String senders = mConversation.getSenders(getContext());
+            if (!TextUtils.isEmpty(senders) && mConversation.subject != null) {
+                mInfoView.setVisibility(View.VISIBLE);
+                mSendersView.setText(senders);
+                mSubjectView.setText(createSubjectSnippet(mConversation.subject,
+                        mConversation.getSnippet()));
+            } else {
+                mProgressView.setVisibility(View.VISIBLE);
+            }
+        }
+    };
+
     private final AccountObserver mAccountObserver = new AccountObserver() {
         @Override
         public void onChanged(Account newAccount) {
@@ -91,6 +126,8 @@
             onAccountChanged();
         }
     };
+    private TextView mSendersView;
+    private TextView mSubjectView;
 
     public static Bundle makeBasicArgs(Account account, Folder folder) {
         Bundle args = new Bundle();
@@ -158,6 +195,57 @@
         setHasOptionsMenu(true);
     }
 
+    public void instantiateProgressIndicators(View rootView) {
+        mSendersView = (TextView) rootView.findViewById(R.id.senders_view);
+        mSubjectView = (TextView) rootView.findViewById(R.id.info_subject_view);
+        mBackgroundView = rootView.findViewById(R.id.background_view);
+        mInfoView = rootView.findViewById(R.id.info_view);
+        mProgressView = rootView.findViewById(R.id.loading_progress);
+    }
+
+    protected void dismissLoadingStatus() {
+        if (mBackgroundView.getVisibility() != View.VISIBLE) {
+            // The runnable hasn't run yet, so just remove it.
+            mHandler.removeCallbacks(mDelayedShow);
+            return;
+        }
+        // Fade out the info view.
+        if (mBackgroundView.getVisibility() == View.VISIBLE) {
+            Animator animator = AnimatorInflater.loadAnimator(getContext(), R.anim.fade_out);
+            animator.setTarget(mBackgroundView);
+            animator.addListener(new AnimatorListener() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    if (mProgressView.getVisibility() != View.VISIBLE) {
+                        mProgressView.setVisibility(View.GONE);
+                    }
+                }
+
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mBackgroundView.setVisibility(View.GONE);
+                    mInfoView.setVisibility(View.GONE);
+                    mProgressView.setVisibility(View.GONE);
+                }
+
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    // Do nothing.
+                }
+
+                @Override
+                public void onAnimationRepeat(Animator animation) {
+                    // Do nothing.
+                }
+            });
+            animator.start();
+        } else {
+            mBackgroundView.setVisibility(View.GONE);
+            mInfoView.setVisibility(View.GONE);
+            mProgressView.setVisibility(View.GONE);
+        }
+    }
+
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
@@ -182,6 +270,49 @@
         return activity != null ? activity.getConversationUpdater() : null;
     }
 
+
+    protected void showLoadingStatus() {
+        if (sMinDelay == -1) {
+            sMinDelay = getContext().getResources()
+                    .getInteger(R.integer.conversationview_show_loading_delay);
+        }
+        // In case there were any other instances around, get rid of them.
+        mHandler.removeCallbacks(mDelayedShow);
+        mHandler.postDelayed(mDelayedShow, sMinDelay);
+    }
+
+    private CharSequence createSubjectSnippet(CharSequence subject, CharSequence snippet) {
+        if (TextUtils.isEmpty(subject) && TextUtils.isEmpty(snippet)) {
+            return "";
+        }
+        if (subject == null) {
+            subject = "";
+        }
+        if (snippet == null) {
+            snippet = "";
+        }
+        SpannableStringBuilder subjectText = new SpannableStringBuilder(getContext().getString(
+                R.string.subject_and_snippet, subject, snippet));
+        ensureSubjectSnippetColors();
+        int snippetStart = 0;
+        int fontColor = sSubjectColor;
+        subjectText.setSpan(new ForegroundColorSpan(fontColor), 0, subject.length(),
+                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        snippetStart = subject.length() + 1;
+        fontColor = sSnippetColor;
+        subjectText.setSpan(new ForegroundColorSpan(fontColor), snippetStart, subjectText.length(),
+                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        return subjectText;
+    }
+
+    private void ensureSubjectSnippetColors() {
+        if (sSubjectColor == Integer.MIN_VALUE) {
+            Resources res = getContext().getResources();
+            sSubjectColor = res.getColor(R.color.subject_text_color_read);
+            sSnippetColor = res.getColor(R.color.snippet_text_color_read);
+        }
+    }
+
     public Context getContext() {
         return mContext;
     }
@@ -195,6 +326,10 @@
         return mCursor;
     }
 
+    public Handler getHandler() {
+        return mHandler;
+    }
+
     public MessageLoaderCallbacks getMessageLoaderCallbacks() {
         return mMessageLoaderCallbacks;
     }
diff --git a/src/com/android/mail/ui/ConversationViewFragment.java b/src/com/android/mail/ui/ConversationViewFragment.java
index 2a5d1fb..fe24ef0 100644
--- a/src/com/android/mail/ui/ConversationViewFragment.java
+++ b/src/com/android/mail/ui/ConversationViewFragment.java
@@ -17,28 +17,20 @@
 
 package com.android.mail.ui;
 
-import android.animation.Animator;
-import android.animation.AnimatorInflater;
-import android.animation.Animator.AnimatorListener;
 import android.app.Activity;
 
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.content.Loader;
-import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.DataSetObserver;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.SystemClock;
 import android.provider.Browser;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
-import android.text.style.ForegroundColorSpan;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -114,20 +106,8 @@
 
     private View mNewMessageBar;
 
-    private View mBackgroundView;
-
-    private View mInfoView;
-
-    private TextView mSendersView;
-
-    private TextView mSubjectView;
-
-    private View mProgressView;
-
     private HtmlConversationTemplates mTemplates;
 
-    private final Handler mHandler = new Handler();
-
     private final MailJsBridge mJsBridge = new MailJsBridge();
 
     private final WebViewClient mWebViewClient = new ConversationWebViewClient();
@@ -162,28 +142,10 @@
     private ConversationViewState mViewState;
 
     private boolean mEnableContentReadySignal;
-    private Runnable mDelayedShow = new Runnable() {
-        @Override
-        public void run() {
-            mBackgroundView.setVisibility(View.VISIBLE);
-            String senders = mConversation.getSenders(getContext());
-            if (!TextUtils.isEmpty(senders) && mConversation.subject != null) {
-                mInfoView.setVisibility(View.VISIBLE);
-                mSendersView.setText(senders);
-                mSubjectView.setText(createSubjectSnippet(mConversation.subject,
-                        mConversation.getSnippet()));
-            } else {
-                mProgressView.setVisibility(View.VISIBLE);
-            }
-        }
-    };
 
     private ContentSizeChangeListener mWebViewSizeChangeListener;
 
     private static final String BUNDLE_VIEW_STATE = "viewstate";
-    private static int sSubjectColor = Integer.MIN_VALUE;
-    private static int sSnippetColor = Integer.MIN_VALUE;
-    private static long sMinDelay = -1;
 
     private static final boolean DEBUG_DUMP_CONVERSATION_HTML = false;
     private static final boolean DISABLE_OFFSCREEN_LOADING = false;
@@ -253,38 +215,6 @@
         }
     }
 
-    private CharSequence createSubjectSnippet(CharSequence subject, CharSequence snippet) {
-        if (TextUtils.isEmpty(subject) && TextUtils.isEmpty(snippet)) {
-            return "";
-        }
-        if (subject == null) {
-            subject = "";
-        }
-        if (snippet == null) {
-            snippet = "";
-        }
-        SpannableStringBuilder subjectText = new SpannableStringBuilder(getContext().getString(
-                R.string.subject_and_snippet, subject, snippet));
-        ensureSubjectSnippetColors();
-        int snippetStart = 0;
-        int fontColor = sSubjectColor;
-        subjectText.setSpan(new ForegroundColorSpan(fontColor), 0, subject.length(),
-                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-        snippetStart = subject.length() + 1;
-        fontColor = sSnippetColor;
-        subjectText.setSpan(new ForegroundColorSpan(fontColor), snippetStart, subjectText.length(),
-                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-        return subjectText;
-    }
-
-    private void ensureSubjectSnippetColors() {
-        if (sSubjectColor == Integer.MIN_VALUE) {
-            Resources res = getContext().getResources();
-            sSubjectColor = res.getColor(R.color.subject_text_color_read);
-            sSnippetColor = res.getColor(R.color.snippet_text_color_read);
-        }
-    }
-
     @Override
     public View onCreateView(LayoutInflater inflater,
             ViewGroup container, Bundle savedInstanceState) {
@@ -307,11 +237,7 @@
             }
         });
 
-        mBackgroundView = rootView.findViewById(R.id.background_view);
-        mInfoView = rootView.findViewById(R.id.info_view);
-        mSendersView = (TextView) rootView.findViewById(R.id.senders_view);
-        mSubjectView = (TextView) rootView.findViewById(R.id.info_subject_view);
-        mProgressView = rootView.findViewById(R.id.loading_progress);
+        instantiateProgressIndicators(rootView);
 
         mWebView = (ConversationWebView) mConversationContainer.findViewById(R.id.webview);
 
@@ -950,59 +876,6 @@
         mActivity.onConversationLoadError();
     }
 
-    private void showLoadingStatus() {
-        if (sMinDelay == -1) {
-            sMinDelay = getContext().getResources()
-                    .getInteger(R.integer.conversationview_show_loading_delay);
-        }
-        // In case there were any other instances around, get rid of them.
-        mHandler.removeCallbacks(mDelayedShow);
-        mHandler.postDelayed(mDelayedShow, sMinDelay);
-    }
-
-    private void dismissLoadingStatus() {
-        if (mBackgroundView.getVisibility() != View.VISIBLE) {
-            // The runnable hasn't run yet, so just remove it.
-            mHandler.removeCallbacks(mDelayedShow);
-            return;
-        }
-        // Fade out the info view.
-        if (mBackgroundView.getVisibility() == View.VISIBLE) {
-            Animator animator = AnimatorInflater.loadAnimator(getContext(), R.anim.fade_out);
-            animator.setTarget(mBackgroundView);
-            animator.addListener(new AnimatorListener() {
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    if (mProgressView.getVisibility() != View.VISIBLE) {
-                        mProgressView.setVisibility(View.GONE);
-                    }
-                }
-
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mBackgroundView.setVisibility(View.GONE);
-                    mInfoView.setVisibility(View.GONE);
-                    mProgressView.setVisibility(View.GONE);
-                }
-
-                @Override
-                public void onAnimationCancel(Animator animation) {
-                    // Do nothing.
-                }
-
-                @Override
-                public void onAnimationRepeat(Animator animation) {
-                    // Do nothing.
-                }
-            });
-            animator.start();
-        } else {
-            mBackgroundView.setVisibility(View.GONE);
-            mInfoView.setVisibility(View.GONE);
-            mProgressView.setVisibility(View.GONE);
-        }
-    }
-
     /**
      * NOTE: all public methods must be listed in the proguard flags so that they can be accessed
      * via reflection and not stripped.
@@ -1014,7 +887,7 @@
         @JavascriptInterface
         public void onWebContentGeometryChange(final String[] overlayBottomStrs) {
             try {
-                mHandler.post(new Runnable() {
+                getHandler().post(new Runnable() {
                     @Override
                     public void run() {
                         if (!mViewsCreated) {
@@ -1058,7 +931,7 @@
         public void onContentReady() {
             final Conversation conv = mConversation;
             try {
-                mHandler.post(new Runnable() {
+                getHandler().post(new Runnable() {
                     @Override
                     public void run() {
                         LogUtils.d(LOG_TAG, "ANIMATION STARTED, ready to draw. t=%s",