articles icon indicating copy to clipboard operation
articles copied to clipboard

005-chromium mojo调用方代码定位

Open xinali opened this issue 1 year ago • 0 comments

本文主要是我在调试chromium代码中,遇到不知道如何找到mojo调用方代码所做的测试,主要以NetworkService为案例,其他mojo也相同

本文所有源码均来源于chromium公开的开源代码

案例

在调试过程中有如下日志输出

[19984:17852:1102/101508.140:INFO:cert_verifier.cc(85)] chromium(STACK): CreateDefaultBacktrace:
	base::debug::CollectStackTrace [0x00007FFDA9A06FB0+48] (G:\codes\chrome_79\src\base\debug\stack_trace_win.cc:284)
	base::debug::StackTrace::StackTrace [0x00007FFDA9A06120+80] (G:\codes\chrome_79\src\base\debug\stack_trace.cc:206)
	base::debug::StackTrace::StackTrace [0x00007FFDA9A060A8+40] (G:\codes\chrome_79\src\base\debug\stack_trace.cc:203)
	// 代码定位
	net::CertVerifier::CreateDefault [0x00007FFDA88A82A4+68] (G:\codes\chrome_79\src\net\cert\cert_verifier.cc:85)
	network::NetworkContext::MakeURLRequestContext [0x00007FFD78B05403+291] (G:\codes\chrome_79\src\services\network\network_context.cc:1591)
	network::NetworkContext::NetworkContext [0x00007FFD78B04512+1330] (G:\codes\chrome_79\src\services\network\network_context.cc:350)
	std::__1::make_unique<network::NetworkContext,network::NetworkService *,mojo::PendingReceiver<network::mojom::NetworkContext>,mojo::StructPtr<network::mojom::NetworkContextParams>,base::OnceCallback<void (network::NetworkContext *)> > [0x00007FFD78B778BF+255] (G:\codes\chrome_79\src\buildtools\third_party\libc++\trunk\include\memory:3131)
	network::NetworkService::CreateNetworkContext [0x00007FFD78B776C3+403] (G:\codes\chrome_79\src\services\network\network_service.cc:407)
	network::mojom::NetworkServiceStubDispatch::Accept [0x00007FFD78EAE6B4+4372] (G:\codes\chrome_79\src\out\Release\gen\services\network\public\mojom\network_service.mojom.cc:2412)
	network::mojom::NetworkServiceStub<mojo::RawPtrImplRefTraits<network::mojom::NetworkService> >::Accept [0x00007FFD78B7F9B2+98] (G:\codes\chrome_79\src\out\Release\gen\services\network\public\mojom\network_service.mojom.h:399)
	mojo::InterfaceEndpointClient::HandleValidatedMessage [0x00007FFDB4D57786+1862] (G:\codes\chrome_79\src\mojo\public\cpp\bindings\lib\interface_endpoint_client.cc:553)
	mojo::InterfaceEndpointClient::HandleIncomingMessageThunk::Accept [0x00007FFDB4D57031+33] (G:\codes\chrome_79\src\mojo\public\cpp\bindings\lib\interface_endpoint_client.cc:140)
	mojo::MessageDispatcher::Accept [0x00007FFDB4D67F68+344] (G:\codes\chrome_79\src\mojo\public\cpp\bindings\lib\message_dispatcher.cc:41)
	mojo::InterfaceEndpointClient::HandleIncomingMessage [0x00007FFDB4D5A598+216] (G:\codes\chrome_79\src\mojo\public\cpp\bindings\lib\interface_endpoint_client.cc:356)
	mojo::internal::MultiplexRouter::ProcessIncomingMessage [0x00007FFDB4D6DB2F+1663] (G:\codes\chrome_79\src\mojo\public\cpp\bindings\lib\multiplex_router.cc:876)
	mojo::internal::MultiplexRouter::Accept [0x00007FFDB4D6D081+673] (G:\codes\chrome_79\src\mojo\public\cpp\bindings\lib\multiplex_router.cc:598)
	mojo::MessageDispatcher::Accept [0x00007FFDB4D67F68+344] (G:\codes\chrome_79\src\mojo\public\cpp\bindings\lib\message_dispatcher.cc:41)
	mojo::Connector::DispatchMessageW [0x00007FFDB4D3EB34+1396] (G:\codes\chrome_79\src\mojo\public\cpp\bindings\lib\connector.cc:604)
	mojo::Connector::ReadAllAvailableMessages [0x00007FFDB4D403C3+675] (G:\codes\chrome_79\src\mojo\public\cpp\bindings\lib\connector.cc:680)
	mojo::Connector::OnHandleReadyInternal [0x00007FFDB4D3FEDD+381] (G:\codes\chrome_79\src\mojo\public\cpp\bindings\lib\connector.cc:515)
	mojo::Connector::OnWatcherHandleReady [0x00007FFDB4D3FD4B+27] (G:\codes\chrome_79\src\mojo\public\cpp\bindings\lib\connector.cc:475)
	base::internal::FunctorTraits<void (mojo::Connector::*)(unsigned int),void>::Invoke<void (mojo::Connector::*)(unsigned int),mojo::Connector *,unsigned int> [0x00007FFDB4D487A5+69] (G:\codes\chrome_79\src\base\bind_internal.h:498)
	base::internal::InvokeHelper<0,void>::MakeItSo<void (mojo::Connector::*const &)(unsigned int),mojo::Connector *,unsigned int> [0x00007FFDB4D486DD+77] (G:\codes\chrome_79\src\base\bind_internal.h:598)
	base::internal::Invoker<base::internal::BindState<void (mojo::Connector::*)(unsigned int),base::internal::UnretainedWrapper<mojo::Connector> >,void (unsigned int)>::RunImpl<void (mojo::Connector::*const &)(unsigned int),const std::__1::tuple<base::interna [0x00007FFDB4D48671+113] (G:\codes\chrome_79\src\base\bind_internal.h:671)
	base::internal::Invoker<base::internal::BindState<void (mojo::Connector::*)(unsigned int),base::internal::UnretainedWrapper<mojo::Connector> >,void (unsigned int)>::Run [0x00007FFDB4D48565+101] (G:\codes\chrome_79\src\base\bind_internal.h:653)
	base::RepeatingCallback<void (unsigned int)>::Run [0x00007FFDB4D36DF8+104] (G:\codes\chrome_79\src\base\callback.h:132)
	...l
	base::Thread::Run [0x00007FFDA9C854AD+381] (G:\codes\chrome_79\src\base\threading\thread.cc:304)
	base::Thread::ThreadMain [0x00007FFDA9C85B4F+1599] (G:\codes\chrome_79\src\base\threading\thread.cc:375)
	base::`anonymous namespace'::ThreadFunc [0x00007FFDA9C7250B+379] (G:\codes\chrome_79\src\base\threading\platform_thread_win.cc:104)
	BaseThreadInitThunk [0x00007FFDE1C27344+20]
	RtlUserThreadStart [0x00007FFDE1F826B1+33]

现在想找到CreateDefault具体的调用者位置,根据上面的日志可以发现CreateDefault是在"网络线程"中被调用,具体由谁发起的,这是我们需要关心的

net::CertVerifier::CreateDefault [0x00007FFDA88A82A4+68] (G:\codes\chrome_79\src\net\cert\cert_verifier.cc:85)
	network::NetworkContext::MakeURLRequestContext [0x00007FFD78B05403+291] (G:\codes\chrome_79\src\services\network\network_context.cc:1591)
	network::NetworkContext::NetworkContext [0x00007FFD78B04512+1330] (G:\codes\chrome_79\src\services\network\network_context.cc:350)
	std::__1::make_unique<network::NetworkContext,network::NetworkService *,mojo::PendingReceiver<network::mojom::NetworkContext>,mojo::StructPtr<network::mojom::NetworkContextParams>,base::OnceCallback<void (network::NetworkContext *)> > [0x00007FFD78B778BF+255] (G:\codes\chrome_79\src\buildtools\third_party\libc++\trunk\include\memory:3131)
	network::NetworkService::CreateNetworkContext 

根据日志找到如下mojom定义


struct LoadInfo {
  uint32 process_id;
  uint32 routing_id;
  string host;
  uint32 load_state;  // net::LoadState enum
  mojo_base.mojom.String16 state_param;
  uint64 upload_position;
  uint64 upload_size;
};

// Network service interface to the browser.
// network接口发送到browser接口
interface NetworkServiceClient {
  // Called periodically to update the client about progress of the current
  // loads. To avoid flooding the client, it has to ack the update before it can
  // receive the next update.
  OnLoadingStateUpdate(array<LoadInfo> infos) => ();

  // Called to send raw header information and information about excluded
  // cookies. Only called when |devtool_request_id| is available to the
  // URLLoader.
  OnRawRequest(
    int32 process_id,
    int32 routing_id,
    string devtool_request_id,
    array<CookieWithStatus> cookies_with_status,
    array<HttpRawHeaderPair> headers);

  // Called to send information about the cookies blocked from storage from a
  // received response. Only called when |devtool_request_id| is available to
  // the URLLoader.
  OnRawResponse(
    int32 process_id,
    int32 routing_id,
    string devtool_request_id,
    array<CookieAndLineWithStatus> cookies_with_status,
    array<HttpRawHeaderPair> headers,
    string? raw_response_headers);
};

// ...

// Parameters needed to initialize the network service.
struct NetworkServiceParams {
  ConnectionType initial_connection_type = CONNECTION_UNKNOWN;
  ConnectionSubtype initial_connection_subtype = SUBTYPE_UNKNOWN;

  // A set of environment variables that should be set in the network
  // service when starting up.
  array<EnvironmentVariable> environment;
};

// Information about how logging should be configured.
// Corresponds to logging::LoggingSettings.
[EnableIf=is_chromeos]
struct LoggingSettings {
  uint32 logging_dest;
  handle log_file_descriptor;
};

// Browser interface to the network service.
// browser接口发送数据到network接口
interface NetworkService {
  // Sets client used by all |NetworkContext|s creating by |NetworkService|.
  // Pending requests may hang if the |client| pipe is closed before they
  // complete.
  SetClient(pending_remote<NetworkServiceClient> client,
            NetworkServiceParams params);

  // Reinitializes the Network Service's logging with the given settings. This
  // is needed on Chrome OS, which switches to a log file in the user's home
  // directory once they log in.
  [EnableIf=is_chromeos]
  ReinitializeLogging(LoggingSettings settings);

  // Starts logging SSL key material to the |file|. This must be called before
  // any SSL connections are made. (See |SSLClientSocket::SetSSLKeyLogger()|
  // for more details).
  SetSSLKeyLogFile(mojo_base.mojom.File file);

  // Creates a new network context with the given parameters.
  CreateNetworkContext(pending_receiver<NetworkContext> context,
                       NetworkContextParams params);

  //...
  
  // Binds the test service's testing interface. Available only in some test
  // environments.
  BindTestInterface(pending_receiver<NetworkServiceTest> receiver);
};

mojom中定义了两个接口

  1. NetworkServiceClient: 实现:通常在浏览器进程中实现。它定义了网络服务可以调用的回调,以通知浏览器进程网络事件或状态的变化。 调用:当网络服务需要通知浏览器进程某些事件(例如,网络状态变化或其他通知)时,网络服务会调用这个接口的方法。这些调用通常发生在网络服务进程的线程中。
  2. NetworkService: 实现:在网络服务进程中实现。它定义了浏览器进程可以调用的网络操作或查询。 调用:当浏览器进程需要执行网络操作或查询时(例如,发起一个新的网络请求或获取网络状态),它会调用这个接口的方法。这些调用通常发生在浏览器进程的主线程或网络线程中。

可以看一下mojom生成后的文件

src\out\Release\gen\services\network\public\mojom\network_service.mojom.h
src\out\Release\gen\services\network\public\mojom\network_service.mojom.cc

这两个生成的文件最主要是定义了8个结构

  1. NetworkServiceClient (Interface):

    • 这是基于 .mojom 文件定义的接口,描述了客户端应该实现的方法集合。
    • 作用:为实现该接口的对象提供合约或蓝图。
  2. NetworkServiceClientProxy:

  • 代表在其他进程中的 NetworkServiceClient 接口的实例。当你调用其上的方法时,它会将这些调用打包成mojo消息并发送到其他进程。
  • 作用:作为发送者,将方法调用转换为mojo消息并发送它们。
  1. NetworkServiceClientStub:

    • 这个类处理传入的mojo消息并将它们分派给实现 NetworkServiceClient 接口的对象。
    • 作用:作为接收器,接收从对端发送的消息并调用相应的方法。
  2. NetworkServiceStubDispatch:

    • 它为NetworkServiceStub类提供支持。
    • NetworkServiceStub接收到一个mojo消息时,它会使用NetworkServiceStubDispatch中的方法来确定如何处理该消息。这同样涉及确定要调用哪个 NetworkService 接口的方法,并进行相应的参数解码。
  • NetworkServiceClientStubDispatch一样,这个类也通常包含静态方法,这些方法知道如何为每个在.mojom文件中定义的方法处理消息。
  1. NetworkService (Interface):

    • 这是基于 .mojom 文件定义的接口,描述了网络服务应该实现的方法集合。
    • 作用:为实现该接口的对象提供合约或蓝图。
  2. NetworkServiceProxy:

    • 代表在其他进程中的 NetworkService 接口的实例。当你调用其上的方法时,它会将这些调用打包成mojo消息并发送到其他进程。
    • 作用:作为发送者,将方法调用转换为mojo消息并发送它们。
  3. NetworkServiceStub:

    • 这个类处理传入的mojo消息并将它们分派给实现 NetworkService 接口的对象。
    • 作用:作为接收器,接收从对端发送的消息并调用相应的方法。
  4. NetworkServiceClientStubDispatch:

    • 它为NetworkServiceClientStub类提供支持。
    • NetworkServiceClientStub接收到一个mojo消息时,它会使用NetworkServiceClientStubDispatch中的方法来确定如何处理该消息。这包括确定要调用哪个NetworkServiceClient接口的方法,并将消息的参数解码为正确的格式。
    • 这个类通常包含静态方法,这些方法知道如何为每个在.mojom文件中定义的方法处理消息。

简而言之:

  • Interface 类(例如 NetworkServiceClientNetworkService)定义了方法的集合,这些方法可以通过IPC进行远程调用。
  • Proxy 类处理从一个进程到另一个进程的消息发送。
  • Stub 类处理从另一个进程到这个进程的消息接收。
  • StubDispatch 类型的类起到了一个关键的中介角色,帮助正确地处理和分派从另一个进程或线程接收的mojo消息。

这种结构允许两个运行在不同进程中的对象通过mojo IPC机制相互通信。

mojo生成的代码有了基础的了解之后再来看一下开始的日志信息

// CreateDefault被调用
net::CertVerifier::CreateDefault 
	network::NetworkContext::MakeURLRequestContext 
		network::NetworkContext::NetworkContext  
			std::__1::make_unique<network::NetworkContext,network::NetworkService *,mojo::PendingReceiver<network::mojom::NetworkContext>,mojo::StructPtr<network::mojom::NetworkContextParams>,base::OnceCallback<void (network::NetworkContext *)> > 
				// CreateDefault通过CreateNetworkContext创建
				network::NetworkService::CreateNetworkContext  
					// CreateNetworkContext通过NetworkServiceStubDispatch派发
					network::mojom::NetworkServiceStubDispatch::Accept 

上文中说明了NetworkServiceProxy的作用,其相当于在其他进程中NetworkService的代理,所以理论上来说,我们只要在proxy代理这部分获取调用栈,应该就能获取到对应使用该功能的代码

注意STACK设置位置是生成的mojo实现代码中,在out目录类似于这样的位置

src\out\Release\gen\services\network\public\mojom\network_service.mojom.cc

设置

void NetworkServiceProxy::CreateNetworkContext(
    mojo::PendingReceiver<::network::mojom::NetworkContext> in_context,
    ::network::mojom::NetworkContextParamsPtr in_params) {

  // 获取调用栈
  GM_STACK();

#if BUILDFLAG(MOJO_TRACE_ENABLED)
  TRACE_EVENT0(
      "mojom",
      "<class "
      "'jinja2::utils::Namespace'>::NetworkService::CreateNetworkContext");
#endif
  const bool kExpectsResponse = false;
  const bool kIsSync = false;
  const uint32_t kFlags =
      ((kExpectsResponse) ? mojo::Message::kFlagExpectsResponse : 0) |
      ((kIsSync) ? mojo::Message::kFlagIsSync : 0);
// ...
}

启动chrome,并查看调用栈

[27448:9696:1107/101016.170:INFO:network_service.mojom.cc(1115)] chromium(STACK): CreateNetworkContextBacktrace:
        base::debug::CollectStackTrace [0x00007FFDD7B46FB0+48] (G:\codes\chrome_79\src\base\debug\stack_trace_win.cc:284)
        base::debug::StackTrace::StackTrace [0x00007FFDD7B46120+80] (G:\codes\chrome_79\src\base\debug\stack_trace.cc:206)
        base::debug::StackTrace::StackTrace [0x00007FFDD7B460A8+40] (G:\codes\chrome_79\src\base\debug\stack_trace.cc:203)
        network::mojom::NetworkServiceProxy::CreateNetworkContext [0x00007FFD96F6F13F+79] (G:\codes\chrome_79\src\out\Release\gen\services\network\public\mojom\network_service.mojom.cc:1115)
        safe_browsing::SafeBrowsingNetworkContext::SharedURLLoaderFactory::GetNetworkContext [0x00007FFD9E474F7D+365] (G:\codes\chrome_79\src\components\safe_browsing\browser\safe_browsing_network_context.cc:52)
        safe_browsing::SafeBrowsingNetworkContext::SharedURLLoaderFactory::GetURLLoaderFactory [0x00007FFD9E47A4AD+333] (G:\codes\chrome_79\src\components\safe_browsing\browser\safe_browsing_network_context.cc:103)
        safe_browsing::SafeBrowsingNetworkContext::SharedURLLoaderFactory::CreateLoaderAndStart [0x00007FFD9E479FF9+313] (G:\codes\chrome_79\src\components\safe_browsing\browser\safe_browsing_network_context.cc:79)
        network::`anonymous namespace'::SimpleURLLoaderImpl::StartRequest [0x00007FFDCD917D2C+1276] (G:\codes\chrome_79\src\services\network\public\cpp\simple_url_loader.cc:1523)
        network::`anonymous namespace'::SimpleURLLoaderImpl::Start [0x00007FFDCD911EEA+922] (G:\codes\chrome_79\src\services\network\public\cpp\simple_url_loader.cc:1500)
        network::`anonymous namespace'::SimpleURLLoaderImpl::DownloadToStringOfUnboundedSizeUntilCrashAndDie [0x00007FFDCD90CE65+197] (G:\codes\chrome_79\src\services\network\public\cpp\simple_url_loader.cc:1197)
        safe_browsing::ModelLoader::StartFetch [0x00007FFDA3BA6AA9+553] (G:\codes\chrome_79\src\chrome\browser\safe_browsing\client_side_model_loader.cc:162)
...

--------------------------

[27448:9696:1107/101006.114:INFO:network_service.mojom.cc(1115)] chromium(STACK): CreateNetworkContextBacktrace:
        base::debug::CollectStackTrace [0x00007FFDD7B46FB0+48] (G:\codes\chrome_79\src\base\debug\stack_trace_win.cc:284)
        base::debug::StackTrace::StackTrace [0x00007FFDD7B46120+80] (G:\codes\chrome_79\src\base\debug\stack_trace.cc:206)
        base::debug::StackTrace::StackTrace [0x00007FFDD7B460A8+40] (G:\codes\chrome_79\src\base\debug\stack_trace.cc:203)
        network::mojom::NetworkServiceProxy::CreateNetworkContext [0x00007FFD96F6F13F+79] (G:\codes\chrome_79\src\out\Release\gen\services\network\public\mojom\network_service.mojom.cc:1115)
        ProfileNetworkContextService::CreateNetworkContext [0x00007FFDA0448E02+210] (G:\codes\chrome_79\src\chrome\browser\net\profile_network_context_service.cc:230)
        Profile::CreateNetworkContext [0x00007FFD9F5699E1+81] (G:\codes\chrome_79\src\chrome\browser\profiles\profile.cc:288)
        ChromeContentBrowserClient::CreateNetworkContext [0x00007FFD9F51CA0B+123] (G:\codes\chrome_79\src\chrome\browser\chrome_content_browser_client.cc:4679)
        content::StoragePartitionImpl::InitNetworkContext [0x00007FFD99A00243+131] (G:\codes\chrome_79\src\content\browser\storage_partition_impl.cc:2281)
        content::StoragePartitionImpl::GetNetworkContext [0x00007FFD99A0017F+207] (G:\codes\chrome_79\src\content\browser\storage_partition_impl.cc:1345)
        content::URLLoaderFactoryGetter::HandleNetworkFactoryRequestOnUIThread [0x00007FFD99A9783C+460] (G:\codes\chrome_79\src\content\browser\url_loader_factory_getter.cc:299)
        content::URLLoaderFactoryGetter::Initialize [0x00007FFD99A9759A+362] (G:\codes\chrome_79\src\content\browser\url_loader_factory_getter.cc:144)
        content::StoragePartitionImpl::Initialize [0x00007FFD999FE4A6+3766] (G:\codes\chrome_79\src\content\browser\storage_partition_impl.cc:1285)
        content::StoragePartitionImplMap::Get [0x00007FFD99A3DFF4+548] (G:\codes\chrome_79\src\content\browser\storage_partition_impl_map.cc:357)
        content::`anonymous namespace'::GetStoragePartitionFromConfig [0x00007FFD984D3713+147] (G:\codes\chrome_79\src\content\browser\browser_context.cc:171)
        content::BrowserContext::GetStoragePartition [0x00007FFD984D363C+252] (G:\codes\chrome_79\src\content\browser\browser_context.cc:388)
        content::BrowserContext::GetDefaultStoragePartition [0x00007FFD984D38AD+29] (G:\codes\chrome_79\src\content\browser\browser_context.cc:420)
        ProfileImpl::DoFinalInit [0x00007FFDA048D061+2177] (G:\codes\chrome_79\src\chrome\browser\profiles\profile_impl.cc:702)
        ProfileImpl::OnLocaleReady [0x00007FFDA048F5D8+1192] (G:\codes\chrome_79\src\chrome\browser\profiles\profile_impl.cc:987)
        ProfileImpl::OnPrefsLoaded [0x00007FFDA048BEE6+566] (G:\codes\chrome_79\src\chrome\browser\profiles\profile_impl.cc:1018)
        ProfileImpl::ProfileImpl [0x00007FFDA048A5B4+1924] (G:\codes\chrome_79\src\chrome\browser\profiles\profile_impl.cc:540)
        Profile::CreateProfile [0x00007FFDA04897F7+1111] (G:\codes\chrome_79\src\chrome\browser\profiles\profile_impl.cc:376)
        ProfileManager::CreateProfileHelper [0x00007FFD9F58F0A5+341] (G:\codes\chrome_79\src\chrome\browser\profiles\profile_manager.cc:1164)
        ProfileManager::CreateAndInitializeProfile [0x00007FFD9F587299+537] (G:\codes\chrome_79\src\chrome\browser\profiles\profile_manager.cc:1398)
        ProfileManager::GetProfile [0x00007FFD9F5867C2+386] (G:\codes\chrome_79\src\chrome\browser\profiles\profile_manager.cc:504)
        GetStartupProfile [0x00007FFDA1592D71+113] (G:\codes\chrome_79\src\chrome\browser\ui\startup\startup_browser_creator.cc:1041)
        `anonymous namespace'::CreatePrimaryProfile [0x00007FFDA0F2C103+947] (G:\codes\chrome_79\src\chrome\browser\chrome_browser_main.cc:425)
        ChromeBrowserMainParts::PreMainMessageLoopRunImpl [0x00007FFDA0F2A419+3609] (G:\codes\chrome_79\src\chrome\browser\chrome_browser_main.cc:1521)
        ChromeBrowserMainParts::PreMainMessageLoopRun [0x00007FFDA0F29553+307] (G:\codes\chrome_79\src\chrome\browser\chrome_browser_main.cc:1195)
        content::BrowserMainLoop::PreMainMessageLoopRun [0x00007FFD98538C8B+363] (G:\codes\chrome_79\src\content\browser\browser_main_loop.cc:1009)
        base::internal::FunctorTraits<int (content::BrowserMainLoop::*)(),void>::Invoke<int (content::BrowserMainLoop::*)(),content::BrowserMainLoop *> [0x00007FFD9854152A+26] (G:\codes\chrome_79\src\base\bind_internal.h:498)
        base::internal::InvokeHelper<0,int>::MakeItSo<int (content::BrowserMainLoop::*)(),content::BrowserMainLoop *> [0x00007FFD985414A4+52] (G:\codes\chrome_79\src\base\bind_internal.h:598)
        base::internal::Invoker<base::internal::BindState<int (content::BrowserMainLoop::*)

类似的还有不少,可以根据自己的需要去找到真正调用该NetworkService的功能代码。

上述文中用到的打印调用栈代码

#include "base/logging.h"
#include <base/debug/stack_trace.h>

base::debug::StackTrace st;
LOG(INFO) << "chromium(STACK): " << __FUNCTION__ << st.ToString()

xinali avatar Nov 07 '23 02:11 xinali