Chrome extension focus - google-chrome-extension

I'm trying to get a Chrome extension to pop up a "popup" or a "panel" in the front of the currently focused window. It seems like the focused boolean for chrome.windows.create isn't working.
It always opens behind the current window, no matter what I've tried.
// popup.html
<html>
<head>
</head>
<body>
</body>
<script src="loader.js"></script>
</html>
// loader.js
function load() {
var popupId;
chrome.windows.create({
type: 'popup',
url: 'http://xxx/bookmarks',
height: 500,
width: 800,
focused: true
}, function(popup) {
popupId = popup.id;
});
chrome.windows.update(popupId, {focused: true});
}
document.getElementsByTagName('body')[0].onload = function() { load(); };
Any ideas would be appreciated. Thanks!

Since you don't really need the popup page, I would suggest you remove it and instead move your code to open a new window in the javascript file for your background page. You can act on a click on your extension icon by using:
chrome.browserAction.onClicked.addListener(function callback)
and supplying your logic in a callback.

Related

How to hide popup.html in chrome extension

Here is my setup and i am trying to figure out if its possible.
I have an Chrome Extension which goes and parses some data from a active page and then copys the result to the clipboard. My popup.html is minimal and looks like this
<!DOCTYPE html>
<html style=''>
<head>
<script src='popup.js'></script>
</head>
<body style="width:600px;">
<textarea id="emailphone" cols="50" rows="10"></textarea>
<br>
<button id="copy-to-clipboard">Copy to Clipboard</button>
</body>
</html>
What i would like to do is actually not even show the popup at all as my script goes and creates an Alert and displays the data. But for one my script sets the Inner Html of the emailphone textarea with the parsed data and then i go and copy the textarea to my clipboard. Here is my popup script
chrome.runtime.onMessage.addListener(function(request, sender) {
if (request.action == "getSource") {
emailphone.innerText = request.source;
myFunction();
}
});
document.addEventListener('DOMContentLoaded', function() {
document.getElementById("copy-to-clipboard").addEventListener("click", copytoclipboard);
});
function onWindowLoad() {
var message = document.querySelector('#emailphone');
chrome.tabs.executeScript(null, {
file: "getPagesSource.js"
}, function() {
// If you try and inject into an extensions page or the webstore/NTP you'll get an error
if (chrome.runtime.lastError) {
emailphone.innerText = 'There was an error injecting script : \n' + chrome.runtime.lastError.message;
}
});
}
function copytoclipboard() {
var copyText = document.getElementById("emailphone");
copyText.select();
copyText.setSelectionRange(0, 99999)
document.execCommand("copy");
alert(copyText.value);
}
window.onload = onWindowLoad;
when i use window.close() it only closes after i close the alert. So what i am looking for is to only show the Alert and not the popup.html

Chrome Extension Error: Refused to execute inline event handler [duplicate]

This seems to be the easiest thing to do, but it's just not working. In a normal browser the .html and .js files works perfectly, but in the Chrome/Firefox extension the onClick function is not performing what it's supposed to do.
.js file:
function hellYeah(text) {
document.getElementById("text-holder").innerHTML = text;
}
.html file:
<!doctype html>
<html>
<head>
<title>
Getting Started Extension's Popup
</title>
<script src="popup.js"></script>
</head>
<body>
<div id="text-holder">
ha
</div>
<br />
<a onClick=hellYeah("xxx")>
hyhy
</a>
</body>
</html>
So basically once the user clicks "hyhy", "ha" should change into "xxx". And again - it works perfectly in the browser but does not work in the extension. Do you know why? Just in case I'm attaching the manifest.json below as well.
manifest.json:
{
"name": "My First Extension",
"version": "1.0",
"manifest_version": 2,
"description": "The first extension that I made.",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"http://api.flickr.com/"
]
}
Chrome Extensions don't allow you to have inline JavaScript (documentation).
The same goes for Firefox WebExtensions (documentation).
You are going to have to do something similar to this:
Assign an ID to the link (<a onClick=hellYeah("xxx")> becomes <a id="link">), and use addEventListener to bind the event. Put the following in your popup.js file:
document.addEventListener('DOMContentLoaded', function() {
var link = document.getElementById('link');
// onClick's logic below:
link.addEventListener('click', function() {
hellYeah('xxx');
});
});
popup.js should be loaded as a separate script file:
<script src="popup.js"></script>
Reason
This does not work, because Chrome forbids any kind of inline code in extensions via Content Security Policy.
Inline JavaScript will not be executed. This restriction bans both inline <script> blocks and inline event handlers (e.g. <button onclick="...">).
How to detect
If this is indeed the problem, Chrome would produce the following error in the console:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.
To access a popup's JavaScript console (which is useful for debug in general), right-click your extension's button and select "Inspect popup" from the context menu.
More information on debugging a popup is available here.
How to fix
One needs to remove all inline JavaScript. There is a guide in Chrome documentation.
Suppose the original looks like:
<a onclick="handler()">Click this</a> <!-- Bad -->
One needs to remove the onclick attribute and give the element a unique id:
<a id="click-this">Click this</a> <!-- Fixed -->
And then attach the listener from a script (which must be in a .js file, suppose popup.js):
// Pure JS:
document.addEventListener('DOMContentLoaded', function() {
document.getElementById("click-this").addEventListener("click", handler);
});
// The handler also must go in a .js file
function handler() {
/* ... */
}
Note the wrapping in a DOMContentLoaded event. This ensures that the element exists at the time of execution. Now add the script tag, for instance in the <head> of the document:
<script src="popup.js"></script>
Alternative if you're using jQuery:
// jQuery
$(document).ready(function() {
$("#click-this").click(handler);
});
Relaxing the policy
Q: The error mentions ways to allow inline code. I don't want to / can't change my code, how do I enable inline scripts?
A: Despite what the error says, you cannot enable inline script:
There is no mechanism for relaxing the restriction against executing inline JavaScript. In particular, setting a script policy that includes 'unsafe-inline' will have no effect.
Update: Since Chrome 46, it's possible to whitelist specific inline code blocks:
As of Chrome 46, inline scripts can be whitelisted by specifying the base64-encoded hash of the source code in the policy. This hash must be prefixed by the used hash algorithm (sha256, sha384 or sha512). See Hash usage for <script> elements for an example.
However, I do not readily see a reason to use this, and it will not enable inline attributes like onclick="code".
I had the same problem, and didnĀ“t want to rewrite the code, so I wrote a function to modify the code and create the inline declarated events:
function compile(qSel){
var matches = [];
var match = null;
var c = 0;
var html = $(qSel).html();
var pattern = /(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/mg;
while (match = pattern.exec(html)) {
var arr = [];
for (i in match) {
if (!isNaN(i)) {
arr.push(match[i]);
}
}
matches.push(arr);
}
var items_with_events = [];
var compiledHtml = html;
for ( var i in matches ){
var item_with_event = {
custom_id : "my_app_identifier_"+i,
code : matches[i][5],
on : matches[i][3],
};
items_with_events.push(item_with_event);
compiledHtml = compiledHtml.replace(/(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/m, "<$2 custom_id='"+item_with_event.custom_id+"' $7 $8");
}
$(qSel).html(compiledHtml);
for ( var i in items_with_events ){
$("[custom_id='"+items_with_events[i].custom_id+"']").bind(items_with_events[i].on, function(){
eval(items_with_events[i].code);
});
}
}
$(document).ready(function(){
compile('#content');
})
This should remove all inline events from the selected node, and recreate them with jquery instead.
I decide to publish my example that I used in my case. I tried to replace content in div using a script. My problem was that Chrome did not recognized / did not run that script.
In more detail What I wanted to do: To click on a link, and that link to "read" an external html file, that it will be loaded in a div section.
I found out that by placing the script before the DIV with ID that
was called, the script did not work.
If the script was in another DIV, also it does not work
The script must be coded using document.addEventListener('DOMContentLoaded', function() as it was told
<body>
<a id=id_page href ="#loving" onclick="load_services()"> loving </a>
<script>
// This script MUST BE under the "ID" that is calling
// Do not transfer it to a differ DIV than the caller "ID"
document.getElementById("id_page").addEventListener("click", function(){
document.getElementById("mainbody").innerHTML = '<object data="Services.html" class="loving_css_edit"; ></object>'; });
</script>
</body>
<div id="mainbody" class="main_body">
"here is loaded the external html file when the loving link will
be clicked. "
</div>
As already mentioned, Chrome Extensions don't allow to have inline JavaScript due to security reasons so you can try this workaround as well.
HTML file
<!doctype html>
<html>
<head>
<title>
Getting Started Extension's Popup
</title>
<script src="popup.js"></script>
</head>
<body>
<div id="text-holder">ha</div><br />
<a class="clickableBtn">
hyhy
</a>
</body>
</html>
<!doctype html>
popup.js
window.onclick = function(event) {
var target = event.target ;
if(target.matches('.clickableBtn')) {
var clickedEle = document.activeElement.id ;
var ele = document.getElementById(clickedEle);
alert(ele.text);
}
}
Or if you are having a Jquery file included then
window.onclick = function(event) {
var target = event.target ;
if(target.matches('.clickableBtn')) {
alert($(target).text());
}
}

Performing browser action on two different pages

I have below files with me
manifest.json
{
"name": "Get Response URL",
"version": "1.0",
"manifest_version": 2,
"name": "Test" ,
"browser_action": {
"icon":"icon.png"
},
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "icon.png"
},
"permissions":["https://myblog.com/*"] ,//Put All your URL here
"manifest_version": 2
}
background.js
chrome.browserAction.onClicked.addListener(function (tab) { //Fired when User Clicks ICON
if (tab.url.indexOf("https://myblog.com/page1.html")==0) { // Inspect whether the place where user clicked matches with our list of URL
chrome.tabs.executeScript(tab.id, {
"file": "page2.js"
}, function () { // Execute your code
console.log("Script Executed .. "); // Notification on Completion
});
}
else if (tab.url.indexOf("https://myblog.com/page2.html")==0) { // Inspect whether the place where user clicked matches with our list of URL
chrome.tabs.executeScript(tab.id, {
"file": "page1.js"
}, function () { // Execute your code
console.log("Script Executed .. "); // Notification on Completion
});
}
});
Page1.html
<html>
<head>
<title>Page1</title>
</head>
<body>
<input type='button' name='submit' id='myBtn' value='click here to move to next page' onclick="document.location.href='page2.html';" />
</body>
</html>
page2.html
<html>
<head>
<title>Page2</title>
</head>
<body>
<input type="text" name="textBox" id="myText" />
</body>
</html>
And to two JavaScript files page1.js and page2.
page1.js
var button=document.getElementById("myBtn");
button.click();
Page2.js
document.getElementById("myText").value="Text Box";
I have developed a Chrome extension. On first page when I click the Chrome extension icon the functionality is working good as per JavaScript file(page1.js) for https://myblog.com/page1 page.
And what I am doing on https://myblog.com/page1 page with the help of page1.js is to just click a button to move to second page that is https://myblog.com/page2. Now I want that page2.js should wrok on page https://myblog.com/page2 as scripted(page2.js) but its not working.
Script is working good when I click the extension icon on page1 and then again click the extension icon on page2.
But I want to extension icon should be clicked on page1 not repetitively.
Edited the Question
Added page1.html and page2.html
page1.js and page2.js
Is it possible to doing the same.
If yes where I am doing the mistake?
here's what you need to do.
Your code block chrome.browserAction.onClicked.addListener(function (tab) { makes the JS functions to execute only when you click the icon. That's why your Page 1 works whereas the Page 2 doesn't.
You want the page2.js to run as soon as the Page2.html is opened right? Hence change the coding of your Page2.html. Add the below code in the page2.html itself.
document.addEventListener("DOMContentLoaded", function(event) {
//Do work
});
What this will do is, as soon as the Page2.html is loaded, it will execute the Javascript. Eventhough it works in most of the browsers, but for IE 8 and below it won't.
If you need for IE 8 and below too, then try using the following code:
<script type="text/JavaScript">
function funtionToBeCalled(){
// code that will be exected after dom ready
}
window.onload=funtionToBeCalled;
</script>

How do I open a link in the current tab for my chrome extension?

Here is my popup.html code:
Google
But when I click the Google link nothing happens. How do I make the link take me to google.com in the current tab?
You need to use chrome.tabs.query to find the selected tab and update it.
So I would do something like:
popup.html:
<div id='clickme'>Google</div>
<script src = 'popupjs.js'></script>
popupjs.js:
document.getElementById('clickme').onclick = function() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var tab = tabs[0];
chrome.tabs.update(tab.id, {url: 'http://www.google.com'});
});
};
This uses chrome.tabs.query and chrome.tabs.update to find the current tab id and update it with the url http://www.google.com.
Note: You will need the tabs permission in your manifest file!
You could then use some CSS to make the div look like a real link, or just change the cursor when hovering over it.

Changing html content onclick chrome extension

Hello and thanks for reading my question. I'll warn you, it will probably seem dull to most of you, but I just can't get it working.
It's about a chrome extension I'm trying to write for my audio stream. Here's what I'm trying to do:
A small icon, that when is clicked once starts playing music, and when is clicked again stops, and so on...
Here's what I've tried:
<!doctype html>
<html>
<head>
</head>
<body>
<script src="popup.js"></script>
<div id="music"></div>
</body>
</html>
and popup.js
var well=0
//Executed when the extension's icon is clicked
chrome.browserAction.onClicked.addListener(function(tab)
{
if(well>0)
{
var well=0;
document.getElementById('music').innerHTML= '<iframe src="#" width="100" height="100"></iframe>';
}
else
{
var well=1;
document.getElementById('music').innerHTML= '<iframe src="http://electro.piratefm.ro/popup.html" width="100" height="100"></iframe>';
}
});
What's happening is that when the extension is loaded, no music plays. When you click it, it starts playing and everything's fine. When you click it again, it stops for a couple of seconds then starts playing again. I need it to stop until you click it again.
Thanks for reading and sorry if it's already been asked or if it's dull.
I fixed it, my js skills are horrible so it was a dumb mistake, this is the fixed version:
var well=0
//Executed when the extension's icon is clicked
chrome.browserAction.onClicked.addListener(function(tab)
{
if(well==1)
{
well=0;
document.getElementById('music').innerHTML= '<iframe src="#" width="100" height="100"></iframe>';
}
else
{
well=1;
document.getElementById('music').innerHTML= '<iframe src="http://electro.piratefm.ro/popup.html" width="100" height="100"></iframe>';
}
});

Resources