Chromium Mojo消息管道的創建和使用文檔

Chromium Mojo 消息管道的創建和使用

版本 備註 編寫人 時間
V1.0 初稿 wangnn01 2020-1-9

一、Mojo 消息管道(無響應)

S1 render 端

1.定義接口

​ 在src/services/spider_mojo/ mojom/spider_mojo.mojom中創建以下Mojom文件,來定義一個簡單的Logger接口,客戶端可以使用該接口來輸出簡單的字符串消息:

1.	module spider_mojo.mojom;  
2.	  
3.	interface Logger{  
4.	    Log(string message);  
5.	};  

還有一個GN目標(src/services/spider_mojo/ mojom/BUILD.gn)用來生成綁定:

1.	import("//mojo/public/tools/bindings/mojom.gni")  
2.	mojom("mojom") {  
3.	  sources = [ "spider_mojo.mojom" ]  
4.	}  

確保需要此接口的任何目標都依賴於此接口,例如,在對應模塊的BUILD.gn中添加像這樣的一行:

1.	deps += [ '//services/spider_mojo/mojom' ]  

​ 例如,在本示例中,render和browser進程中都需要Logger接口,因此需要在兩個進程各自對應的模塊中添加依賴,後面會詳細講述。

注:*.mojom

​ .mojom 是 mojo 的模板文件, mojo 類似於 Android 的 AIDL ,提供了跨語言(C++ / Java / JavaScript)的進程間對象(Object)通信機制, mojom 文件也類似於 aidl 文件,會生成進程間通信對象的抽象接口以及其底層的 IPC 實現。

2.創建管道&發送消息&發送一個PendingReceiver 至Browser

​ 本示例中,我們在src/third_party/blink/renderer/core/html/parser/html_construction_site.cc的函數HTMLConstructionSite::FinishedParsing中添加如下代碼:

1.	//創建消息管道
2.	mojo::Remote<spider_mojo::mojom::Logger> remote;  
3.	mojo::PendingReceiver<spider_mojo::mojom::Logger> receiver = remote.BindNewPipeAndPassReceiver();  
4.	//發送消息
5.	remote->Log("Hello");  
6.	//發送一個PendingReceiver到Browser
7.	document_->GetBrowserInterfaceBroker().GetInterface(std::move(receiver));  

​ 注意:爲了使用mojo相關的方法,還需在src/third_party/blink/renderer/core/html/parser/html_construction_site.cc中添加相應頭文件:

1.	#include "services/spider_mojo/mojom/spider_mojo.mojom.h"  
2.	//spider_mojo_impl.h爲接口Logger的實現,在browser進程中定義,後續會詳細講述
3.	#include "content/browser/spider_mojo/spider_mojo_impl.h"  

​ 在src/third_party/blink/renderer/core/html/parser/BUILD.gn中添加對接口Logger的依賴:

deps+={
    "//services/spider_mojo/mojom"
}

​ render端的操作已完成,接下來是browser端。

S2 browser端

1.實現接口

​ 本示例中,在src/content/browser中新建文件夾“spider_mojo”,並在該文件夾中新建spider_mojo_impl.h和spider_mojo_impl.cc。

​ 其中,spider_mojo_impl.h的內容:

1.	#include "base/logging.h"  
2.	#include "base/macros.h"  
3.	#include "mojo/public/cpp/bindings/receiver.h"  
4.	#include "mojo/public/cpp/bindings/binding.h"  
5.	#include "mojo/public/cpp/bindings/interface_request.h"  
6.	#include "services/spider_mojo/mojom/spider_mojo.mojom.h"  
7.	  
8.	namespace content{  
9.	class LoggerImpl : public spider_mojo::mojom::Logger {  
10.	 public:  
11.	  // NOTE: A common pattern for interface implementations which have one  
12.	  // instance per client is to take a PendingReceiver in the constructor.  
13.	  
14.	  explicit LoggerImpl(mojo::PendingReceiver<spider_mojo::mojom::Logger> receiver);  
15.	   
16.	  ~LoggerImpl() override;  
17.	  
18.	  // spider_mojo::mojom::Logger:  
19.	  void Log(const std::string& message) override;  
20.	  
21.	 private:  
22.	  mojo::Receiver<spider_mojo::mojom::Logger> receiver_;  
23.	  
24.	  DISALLOW_COPY_AND_ASSIGN(LoggerImpl);  
25.	};  
26.	} //namespace content  

​ spider_mojo_impl.cc的內容:

1.	#include "content/browser/spider_mojo/spider_mojo_impl.h"  
2.	#include <utility>  
3.	#include "base/bind.h"  
4.	  
5.	namespace content{  
6.	LoggerImpl::LoggerImpl(mojo::PendingReceiver<spider_mojo::mojom::Logger> receiver)  
7.	    : receiver_(this, std::move(receiver)) {}  
8.	  
9.	LoggerImpl::~LoggerImpl(){}  
10.	  
11.	void LoggerImpl::Log(const std::string& message) {  
12.	  LOG(INFO) << "[Logger] " << message;  
13.	}  
14.	} // namespace content  

​ 在src/content/browser/BUILD.gn中相應位置添加依賴deps以及source:

1.	deps += [  
2.	"//services/spider_mojo/mojom",  
3.	]  
...
1.	sources += [  
2.	    "spider_mojo/spider_mojo_impl.h",  
3.	    "spider_mojo/spider_mojo_impl.cc",  
4.	]  

2.註冊接口

注:*號爲前綴的代碼行需新添加。

1.	//src/content/browser/frame_host/render_frame_host_impl.h
2.	...  
3.	*#include "services/spider_mojo/mojom/spider_mojo.mojom.h"
4.	*#include "content/browser/spider_mojo/spider_mojo_impl.h"  
5.	...  
6.	  
7.	namespace content {  
8.	...  
9.	*class LoggerImpl;  
10.	...  
11.	class CONTENT_EXPORT RenderFrameHostImpl{  
12.	public:  
13.	...  
14.	*void GetLogger(mojo::PendingReceiver<spider_mojo::mojom::Logger> receiver);  
15.	...  
16.	private:  
17.	...  
18.	*std::unique_ptr<LoggerImpl> logger_;  
19.	...  
20.	};  

1.	//src/content/browser/frame_host/render_frame_host_impl.cc  
2.	...  
3.	* void RenderFrameHostImpl::GetLogger(mojo::PendingReceiver<spider_mojo::mojom::Logger> receiver){  
4.	      * logger_ = std::make_unique<LoggerImpl>(std::move(receiver));  
5.	      * LOG(INFO) << "Launching Successfully";  
6.      *}
1.	//src/content/browser/browser_interface_binders.cc  
2.	...  
3.	* #include "services/spider_mojo/mojom/spider_mojo.mojom.h"  
4.	...  
5.	// Documents/frames  
6.	void PopulateFrameBinders(RenderFrameHostImpl* host,  
7.	                          service_manager::BinderMap* map) {  
8.	...  
9.	* map->Add<spider_mojo::mojom::Logger>(base::BindRepeating(  
10.	      &RenderFrameHostImpl::GetLogger,base::Unretained(host)));  
11.	...  
12.	}  

S3 編譯

1.編譯生成接口對應的源文件

​ 使用ninja編譯目標:

1.	//在src/out/default目錄下執行  
2.	ninja services/spider_mojo/mojom 

​ 執行完畢後,將會在src/out/Defaul/gen/service中生成相應的文件夾“spider_mojo”,該文件夾中包含生成的一些源文件:

2.編譯content模塊

​ 使用ninja編譯:

1.	// 在src/out//Default目錄下執行  
2.	ninja content  

​ 至此,大功告成,編譯後會Log輸出“hello”。

二、Mojo 消息管道(帶響應)

​ 創建過程和無響應的Mojo消息管道類似。

S1 render 端

1.定義接口

​ 在src/services/spider_mojo/ mojom/spider_mojo.mojom中創建以下Mojom文件,來定義一個簡單的Logger接口,客戶端可以使用該接口來輸出簡單的字符串消息:

module blink.mojom;

interface Logger{
    Log(string message);  
    GetTail() => (string message);  
}; 

​ 還有一個GN目標(src/services/spider_trans/ mojom/BUILD.gn)用來生成綁定:

import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
  sources = [ "spider_mojo.mojom" ]
} 

​ 確保需要此接口的任何目標都依賴於此接口,例如,在對應模塊的BUILD.gn中添加像這樣的一行:

1.	deps += [ '//services/spider_mojo/mojom' ]  

​ 例如,在本示例中,render和browser進程中都需要Logger接口,因此需要在兩個進程各自對應的模塊中添加依賴,後面會詳細講述。

注:*.mojom

​ .mojom 是 mojo 的模板文件, mojo 類似於 Android 的 AIDL ,提供了跨語言(C++ / Java / JavaScript)的進程間對象(Object)通信機制, mojom 文件也類似於 aidl 文件,會生成進程間通信對象的抽象接口以及其底層的 IPC 實現。

2.創建管道&發送消息&發送一個PendingReceiver 至Browser

​ 本示例中,我們在src/third_party/blink/renderer/core/html/parser/html_construction_site.cc中添加如下代碼:

void HTMLConstructionSite::OnGetTail(const std::string& message) {  
	LOG(ERROR) << "Tail was: " << message;  
}  
...
void HTMLConstructionSite::FinishedParsing(){
    ...
    //創建消息管道
    mojo::Remote<spider_mojo::mojom::Logger> remote; 
    mojo::PendingReceiver<spider_mojo::mojom::Logger> receiver = remote.BindNewPipeAndPassReceiver();   
    //發送一個PendingReceiver到Browser
    document_->GetBrowserInterfaceBroker().GetInterface(std::move(receiver));  
    //發送消息
    remote->Log("Hello"); 
    //獲得響應
    remote->GetTail(base::BindOnce(&OnGetTail) ,base::Unretained(this));  
    ...  
}

​ 注意:爲了使用mojo相關的方法,還需在src/third_party/blink/renderer/core/html/parser/html_construction_site.cc中添加相應頭文件:

1.	#include "services/spider_mojo/mojom/spider_mojo.mojom.h"  
2.	//spider_mojo_impl.h爲接口Logger的實現,在browser進程中定義,後續會詳細講述
3.	#include "content/browser/spider_mojo/spider_mojo_impl.h"  

​ 在src/third_party/blink/renderer/core/html/parser/BUILD.gn中添加對接口Logger的依賴:

deps+={
    "//services/spider_mojo/mojom"
}

​ render端的操作已完成,接下來是browser端。

S2 browser端

1.實現接口

本示例中,在src/content/browser中新建文件夾“spider_mojo”,並在該文件夾中新建spider_mojo_impl.h和spider_mojo_impl.cc。

​ 其中,spider_mojo_impl.h的內容:

#include "base/logging.h"  
#include "base/macros.h"  
#include "mojo/public/cpp/bindings/receiver.h"  
#include "mojo/public/cpp/bindings/binding.h"  
#include "mojo/public/cpp/bindings/interface_request.h"  
#include "services/spider_mojo/mojom/spider_mojo.mojom.h" 	
namespace content{  
	class LoggerImpl : public spider_mojo::mojom::Logger {  
	 public:  
	  // NOTE: A common pattern for interface implementations which have one  
	  // instance per client is to take a PendingReceiver in the constructor.  
	  explicit LoggerImpl(mojo::PendingReceiver<spider_mojo::mojom::Logger> receiver); 	 	   ~LoggerImpl() override;  
      // spider_mojo::mojom::Logger:  
      void Log(const std::string& message) override;  
      void GetTail(GetTailCallback callback) override;
	 private:  
	  mojo::Receiver<spider_mojo::mojom::Logger> receiver_;  
      std::string response;
	  DISALLOW_COPY_AND_ASSIGN(LoggerImpl);  
	};  
} //namespace content      

​ spider_mojo_impl.cc的內容:

#include "content/browser/spider_mojo/spider_mojo_impl.h"  
#include <utility>  
#include "base/bind.h"  

namespace content{  
    LoggerImpl::LoggerImpl(mojo::PendingReceiver<spider_mojo::mojom::Logger> receiver)  
        : receiver_(this, std::move(receiver)) {}  

    LoggerImpl::~LoggerImpl(){}  

    void LoggerImpl::Log(const std::string& message) {  
      LOG(INFO) << "[Logger] " << message;  
      response = message;
    }  
    
    void GetTail(GetTailCallback callback) {  
	  std::move(callback).Run(response);  
	}  

} // namespace content  

​ 在src/content/browser/BUILD.gn中相應位置添加依賴deps以及source:

1.	deps += [  
2.	"//services/spider_mojo/mojom",  
3.	]  
...
1.	sources += [  
2.	    "spider_mojo/spider_mojo_impl.h",  
3.	    "spider_mojo/spider_mojo_impl.cc",  
4.	]  

2.註冊接口

注:*號爲前綴的代碼行需新添加。

1.	//src/content/browser/frame_host/render_frame_host_impl.h
2.	...  
3.	*#include "services/spider_mojo/mojom/spider_mojo.mojom.h"
4.	*#include "content/browser/spider_mojo/spider_mojo_impl.h"  
5.	...  
6.	  
7.	namespace content {  
8.	...  
9.	*class LoggerImpl;  
10.	...  
11.	class CONTENT_EXPORT RenderFrameHostImpl{  
12.	public:  
13.	...  
14.	*void GetLogger(mojo::PendingReceiver<spider_mojo::mojom::Logger> receiver);  
15.	...  
16.	private:  
17.	...  
18.	*std::unique_ptr<LoggerImpl> logger_;  
19.	...  
20.	};  

1.	//src/content/browser/frame_host/render_frame_host_impl.cc  
2.	...  
3.	* void RenderFrameHostImpl::GetLogger(mojo::PendingReceiver<spider_mojo::mojom::Logger> receiver){  
4.	      * logger_ = std::make_unique<LoggerImpl>(std::move(receiver));  
5.	      * LOG(INFO) << "Launching Successfully";  
6.      *}
1.	//src/content/browser/browser_interface_binders.cc  
2.	...  
3.	* #include "services/spider_mojo/mojom/spider_mojo.mojom.h"  
4.	...  
5.	// Documents/frames  
6.	void PopulateFrameBinders(RenderFrameHostImpl* host,  
7.	                          service_manager::BinderMap* map) {  
8.	...  
9.	* map->Add<spider_mojo::mojom::Logger>(base::BindRepeating(  
10.	      &RenderFrameHostImpl::GetLogger,base::Unretained(host)));  
11.	...  
12.	}  

S3 編譯

1.編譯生成接口對應的源文件

​ 使用ninja編譯目標:

1.	//在src/out/default目錄下執行  
2.	ninja services/spider_mojo/mojom 

​ 執行完畢後,將會在src/out/Defaul/gen/service中生成相應的文件夾“spider_mojo”,該文件夾中包含生成的一些源文件:

2.編譯content模塊

​ 使用ninja編譯:

1.	// 在src/out//Default目錄下執行  
2.	ninja content  

​ 至此,大功告成,編譯後會Log輸出“hello”和 "Tail was: hello "

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章