| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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.searchwidget; | 5 package org.chromium.chrome.browser.searchwidget; |
| 6 | 6 |
| 7 import android.annotation.SuppressLint; | 7 import android.annotation.SuppressLint; |
| 8 import android.app.PendingIntent; | 8 import android.app.PendingIntent; |
| 9 import android.appwidget.AppWidgetManager; | 9 import android.appwidget.AppWidgetManager; |
| 10 import android.appwidget.AppWidgetProvider; | 10 import android.appwidget.AppWidgetProvider; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 TemplateUrlService.getInstance().unregisterLoadListener(this); | 88 TemplateUrlService.getInstance().unregisterLoadListener(this); |
| 89 updateCachedEngineName(); | 89 updateCachedEngineName(); |
| 90 } | 90 } |
| 91 | 91 |
| 92 @Override | 92 @Override |
| 93 public void onTemplateURLServiceChanged() { | 93 public void onTemplateURLServiceChanged() { |
| 94 updateCachedEngineName(); | 94 updateCachedEngineName(); |
| 95 } | 95 } |
| 96 | 96 |
| 97 private void updateCachedEngineName() { | 97 private void updateCachedEngineName() { |
| 98 assert LibraryLoader.isInitialized(); | 98 SearchWidgetProvider.updateCachedEngineName(); |
| 99 | |
| 100 // Getting an instance of the TemplateUrlService requires that the n
ative library be | |
| 101 // loaded, but the TemplateUrlService also itself needs to be initia
lized. | |
| 102 TemplateUrlService service = TemplateUrlService.getInstance(); | |
| 103 assert service.isLoaded(); | |
| 104 SearchWidgetProvider.updateCachedEngineName( | |
| 105 service.getDefaultSearchEngineTemplateUrl().getShortName()); | |
| 106 } | 99 } |
| 107 } | 100 } |
| 108 | 101 |
| 109 static final String ACTION_START_TEXT_QUERY = | 102 static final String ACTION_START_TEXT_QUERY = |
| 110 "org.chromium.chrome.browser.searchwidget.START_TEXT_QUERY"; | 103 "org.chromium.chrome.browser.searchwidget.START_TEXT_QUERY"; |
| 111 static final String ACTION_START_VOICE_QUERY = | 104 static final String ACTION_START_VOICE_QUERY = |
| 112 "org.chromium.chrome.browser.searchwidget.START_VOICE_QUERY"; | 105 "org.chromium.chrome.browser.searchwidget.START_VOICE_QUERY"; |
| 113 static final String ACTION_UPDATE_ALL_WIDGETS = | 106 static final String ACTION_UPDATE_ALL_WIDGETS = |
| 114 "org.chromium.chrome.browser.searchwidget.UPDATE_ALL_WIDGETS"; | 107 "org.chromium.chrome.browser.searchwidget.UPDATE_ALL_WIDGETS"; |
| 115 | 108 |
| 116 static final String EXTRA_START_VOICE_SEARCH = | 109 static final String EXTRA_START_VOICE_SEARCH = |
| 117 "org.chromium.chrome.browser.searchwidget.START_VOICE_SEARCH"; | 110 "org.chromium.chrome.browser.searchwidget.START_VOICE_SEARCH"; |
| 118 | 111 |
| 119 private static final String PREF_IS_VOICE_SEARCH_AVAILABLE = | 112 private static final String PREF_IS_VOICE_SEARCH_AVAILABLE = |
| 120 "org.chromium.chrome.browser.searchwidget.IS_VOICE_SEARCH_AVAILABLE"
; | 113 "org.chromium.chrome.browser.searchwidget.IS_VOICE_SEARCH_AVAILABLE"
; |
| 121 private static final String PREF_NUM_CONSECUTIVE_CRASHES = | 114 private static final String PREF_NUM_CONSECUTIVE_CRASHES = |
| 122 "org.chromium.chrome.browser.searchwidget.NUM_CONSECUTIVE_CRASHES"; | 115 "org.chromium.chrome.browser.searchwidget.NUM_CONSECUTIVE_CRASHES"; |
| 123 private static final String PREF_SEARCH_ENGINE_SHORTNAME = | 116 static final String PREF_SEARCH_ENGINE_SHORTNAME = |
| 124 "org.chromium.chrome.browser.searchwidget.SEARCH_ENGINE_SHORTNAME"; | 117 "org.chromium.chrome.browser.searchwidget.SEARCH_ENGINE_SHORTNAME"; |
| 125 | 118 |
| 126 /** Number of consecutive crashes this widget will absorb before giving up.
*/ | 119 /** Number of consecutive crashes this widget will absorb before giving up.
*/ |
| 127 private static final int CRASH_LIMIT = 3; | 120 private static final int CRASH_LIMIT = 3; |
| 128 | 121 |
| 129 private static final String TAG = "searchwidget"; | 122 private static final String TAG = "searchwidget"; |
| 130 private static final Object DELEGATE_LOCK = new Object(); | 123 private static final Object DELEGATE_LOCK = new Object(); |
| 131 private static final Object OBSERVER_LOCK = new Object(); | 124 private static final Object OBSERVER_LOCK = new Object(); |
| 132 | 125 |
| 133 private static SearchWidgetTemplateUrlServiceObserver sObserver; | 126 private static SearchWidgetTemplateUrlServiceObserver sObserver; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 Intent voiceIntent = createStartQueryIntent(context, ACTION_START_VO
ICE_QUERY, id); | 249 Intent voiceIntent = createStartQueryIntent(context, ACTION_START_VO
ICE_QUERY, id); |
| 257 views.setOnClickPendingIntent(R.id.microphone_icon, | 250 views.setOnClickPendingIntent(R.id.microphone_icon, |
| 258 PendingIntent.getBroadcast( | 251 PendingIntent.getBroadcast( |
| 259 context, 0, voiceIntent, PendingIntent.FLAG_UPDATE_C
URRENT)); | 252 context, 0, voiceIntent, PendingIntent.FLAG_UPDATE_C
URRENT)); |
| 260 views.setViewVisibility(R.id.microphone_icon, View.VISIBLE); | 253 views.setViewVisibility(R.id.microphone_icon, View.VISIBLE); |
| 261 } else { | 254 } else { |
| 262 views.setViewVisibility(R.id.microphone_icon, View.GONE); | 255 views.setViewVisibility(R.id.microphone_icon, View.GONE); |
| 263 } | 256 } |
| 264 | 257 |
| 265 // Update what string is displayed by the widget. | 258 // Update what string is displayed by the widget. |
| 266 String text = TextUtils.isEmpty(engineName) | 259 String text = TextUtils.isEmpty(engineName) || !shouldShowFullString() |
| 267 ? context.getString(R.string.search_widget_default) | 260 ? context.getString(R.string.search_widget_default) |
| 268 : context.getString(R.string.search_with_product, engineName); | 261 : context.getString(R.string.search_with_product, engineName); |
| 269 views.setTextViewText(R.id.title, text); | 262 views.setTextViewText(R.id.title, text); |
| 270 | 263 |
| 271 return views; | 264 return views; |
| 272 } | 265 } |
| 273 | 266 |
| 274 /** Creates a trusted Intent that lets the user begin performing queries. */ | 267 /** Creates a trusted Intent that lets the user begin performing queries. */ |
| 275 private static Intent createStartQueryIntent(Context context, String action,
int widgetId) { | 268 private static Intent createStartQueryIntent(Context context, String action,
int widgetId) { |
| 276 Intent intent = new Intent(action, Uri.parse(String.valueOf(widgetId))); | 269 Intent intent = new Intent(action, Uri.parse(String.valueOf(widgetId))); |
| 277 intent.setClass(context, SearchWidgetProvider.class); | 270 intent.setClass(context, SearchWidgetProvider.class); |
| 278 IntentHandler.addTrustedIntentExtras(intent); | 271 IntentHandler.addTrustedIntentExtras(intent); |
| 279 return intent; | 272 return intent; |
| 280 } | 273 } |
| 281 | 274 |
| 282 /** Caches whether or not a voice search is possible. */ | 275 /** Caches whether or not a voice search is possible. */ |
| 283 static void updateCachedVoiceSearchAvailability(boolean isVoiceSearchAvailab
le) { | 276 static void updateCachedVoiceSearchAvailability(boolean isVoiceSearchAvailab
le) { |
| 284 SharedPreferences prefs = getDelegate().getSharedPreferences(); | 277 SharedPreferences prefs = getDelegate().getSharedPreferences(); |
| 285 if (getCachedVoiceSearchAvailability(prefs) != isVoiceSearchAvailable) { | 278 if (getCachedVoiceSearchAvailability(prefs) != isVoiceSearchAvailable) { |
| 286 prefs.edit().putBoolean(PREF_IS_VOICE_SEARCH_AVAILABLE, isVoiceSearc
hAvailable).apply(); | 279 prefs.edit().putBoolean(PREF_IS_VOICE_SEARCH_AVAILABLE, isVoiceSearc
hAvailable).apply(); |
| 287 performUpdate(null); | 280 performUpdate(null); |
| 288 } | 281 } |
| 289 } | 282 } |
| 290 | 283 |
| 284 /** Attempts to update the cached search engine name. */ |
| 285 public static void updateCachedEngineName() { |
| 286 ThreadUtils.assertOnUiThread(); |
| 287 if (!LibraryLoader.isInitialized()) return; |
| 288 |
| 289 // Getting an instance of the TemplateUrlService requires that the nativ
e library be |
| 290 // loaded, but the TemplateUrlService also itself needs to be initialize
d. |
| 291 TemplateUrlService service = TemplateUrlService.getInstance(); |
| 292 if (!service.isLoaded()) return; |
| 293 |
| 294 updateCachedEngineName(service.getDefaultSearchEngineTemplateUrl().getSh
ortName()); |
| 295 } |
| 296 |
| 291 /** | 297 /** |
| 292 * Updates the name of the user's default search engine that is cached in Sh
aredPreferences. | 298 * Updates the name of the user's default search engine that is cached in Sh
aredPreferences. |
| 293 * Caching it in SharedPreferences prevents us from having to load the nativ
e library and the | 299 * Caching it in SharedPreferences prevents us from having to load the nativ
e library and the |
| 294 * TemplateUrlService whenever the widget is updated. | 300 * TemplateUrlService whenever the widget is updated. |
| 295 */ | 301 */ |
| 296 static void updateCachedEngineName(String engineName) { | 302 static void updateCachedEngineName(String engineName) { |
| 297 SharedPreferences prefs = getDelegate().getSharedPreferences(); | 303 SharedPreferences prefs = getDelegate().getSharedPreferences(); |
| 304 |
| 305 if (!shouldShowFullString()) engineName = null; |
| 306 |
| 298 if (!TextUtils.equals(getCachedEngineName(prefs), engineName)) { | 307 if (!TextUtils.equals(getCachedEngineName(prefs), engineName)) { |
| 299 prefs.edit().putString(PREF_SEARCH_ENGINE_SHORTNAME, engineName).app
ly(); | 308 prefs.edit().putString(PREF_SEARCH_ENGINE_SHORTNAME, engineName).app
ly(); |
| 300 performUpdate(null); | 309 performUpdate(null); |
| 301 } | 310 } |
| 302 } | 311 } |
| 303 | 312 |
| 304 /** Updates the number of consecutive crashes this widget has absorbed. */ | 313 /** Updates the number of consecutive crashes this widget has absorbed. */ |
| 305 @SuppressLint("CommitPrefEdits") | 314 @SuppressLint("CommitPrefEdits") |
| 306 static void updateNumConsecutiveCrashes(int newValue) { | 315 static void updateNumConsecutiveCrashes(int newValue) { |
| 307 SharedPreferences prefs = getDelegate().getSharedPreferences(); | 316 SharedPreferences prefs = getDelegate().getSharedPreferences(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 if (numCrashes < CRASH_LIMIT) { | 364 if (numCrashes < CRASH_LIMIT) { |
| 356 // Absorb the crash. | 365 // Absorb the crash. |
| 357 Log.e(TAG, "Absorbing exception caught when attempting to launch
widget.", e); | 366 Log.e(TAG, "Absorbing exception caught when attempting to launch
widget.", e); |
| 358 } else { | 367 } else { |
| 359 // Too many crashes have happened consecutively. Let Android ha
ndle it. | 368 // Too many crashes have happened consecutively. Let Android ha
ndle it. |
| 360 throw e; | 369 throw e; |
| 361 } | 370 } |
| 362 } | 371 } |
| 363 } | 372 } |
| 364 | 373 |
| 374 static boolean shouldShowFullString() { |
| 375 Intent freIntent = FirstRunFlowSequencer.checkIfFirstRunIsNecessary( |
| 376 getDelegate().getContext(), null, false); |
| 377 return freIntent == null; |
| 378 } |
| 379 |
| 365 /** Sets an {@link SearchWidgetProviderDelegate} to interact with. */ | 380 /** Sets an {@link SearchWidgetProviderDelegate} to interact with. */ |
| 366 @VisibleForTesting | 381 @VisibleForTesting |
| 367 static void setDelegateForTest(SearchWidgetProviderDelegate delegate) { | 382 static void setDelegateForTest(SearchWidgetProviderDelegate delegate) { |
| 368 assert sDelegate == null; | 383 assert sDelegate == null; |
| 369 sDelegate = delegate; | 384 sDelegate = delegate; |
| 370 } | 385 } |
| 371 } | 386 } |
| OLD | NEW |