Chrome extension messages not getting through - javascript

manifest.json:
{
"manifest_version": 2,
"name": "chrome-extension-bar",
"description": "Chrome Extension Bar",
"version": "1.0",
"browser_action": {
"default_title": "Chrome Extension Bar",
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
},
"permissions": [
"<all_urls>",
"tabs"
],
"content_security_policy": "script-src 'self' https://ajax.googleapis.com/ https://maxcdn.bootstrapcdn.com ; object-src 'self'"
}
background.js:
console.log("In background.js")
chrome.runtime.onMessage.addListener (
function (request, sender, sendResponse) {
console.log("In listener");
// to send back your response to the current tab
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {fileData: response}, function(response) {
sendResponse({farewell: "goodbye"});
});
});
return true;
}
);
content_script.js:
var current_title_bar = document.getElementById("global-nav");
console.log("Title bar:" + current_title_bar);
current_title_bar.appendChild(extension_bar); // <= GODD, getting here
document.getElementById("idStartButton").addEventListener('click', function () {
console.log('Sending start button message: ' + document.getElementById("idNumSecondsPerPage").value);
chrome.runtime.sendMessage({numSecondsPerPage : document.getElementById("idNumSecondsPerPage").value}, function(response) {
console.log('Got response: ' + response.farewell);
});
});
document.getElementById("idStopButton").addEventListener('click', function () {
console.log('Sending stop button message: ' + document.getElementById("idNumPages").value);
chrome.runtime.sendMessage({numPages : document.getElementById("idNumPages").value}, function(response) {
console.log('Got response: ' + response.farewell);
});
});
The messages seem to be getting sent, but there's I'm not getting anything back from the receiver.
Console log on the page into which the form was injected:
Entering content_script.js
content_script.js:156 Title bar:[object HTMLElement]
content_script:161 Sending start button message: 67
content_script:168 Sending stop button message: 76
Why aren't the messages sent by background.js received by content_script.js? Are they even sent?

If you want to send a message from the background.js script to the content_script.js then you need to set an onMessage listener on the content script.
What you might do in this case is, after receiving the event on the background script, just call the callback function, instead you're sending a new event with a callback function than when it is executed, calls the callback function of the first event.
Instead of doing this:
console.log("In listener");
// to send back your response to the current tab
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {fileData: response}, function(response) {
sendResponse({farewell: "goodbye"});
});
});
just do this
console.log("In listener");
// send back your response
sendResponse({farewell: "goodbye"});

Related

Could not establish connection. Error for chrome extension

I am making a chrome extension and am trying to get my background script to communicate with my content script each time a tab is update. This is the code I am using
//Background
chrome.tabs.onActivated.addListener(function(activeInfo) {
console.log("Tab with id: " + activeInfo.tabId + " and window: " + activeInfo.windowId + " is now active");
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {message : "run", data: "replaceText"}, function(response) {});
});
});
//content
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.message === "run") {
console.log("Received message: " + request.message);
Display();
}
})};
//manifest
"permissions": ["tabs","activeTab","nativeMessaging"],
I am still getting the error Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
I have tried deactivating all my extensions and changing code nothing works.

Sending data from Chrome extension to local python file

I'm trying to send some data from a Chrome extension content script to a background script to my local python file. It goes from the content script to the background script fine, but when I try to send it to the python file, I just get "POST http://localhost:5000/bootstrap 400 (BAD REQUEST)." Can't figure out what's going on. I'm new to this. Many thanks!
background.js
// Sending messages from background / event page
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
chrome.tabs.query({ active: true }, function(tabs) {
const msg = "Hello from background 🔥";
chrome.tabs.sendMessage(tabs[0].id, { "message": msg });
})
}
});
// Listening to messages page
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log(request);
var articleData = request
// Callback for that request
$.ajax({
type: 'POST',
url: 'http://localhost:5000/bootstrap',
data: articleData,
success: function (newArticle){
alert('success');
}
})
sendResponse({ message: "Background has received that message 🔥" });
});
relevant part of fakenews.py
#app.route('/bootstrap', methods=['GET', 'POST'])
def bootstrap():
posted = 1
print ("bootstrap")
global article
if request.method == 'POST':
if not request.form['title'] or not request.form['url'] or not request.form['image_url'] or not request.form['snippet']:
flash('Please enter all the fields', 'error')
else:
article = Article(request.form['title'], request.form['url'], request.form['image_url'],
request.form['snippet'])
db.session.add(article)
try:
db.session.commit()
except exc.SQLAlchemyError:
flash('Article url already exists, failed to post new article')
posted = 0
#return render_template('/error.html', article_url=article.url)
article_list = Article.query.filter_by(url=article.url)
if posted == 1:
flash('Record was successfully added')
else:
db.session.rollback()
article_list = Article.query.filter_by(url=article.url)
article=article_list[0]
print ("article.id=" + str(article.id))
vote_choices = VoteChoice.getVoteChoiceList()
return render_template('/votefor.html', article_id=article.id,
article_title=article.title,
article_url=article.url, vote_choices=vote_choices
)
relevant part of content.js
chrome.runtime.sendMessage({ message: [title, image, url] }, function(response) {
console.log(response);
});
// Listening to messages in Context Script
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log(request);
// Callback
sendResponse({ message: 'Content script has received that message âš¡' })
})
});
manifest.json
{
"manifest_version": 2,
"name": "OrangeBox",
"version": "1.0",
"permissions": ["http://localhost/" ,"tabs"],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["contentScript.js"]
}
],
"background": { "scripts": ["jquery-3.4.1.js", "background.js"], "persistent": false },
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["jquery-3.4.1.js", "waitForKeyElements.js", "content.js"]
}
]
}
Problem
In content.js you're sending
message: [title, image, url]
The background.js is just passing this on to fakenews.py, and this is where things break...
fakenews.py is expecting a request object that looks like
{
title: <some time>,
url: <some url>,
image_url: <...>,
snippet: <...>
}
but what it's getting looks like
{
message: [
<some title>,
<some image>,
<some url>
]
}
Fix
The quick fix is changing the content.js line to be
chrome.runtime.sendMessage({"title": title, "image_url": image, "url": url, "snippet": "test"}, function(response) {
Note I'm putting a placeholder for snippet because the backend is expecting a value for it

Chrome extension, how to send message from panel to content script

My contentScript sends a message to backgroundScript which opens a popup/panel/window. This panel loads an external web page.
I'm injecting some javascript in the panel to interact with it.
What I'm trying do achieve now is to send data from the panel to the 'main page' (contentScript).
I have successfully managed to send messages from the panel to the backgroundScript.
What I don't understand/know is how to pass the data from the backgoundScript to the contentScript.
Updated script from #Haibara Ai's comment
manifest.js
{
"name": "My extension",
"version": "0.1",
"manifest_version": 2,
"description": "description",
"permissions": ["activeTab", "tabs","http://*/*","https://*/*"],
"content_scripts": [
{
// Change 'matches' attribute to load content
// script only in pages you want to.
"matches": ["SomeUrl"],
"js": ["jquery.min.js", "contentscript.js", "notifier.js"]
}
],
"background": {
"scripts": ["eventPage.js"],
"persistent": false
}
}
contentscript.js
$(document).ready(function() {
var link = document.getElementById('inputLink');
// onClick's logic below:
link.addEventListener('click', function() {
chrome.runtime.sendMessage({
action: 'createWindow',
url: $('input[name=link]').val()
}, function(message) {
console.log(message);
})
});
});
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
alert('a');
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
});
eventPage.js
chrome.runtime.onMessage.addListener(function(request) {
if (request && request.action === 'createWindow' && request.url) {
chrome.windows.create(
{
url: request.url,
focused: true,
incognito: true,
type: "panel"
}, function (newWindow) {
chrome.tabs.executeScript(newWindow.tabs[0].id, {
file: "jquery.min.js"
}, function() {
chrome.tabs.executeScript(newWindow.tabs[0].id, {
file: "htmlselection.js"
});
});
chrome.tabs.insertCSS(newWindow.tabs[0].id, {file: "htmlselection.css"});
});
} else {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
console.log(chrome.tabs);
chrome.tabs.sendMessage(tabs[0].id, {action: "SendIt"}, function(response) {});
});
}
});
htmlselection.js (injected in the popup/panel/window)
[...]
//After a click within the popup/panel/window
chrome.runtime.sendMessage({ text: 'test' });
[...]
Thank you for your help.
Updated
If you want to send message inside chrome.runtime.onMessage, just use the callback sendResponse or use sender.tab.id as tabId to send back the message.
And there are other problems with your code:
Since you are use Programming injection to inject script, you should declare them in "web_accessible_resources" in manifest.json
"web_accessible_resources": [
"htmlselection.js",
"jquery.min.js",
"htmlselection.css"
]
In your contentscript.js, just remove message part, since you didn't receive anything in this script.
For eventpage.js, use sendResponse instead of tab.query.
else {
console.log("2");
sendResponse({ action: "SendIt" });
}
Previous
Take a look at Message Passing, you could send a message from background page using the following code snippets:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
Fixed version of the snippet:
chrome.tabs.query({active: true, currentWindow: false}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
Set the currentWindow:false and it worked.

Chrome Extension post request not sending data

First time using the site to ask a question. I'm new to Chrome Extensions so I'm sure I'm making some stupid mistake. I apologize in advance.
I'm trying to grab the current tab's url and POST it to a URL that will then recieve it and push it into a database. Like my own personal bookmarking service. I've debuged as much as I can, the data is making it all the way to where i'm sending my XHR request.. but the data doesn't come out when I echo it on my server side script. I'm confirming that it's hitting my URL because i'm console logging the output... but again no data is being passed.
BACKGROUND.JS
chrome.runtime.onMessage.addListener(function(request, sender, callback) {
if (request.action == "xhttp") {
var xhttp = new XMLHttpRequest();
var method = request.method ? request.method.toUpperCase() : 'GET';
xhttp.open(method, request.url, true);
xhttp.send(request.data);
xhttp.onload = function() {
callback(xhttp.responseText);
};
return true
}
});
MANIFEST.json
{
"name": "bookmarker",
"version": "0.0.1",
"manifest_version": 2,
"description": "POSTIN BOOKMARKS!",
"homepage_url": "URL",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"permissions": [
"contentSettings",
"cookies",
"tabs",
"geolocation",
"http://*/*"
],
"content_scripts": [
{
"js": ["contentscript.js"],
"matches": ["http://*/*"]
}
],
"browser_action": {
"default_icon": "icons/icon16.png",
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"],
"persistent": false
}
}
MAIN.JS
jQuery(function() {
jQuery('.reminded').on('click', function(e){
e.preventDefault();
chrome.tabs.query({currentWindow: true, active: true}, function(tabs){
var url = tabs[0].url,
date = 1391048414,
clientId = 1234
chrome.runtime.sendMessage({
method: "POST",
action: "xhttp",
url: "http://www.API.com/endpoint",
data: {url: url, date: date, clientId: clientId}
}, function(responseText) {
console.log(responseText);
});
});
});
});
Thank you very much in advance for any light anyone can share.
You didn't mention where "main.js" was used, but I guess that it's used in the popup page, right? The popup page can also make cross-domain requests in a Chrome extension when you've declared the permissions in the manifest file. So, just use jQuery.ajax directly to make the cross-domain request:
jQuery.ajax({
type: "POST",
url: "http://www.API.com/endpoint",
data: {url: url, date: date, clientId: clientId},
success: function(data) {
console.log(data);
}
});
For the record, the code in your question is failing because you're trying to submit a JavaScript Object ({url: url, date: date, clientId: clientId} via the .send method of a XMLHttpRequest. This makes no sense, and your server would receive the string [object Object] because of the default serialization of objects.
To get your original code to work, you should use jQuery.param to serialize the form data and xhttp.setRequestHeader("Content-Type", "application/x-www-form-url-encoded");.

Accessing API from Chrome extension

I have a website which I have added as an extension in Google Chrome. What I need is that I have to access a server file from the extension. And I need is that whatever the server file outputs, I need to access the output in the extension.
Here is my manifest.json:
{
"name": "Calpine Extension",
"version": "1.0",
"description": "Log on to calpinemate",
"manifest_version": 2,
"browser_action": {
"default_icon": "icon_128.png"
},
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"browser_action": {
"default_title": "Test Extension",
"default_icon": "calpine_not_logged_in.png"
},
"externally_connectable": {
"matches": ["http://calpinemate.com/"]
}
}
Here is my background.js
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.create({ "url": "http://calpinemate.com" });
});
Now what I need is that I have a server file (index.php) which outputs 1. Now what I need is that I want to get this 1 in extension. That is whatever the file outputs I want that output in extension. How can I do that?
Here is my index.php
<?php echo 1 ;?>
I tried this.But still it is only working on Onclick event.Please check my code.
Here is my background.js
function getGmailUrl() {
return "http://calpinemate.com/";
}
function isGmailUrl(url) {
return url.indexOf(getGmailUrl()) == 0;
}
chrome.browserAction.onClicked.addListener(gotopage);
function gotopage(){
chrome.tabs.query({
url: "http://calpinemate.com/*",
currentWindow: true
}, function(tabs) {
if (tabs.length > 0) {
var tab = tabs[0];
console.log("Found (at least one) Gmail tab: " + tab.url);
console.log("Focusing and refreshing count...");
chrome.tabs.update(tab.id, { active: true });
updateIcon();
} else {
console.log("Could not find Gmail tab. Creating one...");
chrome.tabs.create({ url: getGmailUrl() });
updateIcon();
}
});
}
if (chrome.runtime && chrome.runtime.onStartup) {
chrome.runtime.onStartup.addListener(function() {
updateIcon();
});
} else {
chrome.windows.onCreated.addListener(function() {
updateIcon();
});
}
function updateIcon(){
var req = new XMLHttpRequest();
req.addEventListener("readystatechange", function() {
if (req.readyState == 4) {
if (req.status == 200) {
localStorage.item=req.responseText;
//alert(localStorage.item);
if(localStorage.item==1){
chrome.browserAction.setIcon({path:"calpine_logged_in.png"});
chrome.browserAction.setBadgeBackgroundColor({color:[190, 190, 190, 230]});
chrome.browserAction.setBadgeText({text:""});
}
else{
chrome.browserAction.setIcon({path:"calpine_not_logged_in.png"});
chrome.browserAction.setBadgeBackgroundColor({color:[190, 190, 190, 230]});
chrome.browserAction.setBadgeText({text:""});
}
// We received the data
//alert("Data: " + req.responseText);
} else {
// Handle the error
alert("ERROR: status code " + req.status);
}
}
});
req.open("GET", "http://blog.calpinetech.com/test/index.php", true);
req.send(null);
}
First request permission to access your server:
// In manifest.json
...
permissions: [
...
"*://calpinemate.com/index.php"
],
Then use AJAX to access the data:
var req = new XMLHttpRequest();
req.addEventListener("readystatechange", function() {
if (req.readyState == 4) {
if (req.status == 200) {
// We received the data
alert("Data: " + req.responseText);
} else {
// Handle the error
alert("ERROR: status code " + req.status);
}
}
});
req.open("GET", "https://calpinemate.com/index.php", true);
req.send(null);

Categories

Resources