I found a chrome extension WebNavigation API, but I don't know how to use it. Could someone give me a simple example?
API:
chrome.webNavigation.getFrame(object details, function callback)
If I want to get iframe id and iframe's scr in a page, can I use this API ??
As the docs state, one needs to pass tabId, processId, frameId...
in order to get these values, one needs to listen for .onCompleted():
chrome.webNavigation.onCompleted.addListener(function(e){
chrome.webNavigation.getFrame(
{tabId: e.tabId, processId: e.processId, frameId: e.frameId},
function(details){
console.dir(details);
}
);
});
The event's properties are already known before the .getFrame()
If you want to access page content you should use content scripts
So, for example in the manifest.json:
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://www.example.com/*"],
"js": ["jquery.js", "myscript.js"]
}
],
}
And in myscript.js:
var iframe = document.querySelector('iframe');
alert(iframe.getAttribute('id'), iframe.getAttribute('src'));
Another way is to use programmatic injection which is in fact simplified content scripting.
Update:
To get src from all iframes on the page:
var iframes = document.querySelectorAll('iframe');
for(var i = 0; i < iframes.length; i++){
console.log(iframes[i].getAttribute('id'), iframes[i].getAttribute('src'));
}
Related
I'm building a Google Chrome extension that will add a checkbox to the Compose/Reply window in Gmail. But the console is giving me an error message that it can't read the properties of appendChild (the function I'm using to add this checkbox to the window).
Here's my manifest.json:
"content_scripts": [
{
"matches": ["https://mail.google.com/mail/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
"permissions": [
"tabs",
"https://mail.google.com/*",
"storage"
]
And here is the relevant parts of my contentScript.js file, where the majority of my code is:
// Listen for Reply arrow (top reply) click
let topReplyButton = document.getElementsByClassName('T-I J-J5-Ji T-I-Js-IF aaq T-I-ax7 L3');
topReplyButton[0].addEventListener("click", addUpdateButton);
function addUpdateButton() {
let optionsArea = document.getElementsByClassName("aDh");
if (optionsArea) {
let mauticLabel = document.createElement('label');
mauticLabel.setAttribute('name','mauticLabel');
mauticLabel.innerHTML = "Track with Mautic: ";
mauticLabel.setAttribute('id','mauticLabel');
optionsArea[0].appendChild(mauticLabel);
And this is the error I get in the console when I click the reply button:
Uncaught TypeError: Cannot read properties of undefined (reading 'appendChild')
at HTMLDivElement.addUpdateButton
So something seems to be wrong from the point when I create mauticLabel, but I haven't been able to figure out what's breaking.
Thanks in advance :)
I'm trying to create my first Chrome extension.
It's basically an adblocker for specific elements, in this case - the Facebook comments section.
It works with the all_urls but not with that specific domain.
Manifest file:
{
"name": "My extension",
"version": "1.0",
"manifest_version": 2,
"content_scripts": [
{
"matches": ["http://visir.is/*"], //where your script should be injected
"css": ["style.css"] //the name of the file to be injected
}
]
}
style.css file:
.fbcomment {
display: none;
}
Any ideas how to correct "matches"?
I have tried *://visir.is/* as specified in https://developer.chrome.com/extensions/match_patterns but it only works with all_urls
Viktor,
You are on the wrong way. Your extension should work on Facebook site, and so the matches statement in the manifest must be exactly as the following:
"matches": ["https://www.facebook.com/*"]
Than you need to find all the comments in the timeline (most probably by css class), detect the presence of the target site address (//visir.is/) and then hide these comments.
Because the timeline dynamically load more posts you will also need to observe the new nodes and apply your function on them too (see the example from my Chrome extension below):
var obs = new MutationObserver(function (mutations, observer) {
for (var i = 0; i < mutations[0].addedNodes.length; i++) {
if (mutations[0].addedNodes[i].nodeType == 1) {
$(mutations[0].addedNodes[i]).find(".userContentWrapper").each(function () {
injectFBMButton($(this));
});
}
}
injectMainButton();
});
obs.observe(document.body, { childList: true, subtree: true, attributes: false, characterData: false });
On google chrome, I'd like to intercept some attributes of html tags, and do an action if the attributes has a certain value.
For example, let's say I have a list-item which has an attribute called user:
<li class="MyClass" user="BadUser"> ... </li>
What I would like is to make the content of this item invisible, to delete it, whatever.
I'm new to those extension (I began to take a look at them in this very hour)
How can I do this?
You can use a content script for this purpose. Declare the script (myscript.js in the example below) in your manifest file:
{
"name": "Extension name",
...
"content_scripts":
[
{
"matches": ["*://*/*"],
"js": ["jquery.js", "myscript.js"]
}
],
...
}
Then in the myscript.js write required code, something like this (using jQuery, which is also injected as a content script):
$('[user]').each(function()
{
$(this).removeAttr("user");
});
This is for deleting attribute itself. Of course, you can remove entire element calling remove() instead of removeAttr().
In your content script :
To remove from DOM use this
$('[my_tag]').remove();
And to play with each element you can use this:
$.each($('[my_tag]'), function(index, element) {
console.log(index + ': ' + element);
});
I'm trying to figure out how to write a simple Chrome extension which allows to transliterate web pages from one alphabet to another. Unfortunately Google's documentation on Chrome extensions is pretty much confusing for a beginner. I've seen a lot of similar questions here, f.ex. Replace text in website with Chrome content script extension, but still can't get it clear. In a trial run I'm trying to replace all "a"'s in the page with "Z"'s.
Here's my Manifest.json:
{
"name": "My Chrome extension",
"version": "0.1",
"browser_action": {
"default_icon": "icon.png"
},
"permissions": [
"tabs", "http://*/*", "https://*/*"
],
"content_scripts": [{
"matches": ["http://*/*", "https://*/*"],
"js": ["myscript.js"]
}]
}
Myscript.js:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(
null, {code:"document.body.innerHTML = document.body.innerHTML.replace(new RegExp("a", "g"), "Z")"});
});
But this fails to work. If I include only one line into Myscript.js:
document.body.innerHTML = document.body.innerHTML.replace(new RegExp("a", "g"), "Z");
then all 'a' letters get replaced with 'Z' as soon as the page has loaded, but this is not my goal, as I want to get it working only after the extension button is pressed.
Any help will be much appreciated.
You've set up your extension to inject your code using a content script. A content script will get injected into any page that matches your matches field. What you want is to only inject the script if they click on your Browser action. For this you can either have a background page that listens for the chrome.browserAction.onClicked event and reacts to it. Or you can have a default page for your Browser Action that injects the code into the page and if your put window.close as part of the script this will stop any popup from occuring and allow you to avoid using a background page (Im big on avoiding using a background page when ever possible).
For an example of the first method, check out this sample....
http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/
And here's an example of the second method (which is a modified version of the set_page_color sample)...
manifest.json
{
"name": "A browser action that changes the page color.",
"version": "1.0",
"permissions": [
"tabs", "http://*/*", "https://*/*"
],
"browser_action": {
"default_title": "Set this page's color.",
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"manifest_version": 2
}
popup.html
<!doctype html>
<html>
<head>
<script src="popup.js"></script>
</head>
<body>
</body>
</html>
popup.js
chrome.tabs.executeScript(null,{file:"injectedCode.js"});
window.close();
injectedCode.js
// This was just a quick look at changing text on a page
// there could be more tags you should ignore and there could be a better way of doing this all together
var ignoreTags = ["NOSCRIPT","SCRIPT","STYLE"];
var nodeIterator = document.createNodeIterator(
document,
NodeFilter.SHOW_TEXT,
function (node){
var parentTag = node.parentNode.tagName.toUpperCase();
if ( ignoreTags.indexOf(parentTag)==-1 ) {return true} else {return false};
},
false
);
var node;
while ( (node = nodeIterator.nextNode()) ) {
node.data = node.data.replace(/a/g, 'z');
}
NOTE
As Rob W points out in the comments chrome.tabs and chrome.browserAction are not usable in a content script which is why the chrome.browserAction.onClicked has to be used in a background page.
The code in myscript.js is what gets injected into the page. It doesn't work how you currently have it set up because you are automatically injecting into every page the code that injects in to select pages. You need to move the myscript.js code into a background_page which will then only inject when the button is clicked.
https://code.google.com/chrome/extensions/background_pages.html
How do I write a chrome extension such that every time a user clicks the icon, my script is run but no popup is opened? (I would look this up in the docs myself but for whatever reason they suddenly stopped working, 404ing every page, as I got to this point).
I'm assuming it's just setting up the manifest correctly. Here's what I have now:
{
"name": "My Extension",
"version": "0.1",
"description": "Does some simple stuff",
"browser_action": {
"popup" : "mine.html",
"default_icon": "logo.png"
},
"permissions": [
"notifications"
]
}
Remove popup from your browser_action section of the manifest and use background pages along with browser Action in the background script.
chrome.browserAction.onClicked.addListener(function(tab) { alert('icon clicked')});
First, if you don't want to show a popup, remove "popup" : "mine.html" from your manifest.json (shown in your question).
Your manifest.json will look something like this:
{
"name": "My Extension",
"version": "0.1",
"manifest_version" : 2,
"description": "Does some simple stuff",
"background" : {
"scripts" : ["background.js"]
},
"browser_action": {
"default_icon": "logo .png"
},
"permissions": ["activeTab"]
}
Note that manifest_version must be there and it must be 2.
Note that the activeTab permission has been added.
Note that you can only do one thing when the browser action button is clicked: either you can show a popup, or you can execute a script, but you can't do both.
Second, to execute a script when the icon is clicked, place the code below in your background.js file (the filename is specified in your manifest.json):
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {file: "testScript.js"});
});
Finally, testScript.js is where you should put the code you want to execute when the icon is clicked.
If you want to follow the manifest 3 then you should do:
chrome.action.onClicked.addListener(function (tab) {
console.log("Hello")
});
Further note that you will not see the Hello in normal console, to see the hello go to extensions menu and click on inspect views in front of the specific extension menu.
Instead of specifying a popup page, use the chrome.browserAction.onClicked API, documented here.
you need to add a background file.
but firstly ou need to add an attribute in manifest.json like,
"background":{
"scripts":["background.js"]
}
now name a file in your extension folder as background.js
there is a way of sending objects from background to your content scripts suppose your content script is named content.js then what you need to do is write this code snippet in background.js file
chrome.browserAction.onClicked.addListener(sendfunc);
function sendfunc(tab){
msg={txtt:"execute"};
chrome.tabs.sendMessage(tab.id,msg);
}
what the above code is doing is sending an object named msg to content page and this msg object has a property txtt which is equal to "execute".
what you need to do next is compare the values in content script as
chrome.runtime.onMessage.addListener(recievefunc);
function receivefunc(mssg,sender,sendResponse){
if(mssg.txtt==="execute"){
/*
your code of content script goes here
*/
}
}
now whenever you click the extension icon an object named msg is sent from background to content. the function "recievefunc()" will compare its txtt property with string "execute" if it matches your rest of the code will run.
note: msg,txtt,sendfunc,receivefunc,mssg all are variables and not chrome keywords so you can use anything you want.
hope it helps.
:)
In manifest 3 you might do it like this
// manifest.json
"background": {
"service_worker": "back.js"
},
// back.js
chrome.action.onClicked.addListener(tab => {
chrome.tabs.create({
url: 'index.html'
});
});
This was just what I needed but I should add this:
If all you need is a one-time event like when a user clicks on the extension's icon, then Background Pages is a waste of resources as it will run in the background ALL the time.
Use Event Pages instead:
"background": {
"scripts": ["script.js"],
"persistent": false
}