原文:浏览器扩展系列————异步可插入协议(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注销了。

浏览器扩展系列————异步可插入协议(pluggable protocol)的实现的更多相关文章

  1. 浏览器扩展系列————在WPF中定制WebBrowser快捷菜单

    原文:浏览器扩展系列----在WPF中定制WebBrowser快捷菜单 关于如何定制菜单可以参考codeproject上的这篇文章:http://www.codeproject.com/KB/book ...

  2. 浏览器扩展系列————给MSTHML添加内置脚本对象【包括自定义事件】

    原文:浏览器扩展系列----给MSTHML添加内置脚本对象[包括自定义事件] 使用场合: 在程序中使用WebBrowser或相关的控件如:axWebBrowser等.打开本地的html文件时,可以在h ...

  3. Chrome浏览器扩展开发系列之十四

    Chrome浏览器扩展开发系列之十四:本地消息机制Native messaging 时间:2015-10-08 16:17:59      阅读:1361      评论:0      收藏:0    ...

  4. Chrome浏览器扩展开发系列之十四:本地消息机制Native messagin

    Chrome浏览器扩展开发系列之十四:本地消息机制Native messaging 2016-11-24 09:36 114人阅读 评论(0) 收藏 举报  分类: PPAPI(27)  通过将浏览器 ...

  5. Chrome浏览器扩展开发系列之十六:扩展中可用的Chrome浏览器API

    除了Chrome浏览器支持的chrome.* API之外,Chrome浏览器扩展还可以使用Chrome浏览器为Web页面或Chrome app提供的APIs.对于Chrome浏览器2支持的API,还可 ...

  6. Chrome浏览器扩展开发系列之十四:本地消息机制Native messaging

    通过将浏览器所在客户端的本地应用注册为Chrome浏览器扩展的“本地消息主机(native messaging host)”,Chrome浏览器扩展还可以与客户端本地应用之间收发消息. 客户端的本地应 ...

  7. Chrome浏览器扩展开发系列之十九:扩展开发示例

    翻译总结了这么多的官网内容,下面以一款博主开发的“沪深股票价格变化实时追踪提醒”软件为例,介绍Chrome浏览器扩展程序的开发,开发环境为Eclipse IDE+Chrome Browser. “沪深 ...

  8. Chrome浏览器扩展开发系列之十八:扩展的软件国际化chrome.i18n API

    i18n是internationalization 的简写,这里将讨论软件国际化的问题.熟悉软件国际化的朋友应该知道,软件国际化要求,页面中所有用户可见的字符串都必须置于资源属性文件中.资源属性文件中 ...

  9. Chrome浏览器扩展开发系列之十七:扩展中可用的chrome.events API

    chrome.events中定义了一些常见的事件类型,可以供Chrome浏览器扩展程序发出对应的事件对象. 对于关注的事件,首先要通过addListener()在对应的事件上注册监听器,示例如下: c ...

随机推荐

  1. 创建内向交货单 BBP_INB_DELIVERY_CREATE

    DATA:DEL_HEADER TYPE BBP_INBD_L. DATA:DEL_TAB TYPE TABLE OF BBP_INBD_D WITH HEADER LINE. DATA:DEL_RE ...

  2. [three.js] 地图不能解决重复的问题 Solving with Texture RepeatWrapping Fail Issue

    有些事情,如果你正在寻找侯,怎么也找不到. 有的东西,不经意间,到处: 我认为这是生活中常有的事. 然而,在互联网的浩瀚大海,这同样适用. 正常的一小会儿的积累, 投入少, 积累, 洋大海, 载起一帆 ...

  3. Http与协议TCP协议简单易懂

    于C#编写代码,很多时候会遇到Http协议或TCP合约,这里做一个简单的了解. TCP对应于该传送层协议,和HTTP对应于应用层协议,从本质上讲,两者是没有可比性.Http该协议是基于TCP之上的,当 ...

  4. mouseover与mouseenter与mousemove差额mouseout与mouseleave差额

    <1> HTML <html> <head> <title></title> </head> <body> < ...

  5. mybatis以序列周期,同样处理的这个问题的价值

    原因猜测缓存,由于代码是肯定没问题,但无论怎么查都一样值 <select id="querySeq" resultType="java.lang.Long" ...

  6. 引用类型之object类型

    object类型有两种创建方法,第一种是直接创建法: var person=new Object(); person.name = "Nicholas"; person.age = ...

  7. OSChina 的URL类的源代码重写过程

    此代码是 oschina 到手柄形状像 http://www.oschina.net/p/tomcat 这种URL 此类已经废弃,改用 http://www.oschina.net/code/snip ...

  8. SQL开发中容易忽视的一些小地方(六)

    原文:SQL开发中容易忽视的一些小地方(六) 本文主旨:条件列上的索引对数据库delete操作的影响. 事由:今天在博客园北京俱乐部MSN群中和网友讨论了关于索引对delete的影响问题,事后感觉非常 ...

  9. 由Java代码运行shell命令/脚本

    JDK有两种方法自带通Runtime.getRuntime().exec()和ProcessBuilder课上做, 后者是JDK1.5引进后,,政府还提出要放弃使用Runtime顺便做.现的时候就是採 ...

  10. JPA实体继承映射

    注意:据说,在本文所指的实体是@Entity注解的类. JPA在对象 - 关系映射通常情况下一个实体对应表,不管是什么这两个实体之间的关系.假设两个实体之间的继承关系.那么它是如何映射? JPA实体支 ...