| Index: remoting/host/security_key/security_key_ipc_server_unittest.cc
 | 
| diff --git a/remoting/host/security_key/security_key_ipc_server_unittest.cc b/remoting/host/security_key/security_key_ipc_server_unittest.cc
 | 
| index be7554eb62f98baa493f5c28f1e2c43a40ac4fab..bdedf58939828d82a865cad38a44c738a07e23f0 100644
 | 
| --- a/remoting/host/security_key/security_key_ipc_server_unittest.cc
 | 
| +++ b/remoting/host/security_key/security_key_ipc_server_unittest.cc
 | 
| @@ -14,6 +14,9 @@
 | 
|  #include "base/message_loop/message_loop.h"
 | 
|  #include "base/run_loop.h"
 | 
|  #include "ipc/ipc_channel.h"
 | 
| +#include "mojo/edk/embedder/embedder.h"
 | 
| +#include "mojo/edk/embedder/named_platform_handle_utils.h"
 | 
| +#include "mojo/edk/test/scoped_ipc_support.h"
 | 
|  #include "remoting/host/client_session_details.h"
 | 
|  #include "remoting/host/security_key/fake_security_key_ipc_client.h"
 | 
|  #include "remoting/host/security_key/security_key_ipc_constants.h"
 | 
| @@ -56,6 +59,8 @@ class SecurityKeyIpcServerTest : public testing::Test,
 | 
|    // IPC tests require a valid MessageLoop to run.
 | 
|    base::MessageLoopForIO message_loop_;
 | 
|  
 | 
| +  mojo::edk::test::ScopedIPCSupport ipc_support_;
 | 
| +
 | 
|    // Used to allow |message_loop_| to run during tests.  The instance is reset
 | 
|    // after each stage of the tests has been completed.
 | 
|    std::unique_ptr<base::RunLoop> run_loop_;
 | 
| @@ -77,7 +82,8 @@ class SecurityKeyIpcServerTest : public testing::Test,
 | 
|  };
 | 
|  
 | 
|  SecurityKeyIpcServerTest::SecurityKeyIpcServerTest()
 | 
| -    : run_loop_(new base::RunLoop()) {
 | 
| +    : ipc_support_(message_loop_.task_runner()),
 | 
| +      run_loop_(new base::RunLoop()) {
 | 
|  #if defined(OS_WIN)
 | 
|    EXPECT_TRUE(ProcessIdToSessionId(
 | 
|        GetCurrentProcessId(), reinterpret_cast<DWORD*>(&peer_session_id_)));
 | 
| @@ -88,6 +94,7 @@ SecurityKeyIpcServerTest::SecurityKeyIpcServerTest()
 | 
|        base::TimeDelta::FromMilliseconds(kInitialConnectTimeoutMs),
 | 
|        base::Bind(&SecurityKeyIpcServerTest::SendRequestToClient,
 | 
|                   base::Unretained(this)),
 | 
| +      base::Bind(&base::DoNothing),
 | 
|        base::Bind(&SecurityKeyIpcServerTest::OperationComplete,
 | 
|                   base::Unretained(this)));
 | 
|  }
 | 
| @@ -116,15 +123,15 @@ std::string SecurityKeyIpcServerTest::GetUniqueTestChannelName() {
 | 
|  }
 | 
|  
 | 
|  TEST_F(SecurityKeyIpcServerTest, HandleSingleSecurityKeyRequest) {
 | 
| -  std::string channel_name(GetUniqueTestChannelName());
 | 
| +  mojo::edk::NamedPlatformHandle channel_handle(GetUniqueTestChannelName());
 | 
|    ASSERT_TRUE(security_key_ipc_server_->CreateChannel(
 | 
| -      channel_name,
 | 
| +      channel_handle,
 | 
|        /*request_timeout=*/base::TimeDelta::FromMilliseconds(500)));
 | 
|  
 | 
|    // Create a fake client and connect to the IPC server channel.
 | 
|    FakeSecurityKeyIpcClient fake_ipc_client(base::Bind(
 | 
|        &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this)));
 | 
| -  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name));
 | 
| +  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_handle));
 | 
|    WaitForOperationComplete();
 | 
|  
 | 
|    ASSERT_TRUE(fake_ipc_client.ipc_channel_connected());
 | 
| @@ -151,15 +158,15 @@ TEST_F(SecurityKeyIpcServerTest, HandleSingleSecurityKeyRequest) {
 | 
|  }
 | 
|  
 | 
|  TEST_F(SecurityKeyIpcServerTest, HandleLargeSecurityKeyRequest) {
 | 
| -  std::string channel_name(GetUniqueTestChannelName());
 | 
| +  mojo::edk::NamedPlatformHandle channel_handle(GetUniqueTestChannelName());
 | 
|    ASSERT_TRUE(security_key_ipc_server_->CreateChannel(
 | 
| -      channel_name,
 | 
| +      channel_handle,
 | 
|        /*request_timeout=*/base::TimeDelta::FromMilliseconds(500)));
 | 
|  
 | 
|    // Create a fake client and connect to the IPC server channel.
 | 
|    FakeSecurityKeyIpcClient fake_ipc_client(base::Bind(
 | 
|        &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this)));
 | 
| -  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name));
 | 
| +  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_handle));
 | 
|    WaitForOperationComplete();
 | 
|  
 | 
|    ASSERT_TRUE(fake_ipc_client.ipc_channel_connected());
 | 
| @@ -186,15 +193,15 @@ TEST_F(SecurityKeyIpcServerTest, HandleLargeSecurityKeyRequest) {
 | 
|  }
 | 
|  
 | 
|  TEST_F(SecurityKeyIpcServerTest, HandleReallyLargeSecurityKeyRequest) {
 | 
| -  std::string channel_name(GetUniqueTestChannelName());
 | 
| +  mojo::edk::NamedPlatformHandle channel_handle(GetUniqueTestChannelName());
 | 
|    ASSERT_TRUE(security_key_ipc_server_->CreateChannel(
 | 
| -      channel_name,
 | 
| +      channel_handle,
 | 
|        /*request_timeout=*/base::TimeDelta::FromMilliseconds(500)));
 | 
|  
 | 
|    // Create a fake client and connect to the IPC server channel.
 | 
|    FakeSecurityKeyIpcClient fake_ipc_client(base::Bind(
 | 
|        &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this)));
 | 
| -  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name));
 | 
| +  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_handle));
 | 
|    WaitForOperationComplete();
 | 
|  
 | 
|    ASSERT_TRUE(fake_ipc_client.ipc_channel_connected());
 | 
| @@ -221,15 +228,15 @@ TEST_F(SecurityKeyIpcServerTest, HandleReallyLargeSecurityKeyRequest) {
 | 
|  }
 | 
|  
 | 
|  TEST_F(SecurityKeyIpcServerTest, HandleMultipleSecurityKeyRequests) {
 | 
| -  std::string channel_name(GetUniqueTestChannelName());
 | 
| +  mojo::edk::NamedPlatformHandle channel_handle(GetUniqueTestChannelName());
 | 
|    ASSERT_TRUE(security_key_ipc_server_->CreateChannel(
 | 
| -      channel_name,
 | 
| +      channel_handle,
 | 
|        /*request_timeout=*/base::TimeDelta::FromMilliseconds(500)));
 | 
|  
 | 
|    // Create a fake client and connect to the IPC server channel.
 | 
|    FakeSecurityKeyIpcClient fake_ipc_client(base::Bind(
 | 
|        &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this)));
 | 
| -  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name));
 | 
| +  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_handle));
 | 
|    WaitForOperationComplete();
 | 
|  
 | 
|    ASSERT_TRUE(fake_ipc_client.ipc_channel_connected());
 | 
| @@ -272,15 +279,38 @@ TEST_F(SecurityKeyIpcServerTest, HandleMultipleSecurityKeyRequests) {
 | 
|    fake_ipc_client.CloseIpcConnection();
 | 
|  }
 | 
|  
 | 
| -TEST_F(SecurityKeyIpcServerTest, InitialIpcConnectionTimeout) {
 | 
| +TEST_F(SecurityKeyIpcServerTest, InitialIpcConnectionTimeout_ConnectOnly) {
 | 
|    // Create a channel, then wait for the done callback to be called indicating
 | 
|    // the connection was closed.  This test simulates the IPC Server being
 | 
| -  // created but the client failing to connect to it.
 | 
| -  std::string channel_name(GetUniqueTestChannelName());
 | 
| +  // created, the client connecting to the OS channel, but never communicating
 | 
| +  // over the channel.
 | 
| +  mojo::edk::NamedPlatformHandle channel_handle(GetUniqueTestChannelName());
 | 
|    ASSERT_TRUE(security_key_ipc_server_->CreateChannel(
 | 
| -      channel_name,
 | 
| +      channel_handle,
 | 
|        /*request_timeout=*/base::TimeDelta::FromMilliseconds(500)));
 | 
|    base::Time start_time(base::Time::NowFromSystemTime());
 | 
| +  mojo::edk::ScopedPlatformHandle client_handle =
 | 
| +      mojo::edk::CreateClientHandle(channel_handle);
 | 
| +  WaitForOperationComplete();
 | 
| +  base::TimeDelta elapsed_time = base::Time::NowFromSystemTime() - start_time;
 | 
| +
 | 
| +  ASSERT_NEAR(elapsed_time.InMilliseconds(), kInitialConnectTimeoutMs,
 | 
| +              kConnectionTimeoutErrorDeltaMs);
 | 
| +}
 | 
| +
 | 
| +TEST_F(SecurityKeyIpcServerTest,
 | 
| +       InitialIpcConnectionTimeout_ConnectAndEstablishMojoConnection) {
 | 
| +  // Create a channel, then wait for the done callback to be called indicating
 | 
| +  // the connection was closed.  This test simulates the IPC Server being
 | 
| +  // created, the client establishing a mojo connection, but never constructing
 | 
| +  // an IPC::Channel over it.
 | 
| +  mojo::edk::NamedPlatformHandle channel_handle(GetUniqueTestChannelName());
 | 
| +  ASSERT_TRUE(security_key_ipc_server_->CreateChannel(
 | 
| +      channel_handle,
 | 
| +      /*request_timeout=*/base::TimeDelta::FromMilliseconds(500)));
 | 
| +  base::Time start_time(base::Time::NowFromSystemTime());
 | 
| +  mojo::ScopedMessagePipeHandle client_pipe = mojo::edk::ConnectToPeerProcess(
 | 
| +      mojo::edk::CreateClientHandle(channel_handle));
 | 
|    WaitForOperationComplete();
 | 
|    base::TimeDelta elapsed_time = base::Time::NowFromSystemTime() - start_time;
 | 
|  
 | 
| @@ -292,15 +322,15 @@ TEST_F(SecurityKeyIpcServerTest, NoSecurityKeyRequestTimeout) {
 | 
|    // Create a channel and connect to it via IPC but do not send a request.
 | 
|    // The channel should be closed and cleaned up if the IPC client does not
 | 
|    // issue a request within the specified timeout period.
 | 
| -  std::string channel_name(GetUniqueTestChannelName());
 | 
| +  mojo::edk::NamedPlatformHandle channel_handle(GetUniqueTestChannelName());
 | 
|    ASSERT_TRUE(security_key_ipc_server_->CreateChannel(
 | 
| -      channel_name,
 | 
| +      channel_handle,
 | 
|        /*request_timeout=*/base::TimeDelta::FromMilliseconds(500)));
 | 
|  
 | 
|    // Create a fake client and connect to the IPC server channel.
 | 
|    FakeSecurityKeyIpcClient fake_ipc_client(base::Bind(
 | 
|        &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this)));
 | 
| -  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name));
 | 
| +  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_handle));
 | 
|    WaitForOperationComplete();
 | 
|  
 | 
|    ASSERT_TRUE(fake_ipc_client.ipc_channel_connected());
 | 
| @@ -318,14 +348,14 @@ TEST_F(SecurityKeyIpcServerTest, SecurityKeyResponseTimeout) {
 | 
|    // Create a channel, connect to it via IPC, and issue a request, but do
 | 
|    // not send a response.  This simulates a client-side timeout.
 | 
|    base::TimeDelta request_timeout(base::TimeDelta::FromMilliseconds(50));
 | 
| -  std::string channel_name(GetUniqueTestChannelName());
 | 
| +  mojo::edk::NamedPlatformHandle channel_handle(GetUniqueTestChannelName());
 | 
|    ASSERT_TRUE(
 | 
| -      security_key_ipc_server_->CreateChannel(channel_name, request_timeout));
 | 
| +      security_key_ipc_server_->CreateChannel(channel_handle, request_timeout));
 | 
|  
 | 
|    // Create a fake client and connect to the IPC server channel.
 | 
|    FakeSecurityKeyIpcClient fake_ipc_client(base::Bind(
 | 
|        &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this)));
 | 
| -  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name));
 | 
| +  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_handle));
 | 
|    WaitForOperationComplete();
 | 
|  
 | 
|    ASSERT_TRUE(fake_ipc_client.ipc_channel_connected());
 | 
| @@ -350,14 +380,14 @@ TEST_F(SecurityKeyIpcServerTest, SendResponseTimeout) {
 | 
|    // a response, but do not close the channel after that.  The connection
 | 
|    // should be terminated after the initial timeout period has elapsed.
 | 
|    base::TimeDelta request_timeout(base::TimeDelta::FromMilliseconds(500));
 | 
| -  std::string channel_name(GetUniqueTestChannelName());
 | 
| +  mojo::edk::NamedPlatformHandle channel_handle(GetUniqueTestChannelName());
 | 
|    ASSERT_TRUE(
 | 
| -      security_key_ipc_server_->CreateChannel(channel_name, request_timeout));
 | 
| +      security_key_ipc_server_->CreateChannel(channel_handle, request_timeout));
 | 
|  
 | 
|    // Create a fake client and connect to the IPC server channel.
 | 
|    FakeSecurityKeyIpcClient fake_ipc_client(base::Bind(
 | 
|        &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this)));
 | 
| -  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name));
 | 
| +  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_handle));
 | 
|    WaitForOperationComplete();
 | 
|  
 | 
|    ASSERT_TRUE(fake_ipc_client.ipc_channel_connected());
 | 
| @@ -381,20 +411,70 @@ TEST_F(SecurityKeyIpcServerTest, SendResponseTimeout) {
 | 
|                kConnectionTimeoutErrorDeltaMs);
 | 
|  }
 | 
|  
 | 
| +TEST_F(SecurityKeyIpcServerTest, CleanupPendingConnection) {
 | 
| +  // Test that servers correctly close pending OS connections on
 | 
| +  // |channel_handle|. If multiple servers do remain, the client may happen to
 | 
| +  // connect to the correct server, so create and delete many servers.
 | 
| +  mojo::edk::NamedPlatformHandle channel_handle(GetUniqueTestChannelName());
 | 
| +  for (int i = 0; i < 100; i++) {
 | 
| +    security_key_ipc_server_ = remoting::SecurityKeyIpcServer::Create(
 | 
| +        kTestConnectionId, this,
 | 
| +        base::TimeDelta::FromMilliseconds(kInitialConnectTimeoutMs),
 | 
| +        base::Bind(&SecurityKeyIpcServerTest::SendRequestToClient,
 | 
| +                   base::Unretained(this)),
 | 
| +        base::Bind(&base::DoNothing),
 | 
| +        base::Bind(&SecurityKeyIpcServerTest::OperationComplete,
 | 
| +                   base::Unretained(this)));
 | 
| +    ASSERT_TRUE(security_key_ipc_server_->CreateChannel(
 | 
| +        channel_handle,
 | 
| +        /*request_timeout=*/base::TimeDelta::FromMilliseconds(500)));
 | 
| +  }
 | 
| +  // The mojo system posts tasks as part of its cleanup, so run them all.
 | 
| +  base::RunLoop().RunUntilIdle();
 | 
| +
 | 
| +  // Create a fake client and connect to the IPC server channel.
 | 
| +  FakeSecurityKeyIpcClient fake_ipc_client(base::Bind(
 | 
| +      &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this)));
 | 
| +  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_handle));
 | 
| +  WaitForOperationComplete();
 | 
| +
 | 
| +  ASSERT_TRUE(fake_ipc_client.ipc_channel_connected());
 | 
| +
 | 
| +  // Send a request from the IPC client to the IPC server.
 | 
| +  std::string request_data("Blergh!");
 | 
| +  fake_ipc_client.SendSecurityKeyRequestViaIpc(request_data);
 | 
| +  WaitForOperationComplete();
 | 
| +
 | 
| +  // Verify the request was received.
 | 
| +  ASSERT_EQ(kTestConnectionId, last_connection_id_received_);
 | 
| +  ASSERT_EQ(request_data, last_message_received_);
 | 
| +
 | 
| +  // Send a response from the IPC server to the IPC client.
 | 
| +  std::string response_data("Blargh!");
 | 
| +  ASSERT_TRUE(security_key_ipc_server_->SendResponse(response_data));
 | 
| +  WaitForOperationComplete();
 | 
| +
 | 
| +  // Verify the request was received.
 | 
| +  ASSERT_EQ(response_data, fake_ipc_client.last_message_received());
 | 
| +
 | 
| +  // Typically the client will be the one to close the connection.
 | 
| +  fake_ipc_client.CloseIpcConnection();
 | 
| +}
 | 
| +
 | 
|  #if defined(OS_WIN)
 | 
|  TEST_F(SecurityKeyIpcServerTest, IpcConnectionFailsFromInvalidSession) {
 | 
|    // Change the expected session ID to not match the current session.
 | 
|    peer_session_id_++;
 | 
|  
 | 
|    base::TimeDelta request_timeout(base::TimeDelta::FromMilliseconds(500));
 | 
| -  std::string channel_name(GetUniqueTestChannelName());
 | 
| +  mojo::edk::NamedPlatformHandle channel_handle(GetUniqueTestChannelName());
 | 
|    ASSERT_TRUE(
 | 
| -      security_key_ipc_server_->CreateChannel(channel_name, request_timeout));
 | 
| +      security_key_ipc_server_->CreateChannel(channel_handle, request_timeout));
 | 
|  
 | 
|    // Create a fake client and attempt to connect to the IPC server channel.
 | 
|    FakeSecurityKeyIpcClient fake_ipc_client(base::Bind(
 | 
|        &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this)));
 | 
| -  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name));
 | 
| +  ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_handle));
 | 
|    WaitForOperationComplete();
 | 
|    WaitForOperationComplete();
 | 
|    WaitForOperationComplete();
 | 
| 
 |