I'm writing an extension, I made a menu to it in which the user enters some data. It is necessary to make so that on a click on the button (in the menu of expansion) these data.
Here is how it must works: background.js is the file that is responsible for js in the extension menu. content.js is the file that is responsible for making changes to the DOM on the sites.
document.getElementById('btn').onclick = function() {
var first = document.getElementById('first').value;
var second = document.getElementById('second').value;
//sending in content.js
chrome.extension.sendMessage('hello');
}
<head>
<script type="text/javascript" src="content.js"></script>
<script type="text/javascript" src="background.js"></script>
</head>
<input type="text" id="first">
<input type="text" id="second">
<input type="button" id="btn" value="send">
content.js Getting data:
chrome.extension.onMessage.addListener(function(request){
if(request=='hello'){
console.log('1. Get: ', request);
}
});
But from background.js i get nothing.
Here is manifest.json
{
"manifest_version": 2,
"version": "1.3",
"description": "name",
"browser_action":{
"default_popup": "content/popup.html"
},
"background": {
"persistent": false,
"scripts": ["content/background.js"]
},
"content_scripts": [
{
"matches": [ "https://google.com/*" ],
"js": ["content/content.js"],
"css": ["content/qq.css"],
"run_at": "document_end"
}
]
}
It turns out that I need to send the entered data in the field with the button send to a file that will insert this data into the page I need. How to do it?
Help, because if I put the code that it does in my js file, then it tries to take this data frominput on the page, and not from the extension menu.
Here is the structure:
Ok, there seems to be a couple of n00b issues here:
background.js is a script that runs in the background of all tabs/pages. (The "background" section in the manifest.json specifies this).
PS: The way to debug the background.js is to open chrome's extension page (chrome://extensions/) and click on "Inspect Views: background page" from there. Typically, this is where most of your code would be.
content.js will automatically be inserted into all google.com pages, according to your manifest.
popup.html and it's code only exists as long as the popup is visible. It's typically very light, with little code. So, in your popup.html, remove the two existing <script> entries you have, and just use a single script, (typically popup.js):
<script type="text/javascript" src="popup.js"></script>
When sending info from the popup (or background) to the current tab (in your case it's going to be google.com only) you use the general code:
// Get the current tab & tell it to do something
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var currentTab = tabs[0];
var id = currentTab.id;
chrome.tabs.sendMessage(id,
{ action: 'foo', data:... },
response => { console.log('some response from content.js is:' + response); });
});
but to send a message to the background (from a page or your content script inside google.com), you'd just use this chrome.runtime.sendMessage({action:'foo', data:...});
So, your code should probably be something like:
popup.html
<head>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>...
popup.js:
document.getElementById('btn').onclick = function() {
var first = document.getElementById('first').value;
var second = document.getElementById('second').value;
//sending in content.js
var foo_data="I am foo";
// Get the current tab & tell it to do something
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var currentTab = tabs[0];
var id = currentTab.id;
chrome.tabs.sendMessage(id,
{ action: 'hello', foo:foo_data, first:first, second:second },
response => { console.log(response); });
});
}
background.js
(nothing)
content.js
chrome.runtime.onMessage.addListener(function(request,sender, sendResponse){
if(request.action=='hello'){
console.log(request.foo + ' ' request.first + ' ' + request.second);
sendResponse('I got foo!');
}
});
If it's any help, I've a tiny project that I use to get started on webextension projects here: https://github.com/cmroanirgo/webextension-template. It's got some code to help with making it work cross browser (Firefox, Opera & maybe Edge)
I hope this helps.
Related
I am building a simple page-scraping chrome extension to get a page's title and the contents of a shopping cart. I am getting the shopping cart contents twice but not the tittle page. The chrome.runtime.onMessage.addListener() function is returning the same message twice to popup.html and getting a duplicate of the shopping cart's content and no page title. I have tried to construct the chrome.runtime.onMessage.addListener()in different ways, to no avail. Please advise on where I went wrong or suggest a better approach?
manifest.json
(permissions are allowed on all urls but I'm currently testing the extension on the checkout page of an ecommerce website)
"manifest_version": 2,
"name": "Webscraper Extension",
"description": "Webscraper extension for Chrome",
"version": "1.0",
"background": {
"scripts": ["popup.js"],
"persistent": true
},
"permissions": [
"tabs",
"http://*/",
"https://*/"
],
"browser_action": {
"default_icon": "logo.png",
"default_popup": "popup.html"
}
poppup.html
<!doctype html>
<html>
<head>
<title>Webscraping Extension</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h3>Checkout</h1>
<p id='pagetitle'>This should change to the scraped title!</p>
<div id='cart'>Cart here!</div>
<button id="checkout" class "button">Checkout</button>
</body>
<script src="popup.js"></script>
</html>
popup.js
// Inject the payload.js script into the current tab after the popout has loaded
window.addEventListener('load', function (evt) {
chrome.extension.getBackgroundPage().chrome.tabs.executeScript(null, {
file: 'payload.js'
});;
});
// Listen to messages from the payload.js script and write to popout.html
chrome.runtime.onMessage.addListener(function (message) {
document.getElementById('pagetitle').textContent = message;
document.getElementById('cart').textContent = message;
});
payload.js
// send the page title as a chrome message
chrome.runtime.sendMessage(document.title);
//send the cart as chrome message
var result = "";
var cartitems = document.getElementsByClassName("item-list");
for (var i = 0; i < cartItems.length; i++) {
result += cartItems[i].textContent;
}
chrome.runtime.sendMessage(result);
You have only one message listener that overwrites the textContent of both pagetitle and cart with whatever message it receives. Therefore, both are overwritten with result, which is the latest message received.
Try discriminating the messages with something like:
popup.js
chrome.runtime.onMessage.addListener(function (message) {
if (message.title) document.getElementById('pagetitle').textContent = message.title;
if (message.cart) document.getElementById('cart').textContent = message.cart;
});
payload.js
// send the page title as a chrome message
chrome.runtime.sendMessage({title:document.title});
//send the cart as chrome message
var result = "";
var cartitems = document.getElementsByClassName("item-list");
for (var i = 0; i < cartItems.length; i++) {
result += cartItems[i].textContent;
}
chrome.runtime.sendMessage({cart:result});
I just wanted to ask you if it's possible to send a message from content script to the popup script. It works the other way around - from popup to content:
popup.js
let counter = 0;
let userInput = document.getElementById("userInput").addEventListener("click", () => {
counter++
let params = {
active: true,
currentWindow: true
}
chrome.tabs.query(params, gotTabs);
function gotTabs(tabs) {
chrome.tabs.sendMessage(tabs[0].id, counter)
}
});
content.js
chrome.runtime.onMessage.addListener(gotMessage);
function gotMessage(message) {
console.log(message)
}
index.html
<!DOCTYPE html>
<html>
<body>
<h2>Hello there!</h2>
<button id="userInput">Click me!</button>
</body>
<script src="popup.js"></script>
</html>
My question is, how can I send a message from content script to the popup script, if its possible, because when I switch those files, i got errors like:
content.js:14 Uncaught TypeError: Cannot read property 'query' of undefined
at HTMLDocument.myClickHandler
Thanks for your help.
i want to create a google chrome extension to send data from a a popup form into localhost server. i created below files. Everything works fine but data does not send to localhost server.
could anyone please help me where is my mistake?
thanks.
manifest.json
{
"manifest_version": 2,
"name": "server Plug-ins",
"description": "Send data to database",
"version": "1.0",
"icons": {
"48": "icon.png"
},
"permissions": [
"history",
"browsingData",
"tabs",
"<all_urls>",
"http://192.168.1.222/*",
"storage"
],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html",
"default_title": "Send data to server!"
}
}
alert.js
document.write(" i am here . . .");
// Create our XMLHttpRequest object
var hr = new XMLHttpRequest();
// Create some variables we need to send to our PHP file
var url = "http://192.168.1.222/my_parse_file.php";
var fn = document.getElementById("name").value;
var ln = document.getElementById("details").value;
var vars = "name="+fn+"&details="+ln;
hr.open("POST", url, true);
// Set content type header information for sending url encoded variables in the request
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// Send the data to PHP now... and wait for response to update the status div
hr.send(vars); // Actually execute the request
popup.html
<body>
<label for="">Name</label><br><input type="text" id="name"> <br>
<label for="">Details</label><textarea id="details"></textarea>
<input id="clickme" name="myBtn" type="submit" value="click me">
<script type="text/javascript" src="popup.js"></script>
</body>
popup.js
function hello() {
chrome.tabs.executeScript({
file: 'alert.js'
});
}
document.getElementById('clickme').addEventListener('click', hello);
I think that the problem is that your popup input elements cannot be accessed in the context were the alert.js script is running.
In the alert.js's context, document refers to the document of the tab in which you've inject the script.
You can do something like this to make it work, replace the content of your popup.js file with this:
function hello() {
function contentScript(fn, ln){
document.write(" i am here . . .");
var hr = new XMLHttpRequest();
var url = "http://192.168.1.222/my_parse_file.php";
var vars = "name="+fn+"&details="+ln;
hr.open("POST", url, true);
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
hr.send(vars);
}
var fn = document.getElementById("name").value;
var ln = document.getElementById("details").value;
chrome.tabs.executeScript({
code: (contentScript.toString() + "\ncontentScript('" + fn + "', '" + ln + "');")
});
}
document.getElementById('clickme').addEventListener('click', hello);
You can remove your alert.js file because now, the extension will inject JavaScript code directly instead of injecting a file.
I'm developing a chrome app and i'm trying to send a message to an external webpage. In the whole scenario, the external webpage needs to send a message back (but i'm not trying to achieve this yet).
Here is my code:
background.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Prototype</title>
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<script src="https://code.jquery.com/jquery.js"></script>
<script src="background.js"></script>
</body>
</html>
background.js
var FileMessage = "Hello!";
var scriptName = "script.js";
var tabID;
//open a new tab with an app
function openApp() {
var url = "link_to_external_webpage_on_personal_server";
var win = window.open(url);
}
//function to run js files inside the extension
function runScript(script){
chrome.tabs.executeScript(null, {file: script});
}
//function to send a message to all tabs
function sendMessage(){
chrome.tabs.query({'active': true}, function(tabs) {
if(tabs.length === 1){
var tab = tabs[0];
//var tabID = tab.id;
chrome.extension.sendMessage(null, {newMessage : FileMessage});
console.log("extension sent a message...");
}
});
}
//main()
$(document).ready(function() {
openApp();
//when a new tab is updated
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
//createEvent();
sendMessage();
}
});
});
/*function createEvent(){
$.event.trigger({
type: "newMessage",
message: "Hello World!"
});
}*/
external js file
$(document).ready(function() {
console.log( "app script is running" );
$(document).on("newMessage", newMessageHandler);
/*document.addEventListener("myEvent",myEventHandler);*/
document.addEventListener("newMessage",myEventHandler);
document.addEventListener('newMessage', function(event) {
console.log("message received...");
}, false);
});
I can see that most of the code is running with the console prints. The only one i'm not receiving is the one saying "message received". I've also tried using events (commented in the code) but i was not successful too.
Does anyone know what i'm doing wrong ?
Thanks in advance for the help !
I'm attempting to upload files from a chrome extension to dropbox using the saver api. When the saver window loads however, no files are displayed in the GUI.
Clicking save or cancel does nothing. More importantly (I think), in the background the console throws the following message:
Unable to post message to
chrome-extension://[chrome extension ID]. Recipient has
origin https://www.dropbox.com.
I've read the cross-origin extension documentation, and I believe I have my manifest file configured correctly. It is as follows:
{
"name": "Pic Grabber",
"version": "2.0",
"permissions": [
"activeTab",
"tabs", "<all_urls>", "background",
"http://*/*",
"https://*/*",
"http://*",
"https://*"
],
"content_scripts": [{
"js": ["grabber.js"],
"matches": ["http://*/*", "https://*/*"]
}],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_title": "Download pictures from this page.",
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"manifest_version": 2,
"content_security_policy": "script-src 'self' https://www.dropbox.com/static/api/1/dropins.js; object-src 'self'"
}
I've verified the dropin works on some test code on a server I have access to. Relevent results of diff of the server (which works) and extension GET requests are as follows:
Server:
Request URL:https://www.dropbox.com/saver?origin=[SERVER'S ORIGIN]&app_key=[APP KEY]
Extension:
Request URL:https://www.dropbox.com/saver?origin=chrome-extension[CHROME EXTENSION ID]&app_key=[SAME APP KEY]
Server:
referer:[PATH TO TEST HTML FILE ON SERVER]
(No referer on Extension)
Server:
url:/saver?origin=http%3A%2F%2Fwww.uvm.edu&app_key=7tvbf4mpgd2v56z
Extension:
url:/saver?origin=chrome-extension[CHROME EXTENSION ID]&app_key=[APP KEY]
Server:
origin:[SERVER DOMAIN]
Extension:
origin:chrome-extension://[CHROME EXTENSION ID]
The html of my extension popup is as follows:
<!doctype html>
<!-- used to display the images found by the scripts and offer a save to dropbox button -->
<html>
<head>
<title>PicGrabber</title>
</head>
<body>
<h3>Download the following pictures:</h1>
<hr>
<div id="btn-container"></div>
<script type="text/javascript" src="https://www.dropbox.com/static/api/1/dropins.js" id="dropboxjs" data-app-key="[KEY]"></script>
<script type="text/javascript" src="popup.js"></script>
</body>
</html>
(popup.js is the source of my content-script that performs the bulk of the work of the extension. This script appears to be working correctly, but if I would help I'd be happy to post it as well).
I'm afraid I'm not sure exactly where the error lies. It seems that somehow, the dropbox API is unable to communicate properly with the extension, resulting in a malformed popup that cannot communicate with the Dropbox server.
Any tips/pointers in the right direction would be really appreciated. Thanks!
Edit: I've added the popup.js code to this post in the hope it will help-
/**
This is the popup.js file, used to receive the list of urls that the grabber content script has found and expose them to the popup.html file.
**/
function get_urls() {
var picUrls = chrome.extension.getBackgroundPage().IMAGE_URLS;
if (picUrls){
console.log("The popup.js is working")
// create a container object for the list
var listContainer = document.createElement("div");
// add it to the DOm
document.getElementsByTagName("body")[0].appendChild(listContainer);
// create a ul object for the list items
var listElement = document.createElement("ul");
// add that to the DOm
listContainer.appendChild(listElement);
saveThese = []
// loop through the urls, and append them to the ul object
for (var i = picUrls.length - 1; i >= 0; i--) {
var listItem = document.createElement("li");
// listItem.innerHTML = "<a href='" + picUrls[i].src +"'>" + picUrls[i].name + "</a><img src='" + picUrls[i].src + "'width=25%, height=25%></img>";
listItem.innerHTML = "<img src='" + picUrls[i].src + "'width=25%, height=25%></img>";
listElement.appendChild(listItem);
saveThese.push({
'url':picUrls[i].src,
'filename':picUrls[i].name
});
}
// create dropbox saver dropin
options = {
files: saveThese,
success: function() {},
progress: function(progress) {},
cancel: function() {},
error: function(errmsg) {}
} // end options
}
Dropbox.createSaveButton(options);
var btn = Dropbox.createSaveButton(options);
document.getElementById('btn-container').appendChild(btn);
}
window.onload = get_urls();