diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 15d8177..f955ce5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -157,6 +157,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/acr/browser/lightning/constant/DownloadsPage.java b/app/src/main/java/acr/browser/lightning/constant/DownloadsPage.java index 9bc0a4e..5e5eb8a 100644 --- a/app/src/main/java/acr/browser/lightning/constant/DownloadsPage.java +++ b/app/src/main/java/acr/browser/lightning/constant/DownloadsPage.java @@ -23,6 +23,7 @@ import acr.browser.lightning.R; import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.database.downloads.DownloadItem; import acr.browser.lightning.database.downloads.DownloadsModel; +import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.utils.Preconditions; import acr.browser.lightning.utils.Utils; @@ -58,6 +59,7 @@ public final class DownloadsPage { private File mFilesDir; @Inject Application mApp; + @Inject PreferenceManager mPreferenceManager; @Inject DownloadsModel mManager; @NonNull private final String mTitle; @@ -74,7 +76,7 @@ public final class DownloadsPage { public void onSubscribe(@NonNull SingleSubscriber subscriber) { mFilesDir = mApp.getFilesDir(); - buildDownloadsPage(null); + buildDownloadsPage(); File downloadsWebPage = new File(mFilesDir, FILENAME); @@ -84,36 +86,41 @@ public final class DownloadsPage { }); } - private void buildDownloadsPage(@Nullable final String folder) { + private void buildDownloadsPage() { mManager.getAllDownloads() .subscribe(new SingleOnSubscribe>() { @Override public void onItem(@Nullable List list) { Preconditions.checkNonNull(list); + String directory = mPreferenceManager.getDownloadDirectory(); - final File downloadsWebPage; - if (folder == null || folder.isEmpty()) { - downloadsWebPage = new File(mFilesDir, FILENAME); - } else { - downloadsWebPage = new File(mFilesDir, folder + '-' + FILENAME); - } final StringBuilder downloadsBuilder = new StringBuilder(HEADING_1 + mTitle + HEADING_2); for (int n = 0, size = list.size(); n < size; n++) { final DownloadItem item = list.get(n); downloadsBuilder.append(PART1); - downloadsBuilder.append(item.getUrl()); + downloadsBuilder.append("file://"); + downloadsBuilder.append(directory); + downloadsBuilder.append("/"); + downloadsBuilder.append(item.getTitle()); downloadsBuilder.append(PART2); downloadsBuilder.append(item.getTitle()); + + if (!item.getContentSize().isEmpty()) { + downloadsBuilder.append(" ["); + downloadsBuilder.append(item.getContentSize()); + downloadsBuilder.append("]"); + } + downloadsBuilder.append(PART3); - downloadsBuilder.append(item.getContentSize()); + downloadsBuilder.append(item.getUrl()); downloadsBuilder.append(PART4); } downloadsBuilder.append(END); FileWriter bookWriter = null; try { //noinspection IOResourceOpenedButNotSafelyClosed - bookWriter = new FileWriter(downloadsWebPage, false); + bookWriter = new FileWriter(new File(mFilesDir, FILENAME), false); bookWriter.write(downloadsBuilder.toString()); } catch (IOException e) { e.printStackTrace(); diff --git a/app/src/main/java/acr/browser/lightning/dialog/LightningDialogBuilder.java b/app/src/main/java/acr/browser/lightning/dialog/LightningDialogBuilder.java index 506debd..706e7f4 100644 --- a/app/src/main/java/acr/browser/lightning/dialog/LightningDialogBuilder.java +++ b/app/src/main/java/acr/browser/lightning/dialog/LightningDialogBuilder.java @@ -10,6 +10,7 @@ import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.util.Log; import android.view.View; +import android.webkit.URLUtil; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.EditText; @@ -27,7 +28,6 @@ import acr.browser.lightning.activity.MainActivity; import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.constant.BookmarkPage; import acr.browser.lightning.constant.Constants; -import acr.browser.lightning.constant.DownloadsPage; import acr.browser.lightning.controller.UIController; import acr.browser.lightning.database.HistoryItem; import acr.browser.lightning.database.bookmark.BookmarkModel; @@ -169,21 +169,7 @@ public class LightningDialogBuilder { @NonNull final UIController uiController, @NonNull final String url) { - BrowserDialog.show(activity, R.string.action_bookmarks, - new BrowserDialog.Item(R.string.dialog_delete_download) { - @Override - public void onClick() { - mDownloadsModel.deleteDownload(url).subscribe(new SingleOnSubscribe() { - @Override - public void onItem(@Nullable Boolean item) { - if (item != null && !item) - Log.i(TAG, "error deleting download from database"); - else - uiController.handleDownloadDeleted(); - } - }); - } - }, + BrowserDialog.show(activity, R.string.action_downloads, new BrowserDialog.Item(R.string.dialog_delete_all_downloads) { @Override public void onClick() { @@ -393,6 +379,15 @@ public class LightningDialogBuilder { @Override public void onClick() { Utils.downloadFile(activity, mPreferenceManager, url, userAgent, "attachment"); + + mDownloadsModel.addDownloadIfNotExists(new DownloadItem(url, URLUtil.guessFileName(url, null, null), "")) + .subscribe(new SingleOnSubscribe() { + @Override + public void onItem(@Nullable Boolean item) { + if (item != null && !item) + Log.i(TAG, "error saving download to database"); + } + }); } }); } diff --git a/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java b/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java index 7fdab9b..6f02b92 100644 --- a/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java +++ b/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java @@ -47,15 +47,6 @@ public class DownloadHandler { Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) .getPath(); - @Nullable - static String guessFileExtension(@NonNull String filename) { - int lastIndex = filename.lastIndexOf('.') + 1; - if (lastIndex > 0 && filename.length() > lastIndex) { - return filename.substring(lastIndex, filename.length()); - } - return null; - } - /** * Notify the host application a download should be done, or that the data * should be streamed if a streaming viewer is available. @@ -222,7 +213,7 @@ public class DownloadHandler { Utils.showSnackbar(context, R.string.problem_location_download); return; } - String newMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(guessFileExtension(filename)); + String newMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(Utils.guessFileExtension(filename)); Log.d(TAG, "New mimetype: " + newMimeType); request.setMimeType(newMimeType); request.setDestinationUri(Uri.parse(Constants.FILE + location + filename)); diff --git a/app/src/main/java/acr/browser/lightning/download/FetchUrlMimeType.java b/app/src/main/java/acr/browser/lightning/download/FetchUrlMimeType.java index fcef5ce..96b7078 100644 --- a/app/src/main/java/acr/browser/lightning/download/FetchUrlMimeType.java +++ b/app/src/main/java/acr/browser/lightning/download/FetchUrlMimeType.java @@ -93,7 +93,7 @@ class FetchUrlMimeType extends Thread { if (mimeType.equalsIgnoreCase("text/plain") || mimeType.equalsIgnoreCase("application/octet-stream")) { String newMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension( - DownloadHandler.guessFileExtension(mUri)); + Utils.guessFileExtension(mUri)); if (newMimeType != null) { mRequest.setMimeType(newMimeType); } diff --git a/app/src/main/java/acr/browser/lightning/download/LightningDownloadListener.java b/app/src/main/java/acr/browser/lightning/download/LightningDownloadListener.java index fba4cba..a38bb93 100644 --- a/app/src/main/java/acr/browser/lightning/download/LightningDownloadListener.java +++ b/app/src/main/java/acr/browser/lightning/download/LightningDownloadListener.java @@ -50,7 +50,15 @@ public class LightningDownloadListener implements DownloadListener { new PermissionsResultAction() { @Override public void onGranted() { - String fileName = URLUtil.guessFileName(url, contentDisposition, mimetype); + final String fileName = URLUtil.guessFileName(url, contentDisposition, mimetype); + final String downloadSize; + + if (contentLength > 0) { + downloadSize = Formatter.formatFileSize(mActivity, contentLength); + } else { + downloadSize = mActivity.getString(R.string.unknown_size); + } + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { @@ -58,6 +66,15 @@ public class LightningDownloadListener implements DownloadListener { case DialogInterface.BUTTON_POSITIVE: DownloadHandler.onDownloadStart(mActivity, mPreferenceManager, url, userAgent, contentDisposition, mimetype); + + downloadsModel.addDownloadIfNotExists(new DownloadItem(url, fileName, downloadSize)) + .subscribe(new SingleOnSubscribe() { + @Override + public void onItem(@Nullable Boolean item) { + if (item != null && !item) + Log.i(TAG, "error saving download to database"); + } + }); break; case DialogInterface.BUTTON_NEGATIVE: break; @@ -66,12 +83,6 @@ public class LightningDownloadListener implements DownloadListener { }; AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); // dialog - String downloadSize; - if (contentLength > 0) { - downloadSize = Formatter.formatFileSize(mActivity, contentLength); - } else { - downloadSize = mActivity.getString(R.string.unknown_size); - } String message = mActivity.getString(R.string.dialog_download, downloadSize); Dialog dialog = builder.setTitle(fileName) .setMessage(message) @@ -81,16 +92,6 @@ public class LightningDownloadListener implements DownloadListener { dialogClickListener).show(); BrowserDialog.setDialogSize(mActivity, dialog); Log.i(TAG, "Downloading: " + fileName); - - downloadsModel.addDownloadIfNotExists(new DownloadItem(url, fileName, downloadSize)).subscribe(new SingleOnSubscribe() { - @Override - public void onItem(@Nullable Boolean item) { - super.onItem(item); - - if (item != null && !item) - Log.i(TAG, "error saving download to database"); - } - }); } @Override diff --git a/app/src/main/java/acr/browser/lightning/utils/Utils.java b/app/src/main/java/acr/browser/lightning/utils/Utils.java index 62a2669..0bb7682 100644 --- a/app/src/main/java/acr/browser/lightning/utils/Utils.java +++ b/app/src/main/java/acr/browser/lightning/utils/Utils.java @@ -456,4 +456,13 @@ public final class Utils { return inSampleSize; } + @Nullable + public static String guessFileExtension(@NonNull String filename) { + int lastIndex = filename.lastIndexOf('.') + 1; + if (lastIndex > 0 && filename.length() > lastIndex) { + return filename.substring(lastIndex, filename.length()); + } + return null; + } + } diff --git a/app/src/main/java/acr/browser/lightning/view/LightningWebClient.java b/app/src/main/java/acr/browser/lightning/view/LightningWebClient.java index 0d1fd33..62cdbda 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningWebClient.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningWebClient.java @@ -8,30 +8,31 @@ import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.net.MailTo; +import android.net.Uri; import android.net.http.SslError; import android.os.Build; import android.os.Message; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v4.view.LayoutInflaterCompat; +import android.support.v4.content.FileProvider; import android.support.v7.app.AlertDialog; -import android.text.InputType; -import android.text.method.PasswordTransformationMethod; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.webkit.HttpAuthHandler; +import android.webkit.MimeTypeMap; import android.webkit.SslErrorHandler; +import android.webkit.URLUtil; import android.webkit.ValueCallback; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.EditText; -import android.widget.LinearLayout; import android.widget.TextView; import java.io.ByteArrayInputStream; +import java.io.File; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; @@ -39,6 +40,7 @@ import java.util.Map; import javax.inject.Inject; +import acr.browser.lightning.BuildConfig; import acr.browser.lightning.R; import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.constant.Constants; @@ -358,6 +360,26 @@ public class LightningWebClient extends WebViewClient { } return true; } + } else if (url.startsWith("file://")) { + File file = new File(url.replace("file://", "")); + + if (file.exists()) { + String newMimeType = MimeTypeMap.getSingleton() + .getMimeTypeFromExtension(Utils.guessFileExtension(file.toString())); + + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + Uri contentUri = FileProvider.getUriForFile(mActivity, BuildConfig.APPLICATION_ID + ".fileprovider", file); + intent.setDataAndType(contentUri, newMimeType); + + try { + mActivity.startActivity(intent); + } catch (Exception e) { + System.out.println("LightningWebClient: cannot open downloaded file"); + } + return true; + } } return false; } diff --git a/app/src/main/res/xml/filepaths.xml b/app/src/main/res/xml/filepaths.xml new file mode 100644 index 0000000..065dee8 --- /dev/null +++ b/app/src/main/res/xml/filepaths.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file