chromium browser process 与 render process 间通信通道的建立

       本文介绍browser 进程和 render 进程通信通道的建立, browser 进程与其他子进程, 比如 GPU 进程,Plugin 进程间通信通道的建立是类似的.

       Chromium ipc 正在转向Mojom. Mojom 将会在后续的博文中介绍. 本文的介绍是建立在Mojom  背景知识之上的.  另外, 有关render process 进程的启动过程,也请读者先参考罗升阳分享的文章《Chromium的Render进程启动过程分析 》 本文关注的是进程间通道建立的细节.


     在 browser 进程创建新的 进程前,会先 new RenderProcessHostImpl 的一个实体, 在RenderProcessHostImpl的构造函数里会调用RenderProcessHostImpl::InitializeChannelProxy(). 在 RenderProcessHostImpl::InitializeChannelProxy()中有为进程间通信做准备工作.

void RenderProcessHostImpl::InitializeChannelProxy() {
  // Generate a token used to identify the new child process.
  child_token_ = mojo::edk::GenerateRandomToken();

  scoped_refptr io_task_runner =
      BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);

  // Acquire a Connector which will route connections to a new instance of the
  // renderer service.
  service_manager::Connector* connector =
      BrowserContext::GetConnectorFor(browser_context_);
  if (!connector) {
    // Note that some embedders (e.g. Android WebView) may not initialize a
    // Connector per BrowserContext. In those cases we fall back to the
    // browser-wide Connector.
    if (!ServiceManagerConnection::GetForProcess()) {
      // Additionally, some test code may not initialize the process-wide
      // ServiceManagerConnection prior to this point. This class of test code
      // doesn't care about render processes, so we can initialize a dummy
      // connection.
      service_manager::mojom::ServiceRequest request(&test_service_);
      ServiceManagerConnection::SetForProcess(ServiceManagerConnection::Create(
          std::move(request), io_task_runner));
    }
    connector = ServiceManagerConnection::GetForProcess()->GetConnector();
  }

  // Establish a ServiceManager connection for the new render service instance.
  child_connection_.reset(new ChildConnection(
      mojom::kRendererServiceName,
      base::StringPrintf("%d_%d", id_, instance_id_++), child_token_, connector,
      io_task_runner));

  // Send an interface request to bootstrap the IPC::Channel. Note that this
  // request will happily sit on the pipe until the process is launched and
  // connected to the ServiceManager. We take the other end immediately and
  // plug it into a new ChannelProxy.
  IPC::mojom::ChannelBootstrapPtr bootstrap;
  GetRemoteInterfaces()->GetInterface(&bootstrap);
  std::unique_ptr channel_factory =
      IPC::ChannelMojo::CreateServerFactory(
          bootstrap.PassInterface().PassHandle(), io_task_runner);

  ResetChannelProxy();

  // Do NOT expand ifdef or run time condition checks here! Synchronous
  // IPCs from browser process are banned. It is only narrowly allowed
  // for Android WebView to maintain backward compatibility.
  // See crbug.com/526842 for details.
#if defined(OS_ANDROID)
  if (GetContentClient()->UsingSynchronousCompositing()) {
    channel_ = IPC::SyncChannel::Create(
        this, io_task_runner.get(), &never_signaled_);
  }
#endif  // OS_ANDROID
  if (!channel_)
    channel_.reset(new IPC::ChannelProxy(this, io_task_runner.get()));
  channel_->Init(std::move(channel_factory), true /* create_pipe_now */);

  // See OnProcessLaunched() for some additional details of this somewhat
  // surprising behavior.
  channel_->GetRemoteAssociatedInterface(&remote_route_provider_);
  channel_->GetRemoteAssociatedInterface(&renderer_interface_);

  // We start the Channel in a paused state. It will be briefly unpaused again
  // in Init() if applicable, before process launch is initiated.
  channel_->Pause();
}

这段code 在src/content/browser/render_host/render_process_host_impl.cc中. 请大家先注意child_token_, connector, ChildConnection,channel_factory 几个关键点.

下面一一探究.

     child_token_ 是一串随机字串, 是为后面Render 进程与Browser 进程握手时使用的标志符. 它被传递给了ChildConnection. 后文还会有详细介绍.

     connector  service_manager::Connector* connector = BrowserContext::GetConnectorFor(browser_context_);

     这里的connector 在browser main process 启动时已经创建好了.  看下面的code:

// static
service_manager::Connector* BrowserContext::GetConnectorFor(
    BrowserContext* browser_context) {
  ServiceManagerConnection* connection =
      GetServiceManagerConnectionFor(browser_context);
  return connection ? connection->GetConnector() : nullptr;
}

// static
ServiceManagerConnection* BrowserContext::GetServiceManagerConnectionFor(
    BrowserContext* browser_context) {
  BrowserContextServiceManagerConnectionHolder* connection_holder =
      static_cast(
          browser_context->GetUserData(kServiceManagerConnection));
  return connection_holder ? connection_holder->service_manager_connection()
                           : nullptr;
}
// static
void BrowserContext::Initialize(
    BrowserContext* browser_context,
    const base::FilePath& path) {

  std::string new_id;
  if (GetContentClient() && GetContentClient()->browser()) {
    new_id = GetContentClient()->browser()->GetServiceUserIdForBrowserContext(
        browser_context);
  } else {
    // Some test scenarios initialize a BrowserContext without a content client.
    new_id = base::GenerateGUID();
  }

  ServiceUserIdHolder* holder = static_cast(
      browser_context->GetUserData(kServiceUserId));
  if (holder)
    file::ForgetServiceUserIdUserDirAssociation(holder->user_id());
  file::AssociateServiceUserIdWithUserDir(new_id, path);
  RemoveBrowserContextFromUserIdMap(browser_context);
  g_user_id_to_context.Get()[new_id] = browser_context;
  browser_context->SetUserData(kServiceUserId,
                               new ServiceUserIdHolder(new_id));

  browser_context->SetUserData(kMojoWasInitialized,
                               new base::SupportsUserData::Data);

  ServiceManagerConnection* service_manager_connection =
      ServiceManagerConnection::GetForProcess();
  if (service_manager_connection && base::ThreadTaskRunnerHandle::IsSet()) {
    // NOTE: Many unit tests create a TestBrowserContext without initializing
    // Mojo or the global service manager connection.

    service_manager::mojom::ServicePtr service;
    service_manager::mojom::ServiceRequest service_request(&service);

    service_manager::mojom::PIDReceiverPtr pid_receiver;
    service_manager::Identity identity(mojom::kBrowserServiceName, new_id);
    service_manager_connection->GetConnector()->StartService(
        identity, std::move(service), mojo::MakeRequest(&pid_receiver));
    pid_receiver->SetPID(b

你可能感兴趣的:(Chromium学习,chromium,mojom,ipc,ServiceManager)