Chrome Extension: how to change JS url before he starts loading - javascript

I wanna change src of js javascript before he starts loading using a Chrome Extension.
Manifest.json
{
"name":"Inject DOM",
"version":"1",
"manifest_version":2,
"permissions": [
"webRequest",
"webNavigation",
"http://*/*",
"https://*/*"
],
"content_scripts": [
{
"run_at": "document_end",
"matches": ["http://www.example.com/*"],
"js": ["inject_this.js"]
}
]
}
inject_this.js
I execute this code in various functions scenarios
var element = event.srcElement;
if(/production_path/.test(element.src)){
element.src = element.src.replace(/production_url/gi, "dev_path");
}
Scenario A
document.addEventListener('DOMNodeInserted', nodeInsertedCallback);
Scenario B
Executing this scenario into inject_this.js throw this TypeError:
Uncaught TypeError: Cannot read property 'onBeforeRequest' of undefined
Executing this in another js doesn't work
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
if(/production_url/.test(details.url)){
return {
redirectUrl: details.usl.replace(/production_url/gi, "dev_url")
}
}
},
{urls: ["<all_urls>"]},
["blocking"]);
Where do i put this snippet code ?
Scenario C
document.addEventListener('beforeload', doBeforeLoad , true);
but every time script.src is changed too late, the resource is loaded.
How can I change javascript url before he starts loading?

Your solution B should work.
Two conditions need to be met for this to work:
This code should go to a background script / event page.
You need appropriate permissions: "webRequest", "webRequestBlocking"
You probably also should not use it on <all_urls>, since your extension seems to be specific to a single site (from your manifest). Doing it on all URLs is going to slow your Chrome down and may lead to breaking other sites, consider using a restrictive match pattern like "http://www.example.com/*production_url*"

Related

chrome.idle is undefined in chrome extension

I'm trying to implement a simple idle detection in chrome.
I created an extension with this permission:
"permissions": [
"webNavigation",
"storage",
"tabs",
"*://*/*",
"idle"
],
"background": {
"scripts": ["js/background.js"]
},
"content_scripts": [
{
"run_at": "document_start",
"matches": [
"*://*/*"
],
"css": [
"css/content.css"
],
"js": [
"js/jquery.min.js",
"js/content.js"
]
}
]
and in content.js
$(function () {
console.log('init idle detection');
chrome.idle.queryState(5, function(newState){
//"active", "idle", or "locked"
if(newState === "idle"){ alert(newState); }
});
...init other things...
});
however, chrome.idle is always undefined.
According to documentation, content scripts cannot access idle API. Use it in background script (or popup script) and communicate with content script via messaging.
From the documentation:
Content scripts can access Chrome APIs used by their parent extension
by exchanging messages with the extension. They can also access the
URL of an extension's file with chrome.runtime.getURL() and use the
result the same as other URLs.
//Code for displaying <extensionDir>/images/myimage.png:
var imgURL = chrome.runtime.getURL("images/myimage.png");
document.getElementById("someImage").src = imgURL;
Additionally,
content script can access the following chrome APIs directly:
i18n
storage
runtime:
connect
getManifest
getURL
id
onConnect
onMessage
sendMessage
Content scripts are unable to access other APIs directly.
(Bold type on last line added)

Content script not executing in new window

I am trying to create a Chrome extension that, when clicked, opens a new incognito window and performs some DOM action on it. These are the files I'm using:
manifest.json
{
"manifest_version": 2,
"name": "SampleExtension",
"description": "",
"version": "1.0",
"incognito": "spanning",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["http://www.google.com"],
"js": ["myscript.js"]
}
],
"permissions": [
"tabs",
"activeTab",
"http://www.google.com"
]
}
popup.js
chrome.windows.create({
"url": "http://www.google.com",
"focused": true,
"incognito": true
});
chrome.tabs.executeScript(null, {
"file": "myscript.js",
"run_at": "document_end",
"all_frames": true
});
myscript.js
document.querySelector('a[target]').click();
The extension opens the new window, but my content script doesn't seem to be executing. Any thoughts?
Edit: Added "incognito": "spanning" to the manifest. Still doesn't work, however.
First of all, I understand that you have enabled to run in Incognito Mode. Extensions are disabled by default and, hence, it would not run otherwise.
Secondly, your match pattern needs to end with a slash:
"matches": ["http://www.google.com/"],
Thirdly, Google will redirect you to its https version, hence I would improve the match pattern like this:
"matches": ["*://www.google.com/"],
Still, it didn't work for me as I was redirected to my local Google domain. Hence, I had to do add more:
"matches": [
"*://www.google.com/*",
"*://www.google.com.sg/*"
],
Also, I added the final wildcard, because Google was adding some ?urlParams that I had to match too. And this made it work. Note that I tried with other pages like "*://www.stackoverflow.com/*", and it was easier than Google :)
In case your Google page was just a test, I'd advise to use some less redirected pages to test with.
A final note: I do not think it's possible to use the wildcard for the domain (I tried). However, you can request all the main domains, or request all_pages and then add the logic for Google only on my_script.js to decide whether to execute the action or not. (However, this last piece is not ideal).
Edit post comments:
It seems your function fails because the element is not loaded yet. An easy way to solve this is by doing an interval which checks whether the element is on the page. When it finds it, clicks it and removes the interval.
// Function which clicks element if existing and clears interval after doing it.
var clickLink = function() {
if (document.querySelectorAll('a[target]').length > 0) {
clearInterval(waitAndClick); // stop interval
document.querySelector('a[target]').click(); // click element.
}
}
// Run click function every second, until it clicks it.
var waitAndClick = setInterval(clickLink, 1000);

Auto start chrome extension

I am trying to make a chrome extension that redirects to a other page when it's loaded. For example, if it's google.nl, go to google.nl?example I managed to get that working, but only when i press the extension button. I want to run the script from the background.js but i get the error:
Uncaught TypeError: Cannot read property 'onBeforeRequest' of undefined
Why do i wan't to reload? Well i don't. it's just to test. The original plan is reading the URL and put the open graph data in my extension.
manifest (part)
"content_scripts": [{
"matches": [
"<all_urls>"
],
"js": ["background.js"]
}],
"permissions": [
"tabs",
"activeTab",
"webRequest"
],
"background": {
"scripts": ["background.js"]
}
background.js
chrome.webRequest.onBeforeRequest.addListener(function(a) {
if (a.url.indexOf("http://www.google.com/") >= 0) {
reloadExtensions();
chrome.tabs.get(a.tabId, function(b) {
if ((b.selected == false)) {
chrome.tabs.remove(a.tabId)
}
});
return {redirectUrl: chrome.extension.getURL("close.html")}
}
return {cancel: false}
}, {urls: ["http://reload.extensions/"],types: ["main_frame"]}, ["blocking"]);
iirc the docs say you need to put all the URL's you want to redirect in the permissions array.
If you don't you will see the following error
Checkout Catblock example https://developer.chrome.com/extensions/samples#search:webrequest by removing
I don't think you need the content script parts at all, in fact I suspect that is where you are seeing the error.

develop screenshot chrome extension

i saw a lot of answers here but no one is what i'm looking for.
i want to take screenshot from chrome extension just for the screen i see at the first time without scrolling the page.
and "alert" the created file base64 path.
i have all the right permissions:
"permissions": [
"activeTab",
"tabs" ,
"storage",
"unlimitedStorage",
"browsingData",
"notifications",
"http://*/*",
"https://*/*",
"file://*/*",
"background" // added after i got the answer
],
"background": { // added after i got the answer
"scripts": [
"js/background.js"
]
},
in my manifest.json
i also have the code:
$(document).ready(function() {
alert("1");
chrome.tabs.captureVisibleTab(null, {}, function (image) {
alert("2");
});
});
i got 1 all the time but 2 i never get and i don't know why. please help..
thanks ..
UPDATE
that's the missing part (background.js)
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
chrome.tabs.captureVisibleTab(
null,
{},
function(dataUrl){
sendResponse({imgSrc:dataUrl});
}); //remember that captureVisibleTab() is a statement
return true;
}
);
and then :
chrome.tabs.captureVisibleTab(null, {}, function (image) {
// alert("2");
alert(response.imgSrc);
});
You can't do extension API call in content script.Try to use use message passing if you really want to trigger this function in content script.
And please note that the permission requirement of tabs.captureVisibleTab() has been updated since chrome rev.246766.
Extension need to have '< all_urls >' permission, or been granted the
'activeTab' permission to be allowed to use tabs.captureVisibleTab().
Developer doc doesn't mention it.
manifest.json
"permissions": [
"activeTab",
"tabs" ,
"storage",
"unlimitedStorage",
"browsingData",
"notifications",
"http://*/*",
"https://*/*",
"file://*/*",
"<all_urls>"
]
Try to execute this code below in background page and screenshot capturing will work as expected.
chrome.tabs.captureVisibleTab(null,{},function(dataUri){
console.log(dataUri);
});
screenshot
It actually does not work on Google pages as on the Extensions page, were it looks very natural to test your extension while developing.
(Should be a way to test that before taking the snapshot, I think...)

Communication between scripts in Chrome Extension

I know there are many variations of this question already in existence here, but none of them seem to work for me.
Details:
I'm writing an extension that pulls some email data from emails you send in gmail. In order to achieve this I am using this version of Gmailr https://github.com/joscha/gmailr.
In effect, I have three content scripts: Gmailr.js and main.js (which are pretty much identical to those in the link above) allow me to pull out the information I'm looking for. Then content.js I use to send a message to the background page of the extension.
The problem is that from gmailr.js and main.js I cannot use any of the Chrome APIs, and I'm not really sure why, so I can't send messages from these back to the background page.
That is why I made content.js which can communicate with the background page. However, it does not seem to be able to see anything the other content scripts do. For example, main.js inserts a div at the top of the page. When I try to attach an event listener to a button in this div from content.js, I am told that no such element exists.
How can I get the data pulled out by main.js to be seen by content.js? (I also tried to put the data in local storage, then trigger a custom event listener to tell content.js to read local storage, but no luck because they don't seem to be able to hear each other's event being triggered).
Any insight or alternatives are much appreciated.
(I can post code if necessary, but it's fragmented and long)
My manifest file:
{
"manifest_version": 2,
"name": "Email extractor",
"description": "Extracts data from emails",
"version": "1.0",
"background": {
"script": "background.js"
},
"content_scripts": [
{
"matches": [
"*://mail.google.com/*",
"*://*/*"
],
"js": [
"lib/yepnope.js/yepnope.1.5.4-min.js",
"lib/bootstrap.js",
"main.js",
"gmailr.js",
"content.js"
],
"css": [
"main.css"
],
"run_at": "document_end"
}
],
"permissions": [
"tabs",
"storage",
"background",
"*://mail.google.com/*",
"*://*/*"
],
"browser_action": {
"default_icon": "img/icon.png",
"default_popup": "popup.html"
},
"web_accessible_resources" : [
"writeForm.js",
"disp.js",
"/calendar/jsDatePick.min.1.3.js",
"/calendar/jsDatePick_ltr.min.css",
"lib/gmailr.js",
"lib/jquery-bbq/jquery.ba-bbq.min.js",
"content.js",
"main.js",
"background.js"
]
}
This is main.js:
Gmailr.init(function(G) {
sender = G.emailAddress();
G.insertTop($("<div id='gmailr'><span></span> <span id='status'></span>)");
el = document.getElementById("testid");
el.addEventListener('click', mg, false);
var status = function(msg) {
G.$('#gmailr #status').html(msg); };
G.observe(Gmailr.EVENT_COMPOSE, function(details) {
....
status(" user: " + user);
console.log('user:', user);
//now try to send a message to the background page
//this always returns the error that method sendMessage does not exist for undefined
chrome.runtime.sendMessage({greeting: "test from gmailr"}, function(response) {
console.log("did it send?");
});
});
});
gmailr.js is quite long and is also not my own code but it can be seen here: http://pastebin.com/pK4EG9vh
Hi perhaps 3 likely reason to your problem :
The way you send messages to bgp from main.js and gmailr.js are perhaps wrong because you must arrive to communicate from any content script to your bgp. (in your manifest content script key the gmailr.js is missing). Show us your code it would help.
You seems to have a problem with the moment you search from content.js to access to the element created in main.js. Do you try to access your element with the jQuery $("").on() method ? A simple test must be to declare a function in one cs and to use it in another. If it's not working it's a manifest problem. The order you declare .js file in manifest content script key is important also.
try to in the manifest content script array "run_at":"document_end"
Hope it help !

Categories

Resources