如何通过Tampermonkey脚本(或其他用户脚本)调用自定义Chrome扩展?
Great question! Let's break down your options and validate each approach to connect your Tampermonkey script with a custom Chrome extension for accessing restricted APIs like bookmarks or fileSystem:
1. Chrome Runtime Message Passing (Recommended)
This approach does work with Tampermonkey — it's actually the most secure and straightforward method since it leverages Chrome's official cross-extension communication system. Here's how to set it up:
Step 1: Configure your custom extension's manifest
Add the externally_connectable field to your extension's manifest.json to allow Tampermonkey to send messages to it. You can find Tampermonkey's extension ID by enabling developer mode in chrome://extensions/ and checking its entry. For safety, lock access to only Tampermonkey's ID:
{ "manifest_version": 3, "name": "My API Handler Extension", "version": "1.0", "background": { "service_worker": "background.js" }, "externally_connectable": { "ids": ["dhdgffkkebhmkfjojejmpbldmpobfkfo"] // Tampermonkey's official public ID }, "permissions": ["bookmarks", "fileSystem"] }
Step 2: Add message listener in your extension's background script
In background.js, listen for incoming messages from Tampermonkey and handle the restricted API calls:
chrome.runtime.onMessageExternal.addListener((request, sender, sendResponse) => { // Optional: Validate sender is Tampermonkey to avoid unwanted requests if (sender.id !== "dhdgffkkebhmkfjojejmpbldmpobfkfo") return; switch (request.action) { case "add_bookmark": chrome.bookmarks.create(request.payload, (result) => { sendResponse({ success: true, data: result }); }); return true; // Keep port open for async API response case "read_file": // Handle fileSystem API logic here sendResponse({ success: true, data: "file content" }); break; default: sendResponse({ success: false, error: "Unknown action requested" }); } });
Step 3: Send messages from your Tampermonkey script
Call chrome.runtime.sendMessage with your custom extension's ID to trigger API actions:
// Replace with your custom extension's unique ID const EXTENSION_ID = "your-extension-id-here"; // Example: Request to add a bookmark chrome.runtime.sendMessage(EXTENSION_ID, { action: "add_bookmark", payload: { title: "Automated Bookmark", url: "https://your-target-site.com" } }, (response) => { if (response.success) { console.log("Bookmark added successfully:", response.data); } else { console.error("Failed to add bookmark:", response.error); } });
2. Window.postMessage (Alternative)
This method is fully functional and doesn't require modifying your extension's manifest for external connectivity. It passes messages through the current tab's window object between your Tampermonkey script and a content script in your extension:
Step 1: Add a content script to your extension
Update manifest.json to inject a content script into the sites your Tampermonkey script targets:
{ "manifest_version": 3, "content_scripts": [ { "matches": ["https://your-target-site.com/*"], "js": ["content.js"] } ], "permissions": ["bookmarks", "fileSystem"] }
Step 2: Listen for messages in the content script
In content.js, forward messages to the background script and relay responses back to Tampermonkey:
window.addEventListener("message", (event) => { // Validate origin to prevent cross-site message leaks (even for private use) if (event.origin !== window.location.origin) return; if (event.source !== window) return; // Forward request to background script chrome.runtime.sendMessage(event.data, (response) => { // Send response back to Tampermonkey window.postMessage({ type: "EXTENSION_RESPONSE", data: response }, window.location.origin); }); });
Step 3: Send messages from Tampermonkey
In your Tampermonkey script, send requests via postMessage and listen for the extension's response:
// Send API request to extension window.postMessage({ type: "EXTENSION_REQUEST", action: "add_bookmark", payload: { title: "Automated Bookmark", url: "https://your-target-site.com" } }, window.location.origin); // Listen for the extension's response window.addEventListener("message", (event) => { if (event.origin !== window.location.origin) return; if (event.data.type !== "EXTENSION_RESPONSE") return; const response = event.data.data; if (response.success) { console.log("Bookmark added:", response.data); } else { console.error("Error:", response.error); } });
3. Local Web App + XHR (Not Recommended)
This approach is technically feasible but overkill for your use case. You'd need to run a local HTTP server to act as a middleman between Tampermonkey and your extension (via background script polling or websockets). However, this adds unnecessary complexity (managing a local server, handling CORS, etc.) when the first two methods are simpler and more secure.
Final Recommendation
Stick with Chrome Runtime Message Passing for your use case: it's secure, efficient, and uses Chrome's native API system. Since your scripts are private and only used on specific sites, security risks are minimal, but locking down externally_connectable to Tampermonkey's ID adds an extra layer of safety.
内容的提问来源于stack exchange,提问作者Alex Quinn




