Re: Identifying Tab in OnStateChange C++
Vaibhav <[email protected]> Mon, 26 Apr 2010 20:52:04 -0700 (PDT)
| Newsgroups | gmane.comp.mozilla.devel.dom |
|---|---|
| Organization | http://groups.google.com |
| Message-ID | <e5711426-49f1-4cb1-8757-0773cd5e507d@v12g2000prb.googlegroups.com> |
On Apr 22, 6:07 pm, Vaibhav <[email protected]> wrote: > 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. Hi, Answer to above question is at: http://groups.google.com/group/mozilla.dev.tech.dom/browse_thread/thread/3a4cbe436f4cf22b# Vaibhav.