chrome利用NPAPI开发扩展

发布时间:2016-12-10 20:54:45 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"chrome利用NPAPI开发扩展",主要涉及到chrome利用NPAPI开发扩展方面的内容,对于chrome利用NPAPI开发扩展感兴趣的同学可以参考一下。

chrome扩展必须编写清单文件manifest.json和内容脚本JS,清单文件名字必须是mainifest.json,内容格式为JSON,需要指定扩展页面和内容脚本。   内容脚本 内容脚本在Chrome扩展编写中扮演着非常重要的角色,其内容就是JavaScript代码。内容脚本虽然物理位置是在扩展目录中,但其内容代码是根据匹配规则被注入到对应的原始网页中,因此可以简单的把内容脚本理解为原始网页的组成部分。内容脚本和原始网页共享相同的DOM数据,因此内容脚本可以对页面DOM进行任意增、删、改操作,这是内容脚本最主要的功能。   内容脚本的执行时机 内容脚本执行的时机由run_at字段指明。可以取三个值: document_start:文档开始,相当于document对象刚刚创建,此时DOM树还没有构建完成。这个值是内容脚本挂接文档级事件的好时机。 document_end:文档结束,此时DOM树已经构建,主文档加载完毕,但图片等子资源数据可能未加载完成。 document_idle:空闲,可理解为在window.onload事件之后执行。     内容脚本的执行环境 我们知道chrome浏览器是多进程架构,对于每个扩展也会运行在单独的进程中,但是如果扩展仅仅涉及内容脚本(扩展的功能完全是由内容脚本实现)的话,chrome不会为此扩展启动单独的进程。因为内容脚本被注入到匹配页面中,其执行环境为匹配网页的Render进程。这是内容脚本执行的进程环境。 另外虽然内容脚本被注入到页面中,它和页面中本身的脚本的执行环境也是分割的,即内容脚本运行在孤立的V8上下文环境中。因此内容脚本不能访问页面脚本中的变量和函数。它们唯一共享的是DOM。这是可以理解的,试想如果内容脚本和页面本身的脚本运行在相同的脚本上下文中,变量、函数岂不是可能导致冲突?   内容脚本与本地页面的通信 本地页面: <script>                    functionsendChatMsg()                    {                             varmsgNode = document.getElementById("chat_msg");                             if(msgNode.value== "")                             {                                      return;                             }                                                                                     chrome.windows.getCurrent(function(wnd){                        chrome.tabs.getAllInWindow(wnd.id, function(tabs){                                 for(var i=0; i < tabs.length; i++)                                 {                                          if(tabs[i].url =="http://www.google.com.hk/")                                          {                                                    chrome.tabs.sendRequest(tabs[i].id,{msg: msgNode.value});                                                    msgNode.value="";                                          }                                 }                                 });                 });                                 contentNode =document.getElementById("chat_content");                 contentNode.value = contentNode.value + "我说:" +msgNode.value + "\r\n";                 contentNode.scrollTop = contentNode.scrollHeight;                    }                                       chrome.extension.onRequest.addListener(                    function(data){                             contentNode= document.getElementById("chat_content");                             contentNode.value= contentNode.value + "google说:" + data.msg +"\r\n";                             contentNode.scrollTop= contentNode.scrollHeight;                             }                    );                             </script>   内容脚本: var sendChatMsg = function() {            var msgNode =document.getElementById("chat_msg");          if(msgNode.value =="")          {                    return;          }          chrome.extension.sendRequest({msg:msgNode.value});          contentNode =document.getElementById("chat_content");          contentNode.value =contentNode.value + "i say:" + msgNode.value + "\r\n";          contentNode.scrollTop= contentNode.scrollHeight;          msgNode.value=""; };   chatdiv = document.createElement("div"); chatdiv.id = "chat_div"; chatdiv.style.zIndex = "100"; chatdiv.style.position = "absolute"; chatdiv.style.left = "560px"; chatdiv.style.top = "280px"; chatdiv.style.width = "auto"; chatdiv.style.height = "auto"; chatdiv.style.border = "1px solid"; chatdiv.style.overflow = "auto"; chatdiv.style.backgroundColor = "#F7F4EC"; chatdiv.innerHTML = "<div>" +          "<textareaid=\"chat_content\" ROWS=\"8\"COLS=\"40\"></textarea>" +          "<div><inputid='chat_msg' size=\"35\" type=\"text\"/><inputid='sendBtn' type=\"button\"value=\"send\"/></div></div>"; document.body.appendChild(chatdiv); document.getElementById("sendBtn").addEventListener('click',sendChatMsg,false);   chrome.extension.onRequest.addListener(          function(data){                             contentNode= document.getElementById("chat_content");                             contentNode.value= contentNode.value + "extension say:" + data.msg + "\r\n";                             contentNode.scrollTop= contentNode.scrollHeight;          } );   内容脚本与远程页面的通信 html页面(不属于扩展)需要创建一个自定义事件,当它向DOM中的一个特定元素写入事件数据后就会激活并派发这个自定义事件。 Content script在这个特定元素上监听这个自定义事件,从这个元素中获取数据,并向扩展进程post一个消息。通过这种方式, 页面建立了与扩展的通信链接。 这个方法也适用于反向的通信,如果传参数则需要创建CustomEvent事件来进行通信。 远程页面: var customEvent = document.createEvent('Event'); customEvent.initEvent('myCustomEvent', true, true);   function fireCustomEvent(data) {   hiddenDiv =document.getElementById('myCustomEventDiv');   hiddenDiv.innerText = data;  hiddenDiv.dispatchEvent(customEvent); }   内容脚本: var port = chrome.extension.connect(); document.getElementById('myCustomEventDiv').addEventListener('myCustomEvent',function() {   var eventData =document.getElementById('myCustomEventDiv').innerText;   port.postMessage({message:"myCustomEvent", values: eventData}); });   port.onMessage.addListener(function(msg) {          alert(msg.answer); });   扩展background.html: <script> chrome.extension.onConnect.addListener(function(port) {  port.onMessage.addListener(function(msg) {                    alert(msg.message);                    alert(msg.values);                    port.postMessage({answer:"helloworld"});   }); }); </script>   NPAPI插件开发 在NPAPI编程的接口中你会发现有NP_打头的,有NPP_打头的,有NPN_打头的。NP是npapi的插件库提供给浏览器的最上层的接口;NPP即NP Plugin是插件本身提供给浏览器调用的接口,主要被用来填充NPPluginFuncs的结构体;NPN即NP Netscape,是浏览器提供给插件使用的接口,这些接口一般都在NPNetscapeFuncs结构体中。 入口函数NP_GetEntryPoints、NP_Initialize、 NP_Shutdown()需要在def中导出。浏览器启动时会调用先调用NP_GetEntryPoints获得NPPluginFuncs结构体对象,然后构造NPNetscapeFuncs结构体并调用NP_Initialize给插件相应结构体赋值,浏览器加载页面时创建Plugin实例并调用其NP_New(),浏览器通过NP_GetValue()来得到插件的信息,浏览器通过NPP_SetWindow传入插件窗口的信息,关闭页面时调用NP_Destroy()并释放Plugin实例,关闭浏览器时调用NP_Shutdown()。 在工程中需要实现函数NS_PluginInitialize、NS_PluginShutdown、NS_NewPluginInstance和NS_DestroyPluginInstance。在NP_Initialize中调用函数fillNetscapeFunctionTable()根据参数给NPNetscapeFuncs对象赋值,并调用NS_PluginInitialize;在NPP_New中调用NS_NewPluginInstance生成新的实例对象(插件类CPlugin);在NPP_Destroy中调用插件类的shut()函数并调用NS_DestroyPluginInstance()来释放资源;在NP_Shutdown中调用NS_PluginShutdown。在NP_GetEntryPoints中调用fillPluginFunctionTable来填充NPPluginFuncs对象。 插件类CPlugin需要继承自nsPluginInstanceBase,并实现三个纯虚函数:init(),shut()和isInitialized()。还可以重载nsPluginInstanceBase的虚函数。一下是NPPluginFuncs成员名、成员值与插件类的调用关系(默认调用基类nsPluginInstanceBase的函数): Member NPP_Xxx CPlugin newp NPP_New   destroy NPP_Destroy shut setwindow NPP_SetWindow init/ isInitialized/SetWindow newstream NPP_NewStream NewStream destroystream NPP_DestroyStream DestroyStream asfile NPP_StreamAsFile StreamAsFile writeready NPP_WriteReady WriteReady write NPP_Write Write print NPP_Print Print event NPP_HandleEvent HandleEvent urlnotify NPP_URLNotify URLNotify getvalue NPP_GetValue GetValue setvalue NPP_SetValue SetValue   其中浏览器执行脚本document.getElementById()时会调用函数NPP_GetValue,并传入NPPVpluginScriptableNPObject(作为variable参数)来查询插件是否支持Scriptable功能(即和脚本语言交互的功能),我们可以利用NPN_CreateObject方法来创建一个NPObject对象,并且作为value返回给浏览器。这样浏览器就可以通过这个NPObject对象和我们的插件建立连接。当页面上Javascript调用了我们插件对象的某个方法时,浏览器会调用该NPObject对象的HasProperty来询问是否是一个属性,不是则调用HasMethod方法来查询是否支持这个方法,如果支持则会调用NPObject对象的Invoke方法,传入方法名、参数等信息。这样我们就可以让网页上的脚本语言来执行我们编写的函数了。在Windows上,我们编写的函数就如同编写普通的应用程序一样,可以使用很多Windows API来完成许多复杂的工作。   打开浏览器,在地址栏输入“about:plugins”如果在plugin列表中有本例的npdemo.dll及说明我们的plugin示例已经成功完成。如下图所示:   在页面中测试该插件:pedemo.html <HTML>     <HEAD>     </HEAD>     <BODY>         <embed type="application/demo-plugin">     </BODY> </HTML>   在firefox中测试顺利通过,但是chrome中出现如下截图的问题,需要将MIME类型改为application/x-my-extension。

上一篇:hdu 4707 搜索 目前做的最水的搜索
下一篇:手机中常用的TELECOM 层的协议

相关文章

相关评论