Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
|
Peter Beverloo
2016/12/13 12:15:34
micro nit: 2016
jbudorick
2016/12/14 02:21:59
Done.
| |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "content/shell/browser/layout_test/scoped_android_configuration.h" | |
| 6 | |
| 7 #include <fcntl.h> | |
| 8 #include <iostream> | |
| 9 #include <memory> | |
| 10 | |
| 11 #include "base/android/context_utils.h" | |
| 12 #include "base/android/jni_android.h" | |
| 13 #include "base/android/jni_string.h" | |
| 14 #include "base/command_line.h" | |
| 15 #include "base/files/file_path.h" | |
| 16 #include "base/message_loop/message_loop.h" | |
| 17 #include "base/strings/string_number_conversions.h" | |
| 18 #include "base/synchronization/waitable_event.h" | |
| 19 #include "base/test/test_support_android.h" | |
| 20 #include "content/public/browser/browser_thread.h" | |
| 21 #include "content/public/test/nested_message_pump_android.h" | |
| 22 #include "content/shell/browser/layout_test/blink_test_controller.h" | |
| 23 #include "content/shell/common/layout_test/layout_test_switches.h" | |
| 24 #include "content/shell/common/shell_switches.h" | |
| 25 #include "jni/ShellLayoutTestUtils_jni.h" | |
| 26 #include "net/base/ip_address.h" | |
| 27 #include "net/base/ip_endpoint.h" | |
| 28 #include "net/base/net_errors.h" | |
| 29 #include "net/base/sockaddr_storage.h" | |
| 30 #include "net/socket/socket_posix.h" | |
| 31 #include "url/gurl.h" | |
| 32 | |
| 33 using base::android::ScopedJavaLocalRef; | |
| 34 | |
| 35 namespace content { | |
| 36 | |
| 37 namespace { | |
| 38 | |
| 39 std::unique_ptr<base::MessagePump> CreateMessagePumpForUI() { | |
| 40 return std::unique_ptr<base::MessagePump>(new NestedMessagePumpAndroid()); | |
| 41 } | |
| 42 | |
| 43 void ConnectCompleted(const base::Closure& socket_connected, int rv) { | |
| 44 CHECK_EQ(net::OK, rv) << " Failed to redirect to socket: " | |
| 45 << net::ErrorToString(rv); | |
|
Peter Beverloo
2016/12/13 12:15:34
nit: here and elsewhere -- we no longer use detail
jbudorick
2016/12/14 02:21:59
Switched to LOG_IF(FATAL, condition) << "msg";
| |
| 46 socket_connected.Run(); | |
| 47 } | |
| 48 | |
| 49 void CreateAndConnectSocket( | |
| 50 uint16_t port, | |
| 51 const base::Callback<void(std::unique_ptr<net::SocketPosix>)>& | |
| 52 socket_connected) { | |
| 53 net::SockaddrStorage storage; | |
| 54 net::IPAddress address; | |
| 55 CHECK(address.AssignFromIPLiteral("127.0.0.1")) | |
| 56 << "Failed to create IPAddress from IP literal 127.0.0.1."; | |
| 57 net::IPEndPoint endpoint(address, port); | |
| 58 CHECK(endpoint.ToSockAddr(storage.addr, &storage.addr_len)) | |
| 59 << "Failed to convert " << endpoint.ToString() << " to sockaddr."; | |
| 60 | |
| 61 std::unique_ptr<net::SocketPosix> socket(new net::SocketPosix); | |
|
Peter Beverloo
2016/12/13 12:15:34
micro nit - prefer the following as it avoids the
jbudorick
2016/12/14 02:21:59
Done.
| |
| 62 | |
| 63 int result = socket->Open(AF_INET); | |
| 64 CHECK_EQ(net::OK, result) << "Failed to open socket for " | |
| 65 << endpoint.ToString() << ": " | |
| 66 << net::ErrorToString(result); | |
| 67 | |
| 68 // Set the socket as blocking. | |
| 69 const int flags = fcntl(socket->socket_fd(), F_GETFL); | |
| 70 CHECK_NE(flags, -1); | |
| 71 if (flags & O_NONBLOCK) { | |
| 72 fcntl(socket->socket_fd(), F_SETFL, flags & ~O_NONBLOCK); | |
| 73 } | |
| 74 | |
| 75 net::SocketPosix* socket_ptr = socket.get(); | |
| 76 net::CompletionCallback connect_completed = | |
| 77 base::Bind(&ConnectCompleted, | |
| 78 base::Bind(socket_connected, base::Passed(std::move(socket)))); | |
| 79 result = socket_ptr->Connect(storage, connect_completed); | |
| 80 if (result != net::ERR_IO_PENDING) { | |
| 81 connect_completed.Run(result); | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 void RedirectStdout(int fd) { | |
| 86 CHECK_NE(dup2(fd, STDOUT_FILENO), -1) << "Failed to dup2 stdout: " | |
| 87 << strerror(errno); | |
| 88 } | |
| 89 | |
| 90 void RedirectStdin(int fd) { | |
| 91 CHECK_NE(dup2(fd, STDIN_FILENO), -1) << "Failed to dup2 stdin: " | |
| 92 << strerror(errno); | |
| 93 } | |
| 94 | |
| 95 void RedirectStderr(int fd) { | |
| 96 CHECK_NE(dup2(fd, STDERR_FILENO), -1) << "Failed to dup2 stderr: " | |
| 97 << strerror(errno); | |
| 98 } | |
| 99 | |
| 100 void FinishRedirection( | |
| 101 const base::Callback<void(int)>& redirect, | |
| 102 const base::Callback<void(std::unique_ptr<net::SocketPosix>)>& | |
| 103 transfer_socket, | |
| 104 base::WaitableEvent* event, | |
| 105 std::unique_ptr<net::SocketPosix> socket) { | |
| 106 redirect.Run(socket->socket_fd()); | |
| 107 transfer_socket.Run(std::move(socket)); | |
| 108 event->Signal(); | |
| 109 } | |
| 110 | |
| 111 void RedirectStream( | |
| 112 uint16_t port, | |
| 113 const base::Callback<void(base::WaitableEvent*, | |
| 114 std::unique_ptr<net::SocketPosix>)>& | |
| 115 finish_redirection) { | |
| 116 base::WaitableEvent redirected( | |
| 117 base::WaitableEvent::ResetPolicy::MANUAL, | |
| 118 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
| 119 BrowserThread::PostTask( | |
| 120 BrowserThread::IO, FROM_HERE, | |
| 121 base::Bind(&CreateAndConnectSocket, port, | |
| 122 base::Bind(finish_redirection, &redirected))); | |
| 123 ScopedAllowWaitForAndroidLayoutTests allow_wait; | |
| 124 while (!redirected.IsSignaled()) | |
| 125 redirected.Wait(); | |
| 126 } | |
| 127 | |
| 128 } // namespace | |
| 129 | |
| 130 ScopedAndroidConfiguration::ScopedAndroidConfiguration() : sockets_() { | |
| 131 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 132 ScopedJavaLocalRef<jstring> jtest_data_dir = | |
| 133 Java_ShellLayoutTestUtils_getIsolatedTestRoot(env); | |
| 134 base::FilePath test_data_dir( | |
| 135 base::android::ConvertJavaStringToUTF8(env, jtest_data_dir)); | |
| 136 base::InitAndroidTestPaths(test_data_dir); | |
| 137 | |
| 138 bool success = | |
| 139 base::MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUI); | |
| 140 CHECK(success) << "Unable to initialize the message pump for Android."; | |
| 141 } | |
| 142 | |
| 143 ScopedAndroidConfiguration::~ScopedAndroidConfiguration() = default; | |
| 144 | |
| 145 void ScopedAndroidConfiguration::RedirectStreams() { | |
| 146 // Unretained is safe here because all executions of add_socket finish | |
| 147 // before this function returns. | |
| 148 base::Callback<void(std::unique_ptr<net::SocketPosix>)> add_socket = | |
| 149 base::Bind(&ScopedAndroidConfiguration::AddSocket, | |
| 150 base::Unretained(this)); | |
| 151 | |
| 152 std::string stdout_port_str = | |
| 153 base::CommandLine::ForCurrentProcess()->GetSwitchValueNative( | |
| 154 switches::kAndroidStdoutPort); | |
| 155 unsigned stdout_port = 0; | |
| 156 if (base::StringToUint(stdout_port_str, &stdout_port)) { | |
| 157 RedirectStream(base::checked_cast<uint16_t>(stdout_port), | |
| 158 base::Bind(&FinishRedirection, base::Bind(&RedirectStdout), | |
| 159 add_socket)); | |
| 160 } | |
| 161 | |
| 162 std::string stdin_port_str = | |
| 163 base::CommandLine::ForCurrentProcess()->GetSwitchValueNative( | |
| 164 switches::kAndroidStdinPort); | |
| 165 unsigned stdin_port = 0; | |
| 166 if (base::StringToUint(stdin_port_str, &stdin_port)) { | |
| 167 RedirectStream( | |
| 168 base::checked_cast<uint16_t>(stdin_port), | |
| 169 base::Bind(&FinishRedirection, base::Bind(&RedirectStdin), add_socket)); | |
| 170 } | |
| 171 | |
| 172 std::string stderr_port_str = | |
| 173 base::CommandLine::ForCurrentProcess()->GetSwitchValueNative( | |
| 174 switches::kAndroidStderrPort); | |
| 175 unsigned stderr_port = 0; | |
| 176 if (base::StringToUint(stderr_port_str, &stderr_port)) { | |
| 177 RedirectStream(base::checked_cast<uint16_t>(stderr_port), | |
| 178 base::Bind(&FinishRedirection, base::Bind(&RedirectStderr), | |
| 179 add_socket)); | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 void ScopedAndroidConfiguration::AddSocket( | |
| 184 std::unique_ptr<net::SocketPosix> socket) { | |
| 185 sockets_.push_back(std::move(socket)); | |
| 186 } | |
| 187 | |
| 188 } // namespace content | |
| OLD | NEW |