| 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 |