Chrome extensions communication (content scripts) - javascript

I got 2 extensions in Chrome, both only uses content scripts at the moment. Both extensions listen on websocket for messages from the server. Also they both get the same message "same" (obviously a minimal difference) time. After they got the message they both process it and at the end they both have a result which is an int number.
What I would like to do is sending this number from extension A to extension B and from ext. A to ext. B so they both have the other's result.
I've really tried to google a solution for this, but I couldn't find any. Also I would like to avoid sending the results back to the server and then back to the extensions again.
Is there any way (preferably only JS) to do this?
Thanks!

This has been discussed here: Can Chrome extensions communicate with each other?
you can use this api: https://developer.chrome.com/extensions/messaging#external
chrome.runtime.sendMessage(otherExtensionId, {msg: 'hello'},
function(response) {
if (response.msg='hi')
chrome.runtime.sendMessage(otherExtensionId, {msg: 'how are you?'});
});
and in the other extension:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (request.msg=='hello') {
sendResponse({msg: 'hi'});
}else ifif (request.msg=='how are you?'){
doSomething()
}
});
also for another means of communication, you can create an invisible div inside your page, and have both extensions constantly checking if it's contents change.

Related

How to obtain and manipulate the requestheaders using javascript in console?

I've encountered a paywall and I'm trying to bypass it using javascript in the console. I did some research and found a few different approaches, one of which is changing the requestheader in order to make a given website believe that you got there through a twitter link (thus allowing you to view the content for free). The function I use aims to change the referer by listening to the onBeforeSendHeaders event as specified on https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onBeforeSendHeaders. It looks like the following (NOTE: This function is typed and executed directly inside of the devtools console):
function setReferer(x){
x.requestHeaders = x.requestHeaders.filter(function(header){
if(header.name === 'Referer'){
return false
return true
)}
x.requestheaders.push(
{
"name: "Referer",
"value": "https://t.co/" //Twitter website
}
return {requestHeaders: x.requestHeaders};
}
//this example uses chrome browser
chrome.webRequest.onBeforeSendHeaders.addListener(setReferer,
{
urls: ["<all_urls>"],
types: ["main_frame"], },
["requestHeaders", "blocking", "extraHeaders"] //extraHeaders meant to bypass CORS protocol
);
Unfortunately upon refreshing the window, this approach gives me folllowing error:
GET <some_url> net:ERR_BLOCKED_BY_CLIENT
Behind this error is the URL to the source code of the article, which I was able to load and copy into word, so I got the article I was looking for anyway. However I wasn't able to view it inside of the browsers main frame. Note that I am doing this only for the purpose of polishing my coding skills. I am trying to get a better understanding of the more complicated facets of the HTTP protocol, especially the way headers get sent clientside and interpreted serverside. If anyone knows more about the subject or knows / has a resource that he or she wants to share, this would me greatly appreciated!

Why does my site cert become insecure after a JQuery AJAX call?

I've got a website that uses JQuery to grab information from an API located at: https://api.lootbox.eu/. The website I'm making has a cert that's been created and installed with Let's Encrypts tools. (I followed a tutorial on DigitalOcean to set it up)
Now, when I click a button to make the API call and update the website contents, Google Chrome then deems the cert "Not Secure" (shown in the address bar).
Here's my code.
//when the page has fully loaded
$(document).ready(function(){
function parseResponse(data)
{
//parsing JSON...
//lets avoid the "data.data"
response = data.data;
//set the user's general profile details
$("#user_avatar").attr("src", response.avatar);
$("#comp_rank_img").attr("src", response.competitive.rank_img);
$("#comp_rank").html(response.competitive.rank);
$("#qp_level").html(response.level);
$("#qp_playtime").html(response.playtime.quick);
$("#comp_playtime").html(response.playtime.competitive);
$("#qp_wins").html(response.games.quick.wins);
$("#comp_total_games").html(response.games.competitive.played);
$("#comp_wins").html(response.games.competitive.wins);
$("#comp_losses").html(response.games.competitive.lost);
}
//goes to the Overwatch API and grabs the JSON data for processing.
function processAjax()
{
$.ajax({
url: "https://api.lootbox.eu/pc/us/JuicyBidet-1292/profile"
}).then( function(response){
parseResponse(response);
});
}
//set up the button event listener
$("#submit").click(function(e){
//prevent the button from reloading the page
e.preventDefault();
//run the ajax grabber/processor
processAjax();
});
});
(I need to learn how to format code properly in SO questions...).
I don't get any other errors in my Chrome console (other than "favicon" 404ing - which is unrelated).
I've also tried the website in Microsoft Edge and I get the following in their Console:
SCRIPT7002: XMLHttpRequest: Network Error 0x800c0019, Security certificate required to access this resource is invalid.
I'm thinking either the problem is with my code, or now that I've checked, the API website's cert is invalid in both Chrome and Edge.
Any help would be appreciated. Thanks.
(I'm aware the code is scrappy, I'm learning)
I get this warning "This server could not prove that it is api.lootbox.eu; its security certificate expired 6 days ago"
This could happen because of one among following reasons.
1.Certificate is not issued by the third party site.
2.The third party site certificate is not updated.
3.The third party and browser connection is not secure.
The insecure error is because if a site is loaded over https the browser expects all subsequent calls made by the page will be secure, but in your case you are calling a URL http://api.lootbox.eu/pc/us/JuicyBidet-1292/profile which uses http:// and is insecure thus making your website insecure.
Solution
Use https url's everywhere in your pages.

Is there an alternative to preprocessorScript for Chrome DevTools extensions?

I want to create a custom profiler for Javascript as a Chrome DevTools Extension. To do so, I'd have to instrument all Javascript code of a website (parse to AST, inject hooks, generate new source). This should've been easily possible using chrome.devtools.inspectedWindow.reload() and its parameter preprocessorScript described here: https://developer.chrome.com/extensions/devtools_inspectedWindow.
Unfortunately, this feature has been removed (https://bugs.chromium.org/p/chromium/issues/detail?id=438626) because nobody was using it.
Do you know of any other way I could achieve the same thing with a Chrome Extension? Is there any other way I can replace an incoming Javascript source with a changed version? This question is very specific to Chrome Extensions (and maybe extensions to other browsers), I'm asking this as a last resort before going a different route (e.g. dedicated app).
Use the Chrome Debugging Protocol.
First, use DOMDebugger.setInstrumentationBreakpoint with eventName: "scriptFirstStatement" as a parameter to add a break-point to the first statement of each script.
Second, in the Debugger Domain, there is an event called scriptParsed. Listen to it and if called, use Debugger.setScriptSource to change the source.
Finally, call Debugger.resume each time after you edited a source file with setScriptSource.
Example in semi-pseudo-code:
// Prevent code being executed
cdp.sendCommand("DOMDebugger.setInstrumentationBreakpoint", {
eventName: "scriptFirstStatement"
});
// Enable Debugger domain to receive its events
cdp.sendCommand("Debugger.enable");
cdp.addListener("message", (event, method, params) => {
// Script is ready to be edited
if (method === "Debugger.scriptParsed") {
cdp.sendCommand("Debugger.setScriptSource", {
scriptId: params.scriptId,
scriptSource: `console.log("edited script ${params.url}");`
}, (err, msg) => {
// After editing, resume code execution.
cdg.sendCommand("Debugger.resume");
});
}
});
The implementation above is not ideal. It should probably listen to the breakpoint event, get to the script using the associated event data, edit the script and then resume. Listening to scriptParsed and then resuming the debugger are two things that shouldn't be together, it could create problems. It makes for a simpler example, though.
On HTTP you can use the chrome.webRequest API to redirect requests for JS code to data URLs containing the processed JavaScript code.
However, this won't work for inline script tags. It also won't work on HTTPS, since the data URLs are considered unsafe. And data URLs are can't be longer than 2MB in Chrome, so you won't be able to redirect to large JS files.
If the exact order of execution of each script isn't important you could cancel the script requests and then later send a message with the script content to the page. This would make it work on HTTPS.
To address both issues you could redirect the HTML page itself to a data URL, in order to gain more control. That has a few negative consequences though:
Can't reload page because URL is fixed to data URL
Need to add or update <base> tag to make sure stylesheet/image URLs go to the correct URL
Breaks ajax requests that require cookies/authentication (not sure if this can be fixed)
No support for localStorage on data URLs
Not sure if this works: in order to fix #1 and #4 you could consider setting up an HTML page within your Chrome extension and then using that as the base page instead of a data URL.
Another idea that may or may not work: Use chrome.debugger to modify the source code.

Porting a chrome extension to firefox

First of all: This is no duplicate of "how to automaticly convert a chrome extension"...
I wrote a complex chrome extension which is quite popular. So a lot of people asked me to publish a firefox - version.
I am currently in a quite early state of analyzing the difficulties I might run into. I am able to map most chrome-specific commands to others in firefox.
Just one topic is unsolved until now:
Chrome uses content-scripts and background-scripts.
the communication works that way:
Content-Script:
chrome.runtime.sendMessage(
{
Action: "LoadAll"
}, function(response)
{
mySetting= response.Setting;
}
);
background-script:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse)
{
if (request.Action === "LoadAll")
{
sendResponse({Setting: "hello out there!"});
return true;
}
)
});
(please ignore if I might have missed a bracket)
How is this communication been done on firefox extensions? Or does FF recommend a complete different approach?
If there is no "Take this command" - answer, a link to a more in-depth-explanation would be nice.
The thing you are looking for is Message Manager. We are developing a big and complicated extension for about 2 years for Fx and recently made a good Chrome port of it. Messaging process differs strongly in Fx and Chrome. Think of it like you inject a content script in window/browser/tab, which has few things in common with content scripts in Chrome, and then talk to your extension code from injected script via sendSyncMessage/sendAsyncMessage. I hope this helps.

gapi.client.load not working

I have the following code, which is supposed to be a simple example of using the google api javascript client, and simply displays the long-form URL for a hard-coded shortened URL:
<script>
function appendResults(text) {
var results = document.getElementById('results');
results.appendChild(document.createElement('P'));
results.appendChild(document.createTextNode(text));
}
function makeRequest() {
console.log('Inside makeRequest');
var request = gapi.client.urlshortener.url.get({
'shortUrl': 'http://goo.gl/fbsS'
});
request.execute(function(response) {
appendResults(response.longUrl);
});
}
function load() {
gapi.client.setApiKey('API_KEY');
console.log('After attempting to set API key');
gapi.client.load('urlshortener', 'v1', makeRequest);
console.log('After attempting to load urlshortener');
}
</script>
<script src="https://apis.google.com/js/client.js?onload=load"></script>
except with an actual API key instead of the text 'API_KEY'.
The console output is simply:
After attempting to set API key
After attempting to load urlshortener
but I never see 'Inside makeRequest', which is inside the makeRequest function, which is the callback function for the call to gapi.client.load, leading me to believe that the function is not working (or failing to complete).
Can anyone shed some light on why this might be so and how to fix it?
Thanks in advance.
After spending hours googling the problem, I found out the problem was because I was running this file on the local machine and not on a server.
When you run the above code on chrome you get this error in the developer console "Unable to post message to file://. Recipient has origin null."
For some reason the javascript loads only when running on a actual server or something like XAMPP or WAMP.
If there is any expert who can shed some light to why this happens, it would be really great full to learn.
Hope this helps the others noobies like me out there :D
Short answer (http://code.google.com/p/google-api-javascript-client/issues/detail?id=46):
The JS Client does not currently support making requests from a file:// origin.
Long answer (http://en.wikipedia.org/wiki/Same_origin_policy):
The behavior of same-origin checks and related mechanisms is not well-defined
in a number of corner cases, such as for protocols that do not have a clearly
defined host name or port associated with their URLs (file:, data:, etc.).
This historically caused a fair number of security problems, such as the
generally undesirable ability of any locally stored HTML file to access all
other files on the disk, or communicate with any site on the Internet.

Categories