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

Support added for loading local files through file:// handler #605

Merged
merged 1 commit into from
Oct 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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