Trying to inject CSS after DOM loaded (Writing Chrome Extension) - javascript

I'm trying to write a Chrome Extension that just adds a CSS file to the end of a page's css definitions.
Google's documentation says that I can just use the function chrome.tabs.insertCSS() to add css to a page, but running it from a content_script included javascript file does nothing.
I'm trying two separate methods as documented on Google's site. I have an alert() statement to tell me where in the script I am, but it never runs the final alert. This makes me think that my script may be crashing somewhere in the middle.
Here are my source files:
manifest.json
{
"name": "Custom CSS to GOOGLE",
"version": "1.0",
"description": "The first extension that I made.",
"content_scripts": [
{
"matches": ["http://*/*"],
//"js": ["style_injector.js"],
"js": ["inject.js"],
"css": ["newstyle.css"]
}
],
"permissions": [
"tabs", "http://*/*"
]
}
inject.css
alert("newpage");
chrome.tabs.executeScript(null, {code:"document.body.bgColor='red'"});
chrome.tabs.insertCSS(
null,
{
code:"body{background:red;}"
}
);
alert("finishpage");

You can't call chrome.tabs.* API from a content script. You need to do it from a background page. If you need to communicate between a content script and a background page there is message passing available.
PS. Things like "This makes me think that my script may be crashing somewhere in the middle." could be easily checked by looking at the console (for content scripts it is just a regular console in a tab, Ctrl+J).

"I'm trying to write a Chrome Extension that just adds a CSS file to the end of a page's css definitions"
You might need to add the !important flag to the css you are changing:
When the browser is displaying an HTTP page and the user clicks this extension's browser action, the extension sets the page's bgcolor property to 'red'. The result, unless the page has CSS that sets the background color, is that the page turns red.
...the !important flag is the only way to change some things but you may have to write js to override other styles, check this
As serg said, the background.html page is where you use the injectCSS api:
/* in background.html */
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null,
{code:"document.body.bgColor='red'"});
});
/*in manifest.json */
"permissions": [
"tabs", "http://\*/*"
],

Related

Trying to access iFrame through source URL but showing up blank [duplicate]

I want to ask is there ANY way or extension that can pre-highlight text within the iframe whenever a new window is opened containing iframe? I have tried many extension but none of them works.
I need to filter out content based on certain keywords and the content is within iframe. I can do it with CTRL+F but there are many keywords like 10-15 within each article to be found. So it makes my job very tough and time consuming. Few extensions that I have tried from chrome are multi highlighter, pearls, FF but none of them seems to work.
I also know the reason why these extension can't access content within the iframe i.e. due to cross origin policies.
But I also remember around an year ago I worked with chrome extension named 'Autofill' that could pre-select form elements whenever I opened new chrome window containing iframe.
So is there any work around?
You can set your extension permission to run content scripts in all frames as document at http://developer.chrome.com/extensions/content_scripts.html#registration by setting all_frames to true in the content scripts section of your manifest file. Adding to Google's example from that page, part of your manifest file might look like
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"css": ["mystyles.css"],
"js": ["jquery.js", "myscript.js"],
"all_frames": true
}
],
...
}
You'll need to be careful since your content scripts are going to be inject into the page once for the parent page and one for each iFrame on the page. Once your content script is injected into all frames on the page you can work your magic with finding and highlighting text.
if (window === top) {
console.log('Running inside the main document', location.href);
} else {
console.log('Running inside the frame document', location.href,
[...document.querySelectorAll('*')]);
}

How to predit in chrome extension html before it is displayed

I am building a chrome extension that is also supposed to remove parts of HTML.Thing is, I need to do that when I receive the html from the server BUT before it is displayed.If I use run at for document end and try to modify the HTML it'll look ugly because the page will load and then change, and I want to remove html parts and edit them before it is displayed.
For example, if my extension will need to clear the whole body tag I will need a script like that in runbefore.js:
document.body.innerHTML = "";
But when I use content scripts -
"content_scripts": [
{
"matches": ["https://www.website.com/*"],
"js": ["runbefore.js"],
"run_at": "document_end"
}
It loads the page and only then clears the whole page, and I want to clear the body tag and only then display it.If I use document_start it won't even do anything.
How do I resolve that issue ?
You can change run_at property in your manifest to document_start in your manifest.
You can get more information about this property here.

How to turn on/off chrome extension using local storage in background page?

I've been reading a lot of other answers on here for similar questions but I'm still having trouble. I want the user to be able to turn off my chrome extension at any point by clicking on the icon. The extension that I wrote will execute once at each page load, so when the icon is clicked, it should disable the code from occurring on next page load. When the icon is clicked, it either turns grey to show that it's off, or back to color. This part of the code works, but it is also supposed to be updating a localStorage variable to off/on. Then when the user starts a new page and the content script runs again, the content script checks the localStorage variable and, ideally, will only execute if the variable is set to "on." But instead, it executes every time, even when the icon is grey. I checked the localStorage in the console and the variable says "on" every time. What am I doing wrong?
P.S. I did also check to see whether the content script was always setting the storage variable to "on" (because it checks to see if there is no variable saved yet), but that wasn't the case.
Manifest.json
{
"manifest_version": 2,
"name": "My Extension",
"version": "0.1",
"icons":
{
"128": "128.png",
"48": "48.png",
"16": "16.png"
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["jquery-3.1.1.min.js", "content.js"]
}
],
"browser_action": {
"default_icon": "16.png"
},
"background": {
"scripts": ["background.js"],
"persistent": true
},
"permissions": ["tabs", "storage"],
"web_accessible_resources": [
"spritesheet.png"
]
}
Background Page
chrome.browserAction.onClicked.addListener(function(tab) {
//if on, turn off
if (localStorage.onoff == "on") {
chrome.browserAction.setIcon({path:{"16": "16grey.png", "48": "48grey.png","128": "128grey.png"}});
localStorage.onoff = "off";
//if off, turn on
} else {
chrome.browserAction.setIcon({path:{"16": "16.png", "48": "48.png","128": "128.png"}});
localStorage.onoff = "on";
}
});
Content script
if (!localStorage.onoff) {
localStorage.onoff = "on";
}
if (localStorage.onoff == "on") {
//execute the extension
}
Use chrome.storage.local
You can not use localStorage to move data between your background script and your content script. In your content script, it will access the localStorage of the page/domain for the page in which you have injected the script. This is as it should be. Your content script should be for affecting the page into which it is injected. Thus, the functionality that is not part of the Chrome APIs should work more, or less, as it would if written in a page script.
To set a data value in your background script prior to your content script loading which your content script can read, you should use chrome.storage.local.
You can set it with chrome.storage.local.set():
chrome.storage.local.set({
onOff: 'on'
}, function(){
console.log('Data saved');
});
You can read it with chrome.storage.local.get():
chrome.storage.local.get({
onOff: 'off'
}, function(data) {
if(data.onOff === 'on') {
//Do your code
}
});
Other issues
Loading jQuery:
You are loading jQuery on every page. Particularly given that you are injecting your scripts on every page, you should seriously consider not using jQuery. jQuery is 85KiB of minimized code. That is a fairly heavy burden to add to every single page the user loads.
One of jQuery's primary benefits, cross browser compatibility, is not needed given that you are writing an extension which, very specifically, can only function in one browser (or a very small number of browsers). Thus, this primary benefit has no value to your code.
Everything that you are doing with jQuery in your code can be written in vanilla JavaScript. This will normally cost you very little additional code, particularly when compared to the 85KiB of minimized jQuery code. Thus, while you might be saving a bit of coding, it is at the cost of forcing your users to have 85KiB of jQuery code loaded and evaluated on every single page they view.
I don't know what you are using jQuery for in your code. It could be that it is actually needed for something. On the other hand, it is much more likely that loading it is just a convenience for you (Some people use it just because it makes their code look cleaner). If you are using just some basic jQuery, you may find the queryAll() function written in this other answer of mine to give you some of the functionality that is often looked for.
Injecting your content script in <all_urls>:
You should seriously consider if injecting into every single page the user visits is needed. It quite possibly is. You have given no indication what your code is doing. Thus, there is no way for us to tell. If all URLs are not actually affected by your extension, please look into limiting the URLs into which your code is injected.
In addition, you are turning on and of your content script functionality using a browserAction button. As such, you should consider using tabs.executeScript() to only inject your content script(s) when your extension is turned on.

injecting multiple css and javascript files into a page with chrome extension onClick

I am making a chrome extension that inserts multiple css and javascript files.
I was previously using content scripts but now I want to insert the script and css onClick.
I tried just injecting my main script script.js in my background and keeping the rest of my css files associated with this script in my content script section in manifest. However, when I tried this in my extension it did not work. Should I execute and insert all my content and css in my background and if so in what order because one script or css has to be inserted or executed inside another.
I looked at " Injecting multiple scripts through executeScript in Google Chrome" however I don't know if their is a easier way in my situation and I do not know if that articles applies to css.
Here's part of my manifest:
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"css": ["styles.css", "tipped.css"],
"js": ["jquery-1.9.1.js", "jquery-highlight1.js", "spinners.min.js", "tipped.js","script.js"],
"run_at": "document_end"
}
],
"permissions":[
"activeTab"
],
Here is my background script:
chrome.browserAction.onClicked.addListener(function(activeTab) {
chrome.tabs.executeScript(null, {file: "script.js"});
});

Getting a content script to append image on page load

I've just start out learning how to make extensions for google chrome. I have a very basic understanding so far, so I wanted to try something small.
Right now I am trying to get an image to append to a specific div on a specific page everytime that page loads. The extension loads properly but, the javascript code never seems to run and the image never gets loaded.
This is the manifest.json file I have so far:
{
"manifest_version": 2,
"name": "Icon Creator",
"description": "Creates a custom icon for page",
"version": "1.0",
"content_scripts": [
{
"matches": ["file:///home/tijko/documents/learning/javascript/test_page.html"],
"css": ["sample.css"],
"js":["trial.js"]
}
],
"icons": {"icon": "icon.jpg"},
"web_accessible_resources":["trial.js"]
}
and the javascript:
var test = function() {
custom_icon = document.createElement("img");
target = document.getElementById("location");
custom_icon.src = "icon.png";
target.appendChild(custom_icon);
}
test()
Are you trying to load your own extension's icon.png? Right now you are trying to load icon.png on the domain and path of the local page. Instead, you should do:
custom_icon.src = chrome.runtime.getURL("icon.png");
to refer to your extension's icon.png.
Also, you must list icon.png in your web_accessible_resources. Furthermore, you don't need to list trial.js in your web_accessible_resources (except for very specialized use cases).
Finally, you need to approve your extension for access to file:// pages by checking the appropriate box under your extension's listing in chrome://extensions.
If you are compiling your extension with webpack, and images are being included via CSS (even in included libraries), add a webpack rule for images and such with type 'asset/inline'. They will be converted to Data URLs in the CSS.
I tried to have it find them at the chrome extension URL but it said can't load chrome-extension://invalid/. I set the publicPath option in webpack. might have been doing it wrong.
See this for an example: https://webpack.js.org/loaders/css-loader/#assets

Categories

Resources