标签:
http://blog.csdn.net/cnjet/article/details/6176525
关于什么是浏览器,强大的wiki已经做了比较完善的解释http://en.wikipedia.org/wiki/Web_browser。相关浏览器的比较参考:http://en.wikipedia.org/wiki/Comparison_of_web_browsers#Vulnerabilities
浏览器的核心是layout engine,基本上各浏览器只是包装,主要layout engine参考:http://en.wikipedia.org/wiki/Comparison_of_layout_engines
目前主要的浏览器为Internet Explorer, Firefox, Chrome, Safari和Opera,其余浏览器多为在此基础上的二次开发,如搜狗浏览器,Maxthon等。
浏览器基本都支持针对性的开发,具体的开发支持分为三个层次:主题开发,只能定制浏览器的皮肤界面等;扩展开发,可以定制浏览器的一些功能响应;插件开发,真正的对于浏览器的新功能开发。常见的flash就是使用最广的浏览器插件。目前主要的插件有两种,ActiveX控件和NPAPI插件。
微软的技术基本是COM和ActiveX的天下,IE浏览器插件只支持ActiveX作为插件。具体过程比较简单,使用ATL或MFC开发一个标准的支持IE的ActiveX控件即可。
除微软外,其它浏览器核心基本都是支持NPAPI插件。NPAPI较ActiveX控件更简单,但是只针对浏览器插件。什么是NPAPI,可以参考:http://en.wikipedia.org/wiki/NPAPI
下面主要介绍一个windows32 NPAPI插件的开发实例。
(一)下载所需的头文件或SDK
可以下载GeckoPluginSDK(https://developer.mozilla.org/en/Gecko_SDK),如果觉得麻烦的话可以下载一个只包含头文件的精简版http://code.google.com/p/npapi-headers/(其中函数结构体的大小好像需要点修改)。下面使用精简版;
(二)使用Visual Studio C++建立一个DLL项目(建议选择纯空项目),添加上面下载的头文件;
添加一个Plugin.cpp作为导出函数的源代码文件,添加一个资源文件(这个必须,并且要全部填写下面的资源,否则不会被加载),添加一个.def文件。
(三)填写.def文件(windows下最少有这三个函数)
LIBRARY "NPPlugin"
EXPORTS
NP_GetEntryPoints @1
NP_Initialize @2
NP_Shutdown @3
(四)填写资源文件(windows下此资源文件必须包括所有字符资源)
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "Comments", "simple plugin of NPAPI./0"
VALUE "CompanyName", "FSE Team/0"
VALUE "FileDescription", "npsimple/0"
VALUE "FileExtents", "npHello/0"
VALUE "FileOpenName", "npsimple/0"
VALUE "FileVersion", "1, 0, 0, 1/0"
VALUE "InternalName", "npHello/0"
VALUE "LegalCopyright", "Copyright ?2011/0"
VALUE "LegalTrademarks", "FSE Team./0"
VALUE "MIMEType", "application/npHello/0"
VALUE "OriginalFilename", "npPlugin.dll/0"
VALUE "PrivateBuild", "/0"
VALUE "ProductName", "Simple Example Plugin for Mozilla/0"
VALUE "ProductVersion", "1, 0, 0, 1/0"
VALUE "SpecialBuild", "/0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 1252
END
END
注意:其中很多资源项必须存在,否则浏览器将无法确认其为一个NPAPI插件。
(五)实现基本的插件接口函数
#define EXPORT_API EXTERN_C
static NPNetscapeFuncs NPNFuncs;
static WNDPROC lpOldProc = NULL;
static NPWindow* s_Window = NULL;
EXPORT_API NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs)
{
if(pFuncs == NULL)
return NPERR_INVALID_FUNCTABLE_ERROR;
if(pFuncs->size < sizeof(NPPluginFuncs))
return NPERR_INVALID_FUNCTABLE_ERROR;
pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
pFuncs->size = sizeof(NPPluginFuncs);
pFuncs->newp = NPP_New;
pFuncs->destroy = NPP_Destroy;
pFuncs->setwindow = NPP_SetWindow;
pFuncs->newstream = NULL; //NPP_NewStream;
pFuncs->destroystream = NULL; //NPP_DestroyStream;
pFuncs->asfile = NULL; //NPP_StreamAsFile;
pFuncs->writeready = NULL; //NPP_WriteReady;
pFuncs->write = NULL; //NPP_Write;
pFuncs->print = NULL; //NPP_Print;
pFuncs->event = NULL; //NPP_HandleEvent;
pFuncs->urlnotify = NULL; //NPP_URLNotify;
pFuncs->getvalue = NPP_GetValue;
pFuncs->setvalue = NULL; //NPP_SetValue;
pFuncs->javaClass = NULL;
return NPERR_NO_ERROR;
}
EXPORT_API NPError OSCALL NP_Initialize( NPNetscapeFuncs* pFuncs
#ifdef XP_UNIX
, NPPluginFuncs* pluginFuncs
#endif
)
{
if(pFuncs == NULL)
return NPERR_INVALID_FUNCTABLE_ERROR;
if(HIBYTE(pFuncs->version) > NP_VERSION_MAJOR)
return NPERR_INCOMPATIBLE_VERSION_ERROR;
if(pFuncs->size < sizeof(NPNetscapeFuncs))
return NPERR_INVALID_FUNCTABLE_ERROR;
NPNFuncs.size = pFuncs->size;
NPNFuncs.version = pFuncs->version;
NPNFuncs.geturlnotify = pFuncs->geturlnotify;
NPNFuncs.geturl = pFuncs->geturl;
NPNFuncs.posturlnotify = pFuncs->posturlnotify;
NPNFuncs.posturl = pFuncs->posturl;
NPNFuncs.requestread = pFuncs->requestread;
NPNFuncs.newstream = pFuncs->newstream;
NPNFuncs.write = pFuncs->write;
NPNFuncs.destroystream = pFuncs->destroystream;
NPNFuncs.status = pFuncs->status;
NPNFuncs.uagent = pFuncs->uagent;
NPNFuncs.memalloc = pFuncs->memalloc;
NPNFuncs.memfree = pFuncs->memfree;
NPNFuncs.memflush = pFuncs->memflush;
NPNFuncs.reloadplugins = pFuncs->reloadplugins;
NPNFuncs.getJavaEnv = NULL;
NPNFuncs.getJavaPeer = NULL;
NPNFuncs.getvalue = pFuncs->getvalue;
NPNFuncs.setvalue = pFuncs->setvalue;
NPNFuncs.invalidaterect = pFuncs->invalidaterect;
NPNFuncs.invalidateregion = pFuncs->invalidateregion;
NPNFuncs.forceredraw = pFuncs->forceredraw;
#ifndef WIN32
NPNFuncs.getstringidentifier = pFuncs->getstringidentifier;
NPNFuncs.getstringidentifiers = pFuncs->getstringidentifiers;
NPNFuncs.getintidentifier = pFuncs->getintidentifier;
NPNFuncs.identifierisstring = pFuncs->identifierisstring;
NPNFuncs.utf8fromidentifier = pFuncs->utf8fromidentifier;
NPNFuncs.intfromidentifier = pFuncs->intfromidentifier;
NPNFuncs.createobject = pFuncs->createobject;
NPNFuncs.retainobject = pFuncs->retainobject;
NPNFuncs.releaseobject = pFuncs->releaseobject;
NPNFuncs.invoke = pFuncs->invoke;
NPNFuncs.invokeDefault = pFuncs->invokeDefault;
NPNFuncs.evaluate = pFuncs->evaluate;
NPNFuncs.getproperty = pFuncs->getproperty;
NPNFuncs.setproperty = pFuncs->setproperty;
NPNFuncs.removeproperty = pFuncs->removeproperty;
NPNFuncs.hasproperty = pFuncs->hasproperty;
NPNFuncs.hasmethod = pFuncs->hasmethod;
NPNFuncs.releasevariantvalue = pFuncs->releasevariantvalue;
NPNFuncs.setexception = pFuncs->setexception;
#endif
return NPERR_NO_ERROR;
}
EXPORT_API NPError OSCALL NP_Shutdown(void)
{
return NPERR_NO_ERROR;
}
EXPORT_API char* NP_GetMIMEDescription(void)
{
return "application/nphello: nphello: np plugin";
}
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved)
{
if(instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
NPError rv = NPERR_NO_ERROR;
return rv;
}
NPError NPP_Destroy(NPP instance, NPSavedData** save)
{
// 释放对于窗口的子类化,还原原来的消息处理函数
if( s_Window && s_Window->window ) {
if( lpOldProc ) {
SetWindowLong( HWND(s_Window->window), GWL_WNDPROC, (LONG)lpOldProc );
}
}
s_Window = NULL;
lpOldProc = NULL;
return NPERR_NO_ERROR;
}
static LRESULT CALLBACK PluginWinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_PAINT:
{
// draw a frame and display the string
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
RECT rc;
GetClientRect(hWnd, &rc);
FrameRect(hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
// get our plugin instance object and ask it for the version string
//nsPluginInstance *plugin = (nsPluginInstance *)GetWindowLong(hWnd, GWL_USERDATA);
DrawText(hdc, "IGA laucher", strlen("IGA laucher"), &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hWnd, &ps);
}
break;
default:
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
NPError NPP_SetWindow(NPP instance, NPWindow *window)
{
s_Window = window;
if( !(window->window) ) {
if( lpOldProc ) {
SetWindowLong( HWND(window->window), GWL_WNDPROC, (LONG)lpOldProc );
}
return NPERR_GENERIC_ERROR;
}
HWND hwnd = HWND(window->window);
// subclass window so we can intercept window messages and
// do our drawing to it
lpOldProc = (WNDPROC)SetWindowLong( hwnd, GWL_WNDPROC, (LONG)PluginWinProc );
//// associate window with our nsPluginInstance object so we can access
//// it in the window procedure
//SetWindowLong(hwnd, GWL_USERDATA, (LONG)this);
return NPERR_NO_ERROR;
}
NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value)
{
NPError err = NPERR_NO_ERROR;
switch (variable) {
case NPPVpluginNameString:
*((char **)value) = "application/nphello";
break;
case NPPVpluginDescriptionString:
*((char **)value) = "writen by freecnjet-at-gmail.com";
break;
default:
err = NPERR_GENERIC_ERROR;
}
return err;
}
其中如果需要实现插件的现实,NPP_SetWindow部分将插件和一个容器窗口关联。
(六)插件的安装和使用
插件编译完成后为一个标准的DLL(此处仅讨论windows下的情况)。将此DLL,以np*.dll形式命名并保存在firefox的plugin目录,
在firefox中输入about:plugins;即可看到插件已经安装完成。另外一种更加通用的方式为添加注册表项,注册插件为一个标准插件。
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SOFTWARE/MozillaPlugins/@fse.org/NPP Plugin,version=1.0]
"Description"="NPP plugin"
"Path"="D://Projects//BrownsPlugin//Release//npPlugin.dll"
"ProductName"="NPP plugin"
"Vendor"="fse team."
"Version"="1.0.0.0"
[HKEY_LOCAL_MACHINE/SOFTWARE/MozillaPlugins/@fse.org/NPP Plugin,version=1.0/MimeTypes]
[HKEY_LOCAL_MACHINE/SOFTWARE/MozillaPlugins/@fse.org/NPP Plugin,version=1.0/MimeTypes/application/nphello]
"Description"="NPP plugin(*.nphello)"
"Suffixes"="nphello"
[HKEY_LOCAL_MACHINE/SOFTWARE/MozillaPlugins/@fse.org/NPP Plugin,version=1.0/Suffixes]
"nphello"=""
具体关于NPAPI插件的PLID参考http://www-archive.mozilla.org/projects/plugins/plugin-identifier.html。这样chrome,
opera和safari等都可以支持此插件了,具体可以在地址栏输入about:plugins;即可查看到安装的新插件(注意需要关闭所有
浏览器窗口之后再重新打开浏览器才能确保浏览器会加载新的插件)
最后编辑一个网页,内容如下:
<HTML>
<HEAD>
<TITLE>NPPlugin test webpage</TITLE>
</HEAD>
<BODY>
<center><embed type="application/npHello" width=800 height=600></center>
</BODY>
</HTML>
使用浏览器打开此网页即可发现结果。
浏览器插件开发作为对于浏览器本身功能的扩展应用广泛,NPAPI插件更是当今浏览器所支持的标准插件,结构简单功能强大。
标签:
原文地址:http://www.cnblogs.com/gamekk/p/4780014.html