Preface: I'm a beginner to this stuff.
I'm trying to make an extension that replaces the current tab url with a predefined url. So far I have the following:
chrome.tabs.getSelected(null, function(tab){
chrome.tabs.update(tabs.id, {url: "https://www.wikipedia.org/"});
});
The chrome app developer tool tells me that "tabs is not defined" but I have "tabs" in my manifest permissions. Manifest:
"permissions": [
"tabs",
"declarativeContent",
"https://www.wikipedia.org/"
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_icon": "icon-19.png",
"default_title": "Simple-Switch"
}
Permissions don’t declare variables that you can use (as if there were a "var tabs"); they define what functions you are allowed to use (in this case, that you can call functions in chrome.tabs).
Your problem is that your callback takes an argument of tab, but you use the variable tabs. Hence "tabs is not defined". So the simplest fix would be function(tabs). But you should also use tabs.query instead of the deprecated tabs.getSelected:
chrome.tabs.query({active:true,currentWindow:true}, function(tabs){
chrome.tabs.update(tabs[0].id, {url: "https://www.wikipedia.org/"});
});
You can also change the tabs permission to activeTab.
Related
I'm currently trying to make sense of Google Chrome Extension development, but I'm having issues understanding it correctly.
I'm developing an extension that hosts a list of URLs and opens them on click. This sounds like a trivial task, but it doesn't work. Probably I'm doing something blatantly wrong.
Screenshot
It's not styled, but that's step 2. Basically, I want to open a shortcut on click:
manifest.json
{
"manifest_version": 2,
"name": "Chrome Shortcuts",
"description": "This extension provides shortcuts to locations in Google Chrome",
"version": "1.0.0",
"browser_action":
{
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"content_scripts":
[
{
"js": [ "popup.js" ],
"matches": [ "http://*/*", "https://*/*" ]
}
],
"permissions":
[
"tabs",
"http://*/*"
]
}
popup.html
<!doctype html>
<html>
<head>
<title>Chrome Shortcuts</title>
<script src="popup.js"></script>
</head>
<body>
<ul>
<li>Settings - Passwords</li>
</ul>
</body>
</html>
popup.js
function OpenShortcut(location)
{
chrome.tabs.create({ url: location });
}
You cannot open chrome:// URLs using standard methods. This is a privileged page and the navigation will fail.
Instead, you need to use tabs API. Specifically,
chrome.tabs.create({url: "chrome://settings/passwords"});
Add active: false if you need it to open in background without closing the popup.
I completely missed the fact you're doing it already, sorry! The issue is with trying to activate your code with href="javascript:[some code]".
This, as well as onclick="[some code]", will fail in a Chrome extension due to the Content Security Policy. Specifically, inline code is not allowed (and you cannot modify the CSP in a way that allows it).
The docs give a solution to this - assign the handler from your code, i.e.
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('link1').addEventListener('click', function() {
OpenShortcut('chrome://settings/passwords');
});
});
For this to work, add an id attribute to your links. DOMContentLoaded wrapper is required, since your popup.js is executed before your node exists in the DOM.
chrome-extension, stucked with the error
Uncaught TypeError: Cannot read property 'sendRequest' of undefined
here is my code
manifest.json
{
"manifest_version": 2,
"name": "blah",
"version": "1.0",
"description": "blah",
"browser_action": {
"default_icon": "icon.png"
},
"background": "bg.html", // change to your background page
"permissions": ["http://*/*", "tabs"], //need permission to access all pages & tabs
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"], // run for http & https pages
"js": ["key_event.js"], // key_event.js is injected to the page, this handles key press
"run_at": "document_start" // run before everything else, else there will be conflicts at pages which accept keyboard inputs ( eg:google search)
}
]
}
key_event.js
if (window == top) {
window.addEventListener('keyup', doKeyPress, false); //add the keyboard handler
}
function doKeyPress(e){
if (e.keyCode == 17){ // if e.shiftKey is not provided then script will run at all instances of typing "G"
alert("pressed");
chrome.extension.sendRequest({redirect: "https://www.google.co.in"});//build newurl as per viewtext URL generated earlier.
}
}
bg.html
chrome.extension.onRequest.addListener(function(request, sender) {
chrome.tabs.update(sender.tab.id, {url: request.redirect});
});
plz help me
As already mentioned in comments
The background section of manifest version 2 has to be like
"background": {"scripts": ["bg.js"]}
There is no background page, only background scripts. So you'll have to move your code from bg.html to bg.js and remove all the extra HTML from it.
chrome.extension.sendRequest and chrome.extension.onRequest have been deprecated in favor of chrome.runtime.sendMessage and chrome.runtime.onMessage respectively. That means, you can still use sendRequest and onRequest but it might be subject to removal in a future version of Chrome
The keyCode for G is 71 rather than 17
I'm writing my first Chrome Extension. I've used permission, but I'm seeing my button everywhere.
How can I only show the button on the addresses I'm writing the extension for?
Although the answer from #Sorter works, it is not the best way to solve the problem.
First and foremost, it does not always work. If the page used history.pushState, the page action will disappear and not come back until you trigger the onUpdated or onHighlighted event again Chromium issue 231075.
Secondly, the method is inefficient, because it's triggered for every update of tab state on all pages.
The most efficient and reliable way to get a page action to appear on certain domains is to use the declarativeContent API. This is only available since Chrome 33. Before that, the webNavigation API was the most suitable API. The advantage of these API over the method using the tabs API is that you can safely use event pages, because you can declare URL filters. With these URL filters, the events will only be triggered if you navigate to a page that matches the URL filters. Consequently, your extension/event page will not be activated until really needed (= no wasted RAM or CPU).
Here's a minimal example (background.js) using the webNavigation API:
function onWebNav(details) {
if (details.frameId === 0) {
// Top-level frame
chrome.pageAction.show(details.tabId);
}
}
var filter = {
url: [{
hostEquals: 'example.com'
}]
};
chrome.webNavigation.onCommitted.addListener(onWebNav, filter);
chrome.webNavigation.onHistoryStateUpdated.addListener(onWebNav, filter);
manifest.json:
{
"name": "Name ",
"version": "1",
"manifest_version": 2,
"background": {
"scripts": ["background.js"],
"persistent": false
},
"page_action": {
"default_title": "Only visible on stackoverflow.com"
},
"permissions": [
"webNavigation"
]
}
If you target Chrome 33 and higher, then you can also use the declarativeContent API instead. Simply replace the "webNavigation" permission with "declarativeContent", and use the following background script (background.js):
chrome.runtime.onInstalled.addListener(function() {
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([{
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: {
hostEquals: 'example.com'
}
})
],
actions: [new chrome.declarativeContent.ShowPageAction()]
}]);
});
});
In both examples, I used a UrlFilter that matches the example.com domain.
Create background.js which checks for updated and highlighted tab.
function checkForValidUrl(tabId, changeInfo, tab) {
// If 'example.com' is the hostname for the tabs url.
var a = document.createElement ('a');
a.href = tab.url;
if (a.hostname == "example.com") {
// ... show the page action.
chrome.pageAction.show(tabId);
}
};
// Listen for any changes to the URL of any tab.
chrome.tabs.onUpdated.addListener(checkForValidUrl);
//For highlighted tab as well
chrome.tabs.onHighlighted.addListener(checkForValidUrl);
Create popup.html and popup.js in the similar manner.
You can use the variables defined in background.js in content scripts (popup.js) with
chrome.extension.getBackgroundPage().variableName
Here's the example extention download link.
For your reference and ease, here's the sample manifest.json file
{
"manifest_version": 2,
"name": "Example Extension",
"version": "1.0",
"background": {
"scripts": ["background.js"]
},
"page_action":{
"default_icon": "images/icon_16.png",
"default_popup": "popup.html",
"default_title": "Title for the extension"
},
"permissions": [
"tabs"
]
}
An Updated Way:
I use the following with great success:
chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
var url = info.url || tab.url;
if(url && url.indexOf('example.com') > -1)
chrome.pageAction.show(tabId);
else
chrome.pageAction.hide(tabId);
});
How can I create an extension for Chrome that adds an icon to the toolbar, and when you click it, it opens a new tab with some local web page (for example: f.html)?
I saw this question, but it doesn't really explains what should I add in the manifest file...
This is not true for newer chrome apps.
Newer chrome apps having manifest_version: 2
requires the tabs be opened as:
chrome.browserAction.onClicked.addListener(function(activeTab)
{
var newURL = "http://www.youtube.com/watch?v=oHg5SJYRHA0";
chrome.tabs.create({ url: newURL });
});
Well, in the extensions docs, it states in manifest, you would need to include "tabs" as its permission. Same way they explain the hello world application:
Manifest File:
{
"name": "My Extension",
"version": "1.0",
"description": "Opens up a local webpage",
"icons": { "128": "icon_128.png" },
"background_page": "bg.html",
"browser_action": {
"default_title": "",
"default_icon": "icon_19.png"
},
"permissions": [
"tabs"
],
}
Within the background page, you listen to the mouse click event on the browser action.
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.create({'url': chrome.extension.getURL('f.html')}, function(tab) {
// Tab opened.
});
});
As you noticed above, you will see that I used the question you saw in the other post. Note, this isn't tested, but I believe it should work.
chrome.tabs.create need the permission of "tabs".
Simply using window.open in extension without need of any permission. and the code is shorter. I suggest this solution.
window.open(url,'_blank');
So I am writing my own chrome extension and I have the following content_scripts:
"content_scripts": [{
"matches": ["*://*.youtube.com/*"],
"exclude_globs": ["*user*"],
"css": ["youtube.css"]
}]
As you can see, it runs on youtube. It should however not run on youtube.com/user/, which is why I have an exclude_globs field. However, its not working and it still runs when viewing a user's channel. Anyone got any ideas?
It is a known bug in Chrome , as a work around use insertCSS
Ex:
Following Code in background.js will do the same job as in manifest.json
//Use chrome.tabs.onUpdated.addListener(function(integer tabId, object changeInfo, Tab tab) {...}); as applicable to ensure it works on every page
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.insertCSS(null, {
code: "document.body.bgColor='red'",
"all_frames": true
});
});
OR
//Use chrome.tabs.onUpdated.addListener(function(integer tabId, object changeInfo, Tab tab) {...}); as applicable to ensure it works on every page
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.insertCSS(null, {
file: {file:"content.css"},
"all_frames": true
});
});
Ensure you have enough permissions in manifest
/* in manifest.json */
"permissions": [
"tabs", "http://*/*"
],
References
a) insertCSS
b) Programmatic Injection
Hope this helps.