Discussion:
Identifying Tab in OnStateChange C++
Vaibhav
2010-04-19 13:13:48 UTC
Permalink
Hi,

I am writing Firefox extension using C++.
In OnStateChange method I want to determine the tab associated with
particular request.

Currently I compare DOM Document Pointers to do it.

Following is the Pseudocode:

OnStateChange()
{
//==================================================
//+
// GET URL

nsCString url;
const char *pcszURL;
aRequest->GetName(url);
NS_CStringGetData(url, &pcszURL);

//-
//==================================================

nsCOMPtr<nsIDOMWindow> DOMWin;
rv = aWebProgress->GetDOMWindow(getter_AddRefs(DOMWin));
nsCOMPtr<nsIDOMDocument> DOMDoc;
rv = DOMWin->GetDocument(getter_AddRefs(DOMDoc));

INT iTabIndex;
nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
nsCOMPtr<nsIDOMWindowInternal> dwi;
windowMediator->GetMostRecentWindow(L"navigator:browser",
getter_AddRefs(dwi));
nsCOMPtr<nsIDOMDocument> doc;
dwi->GetDocument(getter_AddRefs(doc));
nsCOMPtr<nsIDOMDocumentXBL> xbl(do_QueryInterface(doc));
nsCOMPtr<nsIDOMElement> domEl;
doc->GetElementById(NS_LITERAL_STRING("content"),
getter_AddRefs(domEl));
nsCOMPtr<nsIDOMElement> pAnoEl;

//
// getting xul:tabpanels
//
xbl->GetAnonymousElementByAttribute(
domEl,
NS_LITERAL_STRING("anonid"),
NS_LITERAL_STRING("panelcontainer"),
getter_AddRefs(pAnoEl)
);
nsString retval;
PRBool bRet = 0;
nsCOMPtr<nsIDOMNodeList> nodeList;
pAnoEl->GetChildNodes(getter_AddRefs(nodeList));
nsCOMPtr<nsIDOMNode> domNode;
PRUint32 len = 0;
rv = nodeList->GetLength(&len);
for( PRUint32 i=0; i<len; i++ )
{
// getting the xul::notificationbox
nsCOMPtr<nsIDOMNode> domNode;
nodeList->Item(i, getter_AddRefs(domNode));
// get the last child of the 'xul::notificationbox' which is the
'xul:browser'
nsCOMPtr<nsIDOMNode> domXULBrowser;
domNode->GetLastChild(getter_AddRefs(domXULBrowser));
nsCOMPtr<nsIDOMXULElement> xulElement =
do_QueryInterface(domXULBrowser);
nsCOMPtr<nsIBoxObject> boxObject;
xulElement->GetBoxObject(getter_AddRefs(boxObject));
nsCOMPtr<nsIBrowserBoxObject> browserboxObject =
do_QueryInterface(boxObject);
nsCOMPtr<nsIDocShell> docShell;
browserboxObject->GetDocShell(getter_AddRefs(docShell));
nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(docShell);
nsCOMPtr<nsIURI> uri;
webNav->GetCurrentURI(getter_AddRefs(uri));
nsCString path;
uri->GetAsciiSpec(path);
const CHAR *ppathspec = path.get();
if (0 == _stricmp(ppathspec, pcszURL))
{
nsCOMPtr<nsIDOMDocument> tabdoc;
webNav->GetDocument(getter_AddRefs(tabdoc));
if (tabdoc.get() == DOMDoc.get())
{
//
// !!! This is the required tab. !!!
// !!! This is the tab associated with the request. !!!
//
}
}
}
}

In above code I am comparing nsIDOMDocument pointers to get currently
navigated tab.

Is there another sure way to do this?

With Best Regards,
Vaibhav.
Vaibhav
2010-04-20 09:41:35 UTC
Permalink
Post by Vaibhav
Hi,
I am writing Firefox extension using C++.
In OnStateChange method I want to determine the tab associated with
particular request.
Currently I compare DOM Document Pointers to do it.
OnStateChange()
{
        //==================================================
        //+
        // GET URL
        nsCString url;
        const char *pcszURL;
        aRequest->GetName(url);
        NS_CStringGetData(url, &pcszURL);
        //-
        //==================================================
        nsCOMPtr<nsIDOMWindow> DOMWin;
        rv = aWebProgress->GetDOMWindow(getter_AddRefs(DOMWin));
        nsCOMPtr<nsIDOMDocument> DOMDoc;
        rv = DOMWin->GetDocument(getter_AddRefs(DOMDoc));
        INT iTabIndex;
        nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
        nsCOMPtr<nsIDOMWindowInternal> dwi;
        windowMediator->GetMostRecentWindow(L"navigator:browser",
getter_AddRefs(dwi));
        nsCOMPtr<nsIDOMDocument> doc;
        dwi->GetDocument(getter_AddRefs(doc));
        nsCOMPtr<nsIDOMDocumentXBL> xbl(do_QueryInterface(doc));
        nsCOMPtr<nsIDOMElement> domEl;
        doc->GetElementById(NS_LITERAL_STRING("content"),
getter_AddRefs(domEl));
        nsCOMPtr<nsIDOMElement> pAnoEl;
        //
    // getting xul:tabpanels
        //
        xbl->GetAnonymousElementByAttribute(
                                                                                domEl,
                                                                                NS_LITERAL_STRING("anonid"),
NS_LITERAL_STRING("panelcontainer"),
                                                                                getter_AddRefs(pAnoEl)
                                                                                );
        nsString retval;
        PRBool bRet = 0;
        nsCOMPtr<nsIDOMNodeList> nodeList;
        pAnoEl->GetChildNodes(getter_AddRefs(nodeList));
        nsCOMPtr<nsIDOMNode> domNode;
        PRUint32 len = 0;
        rv = nodeList->GetLength(&len);
        for( PRUint32 i=0; i<len; i++ )
        {
                // getting the xul::notificationbox
                nsCOMPtr<nsIDOMNode> domNode;
                nodeList->Item(i, getter_AddRefs(domNode));
                // get the last child of the 'xul::notificationbox' which is the
'xul:browser'
                nsCOMPtr<nsIDOMNode> domXULBrowser;
                domNode->GetLastChild(getter_AddRefs(domXULBrowser));
                nsCOMPtr<nsIDOMXULElement> xulElement =
do_QueryInterface(domXULBrowser);
                nsCOMPtr<nsIBoxObject> boxObject;
                xulElement->GetBoxObject(getter_AddRefs(boxObject));
                nsCOMPtr<nsIBrowserBoxObject> browserboxObject =
do_QueryInterface(boxObject);
                nsCOMPtr<nsIDocShell> docShell;
                browserboxObject->GetDocShell(getter_AddRefs(docShell));
                nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(docShell);
                nsCOMPtr<nsIURI> uri;
                webNav->GetCurrentURI(getter_AddRefs(uri));
                nsCString path;
                uri->GetAsciiSpec(path);
                const CHAR *ppathspec = path.get();
                if (0 == _stricmp(ppathspec, pcszURL))
                {
                        nsCOMPtr<nsIDOMDocument> tabdoc;
                        webNav->GetDocument(getter_AddRefs(tabdoc));
                        if (tabdoc.get() == DOMDoc.get())
                        {
                                //
                                //      !!! This is the required tab. !!!
                                //      !!! This is the tab associated with the request. !!!
                                //
                        }
                }
        }
}
In above code I am comparing nsIDOMDocument pointers to get currently
navigated tab.
Is there another sure way to do this?
With Best Regards,
Vaibhav.
Jens Replied:

I would do it like this. Have a map (or whatever fits your needs) that
keeps track of tab instances. Whenever a tab is created then save off
the DOM Window (nsIDOMWindow) which represents the tab in the given
container. You can add a "TabOpen" event handler to the browser window
if you want to get notified when a new tab has been created and find
the DOM window which represents the tab and do whatever you need to
do.

Now when "OnStateChange" is being called then check if the
"STATE_IS_DOCUMENT" bit is set in aStateFlags. If the bit is set then
grab the DOMWindow pointer from the passed in aWebProgress argument.
This can be a sub frame so you want to make sure that you call
"GetTop" on the window. Now that you have the top window then use that
to identify your tab. You can make a quick look up in your map to
return the desired data.

A few things to remember, if save off the nsIDOMWindow point in the
map then remember to the reference count it correctly.(when you add it
and remove it)

If I remember correctly then you can get a " OnStateChange " event for
a given tab before the "TabOpen" event. If you try to locate the
window in the map then it might not exist. If you do add the
nsDOMWindow to the map at this time then it will match the
nsIDOMWindow that you get when "TabOpen" is invoked so its all good.

You can also add a "TabClose" to keep track of when the user closes a
tab and remove the instance from the map.

Hope this helps.
-Jens Sorensen
Vaibhav
2010-04-20 10:04:02 UTC
Permalink
Post by Vaibhav
Post by Vaibhav
Hi,
I am writing Firefox extension using C++.
In OnStateChange method I want to determine the tab associated with
particular request.
Currently I compare DOM Document Pointers to do it.
OnStateChange()
{
        //==================================================
        //+
        // GET URL
        nsCString url;
        const char *pcszURL;
        aRequest->GetName(url);
        NS_CStringGetData(url, &pcszURL);
        //-
        //==================================================
        nsCOMPtr<nsIDOMWindow> DOMWin;
        rv = aWebProgress->GetDOMWindow(getter_AddRefs(DOMWin));
        nsCOMPtr<nsIDOMDocument> DOMDoc;
        rv = DOMWin->GetDocument(getter_AddRefs(DOMDoc));
        INT iTabIndex;
        nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
        nsCOMPtr<nsIDOMWindowInternal> dwi;
        windowMediator->GetMostRecentWindow(L"navigator:browser",
getter_AddRefs(dwi));
        nsCOMPtr<nsIDOMDocument> doc;
        dwi->GetDocument(getter_AddRefs(doc));
        nsCOMPtr<nsIDOMDocumentXBL> xbl(do_QueryInterface(doc));
        nsCOMPtr<nsIDOMElement> domEl;
        doc->GetElementById(NS_LITERAL_STRING("content"),
getter_AddRefs(domEl));
        nsCOMPtr<nsIDOMElement> pAnoEl;
        //
    // getting xul:tabpanels
        //
        xbl->GetAnonymousElementByAttribute(
                                                                                domEl,
                                                                                NS_LITERAL_STRING("anonid"),
NS_LITERAL_STRING("panelcontainer"),
                                                                                getter_AddRefs(pAnoEl)
                                                                                );
        nsString retval;
        PRBool bRet = 0;
        nsCOMPtr<nsIDOMNodeList> nodeList;
        pAnoEl->GetChildNodes(getter_AddRefs(nodeList));
        nsCOMPtr<nsIDOMNode> domNode;
        PRUint32 len = 0;
        rv = nodeList->GetLength(&len);
        for( PRUint32 i=0; i<len; i++ )
        {
                // getting the xul::notificationbox
                nsCOMPtr<nsIDOMNode> domNode;
                nodeList->Item(i, getter_AddRefs(domNode));
                // get the last child of the 'xul::notificationbox' which is the
'xul:browser'
                nsCOMPtr<nsIDOMNode> domXULBrowser;
                domNode->GetLastChild(getter_AddRefs(domXULBrowser));
                nsCOMPtr<nsIDOMXULElement> xulElement =
do_QueryInterface(domXULBrowser);
                nsCOMPtr<nsIBoxObject> boxObject;
                xulElement->GetBoxObject(getter_AddRefs(boxObject));
                nsCOMPtr<nsIBrowserBoxObject> browserboxObject =
do_QueryInterface(boxObject);
                nsCOMPtr<nsIDocShell> docShell;
                browserboxObject->GetDocShell(getter_AddRefs(docShell));
                nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(docShell);
                nsCOMPtr<nsIURI> uri;
                webNav->GetCurrentURI(getter_AddRefs(uri));
                nsCString path;
                uri->GetAsciiSpec(path);
                const CHAR *ppathspec = path.get();
                if (0 == _stricmp(ppathspec, pcszURL))
                {
                        nsCOMPtr<nsIDOMDocument> tabdoc;
                        webNav->GetDocument(getter_AddRefs(tabdoc));
                        if (tabdoc.get() == DOMDoc.get())
                        {
                                //
                                //      !!! This is the required tab. !!!
                                //      !!! This is the tab associated with the request. !!!
                                //
                        }
                }
        }
}
In above code I am comparing nsIDOMDocument pointers to get currently
navigated tab.
Is there another sure way to do this?
With Best Regards,
Vaibhav.
I would do it like this. Have a map (or whatever fits your needs) that
keeps track of tab instances. Whenever a tab is created then save off
the DOM Window (nsIDOMWindow) which represents the tab in the given
container. You can add a "TabOpen" event handler to the browser window
if you want to get notified when a new tab has been created and find
the DOM window which represents the tab and do whatever you need to
do.
Now when "OnStateChange" is being called then check if the
"STATE_IS_DOCUMENT" bit is set in aStateFlags. If the bit is set then
grab the DOMWindow pointer from the passed in aWebProgress argument.
This can be a sub frame so you want to make sure that you call
"GetTop" on the window. Now that you have the top window then use that
to identify your tab. You can make a quick look up in your map to
return the desired data.
A few things to remember, if save off the nsIDOMWindow point in the
map then remember to the reference count it correctly.(when you add it
and remove it)
If I remember correctly then you can get a " OnStateChange " event for
a given tab before the "TabOpen" event. If you try to locate the
window in the map then it might not exist. If you do add the
nsDOMWindow to the map at this time then it will match the
nsIDOMWindow that you get when "TabOpen" is invoked so its all good.
You can also add a "TabClose" to keep track of when the user closes a
tab and remove the instance from the map.
Hope this helps.
-Jens Sorensen
Hi,

Jens, Very Thanks for your reply.

In OnStateChange method, nsIDOMWindow pointer is unique for every tab,
but it is different from nsIDOMWindow pointer I get in "TabSelect"/
"TabOpen" event handler i.e. HandleEvent method.


I am registering for Tab Events i.e. (TabOpen, TabClose, TabSelect,
TabMove) in OnStateChange.

Pseudocode of OnStateChange:

OnStateChange()
{
if ((aStateFlags & STATE_START) && (aStateFlags &
STATE_IS_DOCUMENT))
{
nsCOMPtr<nsIDOMWindow> domwin;
aWebProgress->GetDOMWindow(getter_AddRefs(domwin));
nsCOMPtr<nsIDOMWindow> domtopwin;
domwin->GetTop(getter_AddRefs(domtopwin)); // *** This
domtopwin pointer is unique for every tab.***

nsCOMPtr<nsIDOMEventTarget> evtTarget =
do_QueryInterface(domtopwin);
evtTarget->AddEventListener(NS_LITERAL_STRING("TabOpen"),
this, PR_FALSE);
evtTarget->AddEventListener(NS_LITERAL_STRING("TabClose"),
this, PR_FALSE);
evtTarget->AddEventListener(NS_LITERAL_STRING("TabMove"),
this, PR_FALSE);
evtTarget->AddEventListener(NS_LITERAL_STRING("TabSelect"),
this, PR_FALSE);
evtTarget->AddEventListener(NS_LITERAL_STRING("click"), this,
PR_FALSE);
}
}


Pseudocode of HandleEvent:

HandleEvent(nsIDOMEvent *event)
{
nsEmbedString type;
event->GetType(type);
const PRUnichar *data = type.get();

if (0 == _wcsicmp(data, L"TabOpen"))
{
nsCOMPtr<nsIDOMEventTarget> tab;
event->GetCurrentTarget(getter_AddRefs(tab));

nsCOMPtr<nsIDOMWindow> domwin;
domwin = do_QueryInterface(tab, &rv);

// Here I Called GetTop, but it also returns same pointer as that of
domwin

nsCOMPtr<nsIDOMWindow> domtopwin;
domwin->GetTop(getter_AddRefs(domtopwin));

// Here domtopwin is equal to domwin
}
}


Why DOM Window Pointer from OnStateChange is different than that of
HandleEvent's TabOpen?

With Best Regards,
Vaibhav.
Jens Sorensen
2010-04-21 02:19:15 UTC
Permalink
You are using the wrong DOM window in "HandleEvent"...

I assume you already saved off the panel container, and that you added
the event listeners (if not then look at one of my ealier posts). But
the call basically looks like this..

xbl->GetAnonymousElementByAttribute(domEl,
NS_LITERAL_STRING("anonid"), NS_LITERAL_STRING("panelcontainer"),
getter_AddRefs(panelcontainer) );


NS_IMETHODIMP XXXXXX::HandleEvent(nsIDOMEvent* event)

if( This_Is_The_TabOpen_Event )
{
// Get a collection of all the tabs using the saved off panelcontainer pointer
nsCOMPtr<nsIDOMNodeList> tabs;
panelContainer->GetChildNodes(getter_AddRefs(tabs));

// Its pretty safe to assume that the new tab will be last in the collection
// since new tabs are always appended, lets get the # of tabs
PRUint32 tabCount = 0;
tabs->GetLength(&tabCount);

// Lets get the last tab which is the 'xul::notificationbox' element
for the given tab
nsCOMPtr<nsIDOMNode> newTab;
tabs->Item(tabCount-1, getter_AddRefs(newTab));

// get the last child of the 'xul::notificationbox' which is the
'xul:browser' element
nsCOMPtr<nsIDOMNode> domXULBrowser;
newTab->GetLastChild(getter_AddRefs(domXULBrowser));

nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(domXULBrowser);
nsCOMPtr<nsIBoxObject> boxObject;
xulElement->GetBoxObject(getter_AddRefs(boxObject));
nsCOMPtr<nsIBrowserBoxObject> browserboxObject = do_QueryInterface(boxObject);

nsCOMPtr<nsIDocShell> docShell;
browserboxObject->GetDocShell(getter_AddRefs(docShell));

nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(docShell);
// From here you can get the dom document etc...
:
:

You should be able to match up the above domWindow with the one you
get in your progress listener

Plus you should not be adding "TabOpen" etc. event listeners in you
OnStateChange function. This function will get called a lot plus its
the wrong object that you are adding the event listeners to. You want
to keep "OnStateChange" as light as possible since it will impact
browser performance.


You might find this link very useful
https://developer.mozilla.org/en/Code_snippets/Tabbed_browser

Here is a Java script example.. (Taken from the above link)

// During initialisation
var container = gBrowser.tabContainer;
container.addEventListener("TabOpen", exampleTabAdded, false);

Hope this helps.. You are almost there :)

-Jens
Post by Vaibhav
Post by Vaibhav
Post by Vaibhav
Hi,
I am writing Firefox extension using C++.
In OnStateChange method I want to determine the tab associated with
particular request.
Currently I compare DOM Document Pointers to do it.
OnStateChange()
{
        //==================================================
        //+
        // GET URL
        nsCString url;
        const char *pcszURL;
        aRequest->GetName(url);
        NS_CStringGetData(url, &pcszURL);
        //-
        //==================================================
        nsCOMPtr<nsIDOMWindow> DOMWin;
        rv = aWebProgress->GetDOMWindow(getter_AddRefs(DOMWin));
        nsCOMPtr<nsIDOMDocument> DOMDoc;
        rv = DOMWin->GetDocument(getter_AddRefs(DOMDoc));
        INT iTabIndex;
        nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
        nsCOMPtr<nsIDOMWindowInternal> dwi;
        windowMediator->GetMostRecentWindow(L"navigator:browser",
getter_AddRefs(dwi));
        nsCOMPtr<nsIDOMDocument> doc;
        dwi->GetDocument(getter_AddRefs(doc));
        nsCOMPtr<nsIDOMDocumentXBL> xbl(do_QueryInterface(doc));
        nsCOMPtr<nsIDOMElement> domEl;
        doc->GetElementById(NS_LITERAL_STRING("content"),
getter_AddRefs(domEl));
        nsCOMPtr<nsIDOMElement> pAnoEl;
        //
    // getting xul:tabpanels
        //
        xbl->GetAnonymousElementByAttribute(
                                                                                domEl,
                                                                                NS_LITERAL_STRING("anonid"),
NS_LITERAL_STRING("panelcontainer"),
                                                                                getter_AddRefs(pAnoEl)
                                                                                );
        nsString retval;
        PRBool bRet = 0;
        nsCOMPtr<nsIDOMNodeList> nodeList;
        pAnoEl->GetChildNodes(getter_AddRefs(nodeList));
        nsCOMPtr<nsIDOMNode> domNode;
        PRUint32 len = 0;
        rv = nodeList->GetLength(&len);
        for( PRUint32 i=0; i<len; i++ )
        {
                // getting the xul::notificationbox
                nsCOMPtr<nsIDOMNode> domNode;
                nodeList->Item(i, getter_AddRefs(domNode));
                // get the last child of the 'xul::notificationbox' which is the
'xul:browser'
                nsCOMPtr<nsIDOMNode> domXULBrowser;
                domNode->GetLastChild(getter_AddRefs(domXULBrowser));
                nsCOMPtr<nsIDOMXULElement> xulElement =
do_QueryInterface(domXULBrowser);
                nsCOMPtr<nsIBoxObject> boxObject;
                xulElement->GetBoxObject(getter_AddRefs(boxObject));
                nsCOMPtr<nsIBrowserBoxObject> browserboxObject =
do_QueryInterface(boxObject);
                nsCOMPtr<nsIDocShell> docShell;
                browserboxObject->GetDocShell(getter_AddRefs(docShell));
                nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(docShell);
                nsCOMPtr<nsIURI> uri;
                webNav->GetCurrentURI(getter_AddRefs(uri));
                nsCString path;
                uri->GetAsciiSpec(path);
                const CHAR *ppathspec = path.get();
                if (0 == _stricmp(ppathspec, pcszURL))
                {
                        nsCOMPtr<nsIDOMDocument> tabdoc;
                        webNav->GetDocument(getter_AddRefs(tabdoc));
                        if (tabdoc.get() == DOMDoc.get())
                        {
                                //
                                //      !!! This is the required tab. !!!
                                //      !!! This is the tab associated with the request. !!!
                                //
                        }
                }
        }
}
In above code I am comparing nsIDOMDocument pointers to get currently
navigated tab.
Is there another sure way to do this?
With Best Regards,
Vaibhav.
I would do it like this. Have a map (or whatever fits your needs) that
keeps track of tab instances. Whenever a tab is created then save off
the DOM Window (nsIDOMWindow) which represents the tab in the given
container. You can add a "TabOpen" event handler to the browser window
if you want to get notified when a new tab has been created and find
the DOM window which represents the tab and do whatever you need to
do.
Now when "OnStateChange" is being called then check if the
"STATE_IS_DOCUMENT" bit is set in aStateFlags. If the bit is set then
grab the DOMWindow pointer from the passed in aWebProgress argument.
This can be a sub frame so you want to make sure that you call
"GetTop" on the window. Now that you have the top window then use that
to identify your tab. You can make a quick look up in your map to
return the desired data.
A few things to remember, if save off the nsIDOMWindow point in the
map then remember to the reference count it correctly.(when you add it
and remove it)
If I remember correctly then you can get a " OnStateChange " event for
a given tab before the "TabOpen" event. If you try to locate the
window in the map then it might not exist. If you do add the
nsDOMWindow to the map at this time then it will match the
nsIDOMWindow that you get when "TabOpen" is invoked so its all good.
You can also add a "TabClose" to keep track of when the user closes a
tab and remove the instance from the map.
Hope this helps.
-Jens Sorensen
Hi,
Jens, Very Thanks for your reply.
In OnStateChange method, nsIDOMWindow pointer is unique for every tab,
but it is different from nsIDOMWindow pointer I get in "TabSelect"/
"TabOpen" event handler i.e. HandleEvent method.
I am registering for Tab Events i.e. (TabOpen, TabClose, TabSelect,
TabMove) in OnStateChange.
OnStateChange()
{
  if ((aStateFlags & STATE_START) && (aStateFlags &
STATE_IS_DOCUMENT))
  {
       nsCOMPtr<nsIDOMWindow> domwin;
       aWebProgress->GetDOMWindow(getter_AddRefs(domwin));
       nsCOMPtr<nsIDOMWindow> domtopwin;
       domwin->GetTop(getter_AddRefs(domtopwin)); // *** This
domtopwin pointer is unique for every tab.***
       nsCOMPtr<nsIDOMEventTarget> evtTarget =
do_QueryInterface(domtopwin);
       evtTarget->AddEventListener(NS_LITERAL_STRING("TabOpen"),
this, PR_FALSE);
       evtTarget->AddEventListener(NS_LITERAL_STRING("TabClose"),
this, PR_FALSE);
       evtTarget->AddEventListener(NS_LITERAL_STRING("TabMove"),
this, PR_FALSE);
       evtTarget->AddEventListener(NS_LITERAL_STRING("TabSelect"),
this, PR_FALSE);
       evtTarget->AddEventListener(NS_LITERAL_STRING("click"), this,
PR_FALSE);
  }
}
HandleEvent(nsIDOMEvent *event)
{
   nsEmbedString type;
   event->GetType(type);
   const PRUnichar *data = type.get();
   if (0 == _wcsicmp(data, L"TabOpen"))
   {
       nsCOMPtr<nsIDOMEventTarget> tab;
       event->GetCurrentTarget(getter_AddRefs(tab));
       nsCOMPtr<nsIDOMWindow> domwin;
       domwin = do_QueryInterface(tab, &rv);
       // Here I Called GetTop, but it also returns same pointer as that of
domwin
       nsCOMPtr<nsIDOMWindow> domtopwin;
       domwin->GetTop(getter_AddRefs(domtopwin));
       // Here domtopwin is equal to domwin
   }
}
Why DOM Window Pointer from OnStateChange is different than that of
HandleEvent's TabOpen?
With Best Regards,
Vaibhav.
_______________________________________________
dev-tech-dom mailing list
https://lists.mozilla.org/listinfo/dev-tech-dom
Vaibhav
2010-04-22 13:07:59 UTC
Permalink
Post by Jens Sorensen
You are using the wrong DOM window in "HandleEvent"...
I assume you already saved off the panel container, and that you added
the event listeners  (if not then look at one of my ealier posts). But
the call basically looks like this..
xbl->GetAnonymousElementByAttribute(domEl,
NS_LITERAL_STRING("anonid"), NS_LITERAL_STRING("panelcontainer"),
getter_AddRefs(panelcontainer)  );
NS_IMETHODIMP XXXXXX::HandleEvent(nsIDOMEvent* event)
        if( This_Is_The_TabOpen_Event )
        {      
                // Get a collection of all the tabs using the saved off panelcontainer pointer
                nsCOMPtr<nsIDOMNodeList> tabs;
                panelContainer->GetChildNodes(getter_AddRefs(tabs));
                // Its pretty safe to assume that the new tab will be last in the collection
                // since new tabs are always appended, lets get the # of tabs
                PRUint32 tabCount = 0;
                tabs->GetLength(&tabCount);
                // Lets get the last tab which is the 'xul::notificationbox' element
for the given tab
                nsCOMPtr<nsIDOMNode> newTab;
                tabs->Item(tabCount-1, getter_AddRefs(newTab));
                // get the last child of the 'xul::notificationbox' which is the
'xul:browser' element
                nsCOMPtr<nsIDOMNode> domXULBrowser;
                newTab->GetLastChild(getter_AddRefs(domXULBrowser));
                nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(domXULBrowser);
                nsCOMPtr<nsIBoxObject> boxObject;
                xulElement->GetBoxObject(getter_AddRefs(boxObject));
                nsCOMPtr<nsIBrowserBoxObject> browserboxObject = do_QueryInterface(boxObject);
                nsCOMPtr<nsIDocShell> docShell;
                browserboxObject->GetDocShell(getter_AddRefs(docShell));
                nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(docShell);
                // From here you can get the dom document etc...
                                        :                                      
You should be able to match up the above domWindow with the one you
get in your progress listener
Plus you should not be adding "TabOpen" etc. event listeners in you
OnStateChange function. This function will get called a lot plus its
the wrong object that you are adding the event listeners to. You want
to keep "OnStateChange" as light as possible since it will impact
browser performance.
You might find this link very usefulhttps://developer.mozilla.org/en/Code_snippets/Tabbed_browser
Here is a Java script example.. (Taken from the above link)
// During initialisation
var container = gBrowser.tabContainer;
container.addEventListener("TabOpen", exampleTabAdded, false);
Hope this helps.. You are almost there :)
-Jens
Post by Vaibhav
Post by Vaibhav
Post by Vaibhav
Hi,
I am writing Firefox extension using C++.
In OnStateChange method I want to determine the tab associated with
particular request.
Currently I compare DOM Document Pointers to do it.
OnStateChange()
{
        //==================================================
        //+
        // GET URL
        nsCString url;
        const char *pcszURL;
        aRequest->GetName(url);
        NS_CStringGetData(url, &pcszURL);
        //-
        //==================================================
        nsCOMPtr<nsIDOMWindow> DOMWin;
        rv = aWebProgress->GetDOMWindow(getter_AddRefs(DOMWin));
        nsCOMPtr<nsIDOMDocument> DOMDoc;
        rv = DOMWin->GetDocument(getter_AddRefs(DOMDoc));
        INT iTabIndex;
        nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
        nsCOMPtr<nsIDOMWindowInternal> dwi;
        windowMediator->GetMostRecentWindow(L"navigator:browser",
getter_AddRefs(dwi));
        nsCOMPtr<nsIDOMDocument> doc;
        dwi->GetDocument(getter_AddRefs(doc));
        nsCOMPtr<nsIDOMDocumentXBL> xbl(do_QueryInterface(doc));
        nsCOMPtr<nsIDOMElement> domEl;
        doc->GetElementById(NS_LITERAL_STRING("content"),
getter_AddRefs(domEl));
        nsCOMPtr<nsIDOMElement> pAnoEl;
        //
    // getting xul:tabpanels
        //
        xbl->GetAnonymousElementByAttribute(
                                                                                domEl,
                                                                                NS_LITERAL_STRING("anonid"),
NS_LITERAL_STRING("panelcontainer"),
                                                                                getter_AddRefs(pAnoEl)
                                                                                );
        nsString retval;
        PRBool bRet = 0;
        nsCOMPtr<nsIDOMNodeList> nodeList;
        pAnoEl->GetChildNodes(getter_AddRefs(nodeList));
        nsCOMPtr<nsIDOMNode> domNode;
        PRUint32 len = 0;
        rv = nodeList->GetLength(&len);
        for( PRUint32 i=0; i<len; i++ )
        {
                // getting the xul::notificationbox
                nsCOMPtr<nsIDOMNode> domNode;
                nodeList->Item(i, getter_AddRefs(domNode));
                // get the last child of the 'xul::notificationbox' which is the
'xul:browser'
                nsCOMPtr<nsIDOMNode> domXULBrowser;
                domNode->GetLastChild(getter_AddRefs(domXULBrowser));
                nsCOMPtr<nsIDOMXULElement> xulElement =
do_QueryInterface(domXULBrowser);
                nsCOMPtr<nsIBoxObject> boxObject;
                xulElement->GetBoxObject(getter_AddRefs(boxObject));
                nsCOMPtr<nsIBrowserBoxObject> browserboxObject =
do_QueryInterface(boxObject);
                nsCOMPtr<nsIDocShell> docShell;
                browserboxObject->GetDocShell(getter_AddRefs(docShell));
                nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(docShell);
                nsCOMPtr<nsIURI> uri;
                webNav->GetCurrentURI(getter_AddRefs(uri));
                nsCString path;
                uri->GetAsciiSpec(path);
                const CHAR *ppathspec = path.get();
                if (0 == _stricmp(ppathspec, pcszURL))
                {
                        nsCOMPtr<nsIDOMDocument> tabdoc;
                        webNav->GetDocument(getter_AddRefs(tabdoc));
                        if (tabdoc.get() == DOMDoc.get())
                        {
                                //
                                //      !!! This is the required tab. !!!
                                //      !!! This is the tab associated with the request. !!!
                                //
                        }
                }
        }
}
In above code I am comparing nsIDOMDocument pointers to get currently
navigated tab.
Is there another sure way to do this?
With Best Regards,
Vaibhav.
I would do it like this. Have a map (or whatever fits your needs) that
keeps track of tab instances. Whenever a tab is created then save off
the DOM Window (nsIDOMWindow) which represents the tab in the given
container. You can add a "TabOpen" event handler to the browser window
if you want to get notified when a new tab has been created and find
the DOM window which represents the tab and do whatever you need to
do.
Now when "OnStateChange" is being called then check if the
"STATE_IS_DOCUMENT" bit is set in aStateFlags. If the bit is set then
grab the DOMWindow pointer from the passed in aWebProgress argument.
This can be a sub frame so you want to make sure that you call
"GetTop" on the window. Now that you have the top window then use that
to identify your tab. You can make a quick look up in your map to
return the desired data.
A few things to remember, if save off the nsIDOMWindow point in the
map then remember to the reference count it correctly.(when you add it
and remove it)
If I remember correctly then you can get a " OnStateChange " event for
a given tab before the "TabOpen" event. If you try to locate the
window in the map then it might not exist. If you do add the
nsDOMWindow to the map at this time then it will match the
nsIDOMWindow that you get when "TabOpen" is invoked so its all good.
You can also add a "TabClose" to keep track of when the user closes a
tab and remove the instance from the map.
Hope this helps.
-Jens Sorensen
Hi,
Jens, Very Thanks for your reply.
In OnStateChange method, nsIDOMWindow pointer is unique for every tab,
but it is different from nsIDOMWindow pointer I get in "TabSelect"/
"TabOpen" event handler i.e. HandleEvent method.
I am registering for Tab Events i.e. (TabOpen, TabClose, TabSelect,
TabMove) in OnStateChange.
OnStateChange()
{
  if ((aStateFlags & STATE_START) && (aStateFlags &
STATE_IS_DOCUMENT))
  {
       nsCOMPtr<nsIDOMWindow> domwin;
       aWebProgress->GetDOMWindow(getter_AddRefs(domwin));
       nsCOMPtr<nsIDOMWindow> domtopwin;
       domwin->GetTop(getter_AddRefs(domtopwin)); // *** This
domtopwin pointer is unique for...
read more »
Hello Jens,

Very Thanks for providing me solution.

I am still confused about where do I register Tab & Click events in C+
+.
After reading your last post, I moved my Tab & Click Registration code
to javascript file.

It is as follows:

///////////////////////////////////////////////////////////////////////////////
function Init()
{
var container;
container = gBrowser.tabContainer;

netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
const cid = '@MyXPCOM/TestComponent';
var obj =
Components.classes[cid].getService(Components.interfaces.iTestComponent);

container.addEventListener("TabOpen", obj, false);
container.addEventListener("TabMove", obj, false);
container.addEventListener("TabClose", obj, false);
container.addEventListener("TabSelect", obj, false);
window.addEventListener("click", obj, false);
}

function DeInit()
{
// Actually I want to unregister Tab & Click events, but till this
function gets called
// component instance is no more.
}

window.addEventListener('load', Init, false);
window.addEventListener('unload', DeInit, false);

///////////////////////////////////////////////////////////////

But I want to do above things in C++.

Vaibhav.
Vaibhav
2010-04-27 03:52:04 UTC
Permalink
Post by Vaibhav
Post by Jens Sorensen
I assume you already saved off the panel container, and that you added
the event listeners  (if not then look at one of my ealier posts). But
the call basically looks like this..
xbl->GetAnonymousElementByAttribute(domEl,
NS_LITERAL_STRING("anonid"), NS_LITERAL_STRING("panelcontainer"),
getter_AddRefs(panelcontainer)  );
NS_IMETHODIMP XXXXXX::HandleEvent(nsIDOMEvent* event)
        if( This_Is_The_TabOpen_Event )
        {      
                // Get a collection of all the tabs using the saved off panelcontainer pointer
                nsCOMPtr<nsIDOMNodeList> tabs;
                panelContainer->GetChildNodes(getter_AddRefs(tabs));
                // Its pretty safe to assume that the new tab will be last in the collection
                // since new tabs are always appended, lets get the # of tabs
                PRUint32 tabCount = 0;
                tabs->GetLength(&tabCount);
                // Lets get the last tab which is the 'xul::notificationbox' element
for the given tab
                nsCOMPtr<nsIDOMNode> newTab;
                tabs->Item(tabCount-1, getter_AddRefs(newTab));
                // get the last child of the 'xul::notificationbox' which is the
'xul:browser' element
                nsCOMPtr<nsIDOMNode> domXULBrowser;
                newTab->GetLastChild(getter_AddRefs(domXULBrowser));
                nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(domXULBrowser);
                nsCOMPtr<nsIBoxObject> boxObject;
                xulElement->GetBoxObject(getter_AddRefs(boxObject));
                nsCOMPtr<nsIBrowserBoxObject> browserboxObject = do_QueryInterface(boxObject);
                nsCOMPtr<nsIDocShell> docShell;
                browserboxObject->GetDocShell(getter_AddRefs(docShell));
                nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(docShell);
                // From here you can get the dom document etc...
                                        :                                      
You should be able to match up the above domWindow with the one you
get in your progress listener
Plus you should not be adding "TabOpen" etc. event listeners in you
OnStateChange function. This function will get called a lot plus its
the wrong object that you are adding the event listeners to. You want
to keep "OnStateChange" as light as possible since it will impact
browser performance.
You might find this link very usefulhttps://developer.mozilla.org/en/Code_snippets/Tabbed_browser
Here is a Java script example.. (Taken from the above link)
// During initialisation
var container = gBrowser.tabContainer;
container.addEventListener("TabOpen", exampleTabAdded, false);
Hope this helps.. You are almost there :)
-Jens
Post by Vaibhav
Post by Vaibhav
Post by Vaibhav
Hi,
I am writing Firefox extension using C++.
In OnStateChange method I want to determine the tab associated with
particular request.
Currently I compare DOM Document Pointers to do it.
OnStateChange()
{
        //==================================================
        //+
        // GET URL
        nsCString url;
        const char *pcszURL;
        aRequest->GetName(url);
        NS_CStringGetData(url, &pcszURL);
        //-
        //==================================================
        nsCOMPtr<nsIDOMWindow> DOMWin;
        rv = aWebProgress->GetDOMWindow(getter_AddRefs(DOMWin));
        nsCOMPtr<nsIDOMDocument> DOMDoc;
        rv = DOMWin->GetDocument(getter_AddRefs(DOMDoc));
        INT iTabIndex;
        nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
        nsCOMPtr<nsIDOMWindowInternal> dwi;
        windowMediator->GetMostRecentWindow(L"navigator:browser",
getter_AddRefs(dwi));
        nsCOMPtr<nsIDOMDocument> doc;
        dwi->GetDocument(getter_AddRefs(doc));
        nsCOMPtr<nsIDOMDocumentXBL> xbl(do_QueryInterface(doc));
        nsCOMPtr<nsIDOMElement> domEl;
        doc->GetElementById(NS_LITERAL_STRING("content"),
getter_AddRefs(domEl));
        nsCOMPtr<nsIDOMElement> pAnoEl;
        //
    // getting xul:tabpanels
        //
        xbl->GetAnonymousElementByAttribute(
                                                                                domEl,
                                                                                NS_LITERAL_STRING("anonid"),
NS_LITERAL_STRING("panelcontainer"),
                                                                                getter_AddRefs(pAnoEl)
                                                                                );
        nsString retval;
        PRBool bRet = 0;
        nsCOMPtr<nsIDOMNodeList> nodeList;
        pAnoEl->GetChildNodes(getter_AddRefs(nodeList));
        nsCOMPtr<nsIDOMNode> domNode;
        PRUint32 len = 0;
        rv = nodeList->GetLength(&len);
        for( PRUint32 i=0; i<len; i++ )
        {
                // getting the xul::notificationbox
                nsCOMPtr<nsIDOMNode> domNode;
                nodeList->Item(i, getter_AddRefs(domNode));
                // get the last child of the 'xul::notificationbox' which is the
'xul:browser'
                nsCOMPtr<nsIDOMNode> domXULBrowser;
                domNode->GetLastChild(getter_AddRefs(domXULBrowser));
                nsCOMPtr<nsIDOMXULElement> xulElement =
do_QueryInterface(domXULBrowser);
                nsCOMPtr<nsIBoxObject> boxObject;
                xulElement->GetBoxObject(getter_AddRefs(boxObject));
                nsCOMPtr<nsIBrowserBoxObject> browserboxObject =
do_QueryInterface(boxObject);
                nsCOMPtr<nsIDocShell> docShell;
                browserboxObject->GetDocShell(getter_AddRefs(docShell));
                nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(docShell);
                nsCOMPtr<nsIURI> uri;
                webNav->GetCurrentURI(getter_AddRefs(uri));
                nsCString path;
                uri->GetAsciiSpec(path);
                const CHAR *ppathspec = path.get();
                if (0 == _stricmp(ppathspec, pcszURL))
                {
                        nsCOMPtr<nsIDOMDocument> tabdoc;
                        webNav->GetDocument(getter_AddRefs(tabdoc));
                        if (tabdoc.get() == DOMDoc.get())
                        {
                                //
                                //      !!! This is the required tab. !!!
                                //      !!! This is the tab associated with the request. !!!
                                //
                        }
                }
        }
}
In above code I am comparing nsIDOMDocument pointers to get currently
navigated tab.
Is there another sure way to do this?
With Best Regards,
Vaibhav.
I would do it like this. Have a map (or whatever fits your needs) that
keeps track of tab instances. Whenever a tab is created then save off
the DOM Window (nsIDOMWindow) which represents the tab in the given
container. You can add a "TabOpen" event handler to the browser window
if you want to get notified when a new tab has been created and find
the DOM window which represents the tab and do whatever you need to
do.
Now when "OnStateChange" is being called then check if the
"STATE_IS_DOCUMENT" bit is set in aStateFlags. If the bit is set then
grab the DOMWindow pointer from the passed in aWebProgress argument.
This can be a sub frame so you want to make sure that you call
"GetTop" on the window. Now that you have the top window then use that
to identify your tab. You can make a quick look up in your map to
return the desired data.
A few things to remember, if save off the nsIDOMWindow point in the
map then remember to the reference count it correctly.(when you add it
and remove it)
If I remember correctly then you can get a " OnStateChange " event for
a given tab before the "TabOpen" event. If you try to locate the
window in the map then it might not exist. If you do add the
nsDOMWindow to the map at this time then it will match the
nsIDOMWindow that you get when "TabOpen" is invoked so its all good.
You can also add a "TabClose" to keep track of when the user closes a
tab and remove the instance from the map.
Hope this helps.
-Jens Sorensen
Hi,
Jens, Very Thanks for your reply.
In OnStateChange method, nsIDOMWindow pointer is unique for every tab,
but it is different from nsIDOMWindow pointer I get in "TabSelect"/
"TabOpen" event handler i.e. HandleEvent method.
I am registering for Tab Events i.e. (TabOpen, TabClose, TabSelect,
TabMove) in OnStateChange.
OnStateChange()
{
  if ((aStateFlags & STATE_START) && (aStateFlags &
STATE_IS_DOCUMENT))
  {
       nsCOMPtr<nsIDOMWindow> domwin;
       aWebProgress->GetDOMWindow(getter_AddRefs(domwin));
       nsCOMPtr<nsIDOMWindow> domtopwin;
       domwin->GetTop(getter_AddRefs(domtopwin)); // *** This
domtopwin pointer is unique for...
read more »
Hello Jens,
Very Thanks for providing me solution.
I am still confused about where do I register Tab & Click events in C+
+.
After reading your last post, I moved my Tab & Click Registration code
to javascript file.
/////////////////////////////////////////////////////////////////////////// ////
function Init()
{
        var container;
        container = gBrowser.tabContainer;
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
        var obj =
Components.classes[cid].getService(Components.interfaces.iTestComponent);
        container.addEventListener("TabOpen", obj, false);
        container.addEventListener("TabMove", obj, false);
        container.addEventListener("TabClose", obj, false);
        container.addEventListener("TabSelect", obj, false);
        window.addEventListener("click", obj, false);
}
function DeInit()
{
    // Actually I want to unregister Tab & Click events, but till this
function gets called
    // component instance is no more.
}
window.addEventListener('load', Init, false);
window.addEventListener('unload', DeInit, false);
///////////////////////////////////////////////////////////////
But I want to do above things in C++.
Vaibhav.
Hi,

Answer to above question is at:

http://groups.google.com/group/mozilla.dev.tech.dom/browse_thread/thread/3a4cbe436f4cf22b#

Vaibhav.
Jens Sorensen
2010-04-27 04:32:21 UTC
Permalink
You are welcome, let me know if you need to know how to get to the
actual document from the TabXXX event..
Thanks
Jens Sorensen
Post by Vaibhav
Post by Vaibhav
Post by Jens Sorensen
I assume you already saved off the panel container, and that you added
the event listeners  (if not then look at one of my ealier posts). But
the call basically looks like this..
xbl->GetAnonymousElementByAttribute(domEl,
NS_LITERAL_STRING("anonid"), NS_LITERAL_STRING("panelcontainer"),
getter_AddRefs(panelcontainer)  );
NS_IMETHODIMP XXXXXX::HandleEvent(nsIDOMEvent* event)
        if( This_Is_The_TabOpen_Event )
        {
                // Get a collection of all the tabs using the saved off panelcontainer pointer
                nsCOMPtr<nsIDOMNodeList> tabs;
                panelContainer->GetChildNodes(getter_AddRefs(tabs));
                // Its pretty safe to assume that the new tab will be last in the collection
                // since new tabs are always appended, lets get the # of tabs
                PRUint32 tabCount = 0;
                tabs->GetLength(&tabCount);
                // Lets get the last tab which is the 'xul::notificationbox' element
for the given tab
                nsCOMPtr<nsIDOMNode> newTab;
                tabs->Item(tabCount-1, getter_AddRefs(newTab));
                // get the last child of the 'xul::notificationbox' which is the
'xul:browser' element
                nsCOMPtr<nsIDOMNode> domXULBrowser;
                newTab->GetLastChild(getter_AddRefs(domXULBrowser));
                nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(domXULBrowser);
                nsCOMPtr<nsIBoxObject> boxObject;
                xulElement->GetBoxObject(getter_AddRefs(boxObject));
                nsCOMPtr<nsIBrowserBoxObject> browserboxObject = do_QueryInterface(boxObject);
                nsCOMPtr<nsIDocShell> docShell;
                browserboxObject->GetDocShell(getter_AddRefs(docShell));
                nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(docShell);
                // From here you can get the dom document etc...
You should be able to match up the above domWindow with the one you
get in your progress listener
Plus you should not be adding "TabOpen" etc. event listeners in you
OnStateChange function. This function will get called a lot plus its
the wrong object that you are adding the event listeners to. You want
to keep "OnStateChange" as light as possible since it will impact
browser performance.
You might find this link very usefulhttps://developer.mozilla.org/en/Code_snippets/Tabbed_browser
Here is a Java script example.. (Taken from the above link)
// During initialisation
var container = gBrowser.tabContainer;
container.addEventListener("TabOpen", exampleTabAdded, false);
Hope this helps.. You are almost there :)
-Jens
Post by Vaibhav
Post by Vaibhav
Post by Vaibhav
Hi,
I am writing Firefox extension using C++.
In OnStateChange method I want to determine the tab associated with
particular request.
Currently I compare DOM Document Pointers to do it.
OnStateChange()
{
        //==================================================
        //+
        // GET URL
        nsCString url;
        const char *pcszURL;
        aRequest->GetName(url);
        NS_CStringGetData(url, &pcszURL);
        //-
        //==================================================
        nsCOMPtr<nsIDOMWindow> DOMWin;
        rv = aWebProgress->GetDOMWindow(getter_AddRefs(DOMWin));
        nsCOMPtr<nsIDOMDocument> DOMDoc;
        rv = DOMWin->GetDocument(getter_AddRefs(DOMDoc));
        INT iTabIndex;
        nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
        nsCOMPtr<nsIDOMWindowInternal> dwi;
        windowMediator->GetMostRecentWindow(L"navigator:browser",
getter_AddRefs(dwi));
        nsCOMPtr<nsIDOMDocument> doc;
        dwi->GetDocument(getter_AddRefs(doc));
        nsCOMPtr<nsIDOMDocumentXBL> xbl(do_QueryInterface(doc));
        nsCOMPtr<nsIDOMElement> domEl;
        doc->GetElementById(NS_LITERAL_STRING("content"),
getter_AddRefs(domEl));
        nsCOMPtr<nsIDOMElement> pAnoEl;
        //
    // getting xul:tabpanels
        //
        xbl->GetAnonymousElementByAttribute(
                                                                                domEl,
                                                                                NS_LITERAL_STRING("anonid"),
NS_LITERAL_STRING("panelcontainer"),
                                                                                getter_AddRefs(pAnoEl)
                                                                                );
        nsString retval;
        PRBool bRet = 0;
        nsCOMPtr<nsIDOMNodeList> nodeList;
        pAnoEl->GetChildNodes(getter_AddRefs(nodeList));
        nsCOMPtr<nsIDOMNode> domNode;
        PRUint32 len = 0;
        rv = nodeList->GetLength(&len);
        for( PRUint32 i=0; i<len; i++ )
        {
                // getting the xul::notificationbox
                nsCOMPtr<nsIDOMNode> domNode;
                nodeList->Item(i, getter_AddRefs(domNode));
                // get the last child of the 'xul::notificationbox' which is the
'xul:browser'
                nsCOMPtr<nsIDOMNode> domXULBrowser;
                domNode->GetLastChild(getter_AddRefs(domXULBrowser));
                nsCOMPtr<nsIDOMXULElement> xulElement =
do_QueryInterface(domXULBrowser);
                nsCOMPtr<nsIBoxObject> boxObject;
                xulElement->GetBoxObject(getter_AddRefs(boxObject));
                nsCOMPtr<nsIBrowserBoxObject> browserboxObject =
do_QueryInterface(boxObject);
                nsCOMPtr<nsIDocShell> docShell;
                browserboxObject->GetDocShell(getter_AddRefs(docShell));
                nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(docShell);
                nsCOMPtr<nsIURI> uri;
                webNav->GetCurrentURI(getter_AddRefs(uri));
                nsCString path;
                uri->GetAsciiSpec(path);
                const CHAR *ppathspec = path.get();
                if (0 == _stricmp(ppathspec, pcszURL))
                {
                        nsCOMPtr<nsIDOMDocument> tabdoc;
                        webNav->GetDocument(getter_AddRefs(tabdoc));
                        if (tabdoc.get() == DOMDoc.get())
                        {
                                //
                                //      !!! This is the required tab. !!!
                                //      !!! This is the tab associated with the request. !!!
                                //
                        }
                }
        }
}
In above code I am comparing nsIDOMDocument pointers to get currently
navigated tab.
Is there another sure way to do this?
With Best Regards,
Vaibhav.
I would do it like this. Have a map (or whatever fits your needs) that
keeps track of tab instances. Whenever a tab is created then save off
the DOM Window (nsIDOMWindow) which represents the tab in the given
container. You can add a "TabOpen" event handler to the browser window
if you want to get notified when a new tab has been created and find
the DOM window which represents the tab and do whatever you need to
do.
Now when "OnStateChange" is being called then check if the
"STATE_IS_DOCUMENT" bit is set in aStateFlags. If the bit is set then
grab the DOMWindow pointer from the passed in aWebProgress argument.
This can be a sub frame so you want to make sure that you call
"GetTop" on the window. Now that you have the top window then use that
to identify your tab. You can make a quick look up in your map to
return the desired data.
A few things to remember, if save off the nsIDOMWindow point in the
map then remember to the reference count it correctly.(when you add it
and remove it)
If I remember correctly then you can get a " OnStateChange " event for
a given tab before the "TabOpen" event. If you try to locate the
window in the map then it might not exist. If you do add the
nsDOMWindow to the map at this time then it will match the
nsIDOMWindow that you get when "TabOpen" is invoked so its all good.
You can also add a "TabClose" to keep track of when the user closes a
tab and remove the instance from the map.
Hope this helps.
-Jens Sorensen
Hi,
Jens, Very Thanks for your reply.
In OnStateChange method, nsIDOMWindow pointer is unique for every tab,
but it is different from nsIDOMWindow pointer I get in "TabSelect"/
"TabOpen" event handler i.e. HandleEvent method.
I am registering for Tab Events i.e. (TabOpen, TabClose, TabSelect,
TabMove) in OnStateChange.
OnStateChange()
{
  if ((aStateFlags & STATE_START) && (aStateFlags &
STATE_IS_DOCUMENT))
  {
       nsCOMPtr<nsIDOMWindow> domwin;
       aWebProgress->GetDOMWindow(getter_AddRefs(domwin));
       nsCOMPtr<nsIDOMWindow> domtopwin;
       domwin->GetTop(getter_AddRefs(domtopwin)); // *** This
domtopwin pointer is unique for...
read more »
Hello Jens,
Very Thanks for providing me solution.
I am still confused about where do I register Tab & Click events in C+
+.
After reading your last post, I moved my Tab & Click Registration code
to javascript file.
/////////////////////////////////////////////////////////////////////////// ////
function Init()
{
        var container;
        container = gBrowser.tabContainer;
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
        var obj =
Components.classes[cid].getService(Components.interfaces.iTestComponent);
        container.addEventListener("TabOpen", obj, false);
        container.addEventListener("TabMove", obj, false);
        container.addEventListener("TabClose", obj, false);
        container.addEventListener("TabSelect", obj, false);
        window.addEventListener("click", obj, false);
}
function DeInit()
{
    // Actually I want to unregister Tab & Click events, but till this
function gets called
    // component instance is no more.
}
window.addEventListener('load', Init, false);
window.addEventListener('unload', DeInit, false);
///////////////////////////////////////////////////////////////
But I want to do above things in C++.
Vaibhav.
Hi,
http://groups.google.com/group/mozilla.dev.tech.dom/browse_thread/thread/3a4cbe436f4cf22b#
Vaibhav.
_______________________________________________
dev-tech-dom mailing list
https://lists.mozilla.org/listinfo/dev-tech-dom
Vaibhav
2010-04-27 13:37:03 UTC
Permalink
Post by Jens Sorensen
You are welcome, let me know if you need to know how to get to the
actual document from the TabXXX event..
Thanks
Jens Sorensen
Post by Jens Sorensen
I assume you already saved off the panel container, and that you added
the event listeners  (if not then look at one of my ealier posts). But
the call basically looks like this..
xbl->GetAnonymousElementByAttribute(domEl,
NS_LITERAL_STRING("anonid"), NS_LITERAL_STRING("panelcontainer"),
getter_AddRefs(panelcontainer)  );
NS_IMETHODIMP XXXXXX::HandleEvent(nsIDOMEvent* event)
        if( This_Is_The_TabOpen_Event )
        {
                // Get a collection of all the tabs using the saved off panelcontainer pointer
                nsCOMPtr<nsIDOMNodeList> tabs;
                panelContainer->GetChildNodes(getter_AddRefs(tabs));
                // Its pretty safe to assume that the new tab will be last in the collection
                // since new tabs are always appended, lets get the # of tabs
                PRUint32 tabCount = 0;
                tabs->GetLength(&tabCount);
                // Lets get the last tab which is the 'xul::notificationbox' element
for the given tab
                nsCOMPtr<nsIDOMNode> newTab;
                tabs->Item(tabCount-1, getter_AddRefs(newTab));
                // get the last child of the 'xul::notificationbox' which is the
'xul:browser' element
                nsCOMPtr<nsIDOMNode> domXULBrowser;
                newTab->GetLastChild(getter_AddRefs(domXULBrowser));
                nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(domXULBrowser);
                nsCOMPtr<nsIBoxObject> boxObject;
                xulElement->GetBoxObject(getter_AddRefs(boxObject));
                nsCOMPtr<nsIBrowserBoxObject> browserboxObject = do_QueryInterface(boxObject);
                nsCOMPtr<nsIDocShell> docShell;
                browserboxObject->GetDocShell(getter_AddRefs(docShell));
                nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(docShell);
                // From here you can get the dom document etc...
You should be able to match up the above domWindow with the one you
get in your progress listener
Plus you should not be adding "TabOpen" etc. event listeners in you
OnStateChange function. This function will get called a lot plus its
the wrong object that you are adding the event listeners to. You want
to keep "OnStateChange" as light as possible since it will impact
browser performance.
You might find this link very usefulhttps://developer.mozilla.org/en/Code_snippets/Tabbed_browser
Here is a Java script example.. (Taken from the above link)
// During initialisation
var container = gBrowser.tabContainer;
container.addEventListener("TabOpen", exampleTabAdded, false);
Hope this helps.. You are almost there :)
-Jens
Post by Vaibhav
Post by Vaibhav
Hi,
I am writing Firefox extension using C++.
In OnStateChange method I want to determine the tab associated with
particular request.
Currently I compare DOM Document Pointers to do it.
OnStateChange()
{
        //==================================================
        //+
        // GET URL
        nsCString url;
        const char *pcszURL;
        aRequest->GetName(url);
        NS_CStringGetData(url, &pcszURL);
        //-
        //==================================================
        nsCOMPtr<nsIDOMWindow> DOMWin;
        rv = aWebProgress->GetDOMWindow(getter_AddRefs(DOMWin));
        nsCOMPtr<nsIDOMDocument> DOMDoc;
        rv = DOMWin->GetDocument(getter_AddRefs(DOMDoc));
        INT iTabIndex;
        nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
        nsCOMPtr<nsIDOMWindowInternal> dwi;
        windowMediator->GetMostRecentWindow(L"navigator:browser",
getter_AddRefs(dwi));
        nsCOMPtr<nsIDOMDocument> doc;
        dwi->GetDocument(getter_AddRefs(doc));
        nsCOMPtr<nsIDOMDocumentXBL> xbl(do_QueryInterface(doc));
        nsCOMPtr<nsIDOMElement> domEl;
        doc->GetElementById(NS_LITERAL_STRING("content"),
getter_AddRefs(domEl));
        nsCOMPtr<nsIDOMElement> pAnoEl;
        //
    // getting xul:tabpanels
        //
        xbl->GetAnonymousElementByAttribute(
                                                                                domEl,
                                                                                NS_LITERAL_STRING("anonid"),
NS_LITERAL_STRING("panelcontainer"),
                                                                                getter_AddRefs(pAnoEl)
                                                                                );
        nsString retval;
        PRBool bRet = 0;
        nsCOMPtr<nsIDOMNodeList> nodeList;
        pAnoEl->GetChildNodes(getter_AddRefs(nodeList));
        nsCOMPtr<nsIDOMNode> domNode;
        PRUint32 len = 0;
        rv = nodeList->GetLength(&len);
        for( PRUint32 i=0; i<len; i++ )
        {
                // getting the xul::notificationbox
                nsCOMPtr<nsIDOMNode> domNode;
                nodeList->Item(i, getter_AddRefs(domNode));
                // get the last child of the 'xul::notificationbox' which is the
'xul:browser'
                nsCOMPtr<nsIDOMNode> domXULBrowser;
                domNode->GetLastChild(getter_AddRefs(domXULBrowser));
                nsCOMPtr<nsIDOMXULElement> xulElement =
do_QueryInterface(domXULBrowser);
                nsCOMPtr<nsIBoxObject> boxObject;
                xulElement->GetBoxObject(getter_AddRefs(boxObject));
                nsCOMPtr<nsIBrowserBoxObject> browserboxObject =
do_QueryInterface(boxObject);
                nsCOMPtr<nsIDocShell> docShell;
                browserboxObject->GetDocShell(getter_AddRefs(docShell));
                nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(docShell);
                nsCOMPtr<nsIURI> uri;
                webNav->GetCurrentURI(getter_AddRefs(uri));
                nsCString path;
                uri->GetAsciiSpec(path);
                const CHAR *ppathspec = path.get();
                if (0 == _stricmp(ppathspec, pcszURL))
                {
                        nsCOMPtr<nsIDOMDocument> tabdoc;
                        webNav->GetDocument(getter_AddRefs(tabdoc));
                        if (tabdoc.get() == DOMDoc.get())
                        {
                                //
                                //      !!! This is the required tab. !!!
                                //      !!! This is the tab associated with the request. !!!
                                //
                        }
                }
        }
}
In above code I am comparing nsIDOMDocument pointers to get currently
navigated tab.
Is there another sure way to do this?
With Best Regards,
Vaibhav.
I would do it like this. Have a map (or whatever fits your needs) that
keeps track of tab instances. Whenever a tab is created then save off
the DOM Window (nsIDOMWindow) which represents the tab in the given
container. You can add a "TabOpen" event handler to the browser window
if you want to get notified when a new tab has been created and find
the DOM window which represents the tab and do whatever you need to
do.
Now when "OnStateChange" is being called then check if the
"STATE_IS_DOCUMENT" bit is set in aStateFlags. If the bit is set then
grab the...
read more »
Very Thanks Jens for ur kind response.

I think I get actual document in following ways:

1. TabOpen:
- Go to the last tab as you specified in previous post
- Get Box Object & Browser Box Object pointers
- Get Web Navigation Pointer
- Get Tab Document in following way

nsCOMPtr<nsIDOMDocument> tabdoc;
rv = webNav->GetDocument(getter_AddRefs(tabdoc));

2. TabSelect:
- I check 'selected' attribute of tab element to get the selected
tab and follow above steps.

But I don't know How to identify tab in case of TabMove & TabClose?

Please let me know, Am I following right steps to get Tab Document?

Best Regards,
Vaibhav.

Loading...