Skip to content

Commit

Permalink
Closes #672 Downloads support (#3072)
Browse files Browse the repository at this point in the history
* Downloads

* Disable HW acceleration in the tray to make downloads icon clipping work

* Rebase fixes

* Fix rebase issue

* Fix showing control panels in a new tab containing about:blank

Co-authored-by: Randall E. Barker <simstorm@mac.com>
  • Loading branch information
keianhzo and bluemarvin committed Apr 13, 2020
1 parent 0de17f7 commit ee7d323
Show file tree
Hide file tree
Showing 75 changed files with 3,290 additions and 536 deletions.
1 change: 1 addition & 0 deletions app/metrics.yaml
Expand Up @@ -102,6 +102,7 @@ tabs:
- received
- pre_existing
- browser
- downloads
bugs:
- https://github.com/MozillaReality/FirefoxReality/issues/1609
data_reviews:
Expand Down
11 changes: 11 additions & 0 deletions app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java
Expand Up @@ -60,6 +60,7 @@
import org.mozilla.vrbrowser.telemetry.TelemetryWrapper;
import org.mozilla.vrbrowser.ui.OffscreenDisplay;
import org.mozilla.vrbrowser.ui.adapters.Language;
import org.mozilla.vrbrowser.ui.widgets.AppServicesProvider;
import org.mozilla.vrbrowser.ui.widgets.KeyboardWidget;
import org.mozilla.vrbrowser.ui.widgets.NavigationBarWidget;
import org.mozilla.vrbrowser.ui.widgets.RootWidget;
Expand Down Expand Up @@ -303,6 +304,8 @@ protected void onCreate(Bundle savedInstanceState) {
checkForCrash();

mLifeCycle.setCurrentState(Lifecycle.State.CREATED);

getServicesProvider().getDownloadsManager().init();
}

protected void initializeWidgets() {
Expand Down Expand Up @@ -487,6 +490,8 @@ protected void onDestroy() {

SessionStore.get().onDestroy();

getServicesProvider().getDownloadsManager().end();

super.onDestroy();
mLifeCycle.setCurrentState(Lifecycle.State.DESTROYED);
mViewModelStore.clear();
Expand Down Expand Up @@ -1592,6 +1597,12 @@ public void updateLocale(@NonNull Context context) {
onConfigurationChanged(context.getResources().getConfiguration());
}

@Override
@NonNull
public AppServicesProvider getServicesProvider() {
return (AppServicesProvider)getApplication();
}

private native void addWidgetNative(int aHandle, WidgetPlacement aPlacement);
private native void updateWidgetNative(int aHandle, WidgetPlacement aPlacement);
private native void updateVisibleWidgetsNative();
Expand Down
Expand Up @@ -14,19 +14,22 @@
import org.mozilla.vrbrowser.browser.Services;
import org.mozilla.vrbrowser.db.AppDatabase;
import org.mozilla.vrbrowser.db.DataRepository;
import org.mozilla.vrbrowser.downloads.DownloadsManager;
import org.mozilla.vrbrowser.telemetry.GleanMetricsService;
import org.mozilla.vrbrowser.telemetry.TelemetryWrapper;
import org.mozilla.vrbrowser.ui.adapters.Language;
import org.mozilla.vrbrowser.ui.widgets.AppServicesProvider;
import org.mozilla.vrbrowser.utils.BitmapCache;
import org.mozilla.vrbrowser.utils.LocaleUtils;

public class VRBrowserApplication extends Application {
public class VRBrowserApplication extends Application implements AppServicesProvider {

private AppExecutors mAppExecutors;
private BitmapCache mBitmapCache;
private Services mServices;
private Places mPlaces;
private Accounts mAccounts;
private DownloadsManager mDownloadsManager;

@Override
public void onCreate() {
Expand All @@ -42,6 +45,7 @@ protected void onActivityCreate() {
mPlaces = new Places(this);
mServices = new Services(this, mPlaces);
mAccounts = new Accounts(this);
mDownloadsManager = new DownloadsManager(this);
}

@Override
Expand All @@ -67,7 +71,7 @@ public Places getPlaces() {
return mPlaces;
}

private AppDatabase getDatabase() {
public AppDatabase getDatabase() {
return AppDatabase.getAppDatabase(this, mAppExecutors);
}

Expand All @@ -86,4 +90,8 @@ public BitmapCache getBitmapCache() {
public Accounts getAccounts() {
return mAccounts;
}

public DownloadsManager getDownloadsManager() {
return mDownloadsManager;
}
}
Expand Up @@ -8,6 +8,7 @@
import android.preference.PreferenceManager;
import android.util.Log;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.databinding.ObservableBoolean;
import androidx.lifecycle.Observer;
Expand All @@ -23,6 +24,7 @@
import org.mozilla.vrbrowser.telemetry.GleanMetricsService;
import org.mozilla.vrbrowser.telemetry.TelemetryWrapper;
import org.mozilla.vrbrowser.ui.viewmodel.SettingsViewModel;
import org.mozilla.vrbrowser.ui.widgets.menus.library.SortingContextMenuWidget;
import org.mozilla.vrbrowser.utils.DeviceType;
import org.mozilla.vrbrowser.utils.StringUtils;
import org.mozilla.vrbrowser.utils.SystemUtils;
Expand All @@ -49,6 +51,11 @@ SettingsStore getInstance(final @NonNull Context aContext) {
return mSettingsInstance;
}

@IntDef(value = { INTERNAL, EXTERNAL})
public @interface Storage {}
public static final int INTERNAL = 0;
public static final int EXTERNAL = 1;

private Context mContext;
private SharedPreferences mPrefs;
private SettingsViewModel mSettingsViewModel;
Expand Down Expand Up @@ -93,6 +100,8 @@ SettingsStore getInstance(final @NonNull Context aContext) {
public final static boolean RESTORE_TABS_ENABLED = true;
public final static boolean BYPASS_CACHE_ON_RELOAD = false;
public final static boolean MULTI_E10S = false;
public final static int DOWNLOADS_STORAGE_DEFAULT = INTERNAL;
public final static int DOWNLOADS_SORTING_ORDER_DEFAULT = SortingContextMenuWidget.SORT_FILENAME_AZ;

// Enable telemetry by default (opt-out).
public final static boolean CRASH_REPORTING_DEFAULT = false;
Expand Down Expand Up @@ -719,5 +728,25 @@ public void setMultiE10s(boolean isEnabled) {
public boolean isMultiE10s() {
return mPrefs.getBoolean(mContext.getString(R.string.settings_key_multi_e10s), MULTI_E10S);
}

public void setDownloadsStorage(@Storage int storage) {
SharedPreferences.Editor editor = mPrefs.edit();
editor.putInt(mContext.getString(R.string.settings_key_downloads_external), storage);
editor.commit();
}

public @Storage int getDownloadsStorage() {
return mPrefs.getInt(mContext.getString(R.string.settings_key_downloads_external), DOWNLOADS_STORAGE_DEFAULT);
}

public void setDownloadsSortingOrder(@SortingContextMenuWidget.Order int order) {
SharedPreferences.Editor editor = mPrefs.edit();
editor.putInt(mContext.getString(R.string.settings_key_downloads_sorting_order), order);
editor.commit();
}

public @Storage int getDownloadsSortingOrder() {
return mPrefs.getInt(mContext.getString(R.string.settings_key_downloads_sorting_order), DOWNLOADS_SORTING_ORDER_DEFAULT);
}
}

Expand Up @@ -1201,6 +1201,13 @@ public GeckoResult<SlowScriptResponse> onSlowScript(@NonNull GeckoSession aSessi
return null;
}

@Override
public void onExternalResponse(@NonNull GeckoSession geckoSession, @NonNull GeckoSession.WebResponseInfo webResponseInfo) {
for (GeckoSession.ContentDelegate listener : mContentListeners) {
listener.onExternalResponse(geckoSession, webResponseInfo);
}
}

// TextInput Delegate

@Override
Expand Down
4 changes: 4 additions & 0 deletions app/src/common/shared/org/mozilla/vrbrowser/db/Download.java
@@ -0,0 +1,4 @@
package org.mozilla.vrbrowser.db;

public class Download {
}
@@ -0,0 +1,4 @@
package org.mozilla.vrbrowser.db;

public class DownloadDao {
}
182 changes: 182 additions & 0 deletions app/src/common/shared/org/mozilla/vrbrowser/downloads/Download.java
@@ -0,0 +1,182 @@
package org.mozilla.vrbrowser.downloads;

import android.app.DownloadManager;
import android.content.Context;
import android.database.Cursor;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;

import org.mozilla.vrbrowser.ui.adapters.Language;
import org.mozilla.vrbrowser.utils.LocaleUtils;

import java.io.File;
import java.net.URL;

public class Download {

@IntDef(value = { UNAVAILABLE, PENDING, RUNNING, PAUSED, SUCCESSFUL, FAILED})
@interface Status {}
public static final int UNAVAILABLE = 0;
public static final int PENDING = DownloadManager.STATUS_PENDING;
public static final int RUNNING = DownloadManager.STATUS_RUNNING;
public static final int PAUSED = DownloadManager.STATUS_PAUSED;
public static final int SUCCESSFUL = DownloadManager.STATUS_SUCCESSFUL;
public static final int FAILED = DownloadManager.STATUS_FAILED;

private static final long MEGABYTE = 1024L * 1024L;
private static final long KILOBYTE = 1024L;

private long mId;
private String mUri;
private String mMediaType;
private long mSizeBytes;
private long mDownloadedBytes;
private String mOutputFile;
private String mTitle;
private String mDescription;
private @Status int mStatus;
private long mLastModified;

public static Download from(Cursor cursor) {
Download download = new Download();
download.mId = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
download.mUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI));
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch (status) {
case DownloadManager.STATUS_RUNNING:
download.mStatus = RUNNING;
break;
case DownloadManager.STATUS_FAILED:
download.mStatus = FAILED;
break;
case DownloadManager.STATUS_PAUSED:
download.mStatus = PAUSED;
break;
case DownloadManager.STATUS_PENDING:
download.mStatus = PENDING;
break;
case DownloadManager.STATUS_SUCCESSFUL:
download.mStatus = SUCCESSFUL;
break;
default:
download.mStatus = UNAVAILABLE;
}
download.mMediaType = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE));
download.mTitle = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE));
download.mOutputFile = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
download.mDescription = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_DESCRIPTION));
download.mSizeBytes = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
download.mDownloadedBytes = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
download.mLastModified = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP));
return download;
}

public long getId() {
return mId;
}

public String getUri() {
return mUri;
}

public String getMediaType() {
return mMediaType;
}

public long getSizeBytes() {
return mSizeBytes;
}

public long getDownloadedBytes() {
return mDownloadedBytes;
}

public String getOutputFile() {
return mOutputFile;
}

public String getTitle() {
return mTitle;
}

public String getDescription() {
return mDescription;
}

public int getStatus() {
return mStatus;
}

public String getStatusString() {
switch (mStatus) {
case RUNNING:
return "RUNNING";
case FAILED:
return "FAILED";
case PAUSED:
return "PAUSED";
case PENDING:
return "PENDING";
case SUCCESSFUL:
return "SUCCESSFUL";
case UNAVAILABLE:
return "UNAVAILABLE";
default:
return "UNKNOWN";
}
}

public long getLastModified() {
return mLastModified;
}

public double getProgress() {
if (mSizeBytes != -1) {
return mDownloadedBytes*100.0/mSizeBytes;
}
return 0;
}

public String getFilename() {
try {
File f = new File(new URL(mOutputFile).getPath());
return f.getName();

} catch (Exception e) {
if (mOutputFile != null) {
return mOutputFile;

} else {
return "";
}
}
}

@NonNull
public static String progressString(@NonNull Context context, @NonNull Download download) {
Language language = LocaleUtils.getDisplayLanguage(context);
if (download.mStatus == RUNNING) {
if (download.mSizeBytes < MEGABYTE) {
return String.format(language.getLocale(), "%.2f/%.2fKb (%d%%)",
((double)download.mDownloadedBytes / (double)KILOBYTE),
((double)download.mSizeBytes / (double)KILOBYTE),
(download.mDownloadedBytes*100)/download.mSizeBytes);

} else {
return String.format(language.getLocale(), "%.2f/%.2fMB (%d%%)",
((double)download.mDownloadedBytes / (double)MEGABYTE),
((double)download.mSizeBytes / (double)MEGABYTE),
(download.mDownloadedBytes*100)/download.mSizeBytes);
}

} else {
if (download.mSizeBytes < MEGABYTE) {
return String.format(language.getLocale(), "%.2fKb", ((double)download.mSizeBytes / (double)KILOBYTE));

} else {
return String.format(language.getLocale(), "%.2fMB", ((double)download.mSizeBytes / (double)MEGABYTE));
}
}
}
}

0 comments on commit ee7d323

Please sign in to comment.