Chromium web IDL


转载来自:https://tbolp.github.io/2020/12/04/%E5%9C%A8Chromium%E9%87%8C%E7%9A%84Blink%E4%B8%AD%E6%B7%BB%E5%8A%A0API/?highlight=c

我还没有实践成功,只是单纯记录下

参考文档:

https://github.com/oceanlantern/chrome-blink

https://www.chromium.org/developers/web-idl-interfaces/

https://www.chromium.org/blink/webidl/

在Chromium里的Blink中添加API

我的目标导出js的接口使得可以在页面通过js调用C++的一些方法完成任务

前言

关于导出C++接口方法

1 在extension api导出接口方便extension调用

2 在Blink内核中导出接口

我使用方法2完成导出,阅读一下内容可能需要了解Web IDL,Blink GC,Chromium Task等方面的知识,相关的一些资料在最后给出

环境

chroumium版本 70.0.3538.513

过程

在C++中定义Example类,该类会执行一个耗时操作,完成后调用回调将结果返回

在js里需要构造Example类,添加一个回调函数,然后调用将结果输出

添加目录

在third_party/blink/renderer/modules添加example目录,idl及对应的C++的实现统一放在这个目录

编写IDL文件

1 WebIDL是一种接口描述规范,可以用来生成一些C++和js之间的转换代码

2 inishedCallback为回调限制的类型,编译时会自动生成一个C++对象V8FinishedCallback与之对应

3 [Constructor]表明该interface可以再js中使用new构造,该属性可以有参数,对应的C++方法为static Example* Create(),Example实例被blink GC管理不需要对应的delete

4 Example需要编写blink::Example与之对应

1
2
3
4
5
6
7
8
callback FinishedCallback = void(DOMString msg);

[Constructor]
interface Example {
boolean Start();
DOMString Name();
void OnFinish(FinishedCallback callback);
};

编写C++代码

1 继承ScriptWrappable类可以提供类型描述,并且该类继承GarbageCollectedFinalized,所以Example是一个blink GC对象.类Example声明的方法与idl是对应的,除了构造函数比较特别以外.

2 #include “third_party/blink/renderer/bindings/modules/v8/v8_finished_callback.h”这个文件是根据idl里面callback自动生成的文件,编译后才会有.

3 不要再别的线程里调用js注册的回调函数

以上说明在代码注释里面也有对应

example.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#ifndef __EXAMPLE_H__
#define __EXAMPLE_H__
#include
#include "base/task/post_task.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_finished_callback.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"

// 类Example需要放在blink空间里
namespace blink {

// 类需要继承ScriptWrappable提供类型信息
// ScriptWrappable是一个blink GC管理的类不可以直接delete
class Example final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();

public:
// js调用new时调用该函数,相当于对外导出的构造函数
static Example* Create() { return new Example; }
bool Start() {
return base::PostTaskAndReply(
FROM_HERE, base::BindOnce(&Example::startWork, base::Unretained(this)),
base::BindOnce(&Example::finished, base::Unretained(this)));
}

// String与idl文件中DOMString对应
String Name() { return String("Example"); }

void startWork() { std::this_thread::sleep_for(std::chrono::seconds(10)); }

void finished() {
if (this->callback_) {
// 调用js中的回调
this->callback_->InvokeAndReportException(nullptr,
String("task finished"));
}
}

void OnFinish(V8FinishedCallback* callback) { callback_ = callback; }

// 因为该类包含需要追踪的类Member,该方法必须实现
void Trace(Visitor* visitor) override {
visitor->Trace(callback_);
ScriptWrappable::Trace(visitor);
}

~Example() override = default;

private:
// 保存js注册的回调
Member callback_;
};

} // namespace blink

#endif

example.cc

1
#include "example.h"

编写编译文件

修改的地方比较杂,但是不难理解

1 在third_party/blink/renderer/modules/example里添加以下文件来说明example模块编译的规则

BUILD.gn

1
2
3
4
5
6
7
8
9
10

import("//third_party/blink/renderer/modules/modules.gni")

blink_modules_sources("example") {
sources = [
"example.cc",
"example.h",
]
}

2 在third_party\blink\renderer\modules\BUILD.gn文件的deps变量里添加以下内容确保example模块被编译

1
"//third_party/blink/renderer/modules/example",

3 在third_party\blink\renderer\modules\modules_idl_files.gni文件的modules_idl_files里的get_path_info传入参数中添加以下内容确保idl文件被编译

1
"example/example.idl",

4 在third_party\blink\renderer\bindings\modules\v8\generated.gni文件的generated_modules_callback_function_files变量里添加以下内容确保idl生成的C++文件被编译

1
2
"$bindings_modules_v8_output_dir/v8_finished_callback.cc",
"$bindings_modules_v8_output_dir/v8_finished_callback.h",

验证

chromium编译成功后在console输入以下语句成功后会在10秒后弹出消息

1
2
3
example = new Example()
example.OnFinish((msg)=>{alert(msg)})
example.Start()

参考资料

https://heycam.github.io/webidl/#idl-types

https://www.chromium.org/developers/web-idl-interfaces

https://www.chromium.org/blink/webidl#TOC-Style

https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md#GarbageCollected