简体   繁体   English

在单独的选项卡中显示 chrome 扩展,打开一个新选项卡,抓取页面内容并将其显示在扩展页面上

[英]Display chrome extension in separate tab, open a new tab, scrape page content and display it on the extension page

So far I've always been patient enough to search SO until I found a working solution.到目前为止,我一直有足够的耐心去搜索 SO,直到找到一个可行的解决方案。 However I am really stuck on this one.但是我真的坚持这个。

I am trying to achieve the following:我正在努力实现以下目标:

  1. Display a chrome extension in a new tab instead of a popup在新选项卡而不是弹出窗口中显示 chrome 扩展
  2. Once a search button is clicked a new page should be opened单击搜索按钮后,应打开一个新页面
  3. A content script should read the DOM and return it内容脚本应该读取 DOM 并返回它
  4. The content should be displayed on the extension page内容应显示在扩展页面上

Whenever I click the search button a new page is opened.每当我单击搜索按钮时,都会打开一个新页面。 However, I never get back any response but an error telling me "Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.".但是,我从来没有得到任何响应,而是一个错误告诉我“未经检查的 runtime.lastError:无法建立连接。接收端不存在。”。

Screenshot of error message错误信息截图

I assume there is an issue with the registration of the listener.我认为侦听器的注册存在问题。 I've seen questions where the issue was that a message has been sent before a listener has been registered.我已经看到问题是在侦听器注册之前已发送消息。 I can imagine something similar here but I have not yet been able to resolve it by searching answers on SO.我可以在这里想象类似的事情,但我还无法通过在 SO 上搜索答案来解决它。

If anyone would have the patience to help some chrome extension newbie with this issue any help will be really appreciated!如果有人有耐心帮助一些 chrome 扩展新手解决这个问题,任何帮助将不胜感激!

manifest.json manifest.json

{
  "manifest_version": 3,
  "name": "Test",
  "version": "1",
  "icons": {
    "32": "images/favicon.png"
  },
  "action":
  {
    "default_title":"Test",
    "default_popup": "ui/main.html"
  },
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'; script-src-elem 'self' 'unsafe-inline' http://code.jquery.com/jquery-latest.min.js;"
  },
  "background": {
    "service_worker": "js/background.js"
  },
  "content_scripts": [{
    "matches": ["*://*/*"],
    "js": ["js/content.js"]
  }],
  "permissions": [
    "activeTab"
  ]
}

main.html main.html

 <,DOCTYPE html> <html lang="en"> <head> <meta name="description" content="Test" /> <meta charset="utf-8"> <title>Trade Monitoring</title> <meta name="viewport" content="width=device-width. initial-scale=1"> <meta name="author" content=""> <link rel="stylesheet" href="../css/style.css"> <script src="../js/main.js"></script> </head> <body> <center> <div class="main"> <center> <button id="search">Search</button> <div id="result"> </div> </center> </div> </center> </body> </html>

main.js main.js

 var link= "https://www.google.com"; var extensionTab = 0; var pageTab = 0; chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { var currTab = tabs[0]; if (currTab) { // Sanity check extensionTab = currTab.id; } }); document.addEventListener('DOMContentLoaded', function () { var btn = document.getElementById('search'); btn.addEventListener('click', function() { search(); }); }); function search(){ scrape(); } async function scrape(){ await openPage(); getContent(); } function openPage(){ return new Promise((resolve, reject) => { try{ chrome.tabs.create({ url: link }, function (newTab){ pageTab = newTab.id; resolve(pageTab); }); }catch(e){ reject(e); } }) } function getContent(){ chrome.tabs.sendMessage(pageTab, {method: 'get_dom'}, function (response) { console.log(response); }); //TODO: Display content on extension page }

content.js内容.js

 chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { alert("here"); if (request.name == "name") { payload = request.payload; } });

background.js背景.js

 chrome.tabs.create({url: '../ui/main.html'})

chrome.tabs.create() returns to your code immediately, before the tab actually starts loading, so your message won't be delivered because messaging doesn't wait for future listeners. chrome.tabs.create() 在选项卡实际开始加载之前立即返回您的代码,因此您的消息将不会被传递,因为消息传递不会等待未来的侦听器。

You can either repeat sendMessage in 100ms intervals until it succeeds or you can reverse the direction of the communication and let the new tab's content script be an initiator:您可以每隔 100 毫秒重复一次 sendMessage 直到它成功,或者您可以反转通信的方向并让新选项卡的内容脚本成为发起者:

main.js main.js

async function scrape(url) {
  const tab = await chrome.tabs.create({ url });
  return new Promise(resolve => {
    chrome.runtime.onMessage.addListener(function onMessage(msg, sender) {
      if (msg.method === 'dom' && sender.tab.id === tab.id) {
        resolve(msg.data);
        chrome.runtime.onMessage.removeListener(onMessage);
      }
    });
  });
}

content.js:内容.js:

// analyze DOM
// ..........
chrome.runtime.sendMessage({ method: 'dom', data: ['whatever'] });

The returned data must be JSON-compatible (number, string, boolean, null, and objects/arrays consisting of these types).返回的数据必须是 JSON 兼容的(数字、字符串、boolean、null 以及由这些类型组成的对象/数组)。 Attempting to return a DOM element or a Promise or Map/Set will produce an empty {} .尝试返回 DOM 元素或 Promise 或 Map/Set 将产生一个空的{}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM