Can't use localhost as src of iframe - google-chrome-extension

I'm developing a chrome extension and I want to display in the popup (when a user click extension icon) a page that has an url of localhost, in this page I will check if a user is logged in my site and depend on status I will display content in the page.
So I tried these:
First:
create a popup.html (that doesn't contain the iframe)
in popup.js create an iframe and give it an src, width, height. than append it to the body.
Second:
in the popup.html add the iframe with the src of localhost.
in popup.js create an iframe and give it an src, width, height. than append it to the body.
Neither the first nor the second works. and I get this:
But when I use a normal site in src, like http://bing.com it works and show the page of bing.com

This is a MVCE example that I developed:
The HTML files are:
index.html is the file that is served through the web server
<html>
<body>
<h1>Hello World!</h1>
</body>
</html>
popup.html is the extension popup content
<html>
<body>
<div id="container">
</div>
<script src="content.js"></script>
</body>
</html>
with the manifest for the extension:
manifest.json
{
"manifest_version": 2,
"name": "Test Popup",
"version": "0.1",
"browser_action": {
"default_title": "Popup Test",
"default_popup": "popup.html"
},
"permissions": [
"tabs", "<all_urls>"
],
"content_scripts": [
{
"matches": [
"http://*/*"
],
"js": [
"content.js"
]
}
]
}
All you need is a server for the external file to include, I used ruby:
serve.rb
require 'webrick'
s = WEBrick::HTTPServer.new(:Port => 8888, :DocumentRoot => Dir.pwd).start
All the magic happens in the content javascript:
content.js
function addiframe() {
div = document.getElementById("container");
var frame = document.createElement('iframe');
frame.setAttribute('width', '500px');
frame.setAttribute('height', '500px');
frame.setAttribute('frameborder', '0');
frame.setAttribute('id', 'inject');
frame.setAttribute('src', 'http://localhost:8888');
div.appendChild(frame);
};
addiframe();
and this is an image that shows the result:

Related

How to open a manipulated URL in a new tab without a pop-up

I got the extension to add "dev." to the current URL in a new tab which is working through a pop-up.
I'm trying to disable/remove the pop-up so that the code will work only when pressing the extension button instead.
popup.js:
document.addEventListener("DOMContentLoaded", function() {
console.log("Extension button clicked!");
var button = document.getElementById("change-url");
button.addEventListener("click", function() {
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
var url = new URL(tabs[0].url);
url.hostname = "dev." + url.hostname;
chrome.tabs.create({ url: url.toString() });
});
});
});
manifest.json:
{
"name": "My URL Changer",
"version": "1.0",
"manifest_version": 3,
"permissions": ["scripting"],
"host_permissions": ["<all_urls>"],
"action": {
"default_popup": "popup.html",
"default_title": "My URL Changer"
}
}
popup.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My URL Changer</title>
<script src="popup.js"></script>
</head>
<body>
<h1>My URL Changer</h1>
<button id="change-url">Change URL</button>
</body>
</html>
As woxxom mentioned, the chrome.action.onClicked API is a good fit for this.
The event does not fire if the extension has a popup, so you'll want to remove the default_popup key. However, you'll need to keep the empty action object. This tells Chrome to show an icon for your extension and is also required to make the API available.
With those changes in mind, your manifest would look like this:
{
"name": "My URL Changer",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"scripting"
],
"host_permissions": [
"<all_urls>"
],
"action": {}
}
You should also consider removing <all_urls> and replacing it with just the domains you want your extension to run on, since it's always best to request just the access you need. You could also remove this key entirely and use the activeTab permission instead, which gives your extension access to pages only when the action icon is clicked.
You'll then need to declare a service worker by adding the following to your manifest:
"background": {
"service_worker": "worker.js"
}
And in worker.js, you can copy your code from popup.js making sure to use the action API instead of DOMContentLoaded.

How do I use a localhost instead of .html in manifest.json [duplicate]

I am new to chrome extensions and I am having trouble while writing my first extension for chrome. What I am trying to do is detect the new tab action and redirect to a pre-defined(my webpage) url.
I wrote the manifest.json and the background.html but it doesn't seem to work.
I went through the google papers on the functions and how to use them, but there must be something I've missed.
I do not understand quite a few things that I've done in here, for example the content-scripts in manifest.json.
Some help in fixing this would be appreciated.
EDIT
EDIT2
Here is the updated code
Now I don't have the background.html file.
manifest.json
{
"name": "Tabber",
"manifest_version" : 2,
"version": "1.0",
"description": "MyExtension",
"background" : {
"scripts": ["code.js"]
},
"chrome_url_overrides": {
"newtab": "code.js"
},
"permissions": [
"tabs"
]
}
code.js
<script>
chrome.browserAction.onClicked.addListener(function(tab){
var action_url = "www.xyz.com"
chrome.tabs.create({ url: action_url });
}
</script>
Now when I open a new tab, I get to see the source of the .js file displayed.
Screenshot:
Why isn't the script being executed ?
If you want to over ride a default page, you shoud use html file, not a js file.
And if you just want to over ride a page, you do not need any background page or content script.
Here is the sample code:
menifest.json:
{
"name": "Tabber",
"manifest_version" : 2,
"version": "1.0",
"description": "MyExtension",
"chrome_url_overrides": {
"newtab": "my.html"
},
"permissions": [
"tabs"
]
}
my.html:
<!DOCTYPE html>
<html>
<head>
<title>over ride page</title>
<script type="text/javascript" src="code.js">
</script>
</head>
<body>
</body>
</html>
code.js:
window.open("http://www.google.com", "_self");
Note: you can not write any js in your html file. You need to include js file in html file.
And, you even do not need any js file. just modify the my.html as this:
<head>
<meta http-equiv="refresh"content="0;URL=http://www.google.com">
</head>
With the new chrome extensions you should not put any script code in the background page.
Inline scripts and event handlers disallowed
Due to the use of Content Security Policy, you can no longer use
tags that are inline with the HTML content. These must be
moved to external JS files. In addition, inline event handlers are
also not supported. For example, suppose you had the following code in
your extension:
https://developer.chrome.com/extensions/tut_migration_to_manifest_v2.html#inline_scripts
What you should do is move your code to a js file, either set the
manifest background property to a js file or have a background page
that links to an external js file and put all you js code there...
Try using the background property: http://developer.chrome.com/extensions/background_pages.html
1)basically add to your manifest a background script (you do not need the background page for your extension right now)
background : {
"scripts": ["background.js"]
}
2) Then add a a background.js to your extension directory and put all your js code there..
Then try again, and see if the extension works :)
3) remove all html from the js file and put just you js in the background.js
chrome.browserAction.onClicked.addListener(function(tab){
var action_url = "www.xyz.com"
chrome.tabs.create({ url: action_url });
}
Add this guy to your manifest.json file.
"chrome_url_overrides": {
"newtab": "index.html"
}
with index.html being replaced with your page. This will make it so it will show index.html when you open a new tab instead of the default.
I have an extension that basically does the same thing. Here's my manifest.json that you can use as a reference.
{
"name": "appName",
"version": "0.1",
"manifest_version": 2,
"chrome_url_overrides": {
"newtab": "index.html"
},
"description": "Desc Here",
"icons": {
// "128": "icon128.png"
},
"content_scripts": [ {
"css": ["css/styles.css"],
"js": [ ],
"matches": [ "*://*/*" ],
"run_at": "document_start"
} ],
"minimum_chrome_version": "18",
"permissions": [ "http://*/*", "https://*/*", "cookies", "tabs", "notifications" ]
}

Elements not showing in Background Page Inspector and getting addEventListener is null error

I'm trying to create a chrome extension, so I'm doing tutorials to learn and reading a bunch, but I'm struggling. I'm doing this tutorial. But long-term, from the extension I need users to be able to login to their account, then as they're browsing, send the url that they're at to their account.
popup.html
<!doctype html>
<html>
<head>
<title>Add a Snippet</title>
<script src="popup.js"></script>
<link rel="stylesheet" type="text/css" href="popup.css">
</head>
<body>
<h1>Add a Snippet</h1>
<form id="form">
<textarea id="code"></textarea>
<button type="submit" id="checkPage">Add Snippet</button>
</form>
</body>
</html>
popup.js
What I REALLY don't understand is that according to the console.log lines that I have in there and the error, it's loading the DOMContent, and it doesn't have any problem with finding the form by the id (let f = document.getElementById('form');). But it bombs when I try to attach an event listener?
document.addEventListener('DOMContentLoaded', function() {
console.log('the domcontentloaded');
let f = document.getElementById('form');
f.addEventListener('submit', function(e){
console.log('the form was submitted');
e.preventDefault();
})
}, false);
manifest.json
{
"name": "My Awesome Plugin",
"description": "This extension will be awesome",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html",
"default_title": "This is Awesome"
},
"background": {
"scripts": ["jquery-2.2.3.min.js", "background.js","popup.js"],
"persistent": false
},
"permissions": [
"activeTab",
"declarativeContent",
"https://ajax.googleapis.com/",
"storage",
"tabs",
"http://*/*",
"https://*/*"
],
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["login.js"]
}
],
"manifest_version": 2
}
login.js
console.log('login.js is ready to party');
When I load, I get this in the background inspector (or whatever it's called). So it's not finding the form.
So I looked at the elements, and I'm confused because it's not showing the form or the textarea. But when I click on the chrome extension icon, it's there.
1/Remove popup.js from "background/scripts" section of your manifest.
2/Add popup.js as a script reference in your popup.html file.
This way, popup.js will operate in the context of the popup.html DOM.

How to Inject HTML along with CSS and JS in a single HTML file? - Chrome Extension

My extension is intended to inject some HTML elements using local JavaScript libraries such PrimeUI, jQueryUI and its correspondent CSS stylesheets.
The best way I have found to do so, is to inject the HTML as follows:
// test.js
$.get(chrome.extension.getURL('/overlay.html'), function(data) {
$($.parseHTML(data)).appendTo('body');
}
// manifest.json
{
"name": "Test",
"version": "1.0",
"manifest_version": 2,
"options_page": "",
"description": "Test",
"browser_action": {
"default_title": "Test",
"default_popup": ""
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"js/jquery-3.1.1.min.js",
"js/test.js"
]
}
],
"permissions": [
"tabs"
],
"web_accessible_resources": [
"overlay.html",
"css/font-awesome.min.css",
"css/jquery-ui.min.css",
"css/primeui-all.min.css",
"js/jquery-3.1.1.min.js",
"js/jquery-ui.min.js",
"js/primeelements.min.js",
"js/primeui-all.min.js",
"js/main.js"
]
}
I have the required JavaScript libraries inside "js" folder in the root directory, for security reasons I do not retrieve them from a CDN.
My HTML contains CSS and JS on <head> section, but the styles nor the scripts applies in any way.
<html>
<head>
<link rel="stylesheet" href="css/font-awesome.min.css"/>
<link rel="stylesheet" href="css/jquery-ui.min.css"/>
<link rel="stylesheet" href="css/primeui-all.min.css"/>
<script type="text/javascript" src="js/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery-ui.min.js"></script>
<script type="text/javascript" src="js/primeui-all.min.js"></script>
<script type="text/javascript" src="js/x-tag-core.min.js"></script>
<script type="text/javascript" src="js/primeelements.min.js"></script>
</head>
<body>
<button id="btn-show" type="button">Show</button>
<div id="dlg" title="Godfather I">
<p>The story begins as Don Vito Corleone, ...</p>
</div>
</body>
</html>
// main.js
$(function() {
$('#dlg').puidialog({
showEffect: 'fade',
hideEffect: 'fade',
minimizable: true,
maximizable: true,
responsive: true,
minWidth: 200,
modal: true,
buttons: [{
text: 'Yes',
icon: 'fa-check',
click: function() {
$('#dlg').puidialog('hide');
}
},
{
text: 'No',
icon: 'fa-close',
click: function() {
$('#dlg').puidialog('hide');
}
}
]
});
$('#btn-show').puibutton({
icon: 'fa-external-link-square',
click: function() {
$('#dlg').puidialog('show');
}
});
}
The button is successfully displayed but with no events are attached nor styles.
i.e: if I inject this code on StackOverflow my button get the styles from SO and not mine.
I want to avoid as much as possible JavaScript for creating elements, or injecting tags programmatically, to separate the View from the Controller.
How can I manage to use my styles and scripts with my injected HTML as we do ordinarily? I have tried adding them to web_accessible_resources, and other manifest fields unsuccessfully.
Makyen explained:
It is not possible to parse HTML with <head> elements hardcoded such <script> and <link>. Instead it should be injected in other way.
The ways I have chosen to inject the files are:
For the CSS:
// Test.js
/** CSS Injection */
var link = document.createElement("link");
link.href = chrome.extension.getURL("css/jquery-ui.min.css");
link.type = "text/css";
link.rel = "stylesheet";
document.getElementsByTagName("head")[0].appendChild(link);
For the JS:
// Test.js
/** JavaScript Injection */
var s = document.createElement('script');
s.src = chrome.extension.getURL('js/jquery-3.1.1.min.js');
// "When an inline script is inserted in the document, it's immediately executed
// and the <script> tag can safely be removed". – Rob W.
s.onload = s.remove;
(document.head || document.documentElement).appendChild(s);
Trying to insert large amounts of code/libraries as into the page context using tags has a significant chance of interfering with the current contents/JavaScript of the page. Is there a reason that you are inserting scripts into the page context? Normally, you would have these inserted scripts (and CSS) as content scripts (manifest.json
content_scripts, or chrome.tabs.executeScript()/chrome.tabs.insertCSS(). not in the page context. – Makyen
With the above code I have successfully injected the files, but the styles and functions are applied only sometimes, I will edit when I fix this.

Message passing chrome extension

I wants to create an extension where content script will send message to background page and then on browser action means clicking on extension icon will access that background page and get some data.I am using chrome Version 23.0.1271.64 m on windows8.
I am getting following error.
Port error: Could not establish connection. Receiving end does not exist.
I tried to solve the same. but people are using sendRequest which is not supported by chrome20+. i also found solution mentioned for chrome 20+. But not working. Please help.
Below is the file contents.
manifest.json
{
"name": "Test Extension",
"version": "1.0",
"manifest_version": 2,
"description": "A test extension.",
"background": "background.html",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["jquery.js","content.js"]
}
],
"permissions": ["tabs", "http://*/", "https://*/"],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}
background.html
<html>
<head>
<script src="background.js"></script>
</head>
<body>
<h1>Wy</h1>
</body>
</html>
background.js
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
// Chrome 20+
alert(request);
console.log('received in listener');
sendResponse({farewell: "goodbye"});
});
content.js
$(function(){
console.log('start-sending message');
chrome.extension.sendMessage({greeting: "hello"},function(response){alert(response);});
console.log('end-sending message');
});
popup.html
<!doctype html>
<html>
<head>
<title>Getting Started Extension's Popup</title>
</style>
<!-- JavaScript and HTML must be in separate files for security. -->
<script src="jquery.js"></script>
<script src="popup.js"></script>
</head>
<body>
</body>
</html>
popup.js
$(function(){
var str_html = "<tr><td width='60%'>S</td><td width='40%'>15</td></tr><tr><td width='60%'>M</td><td width='40%'>25</td></tr>";
$('#sizes_container').html(str_html);
var bkg = chrome.extension.getBackgroundPage();
console.log(bkg);
});
You're incorrectly mixing the deprecated "background_page" property with the new signature of "background". The correct way to use background pages is:
"background": {
"scripts": ["background.js"]
}
You can completely get rid off your background.html, because it serves no purpose (the content of your <body> is unused) (if you really need it, use "background": {"page": "background.html"}).
About sendRequest, it is indeed deprecated, but not removed (yet).
Regarding your popup page: You don't have any element with ID sizes_container, so you will obviously not see any output.

Resources