I'm trying to get a simple Google Chrome extension working where a message/variable flows through each of the following steps ...
DOM content (from specific HTML tag)
Contentscript.js
Background.js
Popup.js
Popup.html
I've figured out how to send a message/variable to Background.js and from it in one direction (Background.js -> Popup.js or Background.js -> Contentscript.js), but can't get it through all three successfully (Contentscript.js -> Background.js -> Popup.js). Here are the files in my demo.
Dom
<h1 class="name">Joe Blow</h1>
Content.js
fromDOM = $('h1.name').text();
chrome.runtime.sendMessage({contentscript: "from: contentscript.js", title: fromDOM}, function(b) {
console.log('on: contentscript.js === ' + b.background);
});
Background.js
chrome.tabs.getSelected(null, function(tab) {
chrome.extension.onMessage.addListener(function(msg, sender, sendResponse) {
sendResponse({background: "from: background.js"});
console.log('on: background.js === ' + msg.title);
});
});
Popup.js
chrome.extension.sendMessage({pop: "from: popup.js"}, function(b){
console.log('on: popup.js === ' + b.background);
$('.output').text(b.background);
});
Popup.html
<html>
<head>
<script src="jquery.js"></script>
<script src="popup.js"></script>
</head>
<body>
<p class="output"></p>
</body>
</html>
Manifest.json
{
"name": "Hello World",
"version": "1.0",
"manifest_version": 2,
"description": "My first Chrome extension.",
"background" : {
"scripts": ["background.js"]
},
"permissions": [
"tabs"
],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["http://*/*"],
"js": ["jquery.js","contentscript.js"],
"run_at": "document_end"
}
]
}
I have a feeling I know what the trip-up is, but the documentation is severely lacking for manifest_version: 2 that its tough to decipher. A simple, reusable example would be very helpful in the learning process, as I'm sure this is a common issue.
Alright, changing a few things in your code should make it work like you want. Not all of the changes I am going to make are necessary, but this is just how I might do it.
Content Script
var fromDOM = $('h1.name').text();
chrome.runtime.sendMessage({method:'setTitle',title:fromDOM});
Background
var title;
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
if(message.method == 'setTitle')
title = message.title;
else if(message.method == 'getTitle')
sendResponse(title);
});
Popup.js
chrome.runtime.sendMessage({method:'getTitle'}, function(response){
$('.output').text(response);
});
Related
I got the extension to add "dev." to the current URL in a new tab which is working through a pop-up.
I'm trying to disable/remove the pop-up so that the code will work only when pressing the extension button instead.
popup.js:
document.addEventListener("DOMContentLoaded", function() {
console.log("Extension button clicked!");
var button = document.getElementById("change-url");
button.addEventListener("click", function() {
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
var url = new URL(tabs[0].url);
url.hostname = "dev." + url.hostname;
chrome.tabs.create({ url: url.toString() });
});
});
});
manifest.json:
{
"name": "My URL Changer",
"version": "1.0",
"manifest_version": 3,
"permissions": ["scripting"],
"host_permissions": ["<all_urls>"],
"action": {
"default_popup": "popup.html",
"default_title": "My URL Changer"
}
}
popup.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My URL Changer</title>
<script src="popup.js"></script>
</head>
<body>
<h1>My URL Changer</h1>
<button id="change-url">Change URL</button>
</body>
</html>
As woxxom mentioned, the chrome.action.onClicked API is a good fit for this.
The event does not fire if the extension has a popup, so you'll want to remove the default_popup key. However, you'll need to keep the empty action object. This tells Chrome to show an icon for your extension and is also required to make the API available.
With those changes in mind, your manifest would look like this:
{
"name": "My URL Changer",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"scripting"
],
"host_permissions": [
"<all_urls>"
],
"action": {}
}
You should also consider removing <all_urls> and replacing it with just the domains you want your extension to run on, since it's always best to request just the access you need. You could also remove this key entirely and use the activeTab permission instead, which gives your extension access to pages only when the action icon is clicked.
You'll then need to declare a service worker by adding the following to your manifest:
"background": {
"service_worker": "worker.js"
}
And in worker.js, you can copy your code from popup.js making sure to use the action API instead of DOMContentLoaded.
I am pretty new in the Chrome Extensions field.
I am trying to build an extension to visit some websites and collect information from their HTML.
I am having a hard time getting chrome.scripting.executeScript working properly.
Source Code
manifest.json
{
"name": "Scraper",
"description": "Simple Extension to Scrape Websites, and Push Them to ConnectionSphere for Data Enrichment",
"version": "2.0",
"permissions": ["storage", "webRequest", "scripting", "declarativeContent", "activeTab", "tabs", "downloads", "*://*/*", "http://connectionsphere.com:80/*", "http://connectionsphere.com/api1.0/emails/verify.json"],
"host_permissions": [ "https://www.amazon.com/*", "https://connectionsphere.com/*", "https://github.com/*" ],
"manifest_version": 3,
"icons": {
"48": "/48.png",
"128": "/128.png"
},
"action": {
"default_popup": "popup.html",
"default_icon": {
"48": "/48.png",
"128": "/128.png"
}
}
}
popup.html
<!DOCTYPE html>
<html>
<head>
<title>Scraper</title>
</head>
<body>
<div id="notify-wrapper">
<div id="notify-header">
<h1>Scraper!</h1>
</div>
<div id="notify-containers">
<div class="login-form">
<input type="button" id="start" name="start" value="Start" />
<p id="text" name="text"></p>
</div>
</div>
<script src="popup.js"></script>
</body>
</html>
popup.js
'use strict';
let text = document.getElementById('text');
function upload_page() {
alert('b');
document.body.innerHTML = 'hola';
return document.title;
}
start.onclick = function() {
let page_url_value = 'https://github.com/';
text.innerHTML = 'Scraping page...';
chrome.tabs.query({active: true, currentWindow: true}, async function(tabs) {
// get the tab id
var tab_id = tabs[0].id;
// go to the page
chrome.tabs.update({url: page_url_value});
// fired when tab is updated
chrome.tabs.onUpdated.addListener(function openPage(tabID, changeInfo) {
// tab has finished loading
if(tab_id == tabID && changeInfo.status === 'complete') {
// remove tab onUpdate event as it may get duplicated
chrome.tabs.onUpdated.removeListener(openPage);
// execute content script
alert('a');
chrome.scripting.executeScript(
{
target: {tabId: tab_id, allFrames: true},
func: upload_page
},
// Get the value returned by do_login.
// Reference: https://developer.chrome.com/docs/extensions/reference/scripting/#handling-results
(injectionResults) => {
for (const frameResult of injectionResults)
text.innerHTML = frameResult.result;
}
);
}
});
});
};
The Problem
When the user clicks on the "start" button of the popup, the extension visits a page and calls chrome.scripting.executeScript to run a function that works with the DOM of such a page. But such execution is not performed (thealert('a') happens, but the alert('b') is never executed).
If I refresh the page manually from the browser and click on the "start" button again, then the chrome.scripting.executeScript runs.
I researched for an answer into other posts here, but I didn't find anything.
The answers in this post didn't help me.
I wrote a small test-unit to show the problem I am facing.
It worked after I removed the extension and added it again. Thanks!
I'm trying to create a chrome extension, so I'm doing tutorials to learn and reading a bunch, but I'm struggling. I'm doing this tutorial. But long-term, from the extension I need users to be able to login to their account, then as they're browsing, send the url that they're at to their account.
popup.html
<!doctype html>
<html>
<head>
<title>Add a Snippet</title>
<script src="popup.js"></script>
<link rel="stylesheet" type="text/css" href="popup.css">
</head>
<body>
<h1>Add a Snippet</h1>
<form id="form">
<textarea id="code"></textarea>
<button type="submit" id="checkPage">Add Snippet</button>
</form>
</body>
</html>
popup.js
What I REALLY don't understand is that according to the console.log lines that I have in there and the error, it's loading the DOMContent, and it doesn't have any problem with finding the form by the id (let f = document.getElementById('form');). But it bombs when I try to attach an event listener?
document.addEventListener('DOMContentLoaded', function() {
console.log('the domcontentloaded');
let f = document.getElementById('form');
f.addEventListener('submit', function(e){
console.log('the form was submitted');
e.preventDefault();
})
}, false);
manifest.json
{
"name": "My Awesome Plugin",
"description": "This extension will be awesome",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html",
"default_title": "This is Awesome"
},
"background": {
"scripts": ["jquery-2.2.3.min.js", "background.js","popup.js"],
"persistent": false
},
"permissions": [
"activeTab",
"declarativeContent",
"https://ajax.googleapis.com/",
"storage",
"tabs",
"http://*/*",
"https://*/*"
],
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["login.js"]
}
],
"manifest_version": 2
}
login.js
console.log('login.js is ready to party');
When I load, I get this in the background inspector (or whatever it's called). So it's not finding the form.
So I looked at the elements, and I'm confused because it's not showing the form or the textarea. But when I click on the chrome extension icon, it's there.
1/Remove popup.js from "background/scripts" section of your manifest.
2/Add popup.js as a script reference in your popup.html file.
This way, popup.js will operate in the context of the popup.html DOM.
Thanks for taking the time to read this.
Here is the directory of my extension folder.
And here is the manifest code :
{
"manifest_version": 2,
"name": "Technobuffalo Stories",
"description": "Your Description about Extension goes here",
"version": "1.0",
"content_scripts": [ {
"js": [ "popup.js" ],
"matches": [ "http://feeds.feedburner.com/*" ]
} ],
"permissions": [ "http://feeds.feedburner.com/*" ],
"browser_action": {
"default_icon": "icon_16.jpeg",
"default_popup": "popup.html"
}
}
Here is popup.html :
<html>
<head>
<title>Technobuffalo Stories
</title>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script src="popup.js"></script>
</head>
<body>
<div id="feed" style="background-color:orange;height:500px;width:500px;" ></div>
</body>
</html>
and last of all here is popup.js :
google.load("feeds", "1");
function initialize() {
var feed = new google.feeds.Feed("http://feeds.feedburner.com/technobuffalo/rss?format=xml");
feed.load(function(result) {
if (!result.error) {
var container = document.getElementById("feed");
for (var i = 0; i < result.feed.entries.length; i++) {
var entry = result.feed.entries[i];
var div = document.createElement("div");
div.appendChild(document.createTextNode(entry.title));
container.appendChild(div);
}
}
});
}
google.setOnLoadCallback(initialize);
When I open the popup.html file as it is, the required result is displayed but when I load the Chrome extension, only the background color of the div can be seen. Is there any problem with the permissions that I have set or is it something else?
Thanks,
Yash.
You have to add the following line to manifest.json to be able to use resources from www.google.com:
"content_security_policy": "script-src 'self' https://www.google.com; object-src 'self'"
As Rob W already pointed out this is a security feature that has been introduced with manifest version 2.
I wants to create an extension where content script will send message to background page and then on browser action means clicking on extension icon will access that background page and get some data.I am using chrome Version 23.0.1271.64 m on windows8.
I am getting following error.
Port error: Could not establish connection. Receiving end does not exist.
I tried to solve the same. but people are using sendRequest which is not supported by chrome20+. i also found solution mentioned for chrome 20+. But not working. Please help.
Below is the file contents.
manifest.json
{
"name": "Test Extension",
"version": "1.0",
"manifest_version": 2,
"description": "A test extension.",
"background": "background.html",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["jquery.js","content.js"]
}
],
"permissions": ["tabs", "http://*/", "https://*/"],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}
background.html
<html>
<head>
<script src="background.js"></script>
</head>
<body>
<h1>Wy</h1>
</body>
</html>
background.js
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
// Chrome 20+
alert(request);
console.log('received in listener');
sendResponse({farewell: "goodbye"});
});
content.js
$(function(){
console.log('start-sending message');
chrome.extension.sendMessage({greeting: "hello"},function(response){alert(response);});
console.log('end-sending message');
});
popup.html
<!doctype html>
<html>
<head>
<title>Getting Started Extension's Popup</title>
</style>
<!-- JavaScript and HTML must be in separate files for security. -->
<script src="jquery.js"></script>
<script src="popup.js"></script>
</head>
<body>
</body>
</html>
popup.js
$(function(){
var str_html = "<tr><td width='60%'>S</td><td width='40%'>15</td></tr><tr><td width='60%'>M</td><td width='40%'>25</td></tr>";
$('#sizes_container').html(str_html);
var bkg = chrome.extension.getBackgroundPage();
console.log(bkg);
});
You're incorrectly mixing the deprecated "background_page" property with the new signature of "background". The correct way to use background pages is:
"background": {
"scripts": ["background.js"]
}
You can completely get rid off your background.html, because it serves no purpose (the content of your <body> is unused) (if you really need it, use "background": {"page": "background.html"}).
About sendRequest, it is indeed deprecated, but not removed (yet).
Regarding your popup page: You don't have any element with ID sizes_container, so you will obviously not see any output.