programing

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

cafebook 2023. 9. 5. 20:46
반응형

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

저는 이것이 많은 게시물에서 요청되었다는 것을 알지만 솔직히 이해할 수 없습니다.저는 자바스크립트, 크롬 익스텐션 등 모든 것에 익숙하지 않고 이 수업 과제를 가지고 있습니다.그래서 저는 크로스 도메인 요청을 사용하여 주어진 페이지에서 DOM 객체를 셀 수 있는 플러그인을 만들어야 합니다.저는 지금까지 Chrome Extension API를 사용하여 이를 달성할 수 있었습니다.이제 문제는 contentScript.js 파일에서 내 popup.html 페이지의 데이터를 보여줘야 한다는 것입니다.설명서를 읽어봤는데 크롬으로 메시지를 보내니 어떻게 해야 할지 모르겠어요.

지금까지의 코드는 다음과 같습니다.

매니페스트.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/*"
]

팝업.창구

<!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;
});

팝업.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 

});

어떤 도움이든 감사할 것이고 제가 한 어떤 무례함도 피하세요 :)

당신이 확실히 올바른 방향으로 가고 있지만(실제로는 거의 끝에 가깝다), 코드에는 몇 가지 (imo) 나쁜 관행이 있습니다(예: 그러한 사소한 작업을 위해 전체 라이브러리(jquery)를 주입하거나, 불필요한 권한을 선언하거나, API 메서드에 과도한 호출을 하는 등).
제가 직접 코드를 테스트한 것은 아니지만, 간략한 개요를 보면 다음 사항을 수정하면 (최적에 가깝지는 않지만) 효과적인 해결책이 될 수 있다고 생각합니다.

  1. in manifest.json: jquery를 먼저 지정하여 내용 스크립트의 순서를 변경합니다.관련 문서에 따르면:

"js" [...] 일치하는 페이지에 삽입할 JavaScript 파일 목록입니다.이것들은 이 배열에 나타나는 순서대로 주입됩니다.

(내 것이 아님)

  1. in 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

매니페스트.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);
  }
});

팝업.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);
  });
});

poppoppup.sys:

<!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>

여기에는 localStorage를 사용할 수 있습니다.데이터를 해시 테이블 형식으로 브라우저 메모리에 저장한 다음 언제든지 액세스할 수 있습니다.컨텐츠 스크립트에서 localStorage에 액세스할 수 있는지 잘 모르겠습니다(이전에는 차단되었습니다). 직접 해 보십시오.백그라운드 페이지를 통해 수행하는 방법은 다음과 같습니다(먼저 컨텐츠 스크립트에서 백그라운드 페이지로 데이터를 전달한 다음 localStorage에 저장).

contentScript.js:

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

in eventPage.js(배경 페이지):

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

그런 다음 localStorage["total_elements"]를 사용하여 팝업.js의 해당 변수에 액세스할 수 있습니다.

최신 브라우저의 컨텐츠 스크립트에서 localStorage에 직접 액세스할 수 있습니다.그러면 배경 페이지를 통해 데이터를 전달할 필요가 없습니다.

localStorage에 대한 좋은 읽을거리: http://diveintohtml5.info/storage.html

간단한 해결책을 드리겠습니다.

문제는 콘텐츠 스크립트에 팝업이 아닌 콘텐츠 스크립트에서 팝업으로 메시지를 보내는 방법입니다.

팝업에서 팝업 메시지를 보내야 합니다.

document.addEventListener('DOMContentLoaded', function() {
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
            chrome.tabs.sendMessage(tabs[0].id, {type:"msg_from_popup"}, function(response){
            alert(response)
            });
        });
    })

콘텐츠 스크립트에서 이벤트 수신기를 추가해야 하지만 캐치는 true를 반환해야 한다는 것입니다. 이는 true를 언급하지 않으면 sendResponse를 비동기적으로 사용할 수 있다는 것을 의미합니다. true는 동기적으로 작동합니다. sendResponse 메시지를 즉시 반환해야 합니다.

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
     
        if(request["type"] == 'msg_from_popup'){
            console.log("msg receive from popup");
            
        sendResponse("msg received and sending back reply");// this is how you send message to popup
           
        }
        return true; // this make sure sendResponse will work asynchronously
        
    }
);

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

반응형