OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 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 "chrome/test/webdriver/session_manager.h" |
| 6 |
| 7 #ifdef OS_POSIX |
| 8 #include <netdb.h> |
| 9 #include <unistd.h> |
| 10 #include <arpa/inet.h> |
| 11 #include <net/if.h> |
| 12 #include <sys/ioctl.h> |
| 13 #include <sys/socket.h> |
| 14 #include <sys/types.h> |
| 15 #elif OS_WIN |
| 16 #include <Shellapi.h> |
| 17 #include <Winsock2.h> |
| 18 #endif |
| 19 |
| 20 #include "base/command_line.h" |
| 21 #include "base/lock.h" |
| 22 #include "base/logging.h" |
| 23 #include "base/process.h" |
| 24 #include "base/process_util.h" |
| 25 #include "base/ref_counted.h" |
| 26 #include "base/scoped_ptr.h" |
| 27 |
| 28 #include "chrome/common/chrome_constants.h" |
| 29 #include "chrome/common/chrome_switches.h" |
| 30 |
| 31 namespace webdriver { |
| 32 |
| 33 std::string SessionManager::GetIPAddress() { |
| 34 return std::string(addr_) + std::string(":") + port_; |
| 35 } |
| 36 |
| 37 std::string SessionManager::IPLookup(const std::string& nic) { |
| 38 #ifdef OS_POSIX |
| 39 int socket_conn; |
| 40 struct ifreq ifr; |
| 41 struct sockaddr_in *sin = (struct sockaddr_in *) &ifr.ifr_addr; |
| 42 |
| 43 memset(&ifr, 0, sizeof(ifr)); |
| 44 snprintf(ifr.ifr_name, IFNAMSIZ, "%s", nic.c_str()); |
| 45 sin->sin_family = AF_INET; |
| 46 |
| 47 if (0 > (socket_conn = socket(AF_INET, SOCK_STREAM, 0))) { |
| 48 return std::string(""); |
| 49 } |
| 50 |
| 51 if (0 == ioctl(socket_conn, SIOCGIFADDR, &ifr)) { |
| 52 return std::string(inet_ntoa(sin->sin_addr)); |
| 53 } |
| 54 #endif // cann't use else since a warning will be generated |
| 55 return std::string(""); |
| 56 } |
| 57 |
| 58 bool SessionManager::SetIPAddress(const std::string& p) { |
| 59 port_ = p; |
| 60 std::string prefix("192."); |
| 61 #ifdef OS_POSIX |
| 62 char buff[32]; |
| 63 |
| 64 for (int i = 0; i < 10; ++i) { |
| 65 #ifdef OS_MACOSX |
| 66 snprintf(buff, sizeof(buff), "%s%d", "en", i); |
| 67 #elif OS_LINUX |
| 68 snprintf(buff, sizeof(buff), "%s%d", "eth", i); |
| 69 #endif |
| 70 addr_ = IPLookup(std::string(buff)); |
| 71 if (addr_.length() > 0) { |
| 72 if ((addr_.compare("127.0.0.1") != 0) && |
| 73 (addr_.compare("127.0.1.1") != 0) && |
| 74 (addr_.compare(0, prefix.size(), prefix) != 0)) { |
| 75 return true; |
| 76 } |
| 77 } |
| 78 } |
| 79 return false; |
| 80 #elif OS_WIN |
| 81 hostent *h; |
| 82 char host[1024]; |
| 83 WORD wVersionRequested; |
| 84 WSADATA wsaData; |
| 85 |
| 86 memset(host, 0, sizeof host); |
| 87 wVersionRequested = MAKEWORD(2, 0); |
| 88 if (WSAStartup(wVersionRequested, &wsaData) != 0) { |
| 89 LOG(ERROR) << "Could not initialize the Windows Sockets library"; |
| 90 LOG(ERROR) << std::endl; |
| 91 return false; |
| 92 } |
| 93 if (gethostname(host, sizeof host) != 0) { |
| 94 LOG(ERROR) << "Could not find the hostname of this machine" << std::endl; |
| 95 WSACleanup(); |
| 96 return false; |
| 97 } |
| 98 h = gethostbyname(host); |
| 99 for (int i = 0; ((h->h_addr_list[i]) && (i < h->h_length)); ++i) { |
| 100 addr_ = std::string(inet_ntoa(*(struct in_addr *)h->h_addr_list[i])); |
| 101 if ((addr_.compare("127.0.0.1") != 0) && |
| 102 (addr_.compare("127.0.1.1") != 0) && |
| 103 (addr_.compare(0, prefix.size(), prefix) != 0)) { |
| 104 WSACleanup(); |
| 105 return true; |
| 106 } |
| 107 } |
| 108 |
| 109 WSACleanup(); |
| 110 return false; |
| 111 #endif |
| 112 } |
| 113 |
| 114 std::string SessionManager::GenerateSessionID() { |
| 115 static const char text[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ"\ |
| 116 "RSTUVWXYZ0123456789"; |
| 117 session_generation_.Acquire(); |
| 118 std::string id = ""; |
| 119 count_++; // for every connection made increment the global count |
| 120 for (int i = 0; i < 32; ++i) { |
| 121 #ifdef OS_POSIX |
| 122 id += text[random() % (sizeof text - 1)]; |
| 123 #else |
| 124 id += text[rand() % (sizeof text - 1)]; |
| 125 #endif |
| 126 id += count_; // append the global count to generate a unique id |
| 127 } |
| 128 session_generation_.Release(); |
| 129 return id; |
| 130 } |
| 131 |
| 132 bool SessionManager::Create(std::string* id) { |
| 133 FilePath browser_directory; // Path to the browser executable |
| 134 MessageLoop loop; |
| 135 |
| 136 *id = GenerateSessionID(); |
| 137 if (map_.find(*id) != map_.end()) { |
| 138 LOG(ERROR) << "Failed to generate a unique session ID"; |
| 139 return false; |
| 140 } |
| 141 |
| 142 // Init the commandline singleton from the env |
| 143 CommandLine::Init(0, NULL); |
| 144 |
| 145 // start chrome, if it doesn't startup in 8 seconds quit |
| 146 scoped_ptr<Session> session(new Session(*id, new AutomationProxy(8000))); |
| 147 if (session->proxy() == NULL) { |
| 148 LOG(WARNING) << "Could not allocate automation proxy" << std::endl; |
| 149 return false; |
| 150 } |
| 151 |
| 152 #if defined(OS_POSIX) |
| 153 char* user_data_dir = getenv("CHROME_UI_TESTS_USER_DATA_DIR"); |
| 154 if (user_data_dir) { |
| 155 browser_directory.Append(user_data_dir); |
| 156 } |
| 157 #endif |
| 158 |
| 159 FilePath command = |
| 160 browser_directory.Append(FilePath::FromWStringHack( |
| 161 chrome::kBrowserProcessExecutablePath)); |
| 162 CommandLine command_line(command); |
| 163 |
| 164 // setup the automation port to communicate on |
| 165 command_line.AppendSwitchASCII(switches::kAutomationClientChannelID, |
| 166 session->proxy()->channel_id()); |
| 167 |
| 168 // No first-run dialogs, please. |
| 169 command_line.AppendSwitch(switches::kNoFirstRun); |
| 170 |
| 171 // No default browser check, it would create an info-bar (if we are |
| 172 // not the default browser) that could conflicts with some tests |
| 173 // expectations. |
| 174 command_line.AppendSwitch(switches::kNoDefaultBrowserCheck); |
| 175 |
| 176 // We need cookies on file:// for things like the page cycler. |
| 177 command_line.AppendSwitch(switches::kEnableFileCookies); |
| 178 command_line.AppendSwitch(switches::kDomAutomationController); |
| 179 command_line.AppendSwitch(switches::kFullMemoryCrashReport); |
| 180 |
| 181 // create a temp directory for the new profile |
| 182 if (!session->CreateTemporaryProfileDirectory()) { |
| 183 LOG(ERROR) << "Could not make a temp profile directory, " |
| 184 << session->tmp_profile_dir() << std::endl; |
| 185 LOG(ERROR) << "Need to quit, the issue must be fixed" << std::endl; |
| 186 exit(-1); |
| 187 } |
| 188 |
| 189 command_line.AppendSwitchASCII(switches::kUserDataDir, |
| 190 session->tmp_profile_dir()); |
| 191 |
| 192 base::ProcessHandle process_handle; |
| 193 #if defined(OS_WIN) |
| 194 base::LaunchApp(command_line, false, true, &process_handle); |
| 195 #elif defined(OS_POSIX) |
| 196 // Sometimes one needs to run the browser under a special environment |
| 197 // (e.g. valgrind) without also running the test harness (e.g. python) |
| 198 // under the special environment. Provide a way to wrap the browser |
| 199 // commandline with a special prefix to invoke the special environment. |
| 200 const char* browser_wrapper = getenv("BROWSER_WRAPPER"); |
| 201 |
| 202 if (browser_wrapper) { |
| 203 command_line.PrependWrapper(browser_wrapper); |
| 204 LOG(INFO) << "BROWSER_WRAPPER was set, prefixing command_line with " |
| 205 << browser_wrapper; |
| 206 } |
| 207 |
| 208 base::LaunchApp(command_line.argv(), session->proxy()->fds_to_map(), false, |
| 209 &process_handle); |
| 210 #endif |
| 211 |
| 212 if (!session->Init(process_handle)) { |
| 213 LOG(WARNING) << "Failed to initialize session"; |
| 214 return false; |
| 215 } |
| 216 |
| 217 LOG(INFO) << "New session was created: " << id << std::endl; |
| 218 map_[*id] = session.release(); |
| 219 return true; |
| 220 } |
| 221 |
| 222 bool SessionManager::Has(const std::string& id) const { |
| 223 return map_.find(id) != map_.end(); |
| 224 } |
| 225 |
| 226 bool SessionManager::Delete(const std::string& id) { |
| 227 std::map<std::string, Session*>::iterator it; |
| 228 |
| 229 LOG(INFO) << "Deleting session with ID " << id; |
| 230 it = map_.find(id); |
| 231 if (it == map_.end()) { |
| 232 LOG(INFO) << "No such session with ID " << id; |
| 233 return false; |
| 234 } |
| 235 |
| 236 it->second->Terminate(); |
| 237 map_.erase(it); |
| 238 return true; |
| 239 } |
| 240 |
| 241 Session* SessionManager::GetSession(const std::string& id) const { |
| 242 std::map<std::string, Session*>::const_iterator it; |
| 243 it = map_.find(id); |
| 244 if (it == map_.end()) { |
| 245 LOG(INFO) << "No such session with ID " << id; |
| 246 return NULL; |
| 247 } |
| 248 return it->second; |
| 249 } |
| 250 } // namespace webdriver |
| 251 |
OLD | NEW |