How to fix issues sending data from web page to chrome extension? - javascript

I am trying to pass data from my webpage to the chrome extension.
manifest.json (I am trying to do this in my local environment first)
"externally_connectable": {
"matches": ["*://localhost/*"]
}
In listen.js (a background script):
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.url == blacklistedWebsite)
return; // don't allow this web page access
if (request.openUrlInEditor)
alert('test2');
alert(request.openUrlInEditor);
});
None of the alerts display above.
I got the extension ID of the unpacked chrome extension by viewing the ID when I navigate to chrome://extensions/. In my webpage in localhost environment
// DEVELOPMENT extension ID
var editorExtensionId = "fppgjikaoolnlcmdjalbfkmlcadcckmb";
var url = 'test';
// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
function(response) {
if (!response.success)
handleError(url);
});
When I run this. in the browser, I get an error saying:
Error in event handler for (unknown): TypeError: Cannot read property 'success' of undefined
I'm not sure where to begin debugging this.

After making a few changes in your code I am able achieve your goal.
See below the complete code.
manifest.json
{
"manifest_version": 2,
"name": "CS to Bg Communication",
"version": "0.1",
"background": {
"scripts": ["listen.js"]
},
"content_scripts": [
{
"all_frames" : true,
"matches": ["<all_urls>"],
"js": ["contentscript.js"]
}
],
"browser_action": {
"default_popup": "popup.html"
},
"externally_connectable": {
"matches": ["*://localhost/*"]
}
}
listen.js - the background script
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
blacklistedWebsite = 'http : / / yourdomain . com /';
if (sender.url == blacklistedWebsite)
return; // don't allow this web page access
if (request.openUrlInEditor) {
alert('test2 - ' + request.openUrlInEditor);
sendResponse({"success": true, "AckFromBG": "I have received your messgae. Thanks!"}); // sending back the acknowlege to the webpage
}
});
contentscript.js - the content script - actually does nothing
console.log("this is content script");
web-page.html - The local web page
<html>
<body>
This page will will send some message to BG script
<script type="text/javascript">
// DEVELOPMENT extension ID
var editorExtensionId = "fjaedjckfjgifecmgonfmpaoemochghb"; // replace with your extension ID
var url = 'test';
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url}, function(response) {
console.log(response);
if (!response.success)
handleError(url);
});
function handleError(url) {
console.log(url);
}
</script>
</body>
</html>
Summary of changes:
Defined blacklistedWebsite - this was undefined.
Added sendResponse({"success": true, "AckFromBG": "I have received
your messgae. Thanks!"}); to send back the acknowledgment to the
webpage.
Define function handleError(url) {
console.log(url);
} this was not defined.
That's it. Hope this will solve your issue.

The error you are getting indicates that chrome.runtime.sendMessage is executed. This means that external messaging is set up correctly: otherwise, chrome.runtime.sendMessage wouldn't be exposed to your page's code.
I think the problem is here:
if (sender.url == blacklistedWebsite)
return; // don't allow this web page access
I suspect the problem is blacklistedWebsite being undefined; the code fails with a ReferenceError and no meaningful response is being sent. Since the onMessage listener terminates (even with an error), the calling code gets an undefined response.
Check your background console to confirm if that's the case; if you copied this partial example code but aren't using this blacklisting functionality, delete this branch.
In future, please make sure you understand what every line of code you copy does!

Related

Cannot run my chrome extension in other broswer/machine except mine : some mismatch in unpacked distribution?

Sorry for my poor English, i hope you can understand the issue.
I'm new to chrome extension development,and for sure in my code there are a lot of
thing to change or optimize;
anyway i've written a simple code that, (seems) works at least from my chrome.
The code clicks a button every X minutes in specific page, then wait and parse the result in page.
I've :
a content script (loaded from manifest.json) which "inject" some button and text Input box in page, so user can sets some "filter params" before click a "start button"; the start button then sendMessage() to background.js to set Alarm Event for the click ;
an eventPage (which is set persistent true in actually ) which handle the request from tabs and set a countdown alarm for each tab; when X min are passed fire a message to the interested tab;
I also have a popup.html e popup.js not important here (i think).
I've to distribuite this extension manually, so i would distribuite a zip that user can load with "developer mode ".
*Now the issue is: why the code was working only on my Chrome ? *
I've tested with others 2-3 laptop with Chrome, the background script is loaded (i can see the background page printint console log)
but in webpage the contents.js seems no way executed .
In my chrome works well: i can see in console some initial output (i print the name of dir extension to check) and
the dynamic created element (button,input box ect.) in page.
And all is working, i can fire the start button and receive results of parsing.
During the development i've never run the extension on other machine. Yesterday i've succssfully tested on 2-3 laptop.. then i made only few change but nothing serious.
Today i can run only in my chrome.
In other pc nothing, neither the simple console.log output first line of script.
I can read in console log :
"Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist."
but this also in my working istance in my laptop chrome .
The zip file is the same and the extraction is good, in fact i can actually load the extension and i see the background page debug console.log() sentences
In some case, in laptop where it dosen't work, i've received a message relative jQuery and the fact that chrome.runtime.sendMessage() is not defined; and it points to code in webpage, not mine.
I've see that in webpage code there is something like:
var extid = "mcmhdskbnejjjdjsdkksmeadjaibo";
var extVer = "1.5";
var extStatus = 0;
$(document).ready(function () {
///...
chrome.runtime.sendMessage(extid, {message: "version"},
function (reply) {
if (reply) {
if (reply.version) {
if (reply.version == extVer) {
if (reply.gminfo != 'OK') {
extStatus = 1; /// ...
Seems that chrome.runtime is undefined, and the webpage can't call the sendMessage().
EDIT: this undefined occurs only when my extension is loaded
Maybe there is some conflict when i load my extension? But in my chrome browser works...
Can some expert indicate in where direction i've to investigate?
Thanks a lot for any suggestions.
My Manifest.json :
{"manifest_version": 2,
"name": "myAlarm",
"description": "This extension alerts.",
"version": "0.1",
"permissions": [
"alarms",
"system.cpu",
"storage",
"tabs",
"webNavigation",
"https://www.mytargetsite.com/subUrl/"
],
"web_accessible_resources": [
"icon.png",
"vanillaSelectBox.css"],
"content_scripts": [
{
"matches": ["https://www.mytargetsite.com/subUrl/"],
"css": ["vanillaSelectBox.css"],
"js": ["jquery-3.3.1.min.js","vanillaSelectBox.js","taffy-min.js","content.js"],
"run_at": "document_end"
}
],
"background": {
"scripts": ["eventPage.js"],
"persistent": true
},
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"icons": {
....
}
}
My contents,js (stripped):
chrome.runtime.onMessage.addListener(
function(request, sender) {
// here i parse message "time'up" from background js
});
window.addEventListener('load', function() {
var pt=chrome.runtime.getURL('filterOff.wav');
var p=pt.split("/");
console.log("[myAlarm v0.1] started" );
console.log("[myAlarm v0.1] folder : ("+p[2]+")");
// here i start an active wait for the presence in page of button with ID= btntarget_id
waitForElementToDisplay("#btntarget_id", 500); //when function find button then create and add button and input text to webpage
});
My eventPage.js :
var curr_alarms =[];
chrome.extension.onMessage.addListener(function(request, sender)
{ /// here receive start countdown message from content.js and set alarm ...
}
chrome.alarms.onAlarm.addListener(function(alarm) {
/// here i manage each alarm for each tab
});
chrome.tabs.onRemoved.addListener(function(tabid, removed) {
// ...
});
chrome.tabs.onUpdated.addListener(function
(tabId, changeInfo, tab) {
//
});
edit : in browser where it dosen't work i can read also :
Access to XMLHttpRequest at 'https://mytargetsite.com/suburl/grid.php' (redirected from 'https://mytargetsite.com/suburl/grid.php') from origin 'https://mytargetsite.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
The fact that the declared content script runs or not, should be verified by inspecting in devtools => sources sub-tab => content scripts sub-sub-tab. If it really doesn't run, there can be just two explanations: the URL is different (for example not https) or extensions are blocked by their domain admin via runtime_blocked_hosts which you can see in chrome://policy.
Your development mode extension's id will be different on a different machine unless you pin it by adding a "key" in manifest.json
To use chrome.runtime to send messages to your extension from a webpage code (not from a content script!) your extension's manifest should declare "externally_connectable" and use a different event onMessageExternal, see also sending messages from web pages.
The CORS error may be irrelevant to your code (you can investigate the source of the error by expanding the error's call stack in devtools console).

failed to execute postMessage on DOMWindow : target origin

i am working on firefox addon. i have 2 scripts filler.js and aws.js
filler.js
document.getElementById("orderNow").addEventListener("click", function() {
var domain = 'https://www.amazon.com/';
var openWin = window.open(domain);
//message sender
var message = "WS Iron Man";
openWin.postMessage(message,domain); //sending the message
});
aws.js
window.onload = function () {
//alert('page loaded successfully'); //alert function working here
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
if (event.origin !== "http://localhost/waveapp/includes/pages/order_details.html")
return;
// alert to check function working or not
var msg = event.data;
alert(msg);
}
};
manifest.json
{
"manifest_version": 2,
"name": "Borderify",
"version": "1.0",
"description": "Copy details to amazon.com.",
"icons": {
"48": "icons/border-48.png"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["filler.js"]
},
{
"matches": ["*://*.amazon.com/*"],
"js": ["aws.js"]
}
],
"permissions": [
"clipboardRead",
"unlimitedStorage",
"storage"
]
}
filler.js running in my localhost and aws.js run on amazon.com. this is a firefox extension.
when i run, i am getting error msg in console
"Failed to execute ‘postMessage’ on ‘DOMWindow’: The target origin provided (‘https://www.amazon.com’) does not match the recipient window’s origin (‘null’)"
also getting this msg
"Storage access automatically granted for tracker “https://www.amazon.com” on “http://localhost”"
Please help me fix it, i am sorry for my bad english
I suggest you to read into Window.postMessage().
It says and I quote:
Normally, scripts on different pages are allowed to access each other
if and only if the pages they originate from share the same protocol,
port number, and host (also known as the "same-origin policy").
window.postMessage() provides a controlled mechanism to securely
circumvent this restriction (if used properly).
So it is not a CORS error, because those don't apply in this situation.
There are multiple reasons why this might happen:
You are actually using a different URL than the one provided
You closed your open window already (window will set everything to null, when it is closed)
You are doing something in between window.open and window.postMessage, which might change what is stored inside your reference

Sending message from content script to browseraction in firefox webextension?

Is it possible to send a message from Content script to Browser action directly without using background page? Following is a simplified version of what my code looks like. The content script seems to be working fine, but I get the following error in the console:
Error: Error: Could not establish connection. Receiving end does not exist.
I am assuming it's because the Browser action is not always active. But I don't want to use a Background page because I don't want the script running constantly hogging memory. I am hoping to send message directly to Browser action and display a popup, sort of like browserAction.onClicked displaying a popup. This is my first extension that I am trying to build, so trying to figure things out. Thanks
[manifest.json]
{
"manifest_version": 2,
"name": "Test",
"version": "0.1",
"icons": {
"48": "icons/test.png"
},
"permissions": [
"activeTab"
],
"browser_action": {
"default_icon":"icons/test.png",
"default_title": "test",
"default_popup": "popup/popup.html",
"browser_style": true
},
"content_scripts": [
{
"matches": ["*://testwebsite"],
"js": ["content_scripts/content-script.js"]
}
]
}
[popup.js]
function handleMessage(request, sender, sendResponse) {
console.log("Message from the content script: " +
request.greeting);
sendResponse({response: "Response from background script"});
}
browser.runtime.onMessage.addListener(handleMessage);
[content-script.js]
function handleResponse(message) {
console.log(`Message from the background script: ${message.response}`);
}
function handleError(error) {
console.log(`Error: ${error}`);
}
function send_2_popup() {
var sending = browser.runtime.sendMessage({
greeting: "Greeting from the content script"
});
sending.then(handleResponse, handleError);
}
var btn = document.getElementById("btn");
btn.addEventListener("click", send_2_popup);
You can rather send a message from the popup to the background and get a response as well as a message from background.. this way the background will know that the popup exists and hence the message from background to popup will be successful.

API WebExtensions, communicate between browser and content script

I'm trying to communicate from a web page to an extension and vice versa.
To do so, I looked at the Mozilla documentation here : https://developer.mozilla.org/fr/Add-ons/WebExtensions/Content_scripts#Communicating_with_the_web_page
And it has a simple example, but I can't make it work. On the web page script, I have this :
// page-script.js
var messenger = document.getElementById("from-page-script");
messenger.addEventListener("click", messageContentScript);
function messageContentScript() {
window.postMessage({
direction: "from-page-script",
message: "Message from the page"
}, "*");
On the content scripts page in the extension :
// content-script.js
window.addEventListener("message", function(event) {
if (event.source == window &&
event.data.direction &&
event.data.direction == "from-page-script") {
alert("Content script received message: \"" + event.data.message + "\"");
}
});
I installed the extension (as a temporary one, I uploaded my xpi file), then I used the "Debugging" method of API WebExtensions, and put a breakpoint into the listener, but whenever I call the PostMessage, the extension never seems to receive the event, the breakpoint is never triggered.
Is it possible to communicate this way between a web page and an extension ? Or is there another one ?
The problem was in the manifest of my extension. I declared my content script as a background script.
So, instead of writing this :
"background": {
"scripts": ["myscript.js"],
"persistent": true
},
You have to declare the script like this :
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["myscript.js"]
}
]
I was experiencing similar issues and the problem for me is I was calling the
window.postMessage
function from within an iframe. After I changed this to
top.window.postMessage
it started working.

Google Chrome Extension : Port: Could not establish connection. Receiving end does not exist

I have been looking for an answer for almost a week now, but having read all the stackoverflow items i can't seem to find a solution that is working for me.
The error that i'm having is :
Port: Could not establish connection. Receiving end does not exist. lastError:30 set lastError:30 dispatchOnDisconnect messaging:277
folder layout :
img
developer_icon.png
js
sidebar.js
main.js
jquery-2.0.3.js
manifest.json
my the manifest.json file looks something like this (it is version 2) :`
"browser_action": {
"default_icon": "./img/developer_icon.png"
},
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["./js/sidebar.js"],
"run_at": "document_end"
}
],
"background" : {
"scripts" : ["./js/main.js","./js/jquery-2.0.3.js"]
},
I want to handle the user clicking the extension icon so i could inject a sidebar in the existing website (because the extension i would like to develop requires that amount of space). So in main.js :
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.getSelected(null, function(tab){
chrome.tabs.sendMessage(
//Selected tab id
tab.id,
//Params inside a object data
{callFunction: "toggleSidebar"},
//Optional callback function
function(response) {
console.log(response);
}
);
});
});
and in sidebar.js :
chrome.runtime.onMessage.addListener(function(req,sender,sendResponse){
console.log("sidebar handling request");
toggleSidebar();
});
but i'm never able to see the console.log in my console because of the error. Does someone know what i did wrong?
Thanks in advance!
Just for anyone landing on this page while facing a similar problem:
OP's code does work as expected !
A couple of minor remarks:
The callback for chrome.tabs.sendMessage is optional, so there is no need to define one if you don't intend to call it on the receiving end. I.e. the following is reduntant:
...
//Optional callback function
function(response) {
console.log(response);
}
chrome.tabs.getSelected has beed deprecated and should not be used. Use chrome.tabs.query instead.
In this particular case, the call to chrome.tabs.getSelected is reduntant, since chrome.browserAction.onClicked callback passes the active tab as an argument.

Categories

Resources