2
2
3
3
import android .app .Application ;
4
4
import android .content .Context ;
5
+ import android .util .Pair ;
6
+ import android .util .SparseArray ;
5
7
6
8
import androidx .annotation .NonNull ;
7
9
import androidx .annotation .Nullable ;
19
21
import org .mozilla .vrbrowser .ui .widgets .UIWidget ;
20
22
import org .mozilla .vrbrowser .ui .widgets .WidgetPlacement ;
21
23
import org .mozilla .vrbrowser .ui .widgets .WindowWidget ;
22
- import org .mozilla .vrbrowser .ui .widgets .dialogs .BaseAppDialogWidget ;
23
24
import org .mozilla .vrbrowser .ui .widgets .dialogs .PopUpBlockDialogWidget ;
24
25
import org .mozilla .vrbrowser .ui .widgets .prompts .AlertPromptWidget ;
25
26
import org .mozilla .vrbrowser .ui .widgets .prompts .AuthPromptWidget ;
31
32
import java .util .ArrayList ;
32
33
import java .util .LinkedList ;
33
34
import java .util .List ;
34
- import java .util .NoSuchElementException ;
35
35
import java .util .Optional ;
36
36
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
+ }
38
46
39
47
private PromptWidget mPrompt ;
40
48
private PopUpBlockDialogWidget mPopUpPrompt ;
@@ -43,6 +51,7 @@ public class PromptDelegate implements GeckoSession.PromptDelegate, WindowWidget
43
51
private List <PopUpSite > mAllowedPopUpSites ;
44
52
private PopUpsViewModel mViewModel ;
45
53
private AppExecutors mExecutors ;
54
+ private PopUpDelegate mPopupDelegate ;
46
55
47
56
public PromptDelegate (@ NonNull Context context ) {
48
57
mContext = context ;
@@ -59,16 +68,55 @@ public void attachToWindow(@NonNull WindowWidget window) {
59
68
60
69
mAttachedWindow = window ;
61
70
mAttachedWindow .addWindowListener (this );
62
- mAttachedWindow .getSession ().setPromptDelegate (this );
63
71
mViewModel .getAll ().observeForever (mObserver );
72
+
73
+ if (getSession () != null ) {
74
+ setUpSession (getSession ());
75
+ }
64
76
}
65
77
66
78
public void detachFromWindow () {
79
+ if (getSession () != null ) {
80
+ cleanSession (getSession ());
81
+ }
82
+
67
83
if (mAttachedWindow != null ) {
68
84
mAttachedWindow .removeWindowListener (this );
69
85
mAttachedWindow = null ;
70
86
}
71
87
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
+ }
72
120
}
73
121
74
122
@ Nullable
@@ -220,103 +268,139 @@ public GeckoResult<PromptResponse> onPopupPrompt(@NonNull GeckoSession geckoSess
220
268
221
269
if (!SettingsStore .getInstance (mContext ).isPopUpsBlockingEnabled ()) {
222
270
result .complete (popupPrompt .confirm (AllowOrDeny .ALLOW ));
271
+
223
272
} 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
+ }
227
301
}
228
302
229
303
return result ;
230
304
}
231
305
232
306
static class PopUpRequest {
233
307
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 ) {
235
309
PopUpRequest request = new PopUpRequest ();
236
- request .uri = uri ;
237
310
request .prompt = prompt ;
238
311
request .response = response ;
312
+ request .sessionId = sessionId ;
239
313
240
314
return request ;
241
315
}
242
316
243
- String uri ;
244
317
PopupPrompt prompt ;
245
318
GeckoResult <PromptResponse > response ;
319
+ int sessionId ;
246
320
}
247
321
248
- private LinkedList <PopUpRequest > mPopUpRequests = new LinkedList <>();
322
+ private SparseArray < Pair < String , LinkedList <PopUpRequest >>> mPopUpRequests = new SparseArray <>();
249
323
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
+ }
271
330
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
+ }
274
336
275
- } else {
276
- request .response .complete (request .prompt .dismiss ());
277
- }
337
+ return false ;
338
+ }
278
339
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
+ }
283
356
284
- } catch (NoSuchElementException ignored ) {}
285
- });
286
- }
357
+ if (allowed ) {
358
+ requests .second .forEach ((request ) -> {
359
+ request .response .complete (request .prompt .confirm (AllowOrDeny .ALLOW ));
360
+ });
287
361
288
- @ Override
289
- public void onDismiss () {
290
- request .response .complete (request .prompt .dismiss ());
362
+ mPopUpRequests .remove (sessionId );
291
363
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
+ });
296
369
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 );
302
379
303
- } else {
380
+ } else {
381
+ requests .second .forEach ((request ) -> {
304
382
if (site .get ().allowed ) {
305
383
request .response .complete (request .prompt .confirm (AllowOrDeny .ALLOW ));
306
384
307
385
} else {
308
386
request .response .complete (request .prompt .dismiss ());
309
387
}
310
- }
311
-
388
+ });
312
389
}
313
390
}
314
391
315
392
// WindowWidget.WindowListener
316
393
317
394
@ Override
318
395
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 ();
321
405
}
322
406
}
0 commit comments