Skip to content

Navigations to websites with service worker are being stuck #104

@meyron-island

Description

@meyron-island

I face an issue when navigating to a website while being attached to the page.

simple demo:

import { crx } from './playwright-crx/lib/index.mjs';

const urls = {
  // with service worker
  amazon: 'https://www.amazon.com/',
  // without service worker
  shufersal: 'https://www.shufersal.co.il/online/he/search?text=%D7%97%D7%9C%D7%91',
  // with service worker
  servicenow: 'some-service-now-id(removed mine privacywise)'
};

let crxApp = null;

async function navigateTo(url) {
  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  if (!tab) return;

  // Start crx if not already started
  console.log('Starting crx');
  if (!crxApp) {
    crxApp = await crx.start({ slowMo: 0 });
  }

  // Attach to tab
  console.log('Attaching to tab');
  const page = await crxApp.attach(tab.id);
  console.log('Attached to tab');
  // Navigate using chrome.tabs API
  console.log('Navigating to url');
  await chrome.tabs.update(tab.id, { url });
  console.log('Navigated to url');

  // (Optional: use `page` for any Playwright automation here)

  // Detach when done
  console.log('Detaching from tab');
  await crxApp.detach(tab.id);
  console.log('Detached from tab');
}

document.getElementById('amazon').addEventListener('click', () => {
  navigateTo(urls.amazon);
});

document.getElementById('shufersal').addEventListener('click', () => {
  navigateTo(urls.shufersal);
});

document.getElementById('servicenow').addEventListener('click', () => {
  navigateTo(urls.servicenow);
});

I think I found out the root cause.
Its in CrxTransport.ts file, in line 93 when excluding the service worker:

    else if (message.method === 'Target.setAutoAttach') {
        const [, versionStr] = navigator.userAgent.match(/Chrome\/([0-9]+)./) ?? [];

        // we need to exclude service workers, see:
        // https://github.com/ruifigueira/playwright-crx/issues/1
        // https://chromedevtools.github.io/devtools-protocol/tot/Target/#method-setAutoAttach
        result = await this._send(debuggee, message.method, { ...message.params, filter: [
          { exclude: true, type: 'service_worker' },
          // and these are the defaults:
          // https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetFilter
          { exclude: true, type: 'browser' },
          { exclude: true, type: 'tab' },
          // in versions prior to 126, this fallback doesn't work,
          // but it is necessary for oopif frames to be discoverable in version 126 or greater
          ...(versionStr && parseInt(versionStr, 10) >= 126 ? [{}] : []),
        ] });
      }

This setAutoAttach is running with waitForDebuggerOnStart: true option, That causes all the auto attached targets to wait for a Runtime.runIfWaitingForDebugger command. Playwright sends those commands after a setup he does (adding inspectors to the target etc...).
The issue is when excluding a target type, for some reason the target is still waiting for runIfWaitingForDebugger! Seems like a Chrome Debugger API bug actually.
So, when excluding the service_worker type but sending the Target.setAutoAttach, with waitForDebuggerOnStart: true, we are facing the issue and it looks like the tab is being stuck with a loading state, and the page is not changing. because the service_worker is waiting for runIfWaitingForDebugger, but it will never get it so it will never be loaded. and because we are waiting for all "child" targets (even the excluded - the chrome bug), we are waiting for the service_worker.
After a minute or two it gets a timeout and it continues as usual.

I found out that removing the "{ exclude: true, type: 'service_worker' }," in CrxTransport.ts file will solve the issue because in that way the service_worker will notify with runIfWaitingForDebugger.

I saw that the same line actually solve some issue in the past but I dont really get it... (#1), maybe its irrelevant today.

Would love to hear from you,
Thanks anyway :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions