Content script to update specific tab popup - javascript

Let's have an imaginary extension which takes everything after '/' from url, which is done in content script. Also updates badge and change text in popup.html, which different for every tab (different tab, diff. url)
contentscript.js:
var str = document.URL;
var n = str.lastIndexOf('/');
var result = str.substring(n + 1);
chrome.runtime.sendMessage({message: "result", url: result});
eventpage.js:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.message == "result") {
chrome.browserAction.setBadgeText({tabId:sender.tab.id, "text" : "1"});
links = request.url;
}
popup.js:
$(function () {
var bg = chrome.extension.getBackgroundPage();
$('#total').text(bg.links);
});
popup.html
<!DOCTYPE html>
<html>
<head>
<title>Plugin</title>
<script type="text/javascript" src="jquery-1.11.3.js"></script>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
<div id='total'>Nothing</div>
</body>
</html>
This works only on new loaded tabs, not when I click between them. For example, when I load first page "webpage.com/first" my popup's got 'first'. When I load second page(on different tab) "webpage.com/second" popup is 'second'. After that I click on the first page (on the first tab) and my popup is 'second' which I meant to be 'first'.
//badge in my project is counter, I wrote it here only for getting an idea

If you only need to get the tab url you can do it without content scripts just by using chrome.tabs.query in popup.js:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
$('#total').text(tabs[0].url.replace(/^.+?\/([^\/]*)$/, '$1'));
});
Otherwise use chrome.tabs.executeScript in popup.js:
chrome.tabs.executeScript({
code: "document.querySelector('p.something').textContent"
}, function(results) {
$('#something').text(results[0]);
});
Both methods require "activeTab" permission in manifest.json.

Related

Execute content script within new tab - chrome extentions

I'm trying to create a chrome extension that scrapes some content from a particular website and then opens a new tab and does stuff with the scraped data.
Below is a test I made to see how I might do this. Unfortunately I can't seem to execute the newtab-script.js file as I get this error:
Unchecked runtime.lastError while running tabs.executeScript: Cannot
access contents of url
"chrome-extension://FAKEIDgfdsgfdsgfdsgdsgfdsgFAKEID/newpage.html".
Extension manifest must request permission to access this host.
at Object.callback (chrome-extension://FAKEIDgfdsgfdsgfdsgdsgfdsgFAKEID/background.js:43:25)
websitescrape.js
var button = document.createElement("button");
button.classList.add("web-scrape");
button.innerHTML = "scrape web";
document.querySelector('.placeIWantToPutButton').appendChild(button);
button.addEventListener('click', scrapeData);
function scrapeData(){
//do website scraping stuff here...
var fakedata = [{test:"data1"},{test:"data2"}];
//send scraped data to background.js
chrome.runtime.sendMessage({setdata: fakedata}, function(tab){
//callback
});
}
background.js
var dataTempStorage = [];
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.setdata) {
dataTempStorage = request.setdata;
chrome.tabs.create({
'url': chrome.extension.getURL('newpage.html')
}, function(tab) {
chrome.tabs.executeScript(tab.id, {
file:chrome.extension.getURL("newtab-script.js")});
});
}
if (request == "getdata") {
sendResponse({data: dataTempStorage});
}
});
newtab-script.js
chrome.runtime.sendMessage("getdata", function (response) {
doStuff(response.data);
});
function doStuff(){
//Do staff on newpage.html with data scraped from original page
}
newpage.html
// page ready to be filled with awesome content!
Cause: content scripts can't be injected into extension pages with chrome-extension:// scheme.
Solution: since you have control over that html page just reference the content script file explicitly.
newpage.html:
<script src="newtab-script.js"></script>
</body>
</html>
And don't use executeScript.

Chrome extension - call function defined on tab (Reference error)

I'm opening a tab and trying to call a function defined in it but i always get a "reference error". I send a message to the script after the script is loaded asking to run "test1" function located on the tab code.
Here is my code:
Extention code
chrome.tabs.executeScript(tab.id, {file: "script.js", runAt: "document_end"}, function(array){
//send message executeTest to the created tab
chrome.tabs.sendMessage(tab.id, {msg: "executeTest"});
});
script.js
url = document.URL;
window.addEventListener("load", doStuff, true);
function doStuff(){
//listen for messages coming from extension
chrome.runtime.onMessage.addListener(
function(message, sender) {
var msg = message.msg;
var url = message.url;
switch(msg){
case "executeTest":
test1();
break;
}
}
);
}
Tab HTML
<head>
<title>Test</title>
</head>
<body>
<script src="app.js"></script>
</body>
</html>
Tab Javascript
function test1(){
console.log("test1 is running!");
}
I receive the message on the script but it's not possible to execute "test1()".
What am i doing wrong ?
A couple of unrelated issues here.
chrome.tabs.sendMessage(tab.id, {msg: executeTest});
executeTest is not a string, it's an (undefined) identifier. That's what throwing the error.
Correct way (ninja'd by user2570380) is to write
chrome.tabs.sendMessage(tab.id, {msg: "executeTest"});
The other problem is that you will not be able to call test1(), because content scripts live in isolated context.
To bypass it, you either need to employ messaging between the webpage and your extension, use externally_connectable, or inject some of your code into the page to trigger what you need.
Considering that you do not control the webpage, you need to inject code in the page's context. Example:
control.js
window.addEventListener("message", function(event) {
// We only accept messages from ourselves
if (event.source != window)
return;
if (event.data.source && (event.data.source == "MyExtension")) {
switch(event.data.command){
case "test1":
test1();
break;
}
}
}, false);
script.js
// Initialization
var s = document.createElement('script');
// TODO: add "control.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('control.js');
s.onload = function() {
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
// Sending a command (make sure script initialized listener first)
window.postMessage({ source: "MyExtension", command: "test1" }, "*");
chrome.tabs.sendMessage(tab.id, {msg: "executeTest"});
Quotes.

chrome extension, pass data from content to background

I've created a chrome extension that consists of manifest.json, content.js and background.js. in content.js, I'm extracting the current tab's URL and in background.js, I'm opening a new tab. what I want to do, which doesn't work is to pass the URL from content and append it to the URL that I'm calling in background.
content.js:
chrome.extension.onMessage.addListener(function(request, sender, sendResponse)
{
if(request.greeting=="gimmieyodatas")
{
var output ="URL=";
//check for the character '?' for any parameters in the URL
var paramIndex = document.URL.indexOf("?");
//if found, eliminate the parameters in the URL
if (paramIndex > -1)
{
output += document.URL.substring(0, paramIndex);
};
sendResponse({data: output});
}
else{
sendResponse({});
}
});
background.js:
var output2;
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendMessage(tab.id, {greeting:"gimmieyodatas"}, function(response) {
output2 = response.data;
});
});
chrome.browserAction.onClicked.addListener(function() {
chrome.tabs.create({url: "http://www.google.com?" + output2}, function(tab) {
chrome.tabs.executeScript(tab.id, {file: "content.js"}, function() {
sendMessage();
});
});
});
When I run the extension from an open tab, it opens google on a new tab, but it doesn't append the current tab's URL in google URL, meaning the 'output' data does not get passed to the background.js. What am I doing wrong?
The problem is that you are not telling the background page to send a message when a new tab is opened. The call to chrome.tabs.getSelected only happens once when the extension is first run -- it does not happen every time a new tab is opened.
You're on the right track by using the background page as an intermediary between the two content pages, but I suggest a different approach:
Load the content script every time a new tab is opened, via the manifest file:
"content_scripts": [
{
"matches" : [
"<all_urls>"
],
"js" : [
"content.js"
]
}
],
Use a much simpler content script that just sends a message to the background with the current URL page as soon as it loads:
(content.js)
var paramIndex = document.URL.indexOf('?');
if (paramIndex > -1) {
chrome.runtime.sendMessage({output2: 'URL=' + document.URL.substring(0, paramIndex)});
}
When the background page receives the message it saves the URL to a global variable:
(background.js)
var output2;
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
output2 = request.output2;
});
You can then load that URL when the action button is clicked:
(background.js)
chrome.browserAction.onClicked.addListener(function() {
chrome.tabs.create({url: "http://www.google.com?" + output2});
});

Opening a new tab on Google Chrome Extension

This is my background.html file, It works fine when opening in current tab but I want it to open in new tab, what am I doing wrong?
<html>
<head>
<script>
// Called when the user clicks on the browser action.
chrome.browserAction.onClicked.addListener(function(tab) {
var action_url = "javascript:location.href='http://www.reddit.com/submit?url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)";
chrome.tabs.create(tab.id, {url: action_url}, function(tab));
});
</script>
</head>
</html>
You should read the chrome.tabs.create documentation again. You are passing it invald parameters. You are also using location which is from the background.html document not the webpage document the code is expecting instead of the tab parameter passed to the chrome.browserAction.onClicked listener.
<html>
<head>
<script>
// Called when the user clicks on the browser action.
chrome.browserAction.onClicked.addListener(function(tab) {
var action_url = "http://www.reddit.com/submit?url=" + encodeURIComponent(tab.href) + '&title=' + encodeURIComponent(tab.title);
chrome.tabs.create({ url: action_url });
});
</script>
</head>
</html>
You can try this
<html>
...
<body>
<script>
function createTab() {
chrome.tabs.create({url: "http://www.stackoverflow.com"});
}
</script>
Create a new tab
</body>
</html>
<html>
<head>
<script type="text/javascript">
window.master = ({
newtab: function(url, callback) {
callback = callback === true ? (function() { this.close(); }) : callback;
try {
chrome.tabs.create({
url: url
});
if(typeof callback === "function") { callback.call(this, url); }
} catch(e) {
/* Catch errors due to possible permission issues. */
}
},
link: function(event, close) {
event = event ? event : window.event;
event.preventDefault();
this.newtab(event.href, close);
},
close: function() { window.self.close(); }
});
</script>
</head>
<body>
<!-- Usage is simple:
HTML:
<a href="http://example.com/" onclick="master.link(event)" />
JavaScript:
master.newtab("http://example.com/", true);
-->
</body>
</html>
If you insist on using a popup and want it to close as soon as it is opened, then use what is above. Simply add the link string and a true boolean to the master.newtab function to have it open the new tab and then close the popup.
If you change your mind about closing the popup, you can replace the true boolean with a function to execute if the new tab was created without any errors. You can also use the master.link function for calling the master.newtab function from an anchor element.
The best thing about using Chrome Extensions is you never have to worry about support issues! :D

Chrome Extension Message Passing - Code included

I have a contentscript called file.js that creates variable "found". I want to send the values of varibale "found" to a textbox in popup.html
In file.js (I know varible found is working, tested using an alert).
chrome.extension.sendRequest({foundlinks: found}, function(response) {
console.log(response);
});
In Popup.html:
function pulllinks(){
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
document.getElementById("box").value = request.foundlinks;
sendResponse({});
});
And on the form in popup.html:
<input type = "button" onclick="pulllinks();" name = "box" id="box" value = "Grab Links From Page" />
However, its not doing anything. Any ideas?
Thanks!
You need to be sending requests in the opposite direction - from popup to content script:
popup.html:
function pulllinks(){
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {cmd: "findLinks"}, function(response) {
document.getElementById("box").value = response.foundlinks;
});
});
}
file.js:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if(request.cmd == "findLinks") {
//calculate "found" value and send it back
sendResponse({foundlinks: found});
}
});
First of all, your listener for onRequest should exist from the start, so move it outside of the pulllinks function. Secondly, how are you making sure that your sendRequest is being fired while the popup is open?

Categories