现在的位置: 首页 > 综合 > 正文

When IHTMLWindow2::get_document returns E_ACCESSDENIED

2013年10月29日 ⁄ 综合 ⁄ 共 2671字 ⁄ 字号 评论关闭
 

When IHTMLWindow2::get_document returns E_ACCESSDENIED

Internet Explorer extensions usually needs to access HTML elements. When extensions are initialized they get a IWebBrowser2
pointer representing the browser. Starting with this pointer one can
get any HTML element in the web page but to do that we need to browse a
hierarchy of frames first. The simplest web pages only have one frame
and one document. Web pages containing <frame> or <iframe> have a hierarchy of frames, each frame having its own document.

Here are the objects involved and the corresponding interfaces:

browser      - IWebBrowser2
frame/iframe - IHTMLWindow2
document - IHTMLDocument2
element - IHTMLElement

The list bellow shows what method to call to get one object from another:

browser      -> document        IWebBrowser2::get_Document
document -> frame IHTMLDocument2::get_parentWindow
frame -> document IHTMLWindow2::get_document
frame -> parent frame IHTMLWindow2::get_parent
frame -> children frames IHTMLWindow2::get_frames

A normal call chain to get a HTML element is:

browser -> document -> frame -> child frame -> ... -> child frame -> document -> element

This
will work almost all the time. The problems arise when different frames
contain documents loaded from different internet domains. In this case IHTMLWindow2::get_document returns E_ACCESSDENIED when trying to get the document from the frame object. I think this happens to prevent cross frame scripting atacks.

Here is HtmlWindowToHtmlDocument function I wrote to be used instead IHTMLWindow2::get_document to bypass the restriction:



// Converts a IHTMLWindow2 object to a IHTMLDocument2. Returns NULL in case of failure.
// It takes into account accessing the DOM across frames loaded from different domains.

CComQIPtr<IHTMLDocument2> HtmlWindowToHtmlDocument(CComQIPtr<IHTMLWindow2> spWindow)
{
ATLASSERT(spWindow != NULL);

CComQIPtr<IHTMLDocument2> spDocument;
HRESULT hRes = spWindow->get_document(&spDocument);

if ((S_OK == hRes) && (spDocument != NULL))
{
// The html document was properly retrieved.
return spDocument;
}

// hRes could be E_ACCESSDENIED that means a security restriction that
// prevents scripting across frames that loads documents from different internet domains.

CComQIPtr<IWebBrowser2> spBrws = HtmlWindowToHtmlWebBrowser(spWindow);
if (spBrws == NULL)
{
return CComQIPtr<IHTMLDocument2>();
}

// Get the document object from the IWebBrowser2 object.
CComQIPtr<IDispatch> spDisp;
hRes = spBrws->get_Document(&spDisp);
spDocument = spDisp;

return spDocument;
}


// Converts a IHTMLWindow2 object to a IWebBrowser2. Returns NULL in case of failure.
CComQIPtr<IWebBrowser2> HtmlWindowToHtmlWebBrowser(CComQIPtr<IHTMLWindow2> spWindow)
{
ATLASSERT(spWindow != NULL);

CComQIPtr<IServiceProvider> spServiceProvider = spWindow;
if (spServiceProvider == NULL)
{
return CComQIPtr<IWebBrowser2>();
}

CComQIPtr<IWebBrowser2> spWebBrws;
HRESULT hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws);
if (hRes != S_OK)
{
return CComQIPtr<IWebBrowser2>();
}

return spWebBrws;
}

抱歉!评论已关闭.