Back to index

lightning-sunbird  0.9+nobinonly
nsDocAccessibleWrap.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2003
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Original Author: Aaron Leventhal (aaronl@netscape.com)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsDocAccessibleWrap.h"
00040 #include "ISimpleDOMDocument_i.c"
00041 #include "nsIAccessibilityService.h"
00042 #include "nsIAccessibleEvent.h"
00043 #include "nsIDocShell.h"
00044 #include "nsIDocShellTreeNode.h"
00045 #include "nsIDOMDocumentTraversal.h"
00046 #include "nsIDOMNodeFilter.h"
00047 #include "nsIDOMTreeWalker.h"
00048 #include "nsIFrame.h"
00049 #include "nsIInterfaceRequestorUtils.h"
00050 #include "nsIPresShell.h"
00051 #include "nsISelectionController.h"
00052 #include "nsIServiceManager.h"
00053 #include "nsIURI.h"
00054 #include "nsIViewManager.h"
00055 #include "nsIWebNavigation.h"
00056 #include "nsIWidget.h"
00057 
00058 /* For documentation of the accessibility architecture, 
00059  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
00060  */
00061 
00062 //----- nsDocAccessibleWrap -----
00063 
00064 nsDocAccessibleWrap::nsDocAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell): 
00065   nsDocAccessible(aDOMNode, aShell), mWasAnchor(PR_FALSE)
00066 {
00067 }
00068 
00069 nsDocAccessibleWrap::~nsDocAccessibleWrap()
00070 {
00071 }
00072 
00073 //-----------------------------------------------------
00074 // IUnknown interface methods - see iunknown.h for documentation
00075 //-----------------------------------------------------
00076 STDMETHODIMP_(ULONG) nsDocAccessibleWrap::AddRef()
00077 {
00078   return nsAccessNode::AddRef();
00079 }
00080 
00081 STDMETHODIMP_(ULONG) nsDocAccessibleWrap::Release()
00082 {
00083   return nsAccessNode::Release();
00084 }
00085 
00086 // Microsoft COM QueryInterface
00087 STDMETHODIMP nsDocAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
00088 {
00089   *ppv = NULL;
00090 
00091   if (IID_ISimpleDOMDocument == iid)
00092     *ppv = NS_STATIC_CAST(ISimpleDOMDocument*, this);
00093 
00094   if (NULL == *ppv)
00095     return nsAccessibleWrap::QueryInterface(iid, ppv);
00096     
00097   (NS_REINTERPRET_CAST(IUnknown*, *ppv))->AddRef();
00098   return S_OK;
00099 }
00100 
00101 void nsDocAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild, nsIAccessible **aXPAccessible)
00102 {
00103   *aXPAccessible = nsnull;
00104   if (!mWeakShell)
00105     return; // This document has been shut down
00106 
00107   if (aVarChild.lVal < 0) {
00108     // Get from hash table
00109     void *uniqueID = (void*)(-aVarChild.lVal);  // Convert child ID back to unique ID
00110     nsCOMPtr<nsIAccessNode> accessNode;
00111     GetCachedAccessNode(uniqueID, getter_AddRefs(accessNode));
00112     nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(accessNode));
00113     NS_IF_ADDREF(*aXPAccessible = accessible);
00114     return;
00115   }
00116 
00117   nsDocAccessible::GetXPAccessibleFor(aVarChild, aXPAccessible);
00118 }
00119 
00120 STDMETHODIMP nsDocAccessibleWrap::get_accChild( 
00121       /* [in] */ VARIANT varChild,
00122       /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild)
00123 {
00124   *ppdispChild = NULL;
00125 
00126   if (varChild.vt == VT_I4 && varChild.lVal < 0) {
00127     // AccessibleObjectFromEvent() being called
00128     // that's why the lVal < 0
00129     nsCOMPtr<nsIAccessible> xpAccessible;
00130     GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
00131     if (xpAccessible) {
00132       IAccessible *msaaAccessible;
00133       xpAccessible->GetNativeInterface((void**)&msaaAccessible);
00134       *ppdispChild = NS_STATIC_CAST(IDispatch*, msaaAccessible);
00135       return S_OK;
00136     }
00137     else if (mDocument) {
00138       // If child ID from event can't be found in this window, ask parent.
00139       // This is especially relevant for times when a xul menu item
00140       // has focus, but the system thinks the content window has focus.
00141       nsIDocument* parentDoc = mDocument->GetParentDocument();
00142       if (parentDoc) {
00143         nsIPresShell *parentShell = parentDoc->GetShellAt(0);
00144         nsCOMPtr<nsIWeakReference> weakParentShell(do_GetWeakReference(parentShell));
00145         if (weakParentShell) {
00146           nsCOMPtr<nsIAccessibleDocument> parentDocAccessible = 
00147             nsAccessNode::GetDocAccessibleFor(weakParentShell);
00148           nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(parentDocAccessible));
00149           IAccessible *msaaParentDoc;
00150           if (accessible) {
00151             accessible->GetNativeInterface((void**)&msaaParentDoc);
00152             HRESULT rv = msaaParentDoc->get_accChild(varChild, ppdispChild);
00153             msaaParentDoc->Release();
00154             return rv;
00155           }
00156         }
00157       }
00158     }
00159     return E_FAIL;
00160   }
00161 
00162   // Otherwise, the normal get_accChild() will do
00163   return nsAccessibleWrap::get_accChild(varChild, ppdispChild);
00164 }
00165 
00166 NS_IMETHODIMP nsDocAccessibleWrap::Shutdown()
00167 {
00168   if (mDocLoadTimer) {
00169     mDocLoadTimer->Cancel();
00170     mDocLoadTimer = nsnull;
00171   }
00172   return nsDocAccessible::Shutdown();
00173 }
00174 
00175 NS_IMETHODIMP nsDocAccessibleWrap::FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData)
00176 {
00177 #ifdef DEBUG
00178   // Ensure that we're only firing events that we intend to
00179   PRUint32 supportedEvents[] = {
00180     nsIAccessibleEvent::EVENT_SHOW,
00181     nsIAccessibleEvent::EVENT_HIDE,
00182     nsIAccessibleEvent::EVENT_REORDER,
00183     nsIAccessibleEvent::EVENT_FOCUS,
00184     nsIAccessibleEvent::EVENT_STATE_CHANGE,
00185     nsIAccessibleEvent::EVENT_NAME_CHANGE,
00186     nsIAccessibleEvent::EVENT_DESCRIPTIONCHANGE,
00187     nsIAccessibleEvent::EVENT_VALUE_CHANGE,
00188     nsIAccessibleEvent::EVENT_SELECTION,
00189     nsIAccessibleEvent::EVENT_SELECTION_ADD,
00190     nsIAccessibleEvent::EVENT_SELECTION_REMOVE,
00191     nsIAccessibleEvent::EVENT_SELECTION_WITHIN,
00192     nsIAccessibleEvent::EVENT_ALERT,
00193     nsIAccessibleEvent::EVENT_MENUSTART,
00194     nsIAccessibleEvent::EVENT_MENUEND,
00195     nsIAccessibleEvent::EVENT_MENUPOPUPSTART,
00196     nsIAccessibleEvent::EVENT_MENUPOPUPEND,
00197     nsIAccessibleEvent::EVENT_SCROLLINGSTART,
00198     nsIAccessibleEvent::EVENT_SCROLLINGEND,
00199   };
00200 
00201   PRBool found = PR_FALSE;
00202   for (PRUint32 count = 0; count < NS_ARRAY_LENGTH(supportedEvents); count ++) {
00203     if (aEvent == supportedEvents[count]) {
00204       found = PR_TRUE;
00205       break;
00206     }
00207   }
00208   if (!found) {
00209     NS_WARNING("Event not supported!");
00210   }
00211 #endif
00212   if (!mWeakShell) {   // Means we're not active
00213     return NS_ERROR_FAILURE;
00214   }
00215 
00216   nsDocAccessible::FireToolkitEvent(aEvent, aAccessible, aData); // Fire nsIObserver message
00217 
00218 #ifdef SWALLOW_DOC_FOCUS_EVENTS
00219   // Remove this until we can figure out which focus events are coming at
00220   // the same time as native window focus events, although
00221   // perhaps 2 duplicate focus events on the window isn't really a problem
00222   if (aEvent == nsIAccessibleEvent::EVENT_FOCUS) {
00223     // Don't fire accessible focus event for documents, 
00224     // Microsoft Windows will generate those from native window focus events
00225     nsCOMPtr<nsIAccessibleDocument> accessibleDoc(do_QueryInterface(aAccessible));
00226     if (accessibleDoc)
00227       return NS_OK;
00228   }
00229 #endif
00230 
00231   PRInt32 childID, worldID = OBJID_CLIENT;
00232   PRUint32 role = ROLE_SYSTEM_TEXT; // Default value
00233 
00234   HWND hWnd = (HWND)mWnd;
00235 
00236   if (NS_SUCCEEDED(aAccessible->GetRole(&role)) && role == ROLE_SYSTEM_CARET) {
00237     childID = CHILDID_SELF;
00238     worldID = OBJID_CARET;
00239   }
00240   else {
00241     childID = GetChildIDFor(aAccessible); // get the id for the accessible
00242     if (!childID) {
00243       return NS_OK; // Can't fire an event without a child ID
00244     }
00245     if (aAccessible != this) {
00246       // See if we're in a scrollable area with its own window
00247       nsCOMPtr<nsIAccessible> accessible;
00248       if (aEvent == nsIAccessibleEvent::EVENT_HIDE) {
00249         // Don't use frame from current accessible when we're hiding that accessible
00250         aAccessible->GetParent(getter_AddRefs(accessible));
00251       }
00252       else {
00253         accessible = aAccessible;
00254       }
00255       nsCOMPtr<nsPIAccessNode> privateAccessNode =
00256         do_QueryInterface(accessible);
00257       if (privateAccessNode) {
00258         nsIFrame *frame = privateAccessNode->GetFrame();
00259         if (frame) {
00260           hWnd = (HWND)frame->GetWindow()->GetNativeData(NS_NATIVE_WINDOW); 
00261         }
00262       }
00263     }
00264   }
00265 
00266   // Gecko uses two windows for every scrollable area. One window contains
00267   // scrollbars and the child window contains only the client area.
00268   // Details of the 2 window system:
00269   // * Scrollbar window: caret drawing window & return value for WindowFromAccessibleObject()
00270   // * Client area window: text drawing window & MSAA event window
00271   NotifyWinEvent(aEvent, hWnd, worldID, childID);   // Fire MSAA event for client area window
00272 
00273   return NS_OK;
00274 }
00275 
00276 PRInt32 nsDocAccessibleWrap::GetChildIDFor(nsIAccessible* aAccessible)
00277 {
00278   // A child ID of the window is required, when we use NotifyWinEvent, so that the 3rd party application
00279   // can call back and get the IAccessible the event occured on.
00280   // We use the unique ID exposed through nsIContent::GetContentID()
00281 
00282   void *uniqueID;
00283   nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
00284   if (!accessNode) {
00285     return 0;
00286   }
00287   accessNode->GetUniqueID(&uniqueID);
00288 
00289   // Yes, this means we're only compatibible with 32 bit
00290   // MSAA is only available for 32 bit windows, so it's okay
00291   return - NS_PTR_TO_INT32(uniqueID);
00292 }
00293 
00294 already_AddRefed<nsIAccessible>
00295 nsDocAccessibleWrap::GetFirstLeafAccessible(nsIDOMNode *aStartNode)
00296 {
00297   nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
00298   nsCOMPtr<nsIAccessible> accessible;
00299   nsCOMPtr<nsIDOMTreeWalker> walker; 
00300   nsCOMPtr<nsIDOMNode> currentNode(aStartNode);
00301 
00302   while (currentNode) {
00303     accService->GetAccessibleInWeakShell(currentNode, mWeakShell, getter_AddRefs(accessible)); // AddRef'd
00304     if (accessible) {
00305       PRInt32 numChildren;
00306       accessible->GetChildCount(&numChildren);
00307       if (numChildren == 0) {
00308         nsIAccessible *leafAccessible = accessible;
00309         NS_ADDREF(leafAccessible);
00310         return leafAccessible;  // It's a leaf accessible, return it
00311       }
00312     }
00313     if (!walker) {
00314       // Instantiate walker lazily since we won't need it in 90% of the cases
00315       // where the first DOM node we're given provides an accessible
00316       nsCOMPtr<nsIDOMDocumentTraversal> trav = do_QueryInterface(mDocument);
00317       NS_ASSERTION(trav, "No DOM document traversal for document");
00318       trav->CreateTreeWalker(mDOMNode, 
00319                             nsIDOMNodeFilter::SHOW_ELEMENT | nsIDOMNodeFilter::SHOW_TEXT,
00320                             nsnull, PR_FALSE, getter_AddRefs(walker));
00321       NS_ENSURE_TRUE(walker, nsnull);
00322       walker->SetCurrentNode(currentNode);
00323     }
00324 
00325     walker->NextNode(getter_AddRefs(currentNode));
00326   }
00327 
00328   return nsnull;
00329 }
00330 
00331 NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
00332 {
00333   // Staying on the same page, jumping to a named anchor
00334   // Fire EVENT_SCROLLINGSTART on first leaf accessible -- because some
00335   // assistive technologies only cache the child numbers for leaf accessibles
00336   // the can only relate events back to their internal model if it's a leaf.
00337   // There is usually an accessible for the focus node, but if it's an empty text node
00338   // we have to move forward in the document to get one
00339   if (!mIsContentLoaded || !mDocument) {
00340     return NS_OK;
00341   }
00342   nsCOMPtr<nsISupports> container = mDocument->GetContainer();
00343   nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(container));
00344   nsCAutoString theURL;
00345   if (webNav) {
00346     nsCOMPtr<nsIURI> pURI;
00347     webNav->GetCurrentURI(getter_AddRefs(pURI));
00348     if (pURI) {
00349       pURI->GetSpec(theURL);
00350     }
00351   }
00352   const char kHash = '#';
00353   PRBool hasAnchor = PR_FALSE;
00354   PRInt32 hasPosition = theURL.FindChar(kHash);
00355   if (hasPosition > 0 && hasPosition < (PRInt32)theURL.Length() - 1) {
00356     hasAnchor = PR_TRUE;
00357   }
00358 
00359   // mWasAnchor is set when the previous URL included a named anchor.
00360   // This way we still know to fire the EVENT_SCROLLINGSTART event when we
00361   // move from a named anchor back to the top.
00362   if (!mWasAnchor && !hasAnchor) {
00363     return NS_OK;
00364   }
00365   mWasAnchor = hasAnchor;
00366 
00367   nsCOMPtr<nsIDOMNode> focusNode;
00368   if (hasAnchor) {
00369     nsCOMPtr<nsISelectionController> selCon(do_QueryReferent(mWeakShell));
00370     if (!selCon) {
00371       return NS_OK;
00372     }
00373     nsCOMPtr<nsISelection> domSel;
00374     selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
00375     if (!domSel) {
00376       return NS_OK;
00377     }
00378     domSel->GetFocusNode(getter_AddRefs(focusNode));
00379   }
00380   else {
00381     focusNode = mDOMNode; // Moved to top, so event is for 1st leaf after root
00382   }
00383 
00384   nsCOMPtr<nsIAccessible> accessible = GetFirstLeafAccessible(focusNode);
00385   nsCOMPtr<nsPIAccessible> privateAccessible = do_QueryInterface(accessible);
00386   if (privateAccessible) {
00387     privateAccessible->FireToolkitEvent(nsIAccessibleEvent::EVENT_SCROLLINGSTART,
00388                                         accessible, nsnull);
00389   }
00390   return NS_OK;
00391 }
00392 
00393 void nsDocAccessibleWrap::DocLoadCallback(nsITimer *aTimer, void *aClosure)
00394 {
00395   // Doc has finished loading, fire "load finished" event
00396   // By using short timer we can wait for MS Windows to make the window visible,
00397   // which it does asynchronously. This avoids confusing the screen reader with a
00398   // hidden window. Waiting also allows us to see of the document has focus,
00399   // which is important because we only fire doc loaded events for focused documents.
00400 
00401   nsDocAccessibleWrap *docAcc =
00402     NS_REINTERPRET_CAST(nsDocAccessibleWrap*, aClosure);
00403   if (!docAcc) {
00404     return;
00405   }
00406 
00407   // Fire doc finished event
00408   nsCOMPtr<nsIDOMNode> docDomNode;
00409   docAcc->GetDOMNode(getter_AddRefs(docDomNode));
00410   nsCOMPtr<nsIDocument> doc(do_QueryInterface(docDomNode));
00411   if (doc) {
00412     nsCOMPtr<nsISupports> container = doc->GetContainer();
00413     nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = do_QueryInterface(container);
00414     if (!docShellTreeItem) {
00415       return;
00416     }
00417     nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
00418     docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
00419     if (sameTypeRoot != docShellTreeItem) {
00420       // A frame or iframe has finished loading new content
00421       docAcc->InvalidateCacheSubtree(nsnull, nsIAccessibleEvent::EVENT_REORDER);
00422       return;
00423     }
00424 
00425     // Fire STATE_CHANGE event for doc load finish if focus is in same doc tree
00426     if (gLastFocusedNode) {
00427       nsCOMPtr<nsIDocShellTreeItem> focusedTreeItem =
00428         GetDocShellTreeItemFor(gLastFocusedNode);
00429       if (focusedTreeItem) {
00430         nsCOMPtr<nsIDocShellTreeItem> sameTypeRootOfFocus;
00431         focusedTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRootOfFocus));
00432         if (sameTypeRoot == sameTypeRootOfFocus) {
00433           docAcc->FireToolkitEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE,
00434                                   docAcc, nsnull);
00435           docAcc->FireAnchorJumpEvent();
00436         }
00437       }
00438     }
00439   }
00440 }
00441 
00442 NS_IMETHODIMP nsDocAccessibleWrap::FireDocLoadingEvent(PRBool aIsFinished)
00443 {
00444   if (!mDocument || !mWeakShell)
00445     return NS_OK;  // Document has been shut down
00446 
00447   if (mIsContentLoaded == aIsFinished) {
00448     return NS_OK;  // Already fired the event
00449   }
00450 
00451   nsDocAccessible::FireDocLoadingEvent(aIsFinished);
00452 
00453   if (aIsFinished) {
00454     // Use short timer before firing state change event for finished doc,
00455     // because the window is made visible asynchronously by Microsoft Windows
00456     if (!mDocLoadTimer) {
00457       mDocLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
00458     }
00459     if (mDocLoadTimer) {
00460       mDocLoadTimer->InitWithFuncCallback(DocLoadCallback, this, 0,
00461                                           nsITimer::TYPE_ONE_SHOT);
00462     }
00463   }
00464   else {
00465     nsCOMPtr<nsIDocShellTreeItem> treeItem = GetDocShellTreeItemFor(mDOMNode);
00466     if (!treeItem) {
00467       return NS_OK;
00468     }
00469 
00470     nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
00471     treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
00472     if (sameTypeRoot != treeItem) {
00473       return NS_OK; // We only fire MSAA doc loading events for root content frame
00474     }
00475 
00476     FireToolkitEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, this, nsnull);
00477   }
00478 
00479   return NS_OK;
00480 }
00481 
00482 STDMETHODIMP nsDocAccessibleWrap::get_URL(/* [out] */ BSTR __RPC_FAR *aURL)
00483 {
00484   *aURL = NULL;
00485   nsAutoString URL;
00486   if (NS_SUCCEEDED(GetURL(URL))) {
00487     *aURL= ::SysAllocString(URL.get());
00488     return S_OK;
00489   }
00490   return E_FAIL;
00491 }
00492 
00493 STDMETHODIMP nsDocAccessibleWrap::get_title( /* [out] */ BSTR __RPC_FAR *aTitle)
00494 {
00495   *aTitle = NULL;
00496   nsAutoString title;
00497   if (NS_SUCCEEDED(GetTitle(title))) { // getter_Copies(pszTitle)))) {
00498     *aTitle= ::SysAllocString(title.get());
00499     return S_OK;
00500   }
00501   return E_FAIL;
00502 }
00503 
00504 STDMETHODIMP nsDocAccessibleWrap::get_mimeType(/* [out] */ BSTR __RPC_FAR *aMimeType)
00505 {
00506   *aMimeType = NULL;
00507   nsAutoString mimeType;
00508   if (NS_SUCCEEDED(GetMimeType(mimeType))) {
00509     *aMimeType= ::SysAllocString(mimeType.get());
00510     return S_OK;
00511   }
00512   return E_FAIL;
00513 }
00514 
00515 STDMETHODIMP nsDocAccessibleWrap::get_docType(/* [out] */ BSTR __RPC_FAR *aDocType)
00516 {
00517   *aDocType = NULL;
00518   nsAutoString docType;
00519   if (NS_SUCCEEDED(GetDocType(docType))) {
00520     *aDocType= ::SysAllocString(docType.get());
00521     return S_OK;
00522   }
00523   return E_FAIL;
00524 }
00525 
00526 STDMETHODIMP nsDocAccessibleWrap::get_nameSpaceURIForID(/* [in] */  short aNameSpaceID,
00527   /* [out] */ BSTR __RPC_FAR *aNameSpaceURI)
00528 {
00529   *aNameSpaceURI = NULL;
00530   nsAutoString nameSpaceURI;
00531   if (NS_SUCCEEDED(GetNameSpaceURIForID(aNameSpaceID, nameSpaceURI))) {
00532     *aNameSpaceURI = ::SysAllocString(nameSpaceURI.get());
00533     return S_OK;
00534   }
00535   return E_FAIL;
00536 }
00537 
00538 STDMETHODIMP nsDocAccessibleWrap::put_alternateViewMediaTypes( /* [in] */ BSTR __RPC_FAR *commaSeparatedMediaTypes)
00539 {
00540   return E_NOTIMPL;
00541 }
00542