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

Commit a34be57

Browse files
keianhzobluemarvin
authored andcommitted
Updated Pop-up blocking flow (#2097)
* Updated Pop-ups blocking flow * Fixed url bar icons * Added delay when opening allowed sessions
1 parent 0a5c095 commit a34be57

22 files changed

+419
-158
lines changed

app/src/common/shared/org/mozilla/vrbrowser/browser/PromptDelegate.java

Lines changed: 145 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import android.app.Application;
44
import android.content.Context;
5+
import android.util.Pair;
6+
import android.util.SparseArray;
57

68
import androidx.annotation.NonNull;
79
import androidx.annotation.Nullable;
@@ -19,7 +21,6 @@
1921
import org.mozilla.vrbrowser.ui.widgets.UIWidget;
2022
import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement;
2123
import org.mozilla.vrbrowser.ui.widgets.WindowWidget;
22-
import org.mozilla.vrbrowser.ui.widgets.dialogs.BaseAppDialogWidget;
2324
import org.mozilla.vrbrowser.ui.widgets.dialogs.PopUpBlockDialogWidget;
2425
import org.mozilla.vrbrowser.ui.widgets.prompts.AlertPromptWidget;
2526
import org.mozilla.vrbrowser.ui.widgets.prompts.AuthPromptWidget;
@@ -31,10 +32,17 @@
3132
import java.util.ArrayList;
3233
import java.util.LinkedList;
3334
import java.util.List;
34-
import java.util.NoSuchElementException;
3535
import java.util.Optional;
3636

37-
public class PromptDelegate implements GeckoSession.PromptDelegate, WindowWidget.WindowListener {
37+
public class PromptDelegate implements
38+
GeckoSession.PromptDelegate,
39+
WindowWidget.WindowListener,
40+
GeckoSession.NavigationDelegate {
41+
42+
public interface PopUpDelegate {
43+
void onPopUpAvailable();
44+
void onPopUpsCleared();
45+
}
3846

3947
private PromptWidget mPrompt;
4048
private PopUpBlockDialogWidget mPopUpPrompt;
@@ -43,6 +51,7 @@ public class PromptDelegate implements GeckoSession.PromptDelegate, WindowWidget
4351
private List<PopUpSite> mAllowedPopUpSites;
4452
private PopUpsViewModel mViewModel;
4553
private AppExecutors mExecutors;
54+
private PopUpDelegate mPopupDelegate;
4655

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

6069
mAttachedWindow = window;
6170
mAttachedWindow.addWindowListener(this);
62-
mAttachedWindow.getSession().setPromptDelegate(this);
6371
mViewModel.getAll().observeForever(mObserver);
72+
73+
if (getSession() != null) {
74+
setUpSession(getSession());
75+
}
6476
}
6577

6678
public void detachFromWindow() {
79+
if (getSession() != null) {
80+
cleanSession(getSession());
81+
}
82+
6783
if (mAttachedWindow != null) {
6884
mAttachedWindow.removeWindowListener(this);
6985
mAttachedWindow = null;
7086
}
7187
mViewModel.getAll().removeObserver(mObserver);
88+
89+
clearPopUps();
90+
}
91+
92+
private Session getSession() {
93+
if (mAttachedWindow != null) {
94+
return mAttachedWindow.getSession();
95+
}
96+
return null;
97+
}
98+
99+
private void setUpSession(@NonNull Session aSession) {
100+
aSession.setPromptDelegate(this);
101+
aSession.addNavigationListener(this);
102+
}
103+
104+
private void cleanSession(@NonNull Session aSession) {
105+
aSession.setPromptDelegate(null);
106+
aSession.removeNavigationListener(this);
107+
mPopUpRequests.remove(aSession.hashCode());
108+
}
109+
110+
public void setPopupDelegate(@Nullable PopUpDelegate delegate) {
111+
mPopupDelegate = delegate;
112+
}
113+
114+
public void clearPopUps() {
115+
mPopUpRequests.clear();
116+
117+
if (mPopupDelegate != null) {
118+
mPopupDelegate.onPopUpsCleared();
119+
}
72120
}
73121

74122
@Nullable
@@ -220,103 +268,139 @@ public GeckoResult<PromptResponse> onPopupPrompt(@NonNull GeckoSession geckoSess
220268

221269
if (!SettingsStore.getInstance(mContext).isPopUpsBlockingEnabled()) {
222270
result.complete(popupPrompt.confirm(AllowOrDeny.ALLOW));
271+
223272
} else {
224-
String uri = mAttachedWindow.getSession().getCurrentUri();
225-
PopUpRequest request = PopUpRequest.newRequest(uri, popupPrompt, result);
226-
handlePopUpRequest(request);
273+
final int sessionId = geckoSession.hashCode();
274+
final String uri = mAttachedWindow.getSession().getCurrentUri();
275+
276+
Optional<PopUpSite> site = mAllowedPopUpSites.stream().filter((item) -> item.url.equals(uri)).findFirst();
277+
if (site.isPresent()) {
278+
mAttachedWindow.postDelayed(() -> {
279+
if (site.get().allowed) {
280+
result.complete(popupPrompt.confirm(AllowOrDeny.ALLOW));
281+
282+
} else {
283+
result.complete(popupPrompt.dismiss());
284+
}
285+
}, 500);
286+
287+
} else {
288+
PopUpRequest request = PopUpRequest.newRequest(popupPrompt, result, sessionId);
289+
Pair<String, LinkedList<PopUpRequest>> domainRequestList = mPopUpRequests.get(sessionId);
290+
if (domainRequestList == null) {
291+
LinkedList<PopUpRequest> requestList = new LinkedList<>();
292+
domainRequestList = new Pair<>(uri, requestList);
293+
mPopUpRequests.put(sessionId, domainRequestList);
294+
}
295+
domainRequestList.second.add(request);
296+
297+
if (mPopupDelegate != null) {
298+
mPopupDelegate.onPopUpAvailable();
299+
}
300+
}
227301
}
228302

229303
return result;
230304
}
231305

232306
static class PopUpRequest {
233307

234-
public static PopUpRequest newRequest(@NonNull String uri, @NonNull PopupPrompt prompt, @NonNull GeckoResult<PromptResponse> response) {
308+
public static PopUpRequest newRequest(@NonNull PopupPrompt prompt, @NonNull GeckoResult<PromptResponse> response, int sessionId) {
235309
PopUpRequest request = new PopUpRequest();
236-
request.uri = uri;
237310
request.prompt = prompt;
238311
request.response = response;
312+
request.sessionId = sessionId;
239313

240314
return request;
241315
}
242316

243-
String uri;
244317
PopupPrompt prompt;
245318
GeckoResult<PromptResponse> response;
319+
int sessionId;
246320
}
247321

248-
private LinkedList<PopUpRequest> mPopUpRequests = new LinkedList<>();
322+
private SparseArray<Pair<String, LinkedList<PopUpRequest>>> mPopUpRequests = new SparseArray<>();
249323

250-
private void handlePopUpRequest(@NonNull PopUpRequest request) {
251-
if (mPopUpPrompt != null && mPopUpPrompt.isVisible()) {
252-
mPopUpRequests.add(request);
253-
254-
} else {
255-
Optional<PopUpSite> site = mAllowedPopUpSites.stream().filter((item) -> item.url.equals(request.uri)).findFirst();
256-
if (!site.isPresent()) {
257-
mPopUpPrompt = new PopUpBlockDialogWidget(mContext);
258-
mPopUpPrompt.getPlacement().parentHandle = mAttachedWindow.getHandle();
259-
mPopUpPrompt.getPlacement().parentAnchorY = 0.0f;
260-
mPopUpPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.base_app_dialog_y_distance);
261-
mPopUpPrompt.setTitle(request.uri);
262-
mPopUpPrompt.setButtonsDelegate(new BaseAppDialogWidget.Delegate() {
263-
@Override
264-
public void onButtonClicked(int index) {
265-
boolean allowed = index != PopUpBlockDialogWidget.NEGATIVE;
266-
boolean askAgain = mPopUpPrompt.askAgain();
267-
if (!askAgain) {
268-
mAllowedPopUpSites.add(new PopUpSite(request.uri, allowed));
269-
mViewModel.insertSite(request.uri, allowed);
270-
}
324+
public void showPopUps(GeckoSession session) {
325+
Pair<String, LinkedList<PopUpRequest>> requests = mPopUpRequests.get(session.hashCode());
326+
if (requests != null && !requests.second.isEmpty()) {
327+
showPopUp(session.hashCode(), requests);
328+
}
329+
}
271330

272-
if (allowed) {
273-
request.response.complete(request.prompt.confirm(AllowOrDeny.ALLOW));
331+
public boolean hasPendingPopUps(GeckoSession session) {
332+
Pair<String, LinkedList<PopUpRequest>> requests = mPopUpRequests.get(session.hashCode());
333+
if (requests != null) {
334+
return !requests.second.isEmpty();
335+
}
274336

275-
} else {
276-
request.response.complete(request.prompt.dismiss());
277-
}
337+
return false;
338+
}
278339

279-
mExecutors.mainThread().execute(() -> {
280-
try {
281-
PopUpRequest next = mPopUpRequests.pop();
282-
handlePopUpRequest(next);
340+
private void showPopUp(int sessionId, @NonNull Pair<String, LinkedList<PopUpRequest>> requests) {
341+
String uri = requests.first;
342+
Optional<PopUpSite> site = mAllowedPopUpSites.stream().filter((item) -> item.url.equals(uri)).findFirst();
343+
if (!site.isPresent()) {
344+
mPopUpPrompt = new PopUpBlockDialogWidget(mContext);
345+
mPopUpPrompt.getPlacement().parentHandle = mAttachedWindow.getHandle();
346+
mPopUpPrompt.getPlacement().parentAnchorY = 0.0f;
347+
mPopUpPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.base_app_dialog_y_distance);
348+
mPopUpPrompt.setTitle(uri);
349+
mPopUpPrompt.setButtonsDelegate(index -> {
350+
boolean allowed = index != PopUpBlockDialogWidget.NEGATIVE;
351+
boolean askAgain = mPopUpPrompt.askAgain();
352+
if (allowed && !askAgain) {
353+
mAllowedPopUpSites.add(new PopUpSite(uri, allowed));
354+
mViewModel.insertSite(uri, allowed);
355+
}
283356

284-
} catch (NoSuchElementException ignored) {}
285-
});
286-
}
357+
if (allowed) {
358+
requests.second.forEach((request) -> {
359+
request.response.complete(request.prompt.confirm(AllowOrDeny.ALLOW));
360+
});
287361

288-
@Override
289-
public void onDismiss() {
290-
request.response.complete(request.prompt.dismiss());
362+
mPopUpRequests.remove(sessionId);
291363

292-
mExecutors.mainThread().execute(() -> {
293-
try {
294-
PopUpRequest next = mPopUpRequests.pop();
295-
handlePopUpRequest(next);
364+
mExecutors.mainThread().execute(() -> {
365+
if (mPopupDelegate != null) {
366+
mPopupDelegate.onPopUpsCleared();
367+
}
368+
});
296369

297-
} catch (NoSuchElementException ignored) {}
298-
});
299-
}
300-
});
301-
mPopUpPrompt.show(UIWidget.REQUEST_FOCUS);
370+
} else {
371+
mExecutors.mainThread().execute(() -> {
372+
if (mPopupDelegate != null) {
373+
mPopupDelegate.onPopUpAvailable();
374+
}
375+
});
376+
}
377+
});
378+
mPopUpPrompt.show(UIWidget.REQUEST_FOCUS);
302379

303-
} else {
380+
} else {
381+
requests.second.forEach((request) -> {
304382
if (site.get().allowed) {
305383
request.response.complete(request.prompt.confirm(AllowOrDeny.ALLOW));
306384

307385
} else {
308386
request.response.complete(request.prompt.dismiss());
309387
}
310-
}
311-
388+
});
312389
}
313390
}
314391

315392
// WindowWidget.WindowListener
316393

317394
@Override
318395
public void onSessionChanged(@NonNull Session aOldSession, @NonNull Session aSession) {
319-
aOldSession.setPromptDelegate(null);
320-
aSession.setPromptDelegate(this);
396+
cleanSession(aOldSession);
397+
setUpSession(aSession);
398+
}
399+
400+
// NavigationDelegate
401+
402+
@Override
403+
public void onLocationChange(@NonNull GeckoSession geckoSession, @Nullable String s) {
404+
clearPopUps();
321405
}
322406
}

app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/PopUpAdapter.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,6 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int
9393

9494
return false;
9595
});
96-
binding.site.setOnCheckedChangeListener((compoundButton, value, apply) -> {
97-
if (mCallback != null) {
98-
mCallback.onSwitch(binding.getItem(), value);
99-
}
100-
});
10196

10297
return new PopUpSiteViewHolder(binding);
10398
}
@@ -107,7 +102,6 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi
107102
PopUpSiteViewHolder siteHolder = (PopUpSiteViewHolder) holder;
108103
PopUpSite site = mDisplayList.get(position);
109104
siteHolder.binding.setItem(site);
110-
siteHolder.binding.site.setChecked(site.allowed);
111105
}
112106

113107
@Override

app/src/common/shared/org/mozilla/vrbrowser/ui/callbacks/PopUpSiteItemCallback.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,4 @@
66

77
public interface PopUpSiteItemCallback {
88
void onDelete(@NonNull PopUpSite item);
9-
void onSwitch(@NonNull PopUpSite item, boolean value);
109
}

0 commit comments

Comments
 (0)