Basic message passing in chrome extension seems to fail - javascript

I have read the documentation and this should be basic but I can't seem to get those alerts to appear. What's wrong?
popup.html
<html>
<head>
<script>
function finder() {
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendMessage(tab.id, {type: "feature"}, function(response) {
console.log(response.farewell);
});
});
}
</script>
<style>
p {
border: 1px solid black;
width:200px;
font-size:10px;
}
</style>
</head>
<body>
<p><a id="jira">Click to populate FE description</a></p>
<script>
var jira = document.getElementById('jira');
jira.addEventListener('click', finder, false);
</script>
</body>
</html>
Content Script:
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
alert('sreceived');
if (request.type == "feature") {
alert('score!');
}
});

Inline JavaScript will not be executed. This restriction bans both inline blocks and inline event handlers (e.g. <button onclick="...">).
By above lines it is clear that your popup.html violates restrictions, which can be solved as follows:
Remove all <script> tags in popup.html and move the original code to popup.js.
<html>
<head>
<script src="popup.js"></script> <!-- Added this line -->
<style>
p {
border: 1px solid black;
width:200px;
font-size:10px;
}
</style>
</head>
<body>
<p><a id="jira">Click to populate FE description</a></p>
</body>
</html>
I did not literally copy-paste the code in popup.js. These are the changes I made:
chrome.tabs.getSelected() is deprecated in favour of chrome.tabs.query(), so I updated chrome.tabs.getSelected(null, function(tab) {});
Commented out console.log(response.farewell); because there is no response handler from content script.
Final popup.js
function finder() {
chrome.tabs.query({
"status": "complete",
"currentWindow": true,
"active": true
}, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
type: "feature"
}, function (response) {
//console.log(response.farewell);
});
});
}
document.addEventListener('DOMContentLoaded',= function() {
document.getElementById('jira').onclick = finder;
});
Cautions for manifest.json
Ensured permissions are available as "permissions":["tabs","<all_urls>"],
Permissions for content script also
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
Final manifest.json
{
"name":"Basic Message Passing",
"description":"This demonstrates Basic Message Passing",
"browser_action":{
"default_popup":"popup.html",
"default_icon":"screen.png"
},
"manifest_version":2,
"version":"2",
"permissions":["tabs","<all_urls>"],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
}
Your content script was fine, so I did not change it.
Demonstration
Output:
Let me know if you need more information..

Related

Chrome extensions (can't get and click elements on new chrome tabs)

That's it. Lemme explaim myself.
I coded a chrome extension that when clicking on a button, it will open a new resized tab (a paypal login) , but I can't manage to click the "log in button" of paypal because trying to
document.getElementById('btnLogin').click();
isn't working, neither adding that:
var paypal = window.open("https://www.paypal.com/es/signin", "PayPal", "width=400,height=400,location=yes,menubar=yes,status=yes,titilebar=yes,resizable=yes");
paypal.onload = function() {
paypal.document.getElementById('btnLogin').click();
}
Check out all of my code:
manifest.json
{
"manifest_version": 2,
"name": "Zapatillao",
"description": "Yatusabe te cojo sapatilla",
"version": "2.0.0",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"browser_action": {
"default_popup": "popup.html",
"default_icon": "icon128.jpg"
},
"permissions": [
"tabs",
"http://*/*",
"https://*/*",
"chrome://*/*"
]
}
content.js
document.getElementById('paypal_prelog').addEventListener('click', function() {
chrome.tabs.executeScript({
file: "paypal_prelog.js"
});
});
popup.html
<html>
<head>
<style>
html, body {
height: 200px;
width: 200px;
}
</style>
</head>
<body>
<h1>Discord: Loan#2334</h1>
<button id='paypal_prelog'>PayPal Prelogin</button>
<script src='content.js'></script>
</body>
</html>
paypal_prelog.js
function sleep (ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
var paypal = window.open("https://www.paypal.com/es/signin", "PayPal", "width=400,height=400,location=yes,menubar=yes,status=yes,titilebar=yes,resizable=yes");
paypal.onload = function() {
paypal.document.getElementById('btnLogin').click();
}
function closeWin() {
paypal.close();
}
I have tried thousand of things, hope you can help me.
The solution for a ManifestV2 extension, which you are writing, in short, is to open a new paypal sign-in window using chrome.windows.create and then use chrome.tabs.executeScript to inject a content script code that clicks btnLogin . Your current code does it all wrong though.
Remove content_scripts, tabs, and chrome://*/* from manifest.json.
Remove content.js from your extension and popup.html
Remove paypal_prelog.js
Create popup.js
document.getElementById('paypal_prelog').onclick = () => {
chrome.windows.create({
url: 'https://www.paypal.com/es/signin',
width: 400,
height: 400,
}, w => {
chrome.tabs.executeScript(w.tabs[0].id, {
code: `(${() => {
document.getElementById('btnLogin').click();
}})()`,
});
});
};
load popup.js in popup.html:
<script src="popup.js"></script>
</body>

JQuery Chrome Extension not working

I'm having an issue with my contentscript. I cannot get Jquery to function no matter what! Perhaps you can help me figure out what it is?
I am trying to "catch" a value I write in a field and pass it on for processing after I click a button. I am recieving the "$ is not defined" error which probably means it cannot load JQuery.
Here is my manifest, my html and my code:
{
"name": "Test 2017",
"manifest_version": 2,
"version": "0.1",
"description": "TestApp Jquery",
"browser_action": {
"default_popup": "popup.html",
"default_icon": "icon.png"
},
"background": {
"scripts": ["jquery-3.2.1.min.js",
"background.js"
]
},
"permissions": [
"tabs", "http://*/*", "https://*/*"
],
"content_scripts":
[
{
"matches": [ "http://*/*", "https://*/*"],
"js":["jquery-3.2.1.min.js",
"contentscript.js"]
}
]
}
Popup.html:
<html>
<head>
<script src="jquery-3.2.1.min.js"></script>
<script src="popup.js"></script>
<style type="text/css" media="screen">
body { min-width:250px; text-align: center; }
#click-me { font-size: 20px; }
</style>
</head>
<body>
<div>Input: <input id="input">
<input id="click-me" type="button" value="Go!"/>
</body>
Popup.js
function clickHandler(e) {
chrome.extension.sendMessage({directive: "popup-click"}, function(response)
{
this.close(); // close the popup when the background finishes processing
request
});
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('click-me').addEventListener('click', clickHandler);
})
background.js
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
switch (request.directive) {
case "popup-click":
// execute the content script
chrome.tabs.executeScript(null, { // defaults to the current tab
file: "contentscript.js", // script to inject into page and run in sandbox
allFrames: true // This injects script into iframes in the page and doesn't work before 4.0.266.0.
});
sendResponse({}); // sending back empty response to sender
break;
default:
// helps debug when request directive doesn't match
alert("Unmatched request of '" + request + "' from script to
background.js from " + sender);
}
}
);
Contentscript.js where I try to run Jquery:
var abc = $("#input").val();
console.log(abc);
And then I get the error.
Any help here? Why can't my extension load JQuery? I have the scripts loaded in the right order and all.
Thanks in advance!
There is no need to use a content script for what you are trying to achieve. Content scripts are used to control the DOM of the website that is loaded in your browser. The button you are trying to manipulate is in your popup window and is controlled by popup.js, not contentscript.js. Simply move the jquery code to popup.js and it should work as expected.
Content Scripts are JavaScript files that run in the context of web pages. By using the standard Document Object Model (DOM), they can read details of the web pages the browser visits, or make changes to them.
Popup.html (nothing changed here, jquery script tag is present):
<html>
<head>
<script src="jquery-3.2.1.min.js"></script>
<script src="popup.js"></script>
<style type="text/css" media="screen">
body { min-width:250px; text-align: center; }
#click-me { font-size: 20px; }
</style>
</head>
<body>
<div>Input: <input id="input">
<input id="click-me" type="button" value="Go!"/>
</body>
Popup.js:
function clickHandler(e) {
chrome.extension.sendMessage({directive: "popup-click"}, function(response)
{
this.close(); // close the popup when the background finishes processing
request
});
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('click-me').addEventListener('click', clickHandler);
})
var abc = $("#input").val();
console.log(abc);

chrome extension message passing no response

I'm working on a pretty simple browser extension, but can't get the message passing to work:
I can send messages, but the response is never delivered!
My code:
Its mostly just a copy from the browserActions tutorial, contentscripts tutorial (manifest) and message-passing api definition.
manifest.json:
{
"manifest_version":2,
"name": "FUN SCRIPT",
"version": "1",
"description": "THIS IS SOME FUN SCRIPT",
"browser_action": {
"name": "Fun",
"icons": ["icon.png"],
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"content_scripts": [ {
"js": [ "jquery.js", "background.js" ],
"matches": [ "http://*/*", "https://*/*"]
}],
}
background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
});
popup.js
document.addEventListener('DOMContentLoaded', function () {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
});
popup.html
<!doctype html>
<html>
<head>
<title>Getting Started Extension's Popup</title>
<style>
body {
min-width: 357px;
overflow-x: hidden;
}
img {
margin: 5px;
border: 2px solid black;
vertical-align: middle;
width: 75px;
height: 75px;
}
</style>
<script src="popup.js"></script>
</head>
<body>
</body>
</html>
Since the message from your popup to the content script is sent whenever the popup is loaded, be sure to reload the page to ensure the content script is loaded. Otherwise, you could end up with the following error:
Could not establish connection. Receiving end does not exist.
That said, I tried what you provided, and it worked as is. Since your output is in popup.js, the response is in the console output of the popup. You can view it by right-clicking on your browser action icon, and selecting 'Inspect popup'.

Creating a chrome extension which takes highlighted text on the page and inserts it into a textarea in popup.html

I have spent several hours searching the web for solutions. What I would like to do is take the highlighted text on a page and transfer it to a textarea in the popup.html of the chrome extension. I was wondering if someone could supply me with suggested source code of an extension that could do this.
This is the most pertinent thread I looked at that i thought would be most helpful - query is similar. Button in popup that get selected text - Chrome extension
I tried copying the code and running it as an extension, it does not obtain the highlighted text. Was wondering if anyone had any suggestions and how to solve this problem. Thank you very much.
  Well just like the answer to the question you linked, you will need to make use of Message Passing and Content Scripts. That code is over 2 years old though and makes use of depreciated methods such as onRequest and getSelected. A few simple modifications should be plenty to update it to the new api's.
Popup.html
<!DOCTYPE html>
<html>
<head>
<script src="jquery-1.8.3.min.js"></script>
<script src="popup.js"></script>
<style>
body { width: 300px; }
textarea { width: 250px; height: 100px;}
</style>
</head>
<body>
<textarea id="text"> </textarea>
<button id="paste">Paste Selection</button>
</body>
</html>
popup.js (so as to not have any inline code)
$(function(){
$('#paste').click(function(){pasteSelection();});
});
function pasteSelection() {
chrome.tabs.query({active:true, windowId: chrome.windows.WINDOW_ID_CURRENT},
function(tab) {
chrome.tabs.sendMessage(tab[0].id, {method: "getSelection"},
function(response){
var text = document.getElementById('text');
text.innerHTML = response.data;
});
});
}
selection.js
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
if (request.method == "getSelection")
sendResponse({data: window.getSelection().toString()});
else
sendResponse({}); // snub them.
});
manifest.json
{
"name": "Selected Text",
"version": "0.1",
"description": "Selected Text",
"manifest_version": 2,
"browser_action": {
"default_title": "Selected Text",
"default_icon": "online.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"<all_urls>"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["selection.js"],
"run_at": "document_start",
"all_frames": true
}
]
}
Here is a link to source files.
popup.js
chrome.tabs.executeScript( {
code: "window.getSelection().toString();"
}, function(selection) {
alert(selection[0]);
});
manifest.json
"permissions": [
"activeTab",
],
Have a look at this simple extension https://github.com/kelly-apollo/zdic
Reference to BeardFist answer below
Aslo, in popup.html you can use CDN version instead :
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
And adding this line in the the manifest file :
"content_security_policy": "script-src 'self' 'unsafe-eval' https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js; object-src 'self'",

simple option script for chrome

I'm trying to made a options site for my Chrome Extension. I want just that if checkbox 1 is enable script is runs etc...
I searched around but I found only outdated threads for this topic.
This is the manifest.json from my extension:
{
"name": "My First Extension",
"version": "1.0",
"manifest_version": 2,
"options_page": "options.html",
"description": "The first extension that I made.",
"content_scripts": [
{
"matches": ["http://*.example.com/*"],
"all_frames": true,
"js": ["script1.js", "script2.js"]
}
],
"browser_action": {
"default_icon": "icon.png"
},
"permissions": [
"tabs", "http://*.example.com/*"
]
}
The options.html:
<!DOCTYPE html>
<html>
<body class="uber-frame" i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize" style="font-family: 'Segoe UI', Tahoma, sans-serif; font-size: 125%">
<div id="main-content" align="center">
<div id="mainview">
<section id="scripts">
<h3>Scripts</h3>
<label>
<input type="checkbox" class=script1 >
<span>Enable Script 1</span>
</label>
<div>
<label>
<input type="checkbox" class=script2>
<span>Enable Script 2</span>
</label>
</div>
</section>
</div>
</div>
</body></html>
I don' t know how can i say the extension wich script shout be activ and which not.
I think I need a other script to get the values from the classes of the checkboxes and
probably I should set the content scripts to backgrond scripts.
Would be great if someone could help me.
Update: I've updated all codes for make both script run at the same time.
OK, at first you should save options data in localstorage, so you can access data from all pages. that makes your job easy.
For manipulating data I've created a javascript file named as global.js.
This file must be included at the start of options.html and content.js manually or in manifest.json.
global.js
var localStoragePrefix = "myextension_";
var LS_options = localStoragePrefix + "options";
var Options = {
Scripts : [
{
name : "script 1",
path : "script1.js",
enable : false
},
{
name : "script 2",
path : "script2.js",
enable : false
}
]
};
function DB_setValue(name, value, callback) {
var obj = {};
obj[name] = value;
console.log("ayarlar kaydedildi");
console.log(obj);
chrome.storage.local.set(obj, function() {
if(callback) callback();
});
}
function DB_load(callback) {
chrome.storage.local.get(LS_options, function(r) {
if ($.isEmptyObject(r[LS_options])) {
DB_setValue(LS_options, Options, callback);
} else {
Options = r[LS_options];
callback();
}
});
}
function DB_save(callback) {
DB_setValue(LS_options, Options, function() {
if(callback) callback();
});
}
function DB_clear(callback) {
chrome.storage.local.remove(LS_options, function() {
if(callback) callback();
});
}
And here is the updated options.html, you will see some js files included.
jquery.min.js (You don't need to use this, I just want to make it more useful)
global.js
options.js
options.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="globals.js"></script>
<script type="text/javascript" src="options.js"></script>
</head>
<body class="uber-frame" i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize" style="font-family: 'Segoe UI', Tahoma, sans-serif; font-size: 125%">
<div id="main-content" align="center">
<div id="mainview">
<section id="scripts">
<h3>Scripts</h3>
<div id="scriptTemplate" style="display:none">
<label>
<input type="checkbox" data-script = "script.js" />
<span>Enable Script</span>
</label>
</div>
</section>
</div>
</div>
</body>
</html>
Event handler attachments are in options.js file.
options.js
$(function(){
DB_load(startOptionsPage);
});
function startOptionsPage() {
$.each(Options.Scripts, function(index, script) {
var $scriptTemplate = $("#scriptTemplate").clone().show();
$scriptTemplate.find("label span").html("Enable " + script.name);
$scriptTemplate.find("label input[type='checkbox']")
.data("script", script.path)
.click(function() {
if ($(this).is(":checked")) {
script.enable = true;
} else {
script.enable = false;
}
DB_save(function() {
console.log("DB saved");
});
})
.prop('checked', script.enable);
$("#scripts").append($scriptTemplate);
});
}
And in content.js file we are getting Options and including the script if there is a selected one.
content.js
DB_load(function() {
$.each(Options.Scripts, function(index, script) {
if (script.enable) {
$.getScript(chrome.extension.getURL(script.path), function() {
console.log(script.name + " was loaded!");
});
}
});
});
script1.js
alert("Hello from script1");
script2.js
alert("Hello from script2");
For all of this you should update the manifest.json file.
including global.js into the content_script
permission for localstorage
including web_accessible_resources for script1.js and script2.js (Why?)
Finally here is the updated manifest.json
manifest.json
{
"name": "My First Extension",
"version": "1.0",
"manifest_version": 2,
"options_page": "options.html",
"description": "The first extension that I made.",
"content_scripts": [
{
"matches": ["http://stackoverflow.com/*"],
"all_frames": true,
"js": ["jquery.min.js","globals.js","content.js"],
"run_at": "document_end"
}
],
"browser_action": {
"default_icon": "icon.png"
},
"permissions": [
"tabs", "http://stackoverflow.com/*", "storage"
],
"web_accessible_resources": [
"script1.js",
"script2.js"
]
}
Your script folder should be like this,
How can I add more scripts?
There are only two changes you must make,
You will add script to main folder like the other script1.js and script2.js, and also you will add it to web_accessible_resources into the manifest.json.
You will also update "global.js", just add new script object to Options.Scripts array. like this.
var Options = {
Scripts : [
{
name : "script 1",
path : "script1.js",
enable : false
},
{
name : "script 2",
path : "script2.js",
enable : false
},
{
name : "script 3",
path : "script3.js",
enable : false
}
]
};
That's all. But don't forget to remove extension from chrome before you load the new updated one, because old options will stay there, and that won't work as you expect if don't do that.

Categories