Writing an HTTP filter plugin
Article Metadata
Code Example
Article
Contents |
What is an HTTP filter plugin?
HTTP filter plugins classes that get loaded in to HTTP sessions on Symbian OS, and sit between the HTTP framework and the client, receiving HTTP events and potentially acting on them.
A chain of HTTP filter plugins is automatically loaded with every HTTP session you invoke. You can also manually load additional filters, or remove automatically loaded ones via the RHTTPSession::FilterCollection API.
What can I do with an HTTP filter?
Well, lots! You can modify outgoing requests, look at or modify the responses to a fairly high degree. As far as what you can do, the sky is the limit, basically.
How do I write an HTTP filter?
HTTP filters extend the MHTTPFilter (documented in the devlib.) Filters for automatic loading are packaged in an ECOM object, and also extend the CEComFilter, implementing the KUidFilterPluginInterface interface.
An example of an automatically loading plugin is included below.
A demo HTTP filter
A bare bones demo HTTP filter is attached to this page. It does nothing except log messages on load and unload, and record the URL of all transactions submitted. Hopefully, this will give you the bare essentials and you can flesh it out to create your own filter.
A walkthrough of the key components of the code:
CEComFilter* CDemoFilter::CreateFilterL(TAny* aHttpSession)
{
// The CEcomFilter class passes us a pointer to the RHTTPSession so we can install ourselves
RHTTPSession* session = reinterpret_cast<RHTTPSession*>(aHttpSession);
CDemoFilter* self = new (ELeave) CDemoFilter;
CleanupStack::PushL(self);
self->ConstructL(*session);
CleanupStack::Pop(self);
return self;
}
This is the ECOM plugin entry point. The HTTP framework will load our plugin, and pass us the current HTTP session. We should create an instance of ourselves, and load ourselves as a filter in to the session. This is done in ConstructL:
void CDemoFilter::ConstructL(RHTTPSession& aSession)
{
// install this filter in to the current session
iFilterName = aSession.StringPool().OpenFStringL(KDemoFilterName);
aSession.FilterCollection().AddFilterL(*this, THTTPEvent::EAnyTransactionEvent,
RStringF(), KAnyStatusCode, EClientFilters, iFilterName);
}
The parameters to AddFilterL define which transactions we're called for. We can choose to only get called for certain transactions or events. I've chosen to have my filter called for all transactions. The parameter where I've passed EClientFilters defines where in the chain of filters you get loaded. Most filters will choose EClientFilters, since this will ensure we are invoked after all the system filters.
// virtuals from the HTTP filter M classes
void MHFUnload(RHTTPSession aSession, THTTPFilterHandle aHandle);
void MHFLoad(RHTTPSession aSession, THTTPFilterHandle aHandle);
void MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent);
void MHFSessionRunL(const THTTPSessionEvent& aEvent);
TInt MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent);
TInt MHFSessionRunError(TInt aError, const THTTPSessionEvent& aEvent);
The MHTTPFilter interface defines the virtuals listed above. These aren't pure virtuals, you can choose not to implement some or all of them. My demo filter implements all of them for the purposes of demonstration.
const TImplementationProxy KImplementationTable[] =
{
IMPLEMENTATION_PROXY_ENTRY(0xA00033E9, CDemoFilter::CreateFilterL)
};
EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
{
aTableCount = sizeof(KImplementationTable) / sizeof(TImplementationProxy);
return KImplementationTable;
}
The standard ECOM entry point. Obviously, you'd change 0xA00033E9 to be your own implementation UID procured from Symbian Signed.
And that's pretty much it for the code. Pretty simple, eh?
Getting your HTTP filter loaded automatically
In my plugin, I'm using:
default_data = "HTTP/+DEMOFILTER";
Which means "always load this filter, and don't let it be unloaded."
A note on capabilities
I've given this demo plugin the capabilities:
ReadDeviceData WriteDeviceData ProtServ NetworkControl NetworkServices SwEvent LocalServices ReadUserData WriteUserData UserEnvironment
Which is the very minimum required for the filter to be loaded in the Nokia OSS browser process. I say "minimum", but it's still a hefty chunk of capabilities.
Ideally, you should have ALL-TCB for an HTTP filter. In practice, you'll probably end up with all the non-manufacturer granted capabilities plus Network Control.
Sample project:


Can anyone confirm it is working? I built it for emulator (SDK s60 3rd ed. MR) and tested using "Services" and "Web" applications. The DemoFilter does indeed load and unload but it never gets any kind of events :(.
works fine
works fine - you need DRM for V9.1 devices and V9.2 devices without FP2.
Doesn't seem to work with Opera mini though.
HTTPS and SSL certificate
Article does not explain how to provide server certificate.
Note (edited by emailatravi) - moved from article's body
ALL-TCB capability does not work. The web browser does not let you load the plugin, hence one cannot surf the internet.
In addition to the above capabilities (i.e. ReadDeviceData WriteDeviceData ProtServ NetworkControl NetworkServices SwEvent LocalServices ReadUserData WriteUserData UserEnvironment), you also need to add AllFiles and DRM capabilities. I have tested this on E65.
Re: Note (edited by NevePankaj) - moved here from article's body
No need to have extra capabilities mentioned as above(AllFiles and DRM). It is working with CAPABILITIES(ReadDeviceData WriteDeviceData ProtServ NetworkControl NetworkServices SwEvent LocalServices ReadUserData WriteUserData UserEnvironment). The only thing I observed is not working with Symbian OS v9.1 devices. I have tested on 9.2 and 9.3 devices I have, it's working.
Kurmasys - Not able to build/run
Hi
I am not able to build run the DemoFilter code provided here.
When I try to build I am getting below compile time error. I am new to Symbian so I might be missing something that might be pretty obvious so please excuse me for that.
..\src\demoFilter.cpp:98: warning: variable / argument 'aSession' is not used in function ..\src\demoFilter.cpp:98: warning: variable / argument 'aHandle' is not used in function ..\src\demoFilter.cpp:106: warning: variable / argument 'aSession' is not used in function ..\src\demoFilter.cpp:106: warning: variable / argument 'aHandle' is not used in function ..\src\demoFilter.cpp:122: warning: variable / argument 'aEvent' is not used in function ..\src\demoFilter.cpp:127: warning: variable / argument 'aError' is not used in function ..\src\demoFilter.cpp:127: warning: variable / argument 'aTransaction' is not used in function ..\src\demoFilter.cpp:127: warning: variable / argument 'aEvent' is not used in function ..\src\demoFilter.cpp:133: warning: variable / argument 'aError' is not used in function ..\src\demoFilter.cpp:133: warning: variable / argument 'aEvent' is not used in function mwldsym2.exe: warning: Multiply defined symbol: ___get_MSL_init_count in mwldsym2.exe: warning: files uc_cwhelp.obj (EEXE.LIB), startup.win32.c.obj (msl_all_static_mse_symbian_d.lib), mwldsym2.exe: warning: keeping definition in startup.win32.c.obj mwldsym2.exe: warning: Multiply defined symbol: __CleanUpMSL in mwldsym2.exe: warning: files uc_cwhelp.obj (EEXE.LIB), startup.win32.c.obj (msl_all_static_mse_symbian_d.lib), mwldsym2.exe: warning: keeping definition in startup.win32.c.obj mwldsym2.exe: Undefined symbol: 'void REComSession::DestroyedImplementation(class TUid) (?DestroyedImplementation@REComSession@@SAXVTUid@@@Z)' mwldsym2.exe: referenced from 'CEComFilter::~CEComFilter(void) (??1CEComFilter@@UAE@XZ)' in cecomfilter.h:104
Errors caused tool to abort. mwldsym2.exe: Undefined symbol: 'void RStringBase::Close(void) (?Close@RStringBase@@QAEXXZ)' mwldsym2.exe: referenced from 'CDemoFilter::~CDemoFilter(void) (??1CDemoFilter@@UAE@XZ)' in demoFilter.cpp:87 make[1]: *** [\S60\devices\S60_5th_Edition_SDK_v1.0\epoc32\release\winscw\udeb\smm_0xe5aa5f2e.exe] Error 1 mwldsym2.exe: Undefined symbol: 'class RStringPool RHTTPSession::StringPool(void) const (?StringPool@RHTTPSession@@QBE?AVRStringPool@@XZ)' mwldsym2.exe: referenced from 'void CDemoFilter::ConstructL(class RHTTPSession &) (?ConstructL@CDemoFilter@@AAEXAAVRHTTPSession@@@Z)' in demoFilter.cpp:93 mwldsym2.exe: Undefined symbol: 'class RStringF RStringPool::OpenFStringL(class TDesC8 const &) const (?OpenFStringL@RStringPool@@QBE?AVRStringF@@ABVTDesC8@@@Z)' mwldsym2.exe: referenced from 'void CDemoFilter::ConstructL(class RHTTPSession &) (?ConstructL@CDemoFilter@@AAEXAAVRHTTPSession@@@Z)' in demoFilter.cpp:93 make: *** [TARGETSMM] Error 2 mwldsym2.exe: Undefined symbol: 'void RHTTPFilterCollection::AddFilterL(class MHTTPFilter &, class THTTPEvent, class RStringF, int, int, class RStringF) (?AddFilterL@RHTTPFilterCollection@@QAEXAAVMHTTPFilter@@VTHTTPEvent@@VRStringF@@HH2@Z)' mwldsym2.exe: referenced from 'void CDemoFilter::ConstructL(class RHTTPSession &) (?ConstructL@CDemoFilter@@AAEXAAVRHTTPSession@@@Z)' in demoFilter.cpp:94 mwldsym2.exe: Undefined symbol: 'class RHTTPRequest RHTTPTransaction::Request(void) const (?Request@RHTTPTransaction@@QBE?AVRHTTPRequest@@XZ)' mwldsym2.exe: referenced from 'void CDemoFilter::MHFRunL(class RHTTPTransaction, class THTTPEvent const &) (?MHFRunL@CDemoFilter@@UAEXVRHTTPTransaction@@ABVTHTTPEvent@@@Z)' in demoFilter.cpp:117 mwldsym2.exe: Undefined symbol: 'class TUriC8 const & RHTTPRequest::URI(void) const (?URI@RHTTPRequest@@QBEABVTUriC8@@XZ)' mwldsym2.exe: referenced from 'void CDemoFilter::MHFRunL(class RHTTPTransaction, class THTTPEvent const &) (?MHFRunL@CDemoFilter@@UAEXVRHTTPTransaction@@ABVTHTTPEvent@@@Z)' in demoFilter.cpp:117 mwldsym2.exe: Undefined symbol: 'class TDesC8 const & TUriC8::UriDes(void) const (?UriDes@TUriC8@@QBEABVTDesC8@@XZ)' mwldsym2.exe: referenced from 'void CDemoFilter::MHFRunL(class RHTTPTransaction, class THTTPEvent const &) (?MHFRunL@CDemoFilter@@UAEXVRHTTPTransaction@@ABVTHTTPEvent@@@Z)' in demoFilter.cpp:117 mwldsym2.exe: Undefined symbol: 'int MHTTPFilterBase::MHFSessionRunError(int, class THTTPSessionEvent const &) (?MHFSessionRunError@MHTTPFilterBase@@UAEHHABVTHTTPSessionEvent@@@Z)' mwldsym2.exe: referenced from 'const MHTTPFilterBase::`vftable' (??_7MHTTPFilterBase@@6B@~)' in demoFilter.o mwldsym2.exe: referenced from 'const MHTTPFilter::`vftable' (??_7MHTTPFilter@@6B@~)' in demoFilter.o mwldsym2.exe: Undefined symbol: 'int MHTTPFilterBase::MHFRunError(int, class RHTTPTransaction, class THTTPEvent const &) (?MHFRunError@MHTTPFilterBase@@UAEHHVRHTTPTransaction@@ABVTHTTPEvent@@@Z)' mwldsym2.exe: referenced from 'const MHTTPFilterBase::`vftable' (??_7MHTTPFilterBase@@6B@~)' in demoFilter.o mwldsym2.exe: referenced from 'const MHTTPFilter::`vftable' (??_7MHTTPFilter@@6B@~)' in demoFilter.o mwldsym2.exe: Undefined symbol: 'void MHTTPFilterBase::MHFSessionRunL(class THTTPSessionEvent const &) (?MHFSessionRunL@MHTTPFilterBase@@UAEXABVTHTTPSessionEvent@@@Z)' mwldsym2.exe: referenced from 'const MHTTPFilterBase::`vftable' (??_7MHTTPFilterBase@@6B@~)' in demoFilter.o mwldsym2.exe: referenced from 'const MHTTPFilter::`vftable' (??_7MHTTPFilter@@6B@~)' in demoFilter.o mwldsym2.exe: Undefined symbol: 'void MHTTPFilterBase::MHFRunL(class RHTTPTransaction, class THTTPEvent const &) (?MHFRunL@MHTTPFilterBase@@UAEXVRHTTPTransaction@@ABVTHTTPEvent@@@Z)' mwldsym2.exe: referenced from 'const MHTTPFilterBase::`vftable' (??_7MHTTPFilterBase@@6B@~)' in demoFilter.o mwldsym2.exe: referenced from 'const MHTTPFilter::`vftable' (??_7MHTTPFilter@@6B@~)' in demoFilter.o mwldsym2.exe: Undefined symbol: 'void MHTTPFilter::MHFLoad(class RHTTPSession, class THTTPFilterHandle) (?MHFLoad@MHTTPFilter@@UAEXVRHTTPSession@@VTHTTPFilterHandle@@@Z)' mwldsym2.exe: referenced from 'const MHTTPFilter::`vftable' (??_7MHTTPFilter@@6B@~)' in demoFilter.o mwldsym2.exe: Undefined symbol: 'void MHTTPFilter::MHFUnload(class RHTTPSession, class THTTPFilterHandle) (?MHFUnload@MHTTPFilter@@UAEXVRHTTPSession@@VTHTTPFilterHandle@@@Z)'
mwldsym2.exe: referenced from 'const MHTTPFilter::`vftable' (??_7MHTTPFilter@@6B@~)' in demoFilter.okurmasys 21:26, 11 May 2013 (EEST)
Kurmasys - Additional question
One more query.
Can I use the HTTP filter plugin in my application to monitor the HTTP request/responses are going over the web browser on symbian phone? I just want to read the URLs of HTTP messages.
If not is there any other such mechanism to do achieve functionality?
Thanks in advancekurmasys 21:38, 11 May 2013 (EEST)
Hamishwillee - Linking against bafl?
Where this class is (I think) defined.
You've found all the other methods I know - logs, IP Hook.hamishwillee 08:52, 14 May 2013 (EEST)