append html elements to DOM by background script - google-chrome-extension

I want to append the same html elements to the current TAB's document DOM.
I want these html extended elements to live "forever", so I want to built them once, and append them on every page load by the content script.
I was thinking to place the createElement commends at the background page.
Then for every web page load, I want the content script to communicate with the background script, so it will append them to the current TAB document DOM.
Is that good practice?
My problem is that I don’t know how to append html elements to the DOM from the background page.
Can you please help?

This cannot work. The background page lives in one process, the tab in the other - you cannot send objects from one to the other, only text data (objects sent are automatically converted to JSON). So your best chance is: build everything together in the background page, then get innerHTML of your element and send this text to the content script whenever necessary. The content script should then create a new element and set its innerHTML to the value it received.

You need to do it in content script because "content scripts" are scripts which run in an environment between a page and the Chrome extension. see this. remember these scripts will loaded on every page load and they won't affect already opened tabs.
as an example you can add external scripts like this
var theScript = document.createElement('script');
theScript.src = "http://mybwesite.com/static/js/myscript.js"
document.body.appendChild(theScript);
as long as you've added it's permissions in manifist:
"permissions": [
"activeTab",
"tabs",
"http://*/*", "https://*/*"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/contentscript.js"]
}
]

Related

Insert HTML into page before Javascript is loaded in Chrome/Firefox Extension

I'm trying to make an extension that adds a certain HTML into a page, however it must be done before any javascript of the page is executed and after the elements are there.
I plan to insert something on the body tag, so using "run_at": "document_start" makes me unable to add anything to the page as everything is null at that moment.
Turns out I can accomplish this by writing in manifest.json run_at: "document_start" and in my content.js instead of writing to head or body I can use document.documentElement.appendChild.

Is it possible to access the contents of iframe via chrome extension?

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('*')]);
}

Is this a Google Chrome extensions bug?

I wanted to make a Google Chrome extension that needed to list the <script> tags on a web page. So I made a manifest.json with a script that would "run_at": "document_start" only on that particular web page. When I loaded the page, I noticed that the value of document.getElementsByTagName('script') was that of an array with the proper <script> element in it, but its length was 0 and I couldn't access the elements.
var scripts = document.getElementsByTagName('script');
console.log(scripts.length); // 0
console.log(scripts); // [<script type=​"text/​javascript">​...</script>​] with expected JavaScript in it
Something somewhere is definitely wrong. The scripts variable has length 0 but the console shows it contains an element which cannot be accessed.
From the documentation:
In the case of "document_start", the files are injected after any files from css, but before any other DOM is constructed or any other script is run.
If you need access to the DOM, change run_at to document_end or leave it as the default document_idle.

Chrome Content Scripts not loading JS

I'm trying to work on a Chrome browser extension which does fun things on a contextmenu. The problem is, I can't get the JS files to load within the manifest.json content_scripts.
I don't receive an error, the files simply do not load.
The scripts are good, if I put them in my background page, they fire fine through that background page. The downside of that is it's restricted to only the background page.
{
"name": "Mini",
"description": "Mini",
"permissions": ["contextMenus","management","contentSettings","tabs","http://*/*","https://*/*","editable"],
"version": "0.1",
"manifest_version": 1,
"background_page": "mini.html",
"icons" : {"16" : "mini.png"},
"contexts" : ["link","tab","page"],
"content_scripts": [{"matches":["<all_urls>"],"js":["jquery172min.js","mini.js"]}]
}
I've tried all forms of matches, including "http://\*/\*", "https://\*/\*", "\*://\*/\*"
I've tried whitespaces, no whitespaces. I'm drawing a blank here.
Any help would be appreciated.
$(document).ready(function () {
alert("page is ready");
},true);
My apologies for that. This is a copy of the javascript/Jquery I'm using to test whether the extension has loaded or not. It's just a simple alert.
Content scripts cannot use the chrome.contextMenus API (in fact, these can only use some of the chrome.extension methods).
It's possible to apply match patterns to individual menu items, via chrome.contextMenus.create({title: 'Test', documentUrlPatterns: 'http://*/*'});.
Created menu items can also be modified (chrome.contextMenus.update) and removed (chrome.contextMenus.remove).
To communicate between a Content script and the background page, see Message passing.

Function not defined creating a Chrome Extension Content Script

I'm writing a Chrome content script and when I inject this in the DOM:
"<a href='#' onclick='alert(\"Hi!\");return false;'>Hi</a>"
it works fine (the alert pops up when I click it), however if I create a function for the alert, it will say function undefined. Ex:
"<a href='#' onclick='alertPlease(\"Hi!\");return false;'>Hi</a>"
function alertPlease(x){
alert(x);
}
All my code is the same content script js file.
Do I have to place whatever code that can be used after loading in another js file in the background? I tried adding a background page with the 'alertPlease();' function, but that didn't work either.
Any hint will be greatly appreciated!
Thanks!
Content scripts run in an "isolated world." The webpage and content scripts can't see each other's JavaScript variables (although they can see the same DOM). When you add an onclick attribute within the DOM, the handler is created on the webpage's world, not your extension's world, so that code can't access the other function you defined. Instead of using an onclick handler, you should define your event listener in pure Javascript and then use addEventListener to attach it.
Isolated worlds are a feature to improve security and stability. Things are similar if you're developing within the Greasemonkey sandbox in Firefox.
Doing one of these today with manifest version 3, I learned:
I can't append a button to the page and use
<button type="button" onclick="myContentScriptFunction();">Call CS Function</div>
But, in the content script, I can do vanilla
let loadButton = document.createElement('button');
loadButton.innerText = 'Call CS Function';
loadButton.addEventListener('click', myContentScriptFunction);
document.querySelector('body').append(loadButton);
or jQuery
let loadButton = $("<button type="button">Call CS Function</button>")
loadButton.on("click", myContentScriptFunction)
$("body").append(loadButton);
And both worked as expected with all code in the content script
Info Source: Chrome Extension Samples Example
Specify any scripts in the manifest.json file under "content_scripts"
{
"name": "My Extension",
"content_scripts": [{
"matches": ["<all_urls>"],
"css": ["style.css"],
"js": ["jquery-1.5.js", "script.js"]
}]
}

Resources