Writing an HTTP filter plugin
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;
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);
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 =
EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
aTableCount = sizeof(KImplementationTable) / sizeof(TImplementationProxy);
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.
Note: As mentioned above, there is a minimum set of capabilities required for the plug-in to get loaded, and that of course it is dictated by the capabilities of the process which loads it. Depending on the filter type, and HTTP filter plug-in may be automatically loaded into any application which is using the HTTP stack, and that means that the plug-in must have as many capabilities as possible (ideally All-TCB).
Note: The minimal set of capabilities described reflects what the plug-in requires to be loaded in the Browser, but the capabilities requirement of the Browser itself will change over time. E.g. for adding HTML5 features such as geolocation the browser will require the Location capability and it will become mandatory for all the Browser loaded plug-ins (browser plugins or any other ECOM plug-in loaded indirectly by it). One more reason for the plug-in to have as many capabilities, to protect itself from these type of changes.