chromium/chrome/test/data/extensions/api_test/scripting/persistent_dynamic_scripts/worker.js

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {openTab} from '/_test_resources/test_util/tabs_util.js';

async function getInjectedElementIds() {
  // We use a setTimeout to ensure any other scripts also injected at
  // `document_idle` have a chance to run.
  await new Promise(resolve => { setTimeout(resolve, 0); });
  let childIds = [];
  for (const child of document.body.children)
    childIds.push(child.id);
  return childIds.sort();
};

// For the first session, register one persistent script and one session script.
async function runFirstSession() {
  let scripts = [
    {
      // A set of the minimal required properties, verifying defaults are
      // properly set and retrieved.
      id: 'minimal_script',
      matches: ['*://*/*'],
      js: ['inject_element.js'],
    },
    {
      // A set of all possible properties, verifying all fields are persisted
      // and retrieved. Note we explicitly set values to non-defaults here to
      // verify the storage.
      id: 'maximal_script',
      matches: ['*://*/*'],
      excludeMatches: ['http://example.com/*'],
      css: ['style.css'],
      js: ['inject_element_2.js'],
      allFrames: true,
      matchOriginAsFallback: true,
      runAt: 'document_end',
      world: chrome.scripting.ExecutionWorld.MAIN,
    },
    {
      // A non-persistent script.
      id: 'non_persistent',
      matches: ['*://*/*'],
      js: ['inject_element_3.js'],
      runAt: 'document_end',
      persistAcrossSessions: false
    }
  ];

  await chrome.scripting.registerContentScripts(scripts);

  const config = await chrome.test.getConfig();
  const url = `http://hostperms.com:${config.testServer.port}/simple.html`;

  let tab = await openTab(url);
  let results = await chrome.scripting.executeScript(
      {target: {tabId: tab.id}, func: getInjectedElementIds});

  chrome.test.assertEq(1, results.length);
  chrome.test.assertEq(['injected', 'injected_2', 'injected_3'],
                       results[0].result);

  chrome.test.succeed();
}

// For the second session, verify that the persistent script registered from the
// first session will still be injected into pages. Then replace the persistent
// script. We also register a persistent script, then update it to not persist.
async function runSecondSession() {
  let scripts = await chrome.scripting.getRegisteredContentScripts();

  const expectedScripts = [
    {
      id: 'minimal_script',
      matches: ['*://*/*'],
      js: ['inject_element.js'],
      allFrames: false,
      matchOriginAsFallback: false,
      persistAcrossSessions: true,
      runAt: 'document_idle',
      world: chrome.scripting.ExecutionWorld.ISOLATED,
    },
    {
      id: 'maximal_script',
      matches: ['*://*/*'],
      excludeMatches: ['http://example.com/*'],
      css: ['style.css'],
      js: ['inject_element_2.js'],
      allFrames: true,
      matchOriginAsFallback: true,
      runAt: 'document_end',
      persistAcrossSessions: true,
      world: chrome.scripting.ExecutionWorld.MAIN,
    },
  ];

  chrome.test.assertEq(expectedScripts, scripts);

  const config = await chrome.test.getConfig();
  const url = `http://hostperms.com:${config.testServer.port}/simple.html`;

  let tab = await openTab(url);
  let results = await chrome.scripting.executeScript(
      {target: {tabId: tab.id}, func: getInjectedElementIds});

  chrome.test.assertEq(1, results.length);
  chrome.test.assertEq(['injected', 'injected_2'], results[0].result);

  await chrome.scripting.unregisterContentScripts();

  // Add two new scripts, and then flip their persistence. The IDs indicate
  // the eventual persistent property.
  scripts = [
    {
      id: 'new_script_persistent',
      matches: ['*://*/*'],
      js: ['inject_element_3.js'],
      runAt: 'document_end',
      persistAcrossSessions: false
    },
    {
      id: 'new_script_not_persistent',
      matches: ['*://*/*'],
      js: ['inject_element_4.js']
    },
  ];

  await chrome.scripting.registerContentScripts(scripts);

  const updates = [
    {id: 'new_script_persistent', persistAcrossSessions: true},
    {id: 'new_script_not_persistent', persistAcrossSessions: false}
  ];

  await chrome.scripting.updateContentScripts(updates);
  chrome.test.succeed();
}

// Verify that the removal and addition of a persistent script from the last
// session is applied into this session, and that updating a script's
// persistAcrossSessions flag to false will not persist it into this session.
async function runThirdSession() {
  let scripts = await chrome.scripting.getRegisteredContentScripts();

  const expectedScripts = [
    {
      id: 'new_script_persistent',
      matches: ['*://*/*'],
      js: ['inject_element_3.js'],
      allFrames: false,
      matchOriginAsFallback: false,
      persistAcrossSessions: true,
      runAt: 'document_end',
      world: chrome.scripting.ExecutionWorld.ISOLATED,
    },
  ];

  chrome.test.assertEq(expectedScripts, scripts);

  const config = await chrome.test.getConfig();
  const url = `http://hostperms.com:${config.testServer.port}/simple.html`;
  let tab = await openTab(url);
  let results = await chrome.scripting.executeScript(
      {target: {tabId: tab.id}, func: getInjectedElementIds});

  chrome.test.assertEq(1, results.length);
  chrome.test.assertEq(['injected_3'], results[0].result);

  chrome.test.succeed();
}

// Attach a dummy listener for onStartup to kick off the service worker on
// every browser start, so we call chrome.test.sendMessage
chrome.runtime.onStartup.addListener(async () => {});

chrome.test.sendMessage('ready',testName => {
  if (testName === 'PRE_PRE_PersistentDynamicContentScripts')
    runFirstSession();
  else if (testName === 'PRE_PersistentDynamicContentScripts')
    runSecondSession();
  else if (testName === 'PersistentDynamicContentScripts')
    runThirdSession();
  else
    chrome.test.fail();
});