Skip to content

Commit

Permalink
Adding support to cancel a headless task
Browse files Browse the repository at this point in the history
On UWP, when the app is executing a Background task, the OS can request it to cancel the task (for various reasons). If the app does not cancel its background task quickly, the OS might terminate the app.
This change adds support to cancel the headless task which can be used by native code to forward the cancellation request from the OS to ths JS code.
  • Loading branch information
psivaram committed Aug 1, 2018
1 parent ed6a5ff commit c3bff25
Showing 1 changed file with 33 additions and 6 deletions.
39 changes: 33 additions & 6 deletions Libraries/ReactNative/AppRegistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ const renderApplication = require('renderApplication');

type Task = (taskData: any) => Promise<void>;
type TaskProvider = () => Task;
type TaskCanceller = () => void;
type TaskCancelProvider = () => TaskCanceller;

export type ComponentProvider = () => React$ComponentType<any>;
export type ComponentProviderInstrumentationHook = (
component: ComponentProvider,
Expand All @@ -47,7 +50,8 @@ export type WrapperComponentProvider = any => React$ComponentType<*>;
const runnables: Runnables = {};
let runCount = 1;
const sections: Runnables = {};
const tasks: Map<string, TaskProvider> = new Map();
const taskProviders: Map<string, TaskProvider> = new Map();
const taskCancelProviders: Map<string, TaskCancelProvider> = new Map();
let componentProviderInstrumentationHook: ComponentProviderInstrumentationHook = (
component: ComponentProvider,
) => component();
Expand Down Expand Up @@ -209,13 +213,23 @@ const AppRegistry = {
*
* See http://facebook.github.io/react-native/docs/appregistry.html#registerheadlesstask
*/
registerHeadlessTask(taskKey: string, task: TaskProvider): void {
if (tasks.has(taskKey)) {
registerHeadlessTask(taskKey: string, taskProvider: TaskProvider): void {
this.registerCancellableHeadlessTask(taskKey, taskProvider, () => () => { /* Cancel is no-op */ });
},

/**
* Register a cancellable headless task. A headless task is a bit of code that runs without a UI.
*
* See http://facebook.github.io/react-native/docs/appregistry.html#registercancellableheadlesstask
*/
registerCancellableHeadlessTask(taskKey: string, taskProvider: TaskProvider, taskCancelProvider: TaskCancelProvider): void {
if (taskProviders.has(taskKey)) {
console.warn(
`registerHeadlessTask called multiple times for same key '${taskKey}'`,
`registerHeadlessTask or registerCancellableHeadlessTask called multiple times for same key '${taskKey}'`,
);
}
tasks.set(taskKey, task);
taskProviders.set(taskKey, taskProvider);
taskCancelProviders.set(taskKey, taskCancelProvider);
},

/**
Expand All @@ -224,7 +238,7 @@ const AppRegistry = {
* See http://facebook.github.io/react-native/docs/appregistry.html#startheadlesstask
*/
startHeadlessTask(taskId: number, taskKey: string, data: any): void {
const taskProvider = tasks.get(taskKey);
const taskProvider = taskProviders.get(taskKey);
if (!taskProvider) {
throw new Error(`No task registered for key ${taskKey}`);
}
Expand All @@ -237,6 +251,19 @@ const AppRegistry = {
NativeModules.HeadlessJsTaskSupport.notifyTaskFinished(taskId);
});
},

/**
* Only called from native code. Cancels a headless task.
*
* See http://facebook.github.io/react-native/docs/appregistry.html#cancelheadlesstask
*/
cancelHeadlessTask(taskId: number, taskKey: string): void {
const taskCancelProvider = taskCancelProviders.get(taskKey);
if (!taskCancelProvider) {
throw new Error(`No task canceller registered for key '${taskKey}'`);
}
taskCancelProvider()();
}
};

BatchedBridge.registerCallableModule('AppRegistry', AppRegistry);
Expand Down

0 comments on commit c3bff25

Please sign in to comment.