当前位置: 首页 > 面试题库 >

Chrome扩展程序如何将数据从内容脚本发送到popup.html

符国安
2023-03-14
问题内容

我知道这个问题已经在很多帖子中问过了,但老实说我不明白。我不熟悉JavaScript,Chrome扩展程序和其他所有功能,并且已经完成了此类课程。因此,我需要制作一个插件,该插件将使用跨域请求在任何给定页面上计算DOM对象。到目前为止,我已经可以使用Chrome
Extension
API来实现这一目标。现在的问题是,我需要在contentScript.js文件的popup.html页面上显示数据。我不知道该怎么做,我已经尝试阅读文档,但是在chrome中发消息我只是不知道该怎么做。

以下是到目前为止的代码。

manifest.json

{
"manifest_version":2,

"name":"Dom Reader",
"description":"Counts Dom Objects",
"version":"1.0",

"page_action": {
    "default_icon":"icon.png",
    "default_title":"Dom Reader",
    "default_popup":"popup.html"
},

"background":{
    "scripts":["eventPage.js"],
    "persistent":false
},

"content_scripts":[
    {
        "matches":["http://pluralsight.com/training/Courses/*", "http://pluralsight.com/training/Authors/Details/*",                                          "https://www.youtube.com/user/*", "https://sites.google.com/site/*", "http://127.0.0.1:3667/popup.html"],
        "js":["domReader_cs.js","jquery-1.10.2.js"]
        //"css":["pluralsight_cs.css"]
    }
],

"permissions":[
    "tabs",
    "http://pluralsight.com/*",
    "http://youtube.com/*",
    "https://sites.google.com/*",
    "http://127.0.0.1:3667/*"
]

popup.html

<!doctype html>
<html>

    <title> Dom Reader </title>    
    <script src="jquery-1.10.2.js" type="text/javascript"></script>
    <script src="popup.js" type="text/javascript"></script>

<body>
    <H1> Dom Reader </H1>
    <input type="submit" id="readDom" value="Read DOM Objects" />

   <div id="domInfo">

    </div>
</body>
</html>

eventPage.js

var value1,value2,value3;

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.action == "show") {
    chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        chrome.pageAction.show(tabs[0].id);
    });
}

value1 = request.tElements;
});

popup.js

$(function (){
$('#readDom').click(function(){
chrome.tabs.query({active: true, currentWindow: true}, function (tabs){
    chrome.tabs.sendMessage(tabs[0].id, {action: "readDom"});

 });
});
});

contentScript

var totalElements;
var inputFields;
var buttonElement;

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse){
if(request.action == "readDom"){

    totalElements = $("*").length;
    inputFields = $("input").length;
    buttonElement = $("button").length;


}
})

chrome.runtime.sendMessage({ 
action: "show", 
tElements: totalElements, 
Ifields: inputFields, 
bElements: buttonElement

});

任何帮助,将不胜感激,请避免我做的任何愚蠢:)


问题答案:

尽管您肯定是朝着正确的方向(实际上接近末尾),但是代码中存在几种(imo)不良做法(例如,为这样的琐碎任务注入整个库(jquery),声明不必要的权限,变得多余)调用API方法等)。
我没有亲自测试您的代码,但是从快速的概览中,我相信更正以下内容可能会导致一个可行的解决方案(尽管不是非常接近最佳):

  1. manifest.json中 :更改内容脚本的顺序,将jquery放在首位。根据 相关文档

“ js” […]将注入匹配页面的JavaScript文件列表。这些 以它们 在此数组中 出现的顺序 注入。

(强调我的)

  1. contentscript.js :移动 chrome.runtime.sendMessage({…})onMessage听者回调。

也就是说,这是我建议的方法:

控制流:

  1. 内容脚本将被注入到每个符合某些条件的页面中。
  2. 注入后,内容脚本会将消息发送到事件页面(又称非持久性背景页面),事件页面会将页面操作附加到选项卡。
  3. 加载页面操作弹出窗口后,它将立即向内容脚本发送一条消息,询问其所需的信息。
  4. 内容脚本处理请求,并做出响应,以便页面操作弹出窗口可以显示信息。

目录结构:

          root-directory/
           |_____img
                 |_____icon19.png
                 |_____icon38.png
           |_____manifest.json
           |_____background.js
           |_____content.js
           |_____popup.js
           |_____popup.html

manifest.json:

{
  "manifest_version": 2,
  "name": "Test Extension",
  "version": "0.0",
  "offline_enabled": true,

  "background": {
    "persistent": false,
    "scripts": ["background.js"]
  },

  "content_scripts": [{
    "matches": ["*://*.stackoverflow.com/*"],
    "js": ["content.js"],
    "run_at": "document_idle",
    "all_frames": false
  }],

  "page_action": {
    "default_title": "Test Extension",
    //"default_icon": {
    //  "19": "img/icon19.png",
    //  "38": "img/icon38.png"
    //},
    "default_popup": "popup.html"
  }

  // No special permissions required...
  //"permissions": []
}

background.js:

chrome.runtime.onMessage.addListener((msg, sender) => {
  // First, validate the message's structure.
  if ((msg.from === 'content') && (msg.subject === 'showPageAction')) {
    // Enable the page-action for the requesting tab.
    chrome.pageAction.show(sender.tab.id);
  }
});

content.js:

// Inform the background page that 
// this tab should have a page-action.
chrome.runtime.sendMessage({
  from: 'content',
  subject: 'showPageAction',
});

// Listen for messages from the popup.
chrome.runtime.onMessage.addListener((msg, sender, response) => {
  // First, validate the message's structure.
  if ((msg.from === 'popup') && (msg.subject === 'DOMInfo')) {
    // Collect the necessary data. 
    // (For your specific requirements `document.querySelectorAll(...)`
    //  should be equivalent to jquery's `$(...)`.)
    var domInfo = {
      total: document.querySelectorAll('*').length,
      inputs: document.querySelectorAll('input').length,
      buttons: document.querySelectorAll('button').length,
    };

    // Directly respond to the sender (popup), 
    // through the specified callback.
    response(domInfo);
  }
});

popup.js:

// Update the relevant fields with the new data.
const setDOMInfo = info => {
  document.getElementById('total').textContent = info.total;
  document.getElementById('inputs').textContent = info.inputs;
  document.getElementById('buttons').textContent = info.buttons;
};

// Once the DOM is ready...
window.addEventListener('DOMContentLoaded', () => {
  // ...query for the active tab...
  chrome.tabs.query({
    active: true,
    currentWindow: true
  }, tabs => {
    // ...and send a request for the DOM info...
    chrome.tabs.sendMessage(
        tabs[0].id,
        {from: 'popup', subject: 'DOMInfo'},
        // ...also specifying a callback to be called 
        //    from the receiving end (content script).
        setDOMInfo);
  });
});

popup.html:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="popup.js"></script>
  </head>
  <body>
    <h3 style="font-weight:bold; text-align:center;">DOM Info</h3>
    <table border="1" cellpadding="3" style="border-collapse:collapse;">
      <tr>
        <td nowrap>Total number of elements:</td>
        <td align="right"><span id="total">N/A</span></td>
      </tr>
      <tr>
        <td nowrap>Number of input elements:</td>
        <td align="right"><span id="inputs">N/A</span></td>
      </tr>
      <tr>
        <td nowrap>Number of button elements:</td>
        <td align="right"><span id="buttons">N/A</span></td>
      </tr>
    </table>
  </body>
</html>


 类似资料:
  • 问题内容: 我正在做一个插件来对界面进行一些转换。我不断收到(典型的跨网站问题) 但作为扩展程序,它应该可以访问iframe的内容 … 没有人知道如何访问它的内容以便可以被捕获吗? 问题答案: 通常,没有直接访问其他来源对象的直接方法。如果要在不同框架中的内容脚本之间 安全地 通信,则必须将消息发送到后台页面,该页面又将消息发送回选项卡。 这是一个例子: 的一部分: : : 后台脚本“ bg.js

  • 问题内容: 我正在尝试让我的Chrome扩展程序在加载新页面时运行该功能,但是在尝试了解如何执行此操作时遇到了麻烦。据我了解,我需要在background.html中执行以下操作: 使用来检查时,页面变更 使用运行的脚本。 这是我的代码: 我还想知道init()函数是否可以访问位于其他JS文件中的其他函数? 问题答案: Chrome扩展程序中的JavaScript代码可以分为以下几类: 扩展代码-

  • 问题内容: 我有一个chrome扩展程序,可以在网站上进行一些更改(编辑评论)。 在站点上进行了最近更改之后(站点不是我的站点)-使用ajax加载了注释块(之前是简单的发布请求,整个页面都重新加载了)。 现在,如果我第一次加载页面-内容脚本可以工作,但是当我转到下一页时,说页面#2-使用ajax添加注释,并且不再运行扩展脚本。所以评论并没有改变我想要的方式。 有没有简单的方法来监听页面更改DOM并

  • 问题内容: 我正在构建一个Chrome扩展程序,该扩展程序仅适用于我工作的公司内部的人员。该扩展需要输入-可以通过对共享的MySQL DB服务器的简单查询生成输入(所有员工都可以以只读权限访问该服务器)。 问题是-由于扩展是所有客户端(主要是Javascript)-访问数据库和运行查询的最简单方法是什么?我是否必须创建一个针对扩展名的php / java(/ …)服务? 问题答案: 您必须创建一个

  • 问题内容: 我有一个内容脚本,该脚本使用XHR下载一些二进制数据,该数据稍后发送到后台脚本: 在后台脚本中接收到此数据后,我想形成另一个XHR请求,将该请求上传到我的服务器,所以我这样做: 问题是上传到服务器的文件仅包含以下字符串:“ [object Object]”。我猜发生这种情况是因为ArrayBuffer类型从内容过程转移到后台时以某种方式丢失了吗?我该如何解决? 问题答案: 在内容脚本和

  • 问题内容: 我正在尝试从弹出窗口访问activeTab DOM内容。这是我的清单: 我真的很困惑,背景脚本(持久性事件页:false)还是content_scripts是可行的方法。我已经阅读了所有文档和其他SO帖子,但对我来说仍然没有意义。 有人可以解释为什么我可能会用另一个。 这是我一直在尝试的background.js: 我只是从弹出控制台执行此操作: 我越来越: 更新: content.j