developer tip

Chrome Extension 콘텐츠 스크립트에서 popup.html로 데이터를 보내는 방법

optionbox 2020. 10. 5. 07:53
반응형

Chrome Extension 콘텐츠 스크립트에서 popup.html로 데이터를 보내는 방법


나는 이것이 수많은 게시물에서 요청되었지만 솔직히 이해하지 못한다는 것을 알고 있습니다. 저는 JavaScript, Chrome 확장 프로그램 및 모든 것을 처음 접했고이 수업 과제가 있습니다. 따라서 Cross Domain Requests를 사용하여 특정 페이지에서 DOM 개체를 계산하는 플러그인을 만들어야합니다. 지금까지 Chrome Extension API를 사용하여이를 달성 할 수있었습니다. 이제 문제는 contentScript.js 파일의 popup.html 페이지에 데이터를 표시해야한다는 것입니다. 나는 문서를 읽으려고 시도했지만 크롬에서 메시징을 수행하는 방법을 모르겠지만 무엇을 해야할지 이해할 수 없습니다.

다음은 지금까지의 코드입니다.

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 파일 목록입니다. 이 배열에 나타나는 순서대로 삽입 됩니다 .

    (강조 내)

  2. 에서는 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>

You can use localStorage for that. You can store any data in a hash table format in browser memory and then access it any time. I'm not sure if we can access localStorage from the content script (it was blocked before), try to do it by yourself. Here's how to do it through you background page (I pass data from content script to background page first, then save it in localStorage):

in contentScript.js:

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

in eventPage.js (your background page):

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

Then you can access that variable in popup.js with localStorage["total_elements"].

Maybe you can access localStorage directly from the content script in modern browsers. Then you don't need to pass the data through your background page.

Nice reading about localStorage: http://diveintohtml5.info/storage.html

참고URL : https://stackoverflow.com/questions/20019958/chrome-extension-how-to-send-data-from-content-script-to-popup-html

반응형