Trigger Chrome extension on new tab open - javascript

I need to run Chrome extension when new tab is opened and html document is loaded.
Extension needs to check for new tab title and if it's equal to predefined string, tab should close.
For now, I have manage to write extension that works when I click on it's icon. But I want to make it to run without click on icon after the page is loaded in new tab.
Here is the current code.
function getCurrentTabData(callback) {
var queryInfo = {
active: true,
currentWindow: true
};
chrome.tabs.query(queryInfo, function(tabs) {
var tab = tabs[0];
var title = tab.title;
var id = tab.id;
callback(title, id);
});
}
document.addEventListener('DOMContentLoaded', function() {
getCurrentTabData(function(title, id) {
if(title == 'Page title') {
chrome.tabs.remove(id, function() { });
}
});
});
And here is my manifest.json
{
"manifest_version": 2,
"name": "Auto close tab",
"description": "Auto closes tab if title is matched",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png"
},
"permissions": [
"activeTab"
]
}
How to make it run without click on it's icon?

To accomplish this first of all you will need to have a Background Page that will manage your extension state. You can read about it here: https://developer.chrome.com/extensions/background_pages
Then in the background page script you will need to listen when the tab is created with this piece of code:
chrome.tabs.onCreated.addListener(function callback)
Here is documentation for this: https://developer.chrome.com/extensions/tabs#event-onCreated
Hope this will help to solve your issue.

Related

Firefox extension getSelection().toString() not getting the selected text

I'm making a basic Firefox extension, which takes the selected text on a page, puts it into an URL and opens it in a new tab. I'm struggling with taking the selected text.
I'm aware of the Firefox bug in textarea and input, however, I'm testing it on regular page text.
manifest.json:
{
"manifest_version": 2,
"name": "Send2search test",
"version": "1.0",
"permissions": ["menus"],
"background": {
"scripts": ["bg.js"]
},
}
bg.js:
browser.menus.create(
{
id: "gglSearch",
title: "Search in new tab.",
contexts: ["selection"],
},
);
browser.menus.onClicked.addListener(async function (info, tab) {
var selectedTxt = window.getSelection().toString();
if (info.menuItemId == "gglSearch") {
var searchUrl = `https://www.google.com/search?q=${selectedTxt}`;
let openNewTab = browser.tabs.create(
{
active: false,
url: searchUrl,
index: tab.index+1
}
);
};
});
Every time it just opens blank google search, so nothing is saved in the selectedTxt variable. What am I doing wrong?
I also tried content.getSelection().toString() instead (https://stackoverflow.com/a/670258/20367262), but that caused the new tab to not get created at all.
PS: I know Firefox has "Search Google for" on right click by default, I'm just trying to work out extension developing basics on this.

Chrome extension working on two tabs

I am trying to create a Chrome extension that retrieves some content from the DOM of the current tab, then opens a new tab, and performs an operation on this new tab using the previously retrieved content.
I am attempting to use callbacks to perform this sequence, but I can't figure out a proper way to do it. Now I am able to execute the first script, and get the content from the current tab DOM: what I still can't do is passing this content to the second script, utilities2.js, to be executed on the new tab.
Here's my current code:
popup.html
<!doctype html>
<html>
<head><title>Extension</title></head>
<body>
<button id="clickactivity">Click here</button>
<script src="popup.js"></script>
</body>
</html>
popup.js
function injectTheScript() {
var tempStorage;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.executeScript(tabs[0].id, {file: "content_script.js"}, function(results){
tempStorage = results[0];
});
chrome.tabs.create({"url":"http://www.google.com","selected":true}, function(tab) {
});
});
}
document.getElementById('clickactivity').addEventListener('click', injectTheScript);
contentScript.js
function execContentScript() {
var code = document.getElementById('textarea').value;
return code;
}
execContentScript();
manifest.json
{
"manifest_version": 2,
"name": "My extension",
"description": "My extension",
"version": "1.0",
"permissions": ["tabs", "<all_urls>","activeTab"],
"browser_action": {
"default_popup": "popup.html"
}
}
You can store the content in the local storage of Chrome extension and after navigating to next tab, you can get the content from local storage of Chrome.
The following code may help you in this case:
chrome.storage.local.set({key: value}, function() {
console.log('Value is set to ' + value);
});
chrome.storage.local.get(['key'], function(result) {
console.log('Value currently is ' + result.key);
});
If you want to learn more about the local storage of Chrome, please read from here.
Edit:
I think you don't have idea of background scripts in the Chrome extension. Background scripts which have highest privileges to run the Chrome commands.
The complete workflow will be as follows:
popup.js is included as script
When you click button, injectTheScript function will be called from popup.js
Then it will get the element id from page and then send the request to background.js
Then background.js will save the value to Chrome storage
Then background.js will create new tab
After successful creation of tab, it will execute callback function and get the value from storage of Chrome
The following is the complete code of working extension:
manifest.json
{
"manifest_version": 2,
"name": "My extension",
"description": "My extension",
"version": "1.0",
"permissions": ["tabs", "<all_urls>","activeTab","storage"],
"browser_action": {
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"],
"persistent": false
}
}
popup.html
<!doctype html>
<html>
<head><
title>Extension</title>
</head>
<body>
<button id="clickactivity">Click here</button>
<script src="popup.js"></script>
</body>
</html>
popup.js
function injectTheScript() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var code="abc";
//var code = document.getElementById('textarea').value;
chrome.runtime.sendMessage({type: "navigate",value:code}, function(response) {
console.log('code saved to local storage');
});
});
}
document.getElementById('clickactivity').addEventListener('click', injectTheScript);
background.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.type == "navigate"){
chrome.storage.sync.set({key: request.value}, function() {
console.log('Background got request for saving the code '+request.value+' to local storage');
chrome.tabs.create({"url":"http://www.google.com","selected":true}, function( tab) {
console.log('navigated to new tab');
chrome.storage.sync.get(['key'], function(result) {
console.log('new tab key is '+result.key);
});
});
});
}
});
You don't need utilities2.js and content_script.js.
I've tested the code and it's working according to your requirements.
You can not see the console output if anything is consoled in background page. To see the output on console (for anything in background), open the link chrome://extensions
and click the button Background Page as following
A new window will appear as following

onActiveChanged not working every time

I created a simple chrome extension with the following data but for some reason it is not working all the time, there are times which I need to click on the extension button for it to work next time in the current tab.
I am unable to understand why.. it should ALWAYS work when you click on a tab and activate it (even when you create a new tab - it become activated and should run do-something.js
manifest.json
{
"manifest_version": 2,
"name": "Test",
"description": "Test",
"version": "1",
"browser_action": {
"default_icon": "icon.png",
},
"background": {
"scripts": ["background.js"],
"persistent": false
},
"permissions": [
"activeTab",
"tabs"
]
}
background.js
chrome.tabs.onActiveChanged.addListener(function () {
chrome.tabs.executeScript({
file: 'do-something.js'
});
});
do-something.js
function createNotification() {
var notification = document.createElement('div');
Object.assign(notification.style, {
position: 'fixed',
zIndex: 10000,
textAlign: 'center',
width: '100%',
background: '#f5ae20',
padding: '5px',
top: 0,
left: 0
});
notification.innerHTML = `Test`;
document.body.appendChild(notification);
setTimeout(function() {
notification.remove();
}, 4000);
return notification;
}
createNotification();
Why is it not working all the time?
there is some issue with your code. do-something.js should be mentioned in the manifest file otherwise chrome will not find anything, you can put is as content script, background script or web accessible resource.
But if you put it as content script than it will run every time when the page will load (according) to your current code.
Here is my approach
I put the do-something.js in content script and made a communication channel between background js and content script when in the background it finds that active tab has changed then send a message to content script and display the notification
message passing from background
//listener for detecting tab change
chrome.tabs.onActiveChanged.addListener(function () {
console.log("tab changed");
//query about the active tab and get the tab id
//if you add debug point here it will throw exception because debugger is the current active window , which doesnot have tab
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
//send the message to the content sctipt
chrome.tabs.sendMessage(tabs[0].id, "showNotification", null);//here null is the callback
});
});
Message reception on content script
chrome.runtime.onMessage.addListener(
function (message, sender, sendResponse) {
//you can receive different type of message here
if (message == "showNotification") {
createNotification();
}
});
I have added a github repo for you, you can find more details there.
https://github.com/pfrng/tabChangeListener
Thanks

How to run script on ContextMenu Click Chrome Extension

I'm tried to run script on ContextMenu Click event. I'm used example ContextMenu which have manifest:
{
"name": "Context Menus Sample (with Event Page)",
"description": "Shows some of the features of the Context Menus API using an event page",
"version": "0.7",
"permissions": ["contextMenus"],
"background": {
"persistent": false,
"scripts": ["sample.js"]
},
"manifest_version": 2
}
sample.js:
function onClickHandler(info, tab) {
chrome.tabs.executeScript(null,
{code:"document.body.style.backgroundColor='" + e.target.id + "'"});
};
chrome.contextMenus.onClicked.addListener(onClickHandler);
chrome.runtime.onInstalled.addListener(function() {
var contexts = ["page","selection","link","editable","image","video",
"audio"];
for (var i = 0; i < contexts.length; i++) {
var context = contexts[i];
var title = "Test '" + context + "' menu item";
var id = chrome.contextMenus.create({"title": title, "contexts":[context],
"id": "context" + context});
}
chrome.contextMenus.create({"title": "Oops", "id": "child1"}, function() {
if (chrome.extension.lastError) {
console.log("Got expected error: " + chrome.extension.lastError.message);
}
});
});
and i also change onclick handler to:
function onClickHandler(info, tab) {
chrome.tabs.executeScript(null, {file: "content.js"});
};
when content.js is:
document.body.innerHTML = document.body.innerHTML.replace(new RegExp("text", "gi"), "replaced");
but both of that doesn't working. How to solve it?
Because this question has hundreds of views so I will answer this my old question to help anyone who has the same problem. The answer is based on wOxxOm's comment. I just need to add activeTab permission to the manifest. So should be like this:
{
"name": "Context Menus Sample (with Event Page)",
"description": "Shows some of the features of the Context Menus API using an event page",
"version": "0.7",
"permissions": ["contextMenus","activeTab"],
"background": {
"persistent": false,
"scripts": ["sample.js"]
},
"manifest_version": 2
}
My script before doesn't work because I have code that needs to read/change current active tab content. activeTab permission gives an extension temporary access to the currently active tab when the user invokes the extension - for example by clicking its browser action.

"Attempting to use a disconnected port object" while sending message from content to popup in Chrome extension

So, I need to pass messages from popup to content and vice versa. Currently here is what I am doing now, but this does not work how it's supposed to work:
manifest.json:
{
// Required
"manifest_version": 2,
"name": "Extension name",
"version": "0.1",
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["content.js"]
}
],
"browser_action" : {
"default_title" : "Extension name",
"default_popup" : "popup.html"
},
"permissions": [
"tabs",
"*://*/*",
"contextMenus"
]
}
popup.js
var port = "";
window.onload = function()
{
document.getElementById("captureImage").onclick = captureImage;
}
function captureImage(isBig = true)
{
chrome.tabs.query({'active': true}, function (tabs) {
port = chrome.tabs.connect(tabs[0].id, {name: "Besada"});
port.onMessage.addListener(function(msg) {
alert(msg.message);
});
port.postMessage({message: "getCoords"});
});
}
and content.js
chrome.runtime.onConnect.addListener(function(port){
port.onMessage.addListener(function(msg) {
});
port.postMessage({message: "hello!"}); // this message I receive
document.onmouseup = function(e) {
port.postMessage({message: "hello!"}); // this message produces an error
};
});
What I need is message to be sent when user releases the left mouse button. Here is what happens: when I am clicking a button in my popup.html, the alert with the text "Hello" shows, but when I am clicking anywhere in the page after that, I am getting an error: Uncaught Error: Attempting to use a disconnected port object
What am I doing wrong and how can I fix this?
My guess the port is disconnecting when popup closes when I click on page, but I'm not really sure about this.
The popup ceases to exist as a document when you click elsewhere. It's like a tab that has closed. As such, there's no longer anything to communicate to.
The proper way to fix it is to communicate with the background page instead, or use the non-volatile chrome.storage. Then, when the popup is opened, you can use either information source to show content.

Categories

Resources