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

     2023-02-19     221

关键词:

【中文标题】Chrome 扩展如何将数据从内容脚本发送到 popup.html【英文标题】:Chrome Extension how to send data from content script to popup.html 【发布时间】:2013-11-29 23:03:14 【问题描述】:

我知道这在很多帖子中都被问到过,但老实说我不明白。我是 JavaScript、Chrome 扩展和一切的新手,我有这个班级作业。 所以我需要制作一个插件,可以使用跨域请求计算任何给定页面上的 DOM 对象。 到目前为止,我已经能够使用 Chrome 扩展 API 实现这一目标。 现在的问题是我需要在我的 popup.html 页面上显示 contentScript.js 文件中的数据。 我不知道该怎么做我已经尝试阅读文档,但是在 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");

 );
);
);

内容脚本

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 

);

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

【问题讨论】:

【参考方案1】:

尽管您的方向肯定是正确的(实际上已经接近尾声),但您的代码中有几个 (imo) 不好的做法(例如,为这样一个微不足道的任务注入整个库 (jquery),声明不必要的权限,对 API 方法进行多余的调用等)。 我自己没有测试您的代码,但从快速概述来看,我相信更正以下内容可能会产生一个可行的解决方案(尽管不是非常接近最优):

    ma​​nifest.json 中:更改内容脚本的顺序,将 jquery 放在首位。根据the relevant docs

"js" [...] 要注入匹配页面的 JavaScript 文件列表。这些是按照它们在此数组中出现的顺序注入的。

(强调我的)

    contentscript.js 中:将 chrome.runtime.sendMessage(...) 块移动 inside onMessage listener回调。

也就是说,这是我提出的方法:

控制流程:

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

目录结构:

          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": ["*://*.***.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>

【讨论】:

哇!谢谢兄弟,现在检查你的方法我觉得我的代码产生了多少问题。非常感谢,这就像一个魅力。 :) 你好,对不起,我有一段时间没上,刚刚检查了你的评论。我不能接受任何答案。它说你需要 15 个声望点才能这样做。 你介意帮我解决一个非常相似的问题吗? ***.com/questions/34467627/…> 我目前对此的看法几乎就是您从这个答案中获得的代码。但我仍然无法让它工作,而且似乎无法在这件事上找到任何好的帮助。 为什么你在 popupjs 中使用 chrome.tabs.sendMessage,在 content.js 中使用 chrome.runtime.onMessage.addListener 为什么在 popupjs 中使用 .tabs,在 content.js 中使用 .runtime @hkm:因为这就是您发送和接收消息的方式。都在the docs。【参考方案2】:

您可以为此使用 localStorage。您可以将任何数据以哈希表格式存储在浏览器内存中,然后随时访问。我不确定我们是否可以从内容脚本访问 localStorage(它之前被阻止),尝试自己做。以下是如何通过后台页面进行操作(我首先将数据从内容脚本传递到后台页面,然后将其保存在 localStorage 中):

在 contentScript.js 中:

chrome.runtime.sendMessage(
  total_elements: totalElements // or whatever you want to send
);

在 eventPage.js(你的背景页面)中:

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse)
       localStorage["total_elements"] = request.total_elements;
    
);

然后您可以使用 localStorage["total_elements"] 在 popup.js 中访问该变量。

也许您可以直接从现代浏览器中的内容脚本访问 localStorage。那么你就不需要通过你的后台页面传递数据了。

关于 localStorage 的精彩阅读:http://diveintohtml5.info/storage.html

【讨论】:

请不要推广使用已弃用的 chrome.extension.onRequest/sendRequest(顺便说一句,在执行之前不会加载非持久性背景页面)。请改用 chrome.runtime.* @ExpertSystem 如果您看到此类过时的信息,请建议/进行编辑。 @Xan:所以,你是 [Google-Chrome-Extension] 的继任者 :) 我不喜欢编辑别人的帖子(我觉得这太麻烦了)。此外,有这么多过时的教程和示例(至少在当时),我发现最好明确评论为什么使用.extension.xxx不好,而不是仅仅显示正确的方法(有些人可能认为这是“同样可行的选择”)。我猜这更多的是风格问题。继续努力!

如何将 chrome 扩展 ID 动态发送到网页以进行消息传递

】如何将chrome扩展ID动态发送到网页以进行消息传递【英文标题】:HowtodynamicallysendchromeextensionIDtoawebpageformessagepassing【发布时间】:2016-03-2805:24:28【问题描述】:我通过内容脚本在网页中注入了一个脚本。在脚本中,我使用chrome... 查看详情

无法将变量从内容脚本发送到弹出窗口

...s(我的内容脚本)传递给popup.js。现在我从https://developer.chrome.com/extensions/messaging复制只是为了尝试获取消息。但是 查看详情

尝试从扩展包中的 html 窗口向内容脚本发送消息

】尝试从扩展包中的html窗口向内容脚本发送消息【英文标题】:Tryingtosendamessagefromahtmlwindowthatisintheextensionpackagetothecontentscript【发布时间】:2019-08-0417:22:36【问题描述】:我添加了一个新的(弹出窗口)window不是您在清单中注册... 查看详情

Chrome 扩展程序 |如何在 CDN 的内容和后台脚本中包含库

】Chrome扩展程序|如何在CDN的内容和后台脚本中包含库【英文标题】:ChromeExtension|Howtoincludelibraryincontentandbackgroundscriptsfromcdn【发布时间】:2016-10-0305:58:21【问题描述】:我的Chrome扩展程序有两个文件:内容和后台脚本。我还需要... 查看详情

如何从 chrome 扩展中读取文件?

】如何从chrome扩展中读取文件?【英文标题】:Howtoreadfilefromchromeextension?【发布时间】:2015-05-0515:39:06【问题描述】:我有popup.html,其中popup.js在通过单击浏览器操作加载弹出窗口时被调用。我正在以编程方式使用chrome.tabs.execut... 查看详情

Chrome 扩展:本地存储,如何导出

】Chrome扩展:本地存储,如何导出【英文标题】:ChromeExtension:LocalStorage,howtoexport【发布时间】:2014-06-0308:17:48【问题描述】:我有一个chrome扩展,可以将一堆数据保存到chrome.storage.local。我试图找到简单的方法来导出这些数据并... 查看详情

Chrome 扩展程序:如何在 chrome 扩展程序更新后删除孤立的脚本

】Chrome扩展程序:如何在chrome扩展程序更新后删除孤立的脚本【英文标题】:Chromeextension:Howtoremoveorphanedscriptafterchromextensionupdate【发布时间】:2019-12-1910:45:25【问题描述】:我有一个带有弹出页面的chrome扩展,它通过简单的一次... 查看详情

如何将 JSON 数据从节点 js 脚本发送到不同服务器上的 HTML 文件

】如何将JSON数据从节点js脚本发送到不同服务器上的HTML文件【英文标题】:HowtosendJSONdatafromnodejsscripttoHTMLfileonadifferentserver【发布时间】:2017-06-0619:23:26【问题描述】:好的,我知道下面的代码是您如何使用express将对象发送到HTM... 查看详情

如何将可扩展列表视图的选定子视图数据从片段发送到父活动?

】如何将可扩展列表视图的选定子视图数据从片段发送到父活动?【英文标题】:Howtosendselectedchildviewdataofexpandablelistviewfromfragmenttoparentactivity?【发布时间】:2016-05-2704:12:10【问题描述】:我有一个具有TextViewtvCount的ParentActivity,... 查看详情

从脚本安装 Google Chrome 扩展

】从脚本安装GoogleChrome扩展【英文标题】:InstallGoogleChromeextensionfromscript【发布时间】:2014-02-0515:39:30【问题描述】:我已经创建了我的Google-chrome扩展程序(crx文件),但我不想将它上传到Chrome网上应用店。现在如何以编程方式... 查看详情

如何将数据从 Perl 发送到 Python

】如何将数据从Perl发送到Python【英文标题】:HowtosenddatafromPerltoPython【发布时间】:2012-07-2415:28:09【问题描述】:我问了另一个关于加快使用Perl和Monkeyrunner(Jython)测试Android的过程的问题,得到了thisanswer。启动一个Monkeyrunner脚本... 查看详情

如何在 Chrome 中通过 nativeMessaging 发送/接收短信?

】如何在Chrome中通过nativeMessaging发送/接收短信?【英文标题】:Howtosend/receivetextmessagevianativeMessaginginChrome?【发布时间】:2022-01-0916:23:34【问题描述】:我正在尝试将当前活动选项卡的url发送到python脚本。我的扩展程序已经开始... 查看详情

无法从 Chrome 扩展生成的 iframe 更改元素

】无法从Chrome扩展生成的iframe更改元素【英文标题】:Can\'tchangeelementfromiframegeneratedbyChromeExtension【发布时间】:2017-02-1016:29:09【问题描述】:我正在开发Chrome扩展程序。目前,有一个内容脚本会返回点击元素的XPath。另一个内容... 查看详情

从 chrome 的扩展内容脚本访问 iframe 内容

】从chrome的扩展内容脚本访问iframe内容【英文标题】:accessiframecontentfromachrome\'sextensioncontentscript【发布时间】:2012-07-0417:47:04【问题描述】:我正在做一个插件来对界面进行一些转换。我不断收到unsafejavascriptattempttoaccessframewithu... 查看详情

从 Chrome 扩展中挂钩 Websocket

】从Chrome扩展中挂钩Websocket【英文标题】:HookingWebsocketsfromaChromeExtension【发布时间】:2018-10-0415:32:55【问题描述】:我正在尝试创建一个可以挂钩特定页面的WebSocket的Chrome扩展内容脚本。当前,当页面被访问时,内容脚本会像... 查看详情

Chrome 扩展(内容脚本)+ React:从 DOM 获取 React 组件?

】Chrome扩展(内容脚本)+React:从DOM获取React组件?【英文标题】:ChromeExtension(contentscript)+React:gettingReactcomponentfromDOM?【发布时间】:2017-02-1707:18:34【问题描述】:我了解,有一个chrome扩展“ReactDevTools”可以检查React应用程序。... 查看详情

帮助 android 到 chrome 通信

】帮助android到chrome通信【英文标题】:Helpwithandroidtochromecommunication【发布时间】:2011-07-1118:03:08【问题描述】:我一直致力于创建一个应用程序,该应用程序将字符串从安卓手机发送到服务器,然后从那里发送到Chrome扩展程序... 查看详情

Chrome 扩展:从内容脚本中删除正文属性

】Chrome扩展:从内容脚本中删除正文属性【英文标题】:ChromeExtension:Removebodyattributesfromcontentscript【发布时间】:2016-04-0522:50:47【问题描述】:这不是重复的......这是一个延续我在从Chrome扩展程序中删除body标记中的属性时遇到问... 查看详情