15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "mojo/embedder/embedder.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/location.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "mojo/embedder/platform_support.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "mojo/system/channel.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/system/channel_endpoint.h"
14a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "mojo/system/core.h"
15a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "mojo/system/entrypoints.h"
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/system/message_in_transit.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "mojo/system/message_pipe_dispatcher.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "mojo/system/platform_handle_dispatcher.h"
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "mojo/system/raw_channel.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace mojo {
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace embedder {
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// This is defined here (instead of a header file), since it's opaque to the
25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// outside world. But we need to define it before our (internal-only) functions
26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// that use it.
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct ChannelInfo {
286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ChannelInfo() {}
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ~ChannelInfo() {}
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<system::Channel> channel;
326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // May be null, in which case |DestroyChannelOnIOThread()| must be used (from
346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // the IO thread), instead of |DestroyChannel()|.
356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_refptr<base::TaskRunner> io_thread_task_runner;
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace {
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Helper for |CreateChannel...()|. (Note: May return null for some failures.)
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)scoped_refptr<system::Channel> MakeChannel(
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    system::Core* core,
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ScopedPlatformHandle platform_handle,
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_refptr<system::ChannelEndpoint> channel_endpoint) {
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(platform_handle.is_valid());
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create and initialize a |system::Channel|.
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<system::Channel> channel =
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      new system::Channel(core->platform_support());
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!channel->Init(system::RawChannel::Create(platform_handle.Pass()))) {
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // This is very unusual (e.g., maybe |platform_handle| was invalid or we
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // reached some system resource limit).
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    LOG(ERROR) << "Channel::Init() failed";
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Return null, since |Shutdown()| shouldn't be called in this case.
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return scoped_refptr<system::Channel>();
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Once |Init()| has succeeded, we have to return |channel| (since
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // |Shutdown()| will have to be called on it).
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Attach the endpoint.
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  system::MessageInTransit::EndpointId endpoint_id =
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      channel->AttachEndpoint(channel_endpoint);
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (endpoint_id == system::MessageInTransit::kInvalidEndpointId) {
64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // This means that, e.g., the other endpoint of the message pipe was closed
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // first. But it's not necessarily an error per se.
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DVLOG(2) << "Channel::AttachEndpoint() failed";
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return channel;
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK_EQ(endpoint_id, system::Channel::kBootstrapEndpointId);
70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!channel->RunMessagePipeEndpoint(system::Channel::kBootstrapEndpointId,
72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       system::Channel::kBootstrapEndpointId)) {
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Currently, there's no reason for this to fail.
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    NOTREACHED() << "Channel::RunMessagePipeEndpoint() failed";
75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return channel;
76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return channel;
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void CreateChannelHelper(
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    system::Core* core,
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ScopedPlatformHandle platform_handle,
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_ptr<ChannelInfo> channel_info,
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_refptr<system::ChannelEndpoint> channel_endpoint,
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DidCreateChannelCallback callback,
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  channel_info->channel =
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MakeChannel(core, platform_handle.Pass(), channel_endpoint);
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Hand the channel back to the embedder.
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (callback_thread_task_runner.get()) {
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    callback_thread_task_runner->PostTask(
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        FROM_HERE, base::Bind(callback, channel_info.release()));
9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else {
9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    callback.Run(channel_info.release());
9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}  // namespace
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void Init(scoped_ptr<PlatformSupport> platform_support) {
10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  system::entrypoints::SetCore(new system::Core(platform_support.Pass()));
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// TODO(vtl): Write tests for this.
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ScopedMessagePipeHandle CreateChannelOnIOThread(
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ScopedPlatformHandle platform_handle,
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ChannelInfo** channel_info) {
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(platform_handle.is_valid());
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(channel_info);
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<system::ChannelEndpoint> channel_endpoint;
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<system::MessagePipeDispatcher> dispatcher =
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      system::MessagePipeDispatcher::CreateRemoteMessagePipe(&channel_endpoint);
1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  system::Core* core = system::entrypoints::GetCore();
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(core);
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ScopedMessagePipeHandle rv(
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MessagePipeHandle(core->AddDispatcher(dispatcher)));
1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  *channel_info = new ChannelInfo();
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  (*channel_info)->channel =
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MakeChannel(core, platform_handle.Pass(), channel_endpoint);
1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return rv.Pass();
1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ScopedMessagePipeHandle CreateChannel(
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ScopedPlatformHandle platform_handle,
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<base::TaskRunner> io_thread_task_runner,
13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    DidCreateChannelCallback callback,
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(platform_handle.is_valid());
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<system::ChannelEndpoint> channel_endpoint;
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<system::MessagePipeDispatcher> dispatcher =
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      system::MessagePipeDispatcher::CreateRemoteMessagePipe(&channel_endpoint);
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
140a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  system::Core* core = system::entrypoints::GetCore();
141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(core);
14223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ScopedMessagePipeHandle rv(
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MessagePipeHandle(core->AddDispatcher(dispatcher)));
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<ChannelInfo> channel_info(new ChannelInfo());
1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  channel_info->io_thread_task_runner = io_thread_task_runner;
1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
14823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (rv.is_valid()) {
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    io_thread_task_runner->PostTask(FROM_HERE,
1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                    base::Bind(&CreateChannelHelper,
15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                               base::Unretained(core),
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               base::Passed(&platform_handle),
1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                               base::Passed(&channel_info),
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                               channel_endpoint,
15523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                               callback,
15623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                               callback_thread_task_runner));
1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else {
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    (callback_thread_task_runner.get() ? callback_thread_task_runner
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       : io_thread_task_runner)
1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        ->PostTask(FROM_HERE, base::Bind(callback, channel_info.release()));
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
16323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return rv.Pass();
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DestroyChannelOnIOThread(ChannelInfo* channel_info) {
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(channel_info);
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!channel_info->channel.get()) {
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Presumably, |Init()| on the channel failed.
170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  channel_info->channel->Shutdown();
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete channel_info;
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// TODO(vtl): Write tests for this.
1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DestroyChannel(ChannelInfo* channel_info) {
1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(channel_info);
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(channel_info->io_thread_task_runner.get());
1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!channel_info->channel.get()) {
1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Presumably, |Init()| on the channel failed.
1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return;
1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  channel_info->channel->WillShutdownSoon();
1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  channel_info->io_thread_task_runner->PostTask(
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      FROM_HERE, base::Bind(&DestroyChannelOnIOThread, channel_info));
1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void WillDestroyChannelSoon(ChannelInfo* channel_info) {
1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(channel_info);
1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  channel_info->channel->WillShutdownSoon();
1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)MojoResult CreatePlatformHandleWrapper(
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ScopedPlatformHandle platform_handle,
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MojoHandle* platform_handle_wrapper_handle) {
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(platform_handle_wrapper_handle);
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<system::Dispatcher> dispatcher(
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new system::PlatformHandleDispatcher(platform_handle.Pass()));
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  system::Core* core = system::entrypoints::GetCore();
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(core);
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MojoHandle h = core->AddDispatcher(dispatcher);
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (h == MOJO_HANDLE_INVALID) {
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Handle table full";
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    dispatcher->Close();
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return MOJO_RESULT_RESOURCE_EXHAUSTED;
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *platform_handle_wrapper_handle = h;
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return MOJO_RESULT_OK;
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle,
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     ScopedPlatformHandle* platform_handle) {
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(platform_handle);
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  system::Core* core = system::entrypoints::GetCore();
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(core);
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<system::Dispatcher> dispatcher(
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      core->GetDispatcher(platform_handle_wrapper_handle));
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!dispatcher.get())
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return MOJO_RESULT_INVALID_ARGUMENT;
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (dispatcher->GetType() != system::Dispatcher::kTypePlatformHandle)
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return MOJO_RESULT_INVALID_ARGUMENT;
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  *platform_handle =
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      static_cast<system::PlatformHandleDispatcher*>(dispatcher.get())
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          ->PassPlatformHandle()
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          .Pass();
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return MOJO_RESULT_OK;
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace embedder
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace mojo
241