diff --git a/app/src/common/shared/org/mozilla/vrbrowser/downloads/DownloadsManager.java b/app/src/common/shared/org/mozilla/vrbrowser/downloads/DownloadsManager.java index 3b427d463..f91a447b3 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/downloads/DownloadsManager.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/downloads/DownloadsManager.java @@ -131,7 +131,12 @@ public void startDownload(@NonNull DownloadJob job, @SettingsStore.Storage int s } if (mDownloadManager != null) { - mDownloadManager.enqueue(request); + try { + mDownloadManager.enqueue(request); + } catch (SecurityException e) { + notifyDownloadError("Cannot create output file", job.getFilename()); + return; + } scheduleUpdates(); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/EnvironmentOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/EnvironmentOptionsView.java index 4514f81aa..ef4e4c4e4 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/EnvironmentOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/EnvironmentOptionsView.java @@ -11,6 +11,7 @@ import android.graphics.drawable.BitmapDrawable; import android.view.LayoutInflater; +import androidx.annotation.NonNull; import androidx.databinding.DataBindingUtil; import org.mozilla.vrbrowser.R; @@ -30,7 +31,7 @@ import java.net.URL; import java.util.Arrays; -class EnvironmentOptionsView extends SettingsView { +class EnvironmentOptionsView extends SettingsView implements EnvironmentsManager.EnvironmentListener { private OptionsEnvironmentBinding mBinding; private ImageRadioGroupSetting mEnvironmentsRadio; @@ -80,13 +81,14 @@ protected void updateUI() { public void onShown() { super.onShown(); + mEnvironmentsManager.addListener(this); mWidgetManager.pushWorldBrightness(this, WidgetManagerDelegate.DEFAULT_NO_DIM_BRIGHTNESS); } - @Override public void onHidden() { mWidgetManager.popWorldBrightness(this); + mEnvironmentsManager.removeListener(this); } private void setEnvOverride(boolean value) { @@ -127,7 +129,6 @@ private void setEnv(int checkedId, boolean doApply) { mEnvironmentsRadio.setOnCheckedChangeListener(mEnvsListener); String value = (String) mEnvironmentsRadio.getValueForId(checkedId); - SettingsStore.getInstance(getContext()).setEnvironment(value); mEnvironmentsManager.setOrDownloadEnvironment(value); } @@ -189,4 +190,18 @@ private void updateEnvironments() { setEnv(mEnvironmentsRadio.getIdForValue(env), false); } + @Override + public void onEnvironmentSetSuccess(@NonNull String envId) { + + } + + @Override + public void onEnvironmentSetError(@NonNull String error) { + setEnv(mEnvironmentsRadio.getIdForValue(SettingsStore.getInstance(getContext()).getEnvironment()), false); + mWidgetManager.getFocusedWindow().showAlert( + getContext().getString(R.string.environment__error_title), + error, + null + ); + } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/utils/EnvironmentsManager.java b/app/src/common/shared/org/mozilla/vrbrowser/utils/EnvironmentsManager.java index b75af3065..465023086 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/utils/EnvironmentsManager.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/utils/EnvironmentsManager.java @@ -11,6 +11,7 @@ import com.mozilla.speechlibrary.utils.zip.UnzipCallback; import com.mozilla.speechlibrary.utils.zip.UnzipTask; +import org.mozilla.geckoview.GeckoSession; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.browser.SettingsStore; import org.mozilla.vrbrowser.downloads.Download; @@ -19,19 +20,39 @@ import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; import java.io.File; +import java.util.ArrayList; public class EnvironmentsManager implements DownloadsManager.DownloadsListener, SharedPreferences.OnSharedPreferenceChangeListener { + public interface EnvironmentListener { + default void onEnvironmentSetSuccess(@NonNull String envId) {} + default void onEnvironmentSetError(@NonNull String error) {} + } + private WidgetManagerDelegate mApplicationDelegate; private Context mContext; private DownloadsManager mDownloadManager; private SharedPreferences mPrefs; + private ArrayList mListeners; public EnvironmentsManager(@NonNull Context context) { mContext = context; mApplicationDelegate = ((WidgetManagerDelegate)context); mDownloadManager = mApplicationDelegate.getServicesProvider().getDownloadsManager(); mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext); + mListeners = new ArrayList<>(); + } + + public void addListener(@NonNull EnvironmentListener listener) { + if (!mListeners.contains(listener)) { + mListeners.add(listener); + } + } + + public void removeListener(@NonNull EnvironmentListener listener) { + if (mListeners.contains(listener)) { + mListeners.remove(listener); + } } public void start() { @@ -46,11 +67,15 @@ public void stop() { public void setOrDownloadEnvironment(@NonNull String envId) { if (EnvironmentUtils.isBuiltinEnvironment(mContext, envId)) { + SettingsStore.getInstance(mContext).setEnvironment(envId); + mListeners.forEach(environmentListener -> environmentListener.onEnvironmentSetSuccess(envId)); mApplicationDelegate.updateEnvironment(); } else { if (EnvironmentUtils.isExternalEnvReady(mContext, envId)) { // If the environment is ready, call native to update + SettingsStore.getInstance(mContext).setEnvironment(envId); + mListeners.forEach(environmentListener -> environmentListener.onEnvironmentSetSuccess(envId)); mApplicationDelegate.updateEnvironment(); } else { @@ -98,7 +123,29 @@ private void downloadEnvironment(@NonNull String envId) { if (!isDownloading) { // If the env is not being downloaded, start downloading it DownloadJob job = DownloadJob.create(environment.getPayload()); - mDownloadManager.startDownload(job); + @SettingsStore.Storage int storage = SettingsStore.getInstance(mContext).getDownloadsStorage(); + if (storage == SettingsStore.EXTERNAL && + !mApplicationDelegate.isPermissionGranted(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + mApplicationDelegate.requestPermission( + job.getUri(), + android.Manifest.permission.WRITE_EXTERNAL_STORAGE, + new GeckoSession.PermissionDelegate.Callback() { + @Override + public void grant() { + mDownloadManager.startDownload(job); + } + + @Override + public void reject() { + mListeners.forEach(listener -> listener.onEnvironmentSetError( + mContext.getString(R.string.environment_download_permission_error_body) + )); + } + }); + + } else { + mDownloadManager.startDownload(job); + } } } } @@ -130,17 +177,23 @@ public void onUnzipFinish(@NonNull String zipFile, @NonNull String outputPath) { file.delete(); // the environment is ready, call native to update the current env. + SettingsStore.getInstance(mContext).setEnvironment(env.getValue()); + mListeners.forEach(environmentListener -> environmentListener.onEnvironmentSetSuccess(env.getValue())); mApplicationDelegate.updateEnvironment(); } @Override public void onUnzipCancelled(@NonNull String zipFile) { - + mListeners.forEach(listener -> listener.onEnvironmentSetError( + mContext.getString(R.string.environment_download_unzip_error_body) + )); } @Override public void onUnzipError(@NonNull String zipFile, @Nullable String error) { - + mListeners.forEach(listener -> listener.onEnvironmentSetError( + mContext.getString(R.string.environment_download_unzip_error_body) + )); } }); String zipOutputPath = EnvironmentUtils.getEnvPath(mContext, env.getValue()); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 87c1c0358..ca0695aca 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1832,4 +1832,14 @@ the Select` button. When clicked it closes all the previously selected tabs --> Unknown error + + Permission to write the external storage is required to download the environment. + + + An error occurred while unzipping the environment. + + + Environment error +