Home | History | Annotate | Download | only in automation
      1 // Copyright (c) 2012 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/automation/browser_proxy.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/json/json_reader.h"
     10 #include "base/logging.h"
     11 #include "base/threading/platform_thread.h"
     12 #include "base/time/time.h"
     13 #include "chrome/common/automation_constants.h"
     14 #include "chrome/common/automation_messages.h"
     15 #include "chrome/test/automation/automation_proxy.h"
     16 #include "chrome/test/automation/tab_proxy.h"
     17 #include "chrome/test/automation/window_proxy.h"
     18 #include "ui/gfx/point.h"
     19 
     20 using base::TimeDelta;
     21 using base::TimeTicks;
     22 
     23 bool BrowserProxy::ActivateTab(int tab_index) {
     24   if (!is_valid())
     25     return false;
     26 
     27   int activate_tab_response = -1;
     28 
     29   if (!sender_->Send(new AutomationMsg_ActivateTab(
     30                          handle_, tab_index, &activate_tab_response))) {
     31     return false;
     32   }
     33 
     34   if (activate_tab_response >= 0)
     35     return true;
     36 
     37   return false;
     38 }
     39 
     40 bool BrowserProxy::BringToFront() {
     41   if (!is_valid())
     42     return false;
     43 
     44   bool succeeded = false;
     45 
     46   if (!sender_->Send(new AutomationMsg_BringBrowserToFront(
     47                          handle_, &succeeded))) {
     48     return false;
     49   }
     50 
     51   return succeeded;
     52 }
     53 
     54 bool BrowserProxy::AppendTab(const GURL& tab_url) {
     55   if (!is_valid())
     56     return false;
     57 
     58   int append_tab_response = -1;
     59 
     60   sender_->Send(new AutomationMsg_AppendTab(handle_, tab_url,
     61                                             &append_tab_response));
     62   return append_tab_response >= 0;
     63 }
     64 
     65 bool BrowserProxy::GetActiveTabIndex(int* active_tab_index) const {
     66   if (!is_valid())
     67     return false;
     68 
     69   if (!active_tab_index) {
     70     NOTREACHED();
     71     return false;
     72   }
     73 
     74   int active_tab_index_response = -1;
     75 
     76   if (!sender_->Send(new AutomationMsg_ActiveTabIndex(
     77                          handle_, &active_tab_index_response))) {
     78     return false;
     79   }
     80 
     81   if (active_tab_index_response >= 0) {
     82     *active_tab_index = active_tab_index_response;
     83     return true;
     84   }
     85 
     86   return false;
     87 }
     88 
     89 scoped_refptr<TabProxy> BrowserProxy::GetTab(int tab_index) const {
     90   if (!is_valid())
     91     return NULL;
     92 
     93   int tab_handle = 0;
     94 
     95   sender_->Send(new AutomationMsg_Tab(handle_, tab_index, &tab_handle));
     96   if (!tab_handle)
     97     return NULL;
     98 
     99   TabProxy* tab = static_cast<TabProxy*>(tracker_->GetResource(tab_handle));
    100   if (!tab) {
    101     tab = new TabProxy(sender_, tracker_, tab_handle);
    102     tab->AddRef();
    103   }
    104 
    105   // Since there is no scoped_refptr::attach.
    106   scoped_refptr<TabProxy> result;
    107   result.swap(&tab);
    108   return result;
    109 }
    110 
    111 scoped_refptr<TabProxy> BrowserProxy::GetActiveTab() const {
    112   int active_tab_index;
    113   if (!GetActiveTabIndex(&active_tab_index))
    114     return NULL;
    115   return GetTab(active_tab_index);
    116 }
    117 
    118 bool BrowserProxy::GetTabCount(int* num_tabs) const {
    119   if (!is_valid())
    120     return false;
    121 
    122   if (!num_tabs) {
    123     NOTREACHED();
    124     return false;
    125   }
    126 
    127   int tab_count_response = -1;
    128 
    129   if (!sender_->Send(new AutomationMsg_TabCount(
    130                          handle_, &tab_count_response))) {
    131     return false;
    132   }
    133 
    134   if (tab_count_response >= 0) {
    135     *num_tabs = tab_count_response;
    136     return true;
    137   }
    138 
    139   return false;
    140 }
    141 
    142 bool BrowserProxy::GetType(Browser::Type* type) const {
    143   if (!is_valid())
    144     return false;
    145 
    146   if (!type) {
    147     NOTREACHED();
    148     return false;
    149   }
    150 
    151   int type_as_int;
    152   if (!sender_->Send(new AutomationMsg_Type(handle_, &type_as_int)))
    153     return false;
    154 
    155   *type = static_cast<Browser::Type>(type_as_int);
    156   return true;
    157 }
    158 
    159 bool BrowserProxy::ApplyAccelerator(int id) {
    160   return RunCommandAsync(id);
    161 }
    162 
    163 bool BrowserProxy::WaitForTabCountToBecome(int count) {
    164   bool success = false;
    165   if (!sender_->Send(new AutomationMsg_WaitForTabCountToBecome(
    166                          handle_, count, &success))) {
    167     return false;
    168   }
    169 
    170   return success;
    171 }
    172 
    173 bool BrowserProxy::WaitForTabToBecomeActive(int tab,
    174                                             base::TimeDelta wait_timeout) {
    175   const TimeTicks start = TimeTicks::Now();
    176   while (TimeTicks::Now() - start < wait_timeout) {
    177     base::PlatformThread::Sleep(
    178         base::TimeDelta::FromMilliseconds(automation::kSleepTime));
    179     int active_tab;
    180     if (GetActiveTabIndex(&active_tab) && active_tab == tab)
    181       return true;
    182   }
    183   // If we get here, the active tab hasn't changed.
    184   return false;
    185 }
    186 
    187 bool BrowserProxy::IsFindWindowFullyVisible(bool* is_visible) {
    188   if (!is_valid())
    189     return false;
    190 
    191   if (!is_visible) {
    192     NOTREACHED();
    193     return false;
    194   }
    195 
    196   return sender_->Send(
    197       new AutomationMsg_FindWindowVisibility(handle_, is_visible));
    198 }
    199 
    200 bool BrowserProxy::RunCommandAsync(int browser_command) const {
    201   if (!is_valid())
    202     return false;
    203 
    204   bool result = false;
    205 
    206   sender_->Send(new AutomationMsg_WindowExecuteCommandAsync(handle_,
    207                                                             browser_command,
    208                                                             &result));
    209 
    210   return result;
    211 }
    212 
    213 bool BrowserProxy::RunCommand(int browser_command) const {
    214   if (!is_valid())
    215     return false;
    216 
    217   bool result = false;
    218 
    219   sender_->Send(new AutomationMsg_WindowExecuteCommand(handle_,
    220                                                        browser_command,
    221                                                        &result));
    222 
    223   return result;
    224 }
    225 
    226 bool BrowserProxy::TerminateSession() {
    227   if (!is_valid())
    228     return false;
    229 
    230   bool result = false;
    231 
    232   sender_->Send(new AutomationMsg_TerminateSession(handle_, &result));
    233 
    234   return result;
    235 }
    236 
    237 scoped_refptr<WindowProxy> BrowserProxy::GetWindow() const {
    238   if (!is_valid())
    239     return NULL;
    240 
    241   bool handle_ok = false;
    242   int window_handle = 0;
    243 
    244   sender_->Send(new AutomationMsg_WindowForBrowser(handle_, &handle_ok,
    245                                                    &window_handle));
    246   if (!handle_ok)
    247     return NULL;
    248 
    249   WindowProxy* window =
    250       static_cast<WindowProxy*>(tracker_->GetResource(window_handle));
    251   if (!window) {
    252     window = new WindowProxy(sender_, tracker_, window_handle);
    253     window->AddRef();
    254   }
    255 
    256   // Since there is no scoped_refptr::attach.
    257   scoped_refptr<WindowProxy> result;
    258   result.swap(&window);
    259   return result;
    260 }
    261 
    262 bool BrowserProxy::SendJSONRequest(const std::string& request,
    263                                    int timeout_ms,
    264                                    std::string* response) {
    265   if (!is_valid())
    266     return false;
    267 
    268   bool result = false;
    269   if (!sender_->Send(
    270       new AutomationMsg_SendJSONRequestWithBrowserHandle(handle_,
    271                                                          request,
    272                                                          response,
    273                                                          &result),
    274                                                          timeout_ms))
    275     return false;
    276   return result;
    277 }
    278 
    279 bool BrowserProxy::GetInitialLoadTimes(base::TimeDelta timeout,
    280                                        float* min_start_time,
    281                                        float* max_stop_time,
    282                                        std::vector<float>* stop_times) {
    283   std::string json_response;
    284   const char* kJSONCommand = "{\"command\": \"GetInitialLoadTimes\"}";
    285 
    286   *max_stop_time = 0;
    287   *min_start_time = -1;
    288   if (!SendJSONRequest(
    289           kJSONCommand, timeout.InMilliseconds(), &json_response)) {
    290     // Older browser versions do not support GetInitialLoadTimes.
    291     // Fail gracefully and do not record them in this case.
    292     return false;
    293   }
    294   std::string error;
    295   scoped_ptr<Value> values(base::JSONReader::ReadAndReturnError(
    296       json_response, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error));
    297   if (!error.empty() || values->GetType() != Value::TYPE_DICTIONARY)
    298     return false;
    299 
    300   DictionaryValue* values_dict = static_cast<DictionaryValue*>(values.get());
    301 
    302   Value* tabs_value;
    303   if (!values_dict->Get("tabs", &tabs_value) ||
    304       tabs_value->GetType() != Value::TYPE_LIST)
    305     return false;
    306 
    307   ListValue* tabs_list = static_cast<ListValue*>(tabs_value);
    308 
    309   for (size_t i = 0; i < tabs_list->GetSize(); i++) {
    310     float stop_ms = 0;
    311     float start_ms = 0;
    312     Value* tab_value;
    313     DictionaryValue* tab_dict;
    314 
    315     if (!tabs_list->Get(i, &tab_value) ||
    316         tab_value->GetType() != Value::TYPE_DICTIONARY)
    317       return false;
    318     tab_dict = static_cast<DictionaryValue*>(tab_value);
    319 
    320     double temp;
    321     if (!tab_dict->GetDouble("load_start_ms", &temp))
    322       return false;
    323     start_ms = static_cast<float>(temp);
    324     // load_stop_ms can only be null if WaitForInitialLoads did not run.
    325     if (!tab_dict->GetDouble("load_stop_ms", &temp))
    326       return false;
    327     stop_ms = static_cast<float>(temp);
    328 
    329     if (i == 0)
    330       *min_start_time = start_ms;
    331 
    332     *min_start_time = std::min(start_ms, *min_start_time);
    333     *max_stop_time = std::max(stop_ms, *max_stop_time);
    334     stop_times->push_back(stop_ms);
    335   }
    336   std::sort(stop_times->begin(), stop_times->end());
    337   return true;
    338 }
    339