I am trying to accomplish this login process.
In the extension, there is popup.html, popup.js, background.js and content.js as usual.
In popup.html, there are username and password inputfields and login button.
My vision is: I will catch both inputs in popup.js and send them to background.js and from there, i will send them to django backend. django backend returns logged-in token.
firstly, is this possible way?
my first step is not working: i cannot send message from popup.js to background.js. no error in console, also no success. this is my code:
popup.js
handleLoginClick_: function(){
var email = this.email.value;
var pwd = this.pwd.value;
chrome.tabs.sendMessage(tab.id, {asking: "login"}, function(response) {
sendToDjango(response.answer);
});
}
background.js
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
if (request.asking === "login"){
console.log('got msg from popup.js');
return;
}
});
what am I doing wrong?
this is the manifest.json:
{
"name" : "myBIZMark",
"version" : "1.1",
"description" : "collect competing company's keywords",
"permissions": [
"tabs", "contextMenus", "<all_urls>", "storage"
],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"background": {
"persistent": false,
"scripts": ["jquery111.js","background.js"]
},
"manifest_version": 2,
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["jquery111.js", "contentscript.js","popup.js"]
}
]
}
Your message in popup.js is targeted toward the content scripts, not the background page. You need to use chrome.runtime, not chrome.tabs.
Replace:
chrome.tabs.sendMessage(tab.id, {asking: "login"}, function(response) {
sendToDjango(response.answer);
});
With:
chrome.runtime.sendMessage({asking: "login"}, function(response) {
sendToDjango(response.answer);
});
In summary:
chrome.tabs.sendMessage = background -> content
chrome.runtime.sendMessage = content -> background
Related
I want to extract the HTML of a webpage so that I can analyze it and send a notification to my chrome extension. Sort of like how an adblocker does it when analyzing a web page for ads and then tell the extension how many possible ads there are.
I am trying to use the document object in content-scripts to get the HTML, however, I always seem to get the HTML of my popup file instead. Can anybody help?
content-script.js
chrome.tabs.onActivated.addListener(function(activeInfo) {
chrome.tabs.get(activeInfo.tabId, function(tab) {
console.log("[content.js] onActivated");
chrome.tabs.sendMessage(
activeInfo.tabId,
{
content: document.all[0].innerText,
type: "from_content_script",
url: tab.url
},
{},
function(response) {
console.log("[content.js]" + window.document.all[0].innerText);
}
);
});
});
chrome.tabs.onUpdated.addListener((tabId, change, tab) => {
if (tab.active && change.url) {
console.log("[content.js] onUpdated");
chrome.tabs.sendMessage(
tabId,
{
content: document.all[0].innerText,
type: "from_content_script",
url: change.url
},
{},
function(response) {
console.log("[content.js]" + window.document.all[0].innerText);
}
);
}
});
background.js
let messageObj = {};
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
// Arbitrary string allowing the background to distinguish
// message types. You might also be able to determine this
// from the `sender`.
if (message.type === "from_content_script") {
messageObj = message;
} else if (message.type === "from_popup") {
sendResponse(messageObj);
}
});
manifest.json
{
"short_name": "Extension",
"version": "1.0.0",
"manifest_version": 3,
"name": "My Extension",
"description": "My Extension Description",
"permissions": ["identity", "activeTab", "tabs"],
"icons": {
"16": "logo-16.png",
"48": "logo-48.png",
"128": "logo-128.png"
},
"action": {
"default_icon": "ogo_alt-16.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["./static/js/content-script.js"],
"run_at": "document_end"
}
],
"background": {
"service_worker": "./static/js/background.js"
}
}
Your current content script is nonfunctional because content scripts cannot access chrome.tabs API. If it kinda worked for you, the only explanation is that you loaded it in the popup, which is wrong because the popup is not a web page, it's a separate page with a chrome-extension:// URL.
For your current goal, there's no need for the background script at all because you can simply send a message from the popup to the content script directly to get the data. Since you're showing the info on demand there's also no need to run the content scripts all the time in all the sites i.e. you can remove content_scripts from manifest.json and inject the code on demand from the popup.
TL;DR. Remove content_scripts and background from manifest.json, remove background.js and content-script.js files.
manifest.json:
"permissions": ["activeTab", "scripting"],
popup.html:
<body>
your UI
<script src=popup.js></script>
</body>
popup.js:
(async () => {
const [tab] = await chrome.tabs.query({active: true, currentWindow: true});
let result;
try {
[{result}] = await chrome.scripting.executeScript({
target: {tabId: tab.id},
func: () => document.documentElement.innerText,
});
} catch (e) {
document.body.textContent = 'Cannot access page';
return;
}
// process the result
document.body.textContent = result;
})();
If you want to to analyze the page automatically and display some number on the icon then you will need the background script and possibly content_scripts in manifest.json, but that's a different task.
I am writing my First Chrome Plugin and I just want to get some text present on the current webpage and show it as a alert when i click the Extension. Lets say I am using any any webpage on www.google.com after some Search query, Google shows something like "About 1,21,00,00,000 results (0.39 seconds) " . I want to show this Text as an alert when i execute my plugin. This is what i am doing.
here is the manifest.json that i am using
{
"manifest_version": 2,
"name": "Getting started example",
"description": "This extension shows a Google Image search result for the current page",
"version": "1.0",
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["*://*.google.com/*"],
"js": ["content.js"]
}],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
]
}
Here is my popup.js
document.addEventListener('DOMContentLoaded', function() {
document.getElementById("checkPage").addEventListener("click", handler);
});`
function handler() {
var a = document.getElementById("resultStats");
alert(a.innerText); // or alert(a.innerHTML);
}
Here is my content.js
// Listen for messages
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
// If the received message has the expected format...
if (msg.text === 'report_back') {
// Call the specified callback, passing
// the web-page's DOM content as argument
sendResponse(document.all[0].outerHTML);
}
});
Here is my background.js
var urlRegex = /^https?:\/\/(?:[^./?#]+\.)?google\.com/;
// A function to use as callback
function doStuffWithDom(domContent) {
console.log('I received the following DOM content:\n' + domContent);
}
// When the browser-action button is clicked...
chrome.browserAction.onClicked.addListener(function (tab) {
// ...check the URL of the active tab against our pattern and...
if (urlRegex.test(tab.url)) {
// ...if it matches, send a message specifying a callback too
chrome.tabs.sendMessage(tab.id, {text: 'report_back'}, doStuffWithDom);
}
});
1) run content scrip after document ready ** check "run_at"
"content_scripts": [{
"run_at": "document_idle",
"matches"["*://*.google.com/*"],
"js": ["content.js"]
}],
2) on click of extension make another js to run( popup js). The popup js has access to the ( open page document)
// A function to use as callback
function doStuffWithDom() {
//console.log('I received the following DOM content:\n' + domContent);
//get tabID when browser action clicked # tabId = tab.id
chrome.tabs.executeScript(tabId, {file: "js/popup.js"});
}
3) In popup JS simple you can set alert
var a = document.getElementById("resultStats");
alert(a.innerText); // or alert(a.innerHTML);
Just remove "default_popup" part in manifest.json, as you have listened to chrome.browserAction.onClicked event in background page. They can't live at the same time.
EDIT -- added background script
I need to get a message from the popup script in my chrome extension to the content script. It should send the message when a button inside the popup is clicked.
After reading more, it seems like you can't communicate directly between the popup script and the content script.
I think I need to go:
popup.js > background.js > script.js
I've tried doing this, but I can't seem to get it to work. There are a couple different ways to implement message passing, but not much documentation for this use case.
here's the code (it doesn't seem to pass a message at all right now):
popup.js
/* when something is saved in local storage... */
chrome.storage.sync.set({'myFilter': filter}, function(){
/* send message to background script */
chrome.runtime.sendMessage({greeting: "hello from popup"}, function(response) {
console.log(response.farewell);
});
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "new filter saved"}, function(response) {
console.log(response.farewell);
});
});
});
background.js
/*listen for message from popup, send message to content script */
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a background script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello from popup") {
alert("message passed to background script");
console.log("message passed to background script");
/* send message to content script */
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "popup sent message"}, function(response) {
console.log(response.farewell);
});
});
return true;
sendResponse({farewell: "goodbye"});
}
return false;
});
script.js
/* get notice from background script*/
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 == "popup sent message") {
alert("message passed to content script");
console.log("message passed to content script");
location.reload();
walkWithFilter();
return true;
sendResponse({farewell: "goodbye"});
}
return false;
});
manifest.json
{
"manifest_version": 2,
"name": "filter",
"description": "This extension allows twitter users to filter content in their feed",
"version": "1.0",
"content_scripts":
[
{
"matches": ["*://*/*"],
"js": ["bower_components/jquery/dist/jquery.min.js", "script.js"],
"run_at": "document_end"
}
],
"permissions": [
"tabs",
"storage",
"contextMenus",
"background",
"https://twitter.com/",
"http://twitter.com/"
],
"icons": {
"16": "fa-moon.png"
},
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_title": "filter",
"default_icon": "fa-moon.png",
"default_popup": "popup.html"
}
}
right now this is doing nothing -- no alert message pops up and nothing is printed to the console when I pressed the button with the click event.
This is how it should run:
1) User enters input into popup window 'save-button' and clicks save
2) onclick of the save-button, input is saved in localstorage (this part works)
3) onclick of the save-button, message is sent from popup.js to script.js telling
it that new input has been saved to localstorage
4) Script.js receives message and prints to the regular console "message passed"
The reason I'm doing this is that I need to make the content script do some logic when it receives notice that new input has been saved in local storage. Does this seem reasonable?
You can actually go directly from
popup.js > script.js since the background page's messaging api is accessible to the popup too.
manifest.json
{
"manifest_version": 2,
"name": "filter",
"description": "This extension allows twitter users to filter content in their feed",
"version": "1.0",
"content_scripts":
[
{
"matches": ["<all_urls>"],
"js": ["script.js"],
"run_at": "document_end"
}
],
"permissions": [
"tabs",
"storage",
"contextMenus",
"background",
"https://twitter.com/",
"http://twitter.com/"
],
"icons": {
},
"background": {
"scripts": []
},
"browser_action": {
"default_title": "filter",
"default_popup": "popup.html"
}
}
popup.html
<button id="save-button">save-button</button>
<script src="/popup.js" type='text/javascript'></script>
popup.js
document.getElementById("save-button").onclick = function(){
console.log("clicked button");
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if(tabs.length == 0){
console.log("could not send mesage to current tab");
}else{
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello, how are you content script?"}, function(response) {
console.log("received message from content script: "+response.farewell);
});
}
});
}
script.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
console.log("received message from popup: "+request.greeting);
sendResponse({farewell: "I'm good, thank you popup!"});
});
A very important permission for message passing i.e. tabs which is used to interact with the browser's tab system, is missing in your permission list.
Replace permissions array in manifest.json with
"permissions": [
"tabs",
"storage",
"contextMenus",
"background",
"https://twitter.com/",
"http://twitter.com/"
],
First off, I'm new to making chrome extensions, so don't assume I know a whole lot. For the extension I'm making the user needs to be able to right click on a link, select a context menu item, and the extension needs to get sent the final url of that link.
Specifically amazon affiliate links. So for example the following:
http://amzn.to/1VO7dlp
Would need to get converted to:
http://www.amazon.com/gp/product/0470281731/ref=as_li_ss_tl?ie=UTF8&fpl=fresh&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=desktop-1&pf_rd_r=0WRZW1V7VVDJWS54WCM4&..... blah blah blah
I've looked around and I can't find any answers. Am I SOL?
The code I have so far is pretty basic:
//background.js
chrome.runtime.onInstalled.addListener(function() {
chrome.contextMenus.create({
title: 'Add this Link',
id: 'linkContext',
contexts: ['link'],
});
});
chrome.contextMenus.onClicked.addListener(function(data, tab) {
if (data.menuItemId === "linkContext") {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id,
{
linkUrl: data.linkUrl,
},
function(response) {
alert(response.host);
});
});
}
});
chrome.runtime.onMessage.addListener(
//content_script.js
function(request, sender, sendResponse) {
if (request.linkUrl){
pathArray = request.linkUrl.split( '/' );
protocol = pathArray[0];
host = pathArray[2];
url = protocol + '//' + host;
sendResponse({host: host});
}
});
//manifest.json
{
"name": "jQuery DOM",
"manifest_version": 2,
"version": "1.0",
"description": "Manipulate the DOM when the page is done loading",
"browser_action": {
"name": "Manipulate DOM",
"icons": ["icon.png"],
"default_icon": "icon.png"
},
"background": {
"scripts": ["background.js"],
"persistent": false
},
"permissions": [
"contextMenus"
],
"content_scripts": [ {
"js": [ "jquery.min.js", "content_script.js" ],
"matches": [ "http://*/*", "https://*/*"]
}],
"web_accessible_resources":[
"menu.html",
"menu.css"
]
}
Like I said I'm pretty new to this, so I'm unsure of how to proceed. I'd like to do some parsing of the "final url" so I can present information about it to the user. I.E. the Affiliate ID. But for that I can't use the shortened link from above.
As Redirects is a response from the server back to you, you can read the header-field and see what url your initial url redirects to.
In this case, I just tested to open a new tab in Chrome, and opened the Network tab and navigated to your initial url. Then I saw two separate redirects (http status code 301), before the the full url of the resulting page was shown.
This you can do in code as well, to be able to get to the final url. :)
I'm trying to develop a google chrome extension that scrape out specific data from the page once the page is finished loading. I'm trying to achieve it by executing a javascript file by setting file : 'js/scrape.js' and runAt: 'document_idle'.
However, setting selected : false does work but selected : true doesn't.
index.js:
var crawler = function() {
return {
init : function() {
document.getElementById('open').addEventListener('click', this.open);
},
open : function() {
var url = document.getElementById('url').value;
chrome.tabs.create({
url : url,
selected : true //doesn't work, setting to false does work
}, function(tab) {
chrome.tabs.executeScript(tab.id, {
file : 'js/scrape.js',
runAt : 'document_idle'
});
});
}
}}()
document.addEventListener('DOMContentLoaded', function() {
crawler.init();
});
I included index.js inside popup.html:
<script type="text/javascript" src="index.js"></script>
Finally, manifest.json:
{
"manifest_version": 2,
"name": "Crawler",
"description": "Scrape out the crap.",
"version": "1.0",
"permissions": ["tabs", "http://*/*", "https://*/*"],
"browser_action": {
"default_title": "Scrape out the crap",
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}
Using active => true fixed the issue. I missed the part of the documentation that explains it.