How can I run a extension with Google Chrome for Youtube? - javascript

Hello there,
I want to remove thumbnail images that appear on YouTube. I am using the following code for this.
while (true) {
$("ytd-thumbnail").remove()
}
When I paste this code into console, all thumbnail images are removed. I want it to work on the backplane by adding an extension. The code for the plug-in I'm preparing is below.
manifest.json;
{
"manifest_version": 2,
"name": "test",
"description": "test extension",
"version": "1.0",
"browser_action": {
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
]
}
popup.html
<!doctype html>
<html>
<head>
<title>TEST</title>
<script src="popup.js"></script>
</head>
<body>
<h1>TEST</h1>
<button id="checkPage">Check !</button>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function() {
chrome.tabs.getSelected(null, function(tab) {
d = document;
while (true) {
$("ytd-thumbnail").remove()
}
});
}, false);
}, false);
When I press the checkPage button nothing happens. But this code works when I add a console. What is the problem? Thanks in advance.

There are several issues with the extension :
You are trying to use $ i.e. jquery which is not available in your
popup.js
You are trying to access "ytd-thumbnail" dom elements which belong
to youtube page and not your popup.html. So, even if you replace $
with document.querySelector , you won't find those elements.
I created a working version that looks something like this. I have not included popup.html which is same as yours.
manifest.json
{
"manifest_version": 2,
"name": "Hello Extensions",
"description" : "Base Level Extension",
"version": "1.0",
"browser_action": {
"default_icon": "hello_extensions.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["background.js"],
"all_frames" : true
}
],
"permissions": [
"activeTab",
"tabs"
]
}
2.popup.js
document.addEventListener('DOMContentLoaded', function()
{
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function()
{
chrome.tabs.query({"active":true}, function (tabs){
chrome.tabs.sendMessage(tabs[0].id, "removeThumbnails", function (response) {
});
});
});
});
When the button is clicked, retrieve the active tab and send it a "removeThumbnails" message.
3.background.js
chrome.runtime.onMessage.addListener(function(message, callback) {
if (message == "removeThumbnails")
{
var elements = document.querySelectorAll("ytd-thumbnail");
elements.forEach(a => a.parentNode.removeChild(a));
}
});
background.js is content script and runs in youtube page. It can now access all the dom elements in youtube page. When we receive a "removeThumbnails" message , get all ytd-thumbnail elements and remove them from page.

Related

Chrome extension message listener fires twice

I'm working on Chrome extensions. I try to learn messaging between content and background. I develop simple project for this. But I have issue.
Basic idea is
User click button on extension popup
A function (bot.js) find image from content of tab then extension (background.js) will download it.
The issue is port.onMessage.addListener() in background.js fired twice.
When background.js sends message to contentscript.js there are two same messages in console or when I try to download in background.js (the code line "Do Something") it download the file twice.
How can I solve this problem?
popup.html
<!doctype html>
<html>
<head>
<title>Test Plugin</title>
<script src="background.js"></script>
<script src="popup.js"></script>
</head>
<body>
<h1>Test Plugin</h1>
<button id="btnStart">Button</button>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('btnStart');
checkPageButton.addEventListener('click', function() {
GetImages("Some URL");
}, false);
}, false);
var tab_title = '';
function GetImages(pageURL){
// Tab match for pageURL and return index
chrome.tabs.query({}, function(tabs) {
var tab=null;
for(var i=0;i<tabs.length;i++){
if(tabs[i].url==undefined || tabs[i].url=="" || tabs[i]==null){}
else{
if(tabs[i].url.includes(pageURL)){
tab=tabs[i];
break;
}
}
}
if(tab!=null){
chrome.tabs.executeScript(tab.id, {
file: "bot.js"
}, function(results){
console.log(results);
});
}
});
}
bot.js
var thumbImagesCount = document.querySelectorAll('.classifiedDetailThumbList .thmbImg').length;
var megaImageURL=document.querySelectorAll('.mega-photo-img img')[0].src;
console.log(megaImageURL + " from bot.js");
port.postMessage({key:"download", text: megaImageURL});
background.js
chrome.runtime.onConnect.addListener(function (port) {
console.assert(port.name == "content-script");
port.onMessage.addListener(function(message) {
console.log(message);
if(message.key=="download"){
// Do Something
// Event fires twice
port.postMessage({key:"download", text: "OK"});
}
})
});
contentscript.js
console.log("content script loaded!");
var port = chrome.runtime.connect({name: "content-script"});
port.onMessage.addListener(function(message){
console.log(message);
});
manifest.json
{
"manifest_version": 2,
"name": "Test Extension",
"description": "This extension will download images from gallery",
"version": "1.0",
"icons": {
"16": "bot16.png",
"48": "bot48.png",
"128": "bot128.png" },
"browser_action": {
"default_icon": "bot48.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"downloads",
"http://*/",
"https://*/"
],
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["contentscript.js"]
}
]
}
The background script declared in manifest.json already has its own page, a hidden background page where it runs, so you should not load it in the popup as it makes no sense in case there are listeners for API events, the background page is already listening for them. In this case the copy also creates the second listener while the popup is open.
Solution: don't load background.js in popup.
See also Accessing console and devtools of extension's background.js.

Chrome Extension Content Script Never Run

Hello, I am writing a simple chrome extension which will be used to:
1. open new webpage
2. fill timesheet form based on pasted string array
3. submit timesheet (just clicking "ok" button in the form)
4. open new webpage
For this to work my extension needs to contain:
1. popup.html Browser Action popup, with input textfield for string array, and submit button.
2. timesheet.js - javascript file to add logic to popup.html
3. background.js - background page to take care of filling form, after clicking submit button
4. content_script.js - to access newly opened webpage DOM, to fill the form.
For now, I made a simplified version, which is supposed to:
1. open www.google.com in new tab
2. wait few seconds (optionally, wait or page to finish loading)
3. change background color
Everything seems to be woring fine, except for content_script.js listener doesn't react to message send by background.js
Here is the code:
manifest.json:
{
"manifest_version": 2,
"name": "Timesheet Filler",
"description": "Description.",
"version": "1.0",
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["http://www.google.com/*"],
"js": ["content_script.js"]
}],
"browser_action": {
"default_title": "Timesheet Filler",
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"activeTab",
"http://www.google.com/*"
]
}
popup.html:
<!DOCTYPE html>
<html>
<body>
<button id="btn" >Click Me!</button>
<script src="timesheet.js"></script>
</body>
</html>
timesheet.js:
document.addEventListener('DOMContentLoaded', function(){
init();
});
function init(){
var btn = document.getElementById('btn');
btn.onclick = function() { onBtnClick(); }
}
function onBtnClick(){
chrome.runtime.sendMessage({action:"btnClick"}, btnClickCallback);
}
function btnClickCallback(any){
alert(any);
}
background.js
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if(message.action == "btnClick"){
chrome.tabs.create({url: "http://www.google.com", active:true});
setTimeout(function(){ delayed(); }, 3000);
}
});
function delayed(){
chrome.tabs.query({active:true}, queryCallback);
}
function queryCallback(arr){
var tabId = arr[0].id;
console.log("message shown 3 second after clicking button") // THIS IS WORKING
chrome.tabs.sendMessage(tabId, {action:"doSomething"}); // CONTENT SCRIPT DOESNT REACT TO THIS
}
function contentScriptCallback(any){
alert(any);
}
content_script.js:
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if( message.action == "doSomething"){
document.body.style.backgroundColor='#000000';
alert("do something");
}
});
Download all files in one ZIP here
How to make content_script.js react to to message and change webpage bg color?
SOLUTION: (thanks to #wOxxOm)
Content script wasn't called since matches in content_scripts section as well as permisions of manifest.json was defined wrong.
Easiest fix was to change URL range to: <all_urls>
(for precise urls matches see this link)
Fixed manifest.json:
{
"manifest_version": 2,
"name": "Timesheet Filler",
"description": "Description.",
"version": "1.0",
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content_script.js"]
}],
"browser_action": {
"default_title": "Timesheet Filler",
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"activeTab",
"<all_urls>"
]
}

Extension manifest must request permission to access this host

I am trying to append a div to page of current active tab. However I am getting this error:
Error during tabs.executeScript: Cannot access contents of url ....
Extension manifest must request permission to access this host.
My Code: (show_loader.js)
var dv = document.createElement('div');
dv.id = 'myid';
dv.innerHTML = 'test';
document.body.appendChild(dv);
However when I put this code:
document.body.style.backgroundColor = 'green';
It works as expected and background color of current tab is changed with no other change except for the code in show_loader.js file which is run from popup.js like this:
chrome.tabs.executeScript(null, {file: "show_loader.js"});
My Manifest file also does have:
"permissions":
[
"tabs",
"notifications",
"http://*/",
"https://*/"
],
So I wonder why it gives above error when I try to do anything else other than setting background color. Even simple alert or console.log alone on that page gives same above mentioned error.
How to fix that ?
Update: Complete Relevant Code
Manifest:
{
... name and description ...
"icons":
{
"16" : "img/icon.png",
"48" : "img/48.png",
"128" : "img/128.png"
},
"permissions":
[
"tabs",
"notifications",
"http://*/*",
"https://*/*"
],
"browser_action":
{
"default_icon": "img/icon.png",
"default_title": "Page title",
"default_popup": "popup.html"
}
}
popup.js
// send data to server for saving
$('#btn').click(function(){
chrome.tabs.executeScript(null, {file: "show_loader.js"});
$loader.show();
var data = $(this).closest('form').serialize();
$.ajax({.....});
});
window.onload = function(){
var $loader = $('#loader');
$loader.show();
chrome.tabs.getSelected(null, function(tab) {
//console.log(tab);
$('#url').val(tab.url);
$('#title').val(tab.title);
$loader.hide();
});
};
popup.html
<html>
<head>
<link rel="stylesheet" href="css/style.css" type="text/css" />
</head>
<body>
<form action="" method="post" name="frm" id="frm">
<table border="0" cellpadding="3" cellspecing="0" width="370">
......
</table>
</form>
<script src='js/jquery.js'></script>
<script src='popup.js?v=014423432423'></script>
</body>
</html>
show_loader.js
console.log($); // doesn't work
// document.body.style.backgroundColor = 'green'; // WORKS
Code which worked
manifest.json
{
"name": "Manifest Permissions",
"description": "http://stackoverflow.com/questions/14361061/extension-manifest-must-request-permission-to-access-this-host",
"version": "1",
"manifest_version": 2,
"browser_action": {
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"notifications",
"http://*/",
"https://*/"
]
}
popup.html
<html>
<head>
<script src="back.js"></script>
</head>
<body>
<button id="tmp-clipboard">Click Me</button>
</body>
</html>
back.js
document.addEventListener("DOMContentLoaded", function () {
document.getElementById('tmp-clipboard').onclick = function () {
chrome.tabs.executeScript(null, {
file: "script.js"
});
}
});
script.js
var dv = document.createElement('div');
dv.id = 'myid';
dv.innerHTML = 'test';
document.body.appendChild(dv);
Try Eliminating deprecated chrome.tabs.getSelected from your code and use chrome.tabs.query instead.
Sample Usage
chrome.tabs.query({
"currentWindow": true,
"status": true,
"active": true //Add any parameters you want
}, function (tabs) {//It returns an array
for (tab in tabs) {
//Do your stuff here
}
});
Edit 1
If you intention is to capture active browsing tab in current window where he clicked browser action use this code
chrome.tabs.query({
"currentWindow": true,//Filters tabs in current window
"status": "complete", //The Page is completely loaded
"active": true // The tab or web page is browsed at this state,
"windowType": "normal" // Filters normal web pages, eliminates g-talk notifications etc
}, function (tabs) {//It returns an array
for (tab in tabs) {
$('#url').val(tabs[tab].url);
$('#title').val(tabs[tab].title);
$loader.hide();
}
});
The manifest v3 uses a different permission schema. This is what worked for me:
"host_permissions": [
"https://music.youtube.com/*"
],

How to show the content of an url on an extension's popup?

I'm trying to make a Chrome extension that gets the current page's URL and uses it to create and show a QR code that links to it with the below Google API.
This is my popup.js
chrome.tabs.getSelected(null,function(tab) {
var tablink = tab.url;
});
document.write('https://chart.googleapis.com/chart?chs=100x100&cht=qr&chl=' + tablink);
and this is my manifest.json
{
"name": "Qrit",
"version": "1.0",
"manifest_version": 2,
"description": "Instantly creates a QR Code that links to the current page.",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs"
]
}
The problem is that the popup is simply blank.
I know almost nothing about Javascript, nor Json.
As Tom said, with manifest version 2 you cant have inline scripts. Also, chrome.tabs.getSelected is decapitated and you should use chrome.tabs.query.
Here's something to get you started....
manifest.json
{
"name": "Qrit",
"version": "1.0",
"manifest_version": 2,
"description": "Instantly creates a QR Code that links to the current page.",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs"
]
}
popup.html
<!DOCTYPE html>
<html>
<head>
<script src='popup.js'></script>
</head>
<body>
<div id='message'>Getting Image....</div>
</body>
</html>
popup.js
function onImageLoad() {
var message = document.querySelector('#message');
message.parentNode.removeChild(message);
}
function onImageError(e) {
var message = document.querySelector('#message');
message.innerText = 'Error getting image';
e.srcElement.parentNode.removeChild(e.srcElement);
}
function onWindowLoad() {
chrome.tabs.query({
'active': true,
'windowId': chrome.windows.WINDOW_ID_CURRENT
}, function(tab) {
var image = document.createElement('IMG');
image.src = 'https://chart.googleapis.com/chart?chs=100x100&cht=qr&chl=' + tab[0].url;
document.body.appendChild(image);
image.onload = onImageLoad;
image.onerror = onImageError;
});
}
window.onload = onWindowLoad;
First you write "manifest_version": 2,it doesn't allow inline script.Second,your popup code should write like this
chrome.tabs.getSelected(null,function(tab) {
var tablink = tab.url;
document.write('https://chart.googleapis.com/chart?chs=100x100&cht=qr&chl=' + tablink);
});

Background code runs on any popup click

I'm trying to get login code in background page to run only once on browser start. But it seems global code in bgpage runs every time on popup clicked. Also it runs in different scope. Is it possible to solve this?
// background.js
var someCustomType = new SomeCustomType();
function SomeCustomType() {
this.firstProperty;
}
function thisShouldBeCalledOnce() {
someCustomType.firstProperty = 'defined';
alert('someCustomType.firstProperty=' + someCustomType.firstProperty);
console.log('thisShouldBeCalledOnce');
}
if (true) {
// Alwase 'undefined'
alert('someCustomType.firstProperty=' + someCustomType.firstProperty);
thisShouldBeCalledOnce();
}
Simple code example:
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"
},
"background": {
"scripts": ["background.js"]
},
"permissions": [
"tabs",
"http://*/*",
"https://*/*"
]
}
popup.html: just some dummy code:
<html>
<head>
</head>
<body>
<div>
<p> sometext</p>
<button type="button">Click Me</button>
</div>
</body>
</html>
background.js:
var someCustomType = new SomeCustomType();
function SomeCustomType() {
this.firstProperty;
}
function thisShouldBeCalledOnce() {
someCustomType.firstProperty = 'defined';
alert('someCustomType.firstProperty=' + someCustomType.firstProperty);
console.log('thisShouldBeCalledOnce');
}
thisShouldBeCalledOnce();
In this case, alert was fired once, when you load your extension, when you open popup no alert will be shown. Regards.

Categories