illmatic
illmatic

Reputation: 43

How to get DOM from debugging tab to extension script

I'm looking for a bit of help here as the examples I've seen have only been from the tab to the extension and not the other way around.

I'm looking to grab the source code of a page/tab that I am debugging with a custom Chrome Extension. I want the extension to call a message and the response to be sent back to the extension panel javascript making the call.

Manifest

"permissions": [
  "tabs",
  "<all_urls>",
  "debugger"
],
"background": {
  "scripts": ["background.js"],
  "persistent": false
},
"content_scripts": [
  {
  "matches": ["<all_urls>"],
  "js": ["content.js"]
  }
],

background.js

chrome.browserAction.onClicked.addListener(function() {
  chrome.tabs.query({active:true, windowId:chrome.windows.WINDOW_ID_CURRENT}, function(tabs) {
    debuggee = {tabId:tabs[0].id};
chrome.debugger.attach(debuggee, version, onAttach.bind(null, tabs[0].id));
  });
});

function onAttach(tabId) {
  chrome.windows.create({url: "spy.html?" + tabId, type: "panel", width: 900, height: 700}, function(window) {
    winId = window.id;
});

content.js

chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.data == "getHTML") {
      sendResponse({data: document.getElementById('header').innerHTML});
  }
});

spy.html

<script src="spy.js" type="text/javascript"></script>

spy.js

window.addEventListener("load", function() {
  chrome.debugger.sendCommand({tabId:tabId}, "DOM.getDocument");
  chrome.debugger.onEvent.addListener(onEvent);
});

function onEvent(debuggeeId, message, params) {    
  if (message=="DOM.documentUpdated") {
    chrome.tabs.sendMessage(tabId, {data: "getHTML"}, function(response) {console.log(response.data);});
  }

Result

Port error: Could not establish connection. Receiving end does not exist. miscellaneous_bindings:235 chromeHidden.Port.dispatchOnDisconnect miscellaneous_bindings:235

Error in event handler for 'undefined': Cannot read property 'data' of undefined TypeError: Cannot read property 'data' of undefined
at chrome-extension://fpdkndicjblnkakkiiapbbdflkehjmgm/headers.js:132:91
at miscellaneous_bindings:279:11
at chrome.Event.dispatchToListener (event_bindings:387:21)
at chrome.Event.dispatch_ (event_bindings:373:27)
at chrome.Event.dispatch (event_bindings:393:17)
at Object.chromeHidden.Port.dispatchOnDisconnect (miscellaneous_bindings:238:27)

I get this error when I try to run it. What am I missing?

Upvotes: 2

Views: 3387

Answers (2)

illmatic
illmatic

Reputation: 43

OK I've figured it out. Since I need the DOM of the loaded page, I'm going to use the chrome.tabs.onUpdated.addListener in my background page to send the code when the page is loaded. This way I don't have to depend on the 2 way communication between the tab and extension.

Manifest

Removed content.js

background.js

Added the following

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
  if (tabId != _tabId) {return;}
  if (changeInfo.status == "complete") {
    chrome.tabs.executeScript(tabId, {code:"var x = document.documentElement.innerHTML;x"}, function (r) {
      chrome.extension.sendMessage(null, {"data": r[0]});       
    });
  }
});

content.js

REMOVED

spy.js

Added the following

chrome.extension.onMessage.addListener(function(request, sender) {
  console.log("Request.data: " + request.data);
});

Upvotes: 1

Sudarshan
Sudarshan

Reputation: 18534

How are you capturing tabId of chrome.tabs.sendMessage(tabId,, can you post your full script to debug problem,if you are looking for a sample code for passing message from Chrome Extension to Debugging Tab check this.

References

manifest.json

Registered popup page and content scripts.

{
 "name": "Pass message from Chrome Extension to Debugging Tab",
 "version": "1",
 "description": "http://stackoverflow.com/questions/14205155/how-can-i-pass-a-message-from-my-chrome-extension-to-debugging-tab",
 "browser_action": {
   "default_title": "Selected Text",
   "default_popup": "popup.html" 
 },
 "permissions": [
   "tabs",
   "<all_urls>"
 ],
 "content_scripts": [
  {
    "matches": ["<all_urls>"],
    "js": ["selection.js"]
  }
 ],
 "manifest_version": 2
}

popup.html

Ensured HTML Adheres to CSP

<!DOCTYPE html>
<html>

    <head>
        <style>
            body {
                width: 300px;
            }
            textarea {
                width: 250px;
                height: 100px;
            }
        </style>
        <script src="popup.js"></script>
    </head>

    <body>
          <button id="submit">Pass Message</button>
    </body>

</html>

popup.js

Pass Message to Content Scripts.

function passMessage() {
    //Select current tab to send message
  chrome.tabs.query({"active":true,"currentWindow":true,"status":"complete","windowType":"normal"}, function(tabs) {
  //It returns array so looping over tabs result
    for(tab in tabs){

    //Send Message to a tab
    chrome.tabs.sendMessage(tabs[tab].id, {method: "Hi Content Script"});
    }   
});
}


// Bind On click event to passMessage() function
document.addEventListener("DOMContentLoaded",function (){

    document.getElementById("submit").onclick = passMessage;
});

selection.js

Added a handler to catch messages sent from popup page

 //Add a handler to handle message sent from popup.html
 chrome.extension.onMessage.addListener(function(request, sender) {
    console.log("Message "+request+" is recieved");

});

EDIT:

I got your code working after eliminates some deprecated API() like sendResponse

background.js

chrome.browserAction.onClicked.addListener(function () {
    version = "1.0";
    chrome.tabs.query({
        active: true,
        windowId: chrome.windows.WINDOW_ID_CURRENT
    }, function (tabs) {
        debuggee = {
            tabId: tabs[0].id
        };
        chrome.debugger.attach(debuggee, version, onAttach.bind(null, tabs[0].id));
    });
});

function onAttach(tabId) {
    chrome.windows.create({
        url: "spy.html?" + tabId,
        type: "panel",
        width: 900,
        height: 700
    }, function (window) {
        winId = window.id;
    });
}

content.js

chrome.extension.onMessage.addListener(function (request, sender) {
    console.log("Message recieved");
    if (request.data == "getHTML") {
        chrome.extension.sendMessage({
            "data": "Some Stuff"
        });
    }
});

spy.js

tabId = parseInt(window.location.search.substring(1));
window.addEventListener("load", function () {

    chrome.debugger.sendCommand({
        tabId: tabId
    }, "DOM.getDocument");
    chrome.debugger.onEvent.addListener(onEvent);
});

function onEvent(debuggeeId, message, params) {
    if (message == "DOM.documentUpdated") {
        chrome.tabs.sendMessage(tabId, {
            "data": "getHTML"
        });
    }
}
chrome.extension.onMessage.addListener(function (response, sender) {
    console.log(response);
});

How ever ensure you do not trigger developer tools manually during testing.

Upvotes: 1

Related Questions