12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/chrome_impl.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/devtools_client.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/devtools_event_listener.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/devtools_http_client.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/web_view_impl.h"
1268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/test/chromedriver/net/port_server.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)ChromeImpl::~ChromeImpl() {
1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!quit_)
1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    port_reservation_->Leak();
1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ChromeDesktopImpl* ChromeImpl::GetAsDesktop() {
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return NULL;
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst BrowserInfo* ChromeImpl::GetBrowserInfo() {
240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return devtools_http_client_->browser_info();
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool ChromeImpl::HasCrashedWebView() {
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (WebViewList::iterator it = web_views_.begin();
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       it != web_views_.end(); ++it) {
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((*it)->WasCrashed())
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return true;
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return false;
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ChromeImpl::GetWebViewIds(std::list<std::string>* web_view_ids) {
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  WebViewsInfo views_info;
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = devtools_http_client_->GetWebViewsInfo(&views_info);
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check if some web views are closed.
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebViewList::iterator it = web_views_.begin();
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (it != web_views_.end()) {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!views_info.GetForId((*it)->GetId())) {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      it = web_views_.erase(it);
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++it;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check for newly-opened web views.
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < views_info.GetSize(); ++i) {
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const WebViewInfo& view = views_info.Get(i);
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (view.type != WebViewInfo::kPage && view.type != WebViewInfo::kApp)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Workaround to ignore generated background pages that are
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // being returned as active windows for some builds of Chrome.
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // TODO(bustamante): Once Chrome builds < 1755 are no longer
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    //   supported this check can be removed.
620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    int kBuildNumber = devtools_http_client_->browser_info()->build_no;
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (kBuildNumber < 1755 && view.type == WebViewInfo::kApp &&
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        view.url.find("_generated_background") != std::string::npos)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool found = false;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (WebViewList::const_iterator web_view_iter = web_views_.begin();
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         web_view_iter != web_views_.end(); ++web_view_iter) {
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if ((*web_view_iter)->GetId() == view.id) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        found = true;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!found) {
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      scoped_ptr<DevToolsClient> client(
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          devtools_http_client_->CreateClient(view.id));
78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      for (ScopedVector<DevToolsEventListener>::const_iterator listener =
79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               devtools_event_listeners_.begin();
80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)           listener != devtools_event_listeners_.end(); ++listener) {
81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        client->AddListener(*listener);
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        // OnConnected will fire when DevToolsClient connects later.
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      web_views_.push_back(make_linked_ptr(new WebViewImpl(
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          view.id,
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          devtools_http_client_->browser_info(),
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          client.Pass(),
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          devtools_http_client_->device_metrics())));
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<std::string> web_view_ids_tmp;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (WebViewList::const_iterator web_view_iter = web_views_.begin();
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       web_view_iter != web_views_.end(); ++web_view_iter) {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    web_view_ids_tmp.push_back((*web_view_iter)->GetId());
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  web_view_ids->swap(web_view_ids_tmp);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ChromeImpl::GetWebViewById(const std::string& id, WebView** web_view) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (WebViewList::iterator it = web_views_.begin();
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != web_views_.end(); ++it) {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*it)->GetId() == id) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *web_view = (*it).get();
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return Status(kOk);
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kUnknownError, "web view not found");
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status ChromeImpl::CloseWebView(const std::string& id) {
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = devtools_http_client_->CloseWebView(id);
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (WebViewList::iterator iter = web_views_.begin();
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       iter != web_views_.end(); ++iter) {
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if ((*iter)->GetId() == id) {
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      web_views_.erase(iter);
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Status(kOk);
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
126424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)Status ChromeImpl::ActivateWebView(const std::string& id) {
127424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return devtools_http_client_->ActivateWebView(id);
128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ChromeImpl::IsMobileEmulationEnabled() const {
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return false;
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)Status ChromeImpl::Quit() {
13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Status status = QuitImpl();
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (status.IsOk())
13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    quit_ = true;
13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return status;
13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ChromeImpl::ChromeImpl(
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<DevToolsHttpClient> http_client,
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<DevToolsClient> websocket_client,
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedVector<DevToolsEventListener>& devtools_event_listeners,
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_ptr<PortReservation> port_reservation)
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : quit_(false),
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      devtools_http_client_(http_client.Pass()),
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      devtools_websocket_client_(websocket_client.Pass()),
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      port_reservation_(port_reservation.Pass()) {
150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  devtools_event_listeners_.swap(devtools_event_listeners);
151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
152