Communication between page and extension - google-chrome

i develop my first chrome extension.
I try to call the page from my default_popup.
I try with the chrome.runtime.onMessage.addListener and the chrome.runtime.sendMessage but that do not work.
I read this page https://developer.chrome.com/apps/messaging, but i can't figure out where to place correctly my Listiner.
I need when i open the "default popup", call an event in the page and return something to the "default_popup" came from the page.
More explication :
Actually i have a content.js in this content.js i am able to call the background.js by calling the chrome.runtime.sendMessage but it's call to fast.
The DOM of the page have not enought time to load. My content.js inject some .js file in the webpage to interact with the page.
It's there a way i can call the crhome.extension.sendMessage from the injected page ?
Any suggestion ?

Ok i found it.
We can register in the background.js an event
chrome.runtime.onMessageExternal.addListener(
function (request, sender, sendResponse) {
debugger;
if (sender.url == blacklistedWebsite)
return; // don't allow this web page access
if (request.openUrlInEditor)
openUrl(request.openUrlInEditor);
});
You need to put in the manifest the right rules
"externally_connectable": {
"matches": ["*://*.example.com/*"]
}
After that from your injected page :
chrome.runtime.sendMessage(extensionID, { openUrlInEditor: "test" },
function (response) {
debugger;
if (!response.success)
handleError("est");
});

Related

Content script code is not being executed

I've taken a look at other related SO posts and the solutions haven't helped solve my issue. This is my first chrome extension, so please bear with me!
I'm writing a simple chrome extension that searches for user provided keywords on a webpage. I can't get the content script that returns the DOM content to run. Some of the code, I've taken from an answer in another SO post, but I can't seem to get it to work for me.
I put a console.log("hello world") at the top of the file, and it doesn't show up, so I think it might be the structure of my project.
manifest.json
{
"name": "keyword search",
"version": "0.0.1",
"manifest_version": 2,
"permissions": [ "tabs" , "storage", "activeTab", "<all_urls>"],
"browser_action": {
"default_popup": "html/form.html"
},
"content_scripts": [{
"matches": [ "<all_urls>" ],
"js": [ "js/jquery.min.js", "content_scripts/content_script.js" ]
}],
"homepage_url": "http://google.com/"
}
js/popup.js
function run() {
running = true;
console.log('running');
var url = "https://www.stackoverflow.com/"
// Get KW & category for search
chrome.storage.local.get(["kw"],
function (data) {
kw = data.kw;
console.log("redirecting to find kw: " + kw);
// Send current tab to url
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.update(tabs[0].id, {url: url});
chrome.tabs.sendMessage(tabs[0].id, {type: 'DOM_request'}, searchDOM);
});
}
);
}
function searchDOM(domContent) {
console.log("beginning dom search \n" + domContent);
}
content_scripts/content_script.js
// Listen for messages
console.log("hello world")
chrome.runtime.onMessageExternal.addListener(function (msg, sender, sendResponse) {
// If the received message has the expected format...
if (msg.type === 'DOM_request') {
// Call the specified callback, passing
// the web-page's DOM content as argument
sendResponse(document.all[0].outerHTML);
}
});
console
running
redirecting to find kw: TestKeyword
beginning dom search
undefined
First, onMessageExternal is the wrong event (it's for external messaging):
you should use the standard onMessage.
Second, chrome extensions API is asynchronous so it only registers a job, returns immediately to continue to the next statement in your code without waiting for the job to complete:
chrome.tabs.update enqueues a navigation to a new URL
chrome.tabs.sendMessage enqueues a message sending job
the current page context in the tab gets destroyed along with the running content scripts
the tab starts loading the new URL
the message is delivered into the tab but there are no listeners,
but this step may instead run right after step 2 depending on various factors so the content script running in the old page will receive it which is not what you want
the tab loads the served HTML and emits a DOMContentLoaded event
your content scripts run shortly after that because of the default "run_at": "document_idle"
There are at least three methods to properly time it all:
make your content script emit a message and add an onMessage listener in the popup
use chrome.tabs.onUpdated to wait for the tab to load
use chrome.tabs.onUpdated + chrome.tabs.executeScript to simplify the entire thing
Let's take the executeScript approach.
remove "content_scripts" from manifest.json
instead of chrome.tabs.query (it's not needed) use the following:
chrome.tabs.update({url}, tab => {
chrome.tabs.onUpdated.addListener(function onUpdated(tabId, change, updatedTab) {
if (tabId === tab.id && change.status === 'complete') {
chrome.tabs.onUpdated.removeListener(onUpdated);
chrome.tabs.executeScript(tab.id, {
code: 'document.documentElement.innerHTML',
}, results => {
searchDOM(results[0]);
});
}
});
});

how to show the notification on certain websites extension page action

I'm developing an extension page action that works on certain websites I want to add a notification whenever the user visits the website specific i'm not satisfied just with the icon in the address bar, how do the notification appears when the user accesses the specific site ?
I have these codes
background, to show the icon in specific sites in the address bar
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (~tab.url.indexOf('specificsite.com.br')) {
chrome.pageAction.show(tabId);
}
});
Code for notification
createNotification();
audioNotification();
function audioNotification(){
var yourSound = new Audio('alert.mp3');
yourSound.play();
}
function createNotification(){
var opt = {type: "basic",title: "Your Title",message: "Your message",iconUrl: "128.png"}
chrome.notifications.create("notificationName",opt,function(){});
//include this line if you want to clear the notification after 5 seconds
setTimeout(function(){chrome.notifications.clear("notificationName",function(){});},10000);
}
You can use message passing to get it done by content scripts to detect the switch on certain websites, then notify the background page in order to display the notification for that page. Your content script should send a message using chrome.runtime.sendMessage, and the background page should listen using chrome.runtime.onMessage.addListener:
I created the sample code and tested it works with me:
Content script(myscript.js):
if(onCertainWebsitesNeedNotificationAppearTrue) {
// send message to background script
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
});
}
Background page:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
//alert("good");
if (request.greeting == "hello")
createNotification();
});
function createNotification(){
var opt = {type: "basic",title: "Your Title",message: "Your message",iconUrl: "128.png"}
chrome.notifications.create("notificationName",opt,function(){});
//include this line if you want to clear the notification after 5 seconds
setTimeout(function(){chrome.notifications.clear("notificationName",function(){});},10000);
}
Also keep in mind to register your content script's code and permissions in manifest like:
"permissions": ["notifications"],
"content_scripts": [
{
"matches": ["http://www.certainwebsiteone.com/*", "http://certainwebsitetwo.com/*"],
"js": ["myscript.js"]
}
]

Chrome Extension: Insert a clickable image using a content script

I know hat it is possible, but I am not quite sure how to do it the 'right' way, as to ensure there are no conflicts.
I came across this question: Cannot call functions to content scripts by clicking on image . But it is so convoluted with random comments that it's hard to understand what the corrected way was.
Use case:
Html pages have a div on the page where they expect anyone using the Chrome extension to inject a picture. When users click on he picture, I want to somehow notify an event script. So I know I need to register a listener so the code inserted messages the event script.
Can I get some indication on what code to inject through the content script? I saw that sometimes injecting jquery directly is advised.
I am trying to avoid having the html page to post a message to itself so it can be intercepted. Thanks
With the help of Jquery something like this would capture the image onclick event and allow you to pass a message to a background page in the Chrome Extension:
$("img").click(function(){
var imageSrc = $(this).attr("src");
//Post to a background page in the Chrome Extension
chrome.extension.sendMessage({ cmd: "postImage", data: { imgSrc: imageSrc } }, function (response) {
return response;
});
});
Then in your background.js create a listener for the message:
chrome.extension.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.cmd == "postImage") {
var imageSrc = request.data.imgSrc;
}
});

How to get document.referrer in background.html of Google Chrome Extension?

I can get tab.url and tab.title but could not find an easy way to get the referrer property for the tab - I dont think there is anything as tab.referrer in Google Chrome Extension.
I've only tested this in popups, but it should also work in a background page. Run this script in your background.html:
// register your listener
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
var referrer = request.ref;
// you can now use the referrer
});
// inject script into web site
// this will trigger your registered listener from above
chrome.tabs.executeScript(null, {
code: "chrome.extension.sendRequest({ref: document.referrer}, function(response) {})"
});

about sending messages among bg.html, popup.html and contentscript.js

In my extension, when a button named mybuttonl in popup.html is
clicked, it sends a message "getvar" to contentscript.js, which in turn sends a message "I want var1" to background.html to get an object named var1. (A button named mybutton2 is set up likewise, except it gets the var2 object when clicked).
How should I implement this?
What's more, I am a little confused about the chrome.extension.onRequest.addListener and chrome.extension.sendRequest methods. Could someone please explain?
onRequest.addListener and sendRequest is part of Chrome's extension Messaging. Which is located here http://developer.chrome.com/extensions/messaging.html
Basically, you listen for a request using "onRequest.addListener" that someone sent from triggering a "sendRequest".
In your case, you put a "onRequest.addListener" in your content script to listen for requests coming from the Popup (using sendRequest). And from your content script, you can return a response back to your popup to handle what is happening. In your popup, you have direct access to the background page using chrome.extension.getBackgroundPage().
If you want your content script to communicate to your background page as well (which is not needed since your making stuff more complicated), you can add a "onRequest.addListener" to your background page which only listens for requests coming from the content script. To do that, Message Passing explains it perfectly. "sender.tab" if true, is a content script.
The example below (untested) shows what I mean about message passing. Remember, try to keep stuff simple, not complex.
Example
Popup.html
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {method: "fromPopup", tabid: tab.id}, function(response) {
console.log(response.data);
});
});
ContentScript.js
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == "fromPopup") {
// Send JSON data back to Popup.
sendResponse({data: "from Content Script to Popup"});
// Send JSON data to background page.
chrome.extension.sendRequest({method: "fromContentScript"}, function(response) {
console.log(response.data);
});
} else {
sendResponse({}); // snub them.
}
});
BackgroundPage.html
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
// From content script.
if (sender.tab) {
if (request.method == "fromContentScript")
sendResponse({data: "Response from Background Page"});
else
sendResponse({}); // snub them.
}
});