From a3e66687035d035f6701acf2886bd066de16ecf2 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 15 Oct 2018 12:47:48 +0200 Subject: [PATCH] Support added for loading local files through file:// handler (#605) --- .../mozilla/vrbrowser/PermissionDelegate.java | 57 ++++++++++++++++- .../org/mozilla/vrbrowser/SessionStore.java | 39 ++++++++++-- .../mozilla/vrbrowser/VRBrowserActivity.java | 44 +++++++++++-- .../vrbrowser/WidgetManagerDelegate.java | 8 ++- .../vrbrowser/ui/CrashDialogWidget.java | 43 ++++++++++--- .../vrbrowser/ui/DeveloperOptionsWidget.java | 14 ++++- .../mozilla/vrbrowser/ui/KeyboardWidget.java | 5 +- .../vrbrowser/ui/NavigationBarWidget.java | 38 +++++++++++- .../vrbrowser/ui/PermissionWidget.java | 27 ++++++-- .../vrbrowser/ui/RestartDialogWidget.java | 2 +- .../mozilla/vrbrowser/ui/SettingsWidget.java | 54 ++++++++-------- .../org/mozilla/vrbrowser/ui/TrayWidget.java | 60 ++++++++++-------- .../org/mozilla/vrbrowser/ui/UIWidget.java | 61 +++++-------------- .../ui/prompts/ChoicePromptWidget.java | 4 +- .../mozilla/vrbrowser/utils/ValueHolder.java | 19 ++++++ app/src/main/AndroidManifest.xml | 7 ++- app/src/main/res/values/strings.xml | 2 + 17 files changed, 345 insertions(+), 139 deletions(-) create mode 100644 app/src/common/shared/org/mozilla/vrbrowser/utils/ValueHolder.java diff --git a/app/src/common/shared/org/mozilla/vrbrowser/PermissionDelegate.java b/app/src/common/shared/org/mozilla/vrbrowser/PermissionDelegate.java index 9e48d0ba9..fd87aee14 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/PermissionDelegate.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/PermissionDelegate.java @@ -1,8 +1,10 @@ package org.mozilla.vrbrowser; +import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; +import android.support.annotation.NonNull; import android.util.Log; import org.mozilla.geckoview.GeckoSession; @@ -54,7 +56,7 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in } } - private void handleContentPermission(final String aUri, final PermissionWidget.PermissionType aType, final Callback aCallback) { + public void handlePermission(final String aUri, final PermissionWidget.PermissionType aType, final Callback aCallback) { if (mPermissionWidget == null) { mPermissionWidget = new PermissionWidget(mContext); mPermissionWidget.getPlacement().parentHandle = mParentWidgetHandle; @@ -122,7 +124,7 @@ public void onContentPermissionRequest(GeckoSession aSession, String aUri, int a return; } - handleContentPermission(aUri, type, callback); + handlePermission(aUri, type, callback); } @Override @@ -155,6 +157,55 @@ public void reject() { } }; - handleContentPermission(aUri, type, callback); + handlePermission(aUri, type, callback); + } + + public boolean isPermissionGranted(@NonNull String permission) { + return mContext.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED; + } + + // Handle app permissions that Gecko doesn't handle itself yet + public void onAppPermissionRequest(final GeckoSession aSession, String aUri, final String permission, final Callback callback) { + Log.d(LOGTAG, "onAppPermissionRequest: " + aUri); + + // If the permission is already granted we just grant + if (mContext.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { + + // Check if we support a rationale for that permission + PermissionWidget.PermissionType type = null; + if (permission.equals(Manifest.permission.READ_EXTERNAL_STORAGE)) { + type = PermissionWidget.PermissionType.ReadExternalStorage; + } + + if (type != null) { + // Show rationale + handlePermission(mContext.getString(R.string.app_name), type, new Callback() { + @Override + public void grant() { + onAndroidPermissionsRequest(aSession, new String[]{permission}, callback); + } + + @Override + public void reject() { + if (callback != null) { + callback.reject(); + } + } + }); + + } else { + // Let Android handle the permission request + onAndroidPermissionsRequest(aSession, new String[]{permission}, callback); + } + + } else { + if (callback != null) { + callback.grant(); + } + } + } + + public boolean isPermissionDialogVisible() { + return mPermissionWidget != null && mPermissionWidget.isVisible(); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/SessionStore.java b/app/src/common/shared/org/mozilla/vrbrowser/SessionStore.java index 4d2365072..8a96d11de 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/SessionStore.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/SessionStore.java @@ -14,16 +14,30 @@ import android.view.inputmethod.CursorAnchorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; + import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoProfile; -import org.mozilla.geckoview.*; +import org.mozilla.geckoview.GeckoResult; +import org.mozilla.geckoview.GeckoRuntime; +import org.mozilla.geckoview.GeckoRuntimeSettings; +import org.mozilla.geckoview.GeckoSession; +import org.mozilla.geckoview.GeckoSessionSettings; import org.mozilla.vrbrowser.telemetry.TelemetryWrapper; +import org.mozilla.vrbrowser.utils.ValueHolder; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.util.*; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; public class SessionStore implements GeckoSession.NavigationDelegate, GeckoSession.ProgressDelegate, GeckoSession.ContentDelegate, GeckoSession.TextInputDelegate, GeckoSession.TrackingProtectionDelegate, @@ -787,14 +801,31 @@ public GeckoResult onLoadRequest(@NonNull GeckoSession aSession, @NonNull String aUri, @TargetWindow int target, @LoadRequestFlags int flags) { - GeckoResult result = new GeckoResult<>(); + final GeckoResult result = new GeckoResult<>(); if (aUri.equalsIgnoreCase(PRIVATE_BROWSING_URI)) { switchPrivateMode(); result.complete(true); } else { - result.complete(false); + final ValueHolder count = new ValueHolder(new Integer(0)); + final ValueHolder listenersResult = new ValueHolder(new Boolean(false)); + for (GeckoSession.NavigationDelegate listener: mNavigationListeners) { + GeckoResult listenerResult = listener.onLoadRequest(aSession, aUri, target, flags); + listenerResult.then(new GeckoResult.OnValueListener() { + @Nullable + @Override + public GeckoResult onValue(@Nullable Boolean value) { + listenersResult.setValue(listenersResult.getValue().booleanValue() | value); + if (count.getValue() == mNavigationListeners.size() - 1) { + result.complete(listenersResult.getValue()); + } + count.setValue(count.getValue().intValue() + 1); + + return null; + } + }); + } } return result; diff --git a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java index a1f71e8c7..15365e5c1 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java @@ -17,21 +17,31 @@ import android.os.Handler; import android.os.Looper; import android.support.annotation.Keep; +import android.support.annotation.NonNull; import android.util.Log; import android.view.KeyEvent; -import android.view.MotionEvent; import android.view.View; import android.view.ViewTreeObserver; import android.widget.FrameLayout; + import org.mozilla.gecko.GeckoVRManager; import org.mozilla.gecko.util.ThreadUtils; import org.mozilla.geckoview.CrashReporter; import org.mozilla.geckoview.GeckoRuntime; +import org.mozilla.geckoview.GeckoSession; import org.mozilla.vrbrowser.audio.AudioEngine; import org.mozilla.vrbrowser.audio.VRAudioTheme; import org.mozilla.vrbrowser.search.SearchEngine; import org.mozilla.vrbrowser.telemetry.TelemetryWrapper; -import org.mozilla.vrbrowser.ui.*; +import org.mozilla.vrbrowser.ui.BrowserWidget; +import org.mozilla.vrbrowser.ui.CrashDialogWidget; +import org.mozilla.vrbrowser.ui.KeyboardWidget; +import org.mozilla.vrbrowser.ui.NavigationBarWidget; +import org.mozilla.vrbrowser.ui.OffscreenDisplay; +import org.mozilla.vrbrowser.ui.RootWidget; +import org.mozilla.vrbrowser.ui.TopBarWidget; +import org.mozilla.vrbrowser.ui.TrayWidget; +import org.mozilla.vrbrowser.ui.UIWidget; import java.io.IOException; import java.net.URISyntaxException; @@ -95,6 +105,7 @@ public void run() { LinkedList mBackHandlers; private boolean mIsPresentingImmersive = false; private Thread mUiThread; + private boolean isDimmed; @Override protected void onCreate(Bundle savedInstanceState) { @@ -114,6 +125,7 @@ protected void onCreate(Bundle savedInstanceState) { intentFilter.addAction(CrashReporterService.CRASH_ACTION); registerReceiver(mCrashReceiver, intentFilter, getString(R.string.app_permission_name), null); + isDimmed = false; mLastGesture = NoGesture; super.onCreate(savedInstanceState); @@ -785,9 +797,12 @@ public void popBackHandler(Runnable aRunnable) { @Override public void fadeOutWorld() { - if (SessionStore.get().isCurrentSessionPrivate() ^ + if (!isDimmed && (SessionStore.get().isCurrentSessionPrivate() ^ mNavigationBar.isInFocusMode() ^ - mTray.isSettingsDialogOpened()) { + mTray.isSettingsDialogOpened() ^ + mPermissionDelegate.isPermissionDialogVisible() ^ + (mCrashDialog != null && mCrashDialog.isVisible()))) { + isDimmed = true; queueRunnable(new Runnable() { @Override public void run() { @@ -799,9 +814,12 @@ public void run() { @Override public void fadeInWorld() { - if ((!SessionStore.get().isCurrentSessionPrivate() && + if (isDimmed && (!SessionStore.get().isCurrentSessionPrivate() && !mNavigationBar.isInFocusMode() && - !mTray.isSettingsDialogOpened())) { + !mTray.isSettingsDialogOpened() && + !mPermissionDelegate.isPermissionDialogVisible() && + !(mCrashDialog != null && mCrashDialog.isVisible()))) { + isDimmed = false; queueRunnable(new Runnable() { @Override public void run() { @@ -851,6 +869,20 @@ public void run() { }); } + @Override + public boolean isPermissionGranted(@NonNull String permission) { + return mPermissionDelegate.isPermissionGranted(permission); + } + + @Override + public void requestPermission(@NonNull String uri, @NonNull String permission, GeckoSession.PermissionDelegate.Callback aCallback) { + mPermissionDelegate.onAppPermissionRequest( + SessionStore.get().getCurrentSession(), + uri, + permission, + aCallback); + } + @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/WidgetManagerDelegate.java b/app/src/common/shared/org/mozilla/vrbrowser/WidgetManagerDelegate.java index 1cac1d169..f8eec930a 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/WidgetManagerDelegate.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/WidgetManagerDelegate.java @@ -3,6 +3,8 @@ import android.support.annotation.NonNull; import android.view.View; +import org.mozilla.geckoview.GeckoSession; + public interface WidgetManagerDelegate { interface UpdateListener { void onWidgetUpdate(Widget aWidget); @@ -30,8 +32,10 @@ interface FocusChangeListener { void keyboardDismissed(); void updateEnvironment(); void updatePointerColor(); - void addPermissionListener(@NonNull PermissionListener aListener); - void removePermissionListener(@NonNull PermissionListener aListener); void addFocusChangeListener(@NonNull FocusChangeListener aListener); void removeFocusChangeListener(@NonNull FocusChangeListener aListener); + void addPermissionListener(PermissionListener aListener); + void removePermissionListener(PermissionListener aListener); + boolean isPermissionGranted(@NonNull String permission); + void requestPermission(@NonNull String uri, @NonNull String permission, GeckoSession.PermissionDelegate.Callback aCallback); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/CrashDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/CrashDialogWidget.java index b0aa2681e..83d0fb1a8 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/CrashDialogWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/CrashDialogWidget.java @@ -15,10 +15,11 @@ import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.SessionStore; import org.mozilla.vrbrowser.SettingsStore; +import org.mozilla.vrbrowser.WidgetManagerDelegate; import org.mozilla.vrbrowser.WidgetPlacement; import org.mozilla.vrbrowser.audio.AudioEngine; -public class CrashDialogWidget extends UIWidget { +public class CrashDialogWidget extends UIWidget implements WidgetManagerDelegate.FocusChangeListener { private static final String LOGTAG = "VRB"; public interface CrashDialogDelegate { @@ -50,6 +51,8 @@ public CrashDialogWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { private void initialize(Context aContext) { inflate(aContext, R.layout.crash_dialog, this); + mWidgetManager.addFocusChangeListener(this); + mLearnMoreButton = findViewById(R.id.learnMoreButton); mDontSendButton = findViewById(R.id.dontSendButton); mSendDataButton = findViewById(R.id.sendDataButton); @@ -69,7 +72,7 @@ public void onClick(View view) { SessionStore.get().loadUri(getContext().getString(R.string.crash_dialog_learn_more_url)); - hide(); + onDismiss(); } }); mDontSendButton.setOnClickListener(new OnClickListener() { @@ -79,7 +82,7 @@ public void onClick(View view) { mAudio.playSound(AudioEngine.Sound.CLICK); } - hide(); + onDismiss(); } }); mSendDataButton.setOnClickListener(new OnClickListener() { @@ -89,13 +92,13 @@ public void onClick(View view) { mAudio.playSound(AudioEngine.Sound.CLICK); } + hide(); + if(mCrashDialogDelegate != null) { mCrashDialogDelegate.onSendData(); } SettingsStore.getInstance(getContext()).setCrashReportingEnabled(mSendDataCheckBox.isChecked()); - - hide(); } }); @@ -113,6 +116,13 @@ public void onCheckedChanged(CompoundButton compoundButton, boolean b) { mAudio = AudioEngine.fromContext(aContext); } + @Override + public void releaseWidget() { + mWidgetManager.removeFocusChangeListener(this); + + super.releaseWidget(); + } + @Override protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { aPlacement.visible = false; @@ -127,13 +137,28 @@ protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { } @Override - protected void onBackButton() { - hide(); - if (mDelegate != null) - mDelegate.onWidgetClosed(getHandle()); + public void show() { + super.show(); + + mWidgetManager.fadeOutWorld(); + } + + @Override + public void hide() { + super.hide(); + + mWidgetManager.fadeInWorld(); } public void setCrashDialogDelegate(CrashDialogDelegate aDelegate) { mCrashDialogDelegate = aDelegate; } + + // WidgetManagerDelegate.FocusChangeListener + @Override + public void onGlobalFocusChanged(View oldFocus, View newFocus) { + if (oldFocus == this && isVisible()) { + onDismiss(); + } + } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/DeveloperOptionsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/DeveloperOptionsWidget.java index 354672cbd..11874f2ad 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/DeveloperOptionsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/DeveloperOptionsWidget.java @@ -10,7 +10,6 @@ import android.view.View; import android.widget.CompoundButton; import android.widget.RadioGroup; -import android.widget.TextView; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.SessionStore; @@ -78,7 +77,7 @@ public void onClick(View view) { mAudio.playSound(AudioEngine.Sound.CLICK); } - onBackButton(); + onDismiss(); } }); @@ -175,11 +174,21 @@ private void showRestartDialog() { if (widget == null) { widget = createChild(RestartDialogWidget.class, false); mRestartDialogHandle = widget.getHandle(); + widget.setDelegate(new Delegate() { + @Override + public void onDismiss() { + onRestartDialogDismissed(); + } + }); } widget.show(); } + private void onRestartDialogDismissed() { + show(); + } + private SwitchSetting.OnCheckedChangeListener mRemoteDebuggingListener = new SwitchSetting.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean value, boolean doApply) { @@ -198,6 +207,7 @@ public void onCheckedChanged(CompoundButton compoundButton, boolean value, boole @Override public void onCheckedChanged(CompoundButton compoundButton, boolean value, boolean doApply) { setEnvOverride(value); + showRestartDialog(); } }; diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/KeyboardWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/KeyboardWidget.java index fd2169ddd..66914e437 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/KeyboardWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/KeyboardWidget.java @@ -27,7 +27,6 @@ import org.mozilla.geckoview.GeckoSession; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.SessionStore; -import org.mozilla.vrbrowser.Widget; import org.mozilla.vrbrowser.WidgetManagerDelegate; import org.mozilla.vrbrowser.WidgetPlacement; import org.mozilla.vrbrowser.telemetry.TelemetryWrapper; @@ -173,7 +172,7 @@ public void onClick(View view) { mBackHandler = new Runnable() { @Override public void run() { - onBackButton(); + onDismiss(); } }; @@ -257,7 +256,7 @@ public void dismiss() { mPopupKeyboardLayer.setVisibility(View.GONE); } - protected void onBackButton() { + protected void onDismiss() { dismiss(); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/NavigationBarWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/NavigationBarWidget.java index 7fe501013..ec97e1d52 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/NavigationBarWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/NavigationBarWidget.java @@ -6,6 +6,7 @@ package org.mozilla.vrbrowser.ui; import android.content.Context; +import android.net.Uri; import android.support.annotation.NonNull; import android.util.AttributeSet; import android.util.Log; @@ -404,12 +405,45 @@ public void onCanGoForward(GeckoSession aSession, boolean canGoForward) { } @Override - public GeckoResult onLoadRequest(GeckoSession aSession, String aUri, int target, int flags) { + public GeckoResult onLoadRequest(GeckoSession aSession, final String aUri, int target, int flags) { if (mURLBar != null) { Log.d(LOGTAG, "Got onLoadUri"); mURLBar.setURL(aUri); } - return null; + + final GeckoResult result = new GeckoResult<>(); + if (aUri != null) { + Uri uri = Uri.parse(aUri); + if (uri.getScheme().equals("file")) { + if (!mWidgetManager.isPermissionGranted(android.Manifest.permission.READ_EXTERNAL_STORAGE)) { + mWidgetManager.requestPermission( + aUri, + android.Manifest.permission.READ_EXTERNAL_STORAGE, + new GeckoSession.PermissionDelegate.Callback() { + @Override + public void grant() { + result.complete(false); + } + + @Override + public void reject() { + result.complete(false); + } + }); + + } else { + result.complete(false); + } + + } else { + result.complete(false); + } + + } else { + result.complete(false); + } + + return result; } // Progress Listener diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/PermissionWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/PermissionWidget.java index 70c3d6348..7ac333d8e 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/PermissionWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/PermissionWidget.java @@ -43,7 +43,8 @@ public enum PermissionType { Microphone, CameraAndMicrophone, Location, - Notification + Notification, + ReadExternalStorage } public PermissionWidget(Context aContext) { @@ -108,6 +109,20 @@ protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { aPlacement.anchorY = 0.5f; } + @Override + public void show() { + super.show(); + + mWidgetManager.fadeOutWorld(); + } + + @Override + public void hide() { + super.hide(); + + mWidgetManager.fadeInWorld(); + } + public void showPrompt(String aUri, PermissionType aType, GeckoSession.PermissionDelegate.Callback aCallback) { int messageId; int iconId; @@ -132,6 +147,10 @@ public void showPrompt(String aUri, PermissionType aType, GeckoSession.Permissio messageId = R.string.permission_notification; iconId = R.drawable.ic_icon_dialog_notification; break; + case ReadExternalStorage: + messageId = R.string.permission_read_external_storage; + iconId = R.drawable.ic_icon_dialog_notification; + break; default: Log.e(LOGTAG, "Unimplemented permission type: " + aType); aCallback.reject(); @@ -175,14 +194,14 @@ private void handlePermissionResult(boolean aGranted) { } mPermissionCallback = null; - hide(); + onDismiss(); } // WidgetManagerDelegate.FocusChangeListener @Override public void onGlobalFocusChanged(View oldFocus, View newFocus) { - if (oldFocus == this) { - hide(); + if (oldFocus == this && isVisible()) { + onDismiss(); } } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/RestartDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/RestartDialogWidget.java index 30febb606..64c010608 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/RestartDialogWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/RestartDialogWidget.java @@ -67,7 +67,7 @@ public void onClick(View view) { mAudio.playSound(AudioEngine.Sound.CLICK); } - onBackButton(); + onDismiss(); } }); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/SettingsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/SettingsWidget.java index b0f1381a3..a48084a4b 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/SettingsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/SettingsWidget.java @@ -28,12 +28,11 @@ import java.util.Calendar; import java.util.GregorianCalendar; -public class SettingsWidget extends UIWidget { +public class SettingsWidget extends UIWidget implements WidgetManagerDelegate.FocusChangeListener { private static final String LOGTAG = "VRB"; private AudioEngine mAudio; - private int mRestartDialogHandle = -1; private int mDeveloperOptionsDialogHandle = -1; private TextView mBuildText; @@ -77,6 +76,8 @@ public SettingsWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { private void initialize(Context aContext) { inflate(aContext, R.layout.settings, this); + mWidgetManager.addFocusChangeListener(this); + ImageButton cancelButton = findViewById(R.id.settingsCancelButton); cancelButton.setOnClickListener(new OnClickListener() { @@ -86,7 +87,7 @@ public void onClick(View v) { mAudio.playSound(AudioEngine.Sound.CLICK); } - onBackButton(); + onDismiss(); } }); @@ -189,6 +190,8 @@ public void onClick(View view) { @Override public void releaseWidget() { + mWidgetManager.removeFocusChangeListener(this); + super.releaseWidget(); } @@ -297,18 +300,6 @@ private String versionCodeToDate(final int aVersionCode) { return formatted; } - private void showRestartDialog() { - UIWidget widget = getChild(mRestartDialogHandle); - if (widget == null) { - widget = createChild(RestartDialogWidget.class, false); - mRestartDialogHandle = widget.getHandle(); - } - - widget.show(); - - hide(); - } - private void showDeveloperOptionsDialog() { hide(); @@ -316,26 +307,37 @@ private void showDeveloperOptionsDialog() { if (widget == null) { widget = createChild(DeveloperOptionsWidget.class, false); mDeveloperOptionsDialogHandle = widget.getHandle(); + widget.setDelegate(new Delegate() { + @Override + public void onDismiss() { + onDeveloperOptionsDialogDismissed(); + } + }); } widget.show(); } - @Override - public void toggle() { - super.toggle(); - - if (!isVisible()) - mWidgetManager.fadeInWorld(); - else - mWidgetManager.fadeOutWorld(); + private void onDeveloperOptionsDialogDismissed() { + show(); + mWidgetManager.fadeInWorld(); } + // WindowManagerDelegate.FocusChangeListener @Override - protected void onBackButton() { - super.onBackButton(); + public void onGlobalFocusChanged(View oldFocus, View newFocus) { + boolean dismiss = false; + UIWidget widget = getChild(mDeveloperOptionsDialogHandle); + if (widget != null && oldFocus == widget && widget.isVisible()) { + dismiss = true; - mWidgetManager.fadeInWorld(); + } else if (oldFocus == this && isVisible()) { + dismiss = true; + } + + if (dismiss) { + onDismiss(); + } } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/TrayWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/TrayWidget.java index 8631881df..22ecb5d0e 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/TrayWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/TrayWidget.java @@ -8,16 +8,15 @@ import android.content.Context; import android.util.AttributeSet; import android.view.View; + import org.mozilla.geckoview.GeckoSession; import org.mozilla.geckoview.GeckoSessionSettings; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.SessionStore; -import org.mozilla.vrbrowser.WidgetManagerDelegate; import org.mozilla.vrbrowser.WidgetPlacement; import org.mozilla.vrbrowser.audio.AudioEngine; -public class TrayWidget extends UIWidget implements SessionStore.SessionChangeListener, - WidgetManagerDelegate.FocusChangeListener { +public class TrayWidget extends UIWidget implements SessionStore.SessionChangeListener { private static final String LOGTAG = "VRB"; @@ -46,18 +45,17 @@ public TrayWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { private void initialize(Context aContext) { inflate(aContext, R.layout.tray, this); - mWidgetManager.addFocusChangeListener(this); - mHelpButton = findViewById(R.id.helpButton); mHelpButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - view.requestFocusFromTouch(); if (mAudio != null) { mAudio.playSound(AudioEngine.Sound.CLICK); } onHelpButtonClicked(); + + view.requestFocusFromTouch(); } }); @@ -65,12 +63,13 @@ public void onClick(View view) { mPrivateButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - view.requestFocusFromTouch(); if (mAudio != null) { mAudio.playSound(AudioEngine.Sound.CLICK); } SessionStore.get().switchPrivateMode(); + + view.requestFocusFromTouch(); } }); @@ -78,14 +77,14 @@ public void onClick(View view) { mSettingsButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - if (!isChildVisible(mSettingsDialogHandle)) - view.requestFocusFromTouch(); - if (mAudio != null) { mAudio.playSound(AudioEngine.Sound.CLICK); } - showSettingsDialog(); + toggleSettingsDialog(); + + if (isSettingsDialogOpened()) + view.requestFocusFromTouch(); } }); @@ -115,7 +114,6 @@ protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { @Override public void releaseWidget() { - mWidgetManager.removeFocusChangeListener(this); SessionStore.get().removeSessionChangeListener(this); super.releaseWidget(); @@ -152,14 +150,31 @@ public void onCurrentSessionChange(GeckoSession aSession, int aId) { mIsLastSessionPrivate = isPrivateMode; } - private void showSettingsDialog() { + private void toggleSettingsDialog() { UIWidget widget = getChild(mSettingsDialogHandle); if (widget == null) { widget = createChild(SettingsWidget.class, false); mSettingsDialogHandle = widget.getHandle(); + widget.setDelegate(new Delegate() { + @Override + public void onDismiss() { + onSettingsDialogDismissed(); + } + }); + } + + if (widget.isVisible()) { + widget.hide(); + mWidgetManager.fadeInWorld(); + + } else { + widget.show(); + mWidgetManager.fadeOutWorld(); } + } - widget.toggle(); + private void onSettingsDialogDismissed() { + mWidgetManager.fadeInWorld(); } @Override @@ -180,7 +195,11 @@ public void hide() { public boolean isSettingsDialogOpened() { - return isChildVisible(mSettingsDialogHandle); + UIWidget widget = getChild(mSettingsDialogHandle); + if (widget != null) { + return widget.isVisible(); + } + return false; } private void onHelpButtonClicked() { @@ -193,15 +212,4 @@ private void onHelpButtonClicked() { SessionStore.get().loadUri(getContext().getString(R.string.help_url)); } - - // WindowManagerDelegate.FocusChangeListener - @Override - public void onGlobalFocusChanged(View oldFocus, View newFocus) { - if (isSettingsDialogOpened()) { - UIWidget child = getChild(mSettingsDialogHandle); - if (child != null) { - child.toggle(); - } - } - } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/UIWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/UIWidget.java index 7abb81b21..4d0f1eacf 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/UIWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/UIWidget.java @@ -27,6 +27,10 @@ public abstract class UIWidget extends FrameLayout implements Widget { private static final String LOGTAG = "VRB"; + public interface Delegate { + void onDismiss(); + } + private UISurfaceTextureRenderer mRenderer; private SurfaceTexture mTexture; protected int mHandle; @@ -36,11 +40,7 @@ public abstract class UIWidget extends FrameLayout implements Widget { protected int mInitialHeight; protected Runnable mBackHandler; protected HashMap mChildren; - protected UIWidgetDelegate mDelegate; - - public interface UIWidgetDelegate { - void onWidgetClosed(int aHandle); - } + protected Delegate mDelegate; public UIWidget(Context aContext) { super(aContext); @@ -69,11 +69,12 @@ private void initialize() { mBackHandler = new Runnable() { @Override public void run() { - onBackButton(); + onDismiss(); } }; } + protected abstract void initializeWidgetPlacement(WidgetPlacement aPlacement); @Override @@ -201,7 +202,7 @@ public ViewParent invalidateChildInParent(int[] aLocation, Rect aDirty) { return parent; } - public void setDelegate(UIWidgetDelegate aDelegate) { + public void setDelegate(Delegate aDelegate) { mDelegate = aDelegate; } @@ -250,15 +251,6 @@ public boolean isVisible() { return mWidgetPlacement.visible; } - public boolean isChildVisible(int aHandle) { - UIWidget widget = getChild(aHandle); - if (widget != null) { - return widget.isVisible(); - } - - return false; - } - protected T createChild(@NonNull Class aChildClassName) { return createChild(aChildClassName, true); } @@ -267,15 +259,9 @@ protected T createChild(@NonNull Class aChildClassName, try { Constructor constructor = aChildClassName.getConstructor(new Class[] { Context.class }); UIWidget child = (UIWidget) constructor.newInstance(new Object[] { getContext() }); - if (inheritPlacement) + if (inheritPlacement) { child.getPlacement().parentHandle = getHandle(); - child.setDelegate(new UIWidgetDelegate() { - - @Override - public void onWidgetClosed(int aHandle) { - onChildClosed(aHandle); - } - }); + } mChildren.put(child.mHandle, child); return aChildClassName.cast(child); @@ -292,29 +278,12 @@ protected T getChild(int aChildId) { return (T) mChildren.get(aChildId); } - protected void removeChild(int aChildId) { - UIWidget child = mChildren.get(aChildId); - if (child != null) { - child.hide(); - mChildren.remove(aChildId); - child.releaseWidget(); - } - } - - protected void removeAllChildren() { - for (UIWidget child : mChildren.values()) { - removeChild(child.mHandle); - } - mChildren.clear(); - } - - protected void onChildClosed(int aHandle) { - show(); - } - protected void onBackButton() { + protected void onDismiss() { hide(); - if (mDelegate != null) - mDelegate.onWidgetClosed(getHandle()); + + if (mDelegate != null) { + mDelegate.onDismiss(); + } } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/prompts/ChoicePromptWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/prompts/ChoicePromptWidget.java index 080486fe8..8b9130274 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/prompts/ChoicePromptWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/prompts/ChoicePromptWidget.java @@ -171,7 +171,7 @@ public void releaseWidget() { } @Override - protected void onBackButton() { + protected void onDismiss() { hide(); if (mPromptDelegate != null) { @@ -401,7 +401,7 @@ public boolean onHover(View view, MotionEvent motionEvent) { // WidgetManagerDelegate.FocusChangeListener @Override public void onGlobalFocusChanged(View oldFocus, View newFocus) { - if (oldFocus == this) { + if (oldFocus == this && isVisible()) { if (mPromptDelegate != null) { mPromptDelegate.onDismissed(getDefaultChoices(mListItems)); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/utils/ValueHolder.java b/app/src/common/shared/org/mozilla/vrbrowser/utils/ValueHolder.java new file mode 100644 index 000000000..2c12f7af2 --- /dev/null +++ b/app/src/common/shared/org/mozilla/vrbrowser/utils/ValueHolder.java @@ -0,0 +1,19 @@ +package org.mozilla.vrbrowser.utils; + +public class ValueHolder { + + private T value; + + public ValueHolder(T aValue) { + value = aValue; + } + + public T getValue() { + return value; + } + + public void setValue(Object newValue) { + value = (T) newValue; + } + +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8fe28a21a..b8bc09f78 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,11 +6,12 @@ + + + - - + android:protectionLevel="signature"/> Will you allow %1$s to access your location? Will you allow %1$s to send notifications? + + Will you allow %1$s to read your external storage? Speak now version %1$s Crash Reporting