• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 package com.android.mail.browse;
19 
20 import android.content.AsyncTaskLoader;
21 import android.content.ContentResolver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.net.Uri;
25 
26 import com.android.emailcommon.TempDirectory;
27 import com.android.emailcommon.internet.MimeMessage;
28 import com.android.emailcommon.mail.MessagingException;
29 import com.android.mail.utils.LogTag;
30 import com.android.mail.utils.LogUtils;
31 
32 import java.io.File;
33 import java.io.FileNotFoundException;
34 import java.io.IOException;
35 import java.io.InputStream;
36 
37 /**
38  * Loader that builds a ConversationMessage from an EML file Uri.
39  */
40 public class EmlMessageLoader extends AsyncTaskLoader<ConversationMessage> {
41     private static final String LOG_TAG = LogTag.getLogTag();
42 
43     private Uri mEmlFileUri;
44     private ConversationMessage mMessage;
45 
EmlMessageLoader(Context context, Uri emlFileUri)46     public EmlMessageLoader(Context context, Uri emlFileUri) {
47         super(context);
48         mEmlFileUri = emlFileUri;
49     }
50 
51     @Override
loadInBackground()52     public ConversationMessage loadInBackground() {
53         final Context context = getContext();
54         TempDirectory.setTempDirectory(context);
55         final ContentResolver resolver = context.getContentResolver();
56         final InputStream stream;
57         try {
58             stream = resolver.openInputStream(mEmlFileUri);
59         } catch (FileNotFoundException e) {
60             LogUtils.e(LOG_TAG, e, "Could not find eml file at uri: %s", mEmlFileUri);
61             return null;
62         }
63 
64         final MimeMessage mimeMessage;
65         final ConversationMessage convMessage;
66         try {
67             mimeMessage = new MimeMessage(stream);
68             convMessage = new ConversationMessage(context, mimeMessage, mEmlFileUri);
69         } catch (IOException e) {
70             LogUtils.e(LOG_TAG, e, "Could not read eml file");
71             return null;
72         } catch (MessagingException e) {
73             LogUtils.e(LOG_TAG, e, "Error in parsing eml file");
74             return null;
75         } finally {
76             try {
77                 stream.close();
78             } catch (IOException e) {
79                 return null;
80             }
81 
82             // delete temp files created during parsing
83             final File[] cacheFiles = TempDirectory.getTempDirectory().listFiles();
84             for (final File file : cacheFiles) {
85                 if (file.getName().startsWith("body")) {
86                     file.delete();
87                 }
88             }
89 
90         }
91 
92         return convMessage;
93     }
94 
95     /**
96      * Called when there is new data to deliver to the client.  The
97      * super class will take care of delivering it; the implementation
98      * here just adds a little more logic.
99      */
100     @Override
deliverResult(ConversationMessage result)101     public void deliverResult(ConversationMessage result) {
102         if (isReset()) {
103             // An async query came in while the loader is stopped.  We
104             // don't need the result.
105             if (result != null) {
106                 onReleaseResources(result);
107             }
108             return;
109         }
110         ConversationMessage oldMessage = mMessage;
111         mMessage = result;
112 
113         if (isStarted()) {
114             // If the Loader is currently started, we can immediately
115             // deliver its results.
116             super.deliverResult(result);
117         }
118 
119         // At this point we can release the resources associated with
120         // 'oldMessage' if needed; now that the new result is delivered we
121         // know that it is no longer in use.
122         if (oldMessage != null && oldMessage != mMessage) {
123             onReleaseResources(oldMessage);
124         }
125     }
126 
127     /**
128      * Handles a request to start the Loader.
129      */
130     @Override
onStartLoading()131     protected void onStartLoading() {
132         if (mMessage != null) {
133             // If we currently have a result available, deliver it immediately.
134             deliverResult(mMessage);
135         }
136 
137         if (takeContentChanged() || mMessage == null) {
138             // If the data has changed since the last time it was loaded
139             // or is not currently available, start a load.
140             forceLoad();
141         }
142     }
143 
144     /**
145      * Handles a request to stop the Loader.
146      */
onStopLoading()147     @Override protected void onStopLoading() {
148         // Attempt to cancel the current load task if possible.
149         cancelLoad();
150     }
151 
152     /**
153      * Handles a request to cancel a load.
154      */
155     @Override
onCanceled(ConversationMessage result)156     public void onCanceled(ConversationMessage result) {
157         super.onCanceled(result);
158 
159         // At this point we can release the resources associated with
160         // the message, if needed.
161         if (result != null) {
162             onReleaseResources(result);
163         }
164     }
165 
166     /**
167      * Handles a request to completely reset the Loader.
168      */
169     @Override
onReset()170     protected void onReset() {
171         super.onReset();
172 
173         // Ensure the loader is stopped
174         onStopLoading();
175 
176         // At this point we can release the resources associated with
177         // the message, if needed.
178         if (mMessage != null) {
179             onReleaseResources(mMessage);
180             mMessage = null;
181         }
182     }
183 
184 
185     /**
186      * Helper function to take care of releasing resources associated
187      * with an actively loaded data set.
188      */
onReleaseResources(ConversationMessage message)189     protected void onReleaseResources(ConversationMessage message) {
190         // if this eml message had attachments, start a service to clean up the cache files
191         if (message.attachmentListUri != null) {
192             final Intent intent = new Intent(Intent.ACTION_DELETE);
193             intent.setClass(getContext(), EmlTempFileDeletionService.class);
194             intent.setData(message.attachmentListUri);
195 
196             getContext().startService(intent);
197         }
198     }
199 }
200