├── BackgroundOperationComparison.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── index.bs ├── index.html └── w3c.json /BackgroundOperationComparison.md: -------------------------------------------------------------------------------- 1 | **Purpose of this document:** 2 | 3 | This document is intended as a high level survey of what background capabilities are allowed by operating systems and browsers. 4 | 5 | **Operating Systems** 6 | 7 | All of the major desktop operating systems allow native applications to do significant background work, limited only by scheduling algorithms that prevent starvation of other processes. 8 | 9 | Android has historically had a very open policy for background work, allowing any installed app to do background processing and use network resources. However, that caused extreme battery life and network bandwidth problems for users. In recent releases the OS has started being more restrictive of background operations. In Android Marshmallow, Doze mode was introduced, during which time background processing was limited, and in Nougat, Doze mode has been expanded to be much more aggressive. Additionally, Android is moving to a more controlled model with expansions to the Job Scheduler in Nougat, which gives apps a more restricted set of background operation triggers. 10 | 11 | While Android was historically permissive and is now becoming more restrictive, iOS has followed the opposite path. iOS has always limited the types of apps that can do background processing, although it has expanded those types over time using the Background Execution framework. Particularly interesting is that in iOS7, the ability to respond to push messages and run for 30 seconds was added. Since then, more types of apps have been allowed to run background tasks, and more system services have been developed to allow apps to hand off tasks such as large downloads to the system. 12 | 13 | **References** 14 | 15 | - [Android Doze Mode](https://developer.android.com/training/monitoring-device-state/doze-standby.html) 16 | - [Android Job Scheduler](https://developer.android.com/preview/features/background-optimization.html) 17 | - [iOS Background Execution](https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html) 18 | 19 | **Browsers** 20 | 21 | There are two paths to background operations in browsers: browser extensions and service workers. The two big differences between these are that extensions require a user to explicitly install them, and they are proportionately more powerful. Extensions can run any time the browser is running, and can affect all origins accessed by the browser. Service Workers, in contrast, have limits on how long they can run without a foregrounded page and can only affect their installed origin. 22 | 23 | All major browsers support some form of extensions, and all of them allow unlimited background processing within the browser. Firefox, Chromium, and Opera support very similar mechanisms of background operation called Background Pages. These allow for script execution within the browser at any time. Safari also allows background operation for its extensions, and while the Edge extension framework is still in development, it will likely allow similar abilities for installed extensions. 24 | 25 | Both Chromium based browsers and Firefox support service workers, but they have different levels of allowed background work. Chromium allows service worker processing either in response to a push message or a background sync operation. In the case of the push message, the service worker is required to show a notification if it isn’t in the foreground. In the case of background sync, operation is time limited to 5 minutes. 26 | Firefox allows background service worker activity when triggered by a push message, but limits how often that happens based on a hidden engagement heuristic. Once the service worker has exhausted its internal quota, no future push messages are allowed. 27 | 28 | Edge has publicly stated that service workers will be supported in the browser in the future, but has not released details of their implementation. Safari has released no information. 29 | 30 | **References** 31 | 32 | - [Mozilla Add-On Background Pages](https://developer.mozilla.org/en-US/Add-Ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts) 33 | - [Chromium Extension Background Pages](https://developer.chrome.com/extensions/background_pages) 34 | - [Opera Background Process](https://dev.opera.com/extensions/architecture-overview/) 35 | - [Safari Extension Background operation](https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/ExtensionsOverview/ExtensionsOverview.html#//apple_ref/doc/uid/TP40009977-CH15-SW1) 36 | - [Android Background Sync](https://developers.google.com/web/updates/2015/12/background-sync?hl=en) 37 | - [Mozilla Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers) 38 | 39 | **Conclusion** 40 | 41 | Both native apps and browser extensions are allowed to execute on the user's behalf because the user cared enough about the functionality to install it. In the terms of the Budget API, we're defining that as a level of engagement with the app/extension. Service workers can be installed without a similar up front engagement check to the user, but they do currently require a permission grant to perform any background processing. 42 | 43 | In the future, user agents could allow background processing solely based on measured engagement, rather than relying on coarse grained signals such as permission grants. Any expansion to service worker processing scope must still place limits on the serivce worker, but that should be done in a way that allows developers to provide services to the user. This API is an attempt to provide limits based on user engagement, and give information about those limits to the develoeprs. 44 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Web Platform Incubator Community Group 2 | 3 | This repository is being used for work in the W3C Web Platform Incubator Community Group, governed by the [W3C Community License Agreement (CLA)](http://www.w3.org/community/about/agreements/cla/). To make substantive contributions, you must join the CG. 4 | 5 | If you are not the sole contributor to a contribution (pull request), please identify all 6 | contributors in the pull request comment. 7 | 8 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 9 | 10 | ``` 11 | +@github_username 12 | ``` 13 | 14 | If you added a contributor by mistake, you can remove them in a comment with: 15 | 16 | ``` 17 | -@github_username 18 | ``` 19 | 20 | If you are making a pull request on behalf of someone else but you had no part in designing the 21 | feature, you can remove yourself with the above syntax. 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All Reports in this Repository are licensed by Contributors 2 | under the 3 | [W3C Software and Document License](http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document). 4 | 5 | Contributions to Specifications are made under the 6 | [W3C CLA](https://www.w3.org/community/about/agreements/cla/). 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Web Budget API 2 | [Draft specification](https://wicg.github.io/budget-api/) 3 | 4 | Web applications have been able to execute code, make network requests, and interact 5 | with the user through a browser tab or standalone browser window. This has allowed 6 | users to directly see that a web application is executing code, and generally doing useful things, 7 | on their behalf. 8 | 9 | Following the introduction of the [Push API](https://w3c.github.io/push-api/) and 10 | [Background Synchronization](https://wicg.github.io/BackgroundSync/spec/), this assumption no longer 11 | holds: web applications are now able to both trigger and schedule execution of code in the 12 | background, outside of the user’s control. This brings web application 13 | functionality closer to native applications or browser extensions, 14 | both of which are able to perform extensive 15 | [Background Operations](https://github.com/WICG/budget-api/blob/gh-pages/BackgroundOperationComparison.md). 16 | 17 | In order to protect the user, Chrome has historically required developers to 18 | [display a notification](https://notifications.spec.whatwg.org/) in response to a message. Firefox 19 | grants developers a [budget](https://docs.google.com/document/d/1yYUB4nn9Hu6vPHKp_eN_kXOG47gjteEv8QIf_l18q4w/view) 20 | based on the level of engagement a user has with a website, which is a model that Chrome, with the 21 | release of Chrome 52, has moved to as well. 22 | 23 | In both cases, it's an unknown to the developer whether they _have_ to show a notification. This 24 | eliminates a lot of potential use-cases for the Push API. The 25 | [Budget API](https://wicg.github.io/budget-api/) aims to standardize this concept of budget in 26 | a way that provides value for developers, while not locking user agents into any particular 27 | implementation. 28 | 29 | Today the Budget API focuses on the Push API, but we chose to generalize the concept in order to 30 | _(1)_ be able to provide both immediate and expected values, enabling developers to do near-term 31 | resource planning, _(2)_ be able to extend existing APIs such as Background Sync both to alleviate 32 | the restrictions and to enable developers to request more retries, and _(3)_ enable future resource 33 | consuming APIs such as a Job Scheduler to use the same mechanism. 34 | 35 | This API solely focuses on resource consuming APIs. 36 | 37 | ## Use-cases 38 | - Deciding to _not_ show a notification in response to a low priority push message whose primary 39 | purpose was to synchronize data. 40 | - Deciding whether the origin can schedule a precise timer using a hypothetical Job Scheduler API. 41 | - Deciding on the frequency of server-initiated cache updates of synchronized data. 42 | - Deciding on the server whether there is sufficient budget available to hide previously shown 43 | notifications when the user dismissed them on other devices. 44 | - Deciding to temporarily limit background operations if the budget could be used during an 45 | upcoming sporting event instead. 46 | 47 | ## Examples 48 | 49 | ### 1. Avoid showing low-priority notifications to the user. 50 | ```javascript 51 | self.addEventListener('push', event => { 52 | // Execute the application-specific logic depending on the contents of the 53 | // received push message, for example by storing the received update. 54 | 55 | event.waitUntil(async () => { 56 | const reserved = await navigator.budget.reserve('silent-push'); 57 | if (reserved) { 58 | return; // No need to show a notification. 59 | } 60 | // Not enough budget is available, must show a notification. 61 | return registration.showNotification(...); 62 | }); 63 | }); 64 | ``` 65 | 66 | ### 2. Calculate the number of precise timers that can be used at some point in the future. 67 | ```javascript 68 | async function getPreciseTimersAvailableAt(time) { 69 | const [ cost, budget ] = await Promise.all([ 70 | navigator.budget.getCost('precise-timer'), 71 | navigator.budget.getBudget() 72 | ]); 73 | 74 | for (const state of budget) { 75 | if (state.time <= time) { 76 | continue; 77 | } 78 | 79 | // The |state| occurs after |time|, so return the budget. 80 | return state.budgetAt / cost; 81 | } 82 | 83 | // No budget after |time| is known, so we can't guarantee anything. 84 | return 0; 85 | } 86 | ``` 87 | -------------------------------------------------------------------------------- /index.bs: -------------------------------------------------------------------------------- 1 |
  2 | Title: Web Budget API
  3 | Shortname: budget-api
  4 | Level: 1
  5 | Group: wicg
  6 | Status: ED
  7 | URL: https://wicg.github.io/budget-api/
  8 | Editor: Peter Beverloo, Google, peter@chromium.org
  9 | Abstract: This specification describes an API that can be used to retrieve the amount of budget an origin has available for resource consuming background operations, as well as the cost associated with doing such an operation.
 10 | Repository: WICG/budget-api
 11 | Warning: Obsolete
 12 | 
13 | 14 |
 15 | spec: web-background-sync; urlPrefix: https://wicg.github.io/BackgroundSync/spec/
 16 |     type: dfn
 17 |         text: in the background; url: in-the-background
 18 | spec: push-api; urlPrefix: https://w3c.github.io/push-api/
 19 |     type: dfn
 20 |         text: push message; url: push-message
 21 | spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/
 22 |     urlPrefix: browsers.html
 23 |         type: dfn
 24 |             text: origin; url: concept-origin
 25 |     urlPrefix: infrastructure.html
 26 |         type: dfn
 27 |             text: document; url: document
 28 |             text: in parallel; url: in-parallel
 29 |     urlPrefix: webappapis.html
 30 |         type: dfn
 31 |             text: document environment; url: document-environment
 32 |             text: entry settings object; url: entry-settings-object
 33 |             text: worker environment; url: worker-environment
 34 |         type: interface
 35 |             text: Navigator; url: navigator
 36 |     urlPrefix: workers.html
 37 |         type: dfn
 38 |             text: worker; url: worker
 39 |         type: interface
 40 |             text: WorkerNavigator; url: workernavigator
 41 | spec: promises-guide; urlPrefix: https://www.w3.org/2001/tag/doc/promises-guide#
 42 |     type: dfn
 43 |         text: A new promise; url: a-new-promise
 44 | spec: webidl; urlPrefix: https://heycam.github.io/webidl/
 45 |     type: dfn
 46 |         text: DOMException; url: dfn-DOMException
 47 |     type: interface
 48 |         text: SecurityError; url: securityerror
 49 |         text: sequence; url: idl-sequence
 50 | 
51 | 52 |
53 |

Introduction

54 | This section is non-normative. 55 |

56 | Web Applications have conventionally been able to execute code, make network requests and 57 | interact with the user by means of established interaction, usually through a browser tab. This 58 | has allowed users to associate the presence of a browser tab with the Web Application's ability 59 | to do work on their behalf. 60 |

61 |

62 | Following the introduction of the Push API [[PUSH-API]] and Web Background Synchronization 63 | [[WEB-BACKGROUND-SYNC]], this assumption no longer stands. Web Applications are now able to both 64 | trigger and schedule execution of code in the background, outside of the user’s control. 65 |

66 |

67 | In an effort to mitigate risk to the user, user agents have implemented restrictions such as 68 | time limits on executing code in the background, or a requirement for the Web Application 69 | to use the Web Notification API [[NOTIFICATIONS]] to inform the user of the work they've done. 70 | Those restrictions are often unspecified and left up to the discretion of the user agent. In 71 | some cases, user agents will choose to not enforce these restrictions depending on the intensity 72 | of the user's engagement with the Web Application. 73 |

74 |

75 | This specification describes an API that exposes a budget that can be used by authors to 76 | determine their current budget for resource consuming background operations, as well as 77 | the cost associated with doing a certain background operation. 78 |

79 |

80 | Because this API relates to the ability to do work in the background, which is considered 81 | a privilege, functionality provided by this API is only available in a secure context. 82 |

83 |

84 | An explainer is 85 | available in our GitHub repository. 86 |

87 | 88 |

89 | This specification does not define how user agents establish or store the amount of current 90 | budget. It aims to define an API that exposes sufficient information to make the 91 | budget useful for authors, while not restricting the implementation details and 92 | heuristics specific to a user agent. 93 |

94 | 95 |
96 |

Current budget

97 |

98 | There are various use-cases for needing to know the currently available budget: 99 |

100 | 110 | 111 |
112 |

113 | Determine whether a user visible interaction is required in response to a push message: 114 |

115 |
116 |         self.addEventListener('push', event => {
117 |             // Execute the application-specific logic depending on the contents of the
118 |             // received push message, for example by caching the latest content.
119 | 
120 |             event.waitUntil(
121 |                 navigator.budget.reserve('silent-push').then(reserved => {
122 |                     if (reserved)
123 |                         return;  // No need to show a notification.
124 | 
125 |                     // Not enough budget is available, must show a notification.
126 |                     return registration.showNotification(...);
127 |                 })
128 |             );
129 |         });
130 |       
131 |
132 |
133 | 134 |
135 |

Expected budget

136 |

137 | There are various use-cases for needing to know the budget in advance: 138 |

139 | 152 | 153 |

154 | Add an example that demonstrates a one of these use-cases. 155 |

156 |
157 |
158 | 159 |
160 |

Concepts

161 |

162 | The user engagement with an origin is defined by the intensity of their 163 | interaction with the application by means of navigation, interaction and retention signals. 164 |

165 |

166 | A background operation is the ability for an origin to execute potentially 167 | resource consuming code in the background. 168 |

169 |

170 | The background operation cost is a non-negative number that describes the cost of 171 | executing a background operation on the user's device. 172 |

173 |

174 | An origin has an associated budget, which is a non-negative number derived 175 | from the user engagement that describes how many background operations the 176 | origin is able to do, depending on the associated background operation costs. 177 |

178 |

179 | An origin has an associated list of budget expectations. This starts with the 180 | origin's currently available budget, followed by zero or more entries indicating 181 | the lower bound of available budget at known points in the future. 182 |

183 |

184 | User agents are not required to maintain future-bound budget expectations, but doing so enables 185 | more use-cases for authors. 186 |

187 |

188 | Part of an origin's available budget can be 189 | reserved. This reduces the origin's current budget 190 | by the given cost. 191 |

192 |

193 | The reserved cost of certain background operations could be less than the cost 194 | indicated by {{BudgetService/getCost()}} when the user's device is in favorable 195 | conditions, for example because it's not on battery power. 196 |

197 |
198 | 199 |
200 |

Security and Privacy Considerations

201 | 202 |
203 |

Applicability

204 |

205 | Applicability of the Budget API is limited to potentially resource consuming 206 | background operations—operations that are not sufficiently privacy sensitive to need 207 | express user permission for basic usage. 208 |

209 |

210 | User agents MUST NOT use the Budget API as an alternative to obtaining express user permission 211 | for privacy-sensitive operations such as accurate location access [[GEOLOCATION-API]] and 212 | access to the user's camera and/or microphone [[WEBRTC]]. 213 |

214 |

215 | Examples include Web Background Sync [[WEB-BACKGROUND-SYNC]], which may have execution time 216 | and retry limitations applied by the user agent, and the Push API [[PUSH-API]] in situations 217 | where the effects of a push message are not immediately visible to the user. 218 |

219 | 220 |
221 |

Location Tracking

222 | 223 | 224 |

225 | Fetch requests within background operations may reveal the client’s IP address to the 226 | server after the user left the page. The user agent SHOULD limit tracking by capping the 227 | duration of background operations. 228 |

229 |
230 |
231 | 232 |
233 |

Permissions

234 |

235 | The Budget API provides an alternative to obtaining express user permission where the user 236 | agent believes it can appropriately protect the user for strictly resource consuming 237 | background operations. 238 |

239 |

240 | Both the APIs described in this document, as well as the specifications that depend on this 241 | document, MUST NOT limit the user agent's ability to require express user permission in 242 | addition to budget requirements. 243 |

244 |

245 | User agents that require express user permission for certain background operations MAY 246 | lower or eliminate the background operation cost of such an operation, because the user 247 | has explicitly allowed the Web Application to engage on their behalf. 248 |

249 |
250 |
251 | 252 |
253 |

API

254 | 255 |
256 | 257 |
258 |       [Exposed=Window]
259 |       partial interface Navigator {
260 |           [SameObject] readonly attribute BudgetService budget;
261 |       };
262 |     
263 |
264 |       [Exposed=Worker]
265 |       partial interface WorkerNavigator {
266 |           [SameObject] readonly attribute BudgetService budget;
267 |       };
268 |     
269 | 270 |

271 | The budget attribute's getter must return a {{BudgetService}} 272 | scoped to the entry settings object's origin. 273 |

274 |
275 | 276 |
277 |

The {{BudgetService}} interface

278 |

279 | The {{BudgetService}} interface represents the programmatic interface to the user 280 | agent's budget service. It is available in both document and 281 | worker environments. 282 |

283 | 284 |
285 |       [Exposed=(Window,Worker)]
286 |       interface BudgetService {
287 |           Promise<double> getCost(OperationType operation);
288 |           Promise<sequence<BudgetState>> getBudget();
289 | 
290 |           Promise<boolean> reserve(OperationType operation);
291 |       };
292 |     
293 | 294 |

295 | The getCost() method 296 | returns a promise that will be resolved with the worst-case background operation cost 297 | of the indicated background operation. 298 |

299 |

300 | When invoked, it MUST run the following steps: 301 |

302 |
    303 |
  1. 304 | Let promise be a new promise. 305 |
  2. 306 |
  3. 307 | Let origin be the entry settings object's origin. 308 |
  4. 309 |
  5. 310 | If the origin is not a secure context, reject promise with a 311 | {{SecurityError}} and terminate these steps. 312 |
  6. 313 |
  7. 314 | Return promise and run the following step in parallel: 315 |
      316 |
    1. 317 | Resolve the promise with the worst-case background operation cost 318 | associated with the given operation. 319 |
    2. 320 |
    321 |
  8. 322 |
323 | 324 |

325 | The getBudget() method 326 | returns a promise that will be resolved with a sequence of {{BudgetState}} 327 | objects indicating the expected state of the budget at given times in the future. 328 |

329 |

330 | When invoked, it MUST run the following steps: 331 |

332 |
    333 |
  1. 334 | Let promise be a new promise. 335 |
  2. 336 |
  3. 337 | Let origin be the entry settings object's origin. 338 |
  4. 339 |
  5. 340 | If the origin is not a secure context, reject promise with a 341 | {{SecurityError}} and terminate these steps. 342 |
  6. 343 |
  7. 344 | Return promise and run the following step in parallel: 345 |
      346 |
    1. 347 | Let details be a new {{sequence}}. 348 |
    2. 349 |
    3. 350 | If there are entries in origin's list of budget expectations, for each 351 | entry: 352 | 353 |
        354 |
      1. 355 | Let state be a new {{BudgetState}} instance. 356 |
      2. 357 |
      3. 358 | Set state's {{BudgetState/budgetAt}} attribute to 359 | entry's budget value. 360 |
      4. 361 |
      5. 362 | Set state's {{BudgetState/time}} attribute to the 363 | {{DOMTimeStamp}} representing the final date of entry's validity 364 | in milliseconds since 00:00:00 UTC on 1 January 1970. 365 |
      6. 366 |
      7. 367 | Add state to details. 368 |
      8. 369 |
      370 | 371 | Otherwise: 372 |
        373 |
      1. 374 | Let state be a new {{BudgetState}} instance. 375 |
      2. 376 |
      3. 377 | Set state's {{BudgetState/budgetAt}} attribute to 0. 378 |
      4. 379 |
      5. 380 | Set state's {{BudgetState/time}} attribute to the 381 | {{DOMTimeStamp}} representing the current time in milliseconds since 382 | 00:00:00 UTC on 1 January 1970. 383 |
      6. 384 |
      7. 385 | Add state to details. 386 |
      8. 387 |
      388 |
    4. 389 |
    5. 390 | Resolve the promise with details. 391 |
    6. 392 |
    393 |
  8. 394 |
395 | 396 |

397 | The reserve() method 398 | returns a promise that will be resolved with a boolean indicating whether the requested 399 | budget for operation could be reserved. 400 |

401 |

402 | When invoked, it MUST run the following steps: 403 |

404 |
    405 |
  1. 406 | Let promise be a new promise. 407 |
  2. 408 |
  3. 409 | Let origin be the entry settings object's origin. 410 |
  4. 411 |
  5. 412 | If the origin is not a secure context, reject promise with a 413 | {{SecurityError}} and terminate these steps. 414 |
  6. 415 |
  7. 416 | Return promise and run the following step in parallel: 417 |
      418 |
    1. 419 | Let budget be the amount of budget available to origin. 420 |
    2. 421 |
    3. 422 | Let cost be the background operation cost associated with 423 | operation. 424 |
    4. 425 |
    5. 426 | If cost is greater than budget, resolve the promise with 427 | the boolean false and abort these steps. 428 |
    6. 429 |
    7. 430 | Reserve the cost from origin's 431 | budget and resolve the promise with the boolean true. 432 |
    8. 433 |
    434 |
  8. 435 |
436 |
437 | 438 |
439 |

The {{BudgetState}} interface

440 |

441 | The {{BudgetState}} interface represents the amount of budget available at 442 | a specific point in time. This enables authors to make near-term decisions about how to spend 443 | their budget. 444 |

445 | 446 |
447 |       [Exposed=(Window,Worker)]
448 |       interface BudgetState {
449 |         readonly attribute double budgetAt;
450 |         readonly attribute DOMTimeStamp time;
451 |       };
452 |     
453 | 454 |

455 | The budgetAt attribute's getter must 456 | return the budget at the associated {{BudgetState/time}}. 457 |

458 | 459 |

460 | The time attribute's getter must 461 | return the timestamp representing the time, in milliseconds since 00:00:00 UTC on 1 January 462 | 1970, at which the {{BudgetState/budgetAt}} will be valid. 463 |

464 |
465 | 466 |
467 |

The {{OperationType}} enum

468 |

469 | The {{OperationType}} enumeration describes the known set of background 470 | operations that the Web Budget API caters for. Authors can use this in combination with 471 | {{BudgetService/getCost()}} to interpret their available budget as a 472 | quantifiable set of background operations it can be used for. 473 |

474 | 475 |
476 |       enum OperationType {
477 |         "silent-push"
478 |       };
479 |     
480 | 481 |

482 | The following {{OperationType}} values are defined: 483 |

484 | 491 | 492 |

493 | Specifications are encouraged to extend the {{OperationType}} enumeration with 494 | their own values. Naming consistency with the Permission API [[PERMISSIONS]], where 495 | applicable, is recommended. 496 |

497 |
498 | 499 |
500 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Web Budget API 5 | 6 | 1215 | 1216 | 1217 | 1227 | 1273 | 1302 | 1364 | 1401 | 1459 | 1460 |
1461 |

1462 |

Web Budget API

1463 |

Editor’s Draft,

1464 |
1465 |
1466 |
This version: 1467 |
https://wicg.github.io/budget-api/ 1468 |
Issue Tracking: 1469 |
GitHub 1470 |
Inline In Spec 1471 |
Editor: 1472 |
(Google) 1473 |
1474 |
1475 |
1476 |
1477 | Obsoletion Notice 1478 |

This specification is not being actively maintained, 1479 | and should not be used as a guide for implementations. 1480 | It may be revived in the future, 1481 | but for now should be considered obsolete.

1482 |

If you have questions or comments on this specification, 1483 | please send an email to the editors.

1484 |
1485 |
1486 | 1488 |
1489 |
1490 |
1491 |

Abstract

1492 |

This specification describes an API that can be used to retrieve the amount of budget an origin has available for resource consuming background operations, as well as the cost associated with doing such an operation.

1493 |
1494 |
1495 |

Status of this document

1496 |
1497 |

This specification was published by the Web Platform Incubator Community Group. 1498 | It is not a W3C Standard nor is it on the W3C Standards Track. 1499 | 1500 | Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. 1501 | 1502 | Learn more about W3C Community and Business Groups.

1503 |

1504 |
1505 |
1506 | 1551 |
1552 |
1553 |

1. Introduction

1554 | This section is non-normative. 1555 |

Web Applications have conventionally been able to execute code, make network requests and 1556 | interact with the user by means of established interaction, usually through a browser tab. This 1557 | has allowed users to associate the presence of a browser tab with the Web Application’s ability 1558 | to do work on their behalf.

1559 |

Following the introduction of the Push API [PUSH-API] and Web Background Synchronization [WEB-BACKGROUND-SYNC], this assumption no longer stands. Web Applications are now able to both 1560 | trigger and schedule execution of code in the background, outside of the user’s control.

1561 |

In an effort to mitigate risk to the user, user agents have implemented restrictions such as 1562 | time limits on executing code in the background, or a requirement for the Web Application 1563 | to use the Web Notification API [NOTIFICATIONS] to inform the user of the work they’ve done. 1564 | Those restrictions are often unspecified and left up to the discretion of the user agent. In 1565 | some cases, user agents will choose to not enforce these restrictions depending on the intensity 1566 | of the user’s engagement with the Web Application.

1567 |

This specification describes an API that exposes a budget that can be used by authors to 1568 | determine their current budget for resource consuming background operations, as well as 1569 | the cost associated with doing a certain background operation.

1570 |

Because this API relates to the ability to do work in the background, which is considered 1571 | a privilege, functionality provided by this API is only available in a secure context.

1572 |

An explainer is 1573 | available in our GitHub repository.

1574 |

This specification does not define how user agents establish or store the amount of current budget. It aims to define an API that exposes sufficient information to make the budget useful for authors, while not restricting the implementation details and 1575 | heuristics specific to a user agent.

1576 |
1577 |

1.1. Current budget

1578 |

There are various use-cases for needing to know the currently available budget:

1579 |
    1580 |
  • Deciding to not show a notification in response to a low priority push message 1581 | whose primary purpose was to synchronize data. 1582 |
  • Deciding whether the origin can schedule a precise timer using a hypothetical Job 1583 | Scheduler API. 1584 |
1585 |
1586 | 1587 |

Determine whether a user visible interaction is required in response to a push message:

1588 |
self.addEventListener('push', event => {
1589 |     // Execute the application-specific logic depending on the contents of the
1590 |     // received push message, for example by caching the latest content.
1591 | 
1592 |     event.waitUntil(
1593 |         navigator.budget.reserve('silent-push').then(reserved => {
1594 |             if (reserved)
1595 |                 return;  // No need to show a notification.
1596 | 
1597 |             // Not enough budget is available, must show a notification.
1598 |             return registration.showNotification(...);
1599 |         })
1600 |     );
1601 | });
1602 | 
1603 |
1604 |
1605 |
1606 |

1.2. Expected budget

1607 |

There are various use-cases for needing to know the budget in advance:

1608 |
    1609 |
  • Deciding on the frequency of server-initiated cache updates of synchronized data. 1610 |
  • Deciding on the server whether there is sufficient budget available to hide 1611 | previously shown notifications when the user dismissed them on other devices. 1612 |
  • Deciding to temporarily limit background operations if the budget could be 1613 | used during an upcoming sporting event instead. 1614 |
1615 |

Add an example that demonstrates a one of these use-cases.

1616 |
1617 |
1618 |
1619 |

2. Concepts

1620 |

The user engagement with an origin is defined by the intensity of their 1621 | interaction with the application by means of navigation, interaction and retention signals.

1622 |

A background operation is the ability for an origin to execute potentially 1623 | resource consuming code in the background.

1624 |

The background operation cost is a non-negative number that describes the cost of 1625 | executing a background operation on the user’s device.

1626 |

An origin has an associated budget, which is a non-negative number derived 1627 | from the user engagement that describes how many background operations the origin is able to do, depending on the associated background operation costs.

1628 |

An origin has an associated list of budget expectations. This starts with the origin’s currently available budget, followed by zero or more entries indicating 1629 | the lower bound of available budget at known points in the future.

1630 |

User agents are not required to maintain future-bound budget expectations, but doing so enables 1631 | more use-cases for authors.

1632 |

Part of an origin’s available budget can be reserved. This reduces the origin’s current budget by the given cost.

1633 |

The reserved cost of certain background operations could be less than the cost 1634 | indicated by getCost() when the user’s device is in favorable 1635 | conditions, for example because it’s not on battery power.

1636 |
1637 |
1638 |

3. Security and Privacy Considerations

1639 |
1640 |

3.1. Applicability

1641 |

Applicability of the Budget API is limited to potentially resource consuming background operations—operations that are not sufficiently privacy sensitive to need 1642 | express user permission for basic usage.

1643 |

User agents MUST NOT use the Budget API as an alternative to obtaining express user permission 1644 | for privacy-sensitive operations such as accurate location access [GEOLOCATION-API] and 1645 | access to the user’s camera and/or microphone [WEBRTC].

1646 |

Examples include Web Background Sync [WEB-BACKGROUND-SYNC], which may have execution time 1647 | and retry limitations applied by the user agent, and the Push API [PUSH-API] in situations 1648 | where the effects of a push message are not immediately visible to the user.

1649 |
1650 |

3.1.1. Location Tracking

1651 |

Fetch requests within background operations may reveal the client’s IP address to the 1652 | server after the user left the page. The user agent SHOULD limit tracking by capping the 1653 | duration of background operations.

1654 |
1655 |
1656 |
1657 |

3.2. Permissions

1658 |

The Budget API provides an alternative to obtaining express user permission where the user 1659 | agent believes it can appropriately protect the user for strictly resource consuming background operations.

1660 |

Both the APIs described in this document, as well as the specifications that depend on this 1661 | document, MUST NOT limit the user agent’s ability to require express user permission in 1662 | addition to budget requirements.

1663 |

User agents that require express user permission for certain background operations MAY 1664 | lower or eliminate the background operation cost of such an operation, because the user 1665 | has explicitly allowed the Web Application to engage on their behalf.

1666 |
1667 |
1668 |
1669 |

4. API

1670 |
1671 | 1672 |
[Exposed=Window]
1673 | partial interface Navigator {
1674 |     [SameObject] readonly attribute BudgetService budget;
1675 | };
1676 | 
1677 |
[Exposed=Worker]
1678 | partial interface WorkerNavigator {
1679 |     [SameObject] readonly attribute BudgetService budget;
1680 | };
1681 | 
1682 |

The budget attribute’s getter must return a BudgetService scoped to the entry settings object’s origin.

1683 |
1684 |
1685 |

4.2. The BudgetService interface

1686 |

The BudgetService interface represents the programmatic interface to the user 1687 | agent’s budget service. It is available in both document and worker environments.

1688 |
[Exposed=(Window,Worker)]
1689 | interface BudgetService {
1690 |     Promise<double> getCost(OperationType operation);
1691 |     Promise<sequence<BudgetState>> getBudget();
1692 | 
1693 |     Promise<boolean> reserve(OperationType operation);
1694 | };
1695 | 
1696 |

The getCost() method 1697 | returns a promise that will be resolved with the worst-case background operation cost of the indicated background operation.

1698 |

When invoked, it MUST run the following steps:

1699 |
    1700 |
  1. Let promise be a new promise. 1701 |
  2. Let origin be the entry settings object’s origin. 1702 |
  3. If the origin is not a secure context, reject promise with a SecurityError and terminate these steps. 1703 |
  4. 1704 | Return promise and run the following step in parallel: 1705 |
      1706 |
    1. Resolve the promise with the worst-case background operation cost associated with the given operation. 1707 |
    1708 |
1709 |

The getBudget() method 1710 | returns a promise that will be resolved with a sequence of BudgetState objects indicating the expected state of the budget at given times in the future.

1711 |

When invoked, it MUST run the following steps:

1712 |
    1713 |
  1. Let promise be a new promise. 1714 |
  2. Let origin be the entry settings object’s origin. 1715 |
  3. If the origin is not a secure context, reject promise with a SecurityError and terminate these steps. 1716 |
  4. 1717 | Return promise and run the following step in parallel: 1718 |
      1719 |
    1. Let details be a new sequence. 1720 |
    2. 1721 | If there are entries in origin’s list of budget expectations, for each entry: 1722 |
        1723 |
      1. Let state be a new BudgetState instance. 1724 |
      2. Set state’s budgetAt attribute to entry’s budget value. 1725 |
      3. Set state’s time attribute to the DOMTimeStamp representing the final date of entry’s validity 1726 | in milliseconds since 00:00:00 UTC on 1 January 1970. 1727 |
      4. Add state to details. 1728 |
      1729 |

      Otherwise:

      1730 |
        1731 |
      1. Let state be a new BudgetState instance. 1732 |
      2. Set state’s budgetAt attribute to 0. 1733 |
      3. Set state’s time attribute to the DOMTimeStamp representing the current time in milliseconds since 1734 | 00:00:00 UTC on 1 January 1970. 1735 |
      4. Add state to details. 1736 |
      1737 |
    3. Resolve the promise with details. 1738 |
    1739 |
1740 |

The reserve() method 1741 | returns a promise that will be resolved with a boolean indicating whether the requested 1742 | budget for operation could be reserved.

1743 |

When invoked, it MUST run the following steps:

1744 |
    1745 |
  1. Let promise be a new promise. 1746 |
  2. Let origin be the entry settings object’s origin. 1747 |
  3. If the origin is not a secure context, reject promise with a SecurityError and terminate these steps. 1748 |
  4. 1749 | Return promise and run the following step in parallel: 1750 |
      1751 |
    1. Let budget be the amount of budget available to origin. 1752 |
    2. Let cost be the background operation cost associated with operation. 1753 |
    3. If cost is greater than budget, resolve the promise with 1754 | the boolean false and abort these steps. 1755 |
    4. Reserve the cost from origin’s budget and resolve the promise with the boolean true. 1756 |
    1757 |
1758 |
1759 |
1760 |

4.3. The BudgetState interface

1761 |

The BudgetState interface represents the amount of budget available at 1762 | a specific point in time. This enables authors to make near-term decisions about how to spend 1763 | their budget.

1764 |
[Exposed=(Window,Worker)]
1765 | interface BudgetState {
1766 |   readonly attribute double budgetAt;
1767 |   readonly attribute DOMTimeStamp time;
1768 | };
1769 | 
1770 |

The budgetAt attribute’s getter must 1771 | return the budget at the associated time.

1772 |

The time attribute’s getter must 1773 | return the timestamp representing the time, in milliseconds since 00:00:00 UTC on 1 January 1774 | 1970, at which the budgetAt will be valid.

1775 |
1776 |
1777 |

4.4. The OperationType enum

1778 |

The OperationType enumeration describes the known set of background 1779 | operations that the Web Budget API caters for. Authors can use this in combination with getCost() to interpret their available budget as a 1780 | quantifiable set of background operations it can be used for.

1781 |
enum OperationType {
1782 |   "silent-push"
1783 | };
1784 | 
1785 |

The following OperationType values are defined:

1786 |
    1787 |
  • The silent-push value represents a background 1788 | operation in response to an incoming push message through the Push API that does not 1789 | result in a user visible action. [PUSH-API] 1790 |
1791 |

Specifications are encouraged to extend the OperationType enumeration with 1792 | their own values. Naming consistency with the Permission API [PERMISSIONS], where 1793 | applicable, is recommended.

1794 |
1795 |
1796 |
1797 |
1798 |

Conformance

1799 |

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. 1800 | The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” 1801 | in the normative parts of this document 1802 | are to be interpreted as described in RFC 2119. 1803 | However, for readability, 1804 | these words do not appear in all uppercase letters in this specification.

1805 |

All of the text of this specification is normative 1806 | except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

1807 |

Examples in this specification are introduced with the words “for example” 1808 | or are set apart from the normative text with class="example", like this:

1809 |
This is an example of an informative example.
1810 |

Informative notes begin with the word “Note” 1811 | and are set apart from the normative text with class="note", like this:

1812 |

Note, this is an informative note.

1813 |
1814 | 1943 |

Index

1944 |

Terms defined by this specification

1945 | 1971 | 1977 | 1983 | 1989 | 1996 | 2002 | 2010 | 2016 | 2022 | 2028 | 2035 | 2042 | 2049 | 2057 | 2063 | 2069 | 2075 | 2082 | 2088 |

Terms defined by reference

2089 | 2133 |

References

2134 |

Normative References

2135 |
2136 |
[HTML] 2137 |
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/ 2138 |
[PROMISES-GUIDE] 2139 |
Domenic Denicola. Writing Promise-Using Specifications. 16 February 2016. Finding of the W3C TAG. URL: https://www.w3.org/2001/tag/doc/promises-guide 2140 |
[PUSH-API] 2141 |
Peter Beverloo; et al. Push API. 15 December 2017. WD. URL: https://www.w3.org/TR/push-api/ 2142 |
[RFC2119] 2143 |
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119 2144 |
[SECURE-CONTEXTS] 2145 |
Mike West. Secure Contexts. 15 September 2016. CR. URL: https://www.w3.org/TR/secure-contexts/ 2146 |
[WEB-BACKGROUND-SYNC] 2147 |
Web Background Synchronization. Living Standard. URL: https://wicg.github.io/BackgroundSync/spec/ 2148 |
[WebIDL] 2149 |
Cameron McCormack; Boris Zbarsky; Tobie Langel. Web IDL. 15 December 2016. ED. URL: https://heycam.github.io/webidl/ 2150 |
2151 |

Informative References

2152 |
2153 |
[GEOLOCATION-API] 2154 |
Andrei Popescu. Geolocation API Specification 2nd Edition. 8 November 2016. REC. URL: https://www.w3.org/TR/geolocation-API/ 2155 |
[NOTIFICATIONS] 2156 |
Anne van Kesteren. Notifications API Standard. Living Standard. URL: https://notifications.spec.whatwg.org/ 2157 |
[PERMISSIONS] 2158 |
Mounir Lamouri; Marcos Caceres; Jeffrey Yasskin. Permissions. 25 September 2017. WD. URL: https://www.w3.org/TR/permissions/ 2159 |
[WEBRTC] 2160 |
Adam Bergkvist; et al. WebRTC 1.0: Real-time Communication Between Browsers. 21 June 2018. CR. URL: https://www.w3.org/TR/webrtc/ 2161 |
2162 |

IDL Index

2163 |
[Exposed=Window]
2164 | partial interface Navigator {
2165 |     [SameObject] readonly attribute BudgetService budget;
2166 | };
2167 | 
2168 | [Exposed=Worker]
2169 | partial interface WorkerNavigator {
2170 |     [SameObject] readonly attribute BudgetService budget;
2171 | };
2172 | 
2173 | [Exposed=(Window,Worker)]
2174 | interface BudgetService {
2175 |     Promise<double> getCost(OperationType operation);
2176 |     Promise<sequence<BudgetState>> getBudget();
2177 | 
2178 |     Promise<boolean> reserve(OperationType operation);
2179 | };
2180 | 
2181 | [Exposed=(Window,Worker)]
2182 | interface BudgetState {
2183 |   readonly attribute double budgetAt;
2184 |   readonly attribute DOMTimeStamp time;
2185 | };
2186 | 
2187 | enum OperationType {
2188 |   "silent-push"
2189 | };
2190 | 
2191 | 
2192 |

Issues Index

2193 |
2194 |
Add an example that demonstrates a one of these use-cases.
2195 |
2196 | 2203 | 2216 | 2224 | 2236 | 2242 | 2248 | 2255 | 2262 | 2268 | 2275 | 2282 | 2289 | 2296 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": ["80485"] 3 | , "contacts": ["marcoscaceres"] 4 | , "shortName": "budget-api" 5 | } --------------------------------------------------------------------------------