I have created Chrome extension which should change page body color. It is working when I am clicking on the extension but I want it be done when the page loads, where an alert shows that controls is passing through code, it is not calling the function. Please help to fix this.
----------manifest.json-----------
{
"name": "My Page changer",
"description": "Make the current page red",
"version": "2.0",
"permissions": [
"activeTab"
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_title": "Make this page blue"
},
"manifest_version": 2
}
------------------ background.js--------------------
debugger;
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
debugger;
alert('I am here too ');
/*chrome.tabs.executeScript({
code: 'document.body.style.backgroundColor="blue"'
//code : 'doWhatYouWant()'
});*/
// Execute some script when the page is fully (DOM) ready
chrome.tabs.executeScript(null, {code:"doWhatYouWant();"});
}
});
function doWhatYouWant(){
alert('I am inside doWhatYouWant');
document.body.style.backgroundColor="blue";
}
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Called when the user clicks on the browser action.
chrome.browserAction.onClicked.addListener(function(tab) {
// No tabs or host permissions needed!
alert('i am here');
console.log('Turning ' + tab.url + ' red!');
chrome.tabs.executeScript({
code: 'document.body.style.backgroundColor="red"'
});
});
Your doWhatYouWant function lives in your background page, so you won't be able to call it from a content script.
If the code you want to run is more than a couple lines long, consider putting it into a file in your extension and using the file: field in the InjectDetails parameter when you invoke chrome.tabs.executeScript.
Also, if you want it to run on every page, you can declare it as a content script in your manifest, instead of having the chrome.tabs.onUpdated listener.
There is the "prince" example on google content script tutorial:
https://developer.chrome.com/extensions/content_scripts.html#pi
I tried when learning to "google-extenioning"(?) and it works fine.
Good Luck!
eidt - uh, forgot, files are here
Related
I'm trying to make my first Chrome Extension without any prior JS knowledge, and I have some trouble doing it.
What does the extension do?
It's a page action extension for generating a string and copying it to the clipboard. The string includes certain element attributes from the DOM.
Scope
It's only applicable on two pages (the domains below are examples):
https://xxx.abc.com/CFM/Messages/CFMEWFA/*
https://xxx.abc.com/CFM/Messages/FraudPrevention/*
Elements of the extension
The extension has a popup.html with three clickable options to be chosen at the user's discretion:
No response
Invalid
Valid
The string is formatted based on the user's choice from the popup, and whether the tab URL contains "CFMEWFA" or "FraudPrevention".
popup.html
<!doctype html>
<html>
<body>
<script src="popup.js"></script>
<ul id="MENU">
<li id="MENUnoResponse">No reponse
</li>
<li id="MENUinValid">Invalid
</li>
<li id="MENUvalid">Valid
</li>
</ul>
</body>
</html>
popup.js is supposed to listen for clicks in popup.html, employ a multi item clickhandler, then message background.js at the event of a click. The message should include an argument corresponding to the li id in popup.html.
popup.js
var theParentMenu = document.querySelector("#MENU");
theParentMenu.addEventListener("click", userHasClicked, false);
function userHasClicked(e) {
if (e.target !== e.currentTarget) {
var clickedItem = e.target.id;
chrome.runtime.sendMessage({
directive: e.target.id
}, function(response) {
this.close();
});
};
e.stopPropagation();
}
background.js is governing where the extension icon is shown. It also listens for messages from popup.js (containing an argument determined by the user's choice from popup.html) before executing content.js, a script which runs in the tab.url fetching attributes from the DOM and generating the string. I have yet to start building content.js because of unresolved issues earlier in other files.
background.js
//Displays the page action extension only on specific pages
function checkForValidUrl(tabId, changeInfo, tab) {
if (tab.url.indexOf("https://xxx.abc.com/CFM/Messages/FraudPrevention/") == 0)
{
chrome.pageAction.show(tabId);
}
else if (tab.url.indexOf("https://xxx.abc.com/CFM/Messages/CFMEWFA/") == 0)
{
chrome.pageAction.show(tabId);
}
};
chrome.tabs.onUpdated.addListener(checkForValidUrl)
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
switch (request.directive) {
case "MENUnoReponse":
// execute the content script
chrome.tabs.executeScript(null, { // defaults to the current tab
//file: "contentscript.js", // script to inject into page and run in sandbox
//allFrames: true // This injects script into iframes in the page.
});
sendResponse({}); // sending back empty response to sender
case "MENUinValid":
// execute the content script
chrome.tabs.executeScript(null, { // defaults to the current tab
//file: "contentscript.js", // script to inject into page and run in sandbox
//allFrames: true // This injects script into iframes in the page.
});
sendResponse({}); // sending back empty response to sender
case "MENUvalid":
// execute the content script
chrome.tabs.executeScript(null, { // defaults to the current tab
//file: "contentscript.js", // script to inject into page and run in sandbox
//allFrames: true // This injects script into iframes in the page.
});
sendResponse({}); // sending back empty response to sender
break;
default:
// helps debug when request directive doesn't match
alert("Unmatched request of '" + request + "' from script to background.js from " + sender);
}
}
);
manifest.json
{
"manifest_version": 2,
"name": "EW logger",
"description": "This extension creates logs for early warning and fraud prevention cases",
"version": "1.0",
"page_action": {
"default_title": "EW",
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"]
},
"permissions": [
"tabs",
"clipboardWrite",
"https://xxx.abc.com/*"
]
}
What works:
The extension icon appears like it should.
My problems:
The options in popup.html are not working. Popup.js doesn't do anything when I click.
Do you have any suggestion to how I can "listen" for clicks in popup.html properly, and then send a message containing an argument to background.js?
Your script is running before the body is loaded, so the element is not found. You can fix this by moving the script tag to the bottom of the body. Alternatively, use <script src="popup.js" defer></script> to delay execution until the dom is loaded.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer
Also, you should use console.log(message) and the Chrome Devtools console to debug and check for errors.
https://developer.mozilla.org/en-US/docs/Web/API/Console/log
https://developers.google.com/web/tools/chrome-devtools/
I've developed a Chrome extension that injects a button into the toolbar of a rich-text editor of a specific web page, code available here. This basic extension is based on the concept of the "content script" and works well because the toolbar is present as soon as the page has loaded.
Now, however, I'm confronted by another page where I cannot simply inject my button as soon as the page loads because the user needs to interact with the page first (make a selection or press a button) before the toolbar appears.
So I'm looking for a way to track any changes in the active tab (I have a URL pattern for the page). I don't want or need a browser action (i.e. the little button on the right-hand side of the omnibox), so I was hoping to get away with a background.js event page where I can declare an event listener for certain user-originated events but somehow it's not working.
To explain: I've got my manifest.json, great:
{
"name": "basic tab test",
"description": "blah di blah",
"version": "1.0",
"permissions": [
"activeTab"
],
"background": {
"scripts": ["background.js"], // background script shown below
"persistent": false
},
"content_scripts": [
{
"matches": [
"file://*" // for testing only, of course
],
"js": [
"contentscript.js" // <-- content script shown below
]
}
],
"manifest_version": 2
}
The background.js script looks like this at the moment:
console.log("in background.js");
chrome.tabs.getCurrent(function(tab) {
tab.onActivated.addListener(function(){
console.log("GOT HERE onActivated (inside tab)");
});
});
chrome.tabs.getCurrent(function(tab) {
tab.onZoomChange.addListener(function(){
console.log("GOT HERE onZoomChange (inside tab)");
});
});
// this is actually part of the message passing test
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
});
Of course, these are just tests, but none of the above events actually ever fire. Becoming slightly desperate, I then thought 'well, let's use the message passing method' to send messages from the contentscript.js to the background.js whenever the user presses a button. The contentscript.js looks like this:
document.addEventListener("DOMContentLoaded", function(event) {
console.log("just a canary - got here...");
var btn = document.getElementById("button");
if (btn) {
console.log("there is a button!");
} else {
console.log("there is NO button!");
}
btn.addEventListener("click", function () {
console.log("clicked the button!!!!");
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
})
});
Also, we never arrive inside this event handler (but why oh why?! this is standard jquery-less code for when the DOM is completely loaded). So, this is when I thought I might ask the assembled experts for advice.
TL;DR: I want to track events on the activeTab and if a given DOM element makes its appearance manipulate it (by injecting an element).
By default, "run_at" property for Content Script is "document_idle", which means you scripts will be injected after window.onload event fires, and obviously later than DOMContentLoaded event. So in fact your code in content script is not executed at all.
To make your code work, either:
Remove the outer DOMContentLoaded event listener
Or add "run_at": "document_start" part in your manifest.json
You could take a look at run_at part fore more details.
Whenever my chrome extension icon is clicked, I want to run a script that would make certain changes to the current webpage.
I have tried using content_scripts in my manifest and it worked but the problem is , the script runs even if I did not clicked on the icon.
I have found that, I need to use background script.In my background.js file I have added
chrome.browserAction.onClicked.addListener(function(tab) {
alert();
});
and it is not working.
Here is my manifest file.
{
"manifest_version": 2,
"name": "Reveal Password",
"description": "Reveals password in password input field",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png"
},
"background": {
"scripts": ["background.js"]
}
}
Plus I want to execute the script that I made that manipulates the current web page too.
Use chrome.tabs.executeScript() to execute code in a tab like this:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript({
code: 'alert("Hello")'
});
});
Instead of code, you could also use a file which contains the code :
chrome.tabs.executeScript(null, {file: "content_script.js"});
NOTE : You need activeTab permissions to execute code in an active tab
"permissions": [
"activeTab"
]
I'm trying to create a chrome extension. When the user clicks my extension's icon (browserAction) the content script appends an extra div to the body of the open page(current tab). It works fine in all the sites except google's search page and youtube. I'm not getting any error message or anything. It simply wont give any response.
This is my code in content.js:
alert('sdsd');
$('body').append("<div id='popup'>My extension name</div>");
I've put the alert for testing purpose. So when extension is toggled it should show an alert message followed by appending the div to body, ideally! But it wont for these 2 sites.
Any idea what could be going wrong here?
manifest
{
"name": "My first extension",
"version": "1.0",
"background": { "scripts": ["background.js"] },
"content_scripts": [{
"all_frames": true,
"css": ["style.css"],
"matches": ["http://*/*","https://*/*"]
}],
"permissions": [ "tabs","http://*/*" ],
"browser_action": { "name": "test" },
"manifest_version": 2
}
background.js
chrome.browserAction.onClicked.addListener(function(tab){
chrome.tabs.executeScript(null,{file:"jquery.min.js"},function(){
chrome.tabs.executeScript(null,{file:"content.js"});
});
});
In Youtube's page, $ is overwritten and isn't jQuery. It's
bound: function ()
{
return document.getElementById.apply(document, arguments)
}
So your code makes an exception as there document.getElementById('body') is undefined.
You should try using noConflict().
EDIT :
Why aren't you simply listing jQuery.min.js and your content.js in the content_scripts instead of injecting them programmatically. This would avoid conflicts.
EDIT 2 :
Now that you use content scripts, you should use communication as described here to send from background.js to the content script the instruction to show the alert.
EDIT 3 :
Another solution would have been to use programmatic injection (as you initially did) and not use jquery, $('body').append("<div id='popup'>My extension name</div>"); being translated in vanilla JS to
var div = document.createElement('div');
div.id = 'popup';
document.body.appendChild(div);
document.getElementById('popup').innerHTML = "My extension name";
But it's generally cleaner (and requires less permissions) to avoid programmatic injection.
I'm trying to generate an extension that keeps my brother of facebook. So I decided i'll redirect all facebook links to google for starters.
This is how i went about it.
My manifest.json file :
{
"name": "FBRehab"
"version": "1.0",
"description": "Redirect FB",
"permissions": [
"tabs", "http://www.facebook.com/*", "https://www.facebook.com/*"
],
"browser_action": {
"default_icon": "icon.png",
"background_page": "background.html"
},
]
}
My background.html :
<html>
<head>
<script>
chrome.tabs.executeScript(null, { file: "jquery.js" }, function() {
chrome.tabs.executeScript(null, { file: "try.js" });
});
</script>
</head>
and try.js
<head>
<script language="JavaScript">
var time = null
function move() {
window.location = 'www.google.com'
}
</script>
</head>
Yet, it does not redirect. I've tried directly injecting the try.js using content scripts too.
Please help me.
Thanking you.
Ashar :)
Remember a Background Page runs exactly once in Chrome, it is a single long running script that runs exactly once.
Basically what your code does now is that once your browser loads, it will inject jquery and try Content Scripts to the current tab. You have no tabs that are currently loaded (which it will fail unless you have it auto load a tab). Then it will not do anything anymore because the Background Page runs exactly once!
What you need to do instead is use a Content Script which should be defined as follows:
// Only execute in the top window, we don't want to inject the iframes.
if (window == top) {
window.location = 'www.google.com'
}
In your manifest, you will have the following:
{
"name": "No more Facebook extension",
...
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["redirect.js"]
}
],
...
}
I think you want to use a content script instead of a background page. You can specify that your content script should only run on specific web pages.
Do you ever call move()? Doesn't look like it to me, but I've never developed a Chrome extension before... so I'm not sure if it is ever called automatically.