Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
Support added for loading local files through file:// handler (#605)
Browse files Browse the repository at this point in the history
  • Loading branch information
keianhzo authored Oct 15, 2018
1 parent 73cba99 commit a3e6668
Show file tree
Hide file tree
Showing 17 changed files with 345 additions and 139 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -122,7 +124,7 @@ public void onContentPermissionRequest(GeckoSession aSession, String aUri, int a
return;
}

handleContentPermission(aUri, type, callback);
handlePermission(aUri, type, callback);
}

@Override
Expand Down Expand Up @@ -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();
}
}
39 changes: 35 additions & 4 deletions app/src/common/shared/org/mozilla/vrbrowser/SessionStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -787,14 +801,31 @@ public GeckoResult<Boolean> onLoadRequest(@NonNull GeckoSession aSession,
@NonNull String aUri,
@TargetWindow int target,
@LoadRequestFlags int flags) {
GeckoResult<Boolean> result = new GeckoResult<>();

final GeckoResult<Boolean> result = new GeckoResult<>();
if (aUri.equalsIgnoreCase(PRIVATE_BROWSING_URI)) {
switchPrivateMode();
result.complete(true);

} else {
result.complete(false);
final ValueHolder<Integer> count = new ValueHolder(new Integer(0));
final ValueHolder<Boolean> listenersResult = new ValueHolder(new Boolean(false));
for (GeckoSession.NavigationDelegate listener: mNavigationListeners) {
GeckoResult<Boolean> listenerResult = listener.onLoadRequest(aSession, aUri, target, flags);
listenerResult.then(new GeckoResult.OnValueListener<Boolean, Object>() {
@Nullable
@Override
public GeckoResult<Object> 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;
Expand Down
44 changes: 38 additions & 6 deletions app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -95,6 +105,7 @@ public void run() {
LinkedList<Runnable> mBackHandlers;
private boolean mIsPresentingImmersive = false;
private Thread mUiThread;
private boolean isDimmed;

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand All @@ -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);

Expand Down Expand Up @@ -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() {
Expand All @@ -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() {
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand All @@ -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() {
Expand All @@ -79,7 +82,7 @@ public void onClick(View view) {
mAudio.playSound(AudioEngine.Sound.CLICK);
}

hide();
onDismiss();
}
});
mSendDataButton.setOnClickListener(new OnClickListener() {
Expand All @@ -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();
}
});

Expand All @@ -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;
Expand All @@ -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();
}
}
}
Loading

0 comments on commit a3e6668

Please sign in to comment.