Re: Identifying Tab in OnStateChange C++

Vaibhav <[email protected]> Thu, 22 Apr 2010 06:07:59 -0700 (PDT)
Newsgroups gmane.comp.mozilla.devel.dom
Organization http://groups.google.com
Message-ID <[email protected]>
On Apr 21, 7:19 am, Jens Sorensen <[email protected]> wrote:
> 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
>
>
>
> On Tue, Apr 20, 2010 at 3:04 AM, Vaibhav <[email protected]> wrote:
> > 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...
>
> 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.