如何使用 chrome.scripting API 在当前选项卡上执行脚本?[复制]

How do I execute a script on the current tab using chrome.scripting API? [duplicate]

提问人:Luca Etienne Schulz 提问时间:11/16/2023 更新时间:11/20/2023 访问量:22

问:

我尝试为基于 Chromium 的浏览器创建一个简单的自动点击器。我利用了 Manifest V3 中的 和 权限。activeTabscripting

我试图实现的目标

我希望我的自动答题器在我按下时启动,并在再次按下快捷方式时停止。Alt+Shift+K

我收到的错误

我的 Service Worker 控制台在按下以激活当前选项卡上的扩展时返回以下错误。Alt+Shift+K

Uncaught (in promise) ReferenceError: tab is not defined
Context
service-worker.js
Stack Trace
service-worker.js:11 (anonymous function):

Line 11: target: { tabId: tab.id },

我已经尝试过的

我想遵循最佳实践。官方 API 文档使用 a 来获取扩展应在其中运行的选项卡。我不确定我的错误是否是由于访问超出范围的值造成的,但我确信可能有一种简单的方法可以解决我的问题。function getTabId() { ... }


源代码

manifest.json:

{
  "manifest_version": 3,
  "name": "Autoclicker",
  "description": "A simple auto clicker.",
  "version": "0.1",
  "author": "[email protected]",
  "permissions": [
    "activeTab",
    "scripting"
  ],
  "background": {
    "service_worker": "service-worker.js"
  },
  "commands": {
    "toggle-auto-clicker": {
      "description": "Toggle auto clicker",
      "suggested_key": {
        "default": "Alt+Shift+K"
      }
    }
  }
}

service-worker.js:

let autoClickerEnabled = false;

// Toggle auto clicker
chrome.commands.onCommand.addListener(async (command) => {
  if (command === "toggle-auto-clicker") {
    autoClickerEnabled = !autoClickerEnabled;
    console.log("AutoClicker is now " + (autoClickerEnabled ? "enabled" : "disabled"));

    if (autoClickerEnabled) {
      chrome.scripting.executeScript({
        target: { tabId: tab.id },          // <-- error on this line
        files: ['scripts/auto-clicker.js'],
      })
      .then(() => console.log("injected scripts/auto-clicker.js"))
      .catch(err => console.error("Script injection failed: ", err));
    }   
  }
});

auto-clicker.js:

if (typeof autoClickerInterval === 'undefined') {
  let autoClickerInterval = false;
}

document.addEventListener('mousemove', (event) => {
  let mousePosition = { x: event.clientX, y: event.clientY };
});

function simulateClick() {// snip}
function startAutoClicker() {// snip}
function stopAutoClicker() {// snip}

chrome.runtime.onMessage.addListener((message) => {
  if (message === 'startAutoClicker') {
    startAutoClicker();
  } 
  if (message === 'stopAutoClicker') {
    stopAutoClicker();
  }
});
javascript google-chrome-extension manifest.json

评论


答:

0赞 Luca Etienne Schulz 11/16/2023 #1

我设法让我的自动答题器使用 .我在深入:消息传递的核心概念>文章中找到了它的示例代码。chrome.tabs.query

完整文件在下面。service-worker.js

let autoClickerEnabled = false;

// getCurrentTabId() retrieves the ID of the currently active tab
// in the last focused window,
// which is necessary for sending messages to the correct tab.
async function getCurrentTabId() {
  try {
    return (await chrome.tabs.query({ active: true, lastFocusedWindow: true }))[0]?.id;
  } catch (err) {
    console.error("error getting current tab ID: ", err);
    return null;
  }
}

// This function injects the auto-clicker script into the specified tab
// if it's not already injected.
async function injectScriptIfNeeded(tabId) {
  try {
    // Check if the script is already injected
    const [result] = await chrome.scripting.executeScript({
      target: { tabId },
      function: () => window.autoClickerInjected,
    });

    // If the script is not injected, inject it
    if (!result?.result) {
      await chrome.scripting.executeScript({
        target: { tabId },
        files: ['scripts/auto-clicker.js'],
      });

      // After successful injection, mark the script as injected
      await chrome.scripting.executeScript({
        target: { tabId },
        function: () => { window.autoClickerInjected = true; },
      });
    }
  } catch (err) {
    console.error("Failed to inject or check script: ", err);
  }
}


// This async function toggles the state of the extension.
// It sends a message with { toggle: true } to the content script
// running in the current tab. This approach simplifies the logic
// by not requiring the service worker to keep track of the auto-clicker's state.
async function toggleEnableExtension() {
  let currentTabId = await getCurrentTabId();
  if (currentTabId) {
    await injectScriptIfNeeded(currentTabId);
    chrome.tabs.sendMessage(currentTabId, { toggle: true }).catch(err =>
      console.error("failed to send message: ", err)
    );
  };
}