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

Commit

Permalink
Updated Pop-up blocking flow (#2097)
Browse files Browse the repository at this point in the history
* Updated Pop-ups blocking flow

* Fixed url bar icons

* Added delay when opening allowed sessions
  • Loading branch information
keianhzo authored and bluemarvin committed Oct 30, 2019
1 parent 0a5c095 commit a34be57
Show file tree
Hide file tree
Showing 22 changed files with 419 additions and 158 deletions.
206 changes: 145 additions & 61 deletions app/src/common/shared/org/mozilla/vrbrowser/browser/PromptDelegate.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import android.app.Application;
import android.content.Context;
import android.util.Pair;
import android.util.SparseArray;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
Expand All @@ -19,7 +21,6 @@
import org.mozilla.vrbrowser.ui.widgets.UIWidget;
import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement;
import org.mozilla.vrbrowser.ui.widgets.WindowWidget;
import org.mozilla.vrbrowser.ui.widgets.dialogs.BaseAppDialogWidget;
import org.mozilla.vrbrowser.ui.widgets.dialogs.PopUpBlockDialogWidget;
import org.mozilla.vrbrowser.ui.widgets.prompts.AlertPromptWidget;
import org.mozilla.vrbrowser.ui.widgets.prompts.AuthPromptWidget;
Expand All @@ -31,10 +32,17 @@
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

public class PromptDelegate implements GeckoSession.PromptDelegate, WindowWidget.WindowListener {
public class PromptDelegate implements
GeckoSession.PromptDelegate,
WindowWidget.WindowListener,
GeckoSession.NavigationDelegate {

public interface PopUpDelegate {
void onPopUpAvailable();
void onPopUpsCleared();
}

private PromptWidget mPrompt;
private PopUpBlockDialogWidget mPopUpPrompt;
Expand All @@ -43,6 +51,7 @@ public class PromptDelegate implements GeckoSession.PromptDelegate, WindowWidget
private List<PopUpSite> mAllowedPopUpSites;
private PopUpsViewModel mViewModel;
private AppExecutors mExecutors;
private PopUpDelegate mPopupDelegate;

public PromptDelegate(@NonNull Context context) {
mContext = context;
Expand All @@ -59,16 +68,55 @@ public void attachToWindow(@NonNull WindowWidget window) {

mAttachedWindow = window;
mAttachedWindow.addWindowListener(this);
mAttachedWindow.getSession().setPromptDelegate(this);
mViewModel.getAll().observeForever(mObserver);

if (getSession() != null) {
setUpSession(getSession());
}
}

public void detachFromWindow() {
if (getSession() != null) {
cleanSession(getSession());
}

if (mAttachedWindow != null) {
mAttachedWindow.removeWindowListener(this);
mAttachedWindow = null;
}
mViewModel.getAll().removeObserver(mObserver);

clearPopUps();
}

private Session getSession() {
if (mAttachedWindow != null) {
return mAttachedWindow.getSession();
}
return null;
}

private void setUpSession(@NonNull Session aSession) {
aSession.setPromptDelegate(this);
aSession.addNavigationListener(this);
}

private void cleanSession(@NonNull Session aSession) {
aSession.setPromptDelegate(null);
aSession.removeNavigationListener(this);
mPopUpRequests.remove(aSession.hashCode());
}

public void setPopupDelegate(@Nullable PopUpDelegate delegate) {
mPopupDelegate = delegate;
}

public void clearPopUps() {
mPopUpRequests.clear();

if (mPopupDelegate != null) {
mPopupDelegate.onPopUpsCleared();
}
}

@Nullable
Expand Down Expand Up @@ -220,103 +268,139 @@ public GeckoResult<PromptResponse> onPopupPrompt(@NonNull GeckoSession geckoSess

if (!SettingsStore.getInstance(mContext).isPopUpsBlockingEnabled()) {
result.complete(popupPrompt.confirm(AllowOrDeny.ALLOW));

} else {
String uri = mAttachedWindow.getSession().getCurrentUri();
PopUpRequest request = PopUpRequest.newRequest(uri, popupPrompt, result);
handlePopUpRequest(request);
final int sessionId = geckoSession.hashCode();
final String uri = mAttachedWindow.getSession().getCurrentUri();

Optional<PopUpSite> site = mAllowedPopUpSites.stream().filter((item) -> item.url.equals(uri)).findFirst();
if (site.isPresent()) {
mAttachedWindow.postDelayed(() -> {
if (site.get().allowed) {
result.complete(popupPrompt.confirm(AllowOrDeny.ALLOW));

} else {
result.complete(popupPrompt.dismiss());
}
}, 500);

} else {
PopUpRequest request = PopUpRequest.newRequest(popupPrompt, result, sessionId);
Pair<String, LinkedList<PopUpRequest>> domainRequestList = mPopUpRequests.get(sessionId);
if (domainRequestList == null) {
LinkedList<PopUpRequest> requestList = new LinkedList<>();
domainRequestList = new Pair<>(uri, requestList);
mPopUpRequests.put(sessionId, domainRequestList);
}
domainRequestList.second.add(request);

if (mPopupDelegate != null) {
mPopupDelegate.onPopUpAvailable();
}
}
}

return result;
}

static class PopUpRequest {

public static PopUpRequest newRequest(@NonNull String uri, @NonNull PopupPrompt prompt, @NonNull GeckoResult<PromptResponse> response) {
public static PopUpRequest newRequest(@NonNull PopupPrompt prompt, @NonNull GeckoResult<PromptResponse> response, int sessionId) {
PopUpRequest request = new PopUpRequest();
request.uri = uri;
request.prompt = prompt;
request.response = response;
request.sessionId = sessionId;

return request;
}

String uri;
PopupPrompt prompt;
GeckoResult<PromptResponse> response;
int sessionId;
}

private LinkedList<PopUpRequest> mPopUpRequests = new LinkedList<>();
private SparseArray<Pair<String, LinkedList<PopUpRequest>>> mPopUpRequests = new SparseArray<>();

private void handlePopUpRequest(@NonNull PopUpRequest request) {
if (mPopUpPrompt != null && mPopUpPrompt.isVisible()) {
mPopUpRequests.add(request);

} else {
Optional<PopUpSite> site = mAllowedPopUpSites.stream().filter((item) -> item.url.equals(request.uri)).findFirst();
if (!site.isPresent()) {
mPopUpPrompt = new PopUpBlockDialogWidget(mContext);
mPopUpPrompt.getPlacement().parentHandle = mAttachedWindow.getHandle();
mPopUpPrompt.getPlacement().parentAnchorY = 0.0f;
mPopUpPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.base_app_dialog_y_distance);
mPopUpPrompt.setTitle(request.uri);
mPopUpPrompt.setButtonsDelegate(new BaseAppDialogWidget.Delegate() {
@Override
public void onButtonClicked(int index) {
boolean allowed = index != PopUpBlockDialogWidget.NEGATIVE;
boolean askAgain = mPopUpPrompt.askAgain();
if (!askAgain) {
mAllowedPopUpSites.add(new PopUpSite(request.uri, allowed));
mViewModel.insertSite(request.uri, allowed);
}
public void showPopUps(GeckoSession session) {
Pair<String, LinkedList<PopUpRequest>> requests = mPopUpRequests.get(session.hashCode());
if (requests != null && !requests.second.isEmpty()) {
showPopUp(session.hashCode(), requests);
}
}

if (allowed) {
request.response.complete(request.prompt.confirm(AllowOrDeny.ALLOW));
public boolean hasPendingPopUps(GeckoSession session) {
Pair<String, LinkedList<PopUpRequest>> requests = mPopUpRequests.get(session.hashCode());
if (requests != null) {
return !requests.second.isEmpty();
}

} else {
request.response.complete(request.prompt.dismiss());
}
return false;
}

mExecutors.mainThread().execute(() -> {
try {
PopUpRequest next = mPopUpRequests.pop();
handlePopUpRequest(next);
private void showPopUp(int sessionId, @NonNull Pair<String, LinkedList<PopUpRequest>> requests) {
String uri = requests.first;
Optional<PopUpSite> site = mAllowedPopUpSites.stream().filter((item) -> item.url.equals(uri)).findFirst();
if (!site.isPresent()) {
mPopUpPrompt = new PopUpBlockDialogWidget(mContext);
mPopUpPrompt.getPlacement().parentHandle = mAttachedWindow.getHandle();
mPopUpPrompt.getPlacement().parentAnchorY = 0.0f;
mPopUpPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.base_app_dialog_y_distance);
mPopUpPrompt.setTitle(uri);
mPopUpPrompt.setButtonsDelegate(index -> {
boolean allowed = index != PopUpBlockDialogWidget.NEGATIVE;
boolean askAgain = mPopUpPrompt.askAgain();
if (allowed && !askAgain) {
mAllowedPopUpSites.add(new PopUpSite(uri, allowed));
mViewModel.insertSite(uri, allowed);
}

} catch (NoSuchElementException ignored) {}
});
}
if (allowed) {
requests.second.forEach((request) -> {
request.response.complete(request.prompt.confirm(AllowOrDeny.ALLOW));
});

@Override
public void onDismiss() {
request.response.complete(request.prompt.dismiss());
mPopUpRequests.remove(sessionId);

mExecutors.mainThread().execute(() -> {
try {
PopUpRequest next = mPopUpRequests.pop();
handlePopUpRequest(next);
mExecutors.mainThread().execute(() -> {
if (mPopupDelegate != null) {
mPopupDelegate.onPopUpsCleared();
}
});

} catch (NoSuchElementException ignored) {}
});
}
});
mPopUpPrompt.show(UIWidget.REQUEST_FOCUS);
} else {
mExecutors.mainThread().execute(() -> {
if (mPopupDelegate != null) {
mPopupDelegate.onPopUpAvailable();
}
});
}
});
mPopUpPrompt.show(UIWidget.REQUEST_FOCUS);

} else {
} else {
requests.second.forEach((request) -> {
if (site.get().allowed) {
request.response.complete(request.prompt.confirm(AllowOrDeny.ALLOW));

} else {
request.response.complete(request.prompt.dismiss());
}
}

});
}
}

// WindowWidget.WindowListener

@Override
public void onSessionChanged(@NonNull Session aOldSession, @NonNull Session aSession) {
aOldSession.setPromptDelegate(null);
aSession.setPromptDelegate(this);
cleanSession(aOldSession);
setUpSession(aSession);
}

// NavigationDelegate

@Override
public void onLocationChange(@NonNull GeckoSession geckoSession, @Nullable String s) {
clearPopUps();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,6 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int

return false;
});
binding.site.setOnCheckedChangeListener((compoundButton, value, apply) -> {
if (mCallback != null) {
mCallback.onSwitch(binding.getItem(), value);
}
});

return new PopUpSiteViewHolder(binding);
}
Expand All @@ -107,7 +102,6 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi
PopUpSiteViewHolder siteHolder = (PopUpSiteViewHolder) holder;
PopUpSite site = mDisplayList.get(position);
siteHolder.binding.setItem(site);
siteHolder.binding.site.setChecked(site.allowed);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@

public interface PopUpSiteItemCallback {
void onDelete(@NonNull PopUpSite item);
void onSwitch(@NonNull PopUpSite item, boolean value);
}
Loading

0 comments on commit a34be57

Please sign in to comment.