Chromium 如何查找已经定义好的mojom函数实现c++

进程通信定义通常都是用.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, &params->blob_url_token, &params.message());
  mojo::internal::Serialize<::content::mojom::NavigationClientAssociatedPtrInfoDataView>(
      in_navigation_client, &params->navigation_client, &params.message());
  mojo::internal::Serialize<mojo::InterfacePtrDataView<::blink::mojom::PolicyContainerHostKeepAliveHandleInterfaceBase>>(
      in_initiator_policy_container_keep_alive_handle, &params->initiator_policy_container_keep_alive_handle, &params.message());
  mojo::internal::Serialize<mojo::InterfaceRequestDataView<::content::mojom::NavigationRendererCancellationListenerInterfaceBase>>(
      in_renderer_cancellation_listener, &params->renderer_cancellation_listener, &params.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;
    }
  }

     

总结:搜索其他模块也是类似,debug/gen目录是mojom文件具体实现,其他的是发送和接收实现,找到对应参数定义函数即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值