blob: 32803de4624ddb225fdfd066867efc7ee0418a4f [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;
jrizzoli700a8672015-10-18 00:15:07 +020049import android.widget.ImageButton;
luxiaol62677b02013-07-22 07:54:49 +080050import android.widget.TextView;
51import android.view.Window;
52import android.widget.Toast;
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -070053import android.webkit.MimeTypeMap;
luxiaol62677b02013-07-22 07:54:49 +080054import android.text.TextUtils;
55
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -070056import com.android.browser.reflect.ReflectHelper;
57
luxiaol62677b02013-07-22 07:54:49 +080058public class DownloadSettings extends Activity {
59
60 private EditText downloadFilenameET;
61 private EditText downloadPathET;
62 private TextView downloadEstimateSize;
63 private TextView downloadEstimateTime;
jrizzoli700a8672015-10-18 00:15:07 +020064 private ImageButton downloadStart;
65 private ImageButton downloadCancel;
luxiaol62677b02013-07-22 07:54:49 +080066 private String url;
67 private String userAgent;
68 private String contentDisposition;
69 private String mimetype;
70 private String referer;
Pankaj Garg5762b362015-11-02 07:57:06 -080071 private String authorization;
luxiaol62677b02013-07-22 07:54:49 +080072 private String filenameBase;
73 private String filename;
74 private String filenameExtension;
75 private boolean privateBrowsing;
76 private long contentLength;
77 private String downloadPath;
78 private String downloadPathForUser;
79 private static final int downloadRate = (1024 * 100 * 60);// Download Rate
80 // 100KB/s
81 private final static String LOGTAG = "DownloadSettings";
82 private final static int DOWNLOAD_PATH = 0;
83 private boolean isDownloadStarted = false;
84
85 private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET";
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -070086 private static final String APK_TYPE="apk";
87 private static final String OCTET_STREAM = "application/octet-stream";
luxiaol62677b02013-07-22 07:54:49 +080088
89 protected void onCreate(Bundle savedInstanceState) {
90 super.onCreate(savedInstanceState);
91 // initial the DownloadSettings view
92 requestWindowFeature(Window.FEATURE_NO_TITLE);
93 setContentView(R.layout.download_settings);
94 downloadFilenameET = (EditText) findViewById(R.id.download_filename_edit);
95 downloadPathET = (EditText) findViewById(R.id.download_filepath_selected);
96 downloadEstimateSize = (TextView) findViewById(R.id.download_estimate_size_content);
97 downloadEstimateTime = (TextView) findViewById(R.id.download_estimate_time_content);
jrizzoli700a8672015-10-18 00:15:07 +020098 downloadStart = (ImageButton) findViewById(R.id.download_start);
99 downloadCancel = (ImageButton) findViewById(R.id.download_cancel);
luxiaol62677b02013-07-22 07:54:49 +0800100 downloadPathET.setOnClickListener(downloadPathListener);
101 downloadStart.setOnClickListener(downloadStartListener);
102 downloadCancel.setOnClickListener(downloadCancelListener);
103
104 // get the bundle from Intent
105 Intent intent = getIntent();
106 Bundle fileInfo = intent.getExtras();
107 url = fileInfo.getString("url");
108 userAgent = fileInfo.getString("userAgent");
109 contentDisposition = fileInfo.getString("contentDisposition");
110 mimetype = fileInfo.getString("mimetype");
111 referer = fileInfo.getString("referer");
Pankaj Garg5762b362015-11-02 07:57:06 -0800112 authorization = fileInfo.getString("authorization");
luxiaol62677b02013-07-22 07:54:49 +0800113 contentLength = fileInfo.getLong("contentLength");
114 privateBrowsing = fileInfo.getBoolean("privateBrowsing");
115 filename = fileInfo.getString("filename");
116
117 // download filenamebase's length is depended on filenameLength's values
118 // if filenamebase.length >= flienameLength, destroy the last string!
119
120 filenameBase = DownloadHandler.getFilenameBase(filename);
121 if (filenameBase.length() >= (BrowserUtils.FILENAME_MAX_LENGTH)) {
122 filenameBase = filenameBase.substring(0, BrowserUtils.FILENAME_MAX_LENGTH);
123 }
124
125 // warring when user enter more over letters into the EditText
126 BrowserUtils.maxLengthFilter(DownloadSettings.this, downloadFilenameET,
127 BrowserUtils.FILENAME_MAX_LENGTH);
128
129 downloadFilenameET.setText(filenameBase);
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700130
131 String filenameExtension = DownloadHandler.getFilenameExtension(filename);
132
Axesh R. Ajmera2e241242014-05-19 15:53:38 -0700133 // introspect for octet stream mimetype what type of file extension it has
134 // and reassign mimetype
135 if (mimetype == null || mimetype.isEmpty() || mimetype.equals(OCTET_STREAM)) {
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700136
137 String updatedFileName = filenameBase + "." + filenameExtension;
138 Object[] params = {updatedFileName};
139 Class[] type = new Class[] {String.class};
Bijan Amirzada58383e72014-04-01 14:45:22 -0700140 mimetype = (String) ReflectHelper.invokeMethod("android.media.MediaFile",
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700141 "getMimeTypeForFile", type, params);
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700142 }
143
144 //Add special check for .apk files with octet-stream mimetype
Axesh R. Ajmera77258982014-04-02 14:39:09 -0700145 if (filenameExtension.equals(APK_TYPE) && mimetype != null && mimetype.equals(OCTET_STREAM)) {
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700146 mimetype = "application/vnd.android.package-archive";
147 }
148
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700149 // last way to fetch for mimetype if its still null
150 if (mimetype == null || mimetype.isEmpty())
151 mimetype = MimeTypeMap.getSingleton().getMimeTypeFromExtension(filenameExtension);
152
kaiyizf1a66762013-09-16 16:59:43 +0800153 downloadPath = chooseFolderFromMimeType(BrowserSettings.getInstance().getDownloadPath(),
154 mimetype);
luxiaol62677b02013-07-22 07:54:49 +0800155 downloadPathForUser = DownloadHandler.getDownloadPathForUser(DownloadSettings.this,
156 downloadPath);
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700157
158 autoupdateFileName(filenameBase, DownloadHandler.getFilenameExtension(filename), downloadPath);
luxiaol62677b02013-07-22 07:54:49 +0800159 setDownloadPathForUserText(downloadPathForUser);
160 setDownloadFileSizeText();
161 setDownloadFileTimeText();
luxiaol62677b02013-07-22 07:54:49 +0800162 }
163
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700164 private void autoupdateFileName(String filenameBase, String extension, String downloadPath) {
165 String fullPath = downloadPath + "/" + filenameBase + "." + extension;
166 int count = 1;
167 String newFilenameBase = "";
168
169 while(new File(fullPath).exists()) {
170 newFilenameBase = filenameBase+"-"+count++;
171 fullPath = downloadPath + "/" + newFilenameBase + "." + extension;
172 }
173
174 if(!TextUtils.isEmpty(newFilenameBase)) {
175 filenameBase = newFilenameBase;
176 }
177
178 downloadFilenameET.setText(filenameBase);
179 }
180
luxiaol62677b02013-07-22 07:54:49 +0800181 private OnClickListener downloadPathListener = new OnClickListener() {
182
183 @Override
184 public void onClick(View v) {
185
Vivek Sekharefefe6b2015-01-05 16:01:07 -0800186 final String filemanagerIntent =
187 getResources().getString(R.string.def_intent_file_manager);
188 if (!TextUtils.isEmpty(filemanagerIntent)) {
189 // start filemanager for getting download path
190 try {
191 Intent downloadPathIntent = new Intent(filemanagerIntent);
192 DownloadSettings.this.startActivityForResult(downloadPathIntent, DOWNLOAD_PATH);
193 } catch (Exception e) {
194 String err_msg = getString(R.string.activity_not_found,
195 filemanagerIntent);
196 Toast.makeText(DownloadSettings.this, err_msg, Toast.LENGTH_LONG).show();
197 }
198 } else {
199 Log.e(LOGTAG, "File Manager intent not defined !!");
luxiaol62677b02013-07-22 07:54:49 +0800200 }
201
202 }
203 };
204
205 private OnClickListener downloadStartListener = new OnClickListener() {
206
207 @Override
208 public void onClick(View v) {
209 filenameBase = getFilenameBaseFromUserEnter();
210 // check the filename user enter is null or not
Sagar Dhawan97ed6c92015-07-31 15:36:07 -0700211 if (TextUtils.isEmpty(filenameBase) || TextUtils.isEmpty(downloadPath)) {
luxiaol62677b02013-07-22 07:54:49 +0800212 DownloadHandler.showFilenameEmptyDialog(DownloadSettings.this);
213 return;
214 }
215
216 filenameExtension = DownloadHandler.getFilenameExtension(filename);
217 filename = filenameBase + "." + filenameExtension;
218
219 // check the storage status
220 if (!DownloadHandler.isStorageStatusOK(DownloadSettings.this, filename, downloadPath)) {
221 return;
222 }
223
224 // check the storage memory enough or not
225 try {
226 DownloadHandler.setAppointedFolder(downloadPath);
227 } catch (Exception e) {
228 DownloadHandler.showNoEnoughMemoryDialog(DownloadSettings.this);
229 return;
230 }
kaiyize6a27d02013-08-22 15:08:19 +0800231 boolean isNoEnoughMemory = DownloadHandler.manageNoEnoughMemory(contentLength,
232 downloadPath);
luxiaol62677b02013-07-22 07:54:49 +0800233 if (isNoEnoughMemory) {
kaiyize6a27d02013-08-22 15:08:19 +0800234 DownloadHandler.showNoEnoughMemoryDialog(DownloadSettings.this);
luxiaol62677b02013-07-22 07:54:49 +0800235 return;
236 }
237
238 // check the download file is exist or not
239 String fullFilename = downloadPath + "/" + filename;
240 if (mimetype != null && new File(fullFilename).exists()) {
241 DownloadHandler.fileExistQueryDialog(DownloadSettings.this);
242 return;
243 }
244
245 // staring downloading
246 DownloadHandler.startingDownload(DownloadSettings.this,
247 url, userAgent, contentDisposition,
Pankaj Garg5762b362015-11-02 07:57:06 -0800248 mimetype, referer, authorization, privateBrowsing, contentLength,
luxiaol62677b02013-07-22 07:54:49 +0800249 Uri.encode(filename), downloadPath);
250 isDownloadStarted = true;
251 }
252 };
253
254 private OnClickListener downloadCancelListener = new OnClickListener() {
luxiaol62677b02013-07-22 07:54:49 +0800255 @Override
256 public void onClick(View v) {
257 finish();
258 }
259 };
260
261 protected void onDestroy() {
262 super.onDestroy();
263 }
264
265 protected void onPause() {
266 super.onPause();
267 if (isDownloadStarted) {
268 finish();
269 }
270 }
271
272 protected void onResume() {
273 super.onResume();
274 }
275
276 @Override
277 protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
Vivek Sekharefefe6b2015-01-05 16:01:07 -0800278
luxiaol62677b02013-07-22 07:54:49 +0800279 if (DOWNLOAD_PATH == requestCode) {
Vivek Sekharefefe6b2015-01-05 16:01:07 -0800280 if (resultCode == Activity.RESULT_OK && intent != null) {
281 final String result_dir_sel =
282 getResources().getString(R.string.def_file_manager_result_dir);
283 downloadPath = intent.getStringExtra(result_dir_sel);
Vivek Sekhar76074ac2014-06-27 16:33:13 -0700284 // Fallback logic to stock browser
285 if (downloadPath == null) {
286 Uri uri = intent.getData();
287 if(uri != null)
288 downloadPath = uri.getPath();
289 }
luxiaol62677b02013-07-22 07:54:49 +0800290 if (downloadPath != null) {
291 String rawEmulatedStorageTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET);
292 if (!TextUtils.isEmpty(rawEmulatedStorageTarget)) {
293 if (downloadPath.startsWith("/storage/sdcard0"))
294 downloadPath = downloadPath.replace("/storage/sdcard0",
295 "/storage/emulated/0");
296 if (downloadPath.startsWith("/storage/emulated/legacy"))
297 downloadPath = downloadPath.replace("/storage/emulated/legacy",
298 "/storage/emulated/0");
299 }
300 downloadPathForUser = DownloadHandler.getDownloadPathForUser(
301 DownloadSettings.this, downloadPath);
302 setDownloadPathForUserText(downloadPathForUser);
303 }
304 }
305 }
306 }
307
kaiyizf1a66762013-09-16 16:59:43 +0800308 // Add for carrier feature - download to related folders by mimetype.
309 private static String chooseFolderFromMimeType(String path, String mimeType) {
310 String destinationFolder = null;
311 if (!path.contains(Environment.DIRECTORY_DOWNLOADS) || null == mimeType)
312 return path;
313 if (mimeType.startsWith("audio"))
314 destinationFolder = Environment.DIRECTORY_MUSIC;
315 else if (mimeType.startsWith("video"))
316 destinationFolder = Environment.DIRECTORY_MOVIES;
317 else if (mimeType.startsWith("image"))
318 destinationFolder = Environment.DIRECTORY_PICTURES;
319 if (null != destinationFolder)
320 path = path.replace(Environment.DIRECTORY_DOWNLOADS, destinationFolder);
321 return path;
322 }
323
luxiaol62677b02013-07-22 07:54:49 +0800324 /**
325 * show download path for user
326 *
327 * @param downloadPath the download path user can see
328 */
329 private void setDownloadPathForUserText(String downloadPathForUser) {
330 downloadPathET.setText(downloadPathForUser);
331 }
332
333 /**
334 * get the filename from user select the download path
335 *
336 * @return String the filename from user selected
337 */
338 private String getFilenameBaseFromUserEnter() {
339 return downloadFilenameET.getText().toString();
340 }
341
342 /**
343 * set the download file size for user to be known
344 */
345 private void setDownloadFileSizeText() {
346 String sizeText;
347 if (contentLength <= 0) {
348 sizeText = getString(R.string.unknow_length);
349 } else {
350 sizeText = getDownloadFileSize();
351 }
352 downloadEstimateSize.setText(sizeText);
353
354 }
355
356 /**
357 * set the time which downloaded this file will be estimately use;
358 */
359 private void setDownloadFileTimeText() {
360 String neededTimeText;
361 if (contentLength <= 0) {
362 neededTimeText = getString(R.string.unknow_length);
363 } else {
364 neededTimeText = getNeededTime() + getString(R.string.time_min);
365 }
366 downloadEstimateTime.setText(neededTimeText);
367 }
368
369 /**
370 * count the download file's size and format the values
371 *
372 * @return String the format values
373 */
374 private String getDownloadFileSize() {
375 String currentSizeText = "";
376 if (contentLength > 0) {
377 currentSizeText = Formatter.formatFileSize(DownloadSettings.this, contentLength);
378 }
379 return currentSizeText;
380 }
381
382 /**
383 * get the time download this file will be use,and format this time values
384 *
385 * @return long the valses of time which download this file will be use
386 */
387 private long getNeededTime() {
388 long timeNeeded = contentLength / downloadRate;
389 if (timeNeeded < 1) {
390 timeNeeded = 1;
391 }
392 Log.e(LOGTAG, "TimeNeeded:" + timeNeeded + "min");
393 // return the time like 5 min, not 5 s;
394 return timeNeeded;
395 }
396}