I am creating an extension that I need to have the ability to run the content script multiple times when clicking on the page action button. I have this in my background.js:
chrome.pageAction.onClicked.addListener(function(tab) {
alert('calling content_script');
chrome.tabs.executeScript(null, {
file: 'content_script.js'
},function(){alert("success");});
});
This works the first time the button is clicked. When clicked a second time, I get my popup saying "calling content_script" but the content script is never executed. Why is this?
Here is the background script in its entirety:
function checkForValidUrl(tabId, ChangeInfo, tab){
if(tab.url.indexOf("tiger.armstrong")> -1){
chrome.pageAction.show(tabId);
if(tab.url.indexOf("tiger.armstrong") == 0){
chrome.pageAction.hide(tabId);
}
}
}
chrome.tabs.onUpdated.addListener(checkForValidUrl);
chrome.pageAction.onClicked.addListener(function(tab) {
alert('calling content_script');
chrome.tabs.executeScript(null, {
file: 'content_script.js'
},function(){alert("success");});
});
Here is the manifest:
{
"name": "LiveLab Post Grades",
"version": "2.0",
"permissions": [
"activeTab","tabs","http://*/*","https://*/*"
],
"background": {
"scripts": ["jquery.min.js","background3.js"],
"persistent": false
},
"page_action": {
"default_icon": {
"19": "GIcon.png"
},
"default_title": "LiveLab Tools"
},
"content_scripts": [ {
"js": [ "jquery.min.js" ],
"matches": [ "http://*/*", "https://*/*"],
"run_at": "document_end"
}],
"manifest_version": 2
}
Here is the content script:
var livelabtools = {
/**
* this function is like window.open, but it can POST (rather than GET) from js
* source: http://canop.org/blog/?p=426
*/
canop_open: function (verb, url, data, target) {
var form = document.createElement("form");
form.action = url;
form.method = verb;
form.target = target || "_self";
if (data) {
//for (var key in data) {
var input = document.createElement("input");
input.name = 'data';
input.value = data;//typeof data[key] === "object" ? JSON.stringify(data[key]) : data[key];
form.appendChild(input);
//console.log(form);
//}
}
// these two lines are only needed for ie
//form.style.display = 'none';
//document.body.appendChild(form);
form.submit();
console.log("form submit === " + form);
form.remove();
},
post_grades: function () {
alert('in post grades!!!!');
var str, exercise,
i = 0;
grades = {};
do {
ex_str = "form1:tabSet1:tabInstr:lp2:tabSet4:tabp:lpProgress:ts1:tab7:lp7:table3:rg3:" + i + ":tc3:st3";
lname_str = "form1:tabSet1:tabInstr:lp2:tabSet4:tabp:lpProgress:ts1:tab7:lp7:table3:rg3:" + i + ":tc1:st1";
grade_str = "form1:tabSet1:tabInstr:lp2:tabSet4:tabp:lpProgress:ts1:tab7:lp7:table3:rg3:" + i + ":tc7:st7_field";
exercise = document.getElementById(ex_str);
lname = document.getElementById(lname_str);
grade = document.getElementById(grade_str);
if (exercise != null) {
if (grades[lname.innerHTML] === undefined)
grades[lname.innerHTML] = {};
console.log(lname.innerHTML + ", " + exercise.innerHTML + ", " + grade.innerHTML);
if (grade.value != null && grade.value != '')
grades[lname.innerHTML][exercise.innerHTML] = grade.value;
else
grades[lname.innerHTML][exercise.innerHTML] = "0";
}
i++;
} while (exercise != null);
// console.log(JSON.stringify(grades));
// console.log(JSON.stringify(grades).length)
//window.open("http://aspen2.cscofc.info/jsontocsv.php?data="+JSON.stringify(grades));
console.log('posting...' + "\n JSON.String... = "+ JSON.stringify(grades));
livelabtools.canop_open("post", "http://aspen2.cscofc.info/jsontocsv.php", JSON.stringify(grades));
console.log('done');
return "function end";
}
}
console.log(livelabtools.post_grades());
I won't go into detail about it, unless asked but the important parts to note are the return statement and the console log. Everything runs perfectly fine the first time the page action button is clicked, and when finished, I get "function end" printed to the console. After the initial run, however, whenever I click on the page action button, I get an alert saying "calling content_script" and nothing else happens. Why won't my content script run more than once?
It seems like when a script has already been injected it is not injected again.
So, the way to go would be to initiate your action by passing a message to the content script. (Of course, if the content script has not been injected yet, you need to inject it first.)
One solution I came up with (and after testing confirmed it works fine) is the following:
On pageAction.onClicked send a message from the background page to the content script, asking it to do something (e.g. post the grades). Also, request a response to be sent back to the background page.
[See, also, chrome.tabs.sendMessage(...).]
If the content script has already been injected, have it receive the message, send a confirmation back to the background page and proceed doing something (e.g. posting the grades). This process can take place as many times as you want.
[See, also, chrome.runtime.onMessage.]
The first time that the pageAction.onClicked is fired, there will be no content script listening for messages. In that case, there will be no message confirmation. Instead chrome.runtime.lastError will be set. In that case, the background page will have to inject the content script first and then send the message again.
[See, also, chrome.runtime.lastError.]
Theoreticaly speaking, that should do it !
Practicaly, this is the sample code that worked for me:
manifest.json:
(Note: If you have more specific requirements regarding the pages you need to access, you could incorporate them into the manifest and get rid of some of the permissions.)
{
...
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"page_action": {
"default_title": "Test Extension"
},
"permissions": [
"tabs",
"http://*/*",
"https://*/*"
]
...
}
background.js:
function checkForValidURL(tabId, info, tab) {
var idx = tab.url.indexOf("tiger.armstrong");
if (idx > 0) {
chrome.pageAction.show(tabId);
} else {
chrome.pageAction.hide(tabId);
}
}
chrome.tabs.onUpdated.addListener(checkForValidURL);
function onPageActionClicked(tab) {
// Send message to content script, asking to post grades
alert("Calling content_script...");
chrome.tabs.sendMessage(tab.id, { action: "postGrades" }, function() {
if (chrome.runtime.lastError) {
// The error indicates that the content script
// has not been injected yet. Inject it and...
chrome.tabs.executeScript(tab.id, {
file: "content.js"
}, function() {
if (!chrome.runtime.lastError) {
// ...if injected successfully, send the message anew
onPageActionClicked(tab);
}
});
} else {
// The content script called our response callback,
// confirming that it is there and got our message
alert("Message got through !");
}
});
};
chrome.pageAction.onClicked.addListener(onPageActionClicked);
content.js:
var livelabtools = {
/**
* This function is like window.open, but it can POST (rather than GET) from
* JS source: http://canop.org/blog/?p=426
*/
canop_open: function (method, url, data, target) {
var form = document.createElement("form");
form.action = url;
form.method = method;
form.target = target || "_self";
// 'data' is an object with key-value pairs
// of fields to be sent
if (data) {
for (var key in data) {
var input = document.createElement("input");
input.name = key;
input.value = (typeof(data[key]) === "object")
? JSON.stringify(data[key]) : data[key];
form.appendChild(input);
}
}
form.submit();
form.remove();
},
post_grades: function () {
console.log("Posting some grades...");
livelabtools.canop_open("POST",
"http://aspen2.cscofc.info/jsontocsv.php",
"{}");
console.log("Grades sent !");
}
}
// Listen for messages from the background page
// (It actually listens for messages from anyone in the context,
// but the background page is the one that interrests us)
chrome.runtime.onMessage.addListener(function(msg, sender, response) {
// If we've been asked to post grades...
if (msg.action && (msg.action == "postGrades")) {
// ...confirm we got the message and...
response();
// ...do what we do best: post grades !
livelabtools.post_grades();
}
});
Let's hope this covers it :)
Related
I've searched for this for quite a while and found some solutions relying on mutationobserver (How to wait until an element exists?). However, I don't understand how to lay a project out like this. I don't know how the manifest would look like and how it would interact with the .js files. I don't know if there would be a background.js or a content script. I'm pretty new to building chrome extensions. Can somebody provide a solution (with file names)? so, when a selector becomes visible (after a drop down is clicked, exposing it, for example) text is sent to that selector via something like:
document.getElementById("Note_2").value = "text sent";
tried this:
popup.js
elementLoaded('1662123261320', function(el) {
// Element is ready to use.
el.click(function() {
alert("You just clicked a dynamically inserted element");
});
});
manifest.json
{
"manifest_version": 2,
"name": "Content Scripts example",
"description": "A simple content_scripts example.",
"version": "1.0",
"content_scripts": [
{
"matches": ["http://news.163.com/*","file://*"],
"js": ["popup.js"]
}
],
"permissions": [
"<all_urls>"
]
}
on this site:
https://inputtypes.com/
doesn't alert. still trying
tried adding the text dropdown as well: "#\31 662123564414-inputType". nothing happens
tried this on paypal.com as well.. login button:
waitForElementToDisplay("#ul-btn",function(){alert("Hi");},1000,9000);
anybody know why it's not working?
edit: I kind of got it... I can get it to alert when an element is present, but not to send text to that element. paypal login:
// Call the below function
waitForElementToDisplay("#email",function(){
document.getElementById("#email").value = "N/A";
},1000,9000);
function waitForElementToDisplay(selector, callback, checkFrequencyInMs, timeoutInMs) {
var startTimeInMs = Date.now();
(function loopSearch() {
if (document.querySelector(selector) != null) {
callback();
return;
}
else {
setTimeout(function () {
if (timeoutInMs && Date.now() - startTimeInMs > timeoutInMs)
return;
loopSearch();
}, checkFrequencyInMs);
}
})();
}
anybody know why the text wont prefill?
ok this works just had to remove the #
paypal login page:
// Call the below function
waitForElementToDisplay("#email",function(){
document.getElementById("email").value = "N/A";
},1000,9000);
function waitForElementToDisplay(selector, callback, checkFrequencyInMs, timeoutInMs) {
var startTimeInMs = Date.now();
(function loopSearch() {
if (document.querySelector(selector) != null) {
callback();
return;
}
else {
setTimeout(function () {
if (timeoutInMs && Date.now() - startTimeInMs > timeoutInMs)
return;
loopSearch();
}, checkFrequencyInMs);
}
})();
}
I am new to using chrome extensions and i have a run into a little problem with setting up a chrome extension. I want the extension to read specific values from a web page and then open up a specific page (form with a number of input fields) from a flask application that I have built in a new tab and then use the values that have been scraped to populate specific fields in the page from my flask app.
I have managed to get the extension to generate a new tab and to load the page from my flask app but I am unable to get the fields to populate. It would seem that the page gets loaded before the fields are populated. I have pasted some code to show you how far I have got. The other issue is that I am using the code parameter from executeScripts to perform the populating action but I don't seem to be able to pass arguments into the code string (I suspect this is not the way to do this but I am working off an answer that I have found very helpful up to this point from here https://stackoverflow.com/a/41094570/1977981
Any help would be much appreciated.
manifest.json
{
"manifest_version": 2,
"name": "My Cool Extension",
"version": "0.1",
"permissions": [
"http://localhost:****/lesson/1/note/new/"
],
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["jquery-3.2.1.min.js", "content.js"]
}
],
"browser_action": {
"default_icon": "icon.png"
},
"background": {
"scripts": ["jquery-3.2.1.min.js", "background.js"]
}
}
content.js
// Triggered by sendMessage function in background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
// listening for request message
if( request.message === "clicked_browser_action" ) {
// Retrieve Lesson title from current tab
var lesson = $('._tabbed-sidebar--title--1Dx5w').find('span').text()
// output this value to the console
console.log(lesson);
// Send a single message to the event listener in your extension i.e. background.js
chrome.runtime.sendMessage({"message": "open_new_tab", "lesson": lesson})
}
}
);
background.js
// Called when the user clicks on the browser action icon.
chrome.browserAction.onClicked.addListener(function(tab) {
// Send a message to the active tab
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
// take the current tab shown in the window
var activeTab = tabs[0];
// Send a message to contents.js - this message is being listened for by contents.js and the runtime.onMessage event is fired in content.js script
chrome.tabs.sendMessage(activeTab.id, {"message": "clicked_browser_action"});
});
});
// listening for "open_new_tab" message from content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "open_new_tab" ) {
// create new tab but do not activate the tab yet
chrome.tabs.create({"url": "http://localhost:5000/lesson/1/note/new/", active: false }, function(tab){
// load jquery functionality execute script
chrome.tabs.executeScript(tab.id, {file: "jquery-3.2.1.min.js"}, function(results){
chrome.tabs.executeScript(tab.id,{code:`
(function(arguments){
var count = 100; //Only try 100 times
function autofill(){
var lesson = $('.lesson_subsection');
console.log(lesson);
if(lesson){
lesson.value = arguments[0].lesson;
} else {
if(count-- > 0 ){
//The elements we need don't exist yet, wait a bit to try again.
setTimeout(autofill,250);
}
}
}
autofill();
}, request)();
`}, function(results){
chrome.tabs.update(tab.id,{active:true});
}); //END OF second executeScript function
}); // END OF first executeScript function
} // END OF chrome.tabs.create anonymous function
); // END OF chrome.tabs.create
} // END OF if( request.message === "open_new_tab" ) {
}); // END OF addListener anonymous function
Thank you #wOxxOm your comments were very helpful. I was able to use JSON.stringify to load the arguments in to the injected code string. I also had to load the input element from my form using document.getElementsByClassName() instead of using the jquery version of the object. This also meant i didn't have to load the jquery library see line shown below
var less = document.getElementsByClassName('lesson_subsection')[0];
Now my chrome.runtime.onMessage.addListener function in my background.js script is as follows:
// See content.js function
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "open_new_tab" ) {
chrome.tabs.create({"url": "http://localhost:5000/lesson/1/note/new/", active: false }, function(tab){
console.log('Attempting to inject script into tab:',tab);
chrome.tabs.executeScript(tab.id,{code:`
(function(argument){
var count = 100; //Only try 100 times
function autofill(){
var less = document.getElementsByClassName('lesson_subsection')[0];
if(less){
less.value = argument;
} else {
if(count-- > 0 ){
//The elements we need don't exist yet, wait a bit to try again.
setTimeout(autofill,250);
}
}
}
autofill();
})(` + JSON.stringify(request.lesson) + `);
`}, function(results){
// chrome.tabs.sendMessage(tab.id, {"message": "need to update tab", "tab": tab.id});
chrome.tabs.update(tab.id, { active: true });
}); //END OF executeScript function
} // END OF chrome.tabs.create anonymous function
); // END OF chrome.tabs.create
} // END OF if( request.message === "open_new_tab" ) {
}); // END OF addListener anonymous function
I can't seem to get popover to work in my chrome extension.
The extension is intended to go through my school's registration page, pull up info on my professors through a professor rating website, and show it in a popover. (And link to the pages which works fine).
Here is the school page. Just hit something like Subject = Art
Less than = 200
Some results pop up, you click the extension icon, and bam the script runs. With all that, maybe the error is in my code. I'm not sure.
My code:
Manifest:
{
"name": "RMP",
"description": "Work in Progress",
"manifest_version": 2,
"version": "0.8",
"icons": {
"16": "icon16.png",
"48": "icon48.png",
"128": "icon128.png"
},
"permissions": [
"activeTab",
"http://*/",
"https://*/"
],
"background": {
"scripts": ["jquery-3.2.1.min.js","bootstrap.min.js","background.js"],
"persistent": false
},
"browser_action": {
"default_title": "Click me!"
}//,
//"web_accessible_resources": ["bootstrap-native.js"]
}
Background:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(tab.Id, {file: "jquery-3.2.1.min.js"}, function() {
chrome.tabs.executeScript(tab.Id, {file: "bootstrap.min.js"}, function(){
chrome.tabs.executeScript(tab.Id, {file: "content_script.js"})
});
});
});
Content_script.js:
NOTE --- I am aware I have like 2-3 different attempts at getting popover to work. Can't get anything at all to work unfortunately.
// Handle page's frame (to allow DOM access)
var page = top.frames["TargetContent"].document;
// Reference every professor listed and modify the registration page
Array.from(page.querySelectorAll("[id^='MTG_INSTR$']") ).forEach( el => {
if (el.textContent == "## Heading ##Staff") {
return;
}
// For every professor found, search for RMP page
searchProfessor(el)
});
/**
* Search for professor on RMP, then pass along to pageCheck
*
* #param {Reference to prof} professorEl
*/
function searchProfessor(professorEl) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
pageCheck(this.response,professorEl);
}
}
// Search RMP using CSUF + Prof Name
xhr.open('GET', 'https://www.ratemyprofessors.com/search.jsp?queryoption=HEADER&queryBy=teacherName&schoolName=california+state+university+fullerton&schoolID=&query=' + professorEl.textContent +'&_action_search=Search');
xhr.responseType = 'document';
xhr.send();
}
/**
* Verify prof's page exists and modify registration page
*
* #param {DOM Obj} page
* #param {Reference to prof} element
*/
function pageCheck(page,element){
var ProfURL = page.getElementsByClassName('listing PROFESSOR')[0].childNodes[1].href
// If the element exists, we have a hit (and the prof's page!)
if (ProfURL) {
// Link to the prof's RMP page
addAnchor(element, ProfURL);
// Access the prof's specific RMP page
var xhr1 = new XMLHttpRequest();
// Create box to display prof info on hover
xhr1.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
addTooltip(this.response,element);
}
}
xhr1.open('GET', ProfURL);
xhr1.responseType = 'document';
xhr1.send();
}
}
function addTooltip(profPage,profElement) {
var name = profElement.textContent;
var grade = profPage.getElementsByClassName('grade')[0].textContent;
var difficulty = profPage.getElementsByClassName('grade')[2].textContent;
var ratings = profPage.getElementsByClassName('table-toggle rating-count active')[0].textContent;
ratings = ratings.trim();
var content = "Grade: " + grade;
profElement.firstChild.setAttribute("data-toggle","popover");
profElement.firstChild.setAttribute("data-trigger","hover");
profElement.firstChild.setAttribute("title",name);
profElement.firstChild.setAttribute("data-content",content);
//profElement.popover();
$("[data-toggle=popover]",top.frames["TargetContent"]).popover();
}
/**
* Assign hyperlink to element
*
* #param {Element} wrapper
* #param {String} URL
*/
function addAnchor (wrapper, URL) {
var a = document.createElement('a');
a.href = URL;
a.textContent = wrapper.textContent;
// Opens in new window/tab
a.setAttribute('target', '_blank');
wrapper.replaceChild(a, wrapper.firstChild);
}
$(document).ready(function()
{
$('[data-toggle=popover]').popover(
{
trigger: 'hover',
html: true,
placement: 'right',
content: 'hello world'
});
});
$("[data-toggle=popover]",top.frames["TargetContent"]).popover();
$(".PSLONGEDITBOX",top.frames["TargetContent"].document).popover();
I have a chrome extension with options set through the options_ui tag in manifest.json. I can save options however I noticed the options modal has to be closed for the chrome.storage.sync.set function to complete saving the options. How do I force saving of the options upon clicking "save" even if the options modal is not closed?
options.js:
function save_options() {
var hideAds = document.getElementById('hideAds').checked;
chrome.storage.sync.set({
hideAds: hideAds
}, function() {
// Update status to let user know options were saved
var status = document.getElementById('status');
status.textContent = 'Options successfully saved...';
setTimeout(function() {
status.textContent = '';
}, 1000);
});
}
// Restores checkbox state using the preferences stored in chrome.storage.
function restore_options() {
// Use default values
chrome.storage.sync.get({
hideAds: false
}, function(items) {
document.getElementById('hideAds').checked = items.hideAds;
});
}
document.addEventListener('DOMContentLoaded', restore_options);
document.getElementById('save').addEventListener('click', save_options);
manifest.json:
{
"name": "Redesign",
"version": "1.0",
"manifest_version": 2,
"options_ui": {
"page": "options.html",
"chrome_style": true
}
}
EDIT: Adding background.js code below that doesn't get latest options (after clicking save button on the options page) unless options modal is closed. The alert line below outputs the old saved option value...and the new saved value only after the options modal is closed.
chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
if (info.status == 'complete') {
chrome.storage.sync.get(['hideAds'], function(items) {
if(typeof items.hideAds !== 'undefined') {
hideAds = items.hideAds;
alert(hideAds);
}
})
doSomething(tab);
}
});
You could listen to chrome.storage.onChanged event in background page ( you would never need to listen to chrome.tabs.onUpdated for getting storage value), which fires when one or more items change:
chrome.storage.onChanged.addListener(function(changes, areaName) {
if(areaName === 'sync') {
const hideAdsChange = changes['hideAds'];
if(typeof hideAdsChange !== 'undefined') {
const newValue = hideAdsChange.newValue;
console.log(newValue);
}
}
});
I am looking for a function inside a webpage te activate a chrome extension.
Imagine that http://www.example.com/test.html contains:
<script>
hello();
</script>
And my background page contains the definition of the hello function:
function hello() {
alert("test");
}
How can I make sure that the Chrome extension's background page's hello is called when test.html calls hello();?
Before a web page is able to call a background page's function, the following problems need to be solved:
Be able to use hello(); from a web page. This is done by injecting a script defining hello using Content scripts. The injected function communicates with the content script using a custom event or postMessage.
The content script needs to communicate with the background. This is implemented through chrome.runtime.sendMessage.
If the web page needs to receive a reply as well:
Send a reply from the background page (sendMessage / onMessage, see below).
In the content script, create a custom event or use postMessage to send a message to the web page.
In the web page, handle this message.
All of these methods are asynchronous, and have to be implemented through callback functions.
These steps need to be designed carefully. Here's a generic implementation which implements all of the above steps. What you need to know about the implementation:
In the code-to-be-injected, use the sendMessage method whenever the content script need to be contacted.
Usage: sendMessage(<mixed message> [, <function callback>])
contentscript.js
// Random unique name, to be used to minimize conflicts:
var EVENT_FROM_PAGE = '__rw_chrome_ext_' + new Date().getTime();
var EVENT_REPLY = '__rw_chrome_ext_reply_' + new Date().getTime();
var s = document.createElement('script');
s.textContent = '(' + function(send_event_name, reply_event_name) {
// NOTE: This function is serialized and runs in the page's context
// Begin of the page's functionality
window.hello = function(string) {
sendMessage({
type: 'sayhello',
data: string
}, function(response) {
alert('Background said: ' + response);
});
};
// End of your logic, begin of messaging implementation:
function sendMessage(message, callback) {
var transporter = document.createElement('dummy');
// Handles reply:
transporter.addEventListener(reply_event_name, function(event) {
var result = this.getAttribute('result');
if (this.parentNode) this.parentNode.removeChild(this);
// After having cleaned up, send callback if needed:
if (typeof callback == 'function') {
result = JSON.parse(result);
callback(result);
}
});
// Functionality to notify content script
var event = document.createEvent('Events');
event.initEvent(send_event_name, true, false);
transporter.setAttribute('data', JSON.stringify(message));
(document.body||document.documentElement).appendChild(transporter);
transporter.dispatchEvent(event);
}
} + ')(' + JSON.stringify(/*string*/EVENT_FROM_PAGE) + ', ' +
JSON.stringify(/*string*/EVENT_REPLY) + ');';
document.documentElement.appendChild(s);
s.parentNode.removeChild(s);
// Handle messages from/to page:
document.addEventListener(EVENT_FROM_PAGE, function(e) {
var transporter = e.target;
if (transporter) {
var request = JSON.parse(transporter.getAttribute('data'));
// Example of handling: Send message to background and await reply
chrome.runtime.sendMessage({
type: 'page',
request: request
}, function(data) {
// Received message from background, pass to page
var event = document.createEvent('Events');
event.initEvent(EVENT_REPLY, false, false);
transporter.setAttribute('result', JSON.stringify(data));
transporter.dispatchEvent(event);
});
}
});
background.js
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message && message.type == 'page') {
var page_message = message.message;
// Simple example: Get data from extension's local storage
var result = localStorage.getItem('whatever');
// Reply result to content script
sendResponse(result);
}
});
A Chrome extension is not complete without a manifest file, so here's the manifest.json file which I used to test the answer:
{
"name": "Page to background and back again",
"version": "1",
"manifest_version": 2,
"background": {
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["http://jsfiddle.net/jRaPj/show/*"],
"js": ["contentscript.js"],
"all_frames": true,
"run_at": "document_start"
}]
}
This extension was tested at http://jsfiddle.net/jRaPj/show/ (containing hello(); as seen in the question), and shows a dialog saying "Background said: null".
Open the background page, use localStorage.setItem('whatever', 'Hello!'); to see that the message is correctly changed.
There is a builtin solution to Send messages from web pages to the extension
mainfest.json
"externally_connectable": {
"matches": ["*://*.example.com/*"]
}
Web page:
// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
function(response) {
if (!response.success)
handleError(url);
});
Extension's background script:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.url == blacklistedWebsite)
return; // don't allow this web page access
if (request.openUrlInEditor)
openUrl(request.openUrlInEditor);
});
No, with your above code because of background page(s) architecture
Yes with content scripts
Demonstration Using Content Scripts
manifest.json
Registering content scripts myscripts.js
{
"name": "NFC",
"description": "NFC Liken",
"version": "0.1",
"manifest_version": 2,
"permissions": ["tabs", "http://*/", "https://*/"],
"content_scripts": {
"matches": "http://www.example.com/*",
"js": [ "myscript.js"]
},
"browser_action": {
"default_icon": "sync-icon.png",
"default_title": "I Like I Tag"
}
}
Let me know if you need more information.