Reputation: 1322
I'm writing a chrome extension, mostly for learning purpose which will show me the Google analytics tracking id (UA-xxxxxx-x) if Google Analytics is installed.
I understand that I need to use sendRequest to a content script in the page to retrieve information, and have successfully implemented that functionality
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
// analytics request check GA and send back
if(request.requestDetail == "analytics") {
console.log(window._gaq);
console.log(window._gaq._getAsyncTracker()._getAccount());
// unknown response, send back nothing!
} else {
sendResponse({});
}
});
The listener is receiving the request, Google Analytics is definately installed on the webpage I'm testing, window._gaq and window._gaq._getAsyncTracker()._getAccount() are both accessible via the console and returns what I expect.
Why is window._gaq undefined when accessing via the listener? How should I access it from a chrome extension?
I've got an idea that there is a security reason for this so have also tried modifying the manifest to include the below but still no luck
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
I suppose a secondary question would be:
Is what I'm trying to achieve possible in the manner I am using (I have managed to get a similar result using regex matching on the contents of the page, but would like to access the objects directly)
Upvotes: 2
Views: 1107
Reputation: 4162
This has nothing to do with Content Security Policy. I think you're injecting a content script into web pages and trying to access variables in the web page. Because of content scripts are executed in an isolated world, you cannot directly do this. See https://developer.chrome.com/trunk/extensions/content_scripts.html#execution-environment for more detail.
To access variables in web pages (necessary in your case), you must inject a <script> tag in the page. Retrieve Google Analytics ID in that script, and communicate with the content script (https://developer.chrome.com/trunk/extensions/content_scripts.html#host-page-communication) to have the content script send it back to your extension.
Here's a simple example (Disclaimer: Just to illustrate how to do it. I didn't test it myself.):
window.addEventListener("message", function(event) {
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_PAGE")) {
chrome.extension.sendMessage(...); // Send analytics ID (in event.data.googleAnalyticsId) to your extension here
}, false);
var script = document.createElement('script');
script.appendChild(document.createTextNode('window.postMessage({googleAnalyticsId: (window._gaq ? window._gaq._getAsyncTracker()._getAccount() : ""), type: "FROM_PAGE"}, "*");');
document.appendChild(script);
Also note that chrome.extension.onRequest/sendRequest has been deprecated for a long time (https://developer.chrome.com/trunk/extensions/whats_new.html#20). You should use onMessage/sendMessage instead.
Upvotes: 4
Reputation: 36511
Though I'm not particularly proud of this one, it works; I don't think you can access the variables on the page without injecting another script into the page.
var find_ga_account = function(){
var scripts = document.querySelectorAll('script:not([src])'),
i = 0,
match,
ua = false;
for( ; i < scripts.length; i++){
match = scripts[i].textContent.match(/_setAccount['"]+,[\s]?['"]+(.*)['"]+/)
if(match && match.length > 0){
ua = match[1];
}
}
return ua;
}
Upvotes: 0