Getting a content script to append image on page load - javascript

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

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 run a script (?) to enable WhatsApp web dark mode every time I open it?

WhatsApp Web doesn't have an option to make it dark mode by stock as of right now, but it can be enabled by inspecting element and changing: body class="web" to class="web dark".
Now I don't have any actual programming knowledge but is there a way to make such change automatically every time I open https://web.whatsapp.com/? As of right now I need to manually do it each time.
Thanks for the help.
Yes anything's possible, especially this
in order to run a script every time a page loads, you would want to make a browser extension (usually chrome extension, but same principles would apply to firefox also or possibly other browsers).
But first you need to just think of what that script would be. If you want to change to class nameof the body to something, in this case web dark, then the JavaScript would be
document.body.className = "web dark"
now the slightly hard part is making the actual extension I'll go over the instructions in chrome but similar concepts may apply to other browsers.
First open up a text editor. It can even be notepad, just when you go to file -> save as, change the extension ".txt" to "all files".
Anyways, name the new file "manifest.json" in a brand new folder somewhere, making sure to change the type of "all files" when you save it
Now we need to add some content to it. There are a few mandatory fields for every extension to hae, you can just copy the following and change the parts you want:
{
"name": "the actual name of it",
"version": "1.0",
"description": "put anything you want here!?",
"manifest_version": 2
}
OK now go open chrome, go to the extensions page (usually under tools, or chrome://extensions), then there should be a little tick mark that says "developer mode". If you see it, click it, now you should see a new menu appear that says, as one of the options "load unpacked". Click it.
Now select that new folder you made, that contains the manifest.json file.
If all goes well so far, meaning it loads with no errors, then we can move on.
Now we just need to add whats called a Content Script, which will execute some JS when the page loads.
To do so, add a new field in the manifest.json file, called "content_scripts", with a field called "matches" that contains the base URL of the ste you want to inject the scirpt to (in this case probably whatsapp.com), and another field called "js", containg the path to a new JS file that we are about to make, let's call it myscript.js (which we will get to in a sec). So so far the manifest.json should look like this:
{
"name": "the actual name of it",
"version": "1.0",
"description": "put anything you want here!?",
"manifest_version": 2,
"content_scripts": [{
"matches": ["https://*.whatsapp.com/*"],
"js":["myscript.js"]
}]
}
then reload it to see if there are any errors.
If not, we can move on.
now, create a new file in that same directory as manifest.json, called myscript.js. You can use notepad even, just make sure to set the type to "all files".
In that new file, simply add
function doIt() {
document.body.className = "web dark"
}
if(document.readyState == "complete")
doIt()
else
addEventListener("load", doIt)

How do you run a Js file on any site?

I want to automate something on a website that I don't own. It has to fill out a form automatically and do some clicking actions. Will I be able to do this with JS? Because I don't understand how you can run a .js file on a site without the html tag inside the html code. I can use the console on the site but I want it to look good and clean for users.
Thanks in advance
edit:
So it should look something like this:
An user should be able to select an item in an UI
Then it will automatically search the item on the website.
It will select the item in the right colour and size and add it to the basket.
Then it will checkout (fill in the form and pay).
Are you trying to automate actions?
Maybe selenium will work better.
Selenium has the capability of do those task.. like fill forms, click buttons, hover on elements and more.
Selenium python
You can create a very simple extension:
You will need two files:
yourCode.js // Here goes your code
manifest.json // Here you target the page
Here is what you should put in manifest.json:
{
"manifest_version": 2, // Mandatory
"name": "Auto-submit form", // Mandatory
"version": "1.0", // Mandatory
"content_scripts": [ // This key injects your js file into any target website.
{
"matches": ["your target url"], // Pattern: "*://*/*"
"js": ["yourCode.js"]
}
]
}
And your code resides in yourCode.js:
//Here Goes your JS logic.
Now you have your extension and can install it on your desired browser.
In Firefox go to about:debugging > This Firefox > Load Temporary Add-on
In Chrome go to chrome://extensions > Developer Mode > Load unpacked extension.
A console will be the best solution for your problem as console will show you How exactly your .js code will look like. Kindly elaborate your purpose for a better understanding of the question.

Chrome Extension programmatic UI injection

What I have so far:
manifest.json
{
"name": "Append Test Text",
"description": "Add test123 to body",
"version": "1.0",
"permissions": [
"activeTab"
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_title": "Append Test Text"
},
"manifest_version": 2,
"permissions": [
"https://*/*",
"http://*/*",
"tabs"
]
}
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript({
code: 'var div=document.createElement("div"); document.body.appendChild(div); div.innerText="test123";'
});
});
What it does:
Upon clicking the chrome extension icon, it adds <div>test123</div> to the <body></body> of any given page.
What I Would Like To Achieve:
Alike the bit.ly Chrome extension, I would like to append a lot of content to the DOM. Upon clicking on the extension icon, I would like an overlay element to be added tot he <body></body> along with a sidebar where I can add jQuery tab switches.
As you can see, I've just taken this picture whilst creating this question for StackOverflow.
Questions:
Regarding my current progress and/or any scripts you may submit with your answer; How can I give this appended element an ID and/or class name and check whether this is already present on the DOM before adding it over and over again upon clicking the icon.
How can I append a lot of content to the page to reside within my sidebar. jQuery is present within the site I am creating this extension to be used on. Am I able to create a standard HTML file which is then fetched and then programmatic injected into the DOM which I can use jQuery scripts on for the likes of switching tabs (not Chrome tabs, tabs within the injected content).
Why not take a look at how bit.ly extension does it?
Looking at the code, bit.ly appends a fixed position, 100% width/height iframe to the page that contains an "app" page from the package. Clicking again removes the iframe. There's a bit of special code to work with frameset pages (which I won't comment on here), but other than that that's the general idea.
Part of the page is half-transparent, which gives the illusion of a sidebar, but it does indeed cover the whole page. This is the easiest way to do it, since otherwise you risk breaking the page's layout and there is no general "magic" solution that works everywhere to have your content side by side.
// Injection
var iframe = document.createElement("iframe");
iframe.id = "my-awesome-extension-iframe";
iframe.style.width = "100%";
/* ..more styling like that.. */
iframe.src = chrome.runtime.getURL('my_ui.html');
document.body.appendChild(iframe);
// Removal
var iframe = document.getElementById("my-awesome-extension-iframe");
if (iframe) {
iframe.parentNode.removeChild(iframe);
}
To have full control over the looks of your UI, injecting a frame is preferable, as the page's own CSS and scripts won't "bleed" into your context. Whatever libraries you want, you can include there as you would in a normal page.
If you vehemently object to the idea of using a frame, you can try and inject your UI directly into the page - but beware interfering/incompatible code, restrictive CSP and CSS that bleeds through. This question is relevant: How to really isolate stylesheets in the Google Chrome extension?
You could make the above snippets as separate files, and use executeScript with the file attribute to inject them. They do not require any libraries like jQuery.
Note that code in that frame will have the same level of privilege as content script code - if you need APIs unavailable in content scripts, you'll need to message the background to do it. You'll also need to list the page itself, and all of its resources, in web_accessible_resources.
Dynamic DOM elements may be the way to go if you are adding simple user controls inside a layout. However, if you want to inject a full layout it can be a pain. jQuery may come handy with its function load.
You could have the layout of your sidebar in a static HTML file and have it loaded with jQuery in a given container. Something like this should do it, assuming an id="myContainer":
jQuery
$('#myContainer').load('layout.html')
To answer the first question, to give a specific ID to a dynamically created element, you only have to treat it like a DOM element and set an id to it.
JavaScript
var myElement = document.createElement('div');
myElement.id = 'myContainer';
myElement.className = 'kitten-background jumbo button';
// ...
// other properties you may need
// ...
document.body.appendChild(myElement);
For the second question, to check if an element exists you may as well use jQuery again. If a selector matches something, its length attribute will be greater than zero so that's a clean validation to check that $('#myContainer').length == 0 before inserting.
Good luck in what you are trying to achieve and have fun!

Searching and highlighting text on current page for a Chrome Extension

How should I connect my pages to search and highlight text on current tab?
Currently I have:
manifest.json does defining content/backgr/event page do significant things,auto inject code etc?
popup.html essentially a shell for the search input which is used by search.js
search.js should this be in background/event/content/popup.html page?
What I still don't understand after reading:
What is a content page vs. background/event page?
I know one is constantly running vs injected, but that's as much as I got from the chrome extension manual, I still don't quite understand if the content script/page is seperate from the popup.html for example and what the difference between a script in the popup.html vs content page/script is.
What I know:
I know how to search for text on a page, and replace it or change its style etc. using JS.
I need to read up on the messaging API for Chrome Extensions.
I know I need to know how to use the messaging API, is it going to be required for page search and highlighting?
Summary:
I don't need a walk through or full answer, just a little help visualizing how Chrome extensions work, or at minimum how I should set mine up in relation to page interaction IE:
search.js content page injected >>>>> popup.html
and maybe a short bit about how injection works in chrome extensions(IE, do I only need to specify that it is content page in manifest.json to have it injected or is there more work to it)/expected behavior?
Apologies for the jumbled thoughts/question/possibly missing the things relevant to my questions while reading the manual.
I will start with making the purpose of each kind of page/script more clear.
First is the background page/script. The background script is where your extension lives. It isn't required, but in order to do most extension things, you need one. In it you can set up various event listeners and such depending on what you want it to do. It lives in its own little world and can only interact with other pages and scripts using the chrome.* apis. If you set it up as an event page it works exactly the same except that it unloads when not in use and loads back into memory when it has something to do.
Content scripts refer to injected Javascript and/or css. They are the primary tool used for interacting with web pages. They have very limited access to chrome.* apis, but they have full access to the DOM of the page they are injected into. We will come back to using them in a minute.
Now for Popup pages. Unlike the background script and content script, popups have both a HTML and JS portion. The HTML part is just like any other page, just small and as a overlay popup coming out from the icon. The script portion of it, however, can do all the things the background page does, except that it unloads whenever the popup is closed.
Now that the distinctions are more clear let's move on to what you want to do. It sounds like you want to open the popup, have the user enter text to search for in the current tab, then highlight that text on the page. Since you said that you already know how you plan on highlighting the text, I will leave that part to you.
First to set up our manifest file. For this particular action, we don't need a background script. What we do need is both the "tabs" and "activeTab" permissions. These will enable us to inject our script later. We also need to define the browser action with it's popup. Altogether it would look something like this:
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs", "activeTab"
]
Now in our popup.html file, we can only have markup and css, no inline code at all. We will put it all in our js file and include it. Something like this should work:
<!DOCTYPE html>
<html>
<head>
<script src="popup.js"></script>
</head>
<body>
<input type="text" id="searchText">
<button id="searchButton">Search</button>
</body>
</html>
This is where we come back to the content script stuff. There are two ways to inject a content script, first is to define it in the manifest. This works best when you always want to inject it for a particular set of url's. Second, to use the chrome.tabs.executeScript method to inject it when we need to. That is what we will use.
window.onload = function(){
document.getElementById('searchButton').onclick = searchText;
};
function searchText(){
var search = document.getElementById('searchText').value;
if(search){
chrome.tabs.query({active:true,currentWindow:true},function(tabs){
chrome.tabs.executeScript(tabs[0].id,{file:search.js});
chrome.tabs.sendMessage(tabs[0].id,{method:'search',searchText:search});
});
}
}
With this, we have successfully injected our script and then send the search text to that script. Just make sure that the script is wrapped in a onMessage listener like this:
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
// message.searchText is the text that was captured in the popup
// Search/Highlight code goes here
});
And that pretty much sums it up. With that, you should be able to get it working. If something is still not clear let me know and I will fix it.
I think what's confusing you is the non-existant concept of a "content page". There is no such thing. What you're likely referring to is a "content script". Let me explain the three main components of an extension:
Background Page
As you said, this is the persistent aspect of a Chrome Extension. Even though it can be HTML page it is never rendered. You simply use it to run JavaScript and other content that stays persistent. The only way to "refresh" the background page is to refresh the extension in the extension manager, or to re-install the extension.
This is most useful for saving information that should remain persistent, such as authentication credentials, or counters that should build up over time. Only use the background page when absolutely necessary, though, because it consumes resources as long as the user is running your extension.
You can add a background script like to manafest file like this:
"background": {
"scripts": [
"background.js"
]
},
Or like this:
"background": {
"page": "background.html"
},
Then simply add background.js to background.html via a typical tag.
Popup
This is what you see when you click the icon on the toolbar. It's simply a popup window with some HTML. It can contain HTML, JavaScript, CSS, and whatever you would put in a normal web page.
Not all extension need a popup window, but many do. For example, your highlight extension may not need a popup if all it's doing is highlighting text on a page. However, if you need to collect a search result (which seems likely) or provide the user with some settings or other UI then a popup is a good way to go about this.
You can add a popup to the manifest file like this:
"browser_action": {
"default_popup": "popup.html"
},
Content script
As I mentioned, this is not a "page" per se -- it a script, or set of scripts. A content script is what you use to infuse JavaScript into pages the user is browser. For example, a user goes to Facebook and a content script could change the background to red. This is almost certainly what you'll need to use to highlight text on a page. Simply infuse some JavaScript and any necessarily libraries to search the page or crawl the dom, and render changes to that page.
You can inject content scripts every time a user opens any URL like this:
"content_scripts": [
{
"matches" : [
"<all_urls>"
],
"js" : [
"content.js"
]
}
],
The above injects "content.js" into "all urls".
You'll also need to add this to the permissions:
"permissions": [
"<all_urls>",
]
You can even add JQuery to the list of content scripts. The nice thing about extensions is that the content scripts are sandboxed, so the version of JQuery you inject will not collide with JQuery on pages the user visits.

Categories

Resources