Re: Identifying Tab in OnStateChange C++
Jens Sorensen <[email protected]> Mon, 26 Apr 2010 21:32:21 -0700
| Newsgroups | gmane.comp.mozilla.devel.dom |
|---|---|
| Message-ID | <[email protected]> |
You are welcome, let me know if you need to know how to get to the actual document from the TabXXX event.. Thanks Jens Sorensen On Mon, Apr 26, 2010 at 8:52 PM, Vaibhav <[email protected]> wrote: > 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. > _______________________________________________ > dev-tech-dom mailing list > [email protected] > https://lists.mozilla.org/listinfo/dev-tech-dom >