Chromium浏览器扩展JS对象方法


 

前言: Chromium浏览器采用的是V8引擎解析javascript代码, V8引擎相对于传统的JS引擎效率上有很大的提高,主要是因为它将js代码直接编译成了目标机器代码. V8引擎的编译过程主要是 js代码->抽象代码树->目标机器代码而传统的js编译过程是 js代码->抽象代码树->中间代码->解释执行.  V8引擎在执行需要重复调用函数的js代码中效率有显著提升,但是在执行代码量庞大,函数一般是单次调用的JS代码效率上却并不明显,原因是重复调用的函数只需要被编译成一次机器码就能重复执行,而传统的解释执行方式却需要每次都去解释执行.   

在做Chromium浏览器定制化需求时常常需要扩展JS对象以增加js的功能javascript这门编程语言的概念里,一切皆为对象,变量,函数等等一切皆为对象,没有类的概念,javascript是一门动态语言,它的主要特点是对象的类型和内容是在运行时决定的,是可以不断变化的javascript的世界里,根对象是global对象,所有的一切对象皆为global的子孙对象.在浏览器中,这个global对象的表现为window对象webkit中已实现的对象称为javascript内部对象,内部对象又分为本地对象和内置对象本地对象需要由用户在js代码中使用new方法初化始对象之后才能使用,内置对象是在webkit中已初始化好了可以直接使用例如

Testjs本地对象,使用方法为:  Test test = new Test(); alert(test.value); 

Testjs内置对象,使用方法为:  alert(Test.value); 

 

现在以扩展一个javascript Test本地对象为例子说明如何扩展webkit js对象(本方法试验的chorium版本为53): 

实现目标:  以下js代码能够顺利执行

 var test = new Test(“aaa”,”bbb”,”ccc”); 

               test.setValue(“value”); 

 alert(“ip = “ + test.address  + “,mask = “ + test.mask + “,gateway =”+test.gateway + “,value =  “ + test.value); 

 

实现步骤

1.在webkit core目录(浏览器根目录/src/wibkit/Source/core)相应的位置分别新建Test.idl,Test.h,Test.cpp文件.并在core.gypi中相应的位置将.idlc文件包含进去

2..idl文件是连接js对象和c++对象的媒介,首先根据你要设计的js对象的属性和方法来确定.idl对象,再根据.idl文件来写相应的.h 和 .cpp文件

现在要新增一个 本地js对象,对象名称为Test,它的构造方法是传入三个字符串参数,它有三个可读写字符串属性adress,mask,gateway,一个只读字符串属性value,一个方法为setValue. 

那么Test.idl文件的内容为

[

     Constructor(DOMString ip,DOMString mask,DOMString gateway),

] interface Test {

     readonly  attribute DOMString value;

     attribute DOMString address;

     attribute DOMString mask;

     attribute DOMString gateway;

     void setValue(DOMString value); 

    

};

 

window.idl中加上:

attribute TestConstructor Test;   //注意这里的Test对应的javascript中的Test,如果这里是myTest,那么js代码就是 new myTest(...)

 

   现在写Test 对应的c++,它需要实现 static Test * create(String & str1,String &str2,String& str3)供外部调用只读属性 value 对应的方法 String  value() const;  可读写属性对应的方法 String address() const; void setAddress(const String& ip); //(注意这里的函数名要与前面.idl文件声明的属性名称一致,设置属性的函数需要在前面加set并将第一个字母大写,setAdress函数名一致),mask , gateway属性如上.  .idl中声明的方法在c++类中的方法一致,只需要照旧声明一个方法 void setValue(String &value);就行.  好了,只需要把这些接口实现所有工作就完成了接下来就可以编译运行测试了

类的实现代码如下所示:

#ifndef TEST_H

 

#define TEST_H

#include "wtf/PassRefPtr.h"

#include "core/CoreExport.h"

#include "bindings/core/v8/ScriptWrappable.h"

#include "wtf/RefCounted.h"

#include "wtf/text/WTFString.h"

namespace blink {

class Test  :  public RefCountedWillBeGarbageCollectedFinalized,public ScriptWrappable{

    DEFINE_WRAPPERTYPEINFO();

public:

virtual ~Test();

static PassRefPtrWillBeRawPtr create(){

return  create( String(""), String(""), String("")); 

}

static PassRefPtrWillBeRawPtr create(String ip,String mask,String gateway );

String address() const;

String mask() const; 

String gateway() const; 

void setAddress(const String& ip){mIp=ip;}

void setMask(const String& mask){mMask=mask;}

void setGateway(const String& gateway){mGateWay=gateway;}

String value() const;

void setValue(const String& value){mValue=value;}

private:

explicit Test(String,String,String);

String mValue; 

       String mIp;

String mMask;

String mGateWay;

};

 

}

 

#endif

二 webkit扩展js内置对象的方法

还是以上面的 Test为例

1.Test.idl中将[

     Constructor(DOMString ip,DOMString mask,DOMString gateway),

去除

2. 在 window.idl 将原来的声明改为 [Replaceable] readonly attribute Test Test;

3. DomWindow.h中增加Test的虚函数构造方法声明 virtual Test* test() const {return NULL;}

4.LocalDOMWindow.h中声明方法 Test* test() const  override,新增变量mutable PersistentWillBeMember m_test;

5.LocalDomWindow.cpp中对 test方法做实现

Test* LocalDOMWindow::test() const

{

     if (!m_test)

         m_test = Test::create();

     return m_test.get();

}

 

实现原理

 

Chromium编译系统会首先去解析test.idl,通过python脚本解析.idl文件生成相应的v8test.cpp,v8test.h. v8test对象 会调用到我们手动写的test对象. v8test.cpp对象绑定了js对象相应的属性和方法,所以在运行时V8解析javascript代码时能够找到找到关联的c++对象上运行Test js代码相应的调用步骤是: V8引擎解析js代码-> v8Test->Test

 

 

总结

    在webkit中扩展js对象的方法比较简单,实现过程中出现出错一般也能通过参照原有的代码找到解决方法本文是对chorium浏览器如何扩展js对象作了大体概述,但是对于 python脚本如何解析.idl文件生成对应代码,v8引擎如何解析javascript代码这些内部原理本文未涉及

你可能感兴趣的:(Chromium浏览器扩展JS对象方法)