Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Identify calls to Pluggable Namespace Handler from multiple browser controls

259 views
Skip to first unread message

Christoph Wienands

unread,
Nov 21, 2003, 3:25:38 PM11/21/03
to
Hello everybody,

I'm still working on a C# application that hosts multiple browser windows.
These browser instances are supposed to work 100% isolated, meaning that
e.g. they are not allowed to share cookies (for supporting multiple sessions
on a server). In a prototype I have built a multiple-process application,
where the processes use COM+ to communicate with each other.

Currently I'm trying to put everything together into one application since
.Net processes are way too resource-hungry. I think I have pretty much my
basic toolkit together as there were:
-Implementation of SHDocVw.DWebBrowserEvents2 to intercept Beforenavigate2,
DocumentComplete, etc.
-Implementation of IDocHostUIHandler to control IE behaviour.
-Implementation of IInternetProtocol to intercept HTTP Internet access (via
RegisterNameSpace).

My idea is to use RegisterName and my IInternetProtocol to intercept all
HTTP requests and perform them myself with help of the HttpWebRequest class.
Actually I have already implemented a small framework around this
HttpWebRequest class to keep track of session cookies, read the pure HTML,
etc. The multiple WebBrowser controls would actually never get to see any
cookies since they are caught beforehand.

The problem however is that I have no clue how I can assign intercepted HTTP
requests from a webbrowser control to the correct HttpWebSession to create a
request instead (this is my framework class around HttpWebRequest). To give
a better understanding, here is the sequence of events:

Initialization:
-Register helper classes to intercept Beforenavigate2, DocumentComplete and
control IE behaviour (do not allow pop-ups, etc.)
-Create a ClassFactory for my own IInternetProtocol implementation
-Get the IInternetSession object through CoInternetGetSession()
-Register my ClassFactory with IInternetSession for the HTTP protocol
through RegisterNameSpace

Navigation event to be intercepted:
-ClassFactory.CreateInstance gets called to return a IInternetProtocol
object (my own implementation)
-IInternetProtocol.Start gets called with URL, IInternetProtocolSink and
IInternetBindInfo

At this point I'm lost. It seems, for every HTTP request
ClassFactory.CreateInstance is called. I need to tell from which WebBrowser
control the request came. I thought to identify the Session by the URL that
gets called. However, it can happen that two sessions access the same URL at
the same time and I still need to be able to differentiate (think of
commonly used files like images or Include files).

I appreciate any ideas in that matter. Also, if you see an easier way to do
it, I'm up for that because I have this slight
from-the-back-through-the-chest-into-the-eye feeling ;-)

Thank, Christoph


Igor Tandetnik

unread,
Nov 21, 2003, 4:36:40 PM11/21/03
to
"Christoph Wienands" <cwie...@sswhiteburs.com> wrote in message
news:%23TPSj2G...@TK2MSFTNGP11.phx.gbl...

> The problem however is that I have no clue how I can assign
intercepted HTTP
> requests from a webbrowser control to the correct HttpWebSession to
create a
> request instead (this is my framework class around HttpWebRequest).

I'd try to do the following. Handle BeforeNavigate2 event, cancel the
navigation, reissue it with the custom header that gives the browser ID
or something. Your APP would inspect this header and proceed
accordingly.

Another idea. There's one object that is tagging along all the way from
WebBrowser host to the APP - a security manager (see
IInternetSecurityManager). You implement IServiceProvider on the client
site of WebBrowser control (before you ask, I have no clue how to do it
in .NET), and implement QueryService(IID_IInternetSecurityManager) to
return your implementation of IInternetSecurityManager. Your APP queries
for IServiceProvider on IInternetProtocolSink interface and calls
QueryService to obtain IInternetSecurityManager. Note that you don't
actually get the interface to your object, but to some object that would
eventually delegate all method calls to your object.

So, your implementation of IInternetSecurityManager would return
INET_E_DEFAULT_ACTION for all method calls except one -
QueryCustomPolicy. Just generate a new GUID for your custom policy ID
and return the browser session ID or something when QueryCustomPolicy is
called with this GUID. Otherwise, just return INET_E_DEFAULT_ACTION
again.
--
With best wishes,
Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken


Christoph Wienands

unread,
Nov 21, 2003, 5:17:12 PM11/21/03
to
Hi Igor,

> I'd try to do the following. Handle BeforeNavigate2 event, cancel the
> navigation, reissue it with the custom header that gives the browser ID
> or something. Your APP would inspect this header and proceed
> accordingly.

Header sounds like a good idea :-)

> Another idea. There's one object that is tagging along all the way from
> WebBrowser host to the APP - a security manager (see
> IInternetSecurityManager). You implement IServiceProvider on the client
> site of WebBrowser control (before you ask, I have no clue how to do it
> in .NET), and implement QueryService(IID_IInternetSecurityManager) to
> return your implementation of IInternetSecurityManager. Your APP queries
> for IServiceProvider on IInternetProtocolSink interface and calls
> QueryService to obtain IInternetSecurityManager. Note that you don't
> actually get the interface to your object, but to some object that would
> eventually delegate all method calls to your object.
>
> So, your implementation of IInternetSecurityManager would return
> INET_E_DEFAULT_ACTION for all method calls except one -
> QueryCustomPolicy. Just generate a new GUID for your custom policy ID
> and return the browser session ID or something when QueryCustomPolicy is
> called with this GUID. Otherwise, just return INET_E_DEFAULT_ACTION
> again.

Wow, sounds like an adventurous Sunday afternoon ;-) Thanks for the ideas.

Christoph


Christoph Wienands

unread,
Nov 23, 2003, 11:15:47 PM11/23/03
to
Hello Igor,

> I'd try to do the following. Handle BeforeNavigate2 event, cancel the
> navigation, reissue it with the custom header that gives the browser ID
> or something. Your APP would inspect this header and proceed
> accordingly.
>
> Another idea. There's one object that is tagging along all the way from
> WebBrowser host to the APP - a security manager (see
> IInternetSecurityManager). You implement IServiceProvider on the client
> site of WebBrowser control (before you ask, I have no clue how to do it
> in .NET), and implement QueryService(IID_IInternetSecurityManager) to
> return your implementation of IInternetSecurityManager. Your APP queries
> for IServiceProvider on IInternetProtocolSink interface and calls
> QueryService to obtain IInternetSecurityManager. Note that you don't
> actually get the interface to your object, but to some object that would
> eventually delegate all method calls to your object.

I gaveyour ideas a try and actually the first one worked out perfectly (the
second one looked like a bit too much hassle ;-)

I cancel the navigation and reissue it providing a SessionID as header for
the request. The part in IInternetProtocol was not as trivial as I first
thought. I can not retrieve the header information from IInternetBindInfo
(see MSDN, not supported).

Rather, I had to query the protocol sink for the IServiceProvider interface.
A call to QueryService(IID_IHttpNegotiate, IID_IHttpNegotiate) returns me a
IHttpNegotiate object. Finally calling the BeginningTransaction on that
gives me the custom header with the SessionID information.

Thanks a lot,

Christoph


Christoph Wienands

unread,
Jan 10, 2004, 1:44:49 PM1/10/04
to
Just a quick update on my old problem (in case someone runs into the same
trouble):

At one point it turned out that using the cancel-and-resubmit method was not
sufficent. I got into contact with MS and they sent me a straightforward
solution. Using the code from below you are able to get the IE's window
handle.

private int GetHwnd(IInternetProtocolSink pOIProtSink)
{
Guid IID_IWindowForBindingUI = new
Guid("79eac9d5-bafa-11ce-8c82-00aa004ba90b");
Guid IID_IHttpSecurity = new
Guid("79eac9d7-bafa-11ce-8c82-00aa004ba90b");

IServiceProvider objServiceProvider;
objServiceProvider = (IServiceProvider) pOIProtSink;

IWindowForBindingUI objWindowForBindingUI = (IWindowForBindingUI)
objServiceProvider.QueryService(ref IID_IWindowForBindingUI, ref
IID_IWindowForBindingUI);

int intHandle = 0;
objWindowForBindingUI.GetWindow(ref IID_IHttpSecurity, out intHandle);
return intHandle;
}
}

Christoph


0 new messages