blob: d84d3b79cbbd2ace37b02e7c7acc0e30e9475b65 [file] [log] [blame]
luxiaol62677b02013-07-22 07:54:49 +08001/*
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -07002 * Copyright (c) 2013,2014, The Linux Foundation. All rights reserved.
luxiaol62677b02013-07-22 07:54:49 +08003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
Bijan Amirzada41242f22014-03-21 12:12:18 -070030package com.android.browser;
luxiaol62677b02013-07-22 07:54:49 +080031
32import java.io.File;
33
34import android.app.Activity;
35import android.content.Intent;
36import java.lang.Thread;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080037
Bijan Amirzada41242f22014-03-21 12:12:18 -070038import com.android.browser.R;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080039
luxiaol62677b02013-07-22 07:54:49 +080040import android.net.Uri;
41import android.os.Bundle;
kaiyizf1a66762013-09-16 16:59:43 +080042import android.os.Environment;
luxiaol62677b02013-07-22 07:54:49 +080043import android.text.format.*;
44import android.util.Log;
45import android.view.View;
46import android.view.View.OnClickListener;
47import android.widget.Button;
48import android.widget.EditText;
49import android.widget.TextView;
50import android.view.Window;
51import android.widget.Toast;
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -070052import android.webkit.MimeTypeMap;
luxiaol62677b02013-07-22 07:54:49 +080053import android.text.TextUtils;
54
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -070055import com.android.browser.reflect.ReflectHelper;
56
luxiaol62677b02013-07-22 07:54:49 +080057public class DownloadSettings extends Activity {
58
59 private EditText downloadFilenameET;
60 private EditText downloadPathET;
61 private TextView downloadEstimateSize;
62 private TextView downloadEstimateTime;
63 private Button downloadStart;
64 private Button downloadCancel;
65 private String url;
66 private String userAgent;
67 private String contentDisposition;
68 private String mimetype;
69 private String referer;
Pankaj Garg5762b362015-11-02 07:57:06 -080070 private String authorization;
luxiaol62677b02013-07-22 07:54:49 +080071 private String filenameBase;
72 private String filename;
73 private String filenameExtension;
74 private boolean privateBrowsing;
75 private long contentLength;
76 private String downloadPath;
77 private String downloadPathForUser;
78 private static final int downloadRate = (1024 * 100 * 60);// Download Rate
79 // 100KB/s
80 private final static String LOGTAG = "DownloadSettings";
81 private final static int DOWNLOAD_PATH = 0;
82 private boolean isDownloadStarted = false;
83
84 private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET";
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -070085 private static final String APK_TYPE="apk";
86 private static final String OCTET_STREAM = "application/octet-stream";
luxiaol62677b02013-07-22 07:54:49 +080087
88 protected void onCreate(Bundle savedInstanceState) {
89 super.onCreate(savedInstanceState);
90 // initial the DownloadSettings view
91 requestWindowFeature(Window.FEATURE_NO_TITLE);
92 setContentView(R.layout.download_settings);
93 downloadFilenameET = (EditText) findViewById(R.id.download_filename_edit);
94 downloadPathET = (EditText) findViewById(R.id.download_filepath_selected);
95 downloadEstimateSize = (TextView) findViewById(R.id.download_estimate_size_content);
96 downloadEstimateTime = (TextView) findViewById(R.id.download_estimate_time_content);
97 downloadStart = (Button) findViewById(R.id.download_start);
Sagar Dhawan0e0943b2015-08-19 12:23:22 -070098 downloadCancel = (Button) findViewById(R.id.download_cancel);
luxiaol62677b02013-07-22 07:54:49 +080099 downloadPathET.setOnClickListener(downloadPathListener);
100 downloadStart.setOnClickListener(downloadStartListener);
101 downloadCancel.setOnClickListener(downloadCancelListener);
102
103 // get the bundle from Intent
104 Intent intent = getIntent();
105 Bundle fileInfo = intent.getExtras();
106 url = fileInfo.getString("url");
107 userAgent = fileInfo.getString("userAgent");
108 contentDisposition = fileInfo.getString("contentDisposition");
109 mimetype = fileInfo.getString("mimetype");
110 referer = fileInfo.getString("referer");
Pankaj Garg5762b362015-11-02 07:57:06 -0800111 authorization = fileInfo.getString("authorization");
luxiaol62677b02013-07-22 07:54:49 +0800112 contentLength = fileInfo.getLong("contentLength");
113 privateBrowsing = fileInfo.getBoolean("privateBrowsing");
114 filename = fileInfo.getString("filename");
115
116 // download filenamebase's length is depended on filenameLength's values
117 // if filenamebase.length >= flienameLength, destroy the last string!
118
119 filenameBase = DownloadHandler.getFilenameBase(filename);
120 if (filenameBase.length() >= (BrowserUtils.FILENAME_MAX_LENGTH)) {
121 filenameBase = filenameBase.substring(0, BrowserUtils.FILENAME_MAX_LENGTH);
122 }
123
124 // warring when user enter more over letters into the EditText
125 BrowserUtils.maxLengthFilter(DownloadSettings.this, downloadFilenameET,
126 BrowserUtils.FILENAME_MAX_LENGTH);
127
128 downloadFilenameET.setText(filenameBase);
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700129
130 String filenameExtension = DownloadHandler.getFilenameExtension(filename);
131
Axesh R. Ajmera2e241242014-05-19 15:53:38 -0700132 // introspect for octet stream mimetype what type of file extension it has
133 // and reassign mimetype
134 if (mimetype == null || mimetype.isEmpty() || mimetype.equals(OCTET_STREAM)) {
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700135
136 String updatedFileName = filenameBase + "." + filenameExtension;
137 Object[] params = {updatedFileName};
138 Class[] type = new Class[] {String.class};
Bijan Amirzada58383e72014-04-01 14:45:22 -0700139 mimetype = (String) ReflectHelper.invokeMethod("android.media.MediaFile",
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700140 "getMimeTypeForFile", type, params);
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700141 }
142
143 //Add special check for .apk files with octet-stream mimetype
Axesh R. Ajmera77258982014-04-02 14:39:09 -0700144 if (filenameExtension.equals(APK_TYPE) && mimetype != null && mimetype.equals(OCTET_STREAM)) {
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700145 mimetype = "application/vnd.android.package-archive";
146 }
147
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700148 // last way to fetch for mimetype if its still null
149 if (mimetype == null || mimetype.isEmpty())
150 mimetype = MimeTypeMap.getSingleton().getMimeTypeFromExtension(filenameExtension);
151
kaiyizf1a66762013-09-16 16:59:43 +0800152 downloadPath = chooseFolderFromMimeType(BrowserSettings.getInstance().getDownloadPath(),
153 mimetype);
luxiaol62677b02013-07-22 07:54:49 +0800154 downloadPathForUser = DownloadHandler.getDownloadPathForUser(DownloadSettings.this,
155 downloadPath);
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700156
157 autoupdateFileName(filenameBase, DownloadHandler.getFilenameExtension(filename), downloadPath);
luxiaol62677b02013-07-22 07:54:49 +0800158 setDownloadPathForUserText(downloadPathForUser);
159 setDownloadFileSizeText();
160 setDownloadFileTimeText();
luxiaol62677b02013-07-22 07:54:49 +0800161 }
162
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700163 private void autoupdateFileName(String filenameBase, String extension, String downloadPath) {
164 String fullPath = downloadPath + "/" + filenameBase + "." + extension;
165 int count = 1;
166 String newFilenameBase = "";
167
168 while(new File(fullPath).exists()) {
169 newFilenameBase = filenameBase+"-"+count++;
170 fullPath = downloadPath + "/" + newFilenameBase + "." + extension;
171 }
172
173 if(!TextUtils.isEmpty(newFilenameBase)) {
174 filenameBase = newFilenameBase;
175 }
176
177 downloadFilenameET.setText(filenameBase);
178 }
179
luxiaol62677b02013-07-22 07:54:49 +0800180 private OnClickListener downloadPathListener = new OnClickListener() {
181
182 @Override
183 public void onClick(View v) {
184
Vivek Sekharefefe6b2015-01-05 16:01:07 -0800185 final String filemanagerIntent =
186 getResources().getString(R.string.def_intent_file_manager);
187 if (!TextUtils.isEmpty(filemanagerIntent)) {
188 // start filemanager for getting download path
189 try {
190 Intent downloadPathIntent = new Intent(filemanagerIntent);
191 DownloadSettings.this.startActivityForResult(downloadPathIntent, DOWNLOAD_PATH);
192 } catch (Exception e) {
193 String err_msg = getString(R.string.activity_not_found,
194 filemanagerIntent);
195 Toast.makeText(DownloadSettings.this, err_msg, Toast.LENGTH_LONG).show();
196 }
197 } else {
198 Log.e(LOGTAG, "File Manager intent not defined !!");
luxiaol62677b02013-07-22 07:54:49 +0800199 }
200
201 }
202 };
203
204 private OnClickListener downloadStartListener = new OnClickListener() {
205
206 @Override
207 public void onClick(View v) {
208 filenameBase = getFilenameBaseFromUserEnter();
209 // check the filename user enter is null or not
Sagar Dhawan97ed6c92015-07-31 15:36:07 -0700210 if (TextUtils.isEmpty(filenameBase) || TextUtils.isEmpty(downloadPath)) {
luxiaol62677b02013-07-22 07:54:49 +0800211 DownloadHandler.showFilenameEmptyDialog(DownloadSettings.this);
212 return;
213 }
214
215 filenameExtension = DownloadHandler.getFilenameExtension(filename);
216 filename = filenameBase + "." + filenameExtension;
217
218 // check the storage status
219 if (!DownloadHandler.isStorageStatusOK(DownloadSettings.this, filename, downloadPath)) {
220 return;
221 }
222
223 // check the storage memory enough or not
224 try {
225 DownloadHandler.setAppointedFolder(downloadPath);
226 } catch (Exception e) {
227 DownloadHandler.showNoEnoughMemoryDialog(DownloadSettings.this);
228 return;
229 }
kaiyize6a27d02013-08-22 15:08:19 +0800230 boolean isNoEnoughMemory = DownloadHandler.manageNoEnoughMemory(contentLength,
231 downloadPath);
luxiaol62677b02013-07-22 07:54:49 +0800232 if (isNoEnoughMemory) {
kaiyize6a27d02013-08-22 15:08:19 +0800233 DownloadHandler.showNoEnoughMemoryDialog(DownloadSettings.this);
luxiaol62677b02013-07-22 07:54:49 +0800234 return;
235 }
236
237 // check the download file is exist or not
238 String fullFilename = downloadPath + "/" + filename;
239 if (mimetype != null && new File(fullFilename).exists()) {
240 DownloadHandler.fileExistQueryDialog(DownloadSettings.this);
241 return;
242 }
243
244 // staring downloading
245 DownloadHandler.startingDownload(DownloadSettings.this,
246 url, userAgent, contentDisposition,
Pankaj Garg5762b362015-11-02 07:57:06 -0800247 mimetype, referer, authorization, privateBrowsing, contentLength,
luxiaol62677b02013-07-22 07:54:49 +0800248 Uri.encode(filename), downloadPath);
249 isDownloadStarted = true;
250 }
251 };
252
253 private OnClickListener downloadCancelListener = new OnClickListener() {
luxiaol62677b02013-07-22 07:54:49 +0800254 @Override
255 public void onClick(View v) {
256 finish();
257 }
258 };
259
260 protected void onDestroy() {
261 super.onDestroy();
262 }
263
264 protected void onPause() {
265 super.onPause();
266 if (isDownloadStarted) {
267 finish();
268 }
269 }
270
271 protected void onResume() {
272 super.onResume();
273 }
274
275 @Override
276 protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
Vivek Sekharefefe6b2015-01-05 16:01:07 -0800277
luxiaol62677b02013-07-22 07:54:49 +0800278 if (DOWNLOAD_PATH == requestCode) {
Vivek Sekharefefe6b2015-01-05 16:01:07 -0800279 if (resultCode == Activity.RESULT_OK && intent != null) {
280 final String result_dir_sel =
281 getResources().getString(R.string.def_file_manager_result_dir);
282 downloadPath = intent.getStringExtra(result_dir_sel);
Vivek Sekhar76074ac2014-06-27 16:33:13 -0700283 // Fallback logic to stock browser
284 if (downloadPath == null) {
285 Uri uri = intent.getData();
286 if(uri != null)
287 downloadPath = uri.getPath();
288 }
luxiaol62677b02013-07-22 07:54:49 +0800289 if (downloadPath != null) {
290 String rawEmulatedStorageTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET);
291 if (!TextUtils.isEmpty(rawEmulatedStorageTarget)) {
292 if (downloadPath.startsWith("/storage/sdcard0"))
293 downloadPath = downloadPath.replace("/storage/sdcard0",
294 "/storage/emulated/0");
295 if (downloadPath.startsWith("/storage/emulated/legacy"))
296 downloadPath = downloadPath.replace("/storage/emulated/legacy",
297 "/storage/emulated/0");
298 }
299 downloadPathForUser = DownloadHandler.getDownloadPathForUser(
300 DownloadSettings.this, downloadPath);
301 setDownloadPathForUserText(downloadPathForUser);
302 }
303 }
304 }
305 }
306
kaiyizf1a66762013-09-16 16:59:43 +0800307 // Add for carrier feature - download to related folders by mimetype.
308 private static String chooseFolderFromMimeType(String path, String mimeType) {
309 String destinationFolder = null;
310 if (!path.contains(Environment.DIRECTORY_DOWNLOADS) || null == mimeType)
311 return path;
312 if (mimeType.startsWith("audio"))
313 destinationFolder = Environment.DIRECTORY_MUSIC;
314 else if (mimeType.startsWith("video"))
315 destinationFolder = Environment.DIRECTORY_MOVIES;
316 else if (mimeType.startsWith("image"))
317 destinationFolder = Environment.DIRECTORY_PICTURES;
318 if (null != destinationFolder)
319 path = path.replace(Environment.DIRECTORY_DOWNLOADS, destinationFolder);
320 return path;
321 }
322
luxiaol62677b02013-07-22 07:54:49 +0800323 /**
324 * show download path for user
325 *
326 * @param downloadPath the download path user can see
327 */
328 private void setDownloadPathForUserText(String downloadPathForUser) {
329 downloadPathET.setText(downloadPathForUser);
330 }
331
332 /**
333 * get the filename from user select the download path
334 *
335 * @return String the filename from user selected
336 */
337 private String getFilenameBaseFromUserEnter() {
338 return downloadFilenameET.getText().toString();
339 }
340
341 /**
342 * set the download file size for user to be known
343 */
344 private void setDownloadFileSizeText() {
345 String sizeText;
346 if (contentLength <= 0) {
347 sizeText = getString(R.string.unknow_length);
348 } else {
349 sizeText = getDownloadFileSize();
350 }
351 downloadEstimateSize.setText(sizeText);
352
353 }
354
355 /**
356 * set the time which downloaded this file will be estimately use;
357 */
358 private void setDownloadFileTimeText() {
359 String neededTimeText;
360 if (contentLength <= 0) {
361 neededTimeText = getString(R.string.unknow_length);
362 } else {
363 neededTimeText = getNeededTime() + getString(R.string.time_min);
364 }
365 downloadEstimateTime.setText(neededTimeText);
366 }
367
368 /**
369 * count the download file's size and format the values
370 *
371 * @return String the format values
372 */
373 private String getDownloadFileSize() {
374 String currentSizeText = "";
375 if (contentLength > 0) {
376 currentSizeText = Formatter.formatFileSize(DownloadSettings.this, contentLength);
377 }
378 return currentSizeText;
379 }
380
381 /**
382 * get the time download this file will be use,and format this time values
383 *
384 * @return long the valses of time which download this file will be use
385 */
386 private long getNeededTime() {
387 long timeNeeded = contentLength / downloadRate;
388 if (timeNeeded < 1) {
389 timeNeeded = 1;
390 }
391 Log.e(LOGTAG, "TimeNeeded:" + timeNeeded + "min");
392 // return the time like 5 min, not 5 s;
393 return timeNeeded;
394 }
395}