NOTE: THIS IS MY FIRST CHROME EXTENSION AND THIS IS AN EXERCISE TO GET FAMILIAR WITH DEVELOPING EXTENSIONS.
I am making a chrome extension that parses a page. When the user clicks on the extension button, payload.js executes parsing the page, and in the popup they can select an option that will decide how the parsed info will be outputted.
I want that after they select an option, a function inside of payload.js executes and evaluates the option and formats the parsed information accordingly. Finally, it sends a message back to popup.js containing the formatted parsed info and popup.js displays it in a textbox inside of the popup.
I can communicate from payload.js to popup.js just fine, but cant seem to do the reverse.
Here is my code and what I have tried
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('output').textContent = message;
});
document.addEventListener('DOMContentLoaded', function() {
var opt = document.getElementById('generate_type');
opt.addEventListener('click', function() {
chrome.runtime.sendMessage(opt.value); //contains value of selection
});
});
payload.js
console.log("executed");
var parsed_info = [];
parse_info();
function parse_info()
{
//CODE that parses page
}
function generate_html()
{
//CODE that generates html output in var html
chrome.runtime.sendMessage(html);
}
function generate_reddit()
{
//CODE that generates MARKUP for reddit in var reddit
chrome.runtime.sendMessage(reddit);
}
function eval_opt(opt)
{
//evaluate if we should call generate_reddit or generate_html based on opt
}
chrome.runtime.onMessage.addListener(function (message) {
alert(message);
eval_opt(opt);
});
manifest.json
{
"manifest_version": 2,
"name": "Hello World",
"description": "A simple page-scraping extension for Chrome",
"version": "1.0",
"author": "#Gabriel",
"background": {
"scripts": ["popup.js"],
"persistent": true
},
"permissions": [
"tabs",
"http://*/",
"https://*/"
],
"browser_action": {
"default_icon": "logo.png",
"default_popup": "popup.html"
}
}
Related
I am trying to get some data from current tab to my extension. It's working fine if I change it to popup style but I am looking for the same functionality to open it in a new tab on extension click. Can anybody guide on this how I can achieve this? Thanks in advance
manifest.json.js
{
"manifest_version": 2,
"name": "Hello World",
"description": "A simple page-scraping extension for Chrome",
"version": "1.0",
"author": "#thomasforth",
"background": {
"scripts": ["popup.js"],
"persistent": true
},
"permissions": [
"tabs",
"http://*/",
"*://*/",
"activeTab"
],
"browser_action": {
"default_icon": "logo.png"
}
}
payload.js
// send the page title as a chrome message
chrome.runtime.sendMessage(document.title);
console.log(document.title)
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.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.create({ url: "popup.html", selected: false })
chrome.runtime.onMessage.addListener(function (message) {
document.getElementById('pagetitle').innerHTML = message;
})
})
This the is error which I am getting
Use the id of the tab where onClicked was triggered and pass it to popup script using its URL:
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.create({
url: `popup.html?tabId=` + tab.id,
selected: false,
});
});
// popup.js
const tabId = +new URLSearchParams(location.search).get('tabId');
chrome.tabs.executeScript(tabId, {
file: 'payload.js'
});
I'm Writing a firefox addon that logs the current URL when pressing the addon icon at the toolbar.
When pressing the button, a background script will call the native app. That native app should write the current URL to a txt file. At this point, I'm able to write the text file when hitting the addon button. I'm able to write the contents of a variable created in background.js to a text file. But I can't pass the current URL to the background script.
The addon is based on the example addons from Mozilla:
https://github.com/mdn/webextensions-examples/tree/master/native-messaging
When using var url = window.location.href;I get the URL/Location of the loaded script.
Question: How can I pass the current URL to the background.js, so it will write the URL to a text file?
Below are the scripts:
Code background.js:
var url = window.location.href;
/*
On startup, connect to the "ping_pong" app.
*/
var port = browser.runtime.connectNative("ping_pong");
/*
Listen for messages from the app.
*/
port.onMessage.addListener((response) => {
console.log("Received: " + response);
});
/*
On a click on the browser action, send the app a message.
*/
browser.browserAction.onClicked.addListener(() => {
console.log("Console logger");
port.postMessage(url);
});
Code Manifest.json
{
"description": "ping_pong",
"manifest_version": 2,
"name": "Native messaging start Python",
"version": "1.0",
"icons": {
"48": "icons/message.svg"
},
"browser_specific_settings": {
"gecko": {
"id": "ping_pong#example.org",
"strict_min_version": "50.0"
}
},
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "icons/message.svg"
},
"permissions": ["nativeMessaging"]
I am building a extension which is essentially a plagiarism checker. So, you copy the text and then right click after that you have are directed to our website. Now, what I want to do is that I want to send the selected text from my copied website to my website input page and then I want to click the submit button.
To do that I need to execute these two lines.
document.getElementById("mycontent").value = "selected text";
document.getElementById("checkButton").click();
But the selected text remains in just background.js and never shows up in content script that's why my extension is not working. So, i want to know how can I fix this or is there any other way I can input my text and click the button.
Background.js
var contextsList = ["selection"];
for(i = 0;i<contextsList.length; i++){
var context = contextsList[i];
var titleX = " Check Plagiarism of Selected Text";
chrome.contextMenus.create({title: titleX, contexts:[context], onclick: clickHandler, id: context });
}
function clickHandler(data, tab) {
switch(data.menuItemId.id){
case 'selection' :
ex = encodeURIComponent(data.selectionText);
var config = {content: ex};
chrome.tabs.executeScript(tab.id, {
code: 'var config = ' + JSON.stringify(config)
}, function() {
chrome.tabs.executeScript(tab.id, {file: 'contentScript.js'});
});
// background script
chrome.runtime.onMessage.addListener((request,sender,sendMessage)=>{
if(request.type==="Getcontent"){
const content=// set your content
sendMessage({msg:"cont",content:content})
}
})
chrome.tabs.create({url: "https://greatseotools.net/plagiarism-checker"});
break;
}
}
ContentScript.js
//Content script
chrome.runtime.onMessage.addListener((request,sender,sendMessage)=>{
if(request==='content'){
console.log("content",request.content)
}
})
//wrap this in an event
chrome.runtime.sendMessage({
type:'Getcontent'
})
manifest.json
{
"background": {
"scripts": [ "background.js" ]
},
"browser_action": {
"default_icon": "icons/19.png",
"default_popup": "popup.html"
},
"content_scripts": [ {
"all_frames": true,
"js": ["contentScript.js" ],
"matches": [ "*://*.greatseotools.net/*" ],
"run_at": "document_end"
} ],
"description": "Check Plagiarism by just selecting text..",
"homepage_url": "https://www.prepostseo.com/plagiarism-checker",
"icons": {
"128": "icons/128.png",
"16": "icons/16.png",
"48": "icons/48.png"
},
"manifest_version": 2,
"name": "Plagiarism Checker for Chrome",
"permissions": [ "activeTab","*://*/*", "https://ajax.googleapis.com/", "contextMenus" ],
"update_url": "https://clients2.google.com/service/update2/crx",
"version": "1.0"
}
Website on which I have to input text and click the button.
https://greatseotools.net/plagiarism-checker
In this line chrome.tabs.executeScript({file: 'contentScript.js'}) you didn't pass your selectionText to the content script you can acheive that in many ways here are two of my suggestions :
background script
1. Using the chrome.tabs.executeScript api
ex = encodeURIComponent(data.selectionText);
var config = {content: ex};
chrome.tabs.executeScript(tab.id, {
code: 'var config = ' + JSON.stringify(config)
}, function() {
chrome.tabs.executeScript(tab.id, {file: 'content.js'});
});
content script
and in your content script you should be able to retrieve ex :
alert('mycontent:' + config);
2. Using the chrome messages api between backgound and content script
background script
// background script
chrome.runtime.onMessage.addListener((request,sender,sendMessage)=>{
if(request.type==="Getcontent"){
const content=// set your content
sendMessage({msg:"cont",content:content})
}
})
Content script
//Content script
chrome.runtime.onMessage.addListener((request,sender,sendMessage)=>{
if(request==='content'){
console.log("content",request.content)
}
})
//wrap this in an event
chrome.runtime.sendMessage({
type:'Getcontent'
})
3.use chrome storage
background script
chrome.storage.sync.set({'content':ex})
content script
chrome.storage.sync.get(['content'], function(res) {
console.log('Value currently is ' + res.content);
});
manifest
"permissions": ["storage"]
I can send a message from a popup to a background via:
background.js
chrome.runtime.onMessage.addListener(
function(request) {
alert(request.data.subject);
}
);
popup.js
chrome.runtime.sendMessage({
msg: "something_completed",
data: {
subject: "Loading...",
content: "Just completed!"
}
});
The alert loads fine BUT I need to do the opposite. I would like the background to send an api call when a page is loaded and send the results of that api call to the popup.js so that it can make changes to the DOM. When I switch the above code, no alert is shown. My manifest.json:
{
"name": "example",
"version": "0.0.1",
"description": "Chrome Extension's message passing example",
"browser_action": {
"default_icon": "images/get_started32.png",
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"]
},
"content_scripts":[{
"matches":["http://*/*", "https://*/*"],
"js":["popup.js"]
}],
"permissions": [
"background","webRequest","webRequestBlocking","webNavigation","tabs","notifications"
],
"manifest_version": 2
}
Technically, chrome.runtime.sendMessage will send a message to all extension pages including the popup, however this is not how the communication should be organized.
Note, the popup is running only when shown so if it's hidden it can't receive messages.
Assuming the popup is already visible, the solution is usually to simply wait for the background script's response using return true.
popup.js sends a message:
chrome.runtime.sendMessage({foo: 'bar'}, response => {
// use the response here
});
background script:
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.foo === 'bar') {
doSomeProcessing(msg).then(sendResponse);
return true;
}
});
function doSomeProcessing(msg) {
return new Promise(resolve => {
// do something async
resolve({data: 123});
});
}
I am creating a chrome extension that I want to be able to enable/disable. I have successfully made a popup that does just that. The trouble is, if I reload the extension (or if the user downloads it initially) my content scripts default to being off. I could just inject the content script in the manifest.json but that results in the content script being injected for any new tab--which I do not want. The behavior should be that if you download/reload the extension, it is on by default, but then you can enable it/disable it and that applies to every new tab. I have tried to put an initialization in background.js but that does not get called at startup apparently.
manifest.json
{
"manifest_version": 2,
"name": "Rotten Tomatoes Search",
"description": "This extension searches rotten tomatoes with highlighted text",
"version": "1.0",
"browser_action": {
"default_icon": "./icons/icon_on.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"<all_urls>",
"background"
],
"background": {
"scripts": ["background.js"],
"persistent": true
},
"content_scripts": [{
"js": ["jquery-1.12.3.min.js"],
"matches": ["<all_urls>"]
}]
}
background.js
var isExtensionOn = true;
chrome.tabs.executeScript({code: "console.log('backgournd hit...')"});
turnItOn();
chrome.extension.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.cmd == "setOnOffState") {
isExtensionOn = request.data.value;
}
if (request.cmd == "getOnOffState") {
sendResponse(isExtensionOn);
}
});
function turnItOn() {
chrome.browserAction.setIcon({path: "./icons/icon_on.png"});
chrome.tabs.executeScript({file:"openTooltipMenu.js"});
//$('#toggle').text('disable');
}
popup.js
document.addEventListener('DOMContentLoaded', function() {
// show different text depending on on/off state (for icon, handled by having default icon)
chrome.extension.sendMessage({ cmd: "getOnOffState" }, function(currentState){
if (currentState) $('#toggle').text('disable');
else $('#toggle').text('enable');
});
// allow user to toggle state of extension
var toggle = document.getElementById('toggle')
toggle.addEventListener('click', function() {
//chrome.tabs.executeScript({code: "console.log('toggled...')"});
chrome.extension.sendMessage({ cmd: "getOnOffState" }, function(currentState){
var newState = !currentState;
// toggle to the new state in background
chrome.extension.sendMessage({ cmd: "setOnOffState", data: { value: newState } }, function(){
// after toggling, do stuff based on new state
if (newState) turnOn();
else turnOff();
});
});
})
});
function turnOn() {
chrome.browserAction.setIcon({path: "./icons/icon_on.png"});
chrome.tabs.executeScript({file:"openTooltipMenu.js"});
$('#toggle').text('disable');
}
function turnOff() {
chrome.browserAction.setIcon({path: "./icons/icon_off.png"});
chrome.tabs.executeScript({code: "$('body').off();"});
$('#toggle').text('enable');
}
popup.html
<some code>
<script src="./jquery-1.12.3.min.js"></script>
<script src="./popup.js"></script><style type="text/css"></style>
</head>
<body>
<div class="popupMenu" style="list-style-type:none">
<div class="header">Rotten Tomatoes Search</div>
<hr>
<div class="menuEntry" id="toggle"></div>
</div>
</body>
</html>
I have figured out the issue. My architectural approach was wrong. One should inject the content_script globally but check with the script whether or not something should be done. To be clearer, in the script get the status from the background page and do something based on that. Previously, I was only injecting the script once the popup was loaded or once initially when the background was initialized. Additionally, one must loop through all tabs in all windows to update the state in all tabs (if that's what one wants).