Chrome extension that automatically removes elements from history - javascript

I have a problem with the chrome extension project I'm working on.
Generally, it has only one purpose - to remove the addresses from browsing history that is included in the array. (later on, I'm going to add some UI for it ). The chrome background console doesn't show any errors - additionally, I did it just like the documentation said.
How to make that chrome extension background script removing array elements from history.
console.log("hi");
// delete URL
const arr = [
"https://www.facebook.com/",
"https://www.messenger.com/",
"https://www.netflix.com/",
"https://www.youtube.com/"
]
arr.forEach( site => {
console.log(site)
chrome.history.deleteUrl({ url: site });
});

Related

What does tabs[0] mean in browser extensions?

In the Firefox example of browser extensions, the popup script sends a message to the content script using the following:
browser.tabs.sendMessage(tabs[0].id, {
command: "beastify", beastURL: url }
Looking through the MDN documentation doesn't give a clear cut answer as to what tabs really is. It seems like its an array containing all the tab objects in the browser. But how do I know what tabs[0] is? and what about the rest of the array?
Is using tabs[0] equivalent to finding the current active tab?
This is from Firefox documentation
browser.tabs
.query({ active: true, currentWindow: true })
.then(beastify)
....
function beastify(tabs) {
browser.tabs.insertCSS({ code: hidePage }).then(() => {
let url = beastNameToURL(e.target.textContent);
browser.tabs.sendMessage(tabs[0].id, {
command: "beastify",
beastURL: url
});
});
}
As you can see the beastify function is called with list (array) of tabs from browser.tabs.query()
Because only one tab in the same window can be active, it's save to say that the list will contain only single item, hens we can safely use tabs[0] to access first and only item in the array.

Getting active tab information using chrome extension api

I am working on a chrome extension, and I need information about the active tab (when I say "active", I mean the tab that I am looking at in the current window that is focused).
Using the chrome.tabs api, I should be able to do something like the following to get what I want:
function getActiveTab() {
var activeTabInfo = {"currentWindow": true, "active" : true};
return chrome.tabs.query(activeTabInfo,function (tabs) {
return tabs[0];
});
}
However, when I log the length of tabs within the callback, I'm getting a length of 0. I modeled this snippet after How to fetch URL of current Tab in my chrome extension using javascript, but can't seem to get it to work.
Any thoughts?

How to detect page title change in Google Chrome from an extension?

I'm creating a Google Chrome extension and I need to detect when a page's title changes. The page's title is changed like in Twitter: (num) Twitter (see the screenshot below) - when a new tweet is posted, the number increments. Example:
I'm trying to detect the title changes of a URL that's loaded in one of my tabs and play a beep sound whenever there's a difference. This check is to be done in a repeated interval and I think that can be accomplished using setTimeOut() function.
I've created a manifest.json as follows:
{
"manifest_version": 2,
"name": "Detect Page Title Changes",
"description": "Blah",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "background.html"
},
"permissions": [
"tabs"
]
}
However, I'm clueless about the rest. I've searched through the docs 1 2 and tried the solutions on similar Stack Overflow threads such as this one I but couldn't find anything that suits my requirements.
Do you have any suggestions? Please include an example, if possible.
Instead of arguing in comments that a certain approach is better, let me be more constructive and add an answer by showing a particular implementation I co-wrote myself, and explain some gotchas you may run into. Code snippets refer to a service different from Twitter, but the goal was the same. In fact, this code's goal is to report the exact number of unread messages, so yours might be simpler.
My approach is based on an answer here on SO, and instead of being polling-driven (check condition at fixed intervals) is event-driven (be notified of potential changes in condition).
Advantages include immediate detection of a change (which would otherwise not be detected until the next poll) and not wasting resources on polls while the condition does not change. Admittedly, the second argument hardly applies here, but the first one still stands.
Architecture at a glance:
Inject a content script into the page in question.
Analyze initial state of the title, report to background page via sendMessage.
Register a handler for a title change event.
Whenever the event fires and the handler is called, analyze the new state of the title, report to background page via sendMessage.
Already step 1 has a gotcha to it. Normal content script injection mechanism, when the content script is defined in the manifest, will inject it in pages upon navigation to a page that matches the URL.
"content_scripts": [
{
"matches": [
"*://theoldreader.com/*"
],
"js": ["observer.js"],
"run_at": "document_idle"
}
]
This works pretty well, until your extension is reloaded. This can happen in development as you're applying changes you've made, or in deployed instances as it is auto-updated. What happens then is that content scripts are not re-injected in existing open pages (until navigation happens, like a reload). Therefore, if you rely on manifest-based injection, you should also consider including programmatic injection into already-open tabs when extension initializes:
function startupInject() {
chrome.tabs.query(
{url: "*://theoldreader.com/*"},
function (tabs) {
for (var i in tabs) {
chrome.tabs.executeScript(tabs[i].id, {file: "observer.js"});
}
}
);
}
On the other end, content script instances that were active at the time of extension reload are not terminated, but are orphaned: any sendMessage or similar request will fail. It is, therefore, recommended to always check for exceptions when trying to communicate with the parent extension, and self-terminate (by removing handlers) if it fails:
try {
chrome.runtime.sendMessage({'count' : count});
} catch(e) { // Happens when parent extension is no longer available or was reloaded
console.warn("Could not communicate with parent extension, deregistering observer");
observer.disconnect();
}
Step 2 also has a gotcha to it, though it depends on the specifics of the service you're watching. Some pages inside the scope of the content script will not show the number of unread items, but it does not mean that there are no new messages.
After observing how the web service works, I concluded that if the title changes to something without navigation, it's safe to assume the new value if correct, but for the initial title "no new items" should be ignored as unreliable.
So, the analysis code accounts for whether it's the initial reading or handling an update:
function notify(title, changed) {
// ...
var match = /^\((\d+)\)/.exec(title);
var match_zero = /^The Old Reader$/.exec(title);
if (match && match[1]) {
count = match[1];
} else if (match_zero && changed) {
count = 0;
}
// else, consider that we don't know the count
//...
}
It is called with the initial title and changed = false in step 2.
Steps 3 & 4 are the main answer to "how to watch for title changes" (in an event-driven way).
var target = document.querySelector('head > title');
var observer = new window.MutationObserver(
function(mutations) {
mutations.forEach(
function(mutation){
notify(mutation.target.textContent, true);
}
);
}
);
observer.observe(target, { subtree: true, characterData: true, childList: true });
For specifics as to why certain options of observer.observe are set, see the original answer.
Note that notify is called with changed = true, so going from "(1) The Old Reader" to "The Old Reader" without navigation is considered to be a "true" change to zero unread messages.
Put chrome.tabs.onUpdated.addListener in your background script:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
console.log(changeInfo);
});
changeInfo is an object which includes title changes, e.g. here:
Can then filter on the object so that an action only occurs if changeInfo includes a title change. For additional manipulation, e.g. responding to page title changes with page content / actions, you can send a message to content script from inside the listener after whatever conditions are met.
Create an event page.
Create a content script that gets injected into a webpage when a webpage loads.
Within the content script, use setInterval to poll the page to see if window.document.title changes.
If the title has changed, use chrome.runtime.sendMessage to send a message to your event page.
On your event page, listen for messages with chrome.runtime.onMessage and play a sound.
After researching Chrome's tabs API, it doesn't look like anything stands out to help you directly. However, you should be able to attach an event listener to the title node of the tab(s) you're interested in. The DOMSubtreeModified mutation event works in Chrome, and a quick test in a normal html document proves to work for me - should be no different from within an extension.
var title = document.getElementsByTagName('title')[0];
if (title) {
title.addEventListener('DOMSubtreeModified', function (e) {
// title changed
}, false);
}

How to access performance object of every resource in a web page?

I can see, in Chrome Developer tools, loading time, time it took to get a particular resource from server and other info, for all of the resources in a webpage.
I want to capture these stats using JavaScript. How is it possible?
there is window.performance object available, but only for the requested page, not for page resources.
Is there any way to access performance object of all of the page resources.
You should be able to use window.performance.getEntries() to get resource-specific stats:
var resource = window.performance.getEntries()[0];
console.log(resource.entryType); // "resource"
console.log(resource.duration); // 39.00000000430737
console.log(resource.startTime); // 218.0000000007567
Sample from the above link:
There is still a bug in latest version of chrome - 29.0.1547.76 m
When you raise an xmlhttprequest, lets say while downloading an image, you can see that the resource is downloaded with status code 200 OK in network tab, but the performance.getEntries() or performance.getEntriesByName(resourceUrl) doesn't list the resource entry. When the page load is complete and you evaluate performance.getEntriesByName(resourceUrl) in console, it lists properly. So, there is a lag in chrome while populating the resource entries in performance entries?
In IE10, this works perfectly fine.
window.performance.getEntries()
may return not all resources. after bufferful some records is disapear
need check it before it happend
head code part
var storedEntries = [];
var updateStoredEntries = p => {
storedEntries.concat(
p.getEntries().filter(rec => /yourRegExp/.test(rec.name))
)
};
performance.addEventListener('resourcetimingbufferfull', e => {
updateStoredEntries(e.target)
});
...
later part
updateStoredEntries(performance)

Checking if user has a certain extension installed

I just found out that the Screen Capture by Google extension makes my website's window.onresize event not fire.
I want to perform a javascript check to see if the user has ScreenCapture installed and if so, warn the user of the problem.
A year ago I think I heard of some javascript code that could do this, maybe using some google API, but I don't remember.
Any insight on this? I haven't developed any extensions so I don't really know how they work.
[EDIT]
So I have been asked to show some code. As seen in my previous question ( window.onresize not firing in Chrome but firing in Chrome Incognito ), the problem occurs on any window.onresize event function, so I don't think my code really matters.
Also, there is quite a lot of my code, I don't know how much of it to paste or if it would be helpful.
var debounce = function (func, threshold, execAsap)
{
var timeout;
return function debounced () {//alert("1.1 Y U NO WORK?");
var obj = this, args = arguments;
function delayed () {
if (!execAsap)
func.apply(obj, args);
timeout = null;
}
if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || 100);
};
};
window.onresize = debounce(function (e) { //alert("1.2 Y U NO WORK?");
flag = true;
var point = window.center({width:1,height:1});
doCenter(point);
// does something here, but only once after mouse cursor stops
}, 100, false);
I would like to stress that the problem is not due to the debounce. window.onresize = t; function t (e) { alert("wtf?");} won't work either.
[EDIT2]
Here's the result:
var screenCapture = null;
var screenCaptureImg = document.createElement("img");
screenCaptureImg.setAttribute("src", "chrome-extension://cpngackimfmofbokmjmljamhdncknpmg/images/arrow.png");
/*
* Add event listeners for both "load"- and "error"-event
* Set the variable showing the existence of the extension by
* setting it to "true" or "false" according to the fired event
*/
screenCaptureImg.addEventListener("load", doLoad, false);
function doLoad(e){
screenCapture = true; //removeImgTag(e);
alert("I've so cleverly detected that your Chrome has the ScreenCapture extension enabled. \n\nThis extension interferes with my website's DOM and long story short, it won't be able to scale properly.\n\nSo please disable it. \nConsider this extension: \"Disable All Extensions Plus\", it's a handy selective disabler.");
}
screenCaptureImg.addEventListener("error", function(e){
screenCapture = false; //removeImgTag(e);
}, false);
/*
function removeImgTag(e) {
e.currentTarget.parentNode.removeChild(e.currentTarget);
}
*/
Note that I couldn't get removeImgTag to work, because (at least in chrome), I don't seem to have access to the document object in order to create or remove elements from my page, from within these event functions. This is also why I'm displaying an alert instead of elegantly writing up a document.getElementById("something").innerHTML=...
To detect if an extension is installed in Chrome, you can check for a known resource included in the extension such as an image. Resources for the extension are referenced using the following URL pattern:
chrome-extension://<extensionID>/<pathToFile>
The basic detection technique involves creating a hidden image tag and attaching load and error events to it to see if the image loads (as described here for Firefox):
extensionImg.setAttribute("src", "chrome-extension://<INSERT EXTENSION ID HERE>/images/someImage.png"); // See below for discussion of how to find this
/*
* Add event listeners for both "load"- and "error"-event
* Set the variable showing the existence of the extension by
* setting it to "true" or "false" according to the fired event
*/
extensionImg.addEventListener("load", function(e) {
extensionExists = true;
removeImgTag(e);
}, false);
extensionImg.addEventListener("error", function(e) {
extensionExists = false;
removeImgTag(e);
}, false);
function removeImgTag(e) {
e.currentTarget.parentNode.removeChild(e.currentTarget);
}
Check the installation directory of the extension in the Chrome configuration to find a likely target for detection. On my Linux workstation extensions are located in:
~/.config/chromium/Default/Extensions
You can see that I have 3 extensions installed right now:
~/.config/chromium/Default/Extensions$ ls
cpecbmjeidppdiampimghndkikcmoadk nmpeeekfhbmikbdhlpjbfmnpgcbeggic
cpngackimfmofbokmjmljamhdncknpmg
The odd looking names are the unique IDs given to the extension when it is uploaded to the Chrome webstore. You can obtain the ID either from the webstore or by going to the Extensions tab (wrench -> Extensions) and hovering over the link to the extension in question, or "Screen Capture (by Google)" in this case (note the asterisked extension ID):
https://chrome.google.com/webstore/detail/**cpngackimfmofbokmjmljamhdncknpmg**
In the extension directory there will be one or more versions; you can ignore this. Within the version directory is the actual content of the extension:
~/.config/chromium/Default/Extensions/cpngackimfmofbokmjmljamhdncknpmg/5.0.3_0$ ls
account.js images page.js sina_microblog.js
ajax.js isLoad.js picasa.js site.js
background.html _locales plugin style.css
editor.js manifest.json popup.html ui.js
facebook.js notification.html sha1.js upload_ui.js
hotkey_storage.js oauth.js shortcut.js
hub.html options.html showimage.css
i18n_styles page_context.js showimage.html
In the case of the Screen Capture extension there are a number of images to use:
~/.config/chromium/Default/Extensions/cpngackimfmofbokmjmljamhdncknpmg/5.0.3_0/images$ ls
arrow.png icon_128.png icon_save.png print.png
copy.png icon_16.png line.png region.png
cross.png icon_19.png loading.gif screen.png
custom.png icon_32.png loading_icon.gif sina_icon.png
delete_account_icon.png icon_48.png mark.png toolbar_bg.png
down_arrow.png icon_close.png picasa_icon.png upload.png
facebook_icon.png icon_copy.png popup_bg.jpg whole.png
These can be referenced under this URL:
chrome-extension://cpngackimfmofbokmjmljamhdncknpmg/images/arrow.png
This technique obviously depends on the stability of the content of the extension. I recommend using an image that looks likely to remain through all versions.
As mentioned above, the same technique can be used to detect Firefox extensions. In this case the content URL looks like this:
chrome://<EXTENSION NAME>/content/<PATH TO RESOURCE>
On my Linux workstation Firefox extensions are located in:
~/.mozilla/firefox/<USER PROFILE ID>/extensions
Where <USER PROFILE ID> looks something like this: "h4aqaewq.default"
You can see that I have 2 extensions installed right now, one of which is a directory installation and the other of which is a XPI (pronounced "zippy") file:
~/.mozilla/firefox/h4aqaewq.default/extensions$ ls
{3e9a3920-1b27-11da-8cd6-0800200c9a66} staged
firebug#software.joehewitt.com.xpi
The "staged" directory is where Firefox keeps extensions that will be updated (I think). The GUID directory with the brackets is a directory-based extension installation, and the .xpi file is Firebug.
Note: XPI is going away (see the link above). It's basically a zip file that can be opened and inspected by anything that understands zip. I used Emacs.
Finding the extension ID in Firefox is a bit more involved. Go to "Tools -> Add-ons", click the Extensions tab, click the "More" link next to the extension description, then click the "reviews" link to go to the Firefox extension site and get the ID from the URL (note the asterisked extension ID):
https://addons.mozilla.org/en-US/firefox/addon/**firebug**/reviews/?src=api
There's probably an easier way to do this; suggestions welcome.
TODO: how to find a likely image in a Firefox extension.
As an extra note, in Chrome you can only communicate with an extension via the shared DOM of the page: Host page communication

Categories

Resources