原文:浏览器扩展系列————异步可插入协议(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. webstorm创建nodejs + express + jade 的web 项目

    webstorm创建nodejs + express + jade 的web 项目 前简单了解过nodejs,觉得用nodejs来做个网站也太麻烦了,要自己拼html的字符串返回,这能做网站嘛? 最近 ...

  2. 新手安装使用codeblocks

    很多第一次使用codeblocks的新手总会遇到很多的问题,首先作为一名新手应该下一个完整版的codeblocks,下载地址链接: http://pan.baidu.com/s/1dDxKeD7 密码 ...

  3. Java设计模式(三)-修饰模式

    我们都知道.能够使用两种方式给一个类或者对象加入行为. 一是使用继承.继承是给一个类加入行为的比較有效的途径.通过使用继承,能够使得子类在拥有自身方法的同一时候,还能够拥有父类的方法.可是使用继承是静 ...

  4. YUV摘要格式

    始终保持视频数据YUV联系,因为基于其产品的组织不同的公司格不同的类型定义,派生出多种不同YUV格公式. 大体,YUV从在点的形式的像素组织中,有两个:1.planer状态.2.packet状态. p ...

  5. Java线(一个):线程安全的和不安全

    当我们看JDK API什么时候,总是找一些类描述说:,线程安全或线程安全,例如StringBuilder在,么一句,"将StringBuilder 的实例用于多个线程是不安全的.假设须要这种 ...

  6. 终端查询数据库sqlite(创建你自己,或者是coredata创建)那里的东西

    首先需要知道数据库的路径,coredata一般都是在沙箱中创建Documents目录的.虽然他建立了自己看, sqlite3 #数据库路径#        //进入数据库 .tables  //查看数 ...

  7. 相关Python分割操作

    刚论坛python文本 http://bbs.byr.cn/#!article/Python/1693 攻克了一个关于python分片的问题. 问题: uesrList = ['1','2','3', ...

  8. HDU 1596 find the safest road (最短路)

    find the safest road Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  9. lua 怎样输出树状结构的table?

    为了让游戏前端数据输出更加条理,做了一个简单树状结构来打印数据. ccmlog.lua local function __tostring(value, indent, vmap) local str ...

  10. 如何安装一个优秀的BUG管理平台(转)

    前言 就BUG管理而言,国内的禅道做得很不错,而且持续有更新.我们来看看如何从头到尾安装禅道,各位要注意的是,不是文章深或者浅,而是文章如何在遇到问题的时候,从什么途径和用什么方法解决问题的.现在发觉 ...