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.offlinepages; | 5 package org.chromium.chrome.browser.offlinepages; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
| 8 import android.os.Bundle; |
8 | 9 |
| 10 import org.chromium.base.ApplicationStatus; |
9 import org.chromium.base.Callback; | 11 import org.chromium.base.Callback; |
10 import org.chromium.base.Log; | 12 import org.chromium.base.Log; |
11 import org.chromium.base.library_loader.LibraryProcessType; | 13 import org.chromium.base.SysUtils; |
12 import org.chromium.base.library_loader.ProcessInitException; | 14 import org.chromium.base.VisibleForTesting; |
13 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; | 15 import org.chromium.chrome.browser.background_task_scheduler.NativeBackgroundTas
k; |
14 import org.chromium.chrome.browser.offlinepages.interfaces.BackgroundSchedulerPr
ocessor; | |
15 import org.chromium.components.background_task_scheduler.BackgroundTask; | |
16 import org.chromium.components.background_task_scheduler.BackgroundTask.TaskFini
shedCallback; | 16 import org.chromium.components.background_task_scheduler.BackgroundTask.TaskFini
shedCallback; |
17 import org.chromium.components.background_task_scheduler.TaskIds; | 17 import org.chromium.components.background_task_scheduler.TaskIds; |
18 import org.chromium.components.background_task_scheduler.TaskParameters; | 18 import org.chromium.components.background_task_scheduler.TaskParameters; |
19 import org.chromium.content.browser.BrowserStartupController; | |
20 | 19 |
21 /** | 20 /** |
22 * Handles servicing background offlining requests coming via background_task_sc
heduler component. | 21 * Handles servicing of background offlining requests coming via background_task
_scheduler |
| 22 * component. |
23 */ | 23 */ |
24 public class OfflineBackgroundTask implements BackgroundTask { | 24 public class OfflineBackgroundTask extends NativeBackgroundTask { |
25 private static final String TAG = "OPBackgroundTask"; | 25 private static final String TAG = "OfflineBkgrndTask"; |
26 | 26 |
27 BackgroundSchedulerProcessor mBackgroundProcessor; | 27 @Override |
| 28 @StartBeforeNativeResult |
| 29 protected int onStartTaskBeforeNativeLoaded( |
| 30 Context context, TaskParameters taskParameters, TaskFinishedCallback
callback) { |
| 31 assert taskParameters.getTaskId() == TaskIds.OFFLINE_PAGES_BACKGROUND_JO
B_ID; |
28 | 32 |
29 public OfflineBackgroundTask() { | 33 if (!checkConditions(context, taskParameters.getExtras())) { |
30 mBackgroundProcessor = new BackgroundSchedulerProcessorImpl(); | 34 return RESCHEDULE; |
| 35 } |
| 36 |
| 37 return LOAD_NATIVE; |
31 } | 38 } |
32 | 39 |
33 @Override | 40 @Override |
34 public boolean onStartTask( | 41 protected void onStartTaskWithNative( |
35 Context context, TaskParameters taskParameters, TaskFinishedCallback
callback) { | 42 Context context, TaskParameters taskParameters, TaskFinishedCallback
callback) { |
36 assert taskParameters.getTaskId() == TaskIds.OFFLINE_PAGES_BACKGROUND_JO
B_ID; | 43 assert taskParameters.getTaskId() == TaskIds.OFFLINE_PAGES_BACKGROUND_JO
B_ID; |
37 | 44 |
38 // Ensuring that native potion of the browser is launched. | 45 if (!startScheduledProcessing(BackgroundSchedulerProcessor.getInstance()
, context, |
39 launchBrowserIfNecessary(context); | 46 taskParameters.getExtras(), wrapCallback(callback))) { |
| 47 callback.taskFinished(true); |
| 48 return; |
| 49 } |
40 | 50 |
41 return BackgroundOfflinerTask.startBackgroundRequestsImpl( | 51 // Set up backup scheduled task in case processing is killed before Requ
estCoordinator |
42 mBackgroundProcessor, context, taskParameters.getExtras(), wrapC
allback(callback)); | 52 // has a chance to reschedule base on remaining work. |
| 53 BackgroundScheduler.getInstance().scheduleBackup( |
| 54 TaskExtrasPacker.unpackTriggerConditionsFromBundle(taskParameter
s.getExtras()), |
| 55 BackgroundScheduler.FIVE_MINUTES_IN_MILLISECONDS); |
43 } | 56 } |
44 | 57 |
45 @Override | 58 @Override |
46 public boolean onStopTask(Context context, TaskParameters taskParameters) { | 59 protected boolean onStopTaskBeforeNativeLoaded(Context context, TaskParamete
rs taskParameters) { |
47 return mBackgroundProcessor.stopScheduledProcessing(); | 60 assert taskParameters.getTaskId() == TaskIds.OFFLINE_PAGES_BACKGROUND_JO
B_ID; |
| 61 |
| 62 // Native didn't complete loading, but it was supposed to. Presume we ne
ed to reschedule. |
| 63 return true; |
| 64 } |
| 65 |
| 66 @Override |
| 67 protected boolean onStopTaskWithNative(Context context, TaskParameters taskP
arameters) { |
| 68 assert taskParameters.getTaskId() == TaskIds.OFFLINE_PAGES_BACKGROUND_JO
B_ID; |
| 69 |
| 70 return BackgroundSchedulerProcessor.getInstance().stopScheduledProcessin
g(); |
48 } | 71 } |
49 | 72 |
50 @Override | 73 @Override |
51 public void reschedule(Context context) { | 74 public void reschedule(Context context) { |
52 BackgroundScheduler.getInstance(context).rescheduleOfflinePagesTasksOnUp
grade(); | 75 BackgroundScheduler.getInstance().reschedule(); |
53 } | 76 } |
54 | 77 |
55 /** Wraps the callback for code reuse */ | 78 /** Wraps the callback for code reuse */ |
56 private Callback<Boolean> wrapCallback(final TaskFinishedCallback callback)
{ | 79 private Callback<Boolean> wrapCallback(final TaskFinishedCallback callback)
{ |
57 return new Callback<Boolean>() { | 80 return new Callback<Boolean>() { |
58 @Override | 81 @Override |
59 public void onResult(Boolean result) { | 82 public void onResult(Boolean result) { |
60 callback.taskFinished(result); | 83 callback.taskFinished(result); |
61 } | 84 } |
62 }; | 85 }; |
63 } | 86 } |
64 | 87 |
65 private static void launchBrowserIfNecessary(Context context) { | 88 /** |
66 if (BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER) | 89 * Starts scheduled processing and reports UMA. This method does not check f
or current |
67 .isStartupSuccessfullyCompleted()) { | 90 * conditions and should be used together with {@link #checkConditions} to e
nsure that it |
68 return; | 91 * performs the tasks only when it is supposed to. |
| 92 * |
| 93 * @returns Whether processing will be carried out and completion will be in
dicated through a |
| 94 * callback. |
| 95 */ |
| 96 @VisibleForTesting |
| 97 static boolean startScheduledProcessing(BackgroundSchedulerProcessor bridge,
Context context, |
| 98 Bundle taskExtras, Callback<Boolean> callback) { |
| 99 // Gather UMA data to measure how often the user's machine is amenable t
o background |
| 100 // loading when we wake to do a task. |
| 101 long taskScheduledTimeMillis = TaskExtrasPacker.unpackTimeFromBundle(tas
kExtras); |
| 102 OfflinePageUtils.recordWakeupUMA(context, taskScheduledTimeMillis); |
| 103 |
| 104 DeviceConditions deviceConditions = DeviceConditions.getCurrentCondition
s(context); |
| 105 return bridge.startScheduledProcessing(deviceConditions, callback); |
| 106 } |
| 107 |
| 108 /** @returns Whether conditions for running the tasks are met. */ |
| 109 @VisibleForTesting |
| 110 static boolean checkConditions(Context context, Bundle taskExtras) { |
| 111 TriggerConditions triggerConditions = |
| 112 TaskExtrasPacker.unpackTriggerConditionsFromBundle(taskExtras); |
| 113 |
| 114 DeviceConditions deviceConditions = DeviceConditions.getCurrentCondition
s(context); |
| 115 if (!areBatteryConditionsMet(deviceConditions, triggerConditions)) { |
| 116 Log.d(TAG, "Battery percentage is lower than minimum to start proces
sing"); |
| 117 return false; |
69 } | 118 } |
70 | 119 |
71 // TODO(fgorski): This method is taken from ChromeBackgroundService as a
local fix and will | 120 if (!isSvelteConditionsMet()) { |
72 // be removed with BackgroundTaskScheduler supporting GcmNetworkManager
scheduling. | 121 Log.d(TAG, "Application visible on low-end device so deferring backg
round processing"); |
73 try { | 122 return false; |
74 ChromeBrowserInitializer.getInstance(context).handleSynchronousStart
up(); | |
75 } catch (ProcessInitException e) { | |
76 Log.e(TAG, "ProcessInitException while starting the browser process.
"); | |
77 // Since the library failed to initialize nothing in the application
can work, so kill | |
78 // the whole application not just the activity. | |
79 System.exit(-1); | |
80 } | 123 } |
| 124 |
| 125 return true; |
| 126 } |
| 127 |
| 128 /** Whether battery conditions (on power and enough battery percentage) are
met. */ |
| 129 private static boolean areBatteryConditionsMet( |
| 130 DeviceConditions deviceConditions, TriggerConditions triggerConditio
ns) { |
| 131 return deviceConditions.isPowerConnected() |
| 132 || (deviceConditions.getBatteryPercentage() |
| 133 >= triggerConditions.getMinimumBatteryPercentage()); |
| 134 } |
| 135 |
| 136 /** Whether there are no visible activities when on Svelte. */ |
| 137 private static boolean isSvelteConditionsMet() { |
| 138 return !SysUtils.isLowEndDevice() || !ApplicationStatus.hasVisibleActivi
ties(); |
81 } | 139 } |
82 } | 140 } |
OLD | NEW |