0

I wanna create a Chrome extension that needs to read a specific part which the website posts into the console. Here you can see this part:

Picture of the part in console

I need specifically the "questionsList" part.

How do I do that in the JS of my Extension?

ncls.
  • 113
  • 1
  • 7
  • The simplest solution is probably to override `console.log` **in [page context](/a/9517879)**. A scary alternative is `chrome.debugger` API and [Log](https://chromedevtools.github.io/devtools-protocol/tot/Log/) events. – wOxxOm Feb 18 '21 at 18:46
  • @wOxxOm I'm not sure but this doesn't seem like a solution to my problem. But maybe it's just because I'm too clueless about JS. – ncls. Feb 18 '21 at 19:01
  • That's definitely the reason :-) – wOxxOm Feb 18 '21 at 19:16
  • @wOxxOm Ok, I don't get how I tell it to select the questionList array. Which part of the answer do i have to focus on? – ncls. Feb 18 '21 at 19:17
  • Your page script will override `console.log` with your own function. You'll debug it to see the exact parameters used by the site. Assuming it's the first parameter something like `obj.questionsList`. Look for examples of overriding/hooking page functions using the page context trick I linked, there could be some that you can adapt easily. Or maybe someone else will add an answer here... – wOxxOm Feb 18 '21 at 19:24
  • @wOxxOm My problem is that I don't understand anything he's explaining in this answer. Already read it like 7 times... And are you sure this is the right solution? I mean, he's talking about the script writing "State changed!" into the console when a YouTube video gets played/paused as far as I understood. I don't get the connection... – ncls. Feb 18 '21 at 19:31
  • That answer simply shows how to put the code that will have the ability to override page functions. The code itself doesn't have any connection to anything. – wOxxOm Feb 18 '21 at 19:33
  • @wOxxOm I'm confused... I want my extension to grab the "questionList" array so I can process it inside the extension. – ncls. Feb 18 '21 at 19:35
  • Yes, I know. You've repeated the question. – wOxxOm Feb 18 '21 at 19:36
  • @wOxxOm Ok, I don't understand anything of this solution. So what about the chrome.debugger API solution? Why is it scary? – ncls. Feb 18 '21 at 19:39

1 Answers1

0

As the other user said, overriding the console.log method will be the easier way. You can then iterate over the arguments passed in to the console.log function and see if one of the arguments is an object that has a property named "questionList", and if it does it should store its value in a global object named questionList. You can inject this code in the console:

let oldConsole=window.console
let questionList=[];
window.console=(function(oldConsole){
       return {
             log:function(...args){
                 oldConsole.log(...args)
                for(arg of args){
                  if(typeof arg==="object" && "questionList" in arg){
                    questionList=arg["questionList"]   
                  }
                }
             },
             error:function(...args){
               oldConsole.error(...args)
             }
           }
})(oldConsole);

Now whenever the console logs that particular object you can access this array from the questionList global variable.

Edit: In order to inject this code in the page you can use the Debugger's API "Page.addScriptToEvaluateOnNewDocument" method. First you will have to add the debugger permission in your manifest.json file. Then you can add a listener to your browser action's onClicked event, and then attach the debugger to that particular tab. After that you should enable the Debugger's page domain using the method "Page.enable", then finally you can call the "Page.addScriptToEvaluateOnNewDocument" method:

let tabId;
chrome.browserAction.onClicked.addListener(handleClick)
function handleClick(tab){
    tabId=tab.id
    chrome.debugger.attach({tabId},"1.0")   
    chrome.debugger.sendCommand({tabId},"Page.enable");
    source=`let oldConsole=window.console;
            let questionList=[];
            window.console=(function(oldConsole){
            console.log("Overriding console")
           return {
             log:function(...args){
                 oldConsole.log(...args)
                for(arg of args){
                  if(typeof arg==="object" && "questionList" in arg){
                    questionList=arg["questionList"]   
                  }
                }
             },
             error:function(...args){
               oldConsole.error(...args)
             }
           }
        })(oldConsole);
    `
chrome.debugger.sendCommand({tabId},"Page.addScriptToEvaluateOnNewDocument",{source});

After that you need to navigate to the page in order for the script to be evaluated.

GoPotato
  • 116
  • 2
  • 7
  • It says "Uncaught TypeError: Cannot read property 'style' of null" at line 3 on the Chrome add on page. And when I try to console log questionList it just logs an empty array I think. – ncls. Feb 19 '21 at 07:16
  • It logs the array before the page sends the questionList array so maybe that's why it's empty. – ncls. Feb 19 '21 at 07:29
  • I should have probably explained this better. You can execute this code directly inside the console window, but you cannot use it directly inside a content script since it's not executed in the same context as the page's scripts, so content scripts don't have direct access to window properties such as console. What you can do instead is inject this script inside the page using the Debugger's "Page.addScriptToEvaluateOnNewDocument" method. I'll edit my answer to show how to use this. – GoPotato Feb 19 '21 at 11:57
  • BTW the questionList array will always be empty until the console logs the actual object that contains your array of interest. I think you should probably rephrase your question, you're not actually interested in the console logs, you just want to access the object that is containing that array. There are probably better ways to do so than this. – GoPotato Feb 19 '21 at 12:15
  • But what ways are there to achieve it? – ncls. Feb 22 '21 at 08:40
  • @ncls You do it by debugging the line which is outputting the object to the console and tracking down the source that's creating/modifying the object. I actually saw your post on reddit but I couldn't get the website you linked to work. It's giving me this message "The quiz has not yet started Don't worry - we have you covered. You'll be connected as soon as the quiz master starts it." I won't be able to help much without seeing the actual output by the console and debugging it myself. Sorry. – GoPotato Feb 23 '21 at 01:13
  • If you wanna join, dm me on Reddit or comment so I get a notification and can start the quiz so you can join – ncls. Feb 23 '21 at 10:59