├── assets ├── icon-128.png ├── icon-16.png ├── icon-32.png └── icon-48.png ├── README.md ├── manifest.json ├── background.js ├── LICENSE └── content_script.js /assets/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahednasser/chrome-screenshot-tutorial/HEAD/assets/icon-128.png -------------------------------------------------------------------------------- /assets/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahednasser/chrome-screenshot-tutorial/HEAD/assets/icon-16.png -------------------------------------------------------------------------------- /assets/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahednasser/chrome-screenshot-tutorial/HEAD/assets/icon-32.png -------------------------------------------------------------------------------- /assets/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahednasser/chrome-screenshot-tutorial/HEAD/assets/icon-48.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chrome Screenshot Tutorial 2 | 3 | Repository for the [Chrome Screenshot Tutorial](https://blog.shahednasser.com/how-to-take-screenshots-in-chrome-extension/) that demonstrates how to take a screenshot in a Chrome extension. 4 | 5 | Icons in this extension are by [BZZRICON Studio](https://iconscout.com/contributors/bzzricon) on [Iconscout](https://iconscout.com/). 6 | 7 | ## License 8 | 9 | [MIT](./LICENSE) -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Screenshots", 3 | "version": "0.0.1", 4 | "description": "Take screenshots", 5 | "manifest_version": 3, 6 | "background": { 7 | "service_worker": "background.js" 8 | }, 9 | "permissions": [ 10 | "desktopCapture", 11 | "downloads", 12 | "tabs" 13 | ], 14 | "action": { 15 | "default_title": "Take a Screenshot" 16 | }, 17 | "icons": { 18 | "16": "/assets/icon-16.png", 19 | "32": "/assets/icon-32.png", 20 | "48": "/assets/icon-48.png", 21 | "128": "/assets/icon-128.png" 22 | }, 23 | "content_scripts": [ 24 | { 25 | "matches": [""], 26 | "js": ["content_script.js"] 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | chrome.action.onClicked.addListener(function (tab) { 2 | chrome.desktopCapture.chooseDesktopMedia([ 3 | "screen", 4 | "window", 5 | "tab" 6 | ], tab, (streamId) => { 7 | //check whether the user canceled the request or not 8 | if (streamId && streamId.length) { 9 | setTimeout(() => { 10 | chrome.tabs.sendMessage(tab.id, {name: "stream", streamId}, (response) => console.log(response)) 11 | }, 200) 12 | } 13 | }) 14 | }) 15 | 16 | chrome.runtime.onMessage.addListener((message, sender, senderResponse) => { 17 | if (message.name === 'download' && message.url) { 18 | chrome.downloads.download({ 19 | filename: 'screenshot.png', 20 | url: message.url 21 | }, (downloadId) => { 22 | senderResponse({success: true}) 23 | }) 24 | 25 | return true; 26 | } 27 | }) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Shahed Nasser 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /content_script.js: -------------------------------------------------------------------------------- 1 | chrome.runtime.onMessage.addListener((message, sender, senderResponse) => { 2 | if (message.name === 'stream' && message.streamId) { 3 | let track, canvas 4 | navigator.mediaDevices.getUserMedia({ 5 | video: { 6 | mandatory: { 7 | chromeMediaSource: 'desktop', 8 | chromeMediaSourceId: message.streamId 9 | }, 10 | } 11 | }).then((stream) => { 12 | track = stream.getVideoTracks()[0] 13 | const imageCapture = new ImageCapture(track) 14 | return imageCapture.grabFrame() 15 | }).then((bitmap) => { 16 | track.stop() 17 | canvas = document.createElement('canvas'); 18 | canvas.width = bitmap.width; //if not set, the width will default to 200px 19 | canvas.height = bitmap.height;//if not set, the height will default to 200px 20 | let context = canvas.getContext('2d'); 21 | context.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height) 22 | return canvas.toDataURL(); 23 | }).then((url) => { 24 | chrome.runtime.sendMessage({name: 'download', url}, (response) => { 25 | if (response.success) { 26 | alert("Screenshot saved"); 27 | } else { 28 | alert("Could not save screenshot") 29 | } 30 | canvas.remove() 31 | senderResponse({success: true}) 32 | }) 33 | }).catch((err) => { 34 | alert("Could not take screenshot") 35 | senderResponse({success: false, message: err}) 36 | }) 37 | return true; 38 | } 39 | }) --------------------------------------------------------------------------------