Message passing from an internal extension page to content script - javascript

I'm developing a simple extension for word translating.
What I'm stuck with is I'm using an internal page for settings. What I want to do is passing an array (or any data at least -i'm that devastated-) from this internal page to content script.
I've tried
content script
var port = chrome.runtime.connect();
window.addEventListener("message", function(event) {
// We only accept messages from ourselves
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_PAGE")) {
window.alert("Content script received: " + event.data.text);
port.postMessage(event.data.text);
}
}, false);
internal page's javascript
window.postMessage({ type: "FROM_PAGE", text: "Hello from the webpage!" }, "*");
Internal page is a html file. I want to use it as a settings page. Like AdBlock's "options" page which you can reach from its popup page.
manifest.json
{
"manifest_version": 2,
"name": "Jun",
"description": "See selected words' equivalent.",
"version": "1.0",
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "icon.png",
"default_title": "Click Here!",
"default_popup": "popup.html"
},
"permissions": [
"storage",
"tabs"
],
"content_scripts": [{
"matches": ["http://*/*", "https://*/*"],
"css": ["/lib/jquery-ui.min.css"],
"js": ["/lib/jquery-3.1.1.js", "/lib/jquery-ui.min.js", "/lib/jquery.mark.js", "content.js"],
"run_at": "document_end"
}]
}
and some other useless things so far.
For clarification; extension page link
chrome-extension://inbhgljjpkpodbamjfkehcmloabbhccn/category_settings/categorySettings.html
I hope I could express myself.
Thanks in advance!
PS: You can see project from https://github.com/MisketAdam/Jun
PS2:
extension directory
.
|──*etc*
|──content.js
|──category_settings/
| |──categorySettings.js
| |──categorySettings.css
| |──categorySettings.html
| |──*etc*
SOLVED
Yeah so... After reading https://developer.chrome.com/extensions/messaging throughly and trying out
chrome.runtime.sendMessage
at the internal page's javascript and handling it from background page got it working.
Thanks everyone!

Related

Chrome extension - Execute content script for specific site url

At the moment I'm testing this code. My intention is to scrape some data using a content script
This is what I have in background file
chrome.action.onClicked.addListener( (tab) => {
// chrome.scripting.executeScript({
// target: {tabId: tab.id},
// files: ['content.js']
// })
console.log('Requesting tab: \n', tab)
chrome.windows.create({
type: 'popup',
height: 300,
width: 200,
url: chrome.runtime.getURL('popup.html')
})
})
This is what I have in my content script
console.info('chrome-ext template-vue-js content script')
const DOMnodes = document.querySelectorAll('article')
console.log(`Ecco le informazioni sui prezzi per Sole365`)
console.log('\n')
let details = []
DOMnodes.forEach( (node) => {
// Loop nodi prodotto
details.push(node.dataset)
console.log(`----\n`)
console.log(`Nome prodotto: ${node.dataset.productName}`)
console.log(`Descrizione breve: ${node.children[2].children[1].childNodes[1].childNodes[0].innerText}`)
// price
console.log(`Prezzo: ${node.childNodes[2].childNodes[1].childNodes[2].childNodes[0].innerText}`)
//console.log(``)
//descriz. breve
//node.children[2].children[1].childNodes[1].childNodes[0].innerText
})
console.log(details)
The script isn't executed when the website I set in manifest match. here is the dev version
{
"name": "create-chrome-ext",
"description": "Extract data",
"version": "1.0.0",
"manifest_version": 3,
"icons": {
"16": "img/logo-16.png",
"32": "img/logo-34.png",
"48": "img/logo-48.png",
"128": "img/logo-128.png"
},
"action": {
"default_icon": "img/logo-48.png"
},
"options_page": "options.html",
"background": {
"service_worker": "service-worker-loader.js",
"type": "module"
},
"host_permissions": [
"https://www.example.com/mypath/*/*"
],
"content_scripts": [
{
"js": [
"assets/content-script.js"
],
"matches": [
"https://www.example.com/mypath/*/*"
]
}
],
"web_accessible_resources": [
{
"matches": [],
"resources": [
"img/logo-16.png",
"img/logo-34.png",
"img/logo-48.png",
"img/logo-128.png"
],
"use_dynamic_url": false
},
{
"matches": [
"<all_urls>"
],
"resources": [
"**/*",
"*"
],
"use_dynamic_url": true
}
],
"permissions": [
"activeTab",
"tabs",
"alarms"
]
}
Any idea of why? My idea is to call the script when the icon is clicked and open a popup to get the resulting extracted data to use in vue frontent
When you reload the extension you also need to reinject the content script(s).
If the site is a modern SPA (Single Page Application) it uses fake navigation via history.pushState, so the page stays the same and the content script doesn't re-run.
To verify this is the case:
open devtools
open Network panel
click Doc in devtools toolbar filter
click a link in the page to navigate within the site
see if the request for the new URL is added to the network log
If there's no Doc request, you'll need matches for the entire site e.g. *://www.example.com/* and then either a) use MutationObserver in the content script or b) use chrome.webNavigation API onHistoryStateUpdated and onReferenceFragmentUpdated in the background script, which can be limited via URL filter to the site, the listener for these event(s) will send a message to the event's tabId, which will be received by the content script (example).

Chrome extension, send message from panel.js to content script

I'm trying to intercept youtube requests response from a devtool panel and send it to the content or background script of a Chrome extension. but I can't get it to work.
There is loads of exemple online but most of them use Manifest V2 and I really want to make it work on V3.
I don't know which method to use for sending messages to the content or background script from the panel.js, nor do I know how to listen for incoming messages from the panel in those scripts.
And I don't know if I need to add more permissions in my manifest for this to work :
{
"manifest_version": 3,
"name": "Already Seen",
"version": "1",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["jquery-3.6.0.min.js", "content.js"],
"css": ["avatar.css"]
}
],
"devtools_page" : "devtools.html",
"action": {
"default_icon": "icon.png"
},
"background": {
"service_worker": "background.js"
},
"permissions": ["identity", "storage", "tabs", "webRequest"],
"host_permissions": ["https://www.youtube.com/", "https://youtube.com/"],
"externally_connectable": {
"matches": ["https://youtube.com/*"]
},
"oauth2": {
"client_id": "***************",
"scopes": [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile"
]
}
}
devtools.html
<script src="devtools.js"></script>
devtools.js
chrome.devtools.panels.create("Already Seen", "icon.png", 'panel.html');
panel.html
<html>
<body>
<script src="panel.js"></script>
</body>
</html>
panel.js
chrome.devtools.network.onRequestFinished.addListener((request) => {
request.getContent((body) => {
if (!request.request || !request.request.url) return;
// I NEED TO SEND THE MESSAGE HERE TO BACKGROUND.JS OR CONTENT.JS
});
});
I found another way of doing this by using the chrome.debbuger in the background script but it shows "... started debugging this browser" on top of every pages.

Custom newtab page: content script won't receive message from bgscript

I am building a Chrome extension that injects some HTML and JS when the user clicks the extension icon. So, when the icon is clicked, it is registered in the bg script, and the content script is notified about this like so:
Background script
chrome.browserAction.onClicked.addListener(iconClicked)
function iconClicked(tab) {
var visitors = window.AllVisitors.get(tab.id),
data = {
message: 'toggleMenu',
user: window.user
};
chrome.tabs.sendMessage(tab.id, data);
}
Now, to the problem: In my manifest file, I have also added a custom page for the chrome://newtab page. When the extension icon is clicked while visiting this custom newtab page, the content script does not receive any message what so ever. The default newtab page does actually receive the message as well as any other webpage.
I am thinking that maybe it has something to do with externally_connectable, but adding this does not help:
"externally_connectable": {
"matches": ["chrome://newtab/"],
}
Does anybody know why my custom newtab page does not receive any messages from the background script? Any help is very appreciated!
Manifest file:
{
"manifest_version": 2,
"name": "Orbit",
"version": "0.0.1",
"web_accessible_resources": [
"templates.html",
"img/icon48.png",
"fonts/*.woff",
"img/*"
],
"externally_connectable": {
"matches": ["chrome://newtab/"],
},
"chrome_url_overrides" : {
"newtab": "tab/newtab.html"
},
"icons": {
"16": "img/icon16.png",
"48": "img/icon48.png",
"128": "img/icon128.png"
},
"browser_action": {
"default_icon": {
"16": "img/icon16.png",
"48": "img/icon48.png",
"128": "img/icon128.png"
},
"default_title": "Orbit"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["vendor/chrome-promise.js", "vendor/jquery.js", "vendor/underscore.js", "vendor/backbone.js", "orbit.js"]
},
{
"matches": ["<all_urls>"],
"css": ["sidebar.css"]
}
],
"background": {
"scripts": ["vendor/socket.io.js", "vendor/jquery.js", "vendor/underscore.js", "vendor/backbone.js", "vendor/chrome-promise.js", "vendor/jquery.js", "eventPage.js"],
"persistent": true
},
"permissions": [
"http://fonts.googleapis.com/*",
"https://fonts.googleapis.com/*",
"https://get-orbit.com:8080/*",
"activeTab",
"tabs",
"storage"
]
}
Content scripts aren't injected on chrome-extension:// pages.
Simply add the script manually in your newtab.html:
<html>
<head>
<script src="your-content-script.js"></script>
</head>

Unable to use jquery in google chrome extension

I am trying to use jquery to make a post ajax call and I have tried almost all the solutions on SO but none seem to work. My manifest is:
{"name": "__MSG_extName__",
"version": "0.1",
"manifest_version": 2,
"description": "__MSG_extDesc__",
"icons": {"16": "icon16.png", "128": "icon128.png"},
"background": {"persistent": false, "scripts": ["background.js"]},
"default_locale": "en",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["jquery-2.1.3.js"]
}
],
"permissions": ["contextMenus", "downloads", "downloads.open", "tabs", "http://*/*", "https://*/*"]}
The background.js file is like:
chrome.downloads.onCreated.addListener(function(downloadItem) {
console.log("Download Link is " + downloadItem.url)
chrome.tabs.executeScript(null, { file: "jquery-2.1.3.js" }, function() {
console.log("jquery is loaded");
var linkSync = {
"document": {
"downloadLink": downloadItem.url,
"isSynced": false},
"safe": true
};
$.post("url/to/post",
linkSync,
function( data ) {
console.log("Success" + data );
});
});
});
The error that I am getting is:
Download Link is http://www.mymp3song.com/files/download/id/33724
background.js:14 jquery is loaded
extensions::uncaught_exception_handler:8 Error in response to tabs.executeScript: ReferenceError: $ is not defined
at Object.callback (chrome-extension://kbhkaajolcelehoonafmkgaahfgphnok/background.js:22:2)
at chrome-extension://kbhkaajolcelehoonafmkgaahfgphnok/background.js:13:16
As you may see, I have added the jquery.js both programmatically and in the manifest but none seem to work. Even if I remove either of them it does not work. Can someone point to me what I should do to make it work?
If you want jQuery to function in your background page, you need to add it to the background page.
Both methods that you're trying to use are adding code to the content script context instead.
What you need is this:
"background": {
"persistent": false,
"scripts": ["jquery-2.1.3.js", "background.js"]
},
to load jQuery in your background page. Note that order matters.
I would recommend giving the Architecture Overview a look.
modify your your json to this and it will work for u
reference is Here
"content_scripts": [ {
"js": [ "jquery.min.js", "background.js" ],
"matches": [ "http://*/*", "https://*/*"]
}]

How can I call functions defined in a Chrome Extension from regular websites?

I'd like to make a website that is not part of the chrome plugin but rather just uses some API that the plugin exposes to it. Is this possible and if so, how do I do it? I googled this question and was unable to find anything.
I'm trying to use content scripts but nothing happens. Can someone explain what's wrong here?
manifest.json
{
"manifest_version": 2,
"name": "Hello World Extension",
"description": "This extension prints hello world.",
"version": "1.0",
"background": {
"page": "background.html"
},
"browser_action": {
"default_icon": "img/icon.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["http://locahost:8888/*"],
"js": ["EmotivAPI.js"]
}
]
}
EmotivAPI.js
var port = chrome.runtime.connect();
console.log("Hello?");
window.addEventListener("message", function (event) {
// We only accept messages from ourselves
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_PAGE")) {
console.log("Content script received: " + event.data.text);
port.postMessage(event.data.text);
alert("recieved!");
}
}, false);
js in the webpage
window.sayHello = function () {
window.postMessage({ type: "FROM_PAGE", text: "Hello from webpage!" }, "*");
}
console.log('Emotiv extension loaded.');
}
I'm calling window.sayHello() from the console
Content Scripts can help you in this case.
The content script will be injected into a page:
"content_scripts": [
{
"matches": ["http://www.google.com/*"], // try with "http://localhost:*/*" or "http://localhost:*"
"css": ["mystyles.css"],
"js": ["content_script.js"]
}
]
If you want to inject the code only sometimes, use the permissions field instead
/* in manifest.json */
"permissions": [
"tabs", "http://*/*"
],
In you extension html file, you can then execute the script by:
chrome.tabs.executeScript(null, {file: "content_script.js"});

Categories