Re: Identifying Tab in OnStateChange C++

Vaibhav <[email protected]> Tue, 20 Apr 2010 03:04:02 -0700 (PDT)
Newsgroups gmane.comp.mozilla.devel.dom
Organization http://groups.google.com
Message-ID <[email protected]>
On Apr 20, 2:41 pm, Vaibhav <[email protected]> wrote:
> On Apr 19, 6:13 pm, Vaibhav <[email protected]> wrote:
>
>
>
>
>
> > 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.
>
> 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

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.