i'm having a lot of trouble with Chrome Extensions, im trying to close all open tabs that do not contain a certain class.
This is the general idea of what i am trying to do, some of it is pseudo-code.
//background.js
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.query(function(tabs) {
chrome.tabs.sendMessage(tabs, {"message": "clicked_browser_action"});
});
});
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "clicked_browser_action" ) {
for (var i = 0; i < request.length; i++) {
var existsClass = request[i].getElementByClass("someClass");
if (existClass === null) {
//TODO Close tab
}
}
}
}
);
Any help or suggestions would be appreciated.
Thanks!
I'm assuming your second snippet is from a content script.
In that case, it's as simple as window.close(), because you're in that tab's context. No need for Chrome APIs.
Try this:
//background.js
chrome.browserAction.onClicked.addListener(function () { //when the extension's icon is pressed
chrome.tabs.query({},function(tabs) { // get all tabs
for (var i = tabs.length; i--;){ // loop through all tabs
chrome.tabs.executeScript(tabs[i].id,{code: //execute this code in each tab
"if (!document.querySelector(\".someClass\")) close();"});
// ^ if no element is found with the selected class, close the tab
}
});
});
You don't need a separate content script for that.
Related
I created a chrome extension and I want this extension to work in only one open tab. For example, I want this extension to work only on google.com. But although I have two google.com addresses open, I want this extension to work on only one of them. So the content script will only work on one google.com tab. If I close the tab where the extension is running, I want this extension to work again in the google.com tab that I will open.
First of all, I find the tab id matching google by searching all open windows and tabs. If this tab id is removed, I want it to inject content.js in the tab id that matches google it will find again, but this code did not work.
Can you help me?
Background.js :
var count = 0;
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
// for the current tab, inject the "inject.js" file & execute it
chrome.windows.getCurrent(function (win) {
chrome.tabs.getAllInWindow(win.id, function (tabs) {
// Should output an array of tab objects to your dev console.
for (let i = 0; i < tabs.length; i++) {
if (tabs[i].url.match(/google/g) == "google" && tabs[i].status == "complete") {
chrome.storage.sync.set({ indexTabId: tabs[i].id }, function () {
return;
});
}else{
chrome.storage.sync.set({ indexTabId: null }, function () {
return;
});
}
}
});
});
chrome.storage.sync.set({ removed: false }, function () {
});
chrome.storage.sync.get('indexTabId', function (data) {
// removed
chrome.tabs.onRemoved.addListener(function (tabId, info) {
chrome.tabs.get(tabId, function (tabremoved) {
if (data.indexTabId == tabId) {
chrome.storage.sync.set({ removed: true }, function () {
});
}
});
});
chrome.storage.sync.get('removed', function (data) {
if(data.removed){
count = 0;
}else{
count = 1;
}
});
if (data.indexTabId == tab.id && count < 1) {
count++;
console.log(tab.id);
chrome.tabs.executeScript(tab.id, {
file: 'content.js'
});
}
});
});
Sorry for the relatively broad title... So I have a pretty basic chrome extension with a Popup(html\js) and a content page.
Basically all the extension does is put a button on the popup page that when clicked sends a message to the content script to check all check boxes on the page. The code is pretty basic but it is breaking stuff like dropdown menus and general formatting.
Here is all of my code, like I said it's not much. Any ideas what could be going on?
Content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "toggle_checkboxes" ) {
$(':checkbox').each(function() {
if(this.checked)
this.checked = false;
else
this.checked = true;
});
}
else{
//alert("nothing caught, here is the message:" + request.messgae);
}
}
);
popup.js
function toggle_checkboxes() {
chrome.tabs.query({currentWindow: true, active: true}, function (tabs){
var activeTab = tabs[0];
chrome.tabs.sendMessage(activeTab.id, {"message": "toggle_checkboxes"});
});
}
document.getElementById('toggle_checkboxes').addEventListener('click', toggle_checkboxes);
For example if someone is on google.com I need to popup a different page and if someone is on xyz.com I need to pop a different page. Is that possible?
As suggested by wOxxOm, it may be a better solution to have a single popup page with several sections, and hide/show them as appropriate.
Start with all hidden, and at runtime make a decision:
document.addEventListener("DOMContentLoaded", function() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
// Note: this requires "activeTab" permission to access the URL
if(/* condition on tabs[0].url */) {
/* Adapt UI for condition 1 */
} else if (/* ... */) {
/* Adapt UI for condition 2 */
}
});
});
Do note that it's recommended to use Page Actions instead of Browser Actions for things that make sense only on certain pages.
In your background page you can change the page to display in popup.
Use tabs events to get selected tab and current tab url.
Use :
// Update popup url method
var updatePopupURLForSelectedTab = function (selectedTab) {
var popUpURL = DEFAULT_URL_OF_YOUR_HTML_FILE;
var selectedTabURL = selectedTab.url;
if (selectedTabURL.match(/.*\.?google\.com.*/) != null ) {
popUpURL = GOOGLE_URL_OF_YOUR_HTML_FILE;
}
else if (selectedTabURL.match(/.*\.?xyz\.com.*/) != null) {
popUpURL = XYZ_URL_OF_YOUR_HTML_FILE;
}
// Set Popup URL
chrome.browserAction.setPopup({
popup :popUpURL
});
};
// Get current selected Tab
chrome.tabs.getSelected(null, function (tab) {
updatePopupURLForSelectedTab(tab);
});
// Listen for selected tab
chrome.tabs.onActiveChanged.addListener(function(tabId, selectInfo) {
// Get selected tab
chrome.tabs.get(tabId, function (tab) {
updatePopupURLForSelectedTab(tab);
});
});
// Listen navigation update
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
updatePopupURLForSelectedTab(tab);
});
// Listen for window change
chrome.windows.onFocusChanged.addListener(function (windowId) {
chrome.tabs.getSelected(windowId, function (tab) {
updatePopupURLForSelectedTab(tab);
});
});
I am developing a chrome extension and after it is installed it iterates through opened tabs and if the required Tab is not found then I open a new tab. Following is my code:
var found = false;
chrome.tabs.getAllInWindow(null, function(tabs){
for (var i = 0; i < tabs.length; i++) {
var tabUrl = tabs[i].url;
if (tabUrl == 'http://www.youtube.com') {
chrome.tabs.update(tabs[i].id,{url:someUrl,selected:true});
found = true;
}
}
});
if (!found) {
window.open('https://www.youtube.com/watch?v=somevideid');
}
The problem is that whether the youtube is found or not the NOT FOUND if condition always return true and the default video URL is opened where as it should only open if youtube tab is not found. I think the Last if condition is not at the right place, any idea?
You should use chrome.tabs.query() instead of chrome.tabs.getAllInWindow(). The .query method, if called with an empty queryInfo object, will find ALL the tabs.
So, your code should be like this:
chrome.tabs.query({}, function(tabs) {
var found = false;
for (var i=0; i < tabs.length; i++) {
if (/https?:\/\/www\.youtube\.com/.test(tabs[i].url)) {
found = true;
chrome.tabs.update(tabs[i].id, {url: 'https://www.youtube.com/watch?v=somevideid', active: true});
break; // you found it, stop searching and update the tab
}
}
if (!found) chrome.tabs.create({url: 'https://www.youtube.com/watch?v=somevideid', active: true});
// you didn't find it, create a new tab with the new url and select it
});
Also, I used the regexp /https?:\/\/www\.youtube\.com/ to test the url of the tab, because the url may begin with "http" or "https", or may have some query string attached, like "?hl=en" or similars, so using tab[i].url == "http://www.youtube.com/" will not provide you absolute certainty of finding the tab.
I want to run a content script to identify the first image that links somewhere and return the link to the background script. But I can't pass any messages between them, and I don't know why. Much of the code is comment, I'm trying to simply test if the content script is executing by telling it to change the first header to "test" (since the only thing I can do without messages is change a page's HTML and CSS). The code follows:
EDIT: full updated code
Background script:
chrome.browserAction.onClicked.addListener(function () {
chrome.tabs.query({active:true, currentWindow:true}, function(tabs)
{
chrome.tabs.executeScript(tabs[0].id, {file:"content.js"}, function ()
{
console.log("sending first time");
console.log(tabs[0].id);
chrome.tabs.sendMessage(tabs[0].id,{test: "test"}, function (response)
{
if (undefined == response)
{
console.log ("first one didn't work");
chrome.tabs.sendMessage(tabs[0].id, {test: "test"}, function (response)
{
console.log(response.test);
});
}
});
});
});
});
Content Script:
chrome.runtime.onMessage.addListener( function (msg, sender, sendResponse)
{
/*var test1 = document.getElementsByTagName("h1")[0];
test1.innerHTML="test";*/
sendReponse({test: "123"});
/*var parentList =document.getElementsByTagName("a");
var link = "";
var child;
for (var i=2; i<parentList.length;i++)
{
child=parentList[i].firstChild;
if ("IMG"==child.nodeName)
{
link=parentList[i].href;
break;
}
}
teste1.innerHTML=link;
var answer = new Object();
Answer.link = link;
teste1.innerHTML=answer.link;
sendResponse({messager:answer});*/
});
I was testing the extension at the extension page itself. But it seems you can't inject javascript in it (probably because it is a browser's settings page). It worked nicely on other pages.