Help me take screenshots of a webpage with my chrome extension.

537 views
Skip to first unread message

Siddharth Bhardwaj

unread,
Aug 13, 2023, 2:20:01 PM8/13/23
to Chromium Extensions
Hello, I want to implement a screenshot functionality in my extension. 

If anyone knows DocSumo extension, that's exactly what I want. I want the user to be able to select a custom area of the webpage he's on 

Please help, I've wasted hours trying to figure this out.
I'd really appreciate it if someone could provide the code for that or even just an overview of how i should do it. Just a simple snipping functionality where the extension is listening for a command. 

Ben Bracha

unread,
Aug 14, 2023, 3:20:51 AM8/14/23
to Siddharth Bhardwaj, Chromium Extensions
This code snippet here shows how to mark an area over an image on an HTML page.
Maybe some of it can help...



--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/96559fc1-ca07-4f34-b3f0-cefdddb030d2n%40chromium.org.

Siddharth Bhardwaj

unread,
Aug 14, 2023, 10:51:08 AM8/14/23
to Chromium Extensions, Ben Bracha, Chromium Extensions, Siddharth Bhardwaj
Thank you Ben but i've already seen it. The problem is that when i use html2canvas i get a content policy violation error. Chrome wont let me inject js onto the webpage i'm on. 

Ben Bracha

unread,
Aug 14, 2023, 11:32:05 AM8/14/23
to Siddharth Bhardwaj, Chromium Extensions
can you share what exactly you are doing and the error ?
I’m using html2canvas with chrome extension and it works fine, nothing special i had to do 

Siddharth Bhardwaj

unread,
Aug 14, 2023, 12:31:24 PM8/14/23
to Chromium Extensions, Ben Bracha, Chromium Extensions, Siddharth Bhardwaj
I have a chrome command listener in my background script. 
let isCommandExecuted = false
chrome.commands.onCommand.addListener(function(command) {
    if (command === 'capture-screenshot') {
        commandExecuted=true;
    }
  }); 
chrome.tabs.onActivated.addListener((activeInfo) => {
    if(isCommandExecuted) {
        const tabId = activeInfo.tabId;
        chrome.scripting.executeScript({
            target: {tabId: tabId},
            function: () => {
                function createDiv(){
                    if(!document.getElementById('customDiv')) {
                        divElement = document.createElement('div');
                        divElement.id = 'customDiv';
                        divElement.style.position = 'fixed';
                        divElement.style.background = 'rgba(0, 0, 0, .5)';
                        divElement.style.border = '1px dashed white';
                        divElement.style.pointerEvents = 'none';
                        divElement.style.display = 'none'; // Initially hidden
                        document.body.appendChild(divElement);
                    }
                    if(!document.getElementById('html2canvasID')){
                        const scriptElement = document.createElement('script');
                          scriptElement.id = 'html2canvasID';
                          scriptElement.src = 'https://github.com/niklasvh/html2canvas/releases/download/v1.0.0-alpha.1/html2canvas.js'
                          document.body.appendChild(scriptElement);
                     
                      }
                }
                document.addEventListener('mousedown', (e) => {
                    createDiv();
                    chrome.runtime.sendMessage({action: "mousedown", data: e})
                });
                document.addEventListener('mouseup', (e) => {
                    createDiv();
                    chrome.runtime.sendMessage({action: "mouseup", data: e})
                });
                document.addEventListener('mousemove', (e) => {
                    createDiv();
                    chrome.runtime.sendMessage({action: "mousemove", data: e})
                });
            }
        });
    }
  });

This is the content script.
var dragging = false,
dragStart = {
  x: 0,
  y: 0
},
dragEnd = {
  x: 0,
  y: 0
};

let dragger = document.getElementById("customDiv");

function updateDragger() {
  dragger.classList.add('visible');
  var s = dragger.style;
  s.top = Math.min(dragStart.y, dragEnd.y) + 'px';
  s.left = Math.min(dragStart.x, dragEnd.x) + 'px';
  s.height = Math.abs(dragStart.y - dragEnd.y) + 'px';
  s.width = Math.abs(dragStart.x - dragEnd.x) + 'px';
}
function startDrag(evt) {
  evt.preventDefault();
  document.body.style.cursor = 'crosshair';
  dragging = true;
  dragStart.x = dragEnd.x = evt.clientX;
  dragStart.y = dragEnd.y = evt.clientY;
  updateDragger();
}
function expandDrag(evt) {
  if (!dragging) return;
  dragEnd.x = evt.clientX;
  dragEnd.y = evt.clientY;
  updateDragger();
}

function endDrag() {
  dragging = false;
  dragger.classList.remove('visible');
  // here is the important part
  html2canvas(document.body, {
      width: Math.abs(dragStart.x - dragEnd.x),
      height: Math.abs(dragStart.y - dragEnd.y),
      x: Math.min(dragStart.x, dragEnd.x),
      y: Math.min(dragStart.y, dragEnd.y)
    })
    .then((canvas) => {
      const dataUrl = canvas.toDataUrl();
// here I'm sending this back to popup.js where I'm going to set the src of img tag in my popup.html to this dataUrl
      chrome.runtime.sendMessage({action: 'snipComplete', snipDataUrl: dataUrl});
    });
  document.body.style.cursor = 'auto';
  dragStart.x = dragStart.y = dragEnd.x = dragEnd.y = 0;
}

chrome.runtime.onMessage.addListener((message,sender,sendResponse) => {
  if(message.action === 'mousedown'){
    startDrag(message.data)
  }
})
chrome.runtime.onMessage.addListener((message,sender,sendResponse) => {
  if(message.action === 'mouseup'){
    endDrag(message.data)
  }
})
chrome.runtime.onMessage.addListener((message,sender,sendResponse) => {
  if(message.action === 'mousemove'){
    expandDrag(message.data)
  }
})



This is my first ever extension and it's only been a few days so I know this might look completely brainded what i've coded.

























Ben Bracha

unread,
Aug 14, 2023, 12:56:54 PM8/14/23
to Siddharth Bhardwaj, Chromium Extensions
Interesting.

I'm less experienced with chrome.scripting.executeScript  so not sure how to help here
what is the error you get?

Siddharth Bhardwaj

unread,
Aug 14, 2023, 1:33:40 PM8/14/23
to Chromium Extensions, Ben Bracha, Chromium Extensions, Siddharth Bhardwaj
What did you use in your extension if you don't mind me asking? 

Ben Bracha

unread,
Aug 14, 2023, 1:35:16 PM8/14/23
to Siddharth Bhardwaj, Chromium Extensions
I'm taking the screenshot from the content script itself. Not by using executeScript from background

Siddharth Bhardwaj

unread,
Aug 14, 2023, 1:47:51 PM8/14/23
to Chromium Extensions, Ben Bracha, Chromium Extensions, Siddharth Bhardwaj
Okay. But how are you importing html2canvas. Because if i use the es6 method of importing it says can't import module. How are you using html2canvas in your content script

Ben Bracha

unread,
Aug 14, 2023, 1:49:41 PM8/14/23
to Siddharth Bhardwaj, Chromium Extensions
I'm importing it yes. Just a usual import... don't remember any issues with that

Lu Xu

unread,
Aug 14, 2023, 8:36:05 PM8/14/23
to Ben Bracha, Siddharth Bhardwaj, Chromium Extensions
Hi,
I just would like to mention this code is risky

const scriptElement = document.createElement('script');
scriptElement.id = 'html2canvasID';
document.body.appendChild(scriptElement);

As far as I know, Chrome disallow execute remote script, so it would be better if you import html2canvas package in your source code

And another approach is using captureVisibleTab API here https://developer.chrome.com/docs/extensions/reference/tabs/#method-captureVisibleTab, this approach requires some permission though.
After captured, it would be a base64 dataURI, you can also pass the ROI coordinates, the tab's width and height, and use the Offscreen Canvas APIs https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas to load the full image in a canvas, take ROI section, and save the ROI
 , 

Reply all
Reply to author
Forward
0 new messages