🤳

[tabs.captureVisibleTab] 現在開いてるページのスクリーンショットを撮る

2023/11/07に公開

.
├── background.js
├── manifest.json
└── popup
    ├── popup.html
    └── popup.js
manifest.json
{
  "manifest_version": 3,
  "name": "ScreenShot Tab",
  "description": "現在のタブを撮影",
  "version": "1.0.0",
  "permissions": ["tabs", "activeTab"],
  "action": { "default_popup": "popup/popup.html" },
  "background": { "service_worker": "background.js" }
}
popup/popup.html
<!DOCTYPE html>
<html>
<head>
  <title>Take Screenshot</title>
</head>
<body>
  <button id="screenshotButton">Take Screenshot</button>
  <script src="popup.js"></script>
</body>
</html>
popup/popup.js
document.getElementById("screenshotButton").addEventListener("click", async () => {
  try {
    const response = await chrome.runtime.sendMessage({ type: "takeScreenshot" });
    if (response.dataUrl) {
      const img = document.createElement("img");
      img.src = response.dataUrl;
      document.body.appendChild(img);
    }
  } catch (error) {
    console.error("Error sending message:", error);
  }
});
background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === "takeScreenshot") {
    const option = { active: true, currentWindow: true } // 現在閲覧しているタブ
    chrome.tabs.query(option, (tabs) => {
      const activeTab = tabs[0];
      if (!activeTab) {
        sendResponse({ error: "No active tab." });
        return;
      }
      chrome.tabs.captureVisibleTab(activeTab.windowId, { format: "png" }, (dataUrl) => {
        if (chrome.runtime.lastError) {
          sendResponse({ error: chrome.runtime.lastError.message });
          return;
        }
        sendResponse({ dataUrl: dataUrl }); // スクリーンショットのデータURLを返す
      });
    });
    return true;
  }
});
  • スクリーンショットは現在アクティブなタブでしか取得できない

  • 生成される文字列が、画像ファイルのバイナリデータをBase64でエンコードしたもの。画像データはローカルのどこにも保存おらず、文字列そのものが画像データ。なので保存するときはchrome.storage.*で保存しておく。

  • 1秒間にキャプチャできる回数は決まっている。あまりに連続で撮影を続けるとUnchecked runtime.lastError: This request exceeds the MAX_CAPTURE_VISIBLE_TAB_CALLS_PER_SECOND quota.というエラーが出る。定期的な撮影をしてる拡張機能では400msにするとエラーが出なくなる報告がある。一方、このサンプルアプリはユーザーによるので取りこぼしが発生する可能性もある。そこは仕方がない。

  • 新規タブを開いたときに次のようなエラーが出る。特殊なページを開いたときはおそらく撮影できないのでそれのエラーだろう。通常使うように検索したりクリックする状況ではこのエラーは出ないので放置してる。

Unchecked runtime.lastError: The 'activeTab' permission is not in effect because this extension has not been in invoked.

Discussion