Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(438)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaClient.java

Issue 1321393002: Attempt to head off OmahaClient ANR (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/omaha/VersionNumberGetter.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.omaha; 5 package org.chromium.chrome.browser.omaha;
6 6
7 import android.app.AlarmManager; 7 import android.app.AlarmManager;
8 import android.app.IntentService; 8 import android.app.IntentService;
9 import android.app.PendingIntent; 9 import android.app.PendingIntent;
10 import android.content.Context; 10 import android.content.Context;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 private static final String TAG = "cr.omaha"; 59 private static final String TAG = "cr.omaha";
60 60
61 // Intent actions. 61 // Intent actions.
62 private static final String ACTION_INITIALIZE = 62 private static final String ACTION_INITIALIZE =
63 "org.chromium.chrome.browser.omaha.ACTION_INITIALIZE"; 63 "org.chromium.chrome.browser.omaha.ACTION_INITIALIZE";
64 private static final String ACTION_REGISTER_REQUEST = 64 private static final String ACTION_REGISTER_REQUEST =
65 "org.chromium.chrome.browser.omaha.ACTION_REGISTER_REQUEST"; 65 "org.chromium.chrome.browser.omaha.ACTION_REGISTER_REQUEST";
66 private static final String ACTION_POST_REQUEST = 66 private static final String ACTION_POST_REQUEST =
67 "org.chromium.chrome.browser.omaha.ACTION_POST_REQUEST"; 67 "org.chromium.chrome.browser.omaha.ACTION_POST_REQUEST";
68 68
69 // Strings for extras.
70 private static final String EXTRA_FORCE_ACTION = "forceAction";
71
72 // Delays between events. 69 // Delays between events.
73 private static final long MS_PER_HOUR = 3600000; 70 private static final long MS_PER_HOUR = 3600000;
74 private static final long MS_POST_BASE_DELAY = MS_PER_HOUR; 71 private static final long MS_POST_BASE_DELAY = MS_PER_HOUR;
75 private static final long MS_POST_MAX_DELAY = 5 * MS_PER_HOUR; 72 private static final long MS_POST_MAX_DELAY = 5 * MS_PER_HOUR;
76 private static final long MS_BETWEEN_REQUESTS = 5 * MS_PER_HOUR; 73 private static final long MS_BETWEEN_REQUESTS = 5 * MS_PER_HOUR;
77 private static final int MS_CONNECTION_TIMEOUT = 60000; 74 private static final int MS_CONNECTION_TIMEOUT = 60000;
78 75
79 // Flags for retrieving the OmahaClient's state after it's written to disk. 76 // Flags for retrieving the OmahaClient's state after it's written to disk.
80 // The PREF_PACKAGE doesn't match the current OmahaClient package for histor ical reasons. 77 // The PREF_PACKAGE doesn't match the current OmahaClient package for histor ical reasons.
81 @VisibleForTesting 78 @VisibleForTesting
(...skipping 29 matching lines...) Expand all
111 108
112 // Static fields 109 // Static fields
113 private static boolean sEnableCommunication = true; 110 private static boolean sEnableCommunication = true;
114 private static boolean sEnableUpdateDetection = true; 111 private static boolean sEnableUpdateDetection = true;
115 private static VersionNumberGetter sVersionNumberGetter = null; 112 private static VersionNumberGetter sVersionNumberGetter = null;
116 private static MarketURLGetter sMarketURLGetter = null; 113 private static MarketURLGetter sMarketURLGetter = null;
117 private static Boolean sIsFreshInstallOrDataCleared = null; 114 private static Boolean sIsFreshInstallOrDataCleared = null;
118 115
119 // Member fields not persisted to disk. 116 // Member fields not persisted to disk.
120 private boolean mStateHasBeenRestored; 117 private boolean mStateHasBeenRestored;
121 private Context mApplicationContext;
122 private ExponentialBackoffScheduler mBackoffScheduler; 118 private ExponentialBackoffScheduler mBackoffScheduler;
123 private RequestGenerator mGenerator; 119 private RequestGenerator mGenerator;
124 120
125 // State saved written to and read from disk. 121 // State saved written to and read from disk.
126 private RequestData mCurrentRequest; 122 private RequestData mCurrentRequest;
127 private long mTimestampOfInstall; 123 private long mTimestampOfInstall;
128 private long mTimestampForNextPostAttempt; 124 private long mTimestampForNextPostAttempt;
129 private long mTimestampForNewRequest; 125 private long mTimestampForNewRequest;
130 private String mLatestVersion; 126 private String mLatestVersion;
131 private String mMarketURL; 127 private String mMarketURL;
132 private String mInstallSource; 128 private String mInstallSource;
133 protected boolean mSendInstallEvent; 129 protected boolean mSendInstallEvent;
134 130
135 public OmahaClient() { 131 public OmahaClient() {
136 super(TAG); 132 super(TAG);
137 setIntentRedelivery(true); 133 setIntentRedelivery(true);
138 } 134 }
139 135
140 @Override
141 public void onCreate() {
142 super.onCreate();
143 mApplicationContext = getApplicationContext();
144 mBackoffScheduler = createBackoffScheduler(PREF_PACKAGE, mApplicationCon text,
145 MS_POST_BASE_DELAY, MS_POST_MAX_DELAY);
146 mGenerator = createRequestGenerator(mApplicationContext);
147 }
148
149 /** 136 /**
150 * Sets whether Chrome should be communicating with the Omaha server. 137 * Sets whether Chrome should be communicating with the Omaha server.
151 * The alternative to using a static field within OmahaClient is using a mem ber variable in 138 * The alternative to using a static field within OmahaClient is using a mem ber variable in
152 * the ChromeTabbedActivity. The problem is that it is difficult to set the variable before 139 * the ChromeTabbedActivity. The problem is that it is difficult to set the variable before
153 * ChromeTabbedActivity is started. 140 * ChromeTabbedActivity is started.
154 */ 141 */
155 @VisibleForTesting 142 @VisibleForTesting
156 public static void setEnableCommunication(boolean state) { 143 public static void setEnableCommunication(boolean state) {
157 sEnableCommunication = state; 144 sEnableCommunication = state;
158 } 145 }
(...skipping 11 matching lines...) Expand all
170 return mTimestampForNextPostAttempt; 157 return mTimestampForNextPostAttempt;
171 } 158 }
172 159
173 @VisibleForTesting 160 @VisibleForTesting
174 long getTimestampForNewRequest() { 161 long getTimestampForNewRequest() {
175 return mTimestampForNewRequest; 162 return mTimestampForNewRequest;
176 } 163 }
177 164
178 @VisibleForTesting 165 @VisibleForTesting
179 int getCumulativeFailedAttempts() { 166 int getCumulativeFailedAttempts() {
180 return mBackoffScheduler.getNumFailedAttempts(); 167 return getBackoffScheduler().getNumFailedAttempts();
181 } 168 }
182 169
183 /** 170 /**
184 * Creates the scheduler used to space out POST attempts. 171 * Creates the scheduler used to space out POST attempts.
185 */ 172 */
186 @VisibleForTesting 173 @VisibleForTesting
187 ExponentialBackoffScheduler createBackoffScheduler(String prefPackage, Conte xt context, 174 ExponentialBackoffScheduler createBackoffScheduler(String prefPackage, Conte xt context,
188 long base, long max) { 175 long base, long max) {
189 return new ExponentialBackoffScheduler(prefPackage, context, base, max); 176 return new ExponentialBackoffScheduler(prefPackage, context, base, max);
190 } 177 }
191 178
192 /** 179 /**
193 * Creates the request generator used to create Omaha XML. 180 * Creates the request generator used to create Omaha XML.
194 */ 181 */
195 @VisibleForTesting 182 @VisibleForTesting
196 RequestGenerator createRequestGenerator(Context context) { 183 RequestGenerator createRequestGenerator(Context context) {
197 return ((ChromeApplication) getApplicationContext()).createOmahaRequestG enerator(); 184 return ((ChromeApplication) context.getApplicationContext()).createOmaha RequestGenerator();
198 } 185 }
199 186
200 /** 187 /**
201 * Handles an action on a thread separate from the UI thread. 188 * Handles an action on a thread separate from the UI thread.
202 * @param intent Intent fired by some part of Chrome. 189 * @param intent Intent fired by some part of Chrome.
203 */ 190 */
204 @Override 191 @Override
205 public void onHandleIntent(Intent intent) { 192 public void onHandleIntent(Intent intent) {
206 assert Looper.myLooper() != Looper.getMainLooper(); 193 assert Looper.myLooper() != Looper.getMainLooper();
207 194
208 if (!sEnableCommunication) { 195 if (!sEnableCommunication) {
209 Log.v(TAG, "Disabled. Ignoring intent."); 196 Log.v(TAG, "Disabled. Ignoring intent.");
210 return; 197 return;
211 } 198 }
212 199
213 if (mGenerator == null) {
214 Log.e(TAG, "No request generator set. Ignoring intent.");
215 return;
216 }
217
218 if (!mStateHasBeenRestored) { 200 if (!mStateHasBeenRestored) {
219 restoreState(); 201 restoreState();
220 } 202 }
221 203
222 if (ACTION_INITIALIZE.equals(intent.getAction())) { 204 if (ACTION_INITIALIZE.equals(intent.getAction())) {
223 handleInitialize(); 205 handleInitialize();
224 } else if (ACTION_REGISTER_REQUEST.equals(intent.getAction())) { 206 } else if (ACTION_REGISTER_REQUEST.equals(intent.getAction())) {
225 handleRegisterRequest(intent); 207 handleRegisterRequest(intent);
226 } else if (ACTION_POST_REQUEST.equals(intent.getAction())) { 208 } else if (ACTION_POST_REQUEST.equals(intent.getAction())) {
227 handlePostRequestIntent(intent); 209 handlePostRequestIntent(intent);
228 } else { 210 } else {
229 Log.e(TAG, "Got unknown action from intent: " + intent.getAction()); 211 Log.e(TAG, "Got unknown action from intent: " + intent.getAction());
230 } 212 }
231 } 213 }
232 214
233 public static Intent createInitializeIntent(Context context) { 215 public static Intent createInitializeIntent(Context context) {
234 Intent intent = new Intent(context, OmahaClient.class); 216 Intent intent = new Intent(context, OmahaClient.class);
235 intent.setAction(ACTION_INITIALIZE); 217 intent.setAction(ACTION_INITIALIZE);
236 return intent; 218 return intent;
237 } 219 }
238 220
239 /** 221 /**
240 * Start a recurring alarm to fire request generation intents. 222 * Start a recurring alarm to fire request generation intents.
241 */ 223 */
242 private void handleInitialize() { 224 private void handleInitialize() {
243 scheduleRepeatingAlarm(); 225 scheduleRepeatingAlarm();
244 226
245 // If a request exists, fire a POST intent to restart its timer. 227 // If a request exists, fire a POST intent to restart its timer.
246 if (hasRequest()) { 228 if (hasRequest()) startService(createPostRequestIntent(this));
247 Intent postIntent = createPostRequestIntent(mApplicationContext, fal se);
248 startService(postIntent);
249 }
250 } 229 }
251 230
252 public static Intent createRegisterRequestIntent(Context context, boolean fo rce) { 231 /**
232 * Returns an Intent for registering a new request to send to the server.
233 */
234 static Intent createRegisterRequestIntent(Context context) {
253 Intent intent = new Intent(context, OmahaClient.class); 235 Intent intent = new Intent(context, OmahaClient.class);
254 intent.setAction(ACTION_REGISTER_REQUEST); 236 intent.setAction(ACTION_REGISTER_REQUEST);
255 intent.putExtra(EXTRA_FORCE_ACTION, force);
256 return intent; 237 return intent;
257 } 238 }
258 239
259 /** 240 /**
260 * Determines if a new request should be generated. New requests are only g enerated if enough 241 * Determines if a new request should be generated. New requests are only g enerated if enough
261 * time has passed between now and the last time a request was generated. 242 * time has passed between now and the last time a request was generated.
262 */ 243 */
263 private void handleRegisterRequest(Intent intent) { 244 private void handleRegisterRequest(Intent intent) {
264 boolean force = intent.getBooleanExtra(EXTRA_FORCE_ACTION, false); 245 if (!isChromeBeingUsed()) {
265 if (!isChromeBeingUsed() && !force) {
266 cancelRepeatingAlarm(); 246 cancelRepeatingAlarm();
267 return; 247 return;
268 } 248 }
269 249
270 // If the current request is too old, generate a new one. 250 // If the current request is too old, generate a new one.
271 long currentTimestamp = mBackoffScheduler.getCurrentTime(); 251 long currentTimestamp = getBackoffScheduler().getCurrentTime();
272 boolean isTooOld = hasRequest() 252 boolean isTooOld = hasRequest()
273 && mCurrentRequest.getAgeInMilliseconds(currentTimestamp) >= MS_ BETWEEN_REQUESTS; 253 && mCurrentRequest.getAgeInMilliseconds(currentTimestamp) >= MS_ BETWEEN_REQUESTS;
274 boolean isOverdue = !hasRequest() && currentTimestamp >= mTimestampForNe wRequest; 254 boolean isOverdue = !hasRequest() && currentTimestamp >= mTimestampForNe wRequest;
275 if (isTooOld || isOverdue || force) { 255 if (isTooOld || isOverdue) {
276 registerNewRequest(currentTimestamp); 256 registerNewRequest(currentTimestamp);
277 } 257 }
278 258
279 // Create an intent to send the request. If we're forcing a registratio n, force the POST, 259 // Create an intent to send the request.
280 // as well.
281 if (hasRequest()) { 260 if (hasRequest()) {
282 Intent postIntent = createPostRequestIntent(mApplicationContext, for ce); 261 startService(createPostRequestIntent(this));
283 startService(postIntent);
284 } 262 }
285 } 263 }
286 264
287 public static Intent createPostRequestIntent(Context context, boolean force) { 265 /**
266 * Returns an Intent for POSTing the current request to the Omaha server.
267 */
268 static Intent createPostRequestIntent(Context context) {
288 Intent intent = new Intent(context, OmahaClient.class); 269 Intent intent = new Intent(context, OmahaClient.class);
289 intent.setAction(ACTION_POST_REQUEST); 270 intent.setAction(ACTION_POST_REQUEST);
290 intent.putExtra(EXTRA_FORCE_ACTION, force);
291 return intent; 271 return intent;
292 } 272 }
293 273
294 /** 274 /**
295 * Sends the request it is holding. 275 * Sends the request it is holding.
296 */ 276 */
297 @VisibleForTesting 277 @VisibleForTesting
298 private void handlePostRequestIntent(Intent intent) { 278 private void handlePostRequestIntent(Intent intent) {
299 if (!hasRequest()) { 279 if (!hasRequest()) {
300 return; 280 return;
301 } 281 }
302 282
303 boolean force = intent.getBooleanExtra(EXTRA_FORCE_ACTION, false);
304
305 // If enough time has passed since the last attempt, try sending a reque st. 283 // If enough time has passed since the last attempt, try sending a reque st.
306 long currentTimestamp = mBackoffScheduler.getCurrentTime(); 284 long currentTimestamp = getBackoffScheduler().getCurrentTime();
307 if (currentTimestamp >= mTimestampForNextPostAttempt || force) { 285 if (currentTimestamp >= mTimestampForNextPostAttempt) {
308 // All requests made during the same session should have the same ID . 286 // All requests made during the same session should have the same ID .
309 String sessionID = generateRandomUUID(); 287 String sessionID = generateRandomUUID();
310 boolean sendingInstallRequest = mSendInstallEvent; 288 boolean sendingInstallRequest = mSendInstallEvent;
311 boolean succeeded = generateAndPostRequest(currentTimestamp, session ID); 289 boolean succeeded = generateAndPostRequest(currentTimestamp, session ID);
312 290
313 if (succeeded && sendingInstallRequest) { 291 if (succeeded && sendingInstallRequest) {
314 // Only the first request ever generated should contain an insta ll event. 292 // Only the first request ever generated should contain an insta ll event.
315 mSendInstallEvent = false; 293 mSendInstallEvent = false;
316 294
317 // Create and immediately send another request for a ping and up date check. 295 // Create and immediately send another request for a ping and up date check.
318 registerNewRequest(currentTimestamp); 296 registerNewRequest(currentTimestamp);
319 succeeded = generateAndPostRequest(currentTimestamp, sessionID); 297 generateAndPostRequest(currentTimestamp, sessionID);
nyquist 2015/09/01 22:32:50 So this ignores the return value of the function n
gone 2015/09/01 22:36:12 There's a call right above this where the boolean
320 }
321
322 if (force) {
323 if (succeeded) {
324 Log.v(TAG, "Requests successfully sent to Omaha server.");
325 } else {
326 Log.e(TAG, "Requests failed to reach Omaha server.");
327 }
328 } 298 }
329 } else { 299 } else {
330 // Set an alarm to POST at the proper time. Previous alarms are des troyed. 300 // Set an alarm to POST at the proper time. Previous alarms are des troyed.
331 Intent postIntent = createPostRequestIntent(mApplicationContext, fal se); 301 Intent postIntent = createPostRequestIntent(this);
332 mBackoffScheduler.createAlarm(postIntent, mTimestampForNextPostAttem pt); 302 getBackoffScheduler().createAlarm(postIntent, mTimestampForNextPostA ttempt);
333 } 303 }
334 304
335 // Write everything back out again to save our state. 305 // Write everything back out again to save our state.
336 saveState(); 306 saveState();
337 } 307 }
338 308
339 private boolean generateAndPostRequest(long currentTimestamp, String session ID) { 309 private boolean generateAndPostRequest(long currentTimestamp, String session ID) {
310 ExponentialBackoffScheduler scheduler = getBackoffScheduler();
340 try { 311 try {
341 // Generate the XML for the current request. 312 // Generate the XML for the current request.
342 long installAgeInDays = RequestGenerator.installAge(currentTimestamp , 313 long installAgeInDays = RequestGenerator.installAge(currentTimestamp ,
343 mTimestampOfInstall, mCurrentRequest.isSendInstallEvent()); 314 mTimestampOfInstall, mCurrentRequest.isSendInstallEvent());
344 String version = getVersionNumberGetter().getCurrentlyUsedVersion(mA pplicationContext); 315 String version = getVersionNumberGetter().getCurrentlyUsedVersion(th is);
345 String xml = 316 String xml = getRequestGenerator().generateXML(
346 mGenerator.generateXML(sessionID, version, installAgeInDays, mCurrentRequest); 317 sessionID, version, installAgeInDays, mCurrentRequest);
347 318
348 // Send the request to the server & wait for a response. 319 // Send the request to the server & wait for a response.
349 String response = postRequest(currentTimestamp, xml); 320 String response = postRequest(currentTimestamp, xml);
350 parseServerResponse(response); 321 parseServerResponse(response);
351 322
352 // If we've gotten this far, we've successfully sent a request. 323 // If we've gotten this far, we've successfully sent a request.
353 mCurrentRequest = null; 324 mCurrentRequest = null;
354 mTimestampForNextPostAttempt = currentTimestamp + MS_POST_BASE_DELAY ; 325 mTimestampForNextPostAttempt = currentTimestamp + MS_POST_BASE_DELAY ;
355 mBackoffScheduler.resetFailedAttempts(); 326 scheduler.resetFailedAttempts();
356 Log.i(TAG, "Request to Server Successful. Timestamp for next request :" 327 Log.i(TAG, "Request to Server Successful. Timestamp for next request :"
357 + String.valueOf(mTimestampForNextPostAttempt)); 328 + String.valueOf(mTimestampForNextPostAttempt));
358 329
359 return true; 330 return true;
360 } catch (RequestFailureException e) { 331 } catch (RequestFailureException e) {
361 // Set the alarm to try again later. 332 // Set the alarm to try again later.
362 Log.e(TAG, "Failed to contact server: ", e); 333 Log.e(TAG, "Failed to contact server: ", e);
363 Intent postIntent = createPostRequestIntent(mApplicationContext, fal se); 334 Intent postIntent = createPostRequestIntent(this);
364 mTimestampForNextPostAttempt = mBackoffScheduler.createAlarm(postInt ent); 335 mTimestampForNextPostAttempt = scheduler.createAlarm(postIntent);
365 mBackoffScheduler.increaseFailedAttempts(); 336 scheduler.increaseFailedAttempts();
366 return false; 337 return false;
367 } 338 }
368 } 339 }
369 340
370 /** 341 /**
371 * Sets a repeating alarm that fires request registration Intents. 342 * Sets a repeating alarm that fires request registration Intents.
372 * Setting the alarm overwrites whatever alarm is already there, and rebooti ng 343 * Setting the alarm overwrites whatever alarm is already there, and rebooti ng
373 * clears whatever alarms are currently set. 344 * clears whatever alarms are currently set.
374 */ 345 */
375 private void scheduleRepeatingAlarm() { 346 private void scheduleRepeatingAlarm() {
376 Intent registerIntent = createRegisterRequestIntent(mApplicationContext, false); 347 Intent registerIntent = createRegisterRequestIntent(this);
377 PendingIntent pIntent = 348 PendingIntent pIntent = PendingIntent.getService(this, 0, registerIntent , 0);
378 PendingIntent.getService(mApplicationContext, 0, registerIntent, 0); 349 AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE) ;
379 AlarmManager am =
380 (AlarmManager) mApplicationContext.getSystemService(Context.ALAR M_SERVICE);
381 setAlarm(am, pIntent, AlarmManager.RTC, mTimestampForNewRequest); 350 setAlarm(am, pIntent, AlarmManager.RTC, mTimestampForNewRequest);
382 } 351 }
383 352
384 /** 353 /**
385 * Sets up a timer to fire after each interval. 354 * Sets up a timer to fire after each interval.
386 * Override to prevent a real alarm from being set. 355 * Override to prevent a real alarm from being set.
387 */ 356 */
388 @VisibleForTesting 357 @VisibleForTesting
389 protected void setAlarm(AlarmManager am, PendingIntent operation, int alarmT ype, 358 protected void setAlarm(AlarmManager am, PendingIntent operation, int alarmT ype,
390 long triggerAtTime) { 359 long triggerAtTime) {
391 try { 360 try {
392 am.setRepeating(AlarmManager.RTC, triggerAtTime, MS_BETWEEN_REQUESTS , operation); 361 am.setRepeating(AlarmManager.RTC, triggerAtTime, MS_BETWEEN_REQUESTS , operation);
393 } catch (SecurityException e) { 362 } catch (SecurityException e) {
394 Log.e(TAG, "Failed to set repeating alarm."); 363 Log.e(TAG, "Failed to set repeating alarm.");
395 } 364 }
396 } 365 }
397 366
398 /** 367 /**
399 * Cancels the alarm that launches this service. It will be replaced when C hrome next resumes. 368 * Cancels the alarm that launches this service. It will be replaced when C hrome next resumes.
400 */ 369 */
401 private void cancelRepeatingAlarm() { 370 private void cancelRepeatingAlarm() {
402 Intent requestIntent = createRegisterRequestIntent(mApplicationContext, false); 371 Intent requestIntent = createRegisterRequestIntent(this);
403 PendingIntent pendingIntent = PendingIntent.getService(mApplicationConte xt, 0, 372 PendingIntent pendingIntent =
404 requestIntent, PendingIntent.FLAG_NO_CREATE); 373 PendingIntent.getService(this, 0, requestIntent, PendingIntent.F LAG_NO_CREATE);
405 // Setting FLAG_NO_CREATE forces Android to return an already existing P endingIntent. 374 // Setting FLAG_NO_CREATE forces Android to return an already existing P endingIntent.
406 // Here it would be the one that was used to create the existing alarm ( if it exists). 375 // Here it would be the one that was used to create the existing alarm ( if it exists).
407 // If the pendingIntent is null, it is likely that no alarm was created. 376 // If the pendingIntent is null, it is likely that no alarm was created.
408 if (pendingIntent != null) { 377 if (pendingIntent != null) {
409 AlarmManager am = 378 AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERV ICE);
410 (AlarmManager) mApplicationContext.getSystemService(Context. ALARM_SERVICE);
411 am.cancel(pendingIntent); 379 am.cancel(pendingIntent);
412 pendingIntent.cancel(); 380 pendingIntent.cancel();
413 } 381 }
414 } 382 }
415 383
416 /** 384 /**
417 * Determine whether or not Chrome is currently being used actively. 385 * Determine whether or not Chrome is currently being used actively.
418 */ 386 */
419 @VisibleForTesting 387 @VisibleForTesting
420 protected boolean isChromeBeingUsed() { 388 protected boolean isChromeBeingUsed() {
421 boolean isChromeVisible = ApplicationStatus.hasVisibleActivities(); 389 boolean isChromeVisible = ApplicationStatus.hasVisibleActivities();
422 boolean isScreenOn = ApiCompatibilityUtils.isInteractive(mApplicationCon text); 390 boolean isScreenOn = ApiCompatibilityUtils.isInteractive(this);
423 return isChromeVisible && isScreenOn; 391 return isChromeVisible && isScreenOn;
424 } 392 }
425 393
426 /** 394 /**
427 * Registers a new request with the current timestamp. Internal timestamps are reset to start 395 * Registers a new request with the current timestamp. Internal timestamps are reset to start
428 * fresh. 396 * fresh.
429 * @param currentTimestamp Current time. 397 * @param currentTimestamp Current time.
430 */ 398 */
431 @VisibleForTesting 399 @VisibleForTesting
432 void registerNewRequest(long currentTimestamp) { 400 void registerNewRequest(long currentTimestamp) {
433 mCurrentRequest = createRequestData(currentTimestamp, null); 401 mCurrentRequest = createRequestData(currentTimestamp, null);
434 mBackoffScheduler.resetFailedAttempts(); 402 getBackoffScheduler().resetFailedAttempts();
435 mTimestampForNextPostAttempt = currentTimestamp; 403 mTimestampForNextPostAttempt = currentTimestamp;
436 404
437 // Tentatively set the timestamp for a new request. This will be update d when the server 405 // Tentatively set the timestamp for a new request. This will be update d when the server
438 // is successfully contacted. 406 // is successfully contacted.
439 mTimestampForNewRequest = currentTimestamp + MS_BETWEEN_REQUESTS; 407 mTimestampForNewRequest = currentTimestamp + MS_BETWEEN_REQUESTS;
440 scheduleRepeatingAlarm(); 408 scheduleRepeatingAlarm();
441 409
442 saveState(); 410 saveState();
443 } 411 }
444 412
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 } 447 }
480 } 448 }
481 449
482 return response; 450 return response;
483 } 451 }
484 452
485 /** 453 /**
486 * Parse the server's response and confirm that we received an OK response. 454 * Parse the server's response and confirm that we received an OK response.
487 */ 455 */
488 private void parseServerResponse(String response) throws RequestFailureExcep tion { 456 private void parseServerResponse(String response) throws RequestFailureExcep tion {
489 String appId = mGenerator.getAppId(); 457 String appId = getRequestGenerator().getAppId();
490 boolean sentPingAndUpdate = !mSendInstallEvent; 458 boolean sentPingAndUpdate = !mSendInstallEvent;
491 ResponseParser parser = 459 ResponseParser parser =
492 new ResponseParser(appId, mSendInstallEvent, sentPingAndUpdate, sentPingAndUpdate); 460 new ResponseParser(appId, mSendInstallEvent, sentPingAndUpdate, sentPingAndUpdate);
493 parser.parseResponse(response); 461 parser.parseResponse(response);
494 mTimestampForNewRequest = mBackoffScheduler.getCurrentTime() + MS_BETWEE N_REQUESTS; 462 mTimestampForNewRequest = getBackoffScheduler().getCurrentTime() + MS_BE TWEEN_REQUESTS;
495 mLatestVersion = parser.getNewVersion(); 463 mLatestVersion = parser.getNewVersion();
496 mMarketURL = parser.getURL(); 464 mMarketURL = parser.getURL();
497 scheduleRepeatingAlarm(); 465 scheduleRepeatingAlarm();
498 } 466 }
499 467
500 /** 468 /**
501 * Returns a HttpURLConnection to the server. 469 * Returns a HttpURLConnection to the server.
502 */ 470 */
503 @VisibleForTesting 471 @VisibleForTesting
504 protected HttpURLConnection createConnection() throws RequestFailureExceptio n { 472 protected HttpURLConnection createConnection() throws RequestFailureExceptio n {
505 try { 473 try {
506 URL url = new URL(mGenerator.getServerUrl()); 474 URL url = new URL(getRequestGenerator().getServerUrl());
507 HttpURLConnection connection = (HttpURLConnection) url.openConnectio n(); 475 HttpURLConnection connection = (HttpURLConnection) url.openConnectio n();
508 connection.setConnectTimeout(MS_CONNECTION_TIMEOUT); 476 connection.setConnectTimeout(MS_CONNECTION_TIMEOUT);
509 connection.setReadTimeout(MS_CONNECTION_TIMEOUT); 477 connection.setReadTimeout(MS_CONNECTION_TIMEOUT);
510 return connection; 478 return connection;
511 } catch (MalformedURLException e) { 479 } catch (MalformedURLException e) {
512 throw new RequestFailureException("Caught a malformed URL exception. ", e); 480 throw new RequestFailureException("Caught a malformed URL exception. ", e);
513 } catch (IOException e) { 481 } catch (IOException e) {
514 throw new RequestFailureException("Failed to open connection to URL" , e); 482 throw new RequestFailureException("Failed to open connection to URL" , e);
515 } 483 }
516 } 484 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 } 559 }
592 } 560 }
593 561
594 /** 562 /**
595 * Checks if we know about a newer version available than the one we're usin g. This does not 563 * Checks if we know about a newer version available than the one we're usin g. This does not
596 * actually fire any requests over to the server; it just checks the version we stored the last 564 * actually fire any requests over to the server; it just checks the version we stored the last
597 * time we talked to the Omaha server. 565 * time we talked to the Omaha server.
598 * 566 *
599 * NOTE: This function incurs I/O, so don't use it on the main thread. 567 * NOTE: This function incurs I/O, so don't use it on the main thread.
600 */ 568 */
601 public static boolean isNewerVersionAvailable(Context applicationContext) { 569 static boolean isNewerVersionAvailable(Context context) {
602 assert Looper.myLooper() != Looper.getMainLooper(); 570 assert Looper.myLooper() != Looper.getMainLooper();
603 571
604 // This may be explicitly enabled for some channels and for unit tests. 572 // This may be explicitly enabled for some channels and for unit tests.
605 if (!sEnableUpdateDetection) { 573 if (!sEnableUpdateDetection) {
606 return false; 574 return false;
607 } 575 }
608 576
609 // If the market link is bad, don't show an update to avoid frustrating users trying to 577 // If the market link is bad, don't show an update to avoid frustrating users trying to
610 // hit the "Update" button. 578 // hit the "Update" button.
611 if ("".equals(getMarketURL(applicationContext))) { 579 if ("".equals(getMarketURL(context))) {
612 return false; 580 return false;
613 } 581 }
614 582
615 // Compare version numbers. 583 // Compare version numbers.
616 VersionNumberGetter getter = getVersionNumberGetter(); 584 VersionNumberGetter getter = getVersionNumberGetter();
617 String currentStr = getter.getCurrentlyUsedVersion(applicationContext); 585 String currentStr = getter.getCurrentlyUsedVersion(context);
618 String latestStr = 586 String latestStr = getter.getLatestKnownVersion(context, PREF_PACKAGE, P REF_LATEST_VERSION);
619 getter.getLatestKnownVersion(applicationContext, PREF_PACKAGE, P REF_LATEST_VERSION);
620 587
621 VersionNumber currentVersionNumber = VersionNumber.fromString(currentStr ); 588 VersionNumber currentVersionNumber = VersionNumber.fromString(currentStr );
622 VersionNumber latestVersionNumber = VersionNumber.fromString(latestStr); 589 VersionNumber latestVersionNumber = VersionNumber.fromString(latestStr);
623 590
624 if (currentVersionNumber == null || latestVersionNumber == null) { 591 if (currentVersionNumber == null || latestVersionNumber == null) {
625 return false; 592 return false;
626 } 593 }
627 594
628 return currentVersionNumber.isSmallerThan(latestVersionNumber); 595 return currentVersionNumber.isSmallerThan(latestVersionNumber);
629 } 596 }
630 597
631 /** 598 /**
632 * Determine how the Chrome APK arrived on the device. 599 * Determine how the Chrome APK arrived on the device.
633 * @param context Context to pull resources from. 600 * @param context Context to pull resources from.
634 * @return A String indicating the install source. 601 * @return A String indicating the install source.
635 */ 602 */
636 String determineInstallSource(Context context) { 603 String determineInstallSource() {
637 boolean isInSystemImage = (getApplicationFlags() & ApplicationInfo.FLAG_ SYSTEM) != 0; 604 boolean isInSystemImage = (getApplicationFlags() & ApplicationInfo.FLAG_ SYSTEM) != 0;
638 return isInSystemImage ? INSTALL_SOURCE_SYSTEM : INSTALL_SOURCE_ORGANIC; 605 return isInSystemImage ? INSTALL_SOURCE_SYSTEM : INSTALL_SOURCE_ORGANIC;
639 } 606 }
640 607
641 /** 608 /**
642 * Returns the Application's flags, used to determine if Chrome was installe d as part of the 609 * Returns the Application's flags, used to determine if Chrome was installe d as part of the
643 * system image. 610 * system image.
644 * @return The Application's flags. 611 * @return The Application's flags.
645 */ 612 */
646 @VisibleForTesting 613 @VisibleForTesting
647 public int getApplicationFlags() { 614 int getApplicationFlags() {
648 return mApplicationContext.getApplicationInfo().flags; 615 return getApplicationInfo().flags;
649 } 616 }
650 617
651 /** 618 /**
652 * Reads the data back from the file it was saved to. Uses SharedPreference s to handle I/O. 619 * Reads the data back from the file it was saved to. Uses SharedPreference s to handle I/O.
653 * Sanity checks are performed on the timestamps to guard against clock chan ging. 620 * Sanity checks are performed on the timestamps to guard against clock chan ging.
654 */ 621 */
655 @VisibleForTesting 622 @VisibleForTesting
656 void restoreState() { 623 void restoreState() {
657 boolean mustRewriteState = false; 624 boolean mustRewriteState = false;
658 SharedPreferences preferences = 625 SharedPreferences preferences = getSharedPreferences(PREF_PACKAGE, Conte xt.MODE_PRIVATE);
659 mApplicationContext.getSharedPreferences(PREF_PACKAGE, Context.M ODE_PRIVATE);
660 Map<String, ?> items = preferences.getAll(); 626 Map<String, ?> items = preferences.getAll();
661 627
662 // Read out the recorded data. 628 // Read out the recorded data.
663 long currentTime = mBackoffScheduler.getCurrentTime(); 629 long currentTime = getBackoffScheduler().getCurrentTime();
664 mTimestampForNewRequest = 630 mTimestampForNewRequest =
665 getLongFromMap(items, PREF_TIMESTAMP_FOR_NEW_REQUEST, currentTim e); 631 getLongFromMap(items, PREF_TIMESTAMP_FOR_NEW_REQUEST, currentTim e);
666 mTimestampForNextPostAttempt = 632 mTimestampForNextPostAttempt =
667 getLongFromMap(items, PREF_TIMESTAMP_FOR_NEXT_POST_ATTEMPT, curr entTime); 633 getLongFromMap(items, PREF_TIMESTAMP_FOR_NEXT_POST_ATTEMPT, curr entTime);
668 634
669 long requestTimestamp = getLongFromMap(items, PREF_TIMESTAMP_OF_REQUEST, INVALID_TIMESTAMP); 635 long requestTimestamp = getLongFromMap(items, PREF_TIMESTAMP_OF_REQUEST, INVALID_TIMESTAMP);
670 636
671 // If the preference doesn't exist, it's likely that we haven't sent an install event. 637 // If the preference doesn't exist, it's likely that we haven't sent an install event.
672 mSendInstallEvent = getBooleanFromMap(items, PREF_SEND_INSTALL_EVENT, tr ue); 638 mSendInstallEvent = getBooleanFromMap(items, PREF_SEND_INSTALL_EVENT, tr ue);
673 639
674 // Restore the install source. 640 // Restore the install source.
675 String defaultInstallSource = determineInstallSource(mApplicationContext ); 641 String defaultInstallSource = determineInstallSource();
676 mInstallSource = getStringFromMap(items, PREF_INSTALL_SOURCE, defaultIns tallSource); 642 mInstallSource = getStringFromMap(items, PREF_INSTALL_SOURCE, defaultIns tallSource);
677 643
678 // If we're not sending an install event, don't bother restoring the req uest ID: 644 // If we're not sending an install event, don't bother restoring the req uest ID:
679 // the server does not expect to have persisted request IDs for pings or update checks. 645 // the server does not expect to have persisted request IDs for pings or update checks.
680 String persistedRequestId = mSendInstallEvent 646 String persistedRequestId = mSendInstallEvent
681 ? getStringFromMap(items, PREF_PERSISTED_REQUEST_ID, INVALID_REQ UEST_ID) 647 ? getStringFromMap(items, PREF_PERSISTED_REQUEST_ID, INVALID_REQ UEST_ID)
682 : INVALID_REQUEST_ID; 648 : INVALID_REQUEST_ID;
683 649
684 mCurrentRequest = requestTimestamp == INVALID_TIMESTAMP 650 mCurrentRequest = requestTimestamp == INVALID_TIMESTAMP
685 ? null : createRequestData(requestTimestamp, persistedRequestId) ; 651 ? null : createRequestData(requestTimestamp, persistedRequestId) ;
686 652
687 mLatestVersion = getStringFromMap(items, PREF_LATEST_VERSION, ""); 653 mLatestVersion = getStringFromMap(items, PREF_LATEST_VERSION, "");
688 mMarketURL = getStringFromMap(items, PREF_MARKET_URL, ""); 654 mMarketURL = getStringFromMap(items, PREF_MARKET_URL, "");
689 655
690 // If we don't have a timestamp for when we installed Chrome, then set i t to now. 656 // If we don't have a timestamp for when we installed Chrome, then set i t to now.
691 mTimestampOfInstall = getLongFromMap(items, PREF_TIMESTAMP_OF_INSTALL, c urrentTime); 657 mTimestampOfInstall = getLongFromMap(items, PREF_TIMESTAMP_OF_INSTALL, c urrentTime);
692 658
693 // Confirm that the timestamp for the next request is less than the base delay. 659 // Confirm that the timestamp for the next request is less than the base delay.
694 long delayToNewRequest = mTimestampForNewRequest - currentTime; 660 long delayToNewRequest = mTimestampForNewRequest - currentTime;
695 if (delayToNewRequest > MS_BETWEEN_REQUESTS) { 661 if (delayToNewRequest > MS_BETWEEN_REQUESTS) {
696 Log.w(TAG, "Delay to next request (" + delayToNewRequest 662 Log.w(TAG, "Delay to next request (" + delayToNewRequest
697 + ") is longer than expected. Resetting to now."); 663 + ") is longer than expected. Resetting to now.");
698 mTimestampForNewRequest = currentTime; 664 mTimestampForNewRequest = currentTime;
699 mustRewriteState = true; 665 mustRewriteState = true;
700 } 666 }
701 667
702 // Confirm that the timestamp for the next POST is less than the current delay. 668 // Confirm that the timestamp for the next POST is less than the current delay.
703 long delayToNextPost = mTimestampForNextPostAttempt - currentTime; 669 long delayToNextPost = mTimestampForNextPostAttempt - currentTime;
704 if (delayToNextPost > mBackoffScheduler.getGeneratedDelay()) { 670 if (delayToNextPost > getBackoffScheduler().getGeneratedDelay()) {
705 Log.w(TAG, "Delay to next post attempt (" + delayToNextPost 671 Log.w(TAG, "Delay to next post attempt (" + delayToNextPost
706 + ") is greater than expected (" + mBackoffScheduler.getGene ratedDelay() 672 + ") is greater than expected (" + getBackoffScheduler().get GeneratedDelay()
707 + "). Resetting to now."); 673 + "). Resetting to now.");
708 mTimestampForNextPostAttempt = currentTime; 674 mTimestampForNextPostAttempt = currentTime;
709 mustRewriteState = true; 675 mustRewriteState = true;
710 } 676 }
711 677
712 if (mustRewriteState) { 678 if (mustRewriteState) {
713 saveState(); 679 saveState();
714 } 680 }
715 681
716 mStateHasBeenRestored = true; 682 mStateHasBeenRestored = true;
717 } 683 }
718 684
719 /** 685 /**
720 * Writes out the current state to a file. 686 * Writes out the current state to a file.
721 */ 687 */
722 private void saveState() { 688 private void saveState() {
723 SharedPreferences prefs = 689 SharedPreferences prefs = getSharedPreferences(PREF_PACKAGE, Context.MOD E_PRIVATE);
724 mApplicationContext.getSharedPreferences(PREF_PACKAGE, Context.M ODE_PRIVATE);
725 SharedPreferences.Editor editor = prefs.edit(); 690 SharedPreferences.Editor editor = prefs.edit();
726 editor.putBoolean(PREF_SEND_INSTALL_EVENT, mSendInstallEvent); 691 editor.putBoolean(PREF_SEND_INSTALL_EVENT, mSendInstallEvent);
727 setIsFreshInstallOrDataHasBeenCleared(mApplicationContext); 692 setIsFreshInstallOrDataHasBeenCleared(this);
728 editor.putLong(PREF_TIMESTAMP_OF_INSTALL, mTimestampOfInstall); 693 editor.putLong(PREF_TIMESTAMP_OF_INSTALL, mTimestampOfInstall);
729 editor.putLong(PREF_TIMESTAMP_FOR_NEXT_POST_ATTEMPT, mTimestampForNextPo stAttempt); 694 editor.putLong(PREF_TIMESTAMP_FOR_NEXT_POST_ATTEMPT, mTimestampForNextPo stAttempt);
730 editor.putLong(PREF_TIMESTAMP_FOR_NEW_REQUEST, mTimestampForNewRequest); 695 editor.putLong(PREF_TIMESTAMP_FOR_NEW_REQUEST, mTimestampForNewRequest);
731 editor.putLong(PREF_TIMESTAMP_OF_REQUEST, 696 editor.putLong(PREF_TIMESTAMP_OF_REQUEST,
732 hasRequest() ? mCurrentRequest.getCreationTimestamp() : INVALID_ TIMESTAMP); 697 hasRequest() ? mCurrentRequest.getCreationTimestamp() : INVALID_ TIMESTAMP);
733 editor.putString(PREF_PERSISTED_REQUEST_ID, 698 editor.putString(PREF_PERSISTED_REQUEST_ID,
734 hasRequest() ? mCurrentRequest.getRequestID() : INVALID_REQUEST_ ID); 699 hasRequest() ? mCurrentRequest.getRequestID() : INVALID_REQUEST_ ID);
735 editor.putString(PREF_LATEST_VERSION, mLatestVersion == null ? "" : mLat estVersion); 700 editor.putString(PREF_LATEST_VERSION, mLatestVersion == null ? "" : mLat estVersion);
736 editor.putString(PREF_MARKET_URL, mMarketURL == null ? "" : mMarketURL); 701 editor.putString(PREF_MARKET_URL, mMarketURL == null ? "" : mMarketURL);
737 702
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 Boolean value = (Boolean) items.get(key); 776 Boolean value = (Boolean) items.get(key);
812 return value != null ? value : defaultValue; 777 return value != null ? value : defaultValue;
813 } 778 }
814 779
815 /** 780 /**
816 * @return Whether it is either a fresh install or data has been cleared. 781 * @return Whether it is either a fresh install or data has been cleared.
817 * PREF_TIMESTAMP_OF_INSTALL is set within the first few seconds after a fre sh install. 782 * PREF_TIMESTAMP_OF_INSTALL is set within the first few seconds after a fre sh install.
818 * sIsFreshInstallOrDataCleared will be set to true if PREF_TIMESTAMP_OF_INS TALL has not 783 * sIsFreshInstallOrDataCleared will be set to true if PREF_TIMESTAMP_OF_INS TALL has not
819 * been previously set. Else, it will be set to false. sIsFreshInstallOrData Cleared is 784 * been previously set. Else, it will be set to false. sIsFreshInstallOrData Cleared is
820 * guarded by sLock. 785 * guarded by sLock.
821 * @param applicationContext The current application Context. 786 * @param context The current Context.
822 */ 787 */
823 public static boolean isFreshInstallOrDataHasBeenCleared(Context application Context) { 788 public static boolean isFreshInstallOrDataHasBeenCleared(Context context) {
824 return setIsFreshInstallOrDataHasBeenCleared(applicationContext); 789 return setIsFreshInstallOrDataHasBeenCleared(context);
825 } 790 }
826 791
827 private static boolean setIsFreshInstallOrDataHasBeenCleared(Context applica tionContext) { 792 private static boolean setIsFreshInstallOrDataHasBeenCleared(Context context ) {
828 synchronized (sIsFreshInstallLock) { 793 synchronized (sIsFreshInstallLock) {
829 if (sIsFreshInstallOrDataCleared == null) { 794 if (sIsFreshInstallOrDataCleared == null) {
830 SharedPreferences prefs = applicationContext.getSharedPreference s( 795 SharedPreferences prefs = context.getSharedPreferences(
831 PREF_PACKAGE, Context.MODE_PRIVATE); 796 PREF_PACKAGE, Context.MODE_PRIVATE);
832 sIsFreshInstallOrDataCleared = (prefs.getLong(PREF_TIMESTAMP_OF_ INSTALL, -1) == -1); 797 sIsFreshInstallOrDataCleared = (prefs.getLong(PREF_TIMESTAMP_OF_ INSTALL, -1) == -1);
833 } 798 }
834 return sIsFreshInstallOrDataCleared; 799 return sIsFreshInstallOrDataCleared;
835 } 800 }
836 } 801 }
802
803 protected final RequestGenerator getRequestGenerator() {
804 if (mGenerator == null) mGenerator = createRequestGenerator(this);
805 return mGenerator;
806 }
807
808 protected final ExponentialBackoffScheduler getBackoffScheduler() {
809 if (mBackoffScheduler == null) {
810 mBackoffScheduler = createBackoffScheduler(
811 PREF_PACKAGE, this, MS_POST_BASE_DELAY, MS_POST_MAX_DELAY);
812 }
813 return mBackoffScheduler;
814 }
837 } 815 }
OLDNEW
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/omaha/VersionNumberGetter.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698