OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.physicalweb; | 5 package org.chromium.chrome.browser.physicalweb; |
6 | 6 |
7 import android.app.AlarmManager; | 7 import android.app.AlarmManager; |
8 import android.app.Notification; | 8 import android.app.Notification; |
9 import android.app.NotificationManager; | 9 import android.app.NotificationManager; |
10 import android.app.PendingIntent; | 10 import android.app.PendingIntent; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 * @param urls A set of UrlInfos containing nearby URLs resolvable with
our resolution | 96 * @param urls A set of UrlInfos containing nearby URLs resolvable with
our resolution |
97 * service. | 97 * service. |
98 */ | 98 */ |
99 void onDisplayableUrlsAdded(Collection<UrlInfo> urls); | 99 void onDisplayableUrlsAdded(Collection<UrlInfo> urls); |
100 } | 100 } |
101 | 101 |
102 /** | 102 /** |
103 * Construct the UrlManager. | 103 * Construct the UrlManager. |
104 * @param context An instance of android.content.Context | 104 * @param context An instance of android.content.Context |
105 */ | 105 */ |
| 106 @VisibleForTesting |
106 public UrlManager(Context context) { | 107 public UrlManager(Context context) { |
107 mContext = context; | 108 mContext = context; |
108 mNotificationManager = new NotificationManagerProxyImpl( | 109 mNotificationManager = new NotificationManagerProxyImpl( |
109 (NotificationManager) context.getSystemService(Context.NOTIFICAT
ION_SERVICE)); | 110 (NotificationManager) context.getSystemService(Context.NOTIFICAT
ION_SERVICE)); |
110 mPwsClient = new PwsClientImpl(context); | 111 mPwsClient = new PwsClientImpl(context); |
111 mObservers = new ObserverList<Listener>(); | 112 mObservers = new ObserverList<Listener>(); |
112 mNearbyUrls = new HashSet<>(); | 113 mNearbyUrls = new HashSet<>(); |
113 mResolvedUrls = new HashSet<>(); | 114 mResolvedUrls = new HashSet<>(); |
114 mUrlInfoMap = new HashMap<>(); | 115 mUrlInfoMap = new HashMap<>(); |
115 mUrlsSortedByTimestamp = new PriorityQueue<String>(1, mScanTimestampComp
arator); | 116 mUrlsSortedByTimestamp = new PriorityQueue<String>(1, mScanTimestampComp
arator); |
116 initSharedPreferences(); | 117 initSharedPreferences(); |
117 } | 118 } |
118 | 119 |
119 /** | 120 /** |
120 * Get a singleton instance of this class. | 121 * Get a singleton instance of this class. |
121 * @param context An instance of android.content.Context. | 122 * @return A singleton instance of this class. |
| 123 */ |
| 124 public static UrlManager getInstance() { |
| 125 if (sInstance == null) { |
| 126 sInstance = new UrlManager(ContextUtils.getApplicationContext()); |
| 127 } |
| 128 return sInstance; |
| 129 } |
| 130 |
| 131 /** |
| 132 * Get a singleton instance of this class. |
| 133 * @param context unused |
122 * @return A singleton instance of this class. | 134 * @return A singleton instance of this class. |
123 */ | 135 */ |
124 public static UrlManager getInstance(Context context) { | 136 public static UrlManager getInstance(Context context) { |
125 if (sInstance == null) { | 137 return getInstance(); |
126 sInstance = new UrlManager(context); | |
127 } | |
128 return sInstance; | |
129 } | 138 } |
130 | 139 |
131 /** | 140 /** |
132 * Add an observer to be notified on changes to the nearby URL list. | 141 * Add an observer to be notified on changes to the nearby URL list. |
133 * @param observer The observer to add. | 142 * @param observer The observer to add. |
134 */ | 143 */ |
135 public void addObserver(Listener observer) { | 144 public void addObserver(Listener observer) { |
136 mObservers.addObserver(observer); | 145 mObservers.addObserver(observer); |
137 } | 146 } |
138 | 147 |
(...skipping 20 matching lines...) Expand all Loading... |
159 recordUpdate(); | 168 recordUpdate(); |
160 if (mNearbyUrls.contains(urlInfo.getUrl()) | 169 if (mNearbyUrls.contains(urlInfo.getUrl()) |
161 // In the rare event that our entry is immediately garbage colle
cted from the cache, | 170 // In the rare event that our entry is immediately garbage colle
cted from the cache, |
162 // we should stop here. | 171 // we should stop here. |
163 || !mUrlInfoMap.containsKey(urlInfo.getUrl())) { | 172 || !mUrlInfoMap.containsKey(urlInfo.getUrl())) { |
164 return; | 173 return; |
165 } | 174 } |
166 mNearbyUrls.add(urlInfo.getUrl()); | 175 mNearbyUrls.add(urlInfo.getUrl()); |
167 putCachedNearbyUrls(); | 176 putCachedNearbyUrls(); |
168 | 177 |
169 if (!PhysicalWeb.isOnboarding(mContext) && !mResolvedUrls.contains(urlIn
fo.getUrl())) { | 178 if (!PhysicalWeb.isOnboarding() && !mResolvedUrls.contains(urlInfo.getUr
l())) { |
170 // We need to resolve the URL. | 179 // We need to resolve the URL. |
171 resolveUrl(urlInfo); | 180 resolveUrl(urlInfo); |
172 return; | 181 return; |
173 } | 182 } |
174 registerNewDisplayableUrl(urlInfo); | 183 registerNewDisplayableUrl(urlInfo); |
175 } | 184 } |
176 | 185 |
177 /** | 186 /** |
178 * Add a URL to the store of URLs. | 187 * Add a URL to the store of URLs. |
179 */ | 188 */ |
180 // TODO(conleyo) we should remove this method after calling code only passes
us a UrlInfo. | 189 // TODO(conleyo) we should remove this method after calling code only passes
us a UrlInfo. |
181 @VisibleForTesting | 190 @VisibleForTesting |
182 public void addUrl(String url) { | 191 public void addUrl(String url) { |
183 addUrl(new UrlInfo(url, -1.0, System.currentTimeMillis())); | 192 addUrl(new UrlInfo(url, -1.0, System.currentTimeMillis())); |
184 } | 193 } |
185 | 194 |
186 /** | 195 /** |
187 * Remove a URL to the store of URLs. | 196 * Remove a URL to the store of URLs. |
188 * This method additionally updates the Physical Web notification. | 197 * This method additionally updates the Physical Web notification. |
189 * @param urlInfo The URL to remove. | 198 * @param urlInfo The URL to remove. |
190 */ | 199 */ |
191 @VisibleForTesting | 200 @VisibleForTesting |
192 public void removeUrl(UrlInfo urlInfo) { | 201 public void removeUrl(UrlInfo urlInfo) { |
193 Log.d(TAG, "URL lost: %s", urlInfo); | 202 Log.d(TAG, "URL lost: %s", urlInfo); |
194 recordUpdate(); | 203 recordUpdate(); |
195 mNearbyUrls.remove(urlInfo.getUrl()); | 204 mNearbyUrls.remove(urlInfo.getUrl()); |
196 putCachedNearbyUrls(); | 205 putCachedNearbyUrls(); |
197 | 206 |
198 // If there are no URLs nearby to display, clear the notification. | 207 // If there are no URLs nearby to display, clear the notification. |
199 if (getUrls(PhysicalWeb.isOnboarding(mContext)).isEmpty()) { | 208 if (getUrls(PhysicalWeb.isOnboarding()).isEmpty()) { |
200 clearNotification(); | 209 clearNotification(); |
201 } | 210 } |
202 } | 211 } |
203 | 212 |
204 /** | 213 /** |
205 * Remove a URL to the store of URLs. | 214 * Remove a URL to the store of URLs. |
206 */ | 215 */ |
207 // TODO(conleyo) we should remove this method after calling code only passes
us a UrlInfo. | 216 // TODO(conleyo) we should remove this method after calling code only passes
us a UrlInfo. |
208 @VisibleForTesting | 217 @VisibleForTesting |
209 public void removeUrl(String url) { | 218 public void removeUrl(String url) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 } | 322 } |
314 registerNewDisplayableUrl(urlInfo); | 323 registerNewDisplayableUrl(urlInfo); |
315 } | 324 } |
316 | 325 |
317 private void removeResolvedUrl(UrlInfo url) { | 326 private void removeResolvedUrl(UrlInfo url) { |
318 Log.d(TAG, "PWS unresolved: %s", url); | 327 Log.d(TAG, "PWS unresolved: %s", url); |
319 mResolvedUrls.remove(url.getUrl()); | 328 mResolvedUrls.remove(url.getUrl()); |
320 putCachedResolvedUrls(); | 329 putCachedResolvedUrls(); |
321 | 330 |
322 // If there are no URLs nearby to display, clear the notification. | 331 // If there are no URLs nearby to display, clear the notification. |
323 if (getUrls(PhysicalWeb.isOnboarding(mContext)).isEmpty()) { | 332 if (getUrls(PhysicalWeb.isOnboarding()).isEmpty()) { |
324 clearNotification(); | 333 clearNotification(); |
325 } | 334 } |
326 } | 335 } |
327 | 336 |
328 private void initSharedPreferences() { | 337 private void initSharedPreferences() { |
329 // Check the version. | 338 // Check the version. |
330 final SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); | 339 final SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); |
331 if (prefs.getInt(PREFS_VERSION_KEY, 0) != PREFS_VERSION) { | 340 if (prefs.getInt(PREFS_VERSION_KEY, 0) != PREFS_VERSION) { |
332 new AsyncTask<Void, Void, Void>() { | 341 new AsyncTask<Void, Void, Void>() { |
333 @Override | 342 @Override |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 | 483 |
475 private void showNotification() { | 484 private void showNotification() { |
476 // We should only show notifications if there's no other notification-ba
sed client. | 485 // We should only show notifications if there's no other notification-ba
sed client. |
477 if (!PhysicalWeb.shouldIgnoreOtherClients() | 486 if (!PhysicalWeb.shouldIgnoreOtherClients() |
478 && PhysicalWebEnvironment | 487 && PhysicalWebEnvironment |
479 .getInstance((ChromeApplication) mContext.getApplication
Context()) | 488 .getInstance((ChromeApplication) mContext.getApplication
Context()) |
480 .hasNotificationBasedClient()) { | 489 .hasNotificationBasedClient()) { |
481 return; | 490 return; |
482 } | 491 } |
483 | 492 |
484 if (PhysicalWeb.isOnboarding(mContext)) { | 493 if (PhysicalWeb.isOnboarding()) { |
485 if (PhysicalWeb.getOptInNotifyCount(mContext) < PhysicalWeb.OPTIN_NO
TIFY_MAX_TRIES) { | 494 if (PhysicalWeb.getOptInNotifyCount() < PhysicalWeb.OPTIN_NOTIFY_MAX
_TRIES) { |
486 // high priority notification | 495 // high priority notification |
487 createOptInNotification(true); | 496 createOptInNotification(true); |
488 PhysicalWeb.recordOptInNotification(mContext); | 497 PhysicalWeb.recordOptInNotification(); |
489 PhysicalWebUma.onOptInHighPriorityNotificationShown(mContext); | 498 PhysicalWebUma.onOptInHighPriorityNotificationShown(mContext); |
490 } else { | 499 } else { |
491 // min priority notification | 500 // min priority notification |
492 createOptInNotification(false); | 501 createOptInNotification(false); |
493 PhysicalWebUma.onOptInMinPriorityNotificationShown(mContext); | 502 PhysicalWebUma.onOptInMinPriorityNotificationShown(mContext); |
494 } | 503 } |
495 } else if (PhysicalWeb.isPhysicalWebPreferenceEnabled(mContext)) { | 504 } else if (PhysicalWeb.isPhysicalWebPreferenceEnabled()) { |
496 createNotification(); | 505 createNotification(); |
497 } | 506 } |
498 } | 507 } |
499 | 508 |
500 private void createNotification() { | 509 private void createNotification() { |
501 PendingIntent pendingIntent = createListUrlsIntent(); | 510 PendingIntent pendingIntent = createListUrlsIntent(); |
502 | 511 |
503 // Get values to display. | 512 // Get values to display. |
504 Resources resources = mContext.getResources(); | 513 Resources resources = mContext.getResources(); |
505 String title = resources.getString(R.string.physical_web_notification_ti
tle); | 514 String title = resources.getString(R.string.physical_web_notification_ti
tle); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
571 Collection<UrlInfo> urlInfos = new ArrayList<>(); | 580 Collection<UrlInfo> urlInfos = new ArrayList<>(); |
572 urlInfos.add(urlInfo); | 581 urlInfos.add(urlInfo); |
573 Collection<UrlInfo> wrappedUrlInfos = Collections.unmodifiableCollection
(urlInfos); | 582 Collection<UrlInfo> wrappedUrlInfos = Collections.unmodifiableCollection
(urlInfos); |
574 for (Listener observer : mObservers) { | 583 for (Listener observer : mObservers) { |
575 observer.onDisplayableUrlsAdded(wrappedUrlInfos); | 584 observer.onDisplayableUrlsAdded(wrappedUrlInfos); |
576 } | 585 } |
577 | 586 |
578 // Only trigger the notification if we know we didn't have a notificatio
n up already | 587 // Only trigger the notification if we know we didn't have a notificatio
n up already |
579 // (i.e., we have exactly 1 displayble URL) or this URL doesn't exist in
the cache | 588 // (i.e., we have exactly 1 displayble URL) or this URL doesn't exist in
the cache |
580 // (and hence the user hasn't swiped away a notification for this URL re
cently). | 589 // (and hence the user hasn't swiped away a notification for this URL re
cently). |
581 if (getUrls(PhysicalWeb.isOnboarding(mContext)).size() != 1 | 590 if (getUrls(PhysicalWeb.isOnboarding()).size() != 1 |
582 && urlInfo.hasBeenDisplayed()) { | 591 && urlInfo.hasBeenDisplayed()) { |
583 return; | 592 return; |
584 } | 593 } |
585 | 594 |
586 // Show a notification and mark the URL as displayed. | 595 // Show a notification and mark the URL as displayed. |
587 showNotification(); | 596 showNotification(); |
588 urlInfo.setHasBeenDisplayed(); | 597 urlInfo.setHasBeenDisplayed(); |
589 } | 598 } |
590 | 599 |
591 private void garbageCollect() { | 600 private void garbageCollect() { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 || mResolvedUrls.contains(url) | 653 || mResolvedUrls.contains(url) |
645 || mUrlInfoMap.containsKey(url) | 654 || mUrlInfoMap.containsKey(url) |
646 || mUrlsSortedByTimestamp.contains(url); | 655 || mUrlsSortedByTimestamp.contains(url); |
647 } | 656 } |
648 | 657 |
649 @VisibleForTesting | 658 @VisibleForTesting |
650 int getMaxCacheSize() { | 659 int getMaxCacheSize() { |
651 return MAX_CACHE_SIZE; | 660 return MAX_CACHE_SIZE; |
652 } | 661 } |
653 } | 662 } |
OLD | NEW |