OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/system/platform_channel.h" | 5 #include "mojo/system/platform_channel.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <sys/socket.h> | 8 #include <sys/socket.h> |
9 #include <sys/types.h> | 9 #include <sys/types.h> |
10 #include <unistd.h> | 10 #include <unistd.h> |
11 | 11 |
| 12 #include "base/command_line.h" |
12 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
13 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/posix/global_descriptors.h" |
| 16 #include "base/strings/string_number_conversions.h" |
14 | 17 |
15 namespace mojo { | 18 namespace mojo { |
16 namespace system { | 19 namespace system { |
17 | 20 |
18 namespace { | 21 namespace { |
19 | 22 |
20 void CloseIfNecessary(PlatformChannelHandle* handle) { | 23 const char kMojoChannelDescriptorSwitch[] = "mojo-channel-descriptor"; |
21 if (!handle->is_valid()) | |
22 return; | |
23 | 24 |
24 PCHECK(close(handle->fd) == 0); | 25 bool IsTargetDescriptorUsed( |
25 *handle = PlatformChannelHandle(); | 26 const base::FileHandleMappingVector& file_handle_mapping, |
| 27 int target_fd) { |
| 28 for (size_t i = 0; i < file_handle_mapping.size(); i++) { |
| 29 if (file_handle_mapping[i].second == target_fd) |
| 30 return true; |
| 31 } |
| 32 return false; |
26 } | 33 } |
27 | 34 |
28 class PlatformServerChannelPosix : public PlatformServerChannel { | 35 class PlatformServerChannelPosix : public PlatformServerChannel { |
29 public: | 36 public: |
30 PlatformServerChannelPosix(const std::string& name); | 37 PlatformServerChannelPosix(const std::string& name); |
31 virtual ~PlatformServerChannelPosix(); | 38 virtual ~PlatformServerChannelPosix(); |
32 | 39 |
33 // |PlatformServerChannel| implementation: | 40 // |PlatformServerChannel| implementation: |
34 virtual scoped_ptr<PlatformClientChannel> CreateClientChannel() OVERRIDE; | 41 virtual scoped_ptr<PlatformClientChannel> CreateClientChannel() OVERRIDE; |
35 virtual void GetDataNeededToPassClientChannelToChildProcess( | 42 virtual void GetDataNeededToPassClientChannelToChildProcess( |
(...skipping 16 matching lines...) Expand all Loading... |
52 PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0); | 59 PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0); |
53 PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0); | 60 PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0); |
54 | 61 |
55 mutable_handle()->fd = fds[0]; | 62 mutable_handle()->fd = fds[0]; |
56 DCHECK(is_valid()); | 63 DCHECK(is_valid()); |
57 client_handle_.fd = fds[1]; | 64 client_handle_.fd = fds[1]; |
58 DCHECK(client_handle_.is_valid()); | 65 DCHECK(client_handle_.is_valid()); |
59 } | 66 } |
60 | 67 |
61 PlatformServerChannelPosix::~PlatformServerChannelPosix() { | 68 PlatformServerChannelPosix::~PlatformServerChannelPosix() { |
62 if (is_valid()) | 69 client_handle_.CloseIfNecessary(); |
63 CloseIfNecessary(mutable_handle()); | |
64 if (client_handle_.is_valid()) | |
65 CloseIfNecessary(&client_handle_); | |
66 } | 70 } |
67 | 71 |
68 scoped_ptr<PlatformClientChannel> | 72 scoped_ptr<PlatformClientChannel> |
69 PlatformServerChannelPosix::CreateClientChannel() { | 73 PlatformServerChannelPosix::CreateClientChannel() { |
70 if (!client_handle_.is_valid()) { | 74 if (!client_handle_.is_valid()) { |
71 NOTREACHED(); | 75 NOTREACHED(); |
72 return scoped_ptr<PlatformClientChannel>(); | 76 return scoped_ptr<PlatformClientChannel>(); |
73 } | 77 } |
74 | 78 |
75 scoped_ptr<PlatformClientChannel> rv = | 79 scoped_ptr<PlatformClientChannel> rv = |
76 PlatformClientChannel::CreateFromHandle(client_handle_); | 80 PlatformClientChannel::CreateFromHandle(client_handle_); |
77 DCHECK(rv->is_valid()); | 81 DCHECK(rv->is_valid()); |
78 client_handle_ = PlatformChannelHandle(); | 82 client_handle_ = PlatformChannelHandle(); |
79 return rv.Pass(); | 83 return rv.Pass(); |
80 } | 84 } |
81 | 85 |
82 void PlatformServerChannelPosix::GetDataNeededToPassClientChannelToChildProcess( | 86 void PlatformServerChannelPosix::GetDataNeededToPassClientChannelToChildProcess( |
83 CommandLine* command_line, | 87 CommandLine* command_line, |
84 base::FileHandleMappingVector* file_handle_mapping) const { | 88 base::FileHandleMappingVector* file_handle_mapping) const { |
85 // TODO(vtl) | 89 DCHECK(command_line); |
86 NOTIMPLEMENTED(); | 90 DCHECK(file_handle_mapping); |
| 91 // This is an arbitrary sanity check. (Note that this guarantees that the loop |
| 92 // below will terminate sanely.) |
| 93 CHECK_LT(file_handle_mapping->size(), 1000u); |
| 94 |
| 95 DCHECK(client_handle_.is_valid()); |
| 96 |
| 97 // Find a suitable FD to map our client handle to in the child process. |
| 98 // This has quadratic time complexity in the size of |*file_handle_mapping|, |
| 99 // but |*file_handle_mapping| should be very small (usually/often empty). |
| 100 int target_fd = base::GlobalDescriptors::kBaseDescriptor; |
| 101 while (IsTargetDescriptorUsed(*file_handle_mapping, target_fd)) |
| 102 target_fd++; |
| 103 |
| 104 file_handle_mapping->push_back(std::pair<int, int>(client_handle_.fd, |
| 105 target_fd)); |
| 106 // Log a warning if the command line already has the switch, but "clobber" it |
| 107 // anyway, since it's reasonably likely that all the switches were just copied |
| 108 // from the parent. |
| 109 LOG_IF(WARNING, command_line->HasSwitch(kMojoChannelDescriptorSwitch)) |
| 110 << "Child command line already has switch --" |
| 111 << kMojoChannelDescriptorSwitch << "=" |
| 112 << command_line->GetSwitchValueASCII(kMojoChannelDescriptorSwitch); |
| 113 // (Any existing switch won't actually be removed from the command line, but |
| 114 // the last one appended takes precedence.) |
| 115 command_line->AppendSwitchASCII(kMojoChannelDescriptorSwitch, |
| 116 base::IntToString(target_fd)); |
87 } | 117 } |
88 | 118 |
89 void PlatformServerChannelPosix::ChildProcessLaunched() { | 119 void PlatformServerChannelPosix::ChildProcessLaunched() { |
90 // TODO(vtl) | 120 DCHECK(client_handle_.is_valid()); |
91 NOTIMPLEMENTED(); | 121 client_handle_.CloseIfNecessary(); |
92 } | 122 } |
93 | 123 |
94 } // namespace | 124 } // namespace |
95 | 125 |
96 // ----------------------------------------------------------------------------- | 126 // ----------------------------------------------------------------------------- |
97 | 127 |
98 // Static factory method declared in platform_channel.h. | 128 // Static factory method declared in platform_channel.h. |
99 // static | 129 // static |
100 scoped_ptr<PlatformServerChannel> PlatformServerChannel::Create( | 130 scoped_ptr<PlatformServerChannel> PlatformServerChannel::Create( |
101 const std::string& name) { | 131 const std::string& name) { |
102 return scoped_ptr<PlatformServerChannel>( | 132 return scoped_ptr<PlatformServerChannel>( |
103 new PlatformServerChannelPosix(name)); | 133 new PlatformServerChannelPosix(name)); |
104 } | 134 } |
105 | 135 |
106 // ----------------------------------------------------------------------------- | 136 // ----------------------------------------------------------------------------- |
107 | 137 |
108 // Static factory method declared in platform_channel.h. | 138 // Static factory method declared in platform_channel.h. |
109 // static | 139 // static |
110 scoped_ptr<PlatformClientChannel> | 140 scoped_ptr<PlatformClientChannel> |
111 PlatformClientChannel::CreateFromParentProcess( | 141 PlatformClientChannel::CreateFromParentProcess( |
112 const CommandLine& command_line) { | 142 const CommandLine& command_line) { |
113 // TODO(vtl) | 143 std::string client_fd_string = |
114 NOTIMPLEMENTED(); | 144 command_line.GetSwitchValueASCII(kMojoChannelDescriptorSwitch); |
115 return scoped_ptr<PlatformClientChannel>(); | 145 int client_fd = -1; |
| 146 if (client_fd_string.empty() || |
| 147 !base::StringToInt(client_fd_string, &client_fd) || |
| 148 client_fd < base::GlobalDescriptors::kBaseDescriptor) { |
| 149 LOG(ERROR) << "Missing or invalid --" << kMojoChannelDescriptorSwitch; |
| 150 return scoped_ptr<PlatformClientChannel>(); |
| 151 } |
| 152 |
| 153 return CreateFromHandle(PlatformChannelHandle(client_fd)); |
116 } | 154 } |
117 | 155 |
118 } // namespace system | 156 } // namespace system |
119 } // namespace mojo | 157 } // namespace mojo |
OLD | NEW |