Re: Identifying Tab in OnStateChange C++

Vaibhav <[email protected]> Tue, 20 Apr 2010 02:41:35 -0700 (PDT)
Newsgroups gmane.comp.mozilla.devel.dom
Organization http://groups.google.com
Message-ID <f12ce38b-e8ab-4ce4-89da-1d2a3d727c88@x42g2000vba.googlegroups.com>
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