走进PIMShell(2)--不再使用external扩展浏览器,兼谈三种方案
2008-11-07 13:10
911 查看
方案一:external对象
经常有人用CDHtmlDialog开发纯网页的对话框。这里首先要解决的是“程序”与“网页”之间的通信问题。“程序”访问“网页”可以使用IWebBrowser2接口。“网页”访问“程序”可以在脚本中调用window.external的方法。对于“网页”而言,暂且将前者称为“被动模式”,后者称为“主动模式”。于是,“程序”在建立一个“网页”对话框时,向“网页”提供一个自定义的external对象,就解决了二者之间的通信问题了。
在简单的应用中,上述方案是有效的。但有一个约束性条件:就是“网页”中的代码都是可控的。如果“网页”允许通过iframe元素加载其他来源的子页面时,就会出现安全隐患了。因为当前网页中所有iframe中的子页面也都能访问window.external的方法。那可不可以为每一个“网页”建立一个单独的external对象呢?经测试是不行的。也就是说,“程序”内嵌的“WebBrowser控件”一次只能设置一个external对象,为当前“网页”和其下所有的“子页面”服务。而且,在external对象内部也无法判断此次调用的来源。
方案二:直接提供类似window的全局对象
因为“程序”可以使用IWebBrowser2接口访问“网页”,那么我们可以直接创建一个自定义对象,并将其设为“网页”的全局对象,就像window一样。下面演示如何为“网页”提供一个page对象。
//IWebBrowser2接口是已知的
CComPtr<IWebBrowser2> m_pWebBrowser2;
//得到document
CComPtr<IDispatch> pDocDisp;
m_pWebBrowser2->get_Document(&pDocDisp);
CComQIPtr<IHTMLDocument2> pDoc=pDocDisp;
//得到window
CComPtr<IHTMLWindow> pWindow;
pDoc->get_parentWindow(&pWindow);
//取得window的IDispatchEx接口 (IDispatchEx是动态脚本语言的基础,请参阅:http://blog.csdn.net/pimshell/archive/2008/08/04/2768182.aspx)
CComQIPtr<IDispatchEx> pObject=pWindow;
//创建page对象
CComObject<CPage>* pPage;
CComObject<CPage>::CreateInstance(&pPage);
//为pObject生成 page变量 的 dispid
DISPID dispid;
CComBSTR bstrName=L"page";
pObject->GetDispID(bstrName,fdexNameEnsure,&dispid);
//为page变量赋值
VARIANT var;
DISPID putid;
DISPPARAMS dispparams, dispparamsNoArgs = {NULL, NULL, 0, 0};
putid = DISPID_PROPERTYPUT;
var.vt = VT_DISPATCH;
var.pdispVal = (IDispatch*)pPage;
dispparams.rgvarg = &var;
dispparams.rgdispidNamedArgs = &putid;
dispparams.cArgs = 1;
dispparams.cNamedArgs = 1;
pObject->InvokeEx(dispid, LOCALE_USER_DEFAULT,
DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF,
&dispparams,
NULL, NULL, NULL);
//这样在脚本中就可以直接使用page了。如,page.dosomething(params);
这种方案的好处是可以为每个网页及其下的子页面设置单独的自定义对象,从而细致的控制安全性问题。
弊端:设置“全局对象”的时机不好把握。如果是在OnDocumentComplete事件中执行,当用户刷新页面时,这个事件不会被再次调用。而且,也没有资料表明可以截获“刷新”事件。这样的话,“网页”也就无法通过“全局对象”来访问“程序”了。
方案三:主动模式--控件(ActiveX)和行为(Behavior)
一开始我们说了,对于“网页”而言,“程序”访问“网页”称为“被动模式”,反之称为“主动模式”。前面的两个方案都是“被动模式”,由“程序”提供路径,以便可以被“网页”访问。
而“主动模式”是由“网页”在内部创建“程序”的自定义对象。自定义对象可以针对网页单独创建,而且也可以设置“全局对象”,这样就自然避免了“被动模式”的弊端。“主动模式”主要有两种方式:控件(ActiveX)和行为(Behavior)。Adobe AIR和MS Silverlight采用的是ActiveX。这种方式就是为网页提供了一个功能丰富的DOM元素。优点是性能高,缺点是ActiveX的界面与html的界面并不一致,体验也不同,需要额外的开发技术。PIMShell采用的是Behavior。这种方式就是为网页现有的DOM元素提供额外的属性、方法和事件。比如,为DIV元素附加一个HTMLEditor行为,就可以通过DIV元素实现网页编辑器的功能了。优点是,继续沿用现有的html/javascript技术,缺点是性能略逊于ActiveX。
经常有人用CDHtmlDialog开发纯网页的对话框。这里首先要解决的是“程序”与“网页”之间的通信问题。“程序”访问“网页”可以使用IWebBrowser2接口。“网页”访问“程序”可以在脚本中调用window.external的方法。对于“网页”而言,暂且将前者称为“被动模式”,后者称为“主动模式”。于是,“程序”在建立一个“网页”对话框时,向“网页”提供一个自定义的external对象,就解决了二者之间的通信问题了。
在简单的应用中,上述方案是有效的。但有一个约束性条件:就是“网页”中的代码都是可控的。如果“网页”允许通过iframe元素加载其他来源的子页面时,就会出现安全隐患了。因为当前网页中所有iframe中的子页面也都能访问window.external的方法。那可不可以为每一个“网页”建立一个单独的external对象呢?经测试是不行的。也就是说,“程序”内嵌的“WebBrowser控件”一次只能设置一个external对象,为当前“网页”和其下所有的“子页面”服务。而且,在external对象内部也无法判断此次调用的来源。
方案二:直接提供类似window的全局对象
因为“程序”可以使用IWebBrowser2接口访问“网页”,那么我们可以直接创建一个自定义对象,并将其设为“网页”的全局对象,就像window一样。下面演示如何为“网页”提供一个page对象。
//IWebBrowser2接口是已知的
CComPtr<IWebBrowser2> m_pWebBrowser2;
//得到document
CComPtr<IDispatch> pDocDisp;
m_pWebBrowser2->get_Document(&pDocDisp);
CComQIPtr<IHTMLDocument2> pDoc=pDocDisp;
//得到window
CComPtr<IHTMLWindow> pWindow;
pDoc->get_parentWindow(&pWindow);
//取得window的IDispatchEx接口 (IDispatchEx是动态脚本语言的基础,请参阅:http://blog.csdn.net/pimshell/archive/2008/08/04/2768182.aspx)
CComQIPtr<IDispatchEx> pObject=pWindow;
//创建page对象
CComObject<CPage>* pPage;
CComObject<CPage>::CreateInstance(&pPage);
//为pObject生成 page变量 的 dispid
DISPID dispid;
CComBSTR bstrName=L"page";
pObject->GetDispID(bstrName,fdexNameEnsure,&dispid);
//为page变量赋值
VARIANT var;
DISPID putid;
DISPPARAMS dispparams, dispparamsNoArgs = {NULL, NULL, 0, 0};
putid = DISPID_PROPERTYPUT;
var.vt = VT_DISPATCH;
var.pdispVal = (IDispatch*)pPage;
dispparams.rgvarg = &var;
dispparams.rgdispidNamedArgs = &putid;
dispparams.cArgs = 1;
dispparams.cNamedArgs = 1;
pObject->InvokeEx(dispid, LOCALE_USER_DEFAULT,
DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF,
&dispparams,
NULL, NULL, NULL);
//这样在脚本中就可以直接使用page了。如,page.dosomething(params);
这种方案的好处是可以为每个网页及其下的子页面设置单独的自定义对象,从而细致的控制安全性问题。
弊端:设置“全局对象”的时机不好把握。如果是在OnDocumentComplete事件中执行,当用户刷新页面时,这个事件不会被再次调用。而且,也没有资料表明可以截获“刷新”事件。这样的话,“网页”也就无法通过“全局对象”来访问“程序”了。
方案三:主动模式--控件(ActiveX)和行为(Behavior)
一开始我们说了,对于“网页”而言,“程序”访问“网页”称为“被动模式”,反之称为“主动模式”。前面的两个方案都是“被动模式”,由“程序”提供路径,以便可以被“网页”访问。
而“主动模式”是由“网页”在内部创建“程序”的自定义对象。自定义对象可以针对网页单独创建,而且也可以设置“全局对象”,这样就自然避免了“被动模式”的弊端。“主动模式”主要有两种方式:控件(ActiveX)和行为(Behavior)。Adobe AIR和MS Silverlight采用的是ActiveX。这种方式就是为网页提供了一个功能丰富的DOM元素。优点是性能高,缺点是ActiveX的界面与html的界面并不一致,体验也不同,需要额外的开发技术。PIMShell采用的是Behavior。这种方式就是为网页现有的DOM元素提供额外的属性、方法和事件。比如,为DIV元素附加一个HTMLEditor行为,就可以通过DIV元素实现网页编辑器的功能了。优点是,继续沿用现有的html/javascript技术,缺点是性能略逊于ActiveX。
相关文章推荐
- 使用 XUL 实现浏览器扩展,第 2 部分: 组建一个跨平台的 Firefox 扩展
- 支持在 Web 浏览器中使用加密媒体扩展和 Microsoft PlayReady DRM
- 管道的三种使用方案中,唯一正确而安全的使用方法
- 走进PIMShell(4)--网页的架构htm/xml/js
- 使用userscript扩展浏览器插件
- 走进PIMShell(6)--预定义的全局变量
- 使用 XUL 实现浏览器扩展,第 2 部分: 组建一个跨平台的 Firefox 扩展
- 使用PHP%20cURL扩展模拟浏览器抓取网页
- 使用Beef劫持客户端浏览器并进一步使用Beef+msf拿客户端shell
- 使用 XUL 实现浏览器扩展,第 1 部分: 使用用户界面特性创建一个 Firefox 浏览
- 走进PIMShell(5)--Form(窗体)的应用
- 使用 XUL 实现浏览器扩展,第 1 部分: 使用用户界面特性创建一个 Firefox 浏览器扩展
- 我已使用新的CSDN blog -- PIMShell
- react 使用 eslint 的三种代码检查方案总结,多了解点--让代码更完美....
- WEB之浏览器使用入门--chrome扩展插件安装及好用的扩展插件小集合
- 在IE6系列等老式浏览器中使用HTML5的新标签实现方案
- 不再为命名而苦恼!使用 MSTestEnhancer 单元测试扩展,写契约就够了
- 走进PIMShell(3)--实现TabNew行为(Behavior)
- localforage 对不同浏览器 使用不同的缓存策略 , 大大提高了性能 ,IndexedDB,WebSQL 和 localStorage 三种存储模式