原创|其它|编辑:郝浩|2009-04-24 09:37:36.000|阅读 1077 次
概述:在IE浏览器中,如果想捕获浏览器的HTTP请求,可以通过BHO或者“异步可插协议”技术实现,类似于“迅雷”之类的下载软件,当用户点击一个下载链接会自动弹出。在Symbian OS中有一种技术与“异步可插协议”非常类似,Symbian OS会在HTTP请求中每一步处理过程都通知用户代码,本文将介绍这种技术的实现,并在文章的最后提供在手机上实现下载软件的具体思路。
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
在IE浏览器中,如果想捕获浏览器的HTTP请求,可以通过BHO或者“异步可插协议”技术实现,类似于“迅雷”之类的下载软件,当用户点击一个下载链接会自动弹出。在Symbian OS中有一种技术与“异步可插协议”非常类似,Symbian OS会在HTTP请求中每一步处理过程都通知用户代码,本文将介绍这种技术的实现,并在文章的最后提供在手机上实现下载软件的具体思路。
从类名可以看出,CEComFilter是一个ECOM接口类(关于ECOM方面的编程总结,我会在后面的章节陆续放出),以下列出CEComFilter类的关键代码(SDK中文件cecomfilter.h内):
1 const TUid KUidFilterPluginInterface = {0x101F446D}; 2 class CEComFilter : public CBase 3 { 4 public: 5 static CEComFilter* InstallFilterL(RHTTPSession
aSession, const TUid aEComFilterUid) 6 { 7 TAny* filterPlugin = REComSession::
CreateImplementationL(aEComFilterUid, _FOFF(CEComFilter,
iEcomDtorID), &aSession); 8 return REINTERPRET_CAST(CEComFilter*,
filterPlugin); 9 } 10 11 static CEComFilter* InstallFilterL(RHTTPSession
aSession, const TDesC8& aEComFilterDataType) 12 { 13 TEComResolverParams resolverParams; 14 resolverParams.SetDataType(aEComFilterDataType); 15 16 // This will leave if the plugin is not found17 TAny* filterPlugin = REComSession::
CreateImplementationL(KUidFilterPluginInterface, 18 _FOFF(CEComFilter,iEcomDtorID), 19 &aSession, resolverParams); 20 return REINTERPRET_CAST
(CEComFilter*, filterPlugin); 21 } 22 23 ~CEComFilter() 24 { 25 REComSession::DestroyedImplementation(iEcomDtorID); 26 } 27 28 private: 29 TUid iEcomDtorID; 30 };
通过代码我们可以分析出以下结论:
class REComSession : public RSessionBase { ... IMPORT_C static void ListImplementationsL
(TUid aInterfaceUid, RImplInfoPtrArray& aImplInfoArray); ... }
实现CEComFilter,其实就是实现一个普通的ECOM接口,步骤非常简单,在此不再说明具体步骤。重点在第5步:如何对传入的RHTTPSession进行监控。
SDK中关于RHTTPSession::FilterCollection()方法的解释:
Accessor for the filter collection. Note that the filter collection can't be edited after the first transaction has been created.
注意:如果已经在RHTTPSession上创建了RHTTPTransaction,则不能对Filter Collection进行修改。
此方法返回类型RHTTPFilterCollection,使用RHTTPFilterCollection::AddFilterL的重载函数向RHTTPSession的监视器队列中添加“监视器”,用于捕获HTTP请求信息:
IMPORT_C void AddFilterL(MHTTPFilter& aFilter,
THTTPEvent aEvent, RStringF aHeader, TInt aStatusCode,
TInt aPosition, RStringF aName);
参数说明:
1 class MHTTPFilter 2 { 3 public: 4 IMPORT_C virtual void
MHFUnload(RHTTPSession aSession, THTTPFilterHandle aHandle); 5 IMPORT_C virtual void
MHFLoad(RHTTPSession aSession, THTTPFilterHandle aHandle); 6 IMPORT_C virtual void
MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent); 7 IMPORT_C virtual void
MHFSessionRunL(const THTTPSessionEvent& aEvent); 8 IMPORT_C virtual TInt
MHFRunError(TInt aError, RHTTPTransaction aTransaction,
const THTTPEvent& aEvent); 9 IMPORT_C virtual TInt
MHFSessionRunError(TInt aError, const THTTPSessionEvent& aEvent); 10 };
根据以上分析,我们可以通过实现CEComFilter接口完成一个Demo:只要系统提交了HTTP进行Url的请求,就弹出一个全局消息框,显示HTTP所请求的Url地址。
1、实现接口的类名叫CFelixHttpFilter,定义如下:
1 class CFelixHttpFilter: public CEComFilter,
private MHTTPFilter 2 { 3 public: 4 ~CFelixHttpFilter(); 5 static CFelixHttpFilter* NewL(TAny*
aHttpSession); 6 static CFelixHttpFilter* NewLC(TAny*
aHttpSession); 7 8 public: 9 // MHTTPFilter10 void MHFUnload(RHTTPSession aSession,
THTTPFilterHandle aHandle); 11 void MHFLoad(RHTTPSession aSession,
THTTPFilterHandle aHandle); 12 void MHFRunL(RHTTPTransaction aTransaction,
const THTTPEvent& aEvent); 13 14 private: 15 CFelixHttpFilter(); 16 void ConstructL(TAny* aHttpSession); 17 18 private: 19 RStringF iFilterName; 20 }; 21
2、关键类代码实现如下:
1 _LIT8(KFilterName, "FelixFilter"); 2 3 CFelixHttpFilter::~CFelixHttpFilter() 4 { 5 iFilterName.Close(); 6 } 7 8 CFelixHttpFilter* CFelixHttpFilter::NewLC(TAny* aHttpSession) 9 { 10 CFelixHttpFilter* self = new (ELeave) CFelixHttpFilter(); 11 CleanupStack::PushL(self); 12 self->ConstructL(aHttpSession); 13 return self; 14 } 15 16 CFelixHttpFilter* CFelixHttpFilter::
NewL(TAny* aHttpSession) 17 { 18 CFelixHttpFilter* self =
CFelixHttpFilter::NewLC(aHttpSession); 19 CleanupStack::Pop(); // self;20 return self; 21 } 22 23 void CFelixHttpFilter::ConstructL
(TAny* aHttpSession) 24 { 25 RHTTPSession& httpSession = *
(reinterpret_cast<RHTTPSession*>(aHttpSession)); 26 27 iFilterName = httpSession.StringPool().
OpenFStringL(KFilterName); 28 CleanupClosePushL(iFilterName); 29 30 httpSession.FilterCollection().AddFilterL
(*this, THTTPEvent::EAnyTransactionEvent, RStringF(),
KAnyStatusCode, EClientFilters, iFilterName); 31 CleanupStack::Pop(&iFilterName); 32 } 33 34 void CFelixHttpFilter::MHFUnload(RHTTPSession aSession,
THTTPFilterHandle aHandle) 35 { 36 delete this; 37 } 38 39 void CFelixHttpFilter::MHFRunL(RHTTPTransaction
aTransaction, const THTTPEvent& aEvent) 40 { 41 if (aEvent == THTTPEvent::ESubmit) 42 { 43 // 在此处拦截到请求的Url44 const TDesC8& url = aTransaction.Request().
URI().UriDes(); 45 TBuf<KMaxFileName> url16; 46 url16.Copy(url); 47 48 // 效果:将url打印到屏幕上49 CEikonEnv::Static()->InfoWinL(url16, KNullDesC16); 50 } 51 } 52 53 const TImplementationProxy kImplementationTable[]=54 { 55 IMPLEMENTATION_PROXY_ENTRY(0xA00133E9,
CFelixHttpFilter::NewL) 56 }; 57 58 EXPORT_C const TImplementationProxy*
ImplementationGroupProxy(TInt& aTableCount) 59 { 60 aTableCount = sizeof(kImplementationTable) /
sizeof(TImplementationProxy); 61 return kImplementationTable; 62 } 63
注意,代码第55行中的0xA00133E9是我们ECOM实现的implementation_uid。
3、我们的程序UID3为0xA00133E8,ECOM资源文件名:A00133E8.rss,内容如下:
1 RESOURCE REGISTRY_INFO filterinfo 2 { 3 dll_uid = _UID3; 4 interfaces= 5 { 6 INTERFACE_INFO 7 { 8 interface_uid = 0x101F446D; 9 implementations = 10 { 11 IMPLEMENTATION_INFO 12 { 13 implementation_uid = 0xA00133E9; 14 version_no = 1; 15 display_name = "Felix Filter"; 16 default_data = "HTTP/+FELIXFILTER"; 17 opaque_data = ""; 18 } 19 }; 20 } 21 }; 22 } 23
以上资源文件第16行,default_data的作用:
HTTP监视器能够“主动的”加载或者“被动的”加载,这取决于你资源文件中IMPLEMENTATION_INFO小节中的“default_data”字段(以上代码第16行)所设定的值,有如下三个加载选项被支持:
基本概念都已经清楚,现在我们来想想如何实现手机上的迅雷。根据以下流程可以容易的做到:
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com
文章转载自:博客园