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.