| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "base/strings/string_number_conversions.h" | 5 #include "base/strings/string_number_conversions.h" |
| 6 #include "base/strings/string_split.h" | 6 #include "base/strings/string_split.h" |
| 7 #include "base/strings/string_util.h" | 7 #include "base/strings/string_util.h" |
| 8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
| 9 #include "chrome/browser/devtools/device/android_device_manager.h" | 9 #include "chrome/browser/devtools/device/android_device_manager.h" |
| 10 | 10 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 | 117 |
| 118 using StringMap = std::map<std::string, std::string>; | 118 using StringMap = std::map<std::string, std::string>; |
| 119 | 119 |
| 120 void MapProcessesToPackages(const std::string& response, | 120 void MapProcessesToPackages(const std::string& response, |
| 121 StringMap* pid_to_package, | 121 StringMap* pid_to_package, |
| 122 StringMap* pid_to_user) { | 122 StringMap* pid_to_user) { |
| 123 // Parse 'ps' output which on Android looks like this: | 123 // Parse 'ps' output which on Android looks like this: |
| 124 // | 124 // |
| 125 // USER PID PPID VSIZE RSS WCHAN PC ? NAME | 125 // USER PID PPID VSIZE RSS WCHAN PC ? NAME |
| 126 // | 126 // |
| 127 std::vector<std::string> entries; | 127 for (const base::StringPiece& line : |
| 128 Tokenize(response, "\n", &entries); | 128 base::SplitStringPiece(response, "\n", base::KEEP_WHITESPACE, |
| 129 for (size_t i = 1; i < entries.size(); ++i) { | 129 base::SPLIT_WANT_NONEMPTY)) { |
| 130 std::vector<std::string> fields; | 130 std::vector<std::string> fields = |
| 131 Tokenize(entries[i], " \r", &fields); | 131 base::SplitString(line, " \r", base::KEEP_WHITESPACE, |
| 132 base::SPLIT_WANT_NONEMPTY); |
| 132 if (fields.size() < 9) | 133 if (fields.size() < 9) |
| 133 continue; | 134 continue; |
| 134 std::string pid = fields[1]; | 135 std::string pid = fields[1]; |
| 135 (*pid_to_package)[pid] = fields[8]; | 136 (*pid_to_package)[pid] = fields[8]; |
| 136 (*pid_to_user)[pid] = fields[0]; | 137 (*pid_to_user)[pid] = fields[0]; |
| 137 } | 138 } |
| 138 } | 139 } |
| 139 | 140 |
| 140 StringMap MapSocketsToProcesses(const std::string& response) { | 141 StringMap MapSocketsToProcesses(const std::string& response) { |
| 141 // Parse 'cat /proc/net/unix' output which on Android looks like this: | 142 // Parse 'cat /proc/net/unix' output which on Android looks like this: |
| 142 // | 143 // |
| 143 // Num RefCount Protocol Flags Type St Inode Path | 144 // Num RefCount Protocol Flags Type St Inode Path |
| 144 // 00000000: 00000002 00000000 00010000 0001 01 331813 /dev/socket/zygote | 145 // 00000000: 00000002 00000000 00010000 0001 01 331813 /dev/socket/zygote |
| 145 // 00000000: 00000002 00000000 00010000 0001 01 358606 @xxx_devtools_remote | 146 // 00000000: 00000002 00000000 00010000 0001 01 358606 @xxx_devtools_remote |
| 146 // 00000000: 00000002 00000000 00010000 0001 01 347300 @yyy_devtools_remote | 147 // 00000000: 00000002 00000000 00010000 0001 01 347300 @yyy_devtools_remote |
| 147 // | 148 // |
| 148 // We need to find records with paths starting from '@' (abstract socket) | 149 // We need to find records with paths starting from '@' (abstract socket) |
| 149 // and containing the channel pattern ("_devtools_remote"). | 150 // and containing the channel pattern ("_devtools_remote"). |
| 150 StringMap socket_to_pid; | 151 StringMap socket_to_pid; |
| 151 std::vector<std::string> entries; | 152 for (const base::StringPiece& line : |
| 152 Tokenize(response, "\n", &entries); | 153 base::SplitStringPiece(response, "\n", base::KEEP_WHITESPACE, |
| 153 for (size_t i = 1; i < entries.size(); ++i) { | 154 base::SPLIT_WANT_NONEMPTY)) { |
| 154 std::vector<std::string> fields; | 155 std::vector<std::string> fields = |
| 155 Tokenize(entries[i], " \r", &fields); | 156 base::SplitString(line, " \r", base::KEEP_WHITESPACE, |
| 157 base::SPLIT_WANT_NONEMPTY); |
| 156 if (fields.size() < 8) | 158 if (fields.size() < 8) |
| 157 continue; | 159 continue; |
| 158 if (fields[3] != "00010000" || fields[5] != "01") | 160 if (fields[3] != "00010000" || fields[5] != "01") |
| 159 continue; | 161 continue; |
| 160 std::string path_field = fields[7]; | 162 std::string path_field = fields[7]; |
| 161 if (path_field.size() < 1 || path_field[0] != '@') | 163 if (path_field.size() < 1 || path_field[0] != '@') |
| 162 continue; | 164 continue; |
| 163 size_t socket_name_pos = path_field.find(kDevToolsSocketSuffix); | 165 size_t socket_name_pos = path_field.find(kDevToolsSocketSuffix); |
| 164 if (socket_name_pos == std::string::npos) | 166 if (socket_name_pos == std::string::npos) |
| 165 continue; | 167 continue; |
| 166 | 168 |
| 167 std::string socket = path_field.substr(1); | 169 std::string socket = path_field.substr(1); |
| 168 | 170 |
| 169 std::string pid; | 171 std::string pid; |
| 170 size_t socket_name_end = socket_name_pos + strlen(kDevToolsSocketSuffix); | 172 size_t socket_name_end = socket_name_pos + strlen(kDevToolsSocketSuffix); |
| 171 if (socket_name_end < path_field.size() && | 173 if (socket_name_end < path_field.size() && |
| 172 path_field[socket_name_end] == '_') { | 174 path_field[socket_name_end] == '_') { |
| 173 pid = path_field.substr(socket_name_end + 1); | 175 pid = path_field.substr(socket_name_end + 1); |
| 174 } | 176 } |
| 175 socket_to_pid[socket] = pid; | 177 socket_to_pid[socket] = pid; |
| 176 } | 178 } |
| 177 return socket_to_pid; | 179 return socket_to_pid; |
| 178 } | 180 } |
| 179 | 181 |
| 180 gfx::Size ParseScreenSize(const std::string& str) { | 182 gfx::Size ParseScreenSize(base::StringPiece str) { |
| 181 std::vector<std::string> pairs; | 183 std::vector<base::StringPiece> pairs = |
| 182 Tokenize(str, "-", &pairs); | 184 base::SplitStringPiece(str, "-", base::KEEP_WHITESPACE, |
| 185 base::SPLIT_WANT_NONEMPTY); |
| 183 if (pairs.size() != 2) | 186 if (pairs.size() != 2) |
| 184 return gfx::Size(); | 187 return gfx::Size(); |
| 185 | 188 |
| 186 int width; | 189 int width; |
| 187 int height; | 190 int height; |
| 188 std::vector<std::string> numbers; | 191 std::vector<base::StringPiece> numbers = |
| 189 Tokenize(pairs[1].substr(1, pairs[1].size() - 2), ",", &numbers); | 192 base::SplitStringPiece(pairs[1].substr(1, pairs[1].size() - 2), ",", |
| 193 base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| 190 if (numbers.size() != 2 || | 194 if (numbers.size() != 2 || |
| 191 !base::StringToInt(numbers[0], &width) || | 195 !base::StringToInt(numbers[0], &width) || |
| 192 !base::StringToInt(numbers[1], &height)) | 196 !base::StringToInt(numbers[1], &height)) |
| 193 return gfx::Size(); | 197 return gfx::Size(); |
| 194 | 198 |
| 195 return gfx::Size(width, height); | 199 return gfx::Size(width, height); |
| 196 } | 200 } |
| 197 | 201 |
| 198 gfx::Size ParseWindowPolicyResponse(const std::string& response) { | 202 gfx::Size ParseWindowPolicyResponse(const std::string& response) { |
| 199 std::vector<std::string> lines; | 203 for (const base::StringPiece& line : |
| 200 Tokenize(response, "\r", &lines); | 204 base::SplitStringPiece(response, "\r", base::KEEP_WHITESPACE, |
| 201 for (const std::string& line : lines) { | 205 base::SPLIT_WANT_NONEMPTY)) { |
| 202 size_t pos = line.find(kScreenSizePrefix); | 206 size_t pos = line.find(kScreenSizePrefix); |
| 203 if (pos != std::string::npos) { | 207 if (pos != base::StringPiece::npos) { |
| 204 return ParseScreenSize( | 208 return ParseScreenSize( |
| 205 line.substr(pos + strlen(kScreenSizePrefix))); | 209 line.substr(pos + strlen(kScreenSizePrefix))); |
| 206 } | 210 } |
| 207 } | 211 } |
| 208 return gfx::Size(); | 212 return gfx::Size(); |
| 209 } | 213 } |
| 210 | 214 |
| 211 StringMap MapIdsToUsers(const std::string& response) { | 215 StringMap MapIdsToUsers(const std::string& response) { |
| 212 // Parse 'dumpsys user' output which looks like this: | 216 // Parse 'dumpsys user' output which looks like this: |
| 213 // Users: | 217 // Users: |
| 214 // UserInfo{0:Test User:13} serialNo=0 | 218 // UserInfo{0:Test User:13} serialNo=0 |
| 215 // Created: <unknown> | 219 // Created: <unknown> |
| 216 // Last logged in: +17m18s871ms ago | 220 // Last logged in: +17m18s871ms ago |
| 217 // UserInfo{10:User with : (colon):10} serialNo=10 | 221 // UserInfo{10:User with : (colon):10} serialNo=10 |
| 218 // Created: +3d4h35m1s139ms ago | 222 // Created: +3d4h35m1s139ms ago |
| 219 // Last logged in: +17m26s287ms ago | 223 // Last logged in: +17m26s287ms ago |
| 220 StringMap id_to_username; | 224 StringMap id_to_username; |
| 221 std::vector<std::string> lines; | 225 for (const base::StringPiece& line : |
| 222 Tokenize(response, "\r", &lines); | 226 base::SplitStringPiece(response, "\r", base::KEEP_WHITESPACE, |
| 223 for (const std::string& line : lines) { | 227 base::SPLIT_WANT_NONEMPTY)) { |
| 224 size_t pos = line.find(kUserInfoPrefix); | 228 size_t pos = line.find(kUserInfoPrefix); |
| 225 if (pos != std::string::npos) { | 229 if (pos != std::string::npos) { |
| 226 std::string fields = line.substr(pos + strlen(kUserInfoPrefix)); | 230 base::StringPiece fields = line.substr(pos + strlen(kUserInfoPrefix)); |
| 227 size_t first_pos = fields.find_first_of(":"); | 231 size_t first_pos = fields.find_first_of(":"); |
| 228 size_t last_pos = fields.find_last_of(":"); | 232 size_t last_pos = fields.find_last_of(":"); |
| 229 if (first_pos != std::string::npos && last_pos != std::string::npos) { | 233 if (first_pos != std::string::npos && last_pos != std::string::npos) { |
| 230 std::string id = fields.substr(0, first_pos); | 234 std::string id = fields.substr(0, first_pos).as_string(); |
| 231 std::string name = fields.substr(first_pos + 1, | 235 std::string name = fields.substr(first_pos + 1, |
| 232 last_pos - first_pos - 1); | 236 last_pos - first_pos - 1).as_string(); |
| 233 id_to_username[id] = name; | 237 id_to_username[id] = name; |
| 234 } | 238 } |
| 235 } | 239 } |
| 236 } | 240 } |
| 237 return id_to_username; | 241 return id_to_username; |
| 238 } | 242 } |
| 239 | 243 |
| 240 std::string GetUserName(const std::string& unix_user, | 244 std::string GetUserName(const std::string& unix_user, |
| 241 const StringMap id_to_username) { | 245 const StringMap id_to_username) { |
| 242 // Parse username as returned by ps which looks like 'u0_a31' | 246 // Parse username as returned by ps which looks like 'u0_a31' |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 } | 354 } |
| 351 | 355 |
| 352 // static | 356 // static |
| 353 void AndroidDeviceManager::QueryDeviceInfo( | 357 void AndroidDeviceManager::QueryDeviceInfo( |
| 354 const RunCommandCallback& command_callback, | 358 const RunCommandCallback& command_callback, |
| 355 const DeviceInfoCallback& callback) { | 359 const DeviceInfoCallback& callback) { |
| 356 command_callback.Run( | 360 command_callback.Run( |
| 357 kAllCommands, | 361 kAllCommands, |
| 358 base::Bind(&ReceivedResponse, callback)); | 362 base::Bind(&ReceivedResponse, callback)); |
| 359 } | 363 } |
| OLD | NEW |