1. 插件
WebKit 插件在和引擎交互时 , 主要涉及到两个接口 :
插件 => 引擎: NPNetscapeFuncs
引擎 => 插件: NPPluginFuncs
其中 , 插件到引擎的接口 WebKit 已经实现了。插件要做的事情就是实现引擎 => 插件的接口。
typedef struct _NPPluginFuncs {
uint16_t size;
uint16_t version;
NPP_NewUPP newp;
NPP_DestroyUPP destroy;
NPP_SetWindowUPP setwindow;
NPP_NewStreamUPP newstream;
NPP_DestroyStreamUPP destroystream;
NPP_StreamAsFileUPP asfile;
NPP_WriteReadyUPP writeready;
NPP_WriteUPP write;
NPP_PrintUPP print;
NPP_HandleEventUPP event;
NPP_URLNotifyUPP urlnotify;
// The type of this used to be JRIGlobalRef, which was a void *.
// Use void * here directly now that we don't expose any Java
// specific things in the plugin API.
void* javaClass;
NPP_GetValueUPP getvalue;
NPP_SetValueUPP setvalue;
} NPPluginFuncs;
本文将参考 Android 的插件例子来进行讲解插件的基本原理。
2. Android WebKit 插件
接口的初始化:
NPNetscapeFuncs 的初始化:
initializeExtraBrowserFuncs
事件处理:
HTMLPlugInElement::defaultEventHandler
PluginView::handleEvent
PluginView::handleTouchEvent
PluginWidgetAndroid::sendEvent
NPPluginFuncs::event
进入具体插件的 NPP_HandleEvent
创建 Surface :
PluginView::setFrameRect
PluginView::setNPWindowIfNeeded
PluginWidgetAndroid::setWindow
PluginWidgetAndroid::layoutSurface
NPPluginFuncs::getvalue , kJavaSurface_ANPGetValue
进入插件 NPP_GetValue
所谓 Surface ,其实就是一块内存区域。对于 BackgroundPlugin ,就是继承自 TextView 。
也有可能是 SurfaceView 的子类,取决于具体应用情境。
设置窗口并刷新:
PluginView::setParent|PluginView::paint
PluginView::updatePluginWidget|PluginView::setFrameRect
PluginView::setNPWindowIfNeeded(!!!)
m_plugin->pluginFuncs()->setwindow
NPP_SetWindow(NPPluginFuncs::setwindow)
NPNetscapeFuncs::invalidaterect
NPN_InvalidateRect
PluginView::invalidateRect
刷新界面:
PluginView::invalidateRect
PluginWidgetAndroid::inval
WebViewCore::invalPlugin
WebViewCore::pluginInvalTimerFired
WebViewCore::drawPlugins
PluginWidgetAndroid::draw ,发出 kDraw_ANPEventType 事件,
NPPluginFuncs::event
插件的加载:
HTMLObjectElement::attach
HTMLPlugInElement::updateWidgetCallback
HTMLObjectElement::updateWidget|HTMLEmbedElement::updateWidget|FrameView::updateWidgets|
RenderEmbeddedObject::updateWidget
FrameLoader::requestObject
FrameLoader::loadPlugin
FrameLoaderClientAndroid::createPlugin
PluginView::create
PluginView::platformInit
PluginView::PluginView
PluginView::platformInit
{
setPlatformWidget(new PluginViewBridgeAndroid());
new PluginWidgetAndroid
}