Using Navigate2 to add Custom HTTP Header

D

Dean Hallman

Hello,

I am developing a BHO that should add a custom HTTP header on a
specific domain only. Don't want the header globally, otherwise I
could just add a registry key.

So, on BEFORENAVIGATE2, I am canceling the current navigation and
renavigating with the new custom header using Navigate2. This usually
works fine, but in some cases (particularly when selecting a link that
starts a new window), the Navigate2 call fails.

Running out of ideas, so any help would be greatly appreciated!

Here is my current code to add custom headers (yes, it's in C++/ATL but
a .NET/C# solution would be just as helpful, thanks.)

Note, this code fails with Navigate2 returning HRESULT 0x80004005.

Any ideas?

---

STDMETHODIMP CBho::Invoke(DISPID dispidMember, REFIID riid, LCID lcid,
WORD wFlags,
DISPPARAMS* pDispParams, VARIANT* pvarResult,
EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
if (!pDispParams)
return E_INVALIDARG;

switch (dispidMember)
{

case DISPID_BEFORENAVIGATE2:
{
CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> WebBrowser;
WebBrowser = pDispParams->rgvarg[6].pdispVal;
CW2CT pszUrl(pDispParams->rgvarg[5].pvarVal->bstrVal);
CStdString strUrl( (LPCTSTR)pszUrl );

// This is an "action cancelled" page. After the renav, we
sometimes
// get a brief action cancelled page showing up before the final
// renavigated page. Just block it so it doesn't appear at all.
if (strUrl.Right(12).CompareNoCase(_T("navcancl.htm")) == 0 ) {
WebBrowser->Stop(); // Sometimes Stop() re-enters here, other
times it doesn't
*V_BOOLREF(&pDispParams->rgvarg[0]) = VARIANT_TRUE;
break;
}

if (pDispParams->rgvarg[1].vt != (VT_BYREF|VT_VARIANT)) {
break;
}

// Is this a xyzinc.com domain page? If so, add our HTTP header.
// Note: this block adds "xyzinc-Header:" as a header to outgoing
// GET/POST requests iff "xyzinc.com" is the target domain
if (WebBrowser && m_spWebBrowser2 == WebBrowser) {

CUrl url;
if (url.CrackUrl( (LPCTSTR)pszUrl ) == FALSE) {
break;
}

CStdString strHostName ( url.GetHostName() );

// Is this an "xyzinc.com" url
int lenxyzinc = ( strHostName.GetLength() > 11 ) ? 11 :
strHostName.GetLength();
if (strHostName.Right(lenxyzinc).CompareNoCase(
_T(".xyzinc.com") ) != 0)
break; // not our domain - don't add header

// Dig out the aleady specifed headers. Note, this is only
// new headers added specifically by a "Navigate2()" call.
// The standard headers from the registry are not included.
CComVariant varHEADERS(*pDispParams->rgvarg[1].pvarVal);
varHEADERS.ChangeType(VT_BSTR);
CW2CT pszHeaders( varHEADERS.bstrVal );


// This call is recursive, so we'll get back here again after
// the header is added. So, check if we already added the
header
// and abort everything if this is the second call.
if ( strlen(pszHeaders) == 0 || strstr(pszHeaders,
"xyzinc-Header:") == NULL ) {

// Now we know this is a page to add "xyzinc-Header:" to and
// that this is the first of two calls (recursive).
// So, the way to do it is (1) stop the current navigate.
// (2) reissue a new navigate keeping all params the same
// except adding our "xyzinc-Header:" header.

// Stop the original navigation immediately so it does not
// have enough time to show. Canceling a nav requires
// a "Stop()" call plus returning "TRUE" in the cancel param.
WebBrowser->Stop();
ATLASSERT(V_VT(&pDispParams->rgvarg[0]) == (VT_BOOL |
VT_BYREF)); // Just in case
*V_BOOLREF(&pDispParams->rgvarg[0]) = VARIANT_TRUE;

// Now, specify our header and renav. But first, make sure
// we add our header to any existing headers passed in.
CComVariant vtHeaders;
CStdString strHeader;
strHeader.Format("%sxyzinc-Header: %s\r\n",
(LPCTSTR)pszHeaders, (LPCTSTR)m_pszMyHeader);
vtHeaders = strHeader.c_str();

// Note PostData argument passes pvarVal->pvarVal.
Otherwise,
// postdata is dropped and forms loose the data during a
post.
HRESULT hr = WebBrowser->Navigate2( &pDispParams->rgvarg[5],
&pDispParams->rgvarg[4], &pDispParams->rgvarg[3],
(pDispParams->rgvarg[2].pvarVal)->pvarVal, &vtHeaders );
if (FAILED(hr)) {
LOGFAILURE("Navigate2() failed HRESULT=%x", hr);
// !!!!!! THIS FAILS
// with HRESULT=0x80004005
}
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top