I tried making a chrome extension that could give URL string of current tab of current window.
I had seen similar questions but, don't know why mine is not working.
I had taken care of deprecated calls as well.
Here it is
I have even properly set the permissions in manifest.json file.
But it's not working.
Here are main js file code
//background.js
chrome.browserAction.onClicked.addListener(function(tab) {
// Send a message to the active tab
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var activeTab = tabs[0];
chrome.tabs.sendMessage(activeTab.id, {"message": "clicked_browser_action"});
});
});
//content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "clicked_browser_action" ) {
var firstHref = $("a[href^='http']").eq(0).attr("href");
//console.log(firstHref);
alert(firstHref);
}
}
);
Can someone help me?
you havn't add your HTML file in your manifest file thts why your project is not working,
make some changes in your manifest.json like this :-
.......
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
....some code here//
Alternatively you can see here too for working extension of chrome
https://github.com/MrPardeep/Angular2_typescript_ChromeExtension
Edit2
Change your background.js with this code :-
document.addEventListener('DOMContentLoaded', function () {
var link = document.getElementById('btn');
// onClick's logic below:
link.addEventListener('click', function () {
AddUrl();
});
function AddUrl() {
chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
alert(tabs[0].url)
// document.getElementById('Current_url').value = tabs[0].url;
console.log(tabs[0].url, tabs[0].title, tabs[0].incognito, tabs, this.bookmark_title);
});
}
});
and popup.html with this code :-
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<script src="background.js"></script>
<body>
<h1>This is a Heading</h1>
<button id="btn"> Click Me </button>
</body>
</html>
Related
I have made a programatically injected version of a Chrome extension in order to have the extension working on pages from hosts with different top-level domain names (cfr previous post). Now I would like to add a link to an options page to the popup menu. However I keep getting the following error message:
Unchecked runtime.lastError: Cannot access contents of url
"chrome-extension://••••••••••••••••/options.html".
Extension manifest must request permission to access this host.
Can anyone tell me how to request such a permission? In background.js, I have also tried chrome.tabs.create({url: "options.html"}); without success.
Note that the options page is displayed ok, but the error message keeps coming.
manifest.json:
{
"manifest_version": 2,
"name": "My Extension",
"version": "0.5",
"description": "Does what it does",
"icons": {"32": "icon32.png",
"48": "icon48.png",
"128": "icon128.png"
},
"options_page": "options.html",
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action":{
"default_popup": "popup.html"
},
"optional_permissions":["tabs","https://*/*"],
"permissions": ["storage"]
}
popup.html:
<html>
<head>
</head>
<body>
<ul>
<li id="li_1">Enable My Extension</li>
<li id="li_2">Options</li>
</ul>
<script src="jQuery.js"></script>
<script src="popup.js"></script>
</body>
</html>
popup.js:
jQuery(function($){
var tabId = 0;
$(document).ready(function(){
$("#li_1").click(function(){ // this works
window.close();
chrome.permissions.request({
permissions: ['tabs'],
origins: ["https://*/*"]
}, function(granted) {
if (granted) {
chrome.runtime.sendMessage("granted");
} else {
alert("denied");
}
});
});
$("#li_2").click(function(){ // this sends request to background.js which then causes error
window.close();
chrome.runtime.sendMessage("openOptions");
});
});
});
background.js:
chrome.runtime.onMessage.addListener(
function(message) {
switch(message){
case "granted": //this works, please ignore
var tabId = 0;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
tabId = tabs[0].id;
injectScript(tabId);
chrome.permissions.contains({origins:["https://*/*"]}, function(perm) {
if (perm) {
chrome.tabs.onUpdated.addListener(function(tabId){
injectScript(tabId);
});
}
});
});
break;
case "openOptions": //this does not work – generates error msg
chrome.runtime.openOptionsPage();
break;
}
return true;
});
As suggested by wOxxOm in a comment above, the error was caused by he extension's attempt to inject the content script into the options.html page. One way to circumvent that would be to insert a condition into the injectScript() function (which was not shown in the question) in background.js, ensuring that only web pages are injected. A working version is shown below.
background.js
function injectScript(tab){
chrome.tabs.get(tab,function(thisTab){ // get tab info
if(thisTab.url.startsWith("http")){ // condition: is this a web page?
chrome.tabs.executeScript(tab,{ // if so, inject scripts
file: "jQuery.js"
});
chrome.tabs.executeScript(tab,{
file: "content.js"
});
}
});
}
chrome.runtime.onMessage.addListener(
function(message) {
switch(message){
case "granted":
var tabId = 0;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
tabId = tabs[0].id;
injectScript(tabId);
chrome.permissions.contains({origins:["https://*/*"]}, function(perm) {
if (perm) {
chrome.tabs.onUpdated.addListener(function(tabId){
injectScript(tabId);
});
}
});
});
break;
case "openOptions":
chrome.runtime.openOptionsPage();
break;
}
return true;
});
I am currently writing a simple chrome extension that saves the current webpage to local storage when you click the extension icon in the header.
I have successfully saved the url into local storage using background.js as per the Chrome Documentation here: https://developer.chrome.com/extensions/activeTab.
My issue is that when I click the chrome extension icon the first time my event fires but my popup.js errors out with
Uncaught TypeError: Cannot read property 'getSelected' of undefined
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
console.log('Turning ' + tab.url + ' red!');
var tabNew = tab.url
chrome.storage.sync.set({ ["key" + 1]: tabNew}, function(){
// A data saved callback omg so fancy
});
chrome.storage.sync.get(/* String or Array */["key" + 1], function(items){
// items = [ { "yourBody": "myBody" } ]
console.log(items)
});
chrome.tabs.executeScript({
code: 'document.body.style.backgroundColor="red"'
});
chrome.browserAction.setPopup({popup: 'popup.html'});
});
popup.js
chrome.tabs.getSelected(null, function(tab) {
document.getElementById('currentLink').innerHTML = tab.url;
});
document.addEventListener('DOMContentLoaded', function() {
var link = document.getElementById('download');
// onClick's logic below:
link.addEventListener('click', function() {
chrome.storage.sync.get(null, function(items) { // null implies all items
// Convert object to a string.
var result = JSON.stringify(items);
// Save as file
chrome.downloads.download({
url: 'data:application/json;base64,' + btoa(result),
filename: 'filename_of_exported_file.json'
});
});
});
});
popup.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
<link href='style.css' rel='stylesheet' type='text/css'>
<title>Discoveroo</title>
<!-- <script type="text/javascript" src="https://www.google.com/jsapi"></script> -->
<base target="_blank">
</head>
<body>
<p id="currentLink">Loading ...</p>
<hr />
<ul id="savedLinks"></ul>
<script type="text/javascript" src="popup.js"></script>
<button id="download">Download All</button>
</body>
</html>
manifest.json
{
"name": "APPNAME",
"version": "0.1",
"manifest_version": 2,
"description": "APP DESC",
"permissions": ["activeTab", "storage", "downloads", "<all_urls>"],
"background": {
"scripts": ["background.js"],
"persistent": true
},
"content_scripts": [{
"matches": ["http://*/*", "https://*/*"],
"js": ["popup.js"]
}],
"browser_action": {
"default_title": "Add this page to my list"
},
"icons": {
"128": "icon.png"
}
}
Don't use popup.js as a content script. You don't need the content script. See the architecture overview. The content scripts have limited access to chrome API and run in the web page, not in the browserAction popup which is a totally separate full extension page with its own chrome-extension:// URL and own devtools console etc, not related to the web page.
browserAction.onClicked doesn't work simultaneously with a popup html so you should pick one. In this case since you need to display the popup page, declare it in manifest.json, remove browserAction.onClicked, put its inner code into your popup.js
As a consequence, there'll be no need for the background script
There's probably no need for <all_urls> permission since you already have activeTab which gives you full access to the active tab after the extension icon is clicked.
chrome.tabs.getSelected is deprecated and will be removed eventually so use chrome.tabs.query({active: true, currentWindow: true}, tabs => { ... })
No need to read chrome.storage since you already get the active URL in your popup.js.
Regarding "omg so fancy", callbacks are not an arbitrary weirdness, but a consequence of the basic fact: the API is asynchronous so the callback is invoked at a later point in time, it's like a one-time "onload" event listener. There are many tutorials about asynchronous JavaScript.
Use the safe textContent property instead of the potentially unsafe innerHTML for displaying a plain text string such as the URL.
manifest.json
remove "background"
remove "content_scripts"
add "default_popup"
"browser_action": {
"default_title": "Add this page to my list",
"default_popup": "popup.html"
},
background.js
Delete it.
popup.js
The only things from the old background script you might need, are executeScript and sync.set calls.
chrome.tabs.executeScript({
code: 'document.body.style.backgroundColor="red"'
});
chrome.tabs.query({active: true, currentWindow: true}, ([tab]) => {
document.getElementById('currentLink').textContent = tab.url;
chrome.storage.sync.set({key1: tab.url});
});
You can also load the Mozilla WebExtension polyfill (using <script> tag in your popup.html right before popup.js) and switch to async/await syntax instead of callbacks:
(async () => {
const [tab] = await browser.tabs.query({active: true, currentWindow: true});
document.getElementById('currentLink').textContent = tab.url;
await chrome.storage.sync.set({key1: tab.url});
})();
I'm making my first chrome extension and noticed that messages being sent from my popup.html page were getting duplicated in my content.js message event listener. I've console logged "sending message" before every message send and "message received" before every message, and I don't understand how the messages are being duplicated. I've also checked the chrome dev docs for sendMessage and onMessage and it specifies that the onMessage listener should only be fired once per sendMessage event.
Any help would be appreciated.
popup.html
<!DOCTYPE html>
<html>
<head>
<title>Messaging Practice</title>
</head>
<body>
<h1>Messaging Practice</h1>
<input type="button" id="send-message" value="Button">
<script src="popup.js"></script>
</body>
</html>
content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log('message received')
console.log(request);
}
);
popup.js
var messageButton = document.querySelector("#send-message");
messageButton.onclick = function() {
chrome.tabs.query({currentWindow: true, active: true},
function(tabs) {
chrome.tabs.executeScript(
tabs[0].id, {file: "content.js"}
)
console.log("sending message")
chrome.tabs.sendMessage(tabs[0].id, "string message")
});
}
background.js
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([{
conditions: [new chrome.declarativeContent.PageStateMatcher({
pageUrl: {hostEquals: 'stackoverflow.com'},
})],
actions: [new chrome.declarativeContent.ShowPageAction()]
}]);
});
manifest.json
{
"name": "Send Messages Practice",
"version": "1.0",
"manifest_version": 2,
"description": "Simple messaging practice with the chrome api",
"permissions": ["declarativeContent", "activeTab"],
"background": {
"scripts": ["background.js"],
"persistant": true
},
"page_action": {
"default_popup": "popup.html",
"scripts": ["content.js"],
"matches": ["http://*/*","https://*/*"]
}
}
Adding "return true;" to event handlers will prevent your code from firing again and again:
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.action == "show_alert") {
alert(request.alert);
return true;
}
});
Get the same problem when I run my extension with multiple frames. #Wayne Smallman solution works for me:
recommending that all_frames be set to false in the manifest file
I've been following along on a few tutorials but have been running into examples that use deprecated code.
I'm trying to send the URL of the current tab to the popup.
My code thus far:
Manifest.json contains the proper permissions:
"permissions": [
"activeTab",
"tabs"
]
Popup.js, where I think the problem is but no errors in console.
function setup() {
noCanvas();
var url = 'URL'
function sendMessage() {
var msg = {
from: 'popup',
page: url
}
var params = {
active: true,
currentWindow: true
}
chrome.tabs.query(params, gotTabs);
function gotTabs(tabs) {
chrome.tabs.sendMessage(tabs[0].id, msg);
url = document.getElementById('currentLink').innerHTML;
console.log(url)
}
}
}
Popup.html
<body>
<h1>Popup Interface Example</h1>
<p id="currentLink">Loading ...</p>
</body>
What am I missing here?
I figured it out. Was making it WAY too hard.
Popup.js
chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
var url = tabs[0].url;
console.log(url);
document.getElementById("myText").innerHTML = url;
});
Popup.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Extension Pop-Up</title>
<script src="libraries/p5.js" type="text/javascript"></script>
<script src="libraries/p5.dom.js" type="text/javascript"></script>
<script src="popup.js" type="text/javascript"></script>
</head>
<body>
<h1>Wordnik Lookup</h1>
<p id="myText"></p>
</body>
</html>
I've been trying for hours to get popup.js to talk with the rest of my chrome extension using chrome api's sendMessage and onMessage. For testing purposes, all I want right now is to log something onto my currently active tab when a button is pressed on popup.js. This seems like it should be simple, but I just can't figure out what the problem is. Would really appreciate any help and explanation!
popup.html
<!DOCTYPE html>
<body>
<p>testing</p>
<input type="submit" id="clickme" value="button">
</body>
popup.js
function popup(){
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var activeTab = tabs[0];
chrome.tabs.sendMessage(activeTab.id, {"message": "clicked_browser_action"});
}
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("clickme").addEventListener("click",popup)
});
content.js (I expect this to log 'started' onto console of my active tab)
// content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "clicked_browser_action" ) {
console.log('started')
}
}
);
Just in case it applies, this is the manifest.json
{
"manifest_version":2,
"name": "extension",
"version": "0.1",
"content_scripts":[
{
"matches": [
"<all_urls>"
],
"js":["jquery-3.1.1.min.js","content.js"]
}],
"browser_action":{
"default_icon":"icon.png",
"default_popup":"popup.html"
},
"background":{
"scripts":["background.js"]
}
}