First of all, for better undestanding, I want to discribe what exactly functionality i need to from my extension:
- I open some site [stackoverflow.com || github.com || some else forum] then i need to write text with images as illustrations.
- I open some other window from what I need to do screenshot.
- I create screenshot with Snipping Tool (which place image data to clipboard after screenshoting)
- I`m back to previously opened site
- I [open context menu and choose my custom item in it || click on icon of my browser extension and click on button in it || just use ctrl+v hotkeys]
- My extension now must go to work and upload image data from clipboard to my own server and paste ready formatted for markdown or bbcode text with url to image.
- In options i will can choose what kind of formated text I need to paste.
At this moment, I have this files on my server:
index.html
<button id="pastenupload" type="button" onclick="pastenupload()">SEND FROM CLIPBOARD</button>
<script>
function pastenupload() {
navigator.permissions.query({ name: "clipboard-read" }).then((result) => {
if (result.state == "granted" || result.state == "prompt") {
navigator.clipboard.read().then((data) => {
for (let i = 0; i < data.length; i++) {
if (!data[i].types.includes("image/png")) {
alert("Clipboard contains non-image data. Unable to access it.");
} else {
data[i].getType("image/png").then((blob) => {
fetch(`pastenupload.php`, {method:"POST", body:blob})
.then(response => console.log(response.text()))
});
}
}
});
}
});
}
</script>
pastenupload.php
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, DELETE, PUT, PATCH, OPTIONS');
header("Access-Control-Allow-Headers: X-Requested-With");
// gets entire POST body
$data = file_get_contents('php://input');
// write the data out to the file
$fp = fopen("/path/to/my/file/myfile.png", "wb");
fwrite($fp, $data);
fclose($fp);
echo 'Good Done!';
?>
This work as expected. If image data in clipboard, after press button image stores in selected folder on my server.
Now I try to create chrome browser extension based on the "Getting Started Example" with this files:
manifest.json
{
"name": "Paste&Upload",
"description": "Paste copied image direct into server!",
"version": "1.0",
"manifest_version": 3,
"permissions": ["storage", "activeTab", "scripting", "clipboardRead", "tabs"],
"host_permissions": ["<all_urls>"],
"action": {
"default_popup": "pu_popup.html",
"default_icon": {
"16": "/images/get_started16.png",
"32": "/images/get_started32.png",
"48": "/images/get_started48.png",
"128": "/images/get_started128.png"
}
},
"icons": {
"16": "/images/get_started16.png",
"32": "/images/get_started32.png",
"48": "/images/get_started48.png",
"128": "/images/get_started128.png"
}
}
pu_popup.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="pu_button.css">
</head>
<body>
<button id="changeColor"></button>
<script src="pu_popup.js"></script>
</body>
</html>
pu_popup.js
changeColor.onclick = myFunction;
function myFunction() {
console.log('Is start!');
navigator.clipboard.read().then((data) => {
console.log('Is read!')
for (let i = 0; i < data.length; i++) {
if (!data[i].types.includes("image/png")) {
console.log('Is non blob!');
} else {
data[i].getType("image/png").then((blob) => {
console.log('Is blob!')
fetch('https://myserver/pasteupload.php', {method:"POST", body:blob}).then(response => console.log(response.text()))
});
}
}
});
}
I click on icon of my extension, click on changeColor button, and in dev.tools I see
forms.html:1 Uncaught (in promise) DOMException: Document is not focused.
What I need to change to Document became is focused? Or do I need to look for another approach to solving my problem?
As for the my 6th point, I think I won’t have any problems with it, I indicated it simply for a more accessible understanding of the functionality of the extension that I want to make.
In general, the only thing that interests me is how to properly organize the transfer of image data to my server?
Thanks!
In pu_popup.js I trying change code for click event like this:
changeColor.addEventListener("click", pastenupload());
.
changeColor.addEventListener("click", {
pastenupload();
});
.
changeColor.addEventListener("click", async () => {
pastenupload();
});
.
changeColor.addEventListener("click", async () => {
chrome.scripting.pastenupload();
});
But with no luck. The first three options do not produce errors, but they do nothing. I click and nothing happens.
The last option generates an error
Uncaught (in promise) TypeError: chrome.scripting.pastenupload is not a function
I try to another option - context menus. I add
"background": {"service_worker":"pu_worker.js"}
to the manifest.
Create
pu_worker.js
chrome.contextMenus.create({
id: "context1",
title: "Markdown",
contexts: ["all"]
});
chrome.contextMenus.onClicked.addListener(function(info, tab) {
console.log(info.menuItemId);
navigator.permissions.query({ name: "clipboard-read" }).then((result) => {
if (result.state == "granted" || result.state == "prompt") {
navigator.clipboard.read().then((data) => {
for (let i = 0; i < data.length; i++) {
if (!data[i].types.includes("image/png")) {
alert("Clipboard contains non-image data. Unable to access it.");
} else {
data[i].getType("image/png").then((blob) => {
fetch(`https://myserver/pasteupload.php`, {method:"POST", body:blob})
.then(response => console.log(response.text()))
});
}
}
});
}
});
});
And again with no luck :/ At this time, error is:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'read')
Looks like last error is the because of this two year old bug... Bad luck...