<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                PPAPI的插件,原本是可以使用JS與瀏覽器交互的,[https://code.google.com/p/ppapi/wiki/InterfacingWithJavaScript](https://code.google.com/p/ppapi/wiki/InterfacingWithJavaScript),這里還提供了一個JS與plugin交互的文檔,但現在說不支持了,現在應該通過PPB_Messaging接口來完成Plugin和瀏覽器的交互,具體參考[https://src.chromium.org/viewvc/chrome/trunk/src/ppapi/c/ppb_messaging.h?revision=92312&view=markup](https://src.chromium.org/viewvc/chrome/trunk/src/ppapi/c/ppb_messaging.h?revision=92312&view=markup)這里。我實驗了一下,通了。 Messaging接口很好,傳遞的消息可以自已定義,類型也無限制,非常方便。 > foruok原創,如需轉載請關注foruok的微信訂閱號“程序視界”聯系foruok。 # 使用postMessage通信 Messaging接口與其它大多數接口一樣,分PPB和PPP兩側。分開來說明一下要做的事情。 ### 插件側 要做這么些事情: 1. 實現PPP_Messaging接口,關鍵是void (*HandleMessage)(PP_Instance instance, struct PP_Var message)方法 1. 在Get_Interface中返回名字是PPP_MESSAGING_INTERFACE的接口 1. 在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對。 1. PPP_Messaging的HandleMessage處理瀏覽器的消息,如果需要,調用PPB_Messaging的PostMessage發送消息. 注意,插件側調用PPB_Var接口的VarFromUtf8時,傳入的len不包括’\0’在內。PPAPI的ppb_var.h的注釋里的示例代碼片段有誤,調用時傳遞的長度是sizeof(hello_world),應該減去一。 還有一點,插件和瀏覽器交互的數據,都是數據的拷貝哦,調用接口會發生復制行為。 ### 瀏覽器側 瀏覽器側可以使用JavaScript來監聽插件發送的message事件,也可以使用插件元素的postMessage發送消息給插件。 基本上做下面幾件事即可: 1. 實現處理消息的JS函數,其參數是MessageEvent,data成員為插件發過來的信息,可以當做JS對象來訪問。 1. 監聽插件的message事件 1. 在合適的時候調用插件的postMessage(object)方法發送消息給插件 # 代碼 分插件代碼和HTML代碼。 ### 插件代碼 代碼是在[**在PPAPI插件中創建本地窗口**](http://blog.csdn.net/foruok/article/details/50513228)一文示例代碼的基礎上改的,添加了消息處理的部分。只貼相關的部分了。 **獲取消息相關接口的代碼** 在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", message.type); OutputDebugStringA(szLog); if (message.type == 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 confIdKey[] = "confId"; char userNameKey[] = "userName"; char *szConfId = 0; char*szUserName = 0; struct PP_Var idKey = g_var_interface->VarFromUtf8(confIdKey, sizeof(confIdKey) - 1); struct PP_Var userKey = g_var_interface->VarFromUtf8(userNameKey, sizeof(userNameKey) - 1); struct PP_Var var = g_dictionary_interface->Get(message, idKey); const char *value = g_var_interface->VarToUtf8(var, &len); if (len > 0) { szConfId = malloc(len + 1); strncpy_s(szConfId, len+1, value, len); szConfId[len] = 0; } g_var_interface->Release(var); var = g_dictionary_interface->Get(message, userKey); value = g_var_interface->VarToUtf8(var, &len); if (len > 0) { szUserName = malloc(len + 1); strncpy_s(szUserName, len+1, value, len); szUserName[len] = 0; } g_var_interface->Release(var); sprintf_s(szLog, 256, "Plugin_HandleMessage, dict, command = joinConf, user = %s, confId = %s\r\n", szUserName, szConfId); OutputDebugStringA(szLog); if (szConfId && szUserName) { sprintf_s(szLog, 256, "plugin got confId - %s, user - %s\r\n", szConfId, szUserName); OutputDebugStringA(szLog); joinConf(szConfId, szUserName); } else { OutputDebugString(_T("Invalid conference id or userName\r\n")); } if (szConfId) free(szConfId); if (szUserName) free(szUserName); g_var_interface->Release(idKey); g_var_interface->Release(userKey); /* fake attendees*/ char szMsgTypeValue[] = "userlist"; char szTypeKey[] = "type"; struct PP_Var typeKey = g_var_interface->VarFromUtf8(szTypeKey, sizeof(szTypeKey) - 1); struct PP_Var typeValue = g_var_interface->VarFromUtf8(szMsgTypeValue, sizeof(szMsgTypeValue) - 1); struct PP_Var attendee = g_dictionary_interface->Create(); g_dictionary_interface->Set(attendee, typeKey, typeValue); struct PP_Var userArray = g_array_interface->Create(); char szUser1[] = "ZhangSan"; char szUser2[] = "LiSi"; struct PP_Var user1 = g_var_interface->VarFromUtf8(szUser1, sizeof(szUser1) - 1); struct PP_Var user2 = g_var_interface->VarFromUtf8(szUser2, sizeof(szUser2) - 1); g_array_interface->Set(userArray, 0, user1); g_array_interface->Set(userArray, 1, user2); char szValueKey[] = "value"; struct PP_Var valueKey = g_var_interface->VarFromUtf8(szValueKey, sizeof(szValueKey) - 1); g_dictionary_interface->Set(attendee, valueKey, userArray); g_message_interface->PostMessage(instance, attendee); OutputDebugString(_T("Post attendee to browser")); g_var_interface->Release(typeKey); g_var_interface->Release(typeValue); g_var_interface->Release(user1); g_var_interface->Release(user2); g_var_interface->Release(valueKey); g_var_interface->Release(userArray); g_var_interface->Release(attendee); } else if (strncmp(strCommand, "viewVideo", len) == 0) { char userIdKey[] = "userId"; char *szUserId = 0; struct PP_Var idKey = g_var_interface->VarFromUtf8(userIdKey, sizeof(userIdKey) - 1); struct PP_Var var = g_dictionary_interface->Get(message, idKey); const char *value = g_var_interface->VarToUtf8(var, &len); if (len > 0) { szUserId = malloc(len + 1); strncpy_s(szUserId, len + 1, value, len); szUserId[len] = 0; } if (szUserId) { sprintf_s(szLog, 256, "plugin got userId - %s\r\n", szUserId); OutputDebugStringA(szLog); viewVideo(szUserId, g_child_window); } else { OutputDebugString(_T("Invalid viewVideo command without userId\r\n")); } if (szUserId) free(szUserId); g_var_interface->Release(var); g_var_interface->Release(idKey); } g_var_interface->Release(commandVar); } else if (message.type == PP_VARTYPE_STRING) { char hello_world[] = "Hello world!"; struct PP_Var var = g_var_interface->VarFromUtf8(hello_world, sizeof(hello_world) - 1); g_message_interface->PostMessage(instance, var); // var will be copyed g_var_interface->Release(var); } } static PPP_Messaging message_interface = { &Plugin_HandleMessage }; ~~~ 有點長,比較潦草。 **返回PPP_Messaging的代碼** 完整的PPP_GetInterface函數如下: ~~~ PP_EXPORT const void* PPP_GetInterface(const char* interface_name) { if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) { OutputDebugString(_T("PPP_GetInterface, instance_interface\r\n")); return &instance_interface; } else if (strcmp(interface_name, PPP_INPUT_EVENT_INTERFACE) == 0) { OutputDebugString(_T("PPP_GetInterface, input_interface\r\n")); return &input_interface; } else if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) { OutputDebugString(_T("PPP_GetInterface, message_interface\r\n")); return &message_interface; } return NULL; } ~~~ ### 網頁代碼 網頁代碼如下: ~~~ <!DOCTYPE html> <html> <!-- Copyright (c) 2016 foruok@微信訂閱號“程序視界”(programmer_sight). All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> <head> <style type="text/css"> #contacts { margin: 10px; width: 300px; height: 200px; background-color: gray; } </style> <script type="text/javascript"> function handleMessage(message) { alert(message.data.type); if(message.data.type.localeCompare("userlist") == 0){ var i = 0; ul = document.getElementById("attendee"); for(; i < message.data.value.length; i++){ var li = document.createElement("li"); li.appendChild(document.createTextNode(message.data.value[i])); ul.appendChild(li); } } } function joinConference(){ plugin = document.getElementById('tangplugin'); plugin.postMessage({ command:"joinConf", confId: document.getElementById("confId").value, userName: document.getElementById("userName").value }); } function viewSharedVideo(){ plugin = document.getElementById('tangplugin'); plugin.postMessage({ command:"viewVideo", userId: document.getElementById("userId").value }); } function initialize() { plugin = document.getElementById('tangplugin'); plugin.addEventListener('message', handleMessage, false); } document.addEventListener('DOMContentLoaded', initialize, false); </script> <title>Tang in Plugin</title> </head> <body> <form> ConferenceID: <input type="text" id="confId" />&nbsp;&nbsp;User: <input type="text" id="userName" />&nbsp;&nbsp;<input type="button" value="Join" onclick="joinConference()"/> </form> <hr> <div id="contacts"> <p>contacts:</p> <ul id="attendee"> <!-- here will show attendee list, added by JS callback --> </ul> UserId:<input type="text" id="userId" />&nbsp;&nbsp;<button type="button" onclick="viewSharedVideo()">View Video</button> </div> <p>share video:</p> <embed id="tangplugin" type="application/x-ppapi-tang-video" width="300px" height="200px" top="40px" left="20px"> </body> </html> ~~~ Join按鈕會獲取它前面兩個文本框的內容,發送給插件,插件返回一個用戶列表,網頁解析(HandleMessage方法)出來,動態修改用戶列表。 # 運行效果 貼兩幅圖,點擊Join按鈕之前是醬紫的: ![before](https://box.kancloud.cn/2016-02-22_56caac341008d.jpg "") 點擊Join按鈕后是醬紫的: ![after](https://box.kancloud.cn/2016-02-22_56caac34279dc.jpg "") 其他參考文章: - [**CEF Windows開發環境搭建**](http://blog.csdn.net/foruok/article/details/50468642) - [**CEF加載PPAPI插件**](http://blog.csdn.net/foruok/article/details/50485448) - [**VS2013編譯最簡單的PPAPI插件**](http://blog.csdn.net/foruok/article/details/50485461) - [**理解PPAPI的設計**](http://blog.csdn.net/foruok/article/details/50486788) - [**PPAPI插件與瀏覽器的交互過程**](http://blog.csdn.net/foruok/article/details/50494061) - [**Windows下從源碼編譯CEF**](http://blog.csdn.net/foruok/article/details/50498740) - [**編譯PPAPI的media_stream_video示例**](http://blog.csdn.net/foruok/article/details/50498873) - [**PPAPI插件的繪圖與輸入事件處理**](http://blog.csdn.net/foruok/article/details/50499813) - [**在PPAPI插件中創建本地窗口**](http://blog.csdn.net/foruok/article/details/50513228)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看