1 of 18

Transfer Size Policy and Pause Document APIs

Expanding Content Policies

TPAC - Nov 6th 2017

Josh Karlin

jkarlin@chromium.org

2 of 18

Why is my phone warm?

  • Third-party frames sometimes use excessive data (e.g., looped uncacheable video)
    • This costs the user money
    • Poor loading performance
  • Third-party frames sometimes use excessive CPU (e.g., bitcoin mining)
    • Battery drain
    • Janky experience

Last week a small webpage burned up 800MB ($8 on Google FI) on my wife’s phone. Presumably this wasn’t intentional.

3 of 18

What can we do?

  • FeaturePolicy and SandBox limit the API surface of frames
    • We need something similar that limits a frame’s resource usage
  • Provide APIs so that developers can constrain resources available to frames
    • First-party developers should be able to constrain third-party content
    • The third-party should be able to constrain itself
  • The User Agent should be able to use the same specifications to intervene on the user’s behalf

4 of 18

Moving Forward

Let’s make it possible for the UA and developers to constrain third-party content by limiting access to the network, memory, and CPU

There are lots of ways we could do this, and here’s a start:

  • Transfer Size Policy
    • Fire event when frame gets above X network bytes
  • Pause Document
    • Pauses any combination of script, loading, and rendering in an iframe

5 of 18

Counts the network bytes used by an iframe and its descendants

Fires a bubbling event (transferexceeded) on parent iframe element when given threshold is exceeded

The parent frame can respond however it likes:

  • Inform the user
  • Log the event
  • Unload the frame
  • Pause the frame

6 of 18

Transfer Size Policy - https://github.com/WICG/transfer-size

This leaks size information to the embedding frame.

  • We should mitigate the leak as much as possible, by:
    • Padding the threshold size with a random number of bytes if the frame contains resources x-origin to the embedder
    • Limiting the number of events per top-level navigation

7 of 18

Basic detection of large iframe:

<script>� function onBigFrame(event) {� alert("Frame is too big!");� }� </script>�� <iframe id="foo" ontransferexceeded="onBigFrame(event)" transfersize="300" src="...">

8 of 18

Breakdown by resource type:

<script>� function onBigFrame(event) {� log("Frame went over its javascript budget. FIX!");� }� </script>

<iframe id="foo" ontransferexceeded="onBigFrame(event)" transfersize="script:100, total:500" src="...">

9 of 18

Can be set by headers as well:

transfersizes: {"default":"100", "self":"*", "*.example.com":"style:50, total:500"}

<script>� document.ontransferexceeded=onBigFrame;� </script>

10 of 18

Transfer Size Demo

  1. Load an iframe with a transfersize limit of 10KB
  2. iframe has a button that, when clicked, loads a 4KB resource
  3. Alert pops up once the limit is reached

11 of 18

Pause Document, an effective response

Want to stop a heavy frame from using more resources

But want the user to be able to resume the frame’s activity if it’s useful to them

Hence, iframe pause and unpause

* Also useful to pause off-screen frames to improve the on-screen experience

12 of 18

await frameElement.pause({loading: true, rendering: false, script: false});

await frameElement.unpause();

frameElement.paused();

  • Pausing/Unpausing applies to an iframe and all of its descendants
  • The UA can pause, or script can
    • Script can’t unpause a UA intervention
  • If a frame is paused twice, the options are merged together (union operation)
  • The frame can be unpaused, so we have to try not to break it

13 of 18

  • Pause Loading:
    • Existing resource requests continue (so page can be resumed later)
    • New requests are queued
    • Websockets?

await frameElement.pause({loading: true});

14 of 18

  • Pause Rendering:
    • The frame stops its rendering pipeline
    • Video stops
    • Animated images stop
    • CSS animations stop
    • The UA can cause a render when necessary
      • E.g., frame resized

await frameElement.pause({rendering: true});

15 of 18

  • Pause Script:
    • Any current task running in the frame completes
    • Events and tasks that pertain to the frame are queued
    • UI Events for the frame are discarded
    • rAF is delayed until resumption

await frameElement.pause({script: true});

16 of 18

Pause Document Demo

  • Load an iframe with a transfersize limit of 10KB
  • iframe has a button that, when clicked, loads a 4KB resource
  • Alert pops up once the limit is reached
  • Loading is paused in the frame

17 of 18

For future discussion

  • CPU and Network Throttles
    • Throttle bandwidth
    • Throttle rate that frame’s tasks are run
    • Lower priority of frame’s tasks

18 of 18

Thank you!