bd62a2f310d7dfb7b15f350a31cb14e41e237815
[platform/framework/web/crosswalk.git] / src / chrome / test / chromedriver / chrome / device_manager.cc
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/test/chromedriver/chrome/device_manager.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/logging.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h"
16 #include "chrome/test/chromedriver/chrome/adb.h"
17 #include "chrome/test/chromedriver/chrome/status.h"
18
19 Device::Device(
20     const std::string& device_serial, Adb* adb,
21     base::Callback<void()> release_callback)
22     : serial_(device_serial),
23       adb_(adb),
24       release_callback_(release_callback) {}
25
26 Device::~Device() {
27   release_callback_.Run();
28 }
29
30 Status Device::SetUp(const std::string& package,
31                      const std::string& activity,
32                      const std::string& process,
33                      const std::string& args,
34                      bool use_running_app,
35                      int port) {
36   if (!active_package_.empty())
37     return Status(kUnknownError,
38         active_package_ + " was launched and has not been quit");
39
40   Status status = adb_->CheckAppInstalled(serial_, package);
41   if (!status.IsOk())
42     return status;
43
44   std::string known_activity;
45   std::string command_line_file;
46   std::string device_socket;
47   std::string exec_name;
48   if (package.compare("org.chromium.content_shell_apk") == 0) {
49     known_activity = ".ContentShellActivity";
50     device_socket = "content_shell_devtools_remote";
51     command_line_file = "/data/local/tmp/content-shell-command-line";
52     exec_name = "content_shell";
53   } else if (package.compare("org.chromium.chrome.testshell") == 0) {
54     known_activity = ".ChromiumTestShellActivity";
55     device_socket = "chromium_testshell_devtools_remote";
56     command_line_file = "/data/local/tmp/chromium-testshell-command-line";
57     exec_name = "chromium_testshell";
58   } else if (package.find("chrome") != std::string::npos &&
59              package.find("webview") == std::string::npos) {
60     known_activity = "com.google.android.apps.chrome.Main";
61     device_socket = "chrome_devtools_remote";
62     command_line_file = "/data/local/chrome-command-line";
63     exec_name = "chrome";
64   }
65
66   if (!use_running_app) {
67     status = adb_->ClearAppData(serial_, package);
68     if (!status.IsOk())
69       return status;
70
71     if (!known_activity.empty()) {
72       if (!activity.empty() ||
73           !process.empty())
74         return Status(kUnknownError, "known package " + package +
75                       " does not accept activity/process");
76     } else if (activity.empty()) {
77       return Status(kUnknownError, "WebView apps require activity name");
78     }
79
80     if (!command_line_file.empty()) {
81       status = adb_->SetCommandLineFile(serial_, command_line_file, exec_name,
82                                         args);
83       if (!status.IsOk())
84         return status;
85     }
86
87     status = adb_->Launch(serial_, package,
88                           known_activity.empty() ? activity : known_activity);
89     if (!status.IsOk())
90       return status;
91
92     active_package_ = package;
93   }
94   this->ForwardDevtoolsPort(package, process, device_socket, port);
95
96   return status;
97 }
98
99 Status Device::ForwardDevtoolsPort(const std::string& package,
100                                    const std::string& process,
101                                    std::string& device_socket,
102                                    int port) {
103   if (device_socket.empty()) {
104     // Assume this is a WebView app.
105     int pid;
106     Status status = adb_->GetPidByName(serial_,
107                                        process.empty() ? package : process,
108                                        &pid);
109     if (!status.IsOk()) {
110       if (process.empty())
111         status.AddDetails(
112             "process name must be specified if not equal to package name");
113       return status;
114     }
115     device_socket = base::StringPrintf("webview_devtools_remote_%d", pid);
116   }
117
118   return adb_->ForwardPort(serial_, port, device_socket);
119 }
120
121 Status Device::TearDown() {
122   if (!active_package_.empty()) {
123     std::string response;
124     Status status = adb_->ForceStop(serial_, active_package_);
125     if (!status.IsOk())
126       return status;
127     active_package_ = "";
128   }
129   return Status(kOk);
130 }
131
132 DeviceManager::DeviceManager(Adb* adb) : adb_(adb) {
133   CHECK(adb_);
134 }
135
136 DeviceManager::~DeviceManager() {}
137
138 Status DeviceManager::AcquireDevice(scoped_ptr<Device>* device) {
139   std::vector<std::string> devices;
140   Status status = adb_->GetDevices(&devices);
141   if (!status.IsOk())
142     return status;
143
144   if (devices.empty())
145     return Status(kUnknownError, "There are no devices online");
146
147   base::AutoLock lock(devices_lock_);
148   status = Status(kUnknownError, "All devices are in use (" +
149                   base::IntToString(devices.size()) + " online)");
150   std::vector<std::string>::iterator iter;
151   for (iter = devices.begin(); iter != devices.end(); iter++) {
152     if (!IsDeviceLocked(*iter)) {
153       device->reset(LockDevice(*iter));
154       status = Status(kOk);
155       break;
156     }
157   }
158   return status;
159 }
160
161 Status DeviceManager::AcquireSpecificDevice(
162     const std::string& device_serial, scoped_ptr<Device>* device) {
163   std::vector<std::string> devices;
164   Status status = adb_->GetDevices(&devices);
165   if (!status.IsOk())
166     return status;
167
168   if (std::find(devices.begin(), devices.end(), device_serial) == devices.end())
169     return Status(kUnknownError,
170         "Device " + device_serial + " is not online");
171
172   base::AutoLock lock(devices_lock_);
173   if (IsDeviceLocked(device_serial)) {
174     status = Status(kUnknownError,
175         "Device " + device_serial + " is already in use");
176   } else {
177     device->reset(LockDevice(device_serial));
178     status = Status(kOk);
179   }
180   return status;
181 }
182
183 void DeviceManager::ReleaseDevice(const std::string& device_serial) {
184   base::AutoLock lock(devices_lock_);
185   active_devices_.remove(device_serial);
186 }
187
188 Device* DeviceManager::LockDevice(const std::string& device_serial) {
189   active_devices_.push_back(device_serial);
190   return new Device(device_serial, adb_,
191       base::Bind(&DeviceManager::ReleaseDevice, base::Unretained(this),
192                  device_serial));
193 }
194
195 bool DeviceManager::IsDeviceLocked(const std::string& device_serial) {
196   return std::find(active_devices_.begin(), active_devices_.end(),
197                    device_serial) != active_devices_.end();
198 }
199