v146 · Web APIs · Launch Handler

Stop re-queueing LaunchParams on reload

Chrome 146 fixes a bug where reloading a PWA page after a file handling launch would retrigger the launchQueue consumer with the original LaunchParams — including file handles — from the initial launch. After this fix, a reload is treated as a fresh page load with no queued launch parameters.

concepts

  1. Reload Behavior Demo

    Shows the launchQueue consumer in action and illustrates the Chrome 146 fix: reloading the page does not re-fire the consumer with the original LaunchParams. The consumer only fires when launched fresh from the OS or a link.

  2. Before/After Comparison

    Side-by-side explanation of the old behaviour (reload retriggers consumer) vs the Chrome 146 fix (reload is clean), with the code implications for PWA file handler implementations.

  3. Reload counter trace

    Drive open / reload events against pre-146 and 146 panes simultaneously; the duplicate-document trail accumulates on the left and stays clean on the right.

  4. PWA Launch Tester

    "Simulate initial launch" fires a synthetic LaunchParams object and displays it. A "Reload" button in Chrome 146 mode skips the consumer while pre-v146 mode re-fires it with a warning log entry. Counters track reload count and consumer fires per mode. A timestamped LaunchParams consumer log and a code viewer compare v146 vs pre-v146 handler patterns. Real window.launchQueue.setConsumer() is wired when the API is present.

why it shipped

When a PWA is launched to handle a file, it receives a LaunchParams object through launchQueue.setConsumer(). The LaunchParams includes FileSystemFileHandle objects for the files. The bug: if the user refreshed the page, Chrome would re-queue and re-deliver the same LaunchParams from the original launch — causing file-handling logic to run again unexpectedly on reload. Chrome 146 stops this: a reload produces no LaunchParams.

the change

// In a PWA with file handling:
if ('launchQueue' in window) {
  launchQueue.setConsumer(async launchParams => {
    // Before Chrome 146: this ran on EVERY reload after a file launch
    // Chrome 146+: this ONLY runs on actual launches, not on reload

    for (const handle of launchParams.files) {
      const file = await handle.getFile();
      await openInEditor(file);
    }
  });
}

// If your code relied on reload retrigger (unlikely, but possible):
// Store launch state in sessionStorage to survive reloads instead:
launchQueue.setConsumer(launchParams => {
  const state = { files: launchParams.files.map(h => h.name) };
  sessionStorage.setItem('launchState', JSON.stringify(state));
  // Use launchParams.files to actually open files
});

references