how to comunicate between a content script and a background page - google-chrome

i know this question has been asked before but i dont know hwo to make it work.
this is the content script:
console.log("online");
chrome.extension.sendRequest({foo: "yes"}, function(response) {
console.log(response.thefoo);
});
and this is the background page:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.foo == "yes")
sendResponse({thefoo:"this is the foo"});
else
sendResponse({"it didnt work"});
});
the code that i have here, its from one of the answered questions around here with a few changes that i made, but it didnt work even when i put it exactly.
you can see that answer here Chrome extension: accessing localStorage in content script

---=== background.html ===---
/*
* Handles data sent via chrome.extension.sendRequest().
* #param request Object Data sent in the request.
* #param sender Object Origin of the request.
* #param callbackFunction Function The method to call when the request completes.
*/
function onRequest(request, sender, callbackFunction) {
//your actions here
};
/*
* Add request listener
*/
chrome.extension.onRequest.addListener(onRequest);
---=== contentScript.js ===---
function callbackFunction(response) {
//process the response
}
chrome.extension.sendRequest({'action': 'your action'}, callbackFunction);
you also need to have the content script defined in the manifest file

Related

Report for exceptions from Google Analytics analytics.js exception tracking

Google Universal Analytics has a hit type of exception
ga('send', 'exception', {
'exDescription': 'DatabaseError'
});
I was expecting to be able to just go to the Google Analytics console and find an exeption report at the same level as 'events' however it's nowhere to be seen.
The Android and iOS APIs say Crash and exception data is available primarily in the Crash and Exceptions report but I can't find any report by that name.
Figured it out. I'm not sure why they don't make this a built in report but maybe someday.
I made a custom widget in a dashboard with Exception Description for dimension and 'Crashes' for the metric:
Which gives me a report like this:
You can also go to Customization tab and create a custom report to give you a table of errors, and then add it to your dashboard.
Used with this global exception handler
if (typeof window.onerror == "object")
{
window.onerror = function (err, url, line)
{
if (ga)
{
ga('send', 'exception', {
'exDescription': line + " " + err
});
}
};
}
You can put this handler anywhere in the initialization of your Javascript - which will depend upon how you have all your JS files configured. Alternatively you can just put it inside a <script> tag near the top of your html body tag.
I took Simon_Weaver's guide to making a custom report a few steps further and built out a fairly complete Google Analytics custom exceptions report. I figured it might be worth sharing, so I uploaded it to the GA "Solutions Gallery".
My template: Google Analytics Exceptions Report
Here's a picture of the end result:
I just wanted to expand a bit on #Simon_Weaver 's excellent answer to provide error reports with a few additional details:
Make sure ga() is defined before trying to call it (as an Error could be triggered before the Analytics library is loaded).
Log Exception line numbers and column index in the Analytics Reports (although minified JavaScript code used in production might be difficult to read).
Execute any previously-defined window.onerror callback.
/**
* Send JavaScript error information to Google Analytics.
*
* #param {Window} window A reference to the "window".
* #return {void}
* #author Philippe Sawicki <https://github.com/philsawicki>
*/
(function (window) {
// Retain a reference to the previous global error handler, in case it has been set:
var originalWindowErrorCallback = window.onerror;
/**
* Log any script error to Google Analytics.
*
* Third-party scripts without CORS will only provide "Script Error." as an error message.
*
* #param {String} errorMessage Error message.
* #param {String} url URL where error was raised.
* #param {Number} lineNumber Line number where error was raised.
* #param {Number|undefined} columnNumber Column number for the line where the error occurred.
* #param {Object|undefined} errorObject Error Object.
* #return {Boolean} When the function returns true, this prevents the
* firing of the default event handler.
*/
window.onerror = function customErrorHandler (errorMessage, url, lineNumber, columnNumber, errorObject) {
// Send error details to Google Analytics, if the library is already available:
if (typeof ga === 'function') {
// In case the "errorObject" is available, use its data, else fallback
// on the default "errorMessage" provided:
var exceptionDescription = errorMessage;
if (typeof errorObject !== 'undefined' && typeof errorObject.message !== 'undefined') {
exceptionDescription = errorObject.message;
}
// Format the message to log to Analytics (might also use "errorObject.stack" if defined):
exceptionDescription += ' # ' + url + ':' + lineNumber + ':' + columnNumber;
ga('send', 'exception', {
'exDescription': exceptionDescription,
'exFatal': false, // Some Error types might be considered as fatal.
'appName': 'Application_Name',
'appVersion': '1.0'
});
}
// If the previous "window.onerror" callback can be called, pass it the data:
if (typeof originalWindowErrorCallback === 'function') {
return originalWindowErrorCallback(errorMessage, url, lineNumber, columnNumber, errorObject);
}
// Otherwise, Let the default handler run:
return false;
};
})(window);
// Generate an error, for demonstration purposes:
//throw new Error('Crash!');
Edit: As #Simon_Weaver duly noted, Google Analytics now has documentation about Exception Tracking (which I should have linked to in my original answer -- sorry, rookie mistake!):
https://developers.google.com/analytics/devguides/collection/analyticsjs/exceptions
https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#exception
This is what I came up with so you don't need to include the code everywhere. Just add new ErrorHandler(); to each .js file. This was done for a Chrome Extension, but should work anywhere, I think. I implement the actual ga() stuff in a separate file (hence the app.GA), but you could bake it in here too.
/*
* Copyright (c) 2015-2017, Michael A. Updike All rights reserved.
* Licensed under the BSD-3-Clause
* https://opensource.org/licenses/BSD-3-Clause
* https://github.com/opus1269/photo-screen-saver/blob/master/LICENSE.md
*/
// noinspection ThisExpressionReferencesGlobalObjectJS
(function(window, factory) {
window.ExceptionHandler = factory(window);
}(this, function(window) {
'use strict';
return ExceptionHandler;
/**
* Log Exceptions with analytics. Include: new ExceptionHandler();<br />
* at top of every js file
* #constructor
* #alias ExceptionHandler
*/
function ExceptionHandler() {
if (typeof window.onerror === 'object') {
// global error handler
window.onerror = function(message, url, line, col, errObject) {
if (app && app.GA) {
let msg = message;
let stack = null;
if (errObject && errObject.message && errObject.stack) {
msg = errObject.message;
stack = errObject.stack;
}
app.GA.exception(msg, stack);
}
};
}
}
}));
You can now find a "Crashes and Exceptions" view under Behavior (if property is created as a "mobile app" in Google Analytics).

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 communicate between a options page and background page of chrome extension

I face a problem. Through message passing I transferred DOM data from content script to background page. What i would like to know is how you can establish a communication channel between Options page and background page. The API chrome.extension.getBackgroundPage() is not useful. Nor is traditional message passing through sendRequest and addlistener working . How do i transfer this data from background page to the options page? Could someone provide a tested snippet to explain?
this is what i have been trying .
In my contentscript.js
<script>
var selected_Text ="";
window.addEventListener("dblclick",function(event){
selected_Text = String(window.getSelection());
chrome.extension.sendRequest({greeting: "maprender",name:selected_Text}, function(response) {
alert("reached here")
console.log(response.farewell);
});
//i am to then load options.html on DOM like this
var Div = document.createElement("iframe");
Div.setAttribute('src', chrome.extension.getURL('options.html'));
Div.setAttribute("style","width:130px;height:80px;position:absolute;left:10px;");
Div.setAttribute("id","xyz");
document.body.appendChild(Div);
</script>
I retreive the selected_Text at background.html like this
<script>
var Addr_details={
place:null
};
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
if (request.greeting == "maprender")
{
alert("reached here sendin resp"+request.name);
Addr_details.place = request.name;
sendResponse({farewell: "goodbye"});
}
else
sendResponse({}); // snub them.
});
</script>
Now to access the value of this text at the options page options.html i tried 2 methods
One was to use chrome.extension.getBackgroundPage() like this:
<script>
function init(){
var bkg = chrome.extension.getBackgroundPage();
alert("the selected text is "+bkg.Addr_details.place);
}
</script>
init is onload of options.html .This does not give me the value . infact it just terminates at initialization of chrome.extension.backgroundPage.
Another approach i tried was to create a similar request(like the one already present at contentscript.js) from contentscript.js with a different greeting and add a listener to it at options.html .That doesnt seem to work either at the receiver side(options page) because i get the callback at the contentscript after the request.I am surely doing something wrong , amnt I ?Please help.
It makes sense for the second approach not work. Options.html is not "alive" all of the time, only when the options page is up. Hence, it cannot listen to requests from the content script.
That's exactly what "background" is for.
As for the first approach (using getBackgroundPage()), I never used this method myself, but it seems to bring back only the DOM of the background page, and therefore you cannot access the variables in the background js.
Your best shot should be to send a request from the options page to the background page, asking for this value, e.g.:
Content script:
chrome.extension.sendRequest({greeting: "retrieveAddr"}, function(response) {
// do something with response.addr...
});
Background page:
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
switch (request.greeting) {
case "maprender"):
alert("reached here sendin resp"+request.name);
Addr_details.place = request.name;
sendResponse({farewell: "goodbye"});
break;
case "retrieveAddr":
sendResponse({addr: Addr_details});
default:
sendResponse({}); // snub them.
});
});
Another, easier but hackier solution is to use localStorage to pass info between the options and background pages, as they both share the same one.

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.
}
});