进程通信定义通常都是用.mojom文件或者idl文件格式
以content\common\frame.mojom里面的BeginNavigation函数为例。
一、如何查找BeginNavigation函数定义,在vscode里面直接搜索BeginNavigation,过滤条件
*.idl,*.mojom,*.cc
效果:
这样定义mojom找到了。
content\common\frame.mojom定义如下(截取部分):
// Sent by the renderer to request a navigation.
// |blob_url_token| should be non-null when this is a navigation to a blob:
// URL. The token will then be used to look up the blob associated with the
// blob URL. Without this by the time the navigation code starts fetching
// the URL the blob URL might no longer be valid. |blob_url_token| is
// not part of BeginNavigationParams because that struct needs to be
// cloneable, and thus can't contain mojo interfaces.
// If an invalid BlobURLToken is passed in, or if the token doesn't match the
// url in |common_params|, the navigation will result in a network error.
// |navigation_client| is passed to the renderer to allow for further control
// of the navigation. Allows for Commit and Cancels/Aborts.
// Passing the |initiator_policy_container_keep_alive_handle| is just a means
// to ensure that the PolicyContainerHost of the initiator RenderFrameHost is
// kept alive, even if the RenderFrameHost itself has already been deleted in
// the meantime. If this can be ensured in other ways, it is safe to pass a
// mojo::NullRemote. In particular, if the initiator LocalFrame is alive when
// issuing this mojo call, there is no need to pass
// |initiator_policy_container_keep_alive_handle|, since the initiator
// PolicyContainerHost is kept alive by LocalFrame's PolicyContainer.
// TODO(https://crbug.com/1467502): |navigation_client| should not be
// optional. Make it mandatory.
// |renderer_cancellation_listener| is a per-navigation interface used to
// listen to the end of the renderer-initiated navigation cancelation window
// for this navigation. See comment for NavigationRendererCancellationListener
// for more details.
BeginNavigation(
blink.mojom.CommonNavigationParams common_params,
blink.mojom.BeginNavigationParams begin_params,
pending_remote<blink.mojom.BlobURLToken>? blob_url_token,
pending_associated_remote<NavigationClient>? navigation_client,
pending_remote<blink.mojom.PolicyContainerHostKeepAliveHandle>?
initiator_policy_container_keep_alive_handle,
pending_receiver<NavigationRendererCancellationListener>
renderer_cancellation_listener);
注意mojom文件编译时候会自动生成以下两个文件
out\Debug\gen\content\common\frame.mojom.cc
out\Debug\gen\content\common\frame.mojom.h
二、在vscode搜索BeginNavigation实现代码
第一部分、out\Debug\gen\+对应mojom文件相对目录.h这样存放
例子: out\Debug\gen\content\common\frame.mojom.h
out\Debug\gen\content\common\frame.mojom.cc
1)、发送方会调用在 ::mojo::internal::SendMojoMessage前设置好message.set_method_name("BeginNavigation");
知道此处打断点即可,可以不用想继续搜索发送方是谁了。
看下规律frame.mojom.cc
void FrameHostProxy::BeginNavigation(
::blink::mojom::CommonNavigationParamsPtr in_common_params, ::blink::mojom::BeginNavigationParamsPtr in_begin_params, ::mojo::PendingRemote<::blink::mojom::BlobURLToken> in_blob_url_token, ::mojo::PendingAssociatedRemote<::content::mojom::NavigationClient> in_navigation_client, ::mojo::PendingRemote<::blink::mojom::PolicyContainerHostKeepAliveHandle> in_initiator_policy_container_keep_alive_handle, ::mojo::PendingReceiver<NavigationRendererCancellationListener> in_renderer_cancellation_listener) {
#if BUILDFLAG(MOJO_TRACE_ENABLED)
TRACE_EVENT1(
"mojom", "Send content::mojom::FrameHost::BeginNavigation", "input_parameters",
[&](perfetto::TracedValue context){
auto dict = std::move(context).WriteDictionary();
perfetto::WriteIntoTracedValueWithFallback(
dict.AddItem("common_params"), in_common_params,
"<value of type ::blink::mojom::CommonNavigationParamsPtr>");
perfetto::WriteIntoTracedValueWithFallback(
dict.AddItem("begin_params"), in_begin_params,
"<value of type ::blink::mojom::BeginNavigationParamsPtr>");
perfetto::WriteIntoTracedValueWithFallback(
dict.AddItem("blob_url_token"), in_blob_url_token,
"<value of type ::mojo::PendingRemote<::blink::mojom::BlobURLToken>>");
perfetto::WriteIntoTracedValueWithFallback(
dict.AddItem("navigation_client"), in_navigation_client,
"<value of type ::mojo::PendingAssociatedRemote<::content::mojom::NavigationClient>>");
perfetto::WriteIntoTracedValueWithFallback(
dict.AddItem("initiator_policy_container_keep_alive_handle"), in_initiator_policy_container_keep_alive_handle,
"<value of type ::mojo::PendingRemote<::blink::mojom::PolicyContainerHostKeepAliveHandle>>");
perfetto::WriteIntoTracedValueWithFallback(
dict.AddItem("renderer_cancellation_listener"), in_renderer_cancellation_listener,
"<value of type ::mojo::PendingReceiver<NavigationRendererCancellationListener>>");
});
#endif
const bool kExpectsResponse = false;
const bool kIsSync = false;
const bool kAllowInterrupt = true;
const bool is_urgent = false;
const uint32_t kFlags =
((kExpectsResponse) ? mojo::Message::kFlagExpectsResponse : 0) |
((kIsSync) ? mojo::Message::kFlagIsSync : 0) |
((kAllowInterrupt) ? 0 : mojo::Message::kFlagNoInterrupt) |
((is_urgent) ? mojo::Message::kFlagIsUrgent : 0);
mojo::Message message(
internal::kFrameHost_BeginNavigation_Name, kFlags, 0, 0, nullptr);
mojo::internal::MessageFragment<
::content::mojom::internal::FrameHost_BeginNavigation_Params_Data> params(
message);
params.Allocate();
mojo::internal::MessageFragment<
typename decltype(params->common_params)::BaseType> common_params_fragment(
params.message());
mojo::internal::Serialize<::blink::mojom::CommonNavigationParamsDataView>(
in_common_params, common_params_fragment);
params->common_params.Set(
common_params_fragment.is_null() ? nullptr : common_params_fragment.data());
MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
params->common_params.is_null(),
mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
"null common_params in FrameHost.BeginNavigation request");
mojo::internal::MessageFragment<
typename decltype(params->begin_params)::BaseType> begin_params_fragment(
params.message());
mojo::internal::Serialize<::blink::mojom::BeginNavigationParamsDataView>(
in_begin_params, begin_params_fragment);
params->begin_params.Set(
begin_params_fragment.is_null() ? nullptr : begin_params_fragment.data());
MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
params->begin_params.is_null(),
mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
"null begin_params in FrameHost.BeginNavigation request");
mojo::internal::Serialize<mojo::InterfacePtrDataView<::blink::mojom::BlobURLTokenInterfaceBase>>(
in_blob_url_token, ¶ms->blob_url_token, ¶ms.message());
mojo::internal::Serialize<::content::mojom::NavigationClientAssociatedPtrInfoDataView>(
in_navigation_client, ¶ms->navigation_client, ¶ms.message());
mojo::internal::Serialize<mojo::InterfacePtrDataView<::blink::mojom::PolicyContainerHostKeepAliveHandleInterfaceBase>>(
in_initiator_policy_container_keep_alive_handle, ¶ms->initiator_policy_container_keep_alive_handle, ¶ms.message());
mojo::internal::Serialize<mojo::InterfaceRequestDataView<::content::mojom::NavigationRendererCancellationListenerInterfaceBase>>(
in_renderer_cancellation_listener, ¶ms->renderer_cancellation_listener, ¶ms.message());
MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
!mojo::internal::IsHandleOrInterfaceValid(params->renderer_cancellation_listener),
mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
"invalid renderer_cancellation_listener in FrameHost.BeginNavigation request");
#if defined(ENABLE_IPC_FUZZER)
message.set_interface_name(FrameHost::Name_);
message.set_method_name("BeginNavigation");
#endif
// This return value may be ignored as false implies the Connector has
// encountered an error, which will be visible through other means.
::mojo::internal::SendMojoMessage(*receiver_, message);
}
2)、接收方BeginNavigation 定义如下out\Debug\gen\content\common\frame.mojom.cc
有类似这样的字样就是实现方 impl->BeginNavigation
case internal::kFrameHost_BeginNavigation_Name: {
DCHECK(message->is_serialized());
internal::FrameHost_BeginNavigation_Params_Data* params =
reinterpret_cast<internal::FrameHost_BeginNavigation_Params_Data*>(
message->mutable_payload());
bool success = true;
::blink::mojom::CommonNavigationParamsPtr p_common_params{};
::blink::mojom::BeginNavigationParamsPtr p_begin_params{};
::mojo::PendingRemote<::blink::mojom::BlobURLToken> p_blob_url_token{};
::mojo::PendingAssociatedRemote<::content::mojom::NavigationClient> p_navigation_client{};
::mojo::PendingRemote<::blink::mojom::PolicyContainerHostKeepAliveHandle> p_initiator_policy_container_keep_alive_handle{};
::mojo::PendingReceiver<NavigationRendererCancellationListener> p_renderer_cancellation_listener{};
FrameHost_BeginNavigation_ParamsDataView input_data_view(params, message);
if (success && !input_data_view.ReadCommonParams(&p_common_params))
success = false;
if (success && !input_data_view.ReadBeginParams(&p_begin_params))
success = false;
if (success) {
p_blob_url_token =
input_data_view.TakeBlobUrlToken<decltype(p_blob_url_token)>();
}
if (success) {
p_navigation_client =
input_data_view.TakeNavigationClient<decltype(p_navigation_client)>();
}
if (success) {
p_initiator_policy_container_keep_alive_handle =
input_data_view.TakeInitiatorPolicyContainerKeepAliveHandle<decltype(p_initiator_policy_container_keep_alive_handle)>();
}
if (success) {
p_renderer_cancellation_listener =
input_data_view.TakeRendererCancellationListener<decltype(p_renderer_cancellation_listener)>();
}
if (!success) {
ReportValidationErrorForMessage(
message,
mojo::internal::VALIDATION_ERROR_DESERIALIZATION_FAILED,
FrameHost::Name_, 5, false);
return false;
}
// A null |impl| means no implementation was bound.
DCHECK(impl);
impl->BeginNavigation(
std::move(p_common_params),
std::move(p_begin_params),
std::move(p_blob_url_token),
std::move(p_navigation_client),
std::move(p_initiator_policy_container_keep_alive_handle),
std::move(p_renderer_cancellation_listener));
return true;
}
第二部分、子进程定义
content\renderer\render_frame_impl.cc
GetFrameHost()->BeginNavigation(
MakeCommonNavigationParams(frame_->GetSecurityOrigin(), std::move(info),
load_flags, has_download_sandbox_flag, from_ad,
is_history_navigation_in_new_child_frame,
request_destination),
std::move(begin_navigation_params), std::move(blob_url_token),
std::move(navigation_client_remote),
std::move(initiator_policy_container_keep_alive_handle),
std::move(renderer_cancellation_listener_receiver));
其中GetFrameHost()和FrameHostProxy对应关系很是巧妙。
mojom::FrameHost* RenderFrameImpl::GetFrameHost() {
if (!frame_host_remote_.is_bound())
GetRemoteAssociatedInterfaces()->GetInterface(&frame_host_remote_);
return frame_host_remote_.get();
}
FrameHost和FrameHostProxy是同一个类吗?
先看mojo::AssociatedRemote<mojom::FrameHost> frame_host_remote_;定义
其中用模板对象AssociatedRemote初始化,那么看下定义
template <typename Interface>
class AssociatedRemote {
public:
using InterfaceType = Interface;
using PendingType = PendingAssociatedRemote<Interface>;
using Proxy = typename Interface::Proxy_;
mojo::AssociatedRemote类的Proxy替换完之后是mojom::FrameHost::Proxy_;
那么在看FrameHost定义
class CONTENT_EXPORT FrameHost
: public FrameHostInterfaceBase {
public:
using IPCStableHashFunction = uint32_t(*)();
static const char Name_[];
static IPCStableHashFunction MessageToMethodInfo_(mojo::Message& message);
static const char* MessageToMethodName_(mojo::Message& message);
static constexpr uint32_t Version_ = 0;
static constexpr bool PassesAssociatedKinds_ = true;
static inline constexpr uint32_t kSyncMethodOrdinals[] = {
0
};
static constexpr bool HasUninterruptableMethods_ = false;
using Base_ = FrameHostInterfaceBase;
using Proxy_ = FrameHostProxy;
其中将using Proxy_ = FrameHostProxy;
至此FrameHost和FrameHostProxy完成了关联 其实是一个巧妙的用了模板和using。
这样在mojo::AssociatedRemote类带哦用get函数时候直接获取的是FrameHostProxy。
typename Interface::Proxy_* get() const {
DCHECK(is_bound())
<< "Cannot issue Interface method calls on an unbound AssociatedRemote";
return internal_state_.instance();
}
第三部分、主进程定义
content\browser\renderer_host\render_frame_host_impl.cc
void RenderFrameHostImpl::BeginNavigation(
blink::mojom::CommonNavigationParamsPtr unvalidated_common_params,
blink::mojom::BeginNavigationParamsPtr begin_params,
mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token,
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
mojo::PendingRemote<blink::mojom::PolicyContainerHostKeepAliveHandle>
initiator_policy_container_host_keep_alive_handle,
mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
renderer_cancellation_listener) {
TRACE_EVENT("navigation", "RenderFrameHostImpl::BeginNavigation",
ChromeTrackEvent::kRenderFrameHost, this, "url",
unvalidated_common_params->url.possibly_invalid_spec());
// Only active and prerendered documents are allowed to start navigation in
// their frame.
if (lifecycle_state() != LifecycleStateImpl::kPrerendering) {
// If this is reached in case the RenderFrameHost is in BackForwardCache
// evict the document from BackForwardCache.
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kBeginNavigation)) {
return;
}
}