Get 2 userscripts to interact with each other? - greasemonkey

I have two scripts. I put them in the same namespace (the #namespace field).
I'd like them to interactive with another.
Specifically I want script A to set RunByDefault to 123. Have script B check if RunByDefault==123 or not and then have script A using a timeout or anything to call a function in script B.
How do I do this? I'd hate to merge the scripts.

The scripts cannot directly interact with each other and // #namespace is just to resolve script name conflicts. (That is, you can have 2 different scripts named "Link Remover", only if they have different namespaces.)
Separate scripts can swap information using:
Cookies -- works same-domain only
localStorage -- works same-domain only
Sending and receiving values via AJAX to a server that you control -- works cross-domain.
That's it.
Different running instances, of the same script, can swap information using GM_setValue() and GM_getValue(). This technique has the advantage of being cross-domain, easy, and invisible to the target web page(s).
See this working example of cross-tab communication in Tampermonkey.
On Chrome, and only Chrome, you might be able to use the non-standard FileSystem API to store data on a local file. But this would probably require the user to click for every transaction -- if it worked at all.
Another option is to write an extension (add-on) to act as a helper and do the file IO. You would interact with it via postMessage, usually.
In practice, I've never encountered a situation were it wasn't easier and cleaner to just merge any scripts that really need to share data.
Also, scripts cannot share code, but they can inject JS into the target page and both access that.
Finally, AFAICT, scripts always run sequentially, not in parallel. But you can control the execution order from the Manage User Scripts panel

Related

Is it safe to use fetch with credentials from a content script?

Consider this scenario:
A content script wants to upload a file. I would prefer this operation to be done from my service/background script, but passing a File to that side via messages seems to be somewhat impossible without weird workarounds.
This is a good reference for the workarounds available: Passing FormData/File Object from content script to background script in chrome extension with Manifest V3
Workaround 1 seems bad, since it will require to break up the request which is not compatible with the backend API. Workaround 2 seems insecure, since the host web page will definitely be able to send rogue messages to an embedded iframe as it will share context.
I'm considering having the content script perform the upload directly like this:
The content script loads the authentication secret from extension storage (chrome.storage.sync or chrome.storage.local depending on login persistence mode).
It calls fetch directly to upload the form data.
Is that safe?
One hazard I had in mind was that a host page could hook window.fetch to intercept the credentials. That doesn't seem possible after my testing (the content script has a separate fetch defined in its own isolated environment). Is there anything else to watch out for?

Is it possible for Tampermonkey to share one storage on different websites?

Similar to this, but has more details.
"share"ing is expected to be done by one script.
"storage" is which GM_{g,s}etValue use.
"different websites" are those which have different origins.
My scheme now:
On website A, I insert an iframe of site B, and synchronize storage by postMessage.
Information I've got:
From this, it seems that Tampermonkey used to support share data cross-originly.
As mentioned by wOxxOm, in order for 2 domains to share data via GM storage API, the script must run on both e.g. via #match.
However, in Tampermonkey the domains will get access to the data at the time script was injected.
Update: As pointed out by wOxxOm, "Both Tampermonkey/Violentmonkey provide real-time access to the real values. They do it by propagating the change to all tabs/frames where this script instance runs."
You can also use GM_addValueChangeListener() to listen to changes to the storage.
GM_addValueChangeListener()
Adds a change listener to the storage and returns the listener ID.
'name' is the name of the observed variable.
The 'remote' argument of the callback function shows whether this value was modified from the instance of another tab (true) or within this script instance (false).
Therefore this functionality can be used by scripts of different browser tabs to communicate with each other.
Note: In Greasemonkey & FireMonkey, the asynchronous GM.getValue() would always get the current up-to-date data.

Chrome Extension: How to inject a content script into an iframe's page

I'm working on a Chrome extension that among other things supports a page with multiple dynamically created iframes in it, pointing to multiple different domains. I need to load a content script into each of those iframes, ideally without loading it into every page.
There's a separate content script that's running on all those iframe pages, which can detect that it's in an applicable iframe, and I'd like it to load this other content script. After some wrangling, it can get the frameId of that iframe, but chrome.tabs.executeScript() takes only tabId, not frameId, so the script loads in the top-level page, not the desired iframe.
Note that the script I want to inject needs to run as a content script, with access to the available Chrome APIs.
Is it possible to do this? How?
Update: Ach, you're of course right wOxxOm, that "frameId can be specified inside executeScript's second parameter". Thank you again, make that an answer and I'll accept it. I need to read more carefully, apparently. I'm a long-time programmer, but new to Chrome extensions, there's a lot to absorb.
Secondary question: It appears that I need to add <all_urls> or http://*/* and https://*/*, permission to the manifest for this to be allowed. The main content_script that's doing this has similar match patterns, and I could add this secondary script there too, but it's actually only needed for pages shown in these iframes, so this seems better to me. Are there other downsides to doing it this way, or is there some better approach, other than xhr/eval?

Jmeter script recorder and recording for multiple users/threads

I created in Jmeter a Test Plan that looks like that:
the idea is to keep track of all the APIs the browser access between two pages. So, I open the localhost:63948/Home/LoginEmailSenha and I go until the other page I want. Under the Recording Controller label I get the list of the APIs.
But what can I do so that it feels like there isn't only one person accessing but actually 200? I tried to change the Number of Threads(users) at the Thread Group but nothing seems to change as I want to get the API errors that occured because there are too many people.
HTTP(S) Test Script Recorder is used to create a test scenario "skeleton", it basically stands between browser and application under test, captures requests and generates relevant HTTP Request samplers.
If you need to mimic 200 users you need to replay the recorded scenario with increased number of threads.
References:
JMeter Proxy Step by Step
Building a Web Test Plan
Building an Advanced Web Test Plan
If your target is to simulate the load during recording time you can take a look at JMeter Chrome Extension, it has FollowMe Mode when any your online activity is replicated with a given number of virtual users.

How can I pass a message from outside URL to my Chrome Extension?

I know there's a way for extensions and pages to communicate locally, but I need to send a message from an outside URL, have my Chrome Extension listen for it.
I have tried easyXDM in the background page, but it seems to stop listening after awhile, as if Google "turns off" the Javascript in the background page after awhile.
I think you may try some walk around and build a site with some specific data structure, and then implement a content script which will look for this specific that specific data structure, and when i finds one it can fetch the data you want to be passed to your extension.
Yes, you need a content script that communicates with the page using DOM Events.. Instructions on how to do that are here:
http://code.google.com/chrome/extensions/content_scripts.html#host-page-communication

Resources