OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 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/browser/devtools/android_device.h" |
| 6 #include "chrome/browser/devtools/devtools_adb_bridge.h" |
| 7 #include "chrome/browser/devtools/devtools_target_impl.h" |
| 8 #include "chrome/browser/ui/browser.h" |
| 9 #include "chrome/test/base/in_process_browser_test.h" |
| 10 #include "content/public/test/test_utils.h" |
| 11 |
| 12 const char kDeviceModelCommand[] = "shell:getprop ro.product.model"; |
| 13 const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix"; |
| 14 const char kListProcessesCommand[] = "shell:ps"; |
| 15 const char kDumpsysCommand[] = "shell:dumpsys window policy"; |
| 16 |
| 17 const char kPageListRequest[] = "GET /json HTTP/1.1\r\n\r\n"; |
| 18 const char kVersionRequest[] = "GET /json/version HTTP/1.1\r\n\r\n"; |
| 19 |
| 20 const char kSampleOpenedUnixSockets[] = |
| 21 "Num RefCount Protocol Flags Type St Inode Path\n" |
| 22 "00000000: 00000004 00000000" |
| 23 " 00000000 0002 01 3328 /dev/socket/wpa_wlan0\n" |
| 24 "00000000: 00000002 00000000" |
| 25 " 00010000 0001 01 5394 /dev/socket/vold\n" |
| 26 "00000000: 00000002 00000000" |
| 27 " 00010000 0001 01 11810 @webview_devtools_remote_2425\n" |
| 28 "00000000: 00000002 00000000" |
| 29 " 00010000 0001 01 20893 @chrome_devtools_remote\n"; |
| 30 |
| 31 const char kSampleListProcesses[] = |
| 32 "USER PID PPID VSIZE RSS WCHAN PC NAME\n" |
| 33 "root 1 0 688 508 ffffffff 00000000 S /init\n" |
| 34 "u0_a75 2425 123 933736 193024 ffffffff 00000000 S com.sample.feed\n" |
| 35 "nfc 741 123 706448 26316 ffffffff 00000000 S com.android.nfc"; |
| 36 |
| 37 const char kSampleDumpsysCommand[] = |
| 38 "WINDOW MANAGER POLICY STATE (dumpsys window policy)\r\n" |
| 39 " mSafeMode=false mSystemReady=true mSystemBooted=true\r\n" |
| 40 " mStable=(0,50)-(720,1184)\r\n" // Only mStable parameter is parsed |
| 41 " mForceStatusBar=false mForceStatusBarFromKeyguard=false\r\n"; |
| 42 |
| 43 char kSampleChromeVersion[] = "{\n" |
| 44 " \"Browser\": \"Chrome/32.0.1679.0\",\n" |
| 45 " \"Protocol-Version\": \"1.0\",\n" |
| 46 " \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " |
| 47 "(KHTML, like Gecko) Chrome/32.0.1679.0 Safari/537.36\",\n" |
| 48 " \"WebKit-Version\": \"537.36 (@160162)\"\n" |
| 49 "}"; |
| 50 |
| 51 char kSampleWebViewVersion[] = "{\n" |
| 52 " \"Browser\": \"Version/4.0\",\n" |
| 53 " \"Protocol-Version\": \"1.0\",\n" |
| 54 " \"User-Agent\": \"Mozilla/5.0 (Linux; Android 4.3; Build/KRS74B) " |
| 55 "AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Safari/537.36\",\n" |
| 56 " \"WebKit-Version\": \"537.36 (@157588)\"\n" |
| 57 "}"; |
| 58 |
| 59 char kSampleChromePages[] = "[ {\n" |
| 60 " \"description\": \"\",\n" |
| 61 " \"devtoolsFrontendUrl\": \"/devtools/devtools.html?" |
| 62 "ws=/devtools/page/755DE5C9-D49F-811D-0693-51B8E15C80D2\",\n" |
| 63 " \"id\": \"755DE5C9-D49F-811D-0693-51B8E15C80D2\",\n" |
| 64 " \"title\": \"The Chromium Projects\",\n" |
| 65 " \"type\": \"page\",\n" |
| 66 " \"url\": \"http://www.chromium.org/\",\n" |
| 67 " \"webSocketDebuggerUrl\": \"" |
| 68 "ws:///devtools/page/755DE5C9-D49F-811D-0693-51B8E15C80D2\"\n" |
| 69 "} ]"; |
| 70 |
| 71 char kSampleWebViewPages[] = "[ {\n" |
| 72 " \"description\": \"{\\\"attached\\\":false,\\\"empty\\\":false," |
| 73 "\\\"height\\\":1173,\\\"screenX\\\":0,\\\"screenY\\\":0," |
| 74 "\\\"visible\\\":true,\\\"width\\\":800}\",\n" |
| 75 " \"devtoolsFrontendUrl\": \"http://chrome-devtools-frontend.appspot.com/" |
| 76 "serve_rev/@157588/devtools.html?ws=" |
| 77 "/devtools/page/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n" |
| 78 " \"faviconUrl\": \"http://chromium.org/favicon.ico\",\n" |
| 79 " \"id\": \"3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n" |
| 80 " \"thumbnailUrl\": \"/thumb/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n" |
| 81 " \"title\": \"Blink - The Chromium Projects\",\n" |
| 82 " \"type\": \"page\",\n" |
| 83 " \"url\": \"http://www.chromium.org/blink\",\n" |
| 84 " \"webSocketDebuggerUrl\": \"ws:///devtools/" |
| 85 "page/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\"\n" |
| 86 "}, {\n" |
| 87 " \"description\": \"{\\\"attached\\\":true,\\\"empty\\\":true," |
| 88 "\\\"screenX\\\":0,\\\"screenY\\\":33,\\\"visible\\\":false}\",\n" |
| 89 " \"devtoolsFrontendUrl\": \"http://chrome-devtools-frontend.appspot.com/" |
| 90 "serve_rev/@157588/devtools.html?ws=" |
| 91 "/devtools/page/44681551-ADFD-2411-076B-3AB14C1C60E2\",\n" |
| 92 " \"faviconUrl\": \"\",\n" |
| 93 " \"id\": \"44681551-ADFD-2411-076B-3AB14C1C60E2\",\n" |
| 94 " \"thumbnailUrl\": \"/thumb/44681551-ADFD-2411-076B-3AB14C1C60E2\",\n" |
| 95 " \"title\": \"More Activity\",\n" |
| 96 " \"type\": \"page\",\n" |
| 97 " \"url\": \"about:blank\",\n" |
| 98 " \"webSocketDebuggerUrl\": \"ws:///devtools/page/" |
| 99 "44681551-ADFD-2411-076B-3AB14C1C60E2\"\n" |
| 100 "}]"; |
| 101 |
| 102 class MockDeviceImpl : public AndroidDevice { |
| 103 public: |
| 104 MockDeviceImpl(const std::string& serial, int index, |
| 105 bool connected, const char* device_model) |
| 106 : AndroidDevice(serial, connected), |
| 107 device_model_(device_model) |
| 108 {} |
| 109 |
| 110 virtual void RunCommand(const std::string& command, |
| 111 const CommandCallback& callback) OVERRIDE { |
| 112 const char* response; |
| 113 |
| 114 if (command == kDeviceModelCommand) |
| 115 response = device_model_; |
| 116 else if (command == kOpenedUnixSocketsCommand) |
| 117 response = kSampleOpenedUnixSockets; |
| 118 else if (command == kListProcessesCommand) |
| 119 response = kSampleListProcesses; |
| 120 else if (command == kDumpsysCommand) |
| 121 response = kSampleDumpsysCommand; |
| 122 else |
| 123 NOTREACHED(); |
| 124 |
| 125 base::MessageLoop::current()->PostTask( FROM_HERE, |
| 126 base::Bind(&MockDeviceImpl::RunCommandCallback, |
| 127 this, callback, 0, response)); |
| 128 } |
| 129 |
| 130 void RunCommandCallback(const CommandCallback& callback, int result, |
| 131 const std::string& response) { |
| 132 callback.Run(result, response); |
| 133 } |
| 134 |
| 135 virtual void OpenSocket(const std::string& name, |
| 136 const SocketCallback& callback) OVERRIDE { |
| 137 NOTREACHED(); |
| 138 } |
| 139 |
| 140 virtual void HttpQuery(const std::string& la_name, |
| 141 const std::string& request, |
| 142 const CommandCallback& callback) OVERRIDE { |
| 143 const char* response; |
| 144 |
| 145 if (la_name == "chrome_devtools_remote") { |
| 146 if (request == kVersionRequest) |
| 147 response = kSampleChromeVersion; |
| 148 else if (request == kPageListRequest) |
| 149 response = kSampleChromePages; |
| 150 else |
| 151 NOTREACHED(); |
| 152 } else if (la_name == "webview_devtools_remote_2425") { |
| 153 if (request == kVersionRequest) |
| 154 response = kSampleWebViewVersion; |
| 155 else if (request == kPageListRequest) |
| 156 response = kSampleWebViewPages; |
| 157 else |
| 158 NOTREACHED(); |
| 159 } else { |
| 160 NOTREACHED(); |
| 161 } |
| 162 |
| 163 base::MessageLoop::current()->PostTask( FROM_HERE, |
| 164 base::Bind(&MockDeviceImpl::RunCommandCallback, |
| 165 this, callback, 0, response)); |
| 166 } |
| 167 |
| 168 virtual void HttpUpgrade(const std::string& la_name, |
| 169 const std::string& request, |
| 170 const SocketCallback& callback) { |
| 171 NOTREACHED(); |
| 172 } |
| 173 |
| 174 virtual void HttpQueryCallback(const CommandCallback& next, int code, |
| 175 const std::string& result) { |
| 176 NOTREACHED(); |
| 177 } |
| 178 |
| 179 private: |
| 180 virtual ~MockDeviceImpl() |
| 181 {} |
| 182 |
| 183 const char* device_model_; |
| 184 }; |
| 185 |
| 186 class MockDeviceProvider : public AndroidDeviceProvider { |
| 187 virtual ~MockDeviceProvider() |
| 188 {} |
| 189 |
| 190 virtual void QueryDevices(const QueryDevicesCallback& callback) OVERRIDE { |
| 191 AndroidDeviceProvider::AndroidDevices devices; |
| 192 devices.push_back(new MockDeviceImpl("FirstDevice", 0, true, "Nexus 6")); |
| 193 devices.push_back(new MockDeviceImpl("SecondDevice", 1, false, "Nexus 8")); |
| 194 callback.Run(devices); |
| 195 } |
| 196 }; |
| 197 |
| 198 |
| 199 class DevToolsAdbBridgeTest : public InProcessBrowserTest, |
| 200 public DevToolsAdbBridge::Listener { |
| 201 typedef DevToolsAdbBridge::RemoteDevices::const_iterator rdci; |
| 202 typedef DevToolsAdbBridge::RemoteBrowsers::const_iterator rbci; |
| 203 public: |
| 204 virtual void RemoteDevicesChanged( |
| 205 DevToolsAdbBridge::RemoteDevices* devices) OVERRIDE{ |
| 206 ASSERT_EQ(2U, devices->size()); |
| 207 |
| 208 scoped_refptr<DevToolsAdbBridge::RemoteDevice> connected = |
| 209 (*devices)[0]->IsConnected() ? (*devices)[0] : (*devices)[1]; |
| 210 |
| 211 scoped_refptr<DevToolsAdbBridge::RemoteDevice> not_connected = |
| 212 (*devices)[0]->IsConnected() ? (*devices)[1] : (*devices)[0]; |
| 213 |
| 214 ASSERT_TRUE(connected->IsConnected()); |
| 215 ASSERT_FALSE(not_connected->IsConnected()); |
| 216 |
| 217 ASSERT_EQ(720, connected->screen_size().width()); |
| 218 ASSERT_EQ(1184, connected->screen_size().height()); |
| 219 |
| 220 ASSERT_EQ("FirstDevice", connected->GetSerial()); |
| 221 ASSERT_EQ("Nexus 6", connected->GetModel()); |
| 222 |
| 223 ASSERT_EQ("SecondDevice", not_connected->GetSerial()); |
| 224 ASSERT_EQ("Offline", not_connected->GetModel()); |
| 225 |
| 226 const DevToolsAdbBridge::RemoteBrowsers& browsers = connected->browsers(); |
| 227 ASSERT_EQ(2U, browsers.size()); |
| 228 |
| 229 scoped_refptr<DevToolsAdbBridge::RemoteBrowser> chrome = |
| 230 browsers[0]->product() == "Chrome" ? browsers[0] : browsers[1]; |
| 231 |
| 232 scoped_refptr<DevToolsAdbBridge::RemoteBrowser> webview = |
| 233 browsers[0]->product() == "Chrome" ? browsers[1] : browsers[0]; |
| 234 |
| 235 ASSERT_EQ("Chrome", chrome->product()); |
| 236 ASSERT_EQ("32.0.1679.0", chrome->version()); |
| 237 |
| 238 ASSERT_EQ("Webview", webview->product()); |
| 239 ASSERT_EQ("4.0", webview->version()); |
| 240 |
| 241 // Check that we parse process list properly. |
| 242 ASSERT_EQ("com.sample.feed", webview->package()); |
| 243 |
| 244 std::vector<DevToolsTargetImpl*> chrome_pages = |
| 245 chrome->CreatePageTargets(); |
| 246 std::vector<DevToolsTargetImpl*> webview_pages = |
| 247 webview->CreatePageTargets(); |
| 248 |
| 249 ASSERT_EQ(1U, chrome_pages.size()); |
| 250 ASSERT_EQ(2U, webview_pages.size()); |
| 251 |
| 252 // Check that we have non-empty description for webview pages. |
| 253 ASSERT_EQ(0U, chrome_pages[0]->GetDescription().size()); |
| 254 ASSERT_NE(0U, webview_pages[0]->GetDescription().size()); |
| 255 ASSERT_NE(0U, webview_pages[1]->GetDescription().size()); |
| 256 |
| 257 ASSERT_EQ(GURL("http://www.chromium.org/"), chrome_pages[0]->GetUrl()); |
| 258 ASSERT_EQ("The Chromium Projects", chrome_pages[0]->GetTitle()); |
| 259 |
| 260 STLDeleteElements(&chrome_pages); |
| 261 STLDeleteElements(&webview_pages); |
| 262 |
| 263 runner_->Quit(); |
| 264 } |
| 265 |
| 266 void init() { |
| 267 runner_ = new content::MessageLoopRunner; |
| 268 } |
| 269 |
| 270 protected: |
| 271 scoped_refptr<content::MessageLoopRunner> runner_; |
| 272 }; |
| 273 |
| 274 IN_PROC_BROWSER_TEST_F(DevToolsAdbBridgeTest, Main) { |
| 275 init(); |
| 276 |
| 277 scoped_refptr<DevToolsAdbBridge> adb_bridge = |
| 278 DevToolsAdbBridge::Factory::GetForProfile(browser()->profile()); |
| 279 |
| 280 DevToolsAdbBridge::DeviceProviders providers; |
| 281 providers.push_back(new MockDeviceProvider()); |
| 282 |
| 283 adb_bridge->set_device_providers(providers); |
| 284 |
| 285 if (!adb_bridge) { |
| 286 FAIL() << "Failed to get DevToolsAdbBridge."; |
| 287 } |
| 288 |
| 289 adb_bridge->AddListener(this); |
| 290 |
| 291 runner_->Run(); |
| 292 } |
OLD | NEW |