Chromium 通過IDL方式新增擴充套件API

2023-10-21 12:00:22

基於chromium103版本

1. 自定義擴充套件API介面

chromium預設擴充套件api介面中有chrome.runtime.*,和chrome.send.*等,現在我們就仿照chrome.runtime方式來定義自己的介面,供給外掛或者網頁使用。

其實chromium 增加自定義 api 介面,在原生程式碼中新增有兩種方式,一種是使用json定義,另外一種是使用idl定義。json方式比較繁瑣,不太便利,新版本chromium基本推薦使用IDL方式來定義介面。

原生的api介面程式碼根據作用不同,分佈在不同位置:

chrome使用的API所在位置(檔案路徑在src/chrome/browser/extensions/):

1 chrome\browser\extensions\api
2 chrome\browser\extensions\*
3 chrome\common\extensions\api
4 chrome\common\extensions\*

chrome公共使用所在位置(檔案路徑在src/extensions/browser/):

1 extensions\*
2 extensions\browser\api
3 extensions\common\api
4 extensions\common\mojom

2. 自定義一個介面myInterface.print

3.  新增一個myInterface.idl檔案

src\chrome\common\extensions\api\myInterface.idl

 1 // Use the <code>chrome.myInterface</code> API to myInterface
 2 namespace myInterface{
 3   // myInterface State.
 4   enum EchoState {
 5     OK,
 6     ERROR
 7   };
 8   callback EchoStateCallback = void(EchoState state, DOMString out);
 9 
10   interface Functions {
11     // pring string.
12     static void print(DOMString input, EchoStateCallback callback);
13   };
14 };

4. 實現C++介面標頭檔案(在下面檔案路徑新增一個myInterface.h)

src\chrome\browser\extensions\api\myInterface\myInterface_api.h

 1 #ifndef CHROME_BROWSER_EXTENSIONS_API_MYINTERFACE_MYINTERFACE_API_H_
 2 #define CHROME_BROWSER_EXTENSIONS_API_MYINTERFACE_MYINTERFACE_API_H_
 3 
 4 #include "extensions/browser/extension_function.h"
 5 
 6 namespace extensions {
 7 
 8 class MyInterfacePrintFunction : public ExtensionFunction {
 9  public:
10   MyInterfacePrintFunction () = default;
11   MyInterfacePrintFunction (
12       const MyInterfacePrintFunction &) = delete;
13   MyInterfacePrintFunction & operator=(
14       const MyInterfacePrintFunction &) = delete;
15   DECLARE_EXTENSION_FUNCTION("myInterface.print", MYINTERFACE_PRINT)
16 
17  protected:
18   ~MyInterfacePrintFunction () override = default;
19 
20   // ExtensionFunction overrides.
21   ResponseAction Run() override;
22 };
23 
24 
25 }  // namespace extensions
26 
27 #endif  // CHROME_BROWSER_EXTENSIONS_API_MYINTERFACE_MYINTERFACE_API_H_

5. 實現C++介面CC檔案(在下面檔案路徑新增一個myInterface.cc)

src\chrome\browser\extensions\api\myInterface\myInterface_api.cc

 1 #include "chrome/browser/extensions/api/myInterface/myInterface_api.h"
 2 // 這個是自動生成的,在目錄"gen\chrome\common\extensions\api"下
 3 #include "chrome/common/extensions/api/myInterface.h"
 4 
 5 namespace extensions {
 6 
 7 //MyInterfacePrintFunction
 8 ExtensionFunction::ResponseAction MyInterfacePrintFunction::Run() {
 9   std::unique_ptr<api::myInterface::print::Params> param =
10       api::myInterface::print::Params::Create(*args_);
11   EXTENSION_FUNCTION_VALIDATE(param.get());
12   
13   return RespondNow(ArgumentList(
14   api::myInterface::print::Results::Create(api::myInterface::EchoState::ECHO_STATE_OK, "echo " + param->input)));
15 }
16 
17 }  // namespace extensions

6. 新增編譯檔案

src\chrome\browser\extensions\BUILD.gn

1 "api/myInterface/myInterface_api.cc",
2 "api/myInterface/myInterface_api.h",

7. 設定 api 介面許可權

在 _api_features.json 檔案末尾新增如下內容:

src\chrome\common\extensions\api\_api_features.json

1 ,
2   "myInterface": [{
3     "channel": "stable",
4     "contexts": ["blessed_extension"]
5   }, {
6     "contexts": "all",
7     "channel": "stable",
8     "matches": ["<all_urls>"]
9   }]

在 _permission_features.json檔案末尾新增如下內容:

src\chrome\common\extensions\api\_permission_features.json 

1 ,
2   "myInterface": {
3     "channel": "stable",
4     "extension_types": ["extension", "legacy_packaged_app", "hosted_app", "platform_app"]
5   }

8. 新增介面定義檔案編譯項

在api_sources.gni新增中介面定義檔案:
src\chrome\common\extensions\api\api_sources.gni

1 schema_sources_ = [
2 ...
3 myInterface.idl,
4 ]

在 src\chrome\common\extensions\api\generated_externs_list.txt 末尾新增 afree.idl

9. 新增註冊資訊及常數定義

在src\chrome\common\extensions\permissions\chrome_api_permissions.cc檔案中,找到constexpr APIPermissionInfo::InitInfo permissions_to_register[] =,新增如下內容:

constexpr APIPermissionInfo::InitInfo permissions_to_register[] = {
...
    {APIPermissionID::kMyInterface, "myInterface"},
};

在 src\extensions\browser\extension_function_histogram_value.h 檔案宏定義末尾根據具體宏定義的值新增自己的宏定義,在最大值的基礎上加1

1 enum HistogramValue {
2 ...
3   AUTOTESTPRIVATE_ACTIVATEAPPWINDOW = 1864,
4   MYINTERFACE_PRINT = 1865,
5   // Last entry: Add new entries above, then run:
6   // python tools/metrics/histograms/update_extension_histograms.py
7   ENUM_BOUNDARY
8 };

10. 定義 APIPermissionID 值

src\extensions\common\mojom\api_permission_id.mojom 中,定義自己的 api id,在最大值的基礎上加1

1 enum APIPermissionID {
2 ...
3   kScripting = 566,
4   kMyInterface= 567,
...
5 }

11. 編譯生成即可

ninja -C out\DebugX64 chrome

12. 呼叫方法

chrome.myInterface.print("hello world",function(state,out){console.log(state,out)})