Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use puppeteer inside chrome extension

I want to build a chrome extension for personal use. The extension will scrape some webpages and it will render some information. So I think puppeteer can help me with that. I understand that I need to run node inside a chrome extension. Is it possible? I have found some answers but they are old.

like image 510
Petran Avatar asked Mar 15 '19 13:03

Petran


1 Answers

I know this is 9 months late but I had the same use case at work on Window machines but you can make it work with Mac.

The trick is to use puppeteer-web https://github.com/puppeteer/puppeteer/tree/master/utils/browser#bundling-for-web-browsers

Bundle the repository and place it in your chrome extension folder and then reference it in your popup.html with something like

<script src="./puppeteer/utils/browser/puppeteer-web.js"></script>

You'll then need to take advantage of Chrome's remote debugging functionality as puppeteer-web can't start its own instance via puppeteer.launch() and can only use puppeteer.connect() to connect to an already existing chrome instance.

On windows add --remote-debugging-port=9222 to the end of the target field of the chrome short cut as per How to make Chrome always launch with remote-debugging-port flag

Or on Mac /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --no-first-run --no-default-browser-check --user-data-dir=$(mktemp -d -t 'chrome-remote_data_dir')

Once remote debugging is activated you'll be able to see the webSocketDebuggerUrl property by visiting http://127.0.0.1:9222/json/version on your browser. This is the browserWSEndpoint the connect method will invoke.

You will also need to add the port address to the permissions array in the manifest.json file otherwise ajax requests won't work in the chrome extension.

Eg:

"permissions": [ "tabs" , "identity", "http://127.0.0.1:9222/*"],

Example popup.html file

<!DOCTYPE html>
<html>
  <head>
    <title>Example popup</title>
    <link rel="stylesheet" type="text/css" href="style.css">
  </head>
  <body>
    <div>
      <button id='puppeteer-button'>Do Puppeteer Things</button>
      <script src="./puppeteer/utils/browser/puppeteer-web.js"></script>
      <script type="module" src="popup.js"></script>
    </div>
  </body>
</html>

Example popup.js file

let browserWSEndpoint = '';
const puppeteer = require("puppeteer");

async function initiatePuppeteer() {
  await fetch("http://127.0.0.1:9222/json/version")
    .then(response => response.json())
    .then(function(data) {
        browserWSEndpoint = data.webSocketDebuggerUrl;
      })
    .catch(error => console.log(error));
}

initiatePuppeteer();

// Assign button to puppeteer function

document
  .getElementById("puppeteer-button")
  .addEventListener("click", doPuppeteerThings);

async function doPuppeteerThings() {
  const browser = await puppeteer.connect({
    browserWSEndpoint: browserWSEndpoint
  });
  const page = await browser.newPage();

  // Your puppeteer code goes here

}

Hope that helps, I haven't had any issues by appending remote debugging to my target field on my work window machines, despite feeling a bit hacky. I wrote a short blog post on it with better syntax highlighting here.

like image 194
tchan Avatar answered Sep 24 '22 02:09

tchan