PPAPI的插件,原本是可以使用JS与浏览器交互的,/p/ppapi/wiki/InterfacingWithJavaScript,这里还提供了一个JS与plugin交互的文档,但现在说不支持了,现在应该通过PPB_Messaging接口来完成Plugin和浏览器的交互,具体参考/viewvc/chrome/trunk/src/ppapi/c/ppb_messaging.h?revision=92312&view=markup这里。我实验了一下,通了。
Messaging接口很好,传递的消息可以自已定义,类型也无限制,非常方便。
foruok原创,如需转载请关注foruok的微信订阅号“程序视界”联系foruok。
使用postMessage通信
Messaging接口与其它大多数接口一样,分PPB和PPP两侧。分开来说明一下要做的事情。
插件侧
要做这么些事情:
- 实现PPP_Messaging接口,关键是void (*HandleMessage)(PP_Instance instance, struct PP_Var message)方法
- 在Get_Interface中返回名字是PPP_MESSAGING_INTERFACE的接口
- 在PPP_InitializeModule中获取 PPB_Messaging、PPB_Var、PPB_VarArray、PPB_VarDictionary等接口。
PPB_Messaging的PostMessage用于向浏览器发送消息,发送过去的消息,JS代码可以接收到。
PPB_Var可以用来构造String类型的Var,可以操作Var的引用计数
PPB_VarArray是数组接口,可以创建、访问、设置数组
PPB_VarDictionary是字典(map)接口,可以创建字典Var,可以存取key-value对。 - PPP_Messaging的HandleMessage处理浏览器的消息,如果需要,调用PPB_Messaging的PostMessage发送消息.
注意,插件侧调用PPB_Var接口的VarFromUtf8时,传入的len不包括’\0’在内。PPAPI的ppb_var.h的注释里的示例代码片段有误,调用时传递的长度是sizeof(hello_world),应该减去一。
还有一点,插件和浏览器交互的数据,都是数据的拷贝哦,调用接口会发生复制行为。
浏览器侧
浏览器侧可以使用JavaScript来监听插件发送的message事件,也可以使用插件元素的postMessage发送消息给插件。
基本上做下面几件事即可:
- 实现处理消息的JS函数,其参数是MessageEvent,data成员为插件发过来的信息,可以当做JS对象来访问。
- 监听插件的message事件
- 在合适的时候调用插件的postMessage(object)方法发送消息给插件
代码
分插件代码和HTML代码。
插件代码
代码是在在PPAPI插件中创建本地窗口一文示例代码的基础上改的,添加了消息处理的部分。只贴相关的部分了。
获取消息相关接口的代码
在PPP_InitializeModule中添加了获取PPB_Messaging接口以及其它可能用到的PP_Var类型的接口,有Array和Dictionary。
g_var_interface = (const PPB_Var*)get_browser_interface(PPB_VAR_INTERFACE);
g_dictionary_interface = (const PPB_VarDictionary*)get_browser_interface(PPB_VAR_DICTIONARY_INTERFACE);
g_array_interface = (const PPB_VarArray*)get_browser_interface(PPB_VAR_ARRAY_INTERFACE);
g_message_interface = (const PPB_Messaging*)get_browser_interface(PPB_MESSAGING_INTERFACE);
PPP_Messaging接口的实现
PPP_Messaging接口的实现代码如下:
void Plugin_HandleMessage(PP_Instance instance, struct PP_Var message)
{
char szLog[256] = { 0 };
sprintf_s(szLog, 256, "Plugin_HandleMessage, type = %d\r\n", );
OutputDebugStringA(szLog);
if ( == PP_VARTYPE_DICTIONARY)
{
char command[] = "command";
struct PP_Var commandKey = g_var_interface->VarFromUtf8(command, sizeof(command) - 1);
struct PP_Var commandVar = g_dictionary_interface->Get(message, commandKey);
int len = 0;
const char *strCommand = g_var_interface->VarToUtf8(commandVar, &len);
g_var_interface->Release(commandKey);
sprintf_s(szLog, 256, "Plugin_HandleMessage, dict, command = %s, len = %d\r\n", strCommand, len);
OutputDebugStringA(szLog);
if (len == 0)
{
OutputDebugString(_T("Tang_plugin, recv invalid command\r\n"));
g_var_interface->Release(commandVar);
return;
}
if (strncmp(strCommand, "joinConf", len) == 0)
{
char