4
4
import android .content .Context ;
5
5
import android .content .SharedPreferences ;
6
6
import android .preference .PreferenceManager ;
7
- import android .util .Log ;
8
7
9
8
import androidx .annotation .NonNull ;
10
9
import androidx .annotation .Nullable ;
11
10
import androidx .lifecycle .DefaultLifecycleObserver ;
12
11
import androidx .lifecycle .Lifecycle ;
13
12
import androidx .lifecycle .LifecycleOwner ;
14
13
import androidx .lifecycle .Observer ;
15
- import androidx .recyclerview .widget .DiffUtil ;
16
- import androidx .recyclerview .widget .ListUpdateCallback ;
17
14
18
15
import org .json .JSONException ;
19
16
import org .json .JSONObject ;
27
24
import org .mozilla .vrbrowser .browser .engine .Session ;
28
25
import org .mozilla .vrbrowser .db .SitePermission ;
29
26
import org .mozilla .vrbrowser .ui .viewmodel .SitePermissionViewModel ;
30
- import org .mozilla .vrbrowser .utils .UrlUtils ;
31
27
32
28
import java .util .ArrayList ;
33
29
import java .util .List ;
34
- import java .util .Objects ;
35
30
import java .util .function .Function ;
31
+ import java .util .stream .Collectors ;
32
+
33
+ import static org .mozilla .vrbrowser .db .SitePermission .SITE_PERMISSION_TRACKING ;
36
34
37
35
public class TrackingProtectionStore implements DefaultLifecycleObserver ,
38
- SharedPreferences .OnSharedPreferenceChangeListener , ListUpdateCallback {
36
+ SharedPreferences .OnSharedPreferenceChangeListener {
39
37
40
38
public interface TrackingProtectionListener {
41
- default void onExcludedTrackingProtectionChange (@ NonNull String uri , boolean excluded ) {};
39
+ default void onExcludedTrackingProtectionChange (@ NonNull String url , boolean excluded , boolean isPrivate ) {};
42
40
default void onTrackingProtectionLevelUpdated (int level ) {};
43
41
}
44
42
@@ -56,17 +54,17 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin
56
54
private SitePermissionViewModel mViewModel ;
57
55
private List <TrackingProtectionListener > mListeners ;
58
56
private SharedPreferences mPrefs ;
59
- private List <SitePermission > mCurrentSitePermissions ;
60
57
private List <SitePermission > mSitePermissions ;
58
+ private boolean mIsFirstUpdate ;
61
59
62
60
public TrackingProtectionStore (@ NonNull Context context ,
63
61
@ NonNull GeckoRuntime runtime ) {
64
62
mContext = context ;
65
63
mRuntime = runtime ;
66
64
mContentBlockingController = mRuntime .getContentBlockingController ();
67
65
mListeners = new ArrayList <>();
68
- mCurrentSitePermissions = new ArrayList <>();
69
66
mSitePermissions = new ArrayList <>();
67
+ mIsFirstUpdate = true ;
70
68
71
69
mLifeCycle = ((VRBrowserActivity ) context ).getLifecycle ();
72
70
mLifeCycle .addObserver (this );
@@ -97,100 +95,24 @@ public void onStop(@NonNull LifecycleOwner owner) {
97
95
mViewModel .getAll (SitePermission .SITE_PERMISSION_TRACKING ).removeObserver (mSitePermissionObserver );
98
96
}
99
97
100
- private Observer <List <SitePermission >> mSitePermissionObserver = this ::notifyDiff ;
101
-
102
- @ Override
103
- public void onInserted (int position , int count ) {
104
- if (mSitePermissions == null ) {
105
- return ;
106
- }
107
-
108
- for (int i =0 ; i <count ; i ++) {
109
- SitePermission permission = mSitePermissions .get (position + i );
110
- ContentBlockingException exception = toContentBlockingException (permission );
111
- if (exception != null ) {
112
- mListeners .forEach (listener -> listener .onExcludedTrackingProtectionChange (
113
- UrlUtils .getHost (exception .uri ),
114
- true ));
115
- }
116
- }
117
-
118
- final List <ContentBlockingException > exceptionsList = new ArrayList <>();
119
- mContentBlockingController .clearExceptionList ();
120
- for (SitePermission permission : mSitePermissions ) {
121
- ContentBlockingException exception = toContentBlockingException (permission );
122
- if (exception != null ) {
123
- exceptionsList .add (exception );
124
- }
125
- }
126
- mContentBlockingController .restoreExceptionList (exceptionsList );
127
- }
128
-
129
- @ Override
130
- public void onRemoved (int position , int count ) {
131
- if (mCurrentSitePermissions == null ) {
132
- return ;
133
- }
134
-
135
- for (int i =0 ; i <count ; i ++) {
136
- SitePermission permission = mCurrentSitePermissions .get (position + i );
137
- ContentBlockingException exception = toContentBlockingException (permission );
138
- if (exception != null ) {
139
- mContentBlockingController .removeException (exception );
140
- mListeners .forEach (listener -> listener .onExcludedTrackingProtectionChange (
141
- UrlUtils .getHost (exception .uri ),
142
- false ));
98
+ private Observer <List <SitePermission >> mSitePermissionObserver = new Observer <List <SitePermission >>() {
99
+ @ Override
100
+ public void onChanged (List <SitePermission > sitePermissions ) {
101
+ if (sitePermissions != null ) {
102
+ mSitePermissions = sitePermissions ;
103
+
104
+ // Restore the site list on the permissions storage notification
105
+ if (mIsFirstUpdate ) {
106
+ List <ContentBlockingException > exceptions = sitePermissions
107
+ .stream ()
108
+ .map (TrackingProtectionStore ::toContentBlockingException )
109
+ .collect (Collectors .toList ());
110
+ mContentBlockingController .restoreExceptionList (exceptions );
111
+ mIsFirstUpdate = false ;
112
+ }
143
113
}
144
114
}
145
- }
146
-
147
- @ Override
148
- public void onMoved (int fromPosition , int toPosition ) {
149
- // We never move from the exceptions list
150
- }
151
-
152
- @ Override
153
- public void onChanged (int position , int count , @ Nullable Object payload ) {
154
- // We never update from the exceptions list
155
- }
156
-
157
- private void notifyDiff (List <SitePermission > newList ) {
158
- if (newList == null ) {
159
- return ;
160
- }
161
-
162
- DiffUtil .DiffResult result = DiffUtil .calculateDiff (new DiffUtil .Callback () {
163
- @ Override
164
- public int getOldListSize () {
165
- return mSitePermissions .size ();
166
- }
167
-
168
- @ Override
169
- public int getNewListSize () {
170
- return newList .size ();
171
- }
172
-
173
- @ Override
174
- public boolean areItemsTheSame (int oldItemPosition , int newItemPosition ) {
175
- return mSitePermissions .get (oldItemPosition ).url .equals (newList .get (newItemPosition ).url ) &&
176
- mSitePermissions .get (oldItemPosition ).principal .equals (newList .get (newItemPosition ).principal ) &&
177
- mSitePermissions .get (oldItemPosition ).category == newList .get (newItemPosition ).category ;
178
- }
179
-
180
- @ Override
181
- public boolean areContentsTheSame (int oldItemPosition , int newItemPosition ) {
182
- SitePermission newSite = newList .get (newItemPosition );
183
- SitePermission olSite = mSitePermissions .get (oldItemPosition );
184
- return newSite .url .equals (olSite .url )
185
- && Objects .equals (newSite .category , olSite .category )
186
- && Objects .equals (newSite .principal , olSite .principal );
187
- }
188
- });
189
-
190
- mCurrentSitePermissions = mSitePermissions ;
191
- mSitePermissions = newList ;
192
- result .dispatchUpdatesTo (this );
193
- }
115
+ };
194
116
195
117
@ Override
196
118
public void onDestroy (@ NonNull LifecycleOwner owner ) {
@@ -226,55 +148,47 @@ public void fetchAll(Function<List<SitePermission>, Void> onResult) {
226
148
227
149
public void add (@ NonNull Session session ) {
228
150
mContentBlockingController .addException (session .getGeckoSession ());
229
- // Private sessions don't persist to the content blocking controller exceptions list so we just notify
230
- if (session .isPrivateMode ()) {
231
- mListeners .forEach (listener -> listener .onExcludedTrackingProtectionChange (
232
- UrlUtils .getHost (session .getCurrentUri ()),
233
- true ));
234
- } else {
235
- persist ();
236
- }
151
+ mListeners .forEach (listener -> listener .onExcludedTrackingProtectionChange (
152
+ session .getCurrentUri (),
153
+ true ,
154
+ session .isPrivateMode ()));
155
+ saveExceptions ();
237
156
}
238
157
239
158
public void remove (@ NonNull Session session ) {
240
159
mContentBlockingController .removeException (session .getGeckoSession ());
241
- // Private sessions don't persist to the content blocking controller exceptions list so we just notify
242
- if (session .isPrivateMode ()) {
243
- mListeners .forEach (listener -> listener .onExcludedTrackingProtectionChange (
244
- UrlUtils .getHost (session .getCurrentUri ()),
245
- true ));
246
- } else {
247
- persist ();
248
- }
160
+ mListeners .forEach (listener -> listener .onExcludedTrackingProtectionChange (
161
+ session .getCurrentUri (),
162
+ false ,
163
+ session .isPrivateMode ()));
164
+ saveExceptions ();
249
165
}
250
166
251
167
public void remove (@ NonNull SitePermission permission ) {
252
168
ContentBlockingException exception = toContentBlockingException (permission );
253
169
if (exception != null ) {
254
170
mContentBlockingController .removeException (exception );
255
- persist ();
256
171
}
172
+ mListeners .forEach (listener -> listener .onExcludedTrackingProtectionChange (
173
+ permission .url ,
174
+ false ,
175
+ false ));
176
+ saveExceptions ();
257
177
}
258
178
259
- public void removeAll (@ NonNull List <Session > activeSessions ) {
260
- mContentBlockingController .clearExceptionList ();
261
- activeSessions .forEach (session ->
262
- mListeners .forEach (listener ->
263
- listener .onExcludedTrackingProtectionChange (
264
- UrlUtils .getHost (session .getCurrentUri ()),
265
- false )));
266
- persist ();
179
+ public void removeAll () {
180
+ // We can't use clearExceptionList as that clears also the private browsing exceptions
181
+ mSitePermissions .forEach (this ::remove );
267
182
}
268
183
269
- private void persist () {
270
- mViewModel .deleteAll (SitePermission .SITE_PERMISSION_TRACKING );
184
+ private void saveExceptions () {
271
185
mRuntime .getContentBlockingController ().saveExceptionList ().accept (contentBlockingExceptions -> {
272
- if (contentBlockingExceptions != null && !contentBlockingExceptions .isEmpty ()) {
186
+ mViewModel .deleteAll (SITE_PERMISSION_TRACKING );
187
+ if (contentBlockingExceptions != null ) {
273
188
contentBlockingExceptions .forEach (exception -> {
274
- Log .d ("TrackingProtectionStore" , "Excluded site: " + exception .uri );
275
- SitePermission site = toSitePermission (exception );
276
- if (site != null ) {
277
- mViewModel .insertSite (site );
189
+ SitePermission permission = toSitePermission (exception );
190
+ if (permission != null ) {
191
+ mViewModel .insertSite (permission );
278
192
}
279
193
});
280
194
}
0 commit comments