Access DOM var from content.js script - google-chrome

I'm trying to access a global var (timer) on a webpage using the content.js script via my google chrome extension.
However, everytime it returns undefined, even though I can easily access it via the developer console.
var mySocket;
console.log('content.js');
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
switch(request.task){
case "socketInjection":
window.setTimeout(
function(){ console.log(timer);}, 5000);
break;
}
});
Im using a setTimeout routine there, to make sure the page has loaded completely (which it should've anyways).
Anyone has a solution?
Thanks in advance, Daniel

The extension and the content script both have a different global scope than the page, so if there's something like timer = 5 in the extension or on the page, that isn't visible in the content script.
See
https://developer.chrome.com/extensions/content_scripts
However, content scripts have some limitations. They cannot:
Use variables or functions defined by their extension's pages
Use variables or functions defined by web pages or by other content scripts
This answer discusses some options:
Share in-memory objects in Chrome extension content scripts?

I missunderstood the context of content.js
Content scripts execute in a special environment called an isolated
world. They have access to the DOM of the page they are injected into,
but not to any JavaScript variables or functions created by the page.
It looks to each content script as if there is no other JavaScript
executing on the page it is running on. The same is true in reverse:
JavaScript running on the page cannot call any functions or access any
variables defined by content scripts.
Isolated worlds allow each content script to make changes to its
JavaScript environment without worrying about conflicting with the
page or with other content scripts. For example, a content script
could include JQuery v1 and the page could include JQuery v2, and they
wouldn't conflict with each other.
Another important benefit of isolated worlds is that they completely
separate the JavaScript on the page from the JavaScript in extensions.
This allows us to offer extra functionality to content scripts that
should not be accessible from web pages without worrying about web
pages accessing it.

Related

Window.postMessage - Two pages, same URL

I'm using
window.postMessage({message: "Hello !"}, url);
to send a message from a Chrome Extension (i don't know if this is relevant) to a specific page in a window with multiples opened pages. I noticed that sometimes i have TWO pages with the same URL.
I have a simple question:
How can i be sure to which page is postMessage sending the message ?
I want to send the message to only one tab. Can i use anything else apart from the url to identify the it?
Thanks in advance !
Considering that you said you can modify the remote website's code, and I don't see how to fix the postMessage solution, here are a couple of alternatives. I would love to know if there is a way to fix the postMessage approach, as it is the recommended one from the docs!
First off, you will need to coordinate your scripts from a central background page, which can keep track of open tabs.
Custom DOM events
This is an old recommendation from Chrome docs, that was replaced with window.postMessage example. It is described here (disregard the old chrome.extension.connect API) and consists of firing a custom event in shared DOM.
So, a sample architecture would be a background page deciding which tab to post message to, and sending that tab a message via chrome.tabs.sendMessage, to which your content script listens with chrome.runtime.onMessage. The tab's content script can then communicate with the page using the above custom event technique.
One possible approach to keeping tack of tabs: have the tabs permission to be able to enumerate all open tabs with the chrome.tabs API. Your background page can then decide which tab to message based on URL.
Another possible approach, to eliminate need for the scary tabs permission, is to have your content scripts report to the background page with chrome.runtime.connect as soon as they are initialized. The background page then can keep track of all active instances of your script and therefore decide which tab to message.
Webpage connecting to your extension
This is a "modern" way of doing communication with one exact extension.
It is described in the Chrome docs here. You can define your extension as externally connectable from your webpage, and your webpage initiates a port connection with your background script.
Then, as above, you can track live ports and use them for communication, cutting out the content script middleman.

Google Chrome - Extension vs App

I want to modify chrome start page, change background and maybe logo.
I want to include jQuery in users local storage and load it while users page loads ( search page )
I never done anything with chrome so I want some way where to start. Do I go reading with apps or extensions?
As a rule of thumb: Choose an app if you want to develop an (independent) application that can stand on its own. If you want to interact with the browser (e.g. modify a web page), build an extension.
In your case, you definitely need an extension.
Change start page - use chrome_url_overrides in the manifest file to override newtab.
Locally store jQuery: Although it's possible to store jQuery in local storage, you're probably fine with packaging jQuery with your extension.
To add it to your user's "search page", you have to use a content script. By default, content scripts run in an execution environment that is different from the page (the document's DOM is shared though). Usually, this behavior is desired. If you really want to expose the jQuery library to the scripts in the page, take a look at this answer.
If you really want to load some script from a remote location and use it as a content script, read Chrome extension adding external javascript to current page's html.
I'm not sure what you mean by "change background and maybe logo". If you're referring to the browser's appearance, the only option to do that is by creating a theme. This must be a separate extension.

How to read custom variables from Chrome extension?

I'm making an extension for chrome to visualize the js structure but for some reason I am not able to access custom js variables from the extension. How could I read these vars/properties? like knowing if jQuery exist?
Content scripts run in isolated world:
They cannot:
Use variables or functions defined by web pages or by other content scripts
You should try injecting a <script src='injected.js'><script> (this script should be able to 'see' the web page defined variables and functions) to page header from content script and then establishing a communication between these two. Content script and injected script can talk simply over DOM (by ie. posting messages in a hidden div) or, better, using postMessage/addEventListener.

Communicate between isolated worlds (extension js and webpage js) on chrome extension

As you may know, js files on chrome extensions and pages cannot directly access each other and they run on isolated worlds.
However, I want to access some of the functions on a page and call those functions from the plugin.
And I do not want to make my own version of those functions.
I'm wondering if this is possible... Would appreciate all the answers.
EDIT: The functions are on the background page. Its a browser action extension.
more info: Basically, I have a context menu which creates a tab to submit url to a page. however, re-opening the page makes many tabs and opening so many pages takes time. So I am willing to call the javascript function on the page directly from the extension if one instance of the page is open already. And I have access to the page permission-wise.
TL;DR: Need a way to call a javascript function on a page (without copying it locally) from an extension.
Assuming you know the tab ID of the page whose function you want to call, you can use chrome.tabs.update(tabId, {url: 'javascript:functionNameHere()'}); from your extension page. This works because javascript: URLs are mapped to script execution in the main (i.e. page, not isolated) world.

Is it possible to overload geolocation functions using Chrome extension?

I want to overload navigator.geolocation.getCurrentPosition and navigator.geolocation.watchPosition to simulate geolocation during
development. Is it possible to do it using Google Chrome extension?
You mean something like this?
navigator.geolocation.getCurrentPosition = function(successCallback, errorCallback) {
successCallback({coords:{lattitude:10, longitude:20}});
}
If it is just for your own needs then it would be much easier to just do it in your js code.
If you want to make extension out of it then:
This code needs to be injected on every page of your app (via content script) and put inside dynamically created <script> tag, otherwise you will be inside content script sandbox and your overwritten function will not be visible to the parent page.
You would need to run this code before your app uses geolocation. There is no easy solution for this.
Now there's a chrome extension that does just that - the manual geolocation chrome extension. It tries its best to inject the script before any other one.
I found the extension what you want:)
https://chrome.google.com/webstore/detail/change-geolocation/njjpmclekpigefnogajiknnheheacoaj