Context: I'm building a chrome extension which closes tabs (inputted by the user). In my background script (btw, manifest V3), I have some code written that uses chrome.tabs.remove to close tabs who's URL include the string value of the website to block.
My Problem: As this is a chrome extension, there is an options page. I have a setting button in my popup that when clicked opens up the chrome extension's options page in a new tab. The same thing happens when you right click on the extension and click options. Occasionally, this also occurs when I open a new tab (or use the keyboard shortcut ctrl + t to open a new tab). However, somehow every time I click on one of those buttons/links, it's instantly auto deleted by my extension, and this error appears in the console/extension error list: Uncaught (in promise) Error: No tab with id: 167.
(This also happens when clicking on any other hyperlink.)
Yes, I have the [tabs] permission as well as the [activeTab] permission.
Interestingly, at some point it starts working again (sometimes) but if it does, the chrome.tabs.remove no longer works. In fact, by looking at the console, the whole function responsible to deal with the chrome.tabs.remove fails to work, as my console.log doesn't print anything to the console when it should. So it would be great if someone could explain to me why the event listeners randomly stop working as well :).
Code: note, some console.log is in there from my debugging
function loopInfo(tabsid, trueorfalse) {
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query
let querying = chrome.tabs.query({currentWindow: true, active: true});
querying.then((tabs) => {
chrome.storage.sync.get("list", (value) => {
var websiteList = value.list;
console.log(String(holdURL) + "1");
for (var i = 0; i < websiteList.length; i++) {
console.log("It is looping..." + "2");
if (String(holdURL).includes(websiteList[i]) || websiteList[i].includes(String(holdURL))) {
// onUpdated
if (trueorfalse) {
chrome.tabs.remove(parseInt(tabsid));
}
// onActivated
chrome.tabs.remove(parseInt(tabit));
console.log("It worked!!!!!!!!!!!!!" + "3");
}
}
});
}, () =>{});
}
var holdURL;
var tabit;
chrome.tabs.onActivated.addListener((event) => {
chrome.tabs.query({
active: true,
lastFocusedWindow: true
}, function(tabs) {
var tab = tabs[0];
holdURL = tab.url;
console.log(tab.url + " onActivated");
tabit = event.tabId;
});
// the 1 below is not a tab id, it's just a placeholder
loopInfo(1, false);
})
chrome.tabs.onUpdated.addListener((tabsid, changeInfo, tab) => {
console.log(changeInfo.status);
if (changeInfo.status == "complete") {
var tempId = tabsid;
holdURL = tab.url;
console.log(tab.url + " onUpdated");
loopInfo(tempId, true);
}
});
Much thanks!!
For some reason, the condition for the if statement containing the chrome.tabs.remove commands turns out to be true whenever a tab instantly loads. There is a possibility that the running of onActivated occurs faster than the load of the page, so that it receives an arbitrary url which passes the condition I made for the if statement later.
Temporary fix: make the function call in onActivated to have a setTimeout(loopInfo(1, false), 1500). 1500 ms just in case of computer lag/low internet speed.
Would be interested in seeing a better solution though.
I have a site that dynamically builds a mailto url which it then opens in a new tab/window, using window.open().
window.open("mailto:" + encodeURIComponent(r["to"]));
I'm testing in Chrome at this stage, so other browsers may act differently.
If Chrome has a mailto protocol handler set up (e.g. GMail), then it works as expected.
If Chrome does not have a mailto protocol handler set up, it just opens a tab with the mailto url and nothing else.
That's not the worst result, but it would be nice if there was a way of knowing in advance, so that the user could be in some way guided to setting up their browser so that the mailto url worked nicely.
Previously, I was just opening in the same page by setting window.location.href to the url:
windows.location.href = "mailto:" + encodeURIComponent(r["to"]);
This wasn't great because if there was no protocol handler set, nothing happened. I also would consider this as an option, IF I can at least detect the situation, but wasn't able to find any indication of that either. I guess one option would be to set a timer which if it reached execution could alert the user?
Anyone else already solved this? Seems like a pretty common requirement.
Thanks
Here's what I ended up working with. It doesn't work in all cases, but provides at least some help in recognising unhandled protocols.
It attempts to open the URL in a new window and then after 2s it takes a look to see if it can read the location. If it has opened a third party site (e.g. GMail) this will raise and exception - so we treat this as success.
If no exception occurs, this returns "about:blank" which means we (probably) failed.
function openWin(url) {
return new Promise((resolve, reject) => {
const w = window.open(url);
if (!w) {
reject();
}
setTimeout(function() {
try {
const working = w.document.location.href;
} catch (e) {
resolve();
return;
}
w.close();
reject();
}, 2000);
});
}
Called with something like this:
openWin('mailto:' + encodeURIComponent(to)).then(() => {
// handle success
}).catch(() => {
// handle failure
});
Caveat: This only works for web-based protocol handlers. If for example your mailto is handled by an email app, then this will fail.
In my case, most people would be using web-based email, so it works for most cases. On failure I show a message to the affect of "If your email didn't open, copy the email address here..."
I am in the process of building a Chrome extension, and for the whole thing to work the way I would like it to, I need an external JavaScript script to be able to detect if a user has my extension installed.
For example: A user installs my plugin, then goes to a website with my script on it. The website detects that my extension is installed and updates the page accordingly.
Is this possible?
Chrome now has the ability to send messages from the website to the extension.
So in the extension background.js (content.js will not work) add something like:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (request) {
if (request.message) {
if (request.message == "version") {
sendResponse({version: 1.0});
}
}
}
return true;
});
This will then let you make a call from the website:
var hasExtension = false;
chrome.runtime.sendMessage(extensionId, { message: "version" },
function (reply) {
if (reply) {
if (reply.version) {
if (reply.version >= requiredVersion) {
hasExtension = true;
}
}
}
else {
hasExtension = false;
}
});
You can then check the hasExtension variable. The only drawback is the call is asynchronous, so you have to work around that somehow.
Edit:
As mentioned below, you'll need to add an entry to the manifest.json listing the domains that can message your addon. Eg:
"externally_connectable": {
"matches": ["*://localhost/*", "*://your.domain.com/*"]
},
2021 Update:
chrome.runtime.sendMessage will throw the following exception in console if the extension isn't installed or it's disabled.
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist
To fix this, add this validation inside the sendMessage callback
if (chrome.runtime.lastError) {
// handle error
}
I am sure there is a direct way (calling functions on your extension directly, or by using the JS classes for extensions), but an indirect method (until something better comes along):
Have your Chrome extension look for a specific DIV or other element on your page, with a very specific ID.
For example:
<div id="ExtensionCheck_JamesEggersAwesomeExtension"></div>
Do a getElementById and set the innerHTML to the version number of your extension or something. You can then read the contents of that client-side.
Again though, you should use a direct method if there is one available.
EDIT: Direct method found!!
Use the connection methods found here: https://developer.chrome.com/extensions/extension#global-events
Untested, but you should be able to do...
var myPort=chrome.extension.connect('yourextensionid_qwerqweroijwefoijwef', some_object_to_send_on_connect);
Another method is to expose a web-accessible resource, though this will allow any website to test if your extension is installed.
Suppose your extension's ID is aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, and you add a file (say, a transparent pixel image) as test.png in your extension's files.
Then, you expose this file to the web pages with web_accessible_resources manifest key:
"web_accessible_resources": [
"test.png"
],
In your web page, you can try to load this file by its full URL (in an <img> tag, via XHR, or in any other way):
chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/test.png
If the file loads, then the extension is installed. If there's an error while loading this file, then the extension is not installed.
// Code from https://groups.google.com/a/chromium.org/d/msg/chromium-extensions/8ArcsWMBaM4/2GKwVOZm1qMJ
function detectExtension(extensionId, callback) {
var img;
img = new Image();
img.src = "chrome-extension://" + extensionId + "/test.png";
img.onload = function() {
callback(true);
};
img.onerror = function() {
callback(false);
};
}
Of note: if there is an error while loading this file, said network stack error will appear in the console with no possibility to silence it. When Chromecast used this method, it caused quite a bit of controversy because of this; with the eventual very ugly solution of simply blacklisting very specific errors from Dev Tools altogether by the Chrome team.
Important note: this method will not work in Firefox WebExtensions. Web-accessible resources inherently expose the extension to fingerprinting, since the URL is predictable by knowing the ID. Firefox decided to close that hole by assigning an instance-specific random URL to web accessible resources:
The files will then be available using a URL like:
moz-extension://<random-UUID>/<path/to/resource>
This UUID is randomly generated for every browser instance and is not your extension's ID. This prevents websites from fingerprinting the extensions a user has installed.
However, while the extension can use runtime.getURL() to obtain this address, you can't hard-code it in your website.
I thought I would share my research on this.
I needed to be able to detect if a specific extension was installed for some file:/// links to work.
I came across this article here
This explained a method of getting the manifest.json of an extension.
I adjusted the code a bit and came up with:
function Ext_Detect_NotInstalled(ExtName, ExtID) {
console.log(ExtName + ' Not Installed');
if (divAnnounce.innerHTML != '')
divAnnounce.innerHTML = divAnnounce.innerHTML + "<BR>"
divAnnounce.innerHTML = divAnnounce.innerHTML + 'Page needs ' + ExtName + ' Extension -- to intall the LocalLinks extension click here';
}
function Ext_Detect_Installed(ExtName, ExtID) {
console.log(ExtName + ' Installed');
}
var Ext_Detect = function (ExtName, ExtID) {
var s = document.createElement('script');
s.onload = function () { Ext_Detect_Installed(ExtName, ExtID); };
s.onerror = function () { Ext_Detect_NotInstalled(ExtName, ExtID); };
s.src = 'chrome-extension://' + ExtID + '/manifest.json';
document.body.appendChild(s);
}
var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
if (is_chrome == true) {
window.onload = function () { Ext_Detect('LocalLinks', 'jllpkdkcdjndhggodimiphkghogcpida'); };
}
With this you should be able to use Ext_Detect(ExtensionName,ExtensionID) to detect the installation of any number of extensions.
Another possible solution if you own the website is to use inline installation.
if (chrome.app.isInstalled) {
// extension is installed.
}
I know this an old question but this way was introduced in Chrome 15 and so I thought Id list it for anyone only now looking for an answer.
Here is an other modern approach:
const checkExtension = (id, src, callback) => {
let e = new Image()
e.src = 'chrome-extension://'+ id +'/'+ src
e.onload = () => callback(1), e.onerror = () => callback(0)
}
// "src" must be included to "web_accessible_resources" in manifest.json
checkExtension('gighmmpiobklfepjocnamgkkbiglidom', 'icons/icon24.png', (ok) => {
console.log('AdBlock: %s', ok ? 'installed' : 'not installed')
})
checkExtension('bhlhnicpbhignbdhedgjhgdocnmhomnp', 'images/checkmark-icon.png', (ok) => {
console.log('ColorZilla: %s', ok ? 'installed' : 'not installed')
})
I used the cookie method:
In my manifest.js file I included a content script that only runs on my site:
"content_scripts": [
{
"matches": [
"*://*.mysite.co/*"
],
"js": ["js/mysite.js"],
"run_at": "document_idle"
}
],
in my js/mysite.js I have one line:
document.cookie = "extension_downloaded=True";
and in my index.html page I look for that cookie.
if (document.cookie.indexOf('extension_downloaded') != -1){
document.getElementById('install-btn').style.display = 'none';
}
You could have the extension set a cookie and have your websites JavaScript check if that cookie is present and update accordingly. This and probably most other methods mentioned here could of course be cirvumvented by the user, unless you try and have the extension create custom cookies depending on timestamps etc, and have your application analyze them server side to see if it really is a user with the extension or someone pretending to have it by modifying his cookies.
There's another method shown at this Google Groups post. In short, you could try detecting whether the extension icon loads successfully. This may be helpful if the extension you're checking for isn't your own.
Webpage interacts with extension through background script.
manifest.json:
"background": {
"scripts": ["background.js"],
"persistent": true
},
"externally_connectable": {
"matches": ["*://(domain.ext)/*"]
},
background.js:
chrome.runtime.onMessageExternal.addListener(function(msg, sender, sendResponse) {
if ((msg.action == "id") && (msg.value == id))
{
sendResponse({id : id});
}
});
page.html:
<script>
var id = "some_ext_id";
chrome.runtime.sendMessage(id, {action: "id", value : id}, function(response) {
if(response && (response.id == id)) //extension installed
{
console.log(response);
}
else //extension not installed
{
console.log("Please consider installig extension");
}
});
</script>
Your extension could interact with the website (e.g. changing variables) and your website could detect this.
But there should be a better way to do this. I wonder how Google is doing it on their extension gallery (already installed applications are marked).
Edit:
The gallery use the chrome.management.get function. Example:
chrome.management.get("mblbciejcodpealifnhfjbdlkedplodp", function(a){console.log(a);});
But you can only access the method from pages with the right permissions.
A lot of the answers here so far are Chrome only or incur an HTTP overhead penalty. The solution that we are using is a little different:
1. Add a new object to the manifest content_scripts list like so:
{
"matches": ["https://www.yoursite.com/*"],
"js": [
"install_notifier.js"
],
"run_at": "document_idle"
}
This will allow the code in install_notifier.js to run on that site (if you didn't already have permissions there).
2. Send a message to every site in the manifest key above.
Add something like this to install_notifier.js (note that this is using a closure to keep the variables from being global, but that's not strictly necessary):
// Dispatch a message to every URL that's in the manifest to say that the extension is
// installed. This allows webpages to take action based on the presence of the
// extension and its version. This is only allowed for a small whitelist of
// domains defined in the manifest.
(function () {
let currentVersion = chrome.runtime.getManifest().version;
window.postMessage({
sender: "my-extension",
message_name: "version",
message: currentVersion
}, "*");
})();
Your message could say anything, but it's useful to send the version so you know what you're dealing with. Then...
3. On your website, listen for that message.
Add this to your website somewhere:
window.addEventListener("message", function (event) {
if (event.source == window &&
event.data.sender &&
event.data.sender === "my-extension" &&
event.data.message_name &&
event.data.message_name === "version") {
console.log("Got the message");
}
});
This works in Firefox and Chrome, and doesn't incur HTTP overhead or manipulate the page.
You could also use a cross-browser method what I have used.
Uses the concept of adding a div.
in your content script (whenever the script loads, it should do this)
if ((window.location.href).includes('*myurl/urlregex*')) {
$('html').addClass('ifextension');
}
in your website you assert something like,
if (!($('html').hasClass('ifextension')){}
And throw appropriate message.
If you have control over the Chrome extension, you can try what I did:
// Inside Chrome extension
var div = document.createElement('div');
div.setAttribute('id', 'myapp-extension-installed-div');
document.getElementsByTagName('body')[0].appendChild(div);
And then:
// On web page that needs to detect extension
if ($('#myapp-extension-installed-div').length) {
}
It feels a little hacky, but I couldn't get the other methods to work, and I worry about Chrome changing its API here. It's doubtful this method will stop working any time soon.
If you're trying to detect any extension from any website,
This post helped: https://ide.hey.network/post/5c3b6c7aa7af38479accc0c7
Basically, the solution would be to simply try to get a specific file (manifest.json or an image) from the extension by specifying its path. Here's what I used. Definitely working:
const imgExists = function(_f, _cb) {
const __i = new Image();
__i.onload = function() {
if (typeof _cb === 'function') {
_cb(true);
}
}
__i.onerror = function() {
if (typeof _cb === 'function') {
_cb(false);
}
}
__i.src = _f;
__i = null;
});
try {
imgExists("chrome-extension://${CHROME_XT_ID}/xt_content/assets/logo.png", function(_test) {
console.log(_test ? 'chrome extension installed !' : 'chrome extension not installed..');
ifrm.xt_chrome = _test;
// use that information
});
} catch (e) {
console.log('ERROR', e)
}
Here is how you can detect a specific Extension installed and show a warning message.
First you need to open the manifest file of the extension by going to chrome-extension://extension_id_here_hkdppipefbchgpohn/manifest.json and look for any file name within "web_accessible_resources" section.
<div class="chromewarning" style="display:none">
<script type="text/javascript">
$.get("chrome-extension://extension_id_here_hkdppipefbchgpohn/filename_found_in_ web_accessible_resources.png").done(function () {
$(".chromewarning").show();
}).fail(function () {
// alert("failed.");
});
</script>
<p>We have detected a browser extension that conflicts with learning modules in this course.</p>
</div>
Chrome Extension Manifest v3:
const isFirefox = chrome.runtime.OnInstalledReason.CHROME_UPDATE != "chrome_update";
For FireFox, I believe chrome.runtime.OnInstalledReason.BROWSER_UPDATE will be "browser_update": https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/OnInstalledReason
I've got some code running in an iframe on 3rd-party sites. Some will be directly in the top page, some will be inside another iframe and some of these may be cross-domain. I need to find a way to get the URL value of the top page using any means necessary.
The furthest I can go up due to cross-domain policy is until the browser stops what the code is doing. I catch the error and look at the referrer of the current window context I'm in. Most cases the page above this is the top page, but not necessarily.
The only way I can see around this is building up a list of URLs which I think are the top page, and then sending a bot with a JS browser validate by seeing if the iframe my code got up to was in fact directly nested in them.
That's still not particularly accurate though, and I'm sure there must be another way of doing it...
Thanks to anyone who can help.
There is actually a way to get the domain in both Chrome and Opera, (in multiple nested cross-domain iframes), though it is not possible in other browsers.
You need to use the 'window.location.ancestorOrigins' property.
I have created a snippet of code below, which should work for you and if you think you can improve the code or comments, please don't hesitate to edit the gist on Github so we can make it even better:
Gist: https://gist.github.com/ocundale/281f98a36a05c183ff3f.js
Code (ES2015):
// return topmost browser window of current window & boolean to say if cross-domain exception occurred
const getClosestTop = () => {
let oFrame = window,
bException = false;
try {
while (oFrame.parent.document !== oFrame.document) {
if (oFrame.parent.document) {
oFrame = oFrame.parent;
} else {
//chrome/ff set exception here
bException = true;
break;
}
}
} catch(e){
// Safari needs try/catch so sets exception here
bException = true;
}
return {
'topFrame': oFrame,
'err': bException
};
};
// get best page URL using info from getClosestTop
const getBestPageUrl = ({err:crossDomainError, topFrame}) => {
let sBestPageUrl = '';
if (!crossDomainError) {
// easy case- we can get top frame location
sBestPageUrl = topFrame.location.href;
} else {
try {
try {
// If friendly iframe
sBestPageUrl = window.top.location.href;
} catch (e) {
//If chrome use ancestor origin array
let aOrigins = window.location.ancestorOrigins;
//Get last origin which is top-domain (chrome only):
sBestPageUrl = aOrigins[aOrigins.length - 1];
}
} catch (e) {
sBestPageUrl = topFrame.document.referrer;
}
}
return sBestPageUrl;
};
// To get page URL, simply run following within an iframe on the page:
const TOPFRAMEOBJ = getClosestTop();
const PAGE_URL = getBestPageUrl(TOPFRAMEOBJ);
If anybody would like the code in standard ES5, let me know, or simply run it through a converter online.
Definitely not possible without communicating with some sort of external system. The cleanest/most accurate way to gather data is to get the top window URL if the browser lets you, but catch errors and use the referer with a flag to note it's the referer.
I'm currently trying to build a firefox extension that determines a proxy for each http request based on Regular Expressions. The Proxy that has been used for loading a page should be remembered for any new request coming from that page, ie. any image/script/css file needed for that page, any outgoing links or ajax requests. That also means that the proxy needs to be remembered for each open tab.
This is where I run into my problem: Up until now I tried to mark each open tab by inserting a unique id as an attribute of the browser element of the tab, and looking for this id in an implementation of the shouldLoad() method of nsiContentPolicy. The code I'm using for this is shown below, and it was extracted from the addon sdk's getTabForContentWindow method in tabs/utils.js.
shouldLoad: function(contentType, contentLocation, requestOrigin, context, mimeTypeGuess, extra)
{
var tabId = null;
if (!(context instanceof CI.nsIDOMWindow))
{
// If this is an element, get the corresponding document
if (context instanceof CI.nsIDOMNode && context.ownerDocument)
context = context.ownerDocument;
// Now we should have a document, get its window
if (context instanceof CI.nsIDOMDocument)
context = context.defaultView;
else
context = null;
}
let browser;
try {
browser = context.QueryInterface(CI.nsIInterfaceRequestor)
.getInterface(CI.nsIWebNavigation)
.QueryInterface(CI.nsIDocShell)
.chromeEventHandler;
} catch(e) {
this.console.log(e);
}
let chromeWindow = browser.ownerDocument.defaultView;
if ('gBrowser' in chromeWindow && chromeWindow.gBrowser &&
'browsers' in chromeWindow.gBrowser) {
let browsers = chromeWindow.gBrowser.browsers;
let i = browsers.indexOf(browser);
if (i !== -1)
tabId = chromeWindow.gBrowser.tabs[i].getAttribute("PMsMark");
}
return CI.nsIContentPolicy.ACCEPT;
}
This works fine for any load that does not change the displayed document, but as soon as the document is changed(ie. a new page is loaded), the variable browser is null.
I have looked at the other mechanisms for intercepting page loads described on https://developer.mozilla.org/en-US/Add-ons/Overlay_Extensions/XUL_School/Intercepting_Page_Loads , but those seem to be unsuitable for what I want to achieve, because as far as I understand they work on HTTP requests, and for a request to exist, the proxy already needed to be determined.
So, if anybody knows a way to catch imminent loads before they become requests, and at the same time, it's possible to find out which tab is responsible for those loads-to-be, I'd be glad if they could let me know in the answers! Thanks in advance!
https://developer.mozilla.org/en-US/docs/Code_snippets/Tabbed_browser#Getting_the_browser_that_fires_the_http-on-modify-request_notification
Components.utils.import('resource://gre/modules/Services.jsm');
Services.obs.addObserver(httpObs, 'http-on-opening-request', false);
//Services.obs.removeObserver(httpObs, 'http-on-modify-request'); //uncomment this line, or run this line when you want to remove the observer
var httpObs = {
observe: function (aSubject, aTopic, aData) {
if (aTopic == 'http-on-opening-request') {
/*start - do not edit here*/
var oHttp = aSubject.QueryInterface(Components.interfaces.nsIHttpChannel); //i used nsIHttpChannel but i guess you can use nsIChannel, im not sure why though
var interfaceRequestor = oHttp.notificationCallbacks.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
//var DOMWindow = interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow); //not to be done anymore because: https://developer.mozilla.org/en-US/docs/Updating_extensions_for_Firefox_3.5#Getting_a_load_context_from_a_request //instead do the loadContext stuff below
var loadContext;
try {
loadContext = interfaceRequestor.getInterface(Components.interfaces.nsILoadContext);
} catch (ex) {
try {
loadContext = aSubject.loadGroup.notificationCallbacks.getInterface(Components.interfaces.nsILoadContext);
//in ff26 aSubject.loadGroup.notificationCallbacks was null for me, i couldnt find a situation where it wasnt null, but whenever this was null, and i knew a loadContext is supposed to be there, i found that "interfaceRequestor.getInterface(Components.interfaces.nsILoadContext);" worked fine, so im thinking in ff26 it doesnt use aSubject.loadGroup.notificationCallbacks anymore, but im not sure
} catch (ex2) {
loadContext = null;
//this is a problem i dont know why it would get here
}
}
/*end do not edit here*/
/*start - do all your edits below here*/
var url = oHttp.URI.spec; //can get url without needing loadContext
if (loadContext) {
var contentWindow = loadContext.associatedWindow; //this is the HTML window of the page that just loaded
//aDOMWindow this is the firefox window holding the tab
var aDOMWindow = contentWindow.top.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
var gBrowser = aDOMWindow.gBrowser; //this is the gBrowser object of the firefox window this tab is in
var aTab = gBrowser._getTabForContentWindow(contentWindow.top); //this is the clickable tab xul element, the one found in the tab strip of the firefox window, aTab.linkedBrowser is same as browser var above //can stylize tab like aTab.style.backgroundColor = 'blue'; //can stylize the tab like aTab.style.fontColor = 'red';
var browser = aTab.linkedBrowser; //this is the browser within the tab //this is what the example in the previous section gives
//end getting other useful stuff
} else {
Components.utils.reportError('EXCEPTION: Load Context Not Found!!');
//this is likely no big deal as the channel proably has no associated window, ie: the channel was loading some resource. but if its an ajax call you may end up here
}
}
}
};