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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java

Issue 2577303002: [Downloads] DownloadNotificationService action fallback (Closed)
Patch Set: Ugh source control Created 4 years 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 | « chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java ('k') | no next file » | 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.download; 5 package org.chromium.chrome.browser.download;
6 6
7 import android.app.ActivityManager; 7 import android.app.ActivityManager;
8 import android.app.DownloadManager; 8 import android.app.DownloadManager;
9 import android.app.Notification; 9 import android.app.Notification;
10 import android.app.NotificationManager; 10 import android.app.NotificationManager;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 48
49 /** 49 /**
50 * Service responsible for creating and updating download notifications even aft er 50 * Service responsible for creating and updating download notifications even aft er
51 * Chrome gets killed. 51 * Chrome gets killed.
52 */ 52 */
53 public class DownloadNotificationService extends Service { 53 public class DownloadNotificationService extends Service {
54 static final String EXTRA_DOWNLOAD_GUID = "DownloadGuid"; 54 static final String EXTRA_DOWNLOAD_GUID = "DownloadGuid";
55 static final String EXTRA_DOWNLOAD_FILE_PATH = "DownloadFilePath"; 55 static final String EXTRA_DOWNLOAD_FILE_PATH = "DownloadFilePath";
56 static final String EXTRA_NOTIFICATION_DISMISSED = "NotificationDismissed"; 56 static final String EXTRA_NOTIFICATION_DISMISSED = "NotificationDismissed";
57 static final String EXTRA_IS_SUPPORTED_MIME_TYPE = "IsSupportedMimeType"; 57 static final String EXTRA_IS_SUPPORTED_MIME_TYPE = "IsSupportedMimeType";
58 static final String EXTRA_IS_OFF_THE_RECORD =
59 "org.chromium.chrome.browser.download.IS_OFF_THE_RECORD";
60 static final String EXTRA_IS_OFFLINE_PAGE =
61 "org.chromium.chrome.browser.download.IS_OFFLINE_PAGE";
58 62
59 public static final String ACTION_DOWNLOAD_CANCEL = 63 public static final String ACTION_DOWNLOAD_CANCEL =
60 "org.chromium.chrome.browser.download.DOWNLOAD_CANCEL"; 64 "org.chromium.chrome.browser.download.DOWNLOAD_CANCEL";
61 public static final String ACTION_DOWNLOAD_PAUSE = 65 public static final String ACTION_DOWNLOAD_PAUSE =
62 "org.chromium.chrome.browser.download.DOWNLOAD_PAUSE"; 66 "org.chromium.chrome.browser.download.DOWNLOAD_PAUSE";
63 public static final String ACTION_DOWNLOAD_RESUME = 67 public static final String ACTION_DOWNLOAD_RESUME =
64 "org.chromium.chrome.browser.download.DOWNLOAD_RESUME"; 68 "org.chromium.chrome.browser.download.DOWNLOAD_RESUME";
65 static final String ACTION_DOWNLOAD_RESUME_ALL = 69 static final String ACTION_DOWNLOAD_RESUME_ALL =
66 "org.chromium.chrome.browser.download.DOWNLOAD_RESUME_ALL"; 70 "org.chromium.chrome.browser.download.DOWNLOAD_RESUME_ALL";
67 public static final String ACTION_DOWNLOAD_OPEN = 71 public static final String ACTION_DOWNLOAD_OPEN =
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 || Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { 293 || Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
290 builder.setSubText(duration); 294 builder.setSubText(duration);
291 } else { 295 } else {
292 builder.setContentInfo(duration); 296 builder.setContentInfo(duration);
293 } 297 }
294 } 298 }
295 int notificationId = getNotificationId(downloadGuid); 299 int notificationId = getNotificationId(downloadGuid);
296 if (startTime > 0) builder.setWhen(startTime); 300 if (startTime > 0) builder.setWhen(startTime);
297 301
298 // Clicking on an in-progress download sends the user to see all their d ownloads. 302 // Clicking on an in-progress download sends the user to see all their d ownloads.
299 Intent downloadHomeIntent = buildActionIntent( 303 Intent downloadHomeIntent = buildActionIntent(mContext,
300 mContext, DownloadManager.ACTION_NOTIFICATION_CLICKED, null, nul l); 304 DownloadManager.ACTION_NOTIFICATION_CLICKED, null, isOffTheRecor d, isOfflinePage);
301 builder.setContentIntent(PendingIntent.getBroadcast( 305 builder.setContentIntent(PendingIntent.getBroadcast(
302 mContext, notificationId, downloadHomeIntent, PendingIntent.FLAG _UPDATE_CURRENT)); 306 mContext, notificationId, downloadHomeIntent, PendingIntent.FLAG _UPDATE_CURRENT));
303 builder.setAutoCancel(false); 307 builder.setAutoCancel(false);
304 308
305 Intent pauseIntent = buildActionIntent( 309 Intent pauseIntent = buildActionIntent(
306 mContext, ACTION_DOWNLOAD_PAUSE, downloadGuid, fileName); 310 mContext, ACTION_DOWNLOAD_PAUSE, downloadGuid, isOffTheRecord, i sOfflinePage);
307 builder.addAction(R.drawable.ic_media_control_pause, 311 builder.addAction(R.drawable.ic_media_control_pause,
308 mContext.getResources().getString(R.string.download_notification _pause_button), 312 mContext.getResources().getString(R.string.download_notification _pause_button),
309 buildPendingIntent(pauseIntent, notificationId)); 313 buildPendingIntent(pauseIntent, notificationId));
310 314
311 Intent cancelIntent = buildActionIntent( 315 Intent cancelIntent = buildActionIntent(
312 mContext, ACTION_DOWNLOAD_CANCEL, downloadGuid, fileName); 316 mContext, ACTION_DOWNLOAD_CANCEL, downloadGuid, isOffTheRecord, isOfflinePage);
313 builder.addAction(R.drawable.btn_close_white, 317 builder.addAction(R.drawable.btn_close_white,
314 mContext.getResources().getString(R.string.download_notification _cancel_button), 318 mContext.getResources().getString(R.string.download_notification _cancel_button),
315 buildPendingIntent(cancelIntent, notificationId)); 319 buildPendingIntent(cancelIntent, notificationId));
316 320
317 updateNotification(notificationId, builder.build()); 321 updateNotification(notificationId, builder.build());
318 322
319 int itemType = isOfflinePage ? DownloadSharedPreferenceEntry.ITEM_TYPE_O FFLINE_PAGE 323 int itemType = isOfflinePage ? DownloadSharedPreferenceEntry.ITEM_TYPE_O FFLINE_PAGE
320 : DownloadSharedPreferenceEntry.ITEM_TYPE_D OWNLOAD; 324 : DownloadSharedPreferenceEntry.ITEM_TYPE_D OWNLOAD;
321 addOrReplaceSharedPreferenceEntry(new DownloadSharedPreferenceEntry(noti ficationId, 325 addOrReplaceSharedPreferenceEntry(new DownloadSharedPreferenceEntry(noti ficationId,
322 isOffTheRecord, canDownloadWhileMetered, downloadGuid, fileName, itemType, true)); 326 isOffTheRecord, canDownloadWhileMetered, downloadGuid, fileName, itemType, true));
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 return; 375 return;
372 } 376 }
373 377
374 String contentText = mContext.getResources().getString( 378 String contentText = mContext.getResources().getString(
375 R.string.download_notification_paused); 379 R.string.download_notification_paused);
376 NotificationCompat.Builder builder = buildNotification( 380 NotificationCompat.Builder builder = buildNotification(
377 R.drawable.ic_download_pause, entry.fileName, contentText); 381 R.drawable.ic_download_pause, entry.fileName, contentText);
378 382
379 // Clicking on an in-progress download sends the user to see all their d ownloads. 383 // Clicking on an in-progress download sends the user to see all their d ownloads.
380 Intent downloadHomeIntent = buildActionIntent( 384 Intent downloadHomeIntent = buildActionIntent(
381 mContext, DownloadManager.ACTION_NOTIFICATION_CLICKED, null, nul l); 385 mContext, DownloadManager.ACTION_NOTIFICATION_CLICKED, null, fal se, false);
382 builder.setContentIntent(PendingIntent.getBroadcast(mContext, entry.noti ficationId, 386 builder.setContentIntent(PendingIntent.getBroadcast(mContext, entry.noti ficationId,
383 downloadHomeIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 387 downloadHomeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
384 builder.setAutoCancel(false); 388 builder.setAutoCancel(false);
385 389
386 Intent resumeIntent = buildActionIntent(mContext, ACTION_DOWNLOAD_RESUME , 390 Intent resumeIntent = buildActionIntent(mContext, ACTION_DOWNLOAD_RESUME ,
387 entry.downloadGuid, entry.fileName); 391 entry.downloadGuid, entry.isOffTheRecord, entry.isOfflinePage()) ;
388 builder.addAction(R.drawable.ic_get_app_white_24dp, 392 builder.addAction(R.drawable.ic_get_app_white_24dp,
389 mContext.getResources().getString(R.string.download_notification _resume_button), 393 mContext.getResources().getString(R.string.download_notification _resume_button),
390 buildPendingIntent(resumeIntent, entry.notificationId)); 394 buildPendingIntent(resumeIntent, entry.notificationId));
391 395
392 Intent cancelIntent = buildActionIntent(mContext, ACTION_DOWNLOAD_CANCEL , 396 Intent cancelIntent = buildActionIntent(mContext, ACTION_DOWNLOAD_CANCEL ,
393 entry.downloadGuid, entry.fileName); 397 entry.downloadGuid, entry.isOffTheRecord, entry.isOfflinePage()) ;
394 builder.addAction(R.drawable.btn_close_white, 398 builder.addAction(R.drawable.btn_close_white,
395 mContext.getResources().getString(R.string.download_notification _cancel_button), 399 mContext.getResources().getString(R.string.download_notification _cancel_button),
396 buildPendingIntent(cancelIntent, entry.notificationId)); 400 buildPendingIntent(cancelIntent, entry.notificationId));
397 401
398 Intent dismissIntent = new Intent(cancelIntent); 402 Intent dismissIntent = new Intent(cancelIntent);
399 dismissIntent.putExtra(EXTRA_NOTIFICATION_DISMISSED, true); 403 dismissIntent.putExtra(EXTRA_NOTIFICATION_DISMISSED, true);
400 builder.setDeleteIntent(buildPendingIntent(dismissIntent, entry.notifica tionId)); 404 builder.setDeleteIntent(buildPendingIntent(dismissIntent, entry.notifica tionId));
401 405
402 updateNotification(entry.notificationId, builder.build()); 406 updateNotification(entry.notificationId, builder.build());
403 // Update the SharedPreference entry with the new isAutoResumable value. 407 // Update the SharedPreference entry with the new isAutoResumable value.
(...skipping 18 matching lines...) Expand all
422 String downloadGuid, String filePath, String fileName, long systemDo wnloadId, 426 String downloadGuid, String filePath, String fileName, long systemDo wnloadId,
423 boolean isOfflinePage, boolean isSupportedMimeType) { 427 boolean isOfflinePage, boolean isSupportedMimeType) {
424 int notificationId = getNotificationId(downloadGuid); 428 int notificationId = getNotificationId(downloadGuid);
425 NotificationCompat.Builder builder = buildNotification( 429 NotificationCompat.Builder builder = buildNotification(
426 R.drawable.offline_pin, fileName, 430 R.drawable.offline_pin, fileName,
427 mContext.getResources().getString(R.string.download_notification _completed)); 431 mContext.getResources().getString(R.string.download_notification _completed));
428 ComponentName component = new ComponentName( 432 ComponentName component = new ComponentName(
429 mContext.getPackageName(), DownloadBroadcastReceiver.class.getNa me()); 433 mContext.getPackageName(), DownloadBroadcastReceiver.class.getNa me());
430 Intent intent; 434 Intent intent;
431 if (isOfflinePage) { 435 if (isOfflinePage) {
432 intent = buildActionIntent( 436 intent = buildActionIntent(mContext, ACTION_DOWNLOAD_OPEN, downloadG uid, false, true);
433 mContext, ACTION_DOWNLOAD_OPEN, downloadGuid, fileName);
434 } else { 437 } else {
435 intent = new Intent(DownloadManager.ACTION_NOTIFICATION_CLICKED); 438 intent = new Intent(DownloadManager.ACTION_NOTIFICATION_CLICKED);
436 long[] idArray = {systemDownloadId}; 439 long[] idArray = {systemDownloadId};
437 intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_ID S, idArray); 440 intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_ID S, idArray);
438 intent.putExtra(EXTRA_DOWNLOAD_FILE_PATH, filePath); 441 intent.putExtra(EXTRA_DOWNLOAD_FILE_PATH, filePath);
439 intent.putExtra(EXTRA_IS_SUPPORTED_MIME_TYPE, isSupportedMimeType); 442 intent.putExtra(EXTRA_IS_SUPPORTED_MIME_TYPE, isSupportedMimeType);
440 } 443 }
441 intent.setComponent(component); 444 intent.setComponent(component);
442 builder.setContentIntent(PendingIntent.getBroadcast( 445 builder.setContentIntent(PendingIntent.getBroadcast(
443 mContext, notificationId, intent, PendingIntent.FLAG_UPDATE_CURR ENT)); 446 mContext, notificationId, intent, PendingIntent.FLAG_UPDATE_CURR ENT));
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 private PendingIntent buildPendingIntent(Intent intent, int notificationId) { 510 private PendingIntent buildPendingIntent(Intent intent, int notificationId) {
508 return PendingIntent.getBroadcast( 511 return PendingIntent.getBroadcast(
509 mContext, notificationId, intent, PendingIntent.FLAG_UPDATE_CURR ENT); 512 mContext, notificationId, intent, PendingIntent.FLAG_UPDATE_CURR ENT);
510 } 513 }
511 514
512 /** 515 /**
513 * Helper method to build an download action Intent from the provided inform ation. 516 * Helper method to build an download action Intent from the provided inform ation.
514 * @param context {@link Context} to pull resources from. 517 * @param context {@link Context} to pull resources from.
515 * @param action Download action to perform. 518 * @param action Download action to perform.
516 * @param downloadGuid GUID of the download. 519 * @param downloadGuid GUID of the download.
517 * @param fileName Name of the download file. 520 * @param isOffTheRecord Whether the download is incognito.
521 * @param isOfflinePage Whether the download represents an Offline Page.
518 */ 522 */
519 static Intent buildActionIntent(Context context, String action, String downl oadGuid, 523 static Intent buildActionIntent(Context context, String action, String downl oadGuid,
520 String fileName) { 524 boolean isOffTheRecord, boolean isOfflinePage) {
521 ComponentName component = new ComponentName( 525 ComponentName component = new ComponentName(
522 context.getPackageName(), DownloadBroadcastReceiver.class.getNam e()); 526 context.getPackageName(), DownloadBroadcastReceiver.class.getNam e());
523 Intent intent = new Intent(action); 527 Intent intent = new Intent(action);
524 intent.setComponent(component); 528 intent.setComponent(component);
525 intent.putExtra(EXTRA_DOWNLOAD_GUID, downloadGuid); 529 intent.putExtra(EXTRA_DOWNLOAD_GUID, downloadGuid);
530 intent.putExtra(EXTRA_IS_OFF_THE_RECORD, isOffTheRecord);
531 intent.putExtra(EXTRA_IS_OFFLINE_PAGE, isOfflinePage);
526 return intent; 532 return intent;
527 } 533 }
528 534
529 /** 535 /**
530 * Builds a notification to be displayed. 536 * Builds a notification to be displayed.
531 * @param iconId Id of the notification icon. 537 * @param iconId Id of the notification icon.
532 * @param title Title of the notification. 538 * @param title Title of the notification.
533 * @param contentText Notification content text to be displayed. 539 * @param contentText Notification content text to be displayed.
534 * @return notification builder that builds the notification to be displayed 540 * @return notification builder that builds the notification to be displayed
535 */ 541 */
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 return getDownloadSharedPreferenceEntry(guid); 586 return getDownloadSharedPreferenceEntry(guid);
581 } 587 }
582 588
583 /** 589 /**
584 * Helper method to launch the browser process and handle a download operati on that is included 590 * Helper method to launch the browser process and handle a download operati on that is included
585 * in the given intent. 591 * in the given intent.
586 * @param intent Intent with the download operation. 592 * @param intent Intent with the download operation.
587 */ 593 */
588 private void handleDownloadOperation(final Intent intent) { 594 private void handleDownloadOperation(final Intent intent) {
589 final DownloadSharedPreferenceEntry entry = getDownloadEntryFromIntent(i ntent); 595 final DownloadSharedPreferenceEntry entry = getDownloadEntryFromIntent(i ntent);
590 if (entry == null) return; 596 if (entry == null) {
597 handleDownloadOperationForMissingNotification(intent);
598 return;
599 }
600
591 if (intent.getAction() == ACTION_DOWNLOAD_PAUSE) { 601 if (intent.getAction() == ACTION_DOWNLOAD_PAUSE) {
592 // If browser process already goes away, the download should have al ready paused. Do 602 // If browser process already goes away, the download should have al ready paused. Do
593 // nothing in that case. 603 // nothing in that case.
594 if (!DownloadManagerService.hasDownloadManagerService()) { 604 if (!DownloadManagerService.hasDownloadManagerService()) {
595 notifyDownloadPaused(entry.downloadGuid, !entry.isOffTheRecord, false); 605 notifyDownloadPaused(entry.downloadGuid, !entry.isOffTheRecord, false);
596 return; 606 return;
597 } 607 }
598 } else if (intent.getAction() == ACTION_DOWNLOAD_RESUME) { 608 } else if (intent.getAction() == ACTION_DOWNLOAD_RESUME) {
599 boolean metered = DownloadManagerService.isActiveNetworkMetered(mCon text); 609 boolean metered = DownloadManagerService.isActiveNetworkMetered(mCon text);
600 if (!entry.canDownloadWhileMetered) { 610 if (!entry.canDownloadWhileMetered) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 try { 678 try {
669 ChromeBrowserInitializer.getInstance(mContext).handlePreNativeStartu p(parts); 679 ChromeBrowserInitializer.getInstance(mContext).handlePreNativeStartu p(parts);
670 ChromeBrowserInitializer.getInstance(mContext).handlePostNativeStart up(true, parts); 680 ChromeBrowserInitializer.getInstance(mContext).handlePostNativeStart up(true, parts);
671 } catch (ProcessInitException e) { 681 } catch (ProcessInitException e) {
672 Log.e(TAG, "Unable to load native library.", e); 682 Log.e(TAG, "Unable to load native library.", e);
673 ChromeApplication.reportStartupErrorAndExit(e); 683 ChromeApplication.reportStartupErrorAndExit(e);
674 } 684 }
675 } 685 }
676 686
677 /** 687 /**
688 * Handles operations for downloads that the DownloadNotificationService is unaware of.
689 *
690 * This can happen because the DownloadNotificationService learn about downl oads later than
691 * Download Home does, and may not yet have a DownloadSharedPreferenceEntry for the item.
692 *
693 * TODO(qinmin): Talk with dfalcantara@ about whether this is the best path forward.
694 */
695 private void handleDownloadOperationForMissingNotification(Intent intent) {
696 String action = intent.getAction();
697 String downloadGuid = IntentUtils.safeGetStringExtra(intent, EXTRA_DOWNL OAD_GUID);
698 boolean isOffTheRecord =
699 IntentUtils.safeGetBooleanExtra(intent, EXTRA_IS_OFF_THE_RECORD, false);
700 int itemType = IntentUtils.safeGetBooleanExtra(intent, EXTRA_IS_OFFLINE_ PAGE, false)
701 ? DownloadSharedPreferenceEntry.ITEM_TYPE_OFFLINE_PAGE
702 : DownloadSharedPreferenceEntry.ITEM_TYPE_DOWNLOAD;
703 if (itemType != DownloadSharedPreferenceEntry.ITEM_TYPE_DOWNLOAD) return ;
704
705 // Pass information directly to the DownloadManagerService.
706 if (TextUtils.equals(action, ACTION_DOWNLOAD_CANCEL)) {
707 getServiceDelegate(itemType).cancelDownload(downloadGuid, isOffTheRe cord, false);
708 } else if (TextUtils.equals(action, ACTION_DOWNLOAD_PAUSE)) {
709 getServiceDelegate(itemType).pauseDownload(downloadGuid, isOffTheRec ord);
710 } else if (TextUtils.equals(action, ACTION_DOWNLOAD_RESUME)) {
711 DownloadInfo info = new DownloadInfo.Builder()
712 .setDownloadGuid(downloadGuid)
713 .setIsOffTheRecord(isOffTheRecord)
714 .build();
715 getServiceDelegate(itemType).resumeDownload(new DownloadItem(false, info), true);
716 }
717 }
718
719 /**
678 * Gets appropriate download delegate that can handle interactions with down load item referred 720 * Gets appropriate download delegate that can handle interactions with down load item referred
679 * to by the entry. 721 * to by the entry.
680 * @param forOfflinePage Whether the service should deal with offline pages or downloads. 722 * @param forOfflinePage Whether the service should deal with offline pages or downloads.
681 * @return delegate for interactions with the entry 723 * @return delegate for interactions with the entry
682 */ 724 */
683 DownloadServiceDelegate getServiceDelegate(int downloadItemType) { 725 DownloadServiceDelegate getServiceDelegate(int downloadItemType) {
684 if (downloadItemType == DownloadSharedPreferenceEntry.ITEM_TYPE_OFFLINE_ PAGE) { 726 if (downloadItemType == DownloadSharedPreferenceEntry.ITEM_TYPE_OFFLINE_ PAGE) {
685 return OfflinePageDownloadBridge.getDownloadServiceDelegate(); 727 return OfflinePageDownloadBridge.getDownloadServiceDelegate();
686 } 728 }
687 if (downloadItemType != DownloadSharedPreferenceEntry.ITEM_TYPE_DOWNLOAD ) { 729 if (downloadItemType != DownloadSharedPreferenceEntry.ITEM_TYPE_DOWNLOAD ) {
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 return context.getString(R.string.remaining_duration_minutes, minute s); 930 return context.getString(R.string.remaining_duration_minutes, minute s);
889 } else if (minutes > 0) { 931 } else if (minutes > 0) {
890 return context.getString(R.string.remaining_duration_one_minute); 932 return context.getString(R.string.remaining_duration_one_minute);
891 } else if (seconds == 1) { 933 } else if (seconds == 1) {
892 return context.getString(R.string.remaining_duration_one_second); 934 return context.getString(R.string.remaining_duration_one_second);
893 } else { 935 } else {
894 return context.getString(R.string.remaining_duration_seconds, second s); 936 return context.getString(R.string.remaining_duration_seconds, second s);
895 } 937 }
896 } 938 }
897 } 939 }
OLDNEW
« no previous file with comments | « chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698