浏览器扩展系列————异步可插入协议(pluggable protocol)的实现

      IE中有很多我们比较熟悉的协议,如http,https,mailto,ftp等。当然你也可以实现自己定义的协议,稍微谈一下这里所说的协议,从我的理解来说这里的协议只有当你的网页引用某个资源时才会调用,而不是随便在某个属性的值前面加上某个协议的名称就可以了。常见的协议调用如img的src属性中,很多元素style中的background-image属性中,还有a标签的href属性中。

       言归正传,前面说到的实现自定义协议就用到了一种IE下异步可插入协议的技术。

       从分类上来说,这种异步可插入协议的技术还分为两种:

  • 永久的异步可插入协议,就像http,https,mailto这种不论在ie中或是其它用到浏览器控件中使用。
  • 临时的异步可插入协议,只能用在某个进程内,用完可以擦除。

 

     更详细介绍异步可插入协议的资源有http://www.cppblog.com/bigsml/archive/2008/03/23/45145.html

     因为网上介绍永久的异步可插入协议的资源还很多,如codeproject上的:

http://www.cppblog.com/bigsml/archive/2008/03/23/45145.html
http://www.codeproject.com/KB/aspnet/AspxProtocol.aspx

    这篇就主要谈谈如何实现临时的异步可插入协议的方法。

 

下面谈下具体的实现。

在本实现中主要用到了下面这几个接口:

  • IInternetProtocol
  • IInternetProtocolRoot
  • IInternetSession
  • IInternetProtocolInfo

     

IInternetProtocol接口

它有四个方法:

LockRequest 

Locks the requested resource so that the IInternetProtocolRoot::Terminate method can be called, and the remaining data can be read.

Read 

Reads data that the pluggable protocol handler gets.  

Seek 

Moves the current seek offset. 

UnlockRequest 

Frees any resources associated with a lock.

主要用于下载资源,将处理后的资源传递给IE进行显示。

 

IInternetProtocolRoot接口

Abort 

Cancels an operation that is in progress.  

Continue 

Enables the pluggable protocol handler to continue processing data on the apartment thread.  

Resume 

Not currently implemented.  

Start 

Starts the operation.

Suspend 

Not implemented. 

Terminate 

Releases the resources used by the pluggable protocol handler.  

主要用于解析资源,准备待下载的资源。

 

IInternetSession接口

它包括9个方法,根据需要我们只用到了下面两个方法:

RegisterNameSpace

Registers a temporary pluggable namespace handler on the current process.

UnregisterNameSpace 

Unregisters a temporary pluggable namespace handler. 

实现临时可插入协议的注册和取消。

 

IInternetProtocolInfo接口

它包括4个方法。

CombineUrl 

Combines a base URL and relative URL into a full URL.  

CompareUrl 

Compares two URLs and determines if they are equal.

ParseUrl 

Parses a URL.  

QueryInfo 

Gets information related to the specified URL.  

主要提供了对于Url的处理。

 

此外,在构造IInternetSession的时候还用到了一个外部方法:

[DllImport("urlmon.dll")]

private static extern void CoInternetGetSession(int sessionMode,

out IInternetSession session, int reserved);

 

预备的知识介绍完,下面就是具体实现了。

一般方法是在一个类中实现IInternetProtocol,IInternetProtocolRoot,IInternetProtocolInfo三个接口,然后通过IInternetSession接口的RegisterNameSpace方法来注册这个自定义协议,用完这后再调用UnregisterNameSpace方法来注销这个自定义协议。

关于IE和IInternetProtocol,IInternetProtocolRoot,IInternetProtocolInfo三个接口的调用流程可以参考msdn上的介绍,中文版的翻译可以参考:

http://www.cnblogs.com/volnet/archive/2008/03/28/About_Asynchronous_Pluggable_Protocols.html

 

首先通过CoInternetGetSession方法得到一个IInternetSession对象,然后注册自定义的协议:

IInternetSession session;

CoInternetGetSession(0, out session, 0);

Guid guid = new Guid("79EAC9E4-BAF9-11CE-8C82-00AA004BA90B");

session.RegisterNameSpace(new ClassFactory(), ref guid, ProcotolName, 0, null, 0);

在注册的时候要传入一个实现了IClassFactory接口的对象,下面是对次接口的实现:

// Interface IClassFactory is here to provide a C# definition of the

// COM IClassFactory interface.

[

ComImport, // This interface originated from COM.

ComVisible(true), // It is not hard to imagine that this interface must not be exposed to COM.

InterfaceType(ComInterfaceType.InterfaceIsIUnknown), // Indicate that this interface is not IDispatch-based.

Guid("00000001-0000-0000-C000-000000000046") // This GUID is the actual GUID of IClassFactory.

]

public interface IClassFactory

{

void CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject);

}

 

[ComVisible(true)]

public class ClassFactory : IClassFactory

{

#region IClassFactory Implementations

public void CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject)

{

ppvObject = Marshal.GetComInterfaceForObject(new MyImageProtocol(), typeof(IInternetProtocolInfo));

}

#endregion

}

 

一下至于IInternetProtocol,IInternetProtocolRoot,IInternetProtocolInfo三个接口实现,大家可以参考上面提到的http://www.cnblogs.com/volnet/archive/2008/03/28/About_Asynchronous_Pluggable_Protocols.html这篇文章。不过要注意的就是这个实现的第二个协议似乎有bug,在实验一次后,可能将IE搞崩溃了,所以实验时要谨慎,不行就用regasm /u命令将dll注销了。

posted on 2009-03-28 18:42  chinese_submarine  阅读(4990)  评论(4编辑  收藏  举报