Final eml viewer cleanup.

Fixes b/9560839. Now we show the title of
the eml file and we also show an overflow
button with settings/send feedback/help.

Change-Id: I5eab245d9fd47e37b83eadcb419255939117ab39
diff --git a/res/menu/eml_viewer_menu.xml b/res/menu/eml_viewer_menu.xml
new file mode 100644
index 0000000..662d95c
--- /dev/null
+++ b/res/menu/eml_viewer_menu.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2013 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- Always available -->
+    <item android:id="@+id/settings"
+          android:title="@string/menu_settings"
+          android:showAsAction="never" />
+
+    <!-- Always available -->
+    <item
+            android:id="@+id/feedback_menu_item"
+            android:icon="@android:drawable/ic_menu_send"
+            android:showAsAction="never"
+            android:title="@string/feedback" />
+
+    <!-- Available if the account specifies a help url -->
+    <item
+            android:id="@+id/help_info_menu_item"
+            android:icon="@android:drawable/ic_menu_help"
+            android:showAsAction="never"
+            android:title="@string/help_and_info" />
+</menu>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 09e554b..10c91e7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -947,4 +947,7 @@
 
     <!-- Content Provider Authority for Eml Attachments -->
     <string name="eml_attachment_provider" translatable="false">com.android.mail.provider.eml.attachment</string>
+
+    <!-- Action bar title for viewing messages that are attached to another message. -->
+    <string name="attached_message">Attached message</string>
 </resources>
diff --git a/src/com/android/mail/browse/ConversationViewAdapter.java b/src/com/android/mail/browse/ConversationViewAdapter.java
index 89ccb09..9f278ab 100644
--- a/src/com/android/mail/browse/ConversationViewAdapter.java
+++ b/src/com/android/mail/browse/ConversationViewAdapter.java
@@ -250,7 +250,7 @@
         @Override
         public void bindView(View v, boolean measureOnly) {
             final MessageFooterView attachmentsView = (MessageFooterView) v;
-            attachmentsView.bind(headerItem, measureOnly);
+            attachmentsView.bind(headerItem, mAccountController.getAccount().uri, measureOnly);
         }
 
         @Override
diff --git a/src/com/android/mail/browse/EmlMessageViewFragment.java b/src/com/android/mail/browse/EmlMessageViewFragment.java
index 13a3e54..79a42b4 100644
--- a/src/com/android/mail/browse/EmlMessageViewFragment.java
+++ b/src/com/android/mail/browse/EmlMessageViewFragment.java
@@ -19,17 +19,22 @@
 
 import android.app.Fragment;
 import android.app.LoaderManager;
+import android.content.CursorLoader;
 import android.content.Loader;
+import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.provider.OpenableColumns;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.webkit.WebView;
 
+import com.android.mail.R;
 import com.android.mail.providers.Account;
 import com.android.mail.providers.Address;
+import com.android.mail.providers.UIProvider;
 import com.android.mail.ui.AbstractConversationWebViewClient;
 import com.android.mail.ui.ContactLoaderCallbacks;
 import com.android.mail.ui.SecureConversationViewController;
@@ -49,12 +54,14 @@
  * of the rendering work.
  */
 public class EmlMessageViewFragment extends Fragment
-        implements SecureConversationViewControllerCallbacks,
-        LoaderManager.LoaderCallbacks<ConversationMessage> {
+        implements SecureConversationViewControllerCallbacks {
     private static final String ARG_EML_FILE_URI = "eml_file_uri";
+    private static final String ARG_ACCOUNT_URI = "account_uri";
     private static final String BASE_URI = "x-thread://message/rfc822/";
+
     private static final int MESSAGE_LOADER = 0;
     private static final int CONTACT_LOADER = 1;
+    private static final int FILENAME_LOADER = 2;
 
     private final Handler mHandler = new Handler();
 
@@ -62,7 +69,11 @@
     private SecureConversationViewController mViewController;
     private ContactLoaderCallbacks mContactLoaderCallbacks;
 
+    private final MessageLoadCallbacks mMessageLoadCallbacks = new MessageLoadCallbacks();
+    private final FilenameLoadCallbacks mFilenameLoadCallbacks = new FilenameLoadCallbacks();
+
     private Uri mEmlFileUri;
+    private Uri mAccountUri;
 
     /**
      * Cache of email address strings to parsed Address objects.
@@ -100,10 +111,11 @@
      * Creates a new instance of {@link EmlMessageViewFragment},
      * initialized to display an eml file from the specified {@link Uri}.
      */
-    public static EmlMessageViewFragment newInstance(Uri emlFileUri) {
+    public static EmlMessageViewFragment newInstance(Uri emlFileUri, Uri accountUri) {
         EmlMessageViewFragment f = new EmlMessageViewFragment();
         Bundle args = new Bundle();
         args.putParcelable(ARG_EML_FILE_URI, emlFileUri);
+        args.putParcelable(ARG_ACCOUNT_URI, accountUri);
         f.setArguments(args);
         return f;
     }
@@ -122,9 +134,12 @@
 
         Bundle args = getArguments();
         mEmlFileUri = args.getParcelable(ARG_EML_FILE_URI);
+        mAccountUri = args.getParcelable(ARG_ACCOUNT_URI);
 
         mWebViewClient = new EmlWebViewClient(null);
         mViewController = new SecureConversationViewController(this);
+
+        getActivity().getActionBar().setTitle(R.string.attached_message);
     }
 
     @Override
@@ -192,7 +207,9 @@
 
     @Override
     public void startMessageLoader() {
-        getLoaderManager().initLoader(MESSAGE_LOADER, null, this);
+        final LoaderManager manager = getLoaderManager();
+        manager.initLoader(MESSAGE_LOADER, null, mMessageLoadCallbacks);
+        manager.initLoader(FILENAME_LOADER, null, mFilenameLoadCallbacks);
     }
 
     @Override
@@ -205,30 +222,59 @@
         return true;
     }
 
+    @Override
+    public Uri getAccountUri() {
+        return mAccountUri;
+    }
+
     // End SecureConversationViewControllerCallbacks
 
-    // Start LoaderCallbacks
+    private class MessageLoadCallbacks
+            implements LoaderManager.LoaderCallbacks<ConversationMessage> {
+        @Override
+        public Loader<ConversationMessage> onCreateLoader(int id, Bundle args) {
+            switch (id) {
+                case MESSAGE_LOADER:
+                    return new EmlMessageLoader(getActivity(), mEmlFileUri);
+                default:
+                    return null;
+            }
+        }
 
-    @Override
-    public Loader<ConversationMessage> onCreateLoader(int id, Bundle args) {
-        switch (id) {
-            case MESSAGE_LOADER:
-                return new EmlMessageLoader(getActivity(), mEmlFileUri);
-            default:
-                return null;
+        @Override
+        public void onLoadFinished(Loader<ConversationMessage> loader, ConversationMessage data) {
+            mViewController.setSubject(data.subject);
+            mViewController.renderMessage(data);
+        }
+
+        @Override
+        public void onLoaderReset(Loader<ConversationMessage> loader) {
+            // Do nothing
         }
     }
 
-    @Override
-    public void onLoadFinished(Loader<ConversationMessage> loader, ConversationMessage data) {
-        mViewController.setSubject(data.subject);
-        mViewController.renderMessage(data);
+    private class FilenameLoadCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
+        @Override
+        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+            switch (id) {
+                case FILENAME_LOADER:
+                    return new CursorLoader(getActivity(), mEmlFileUri,
+                            UIProvider.ATTACHMENT_PROJECTION, null, null, null);
+                default:
+                    return null;
+            }
+        }
+
+        @Override
+        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+            data.moveToFirst();
+            getActivity().getActionBar().setSubtitle(
+                    data.getString(data.getColumnIndex(OpenableColumns.DISPLAY_NAME)));
+        }
+
+        @Override
+        public void onLoaderReset(Loader<Cursor> loader) {
+        }
     }
 
-    @Override
-    public void onLoaderReset(Loader<ConversationMessage> loader) {
-        // Do nothing
-    }
-
-    // End LoaderCallbacks
 }
diff --git a/src/com/android/mail/browse/EmlViewerActivity.java b/src/com/android/mail/browse/EmlViewerActivity.java
index 2524b0f..3deb87c 100644
--- a/src/com/android/mail/browse/EmlViewerActivity.java
+++ b/src/com/android/mail/browse/EmlViewerActivity.java
@@ -19,22 +19,47 @@
 
 import android.app.ActionBar;
 import android.app.Activity;
-import android.app.FragmentManager;
 import android.app.FragmentTransaction;
+import android.app.LoaderManager;
+import android.content.Context;
 import android.content.Intent;
+import android.content.Loader;
+import android.net.Uri;
 import android.os.Bundle;
+import android.view.Menu;
 import android.view.MenuItem;
 
 import com.android.mail.R;
+import com.android.mail.content.CursorCreator;
+import com.android.mail.content.ObjectCursor;
+import com.android.mail.content.ObjectCursorLoader;
+import com.android.mail.providers.Account;
+import com.android.mail.providers.UIProvider;
+import com.android.mail.ui.FeedbackEnabledActivity;
 import com.android.mail.utils.LogTag;
 import com.android.mail.utils.LogUtils;
 import com.android.mail.utils.MimeType;
+import com.android.mail.utils.Utils;
 
-public class EmlViewerActivity extends Activity {
+public class EmlViewerActivity extends Activity implements FeedbackEnabledActivity {
+    public static final String EXTRA_ACCOUNT_URI = "extra-account-uri";
+
     private static final String LOG_TAG = LogTag.getLogTag();
 
     private static final String FRAGMENT_TAG = "eml_message_fragment";
 
+    private static final int ACCOUNT_LOADER = 0;
+
+    private static final String SAVED_ACCOUNT = "saved-account";
+
+    private MenuItem mHelpItem;
+    private MenuItem mSendFeedbackItem;
+
+    private Uri mAccountUri;
+    private Account mAccount;
+
+    private final AccountLoadCallbacks mAccountLoadCallbacks = new AccountLoadCallbacks();
+
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.eml_viewer_activity);
@@ -45,26 +70,53 @@
         final Intent intent = getIntent();
         final String action = intent.getAction();
         final String type = intent.getType();
+        mAccountUri = intent.getParcelableExtra(EXTRA_ACCOUNT_URI);
 
-        if (Intent.ACTION_VIEW.equals(action) &&
-                MimeType.isEmlMimeType(type)) {
-            final FragmentManager manager = getFragmentManager();
-
-            if (manager.findFragmentByTag(FRAGMENT_TAG) == null) {
-                final FragmentTransaction transaction = manager.beginTransaction();
-                transaction.add(R.id.eml_root,
-                        EmlMessageViewFragment.newInstance(intent.getData()), FRAGMENT_TAG);
+        if (savedInstanceState == null) {
+            if (Intent.ACTION_VIEW.equals(action) &&
+                    MimeType.isEmlMimeType(type)) {
+                final FragmentTransaction transaction = getFragmentManager().beginTransaction();
+                transaction.add(R.id.eml_root, EmlMessageViewFragment.newInstance(
+                        intent.getData(), mAccountUri), FRAGMENT_TAG);
                 transaction.commit();
+            } else {
+                LogUtils.wtf(LOG_TAG,
+                        "Entered EmlViewerActivity with wrong intent action or type: %s, %s",
+                        action, type);
+                finish(); // we should not be here. bail out. bail out.
+                return;
             }
         } else {
-            LogUtils.wtf(LOG_TAG,
-                    "Entered EmlViewerActivity with wrong intent action or type: %s, %s",
-                    action, type);
-            finish(); // we should not be here. bail out. bail out.
+            if (savedInstanceState.containsKey(SAVED_ACCOUNT)) {
+                mAccount = savedInstanceState.getParcelable(SAVED_ACCOUNT);
+            }
         }
+
+        getLoaderManager().initLoader(ACCOUNT_LOADER, Bundle.EMPTY, mAccountLoadCallbacks);
     }
 
 
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.eml_viewer_menu, menu);
+        mHelpItem = menu.findItem(R.id.help_info_menu_item);
+        mSendFeedbackItem = menu.findItem(R.id.feedback_menu_item);
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        if (mHelpItem != null) {
+            mHelpItem.setVisible(mAccount != null
+                    && mAccount.supportsCapability(UIProvider.AccountCapabilities.HELP_CONTENT));
+        }
+        if (mSendFeedbackItem != null) {
+            mSendFeedbackItem.setVisible(mAccount != null
+                    && mAccount.supportsCapability(UIProvider.AccountCapabilities.SEND_FEEDBACK));
+        }
+
+        return true;
+    }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
@@ -72,8 +124,48 @@
             case android.R.id.home:
                 finish();
                 return true;
+            case R.id.settings:
+                Utils.showSettings(this, mAccount);
+                break;
+            case R.id.help_info_menu_item:
+                Utils.showHelp(this, mAccount, getString(R.string.main_help_context));
+                break;
+            case R.id.feedback_menu_item:
+                Utils.sendFeedback(this, mAccount, false);
+                break;
+            default:
+                return super.onOptionsItemSelected(item);
         }
 
-        return super.onOptionsItemSelected(item);
+        return true;
+    }
+
+    @Override
+    public Context getActivityContext() {
+        return this;
+    }
+
+    private class AccountLoadCallbacks
+            implements LoaderManager.LoaderCallbacks<ObjectCursor<Account>> {
+
+        @Override
+        public Loader<ObjectCursor<Account>> onCreateLoader(int id, Bundle args) {
+            final String[] projection = UIProvider.ACCOUNTS_PROJECTION;
+            final CursorCreator<Account> factory = Account.FACTORY;
+            return new ObjectCursorLoader<Account>(
+                    EmlViewerActivity.this, mAccountUri, projection, factory);
+        }
+
+        @Override
+        public void onLoadFinished(Loader<ObjectCursor<Account>> loader,
+                ObjectCursor<Account> data) {
+            if (data != null && data.moveToFirst()) {
+                mAccount = data.getModel();
+            }
+        }
+
+        @Override
+        public void onLoaderReset(Loader<ObjectCursor<Account>> loader) {
+        }
     }
 }
diff --git a/src/com/android/mail/browse/MessageAttachmentBar.java b/src/com/android/mail/browse/MessageAttachmentBar.java
index b1d26cc..ac0221d 100644
--- a/src/com/android/mail/browse/MessageAttachmentBar.java
+++ b/src/com/android/mail/browse/MessageAttachmentBar.java
@@ -22,6 +22,7 @@
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
+import android.net.Uri;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -68,6 +69,7 @@
 
     private final AttachmentActionHandler mActionHandler;
     private boolean mSaveClicked;
+    private Uri mAccountUri;
 
     private final Runnable mUpdateRunnable = new Runnable() {
             @Override
@@ -78,6 +80,7 @@
 
     private static final String LOG_TAG = LogTag.getLogTag();
 
+
     public MessageAttachmentBar(Context context) {
         this(context, null);
     }
@@ -102,9 +105,11 @@
      * Render or update an attachment's view. This happens immediately upon instantiation, and
      * repeatedly as status updates stream in, so only properties with new or changed values will
      * cause sub-views to update.
-     *
      */
-    public void render(Attachment attachment, boolean loaderResult) {
+    public void render(Attachment attachment, Uri accountUri, boolean loaderResult) {
+        // get account uri for potential eml viewer usage
+        mAccountUri = accountUri;
+
         final Attachment prevAttachment = mAttachment;
         mAttachment = attachment;
         mActionHandler.setAttachment(mAttachment);
@@ -293,6 +298,7 @@
         // viewer rather than let any activity open it.
         if (MimeType.isEmlMimeType(contentType)) {
             intent.setClass(getContext(), EmlViewerActivity.class);
+            intent.putExtra(EmlViewerActivity.EXTRA_ACCOUNT_URI, mAccountUri);
         }
 
         try {
diff --git a/src/com/android/mail/browse/MessageFooterView.java b/src/com/android/mail/browse/MessageFooterView.java
index fd29a87..de1b914 100644
--- a/src/com/android/mail/browse/MessageFooterView.java
+++ b/src/com/android/mail/browse/MessageFooterView.java
@@ -63,6 +63,8 @@
 
     private static final String LOG_TAG = LogTag.getLogTag();
 
+    private Uri mAccountUri;
+
     public MessageFooterView(Context context) {
         this(context, null);
     }
@@ -88,7 +90,9 @@
         mFragmentManager = fragmentManager;
     }
 
-    public void bind(MessageHeaderItem headerItem, boolean measureOnly) {
+    public void bind(MessageHeaderItem headerItem, Uri accountUri, boolean measureOnly) {
+        mAccountUri = accountUri;
+
         // Resets the footer view. This step is only done if the
         // attachmentsListUri changes so that we don't
         // repeat the work of layout and measure when
@@ -200,7 +204,7 @@
                 mAttachmentBarList.addView(barAttachmentView);
             }
 
-            barAttachmentView.render(attachment, loaderResult);
+            barAttachmentView.render(attachment, mAccountUri, loaderResult);
         }
     }
 
diff --git a/src/com/android/mail/ui/SecureConversationViewController.java b/src/com/android/mail/ui/SecureConversationViewController.java
index a3e6ec8..f049168 100644
--- a/src/com/android/mail/ui/SecureConversationViewController.java
+++ b/src/com/android/mail/ui/SecureConversationViewController.java
@@ -149,7 +149,7 @@
         mMessageHeaderView.bind(item, false);
         if (mMessage.hasAttachments) {
             mMessageFooterView.setVisibility(View.VISIBLE);
-            mMessageFooterView.bind(item, false);
+            mMessageFooterView.bind(item, mCallbacks.getAccountUri(), false);
         }
     }
 
diff --git a/src/com/android/mail/ui/SecureConversationViewControllerCallbacks.java b/src/com/android/mail/ui/SecureConversationViewControllerCallbacks.java
index 06857ed..2e4f5d9 100644
--- a/src/com/android/mail/ui/SecureConversationViewControllerCallbacks.java
+++ b/src/com/android/mail/ui/SecureConversationViewControllerCallbacks.java
@@ -18,6 +18,7 @@
 package com.android.mail.ui;
 
 import android.app.Fragment;
+import android.net.Uri;
 import android.os.Handler;
 
 import com.android.mail.ContactInfoSource;
@@ -44,4 +45,5 @@
     public void startMessageLoader();
     public String getBaseUri();
     public boolean isViewOnlyMode();
+    public Uri getAccountUri();
 }
diff --git a/src/com/android/mail/ui/SecureConversationViewFragment.java b/src/com/android/mail/ui/SecureConversationViewFragment.java
index c3efd59..91cc398 100644
--- a/src/com/android/mail/ui/SecureConversationViewFragment.java
+++ b/src/com/android/mail/ui/SecureConversationViewFragment.java
@@ -176,6 +176,11 @@
         return false;
     }
 
+    @Override
+    public Uri getAccountUri() {
+        return mAccount.uri;
+    }
+
     // End implementations of SecureConversationViewControllerCallbacks
 
     @Override