| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/test/automation/browser_proxy.h" |
| |
| #include <algorithm> |
| |
| #include "base/json/json_reader.h" |
| #include "base/logging.h" |
| #include "base/test/test_timeouts.h" |
| #include "base/threading/platform_thread.h" |
| #include "base/time.h" |
| #include "chrome/common/automation_constants.h" |
| #include "chrome/common/automation_messages.h" |
| #include "chrome/test/automation/automation_proxy.h" |
| #include "chrome/test/automation/tab_proxy.h" |
| #include "chrome/test/automation/window_proxy.h" |
| #include "ui/gfx/point.h" |
| |
| using base::TimeDelta; |
| using base::TimeTicks; |
| |
| bool BrowserProxy::ActivateTab(int tab_index) { |
| if (!is_valid()) |
| return false; |
| |
| int activate_tab_response = -1; |
| |
| if (!sender_->Send(new AutomationMsg_ActivateTab( |
| handle_, tab_index, &activate_tab_response))) { |
| return false; |
| } |
| |
| if (activate_tab_response >= 0) |
| return true; |
| |
| return false; |
| } |
| |
| bool BrowserProxy::BringToFront() { |
| if (!is_valid()) |
| return false; |
| |
| bool succeeded = false; |
| |
| if (!sender_->Send(new AutomationMsg_BringBrowserToFront( |
| handle_, &succeeded))) { |
| return false; |
| } |
| |
| return succeeded; |
| } |
| |
| bool BrowserProxy::IsMenuCommandEnabled(int id, bool* enabled) { |
| if (!is_valid()) |
| return false; |
| |
| return sender_->Send(new AutomationMsg_IsMenuCommandEnabled(handle_, id, |
| enabled)); |
| } |
| |
| bool BrowserProxy::AppendTab(const GURL& tab_url) { |
| if (!is_valid()) |
| return false; |
| |
| int append_tab_response = -1; |
| |
| sender_->Send(new AutomationMsg_AppendTab(handle_, tab_url, |
| &append_tab_response)); |
| return append_tab_response >= 0; |
| } |
| |
| bool BrowserProxy::GetActiveTabIndex(int* active_tab_index) const { |
| if (!is_valid()) |
| return false; |
| |
| if (!active_tab_index) { |
| NOTREACHED(); |
| return false; |
| } |
| |
| int active_tab_index_response = -1; |
| |
| if (!sender_->Send(new AutomationMsg_ActiveTabIndex( |
| handle_, &active_tab_index_response))) { |
| return false; |
| } |
| |
| if (active_tab_index_response >= 0) { |
| *active_tab_index = active_tab_index_response; |
| return true; |
| } |
| |
| return false; |
| } |
| |
| scoped_refptr<TabProxy> BrowserProxy::GetTab(int tab_index) const { |
| if (!is_valid()) |
| return NULL; |
| |
| int tab_handle = 0; |
| |
| sender_->Send(new AutomationMsg_Tab(handle_, tab_index, &tab_handle)); |
| if (!tab_handle) |
| return NULL; |
| |
| TabProxy* tab = static_cast<TabProxy*>(tracker_->GetResource(tab_handle)); |
| if (!tab) { |
| tab = new TabProxy(sender_, tracker_, tab_handle); |
| tab->AddRef(); |
| } |
| |
| // Since there is no scoped_refptr::attach. |
| scoped_refptr<TabProxy> result; |
| result.swap(&tab); |
| return result; |
| } |
| |
| scoped_refptr<TabProxy> BrowserProxy::GetActiveTab() const { |
| int active_tab_index; |
| if (!GetActiveTabIndex(&active_tab_index)) |
| return NULL; |
| return GetTab(active_tab_index); |
| } |
| |
| bool BrowserProxy::GetTabCount(int* num_tabs) const { |
| if (!is_valid()) |
| return false; |
| |
| if (!num_tabs) { |
| NOTREACHED(); |
| return false; |
| } |
| |
| int tab_count_response = -1; |
| |
| if (!sender_->Send(new AutomationMsg_TabCount( |
| handle_, &tab_count_response))) { |
| return false; |
| } |
| |
| if (tab_count_response >= 0) { |
| *num_tabs = tab_count_response; |
| return true; |
| } |
| |
| return false; |
| } |
| |
| bool BrowserProxy::GetType(Browser::Type* type) const { |
| if (!is_valid()) |
| return false; |
| |
| if (!type) { |
| NOTREACHED(); |
| return false; |
| } |
| |
| int type_as_int; |
| if (!sender_->Send(new AutomationMsg_Type(handle_, &type_as_int))) |
| return false; |
| |
| *type = static_cast<Browser::Type>(type_as_int); |
| return true; |
| } |
| |
| bool BrowserProxy::IsApplication(bool* is_application) { |
| DCHECK(is_application); |
| |
| if (!is_valid()) |
| return false; |
| |
| bool success = false; |
| if (!sender_->Send(new AutomationMsg_IsBrowserInApplicationMode( |
| handle_, is_application, &success))) { |
| return false; |
| } |
| |
| return success; |
| } |
| |
| bool BrowserProxy::ApplyAccelerator(int id) { |
| return RunCommandAsync(id); |
| } |
| |
| bool BrowserProxy::SimulateDrag(const gfx::Point& start, |
| const gfx::Point& end, |
| int flags, |
| bool press_escape_en_route) { |
| if (!is_valid()) |
| return false; |
| |
| std::vector<gfx::Point> drag_path; |
| drag_path.push_back(start); |
| drag_path.push_back(end); |
| |
| bool result = false; |
| |
| if (!sender_->Send(new AutomationMsg_WindowDrag( |
| handle_, drag_path, flags, press_escape_en_route, &result))) { |
| return false; |
| } |
| |
| return result; |
| } |
| |
| bool BrowserProxy::WaitForTabCountToBecome(int count) { |
| bool success = false; |
| if (!sender_->Send(new AutomationMsg_WaitForTabCountToBecome( |
| handle_, count, &success))) { |
| return false; |
| } |
| |
| return success; |
| } |
| |
| bool BrowserProxy::WaitForTabToBecomeActive(int tab, |
| int wait_timeout) { |
| const TimeTicks start = TimeTicks::Now(); |
| const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout); |
| while (TimeTicks::Now() - start < timeout) { |
| base::PlatformThread::Sleep(automation::kSleepTime); |
| int active_tab; |
| if (GetActiveTabIndex(&active_tab) && active_tab == tab) |
| return true; |
| } |
| // If we get here, the active tab hasn't changed. |
| return false; |
| } |
| |
| bool BrowserProxy::OpenFindInPage() { |
| if (!is_valid()) |
| return false; |
| |
| return sender_->Send(new AutomationMsg_OpenFindInPage(handle_)); |
| // This message expects no response. |
| } |
| |
| bool BrowserProxy::GetFindWindowLocation(int* x, int* y) { |
| if (!is_valid() || !x || !y) |
| return false; |
| |
| return sender_->Send(new AutomationMsg_FindWindowLocation(handle_, x, y)); |
| } |
| |
| bool BrowserProxy::IsFindWindowFullyVisible(bool* is_visible) { |
| if (!is_valid()) |
| return false; |
| |
| if (!is_visible) { |
| NOTREACHED(); |
| return false; |
| } |
| |
| return sender_->Send( |
| new AutomationMsg_FindWindowVisibility(handle_, is_visible)); |
| } |
| |
| bool BrowserProxy::RunCommandAsync(int browser_command) const { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| |
| sender_->Send(new AutomationMsg_WindowExecuteCommandAsync(handle_, |
| browser_command, |
| &result)); |
| |
| return result; |
| } |
| |
| bool BrowserProxy::RunCommand(int browser_command) const { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| |
| sender_->Send(new AutomationMsg_WindowExecuteCommand(handle_, |
| browser_command, |
| &result)); |
| |
| return result; |
| } |
| |
| bool BrowserProxy::GetBookmarkBarVisibility(bool* is_visible, |
| bool* is_animating) { |
| if (!is_valid()) |
| return false; |
| |
| if (!is_visible || !is_animating) { |
| NOTREACHED(); |
| return false; |
| } |
| |
| return sender_->Send(new AutomationMsg_BookmarkBarVisibility( |
| handle_, is_visible, is_animating)); |
| } |
| |
| bool BrowserProxy::GetBookmarksAsJSON(std::string *json_string) { |
| if (!is_valid()) |
| return false; |
| |
| if (!WaitForBookmarkModelToLoad()) |
| return false; |
| |
| bool result = false; |
| sender_->Send(new AutomationMsg_GetBookmarksAsJSON(handle_, |
| json_string, |
| &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::WaitForBookmarkModelToLoad() { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| sender_->Send(new AutomationMsg_WaitForBookmarkModelToLoad(handle_, &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::AddBookmarkGroup(int64 parent_id, int index, |
| std::wstring& title) { |
| if (!is_valid()) |
| return false; |
| bool result = false; |
| sender_->Send(new AutomationMsg_AddBookmarkGroup(handle_, |
| parent_id, index, |
| title, |
| &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::AddBookmarkURL(int64 parent_id, int index, |
| std::wstring& title, const GURL& url) { |
| if (!is_valid()) |
| return false; |
| bool result = false; |
| sender_->Send(new AutomationMsg_AddBookmarkURL(handle_, |
| parent_id, index, |
| title, url, |
| &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::ReparentBookmark(int64 id, int64 new_parent_id, int index) { |
| if (!is_valid()) |
| return false; |
| bool result = false; |
| sender_->Send(new AutomationMsg_ReparentBookmark(handle_, |
| id, new_parent_id, |
| index, |
| &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::SetBookmarkTitle(int64 id, const std::wstring& title) { |
| if (!is_valid()) |
| return false; |
| bool result = false; |
| sender_->Send(new AutomationMsg_SetBookmarkTitle(handle_, |
| id, title, |
| &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::SetBookmarkURL(int64 id, const GURL& url) { |
| if (!is_valid()) |
| return false; |
| bool result = false; |
| sender_->Send(new AutomationMsg_SetBookmarkURL(handle_, |
| id, url, |
| &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::RemoveBookmark(int64 id) { |
| if (!is_valid()) |
| return false; |
| bool result = false; |
| sender_->Send(new AutomationMsg_RemoveBookmark(handle_, |
| id, |
| &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::IsShelfVisible(bool* is_visible) { |
| if (!is_valid()) |
| return false; |
| |
| if (!is_visible) { |
| NOTREACHED(); |
| return false; |
| } |
| |
| return sender_->Send(new AutomationMsg_ShelfVisibility(handle_, |
| is_visible)); |
| } |
| |
| bool BrowserProxy::SetShelfVisible(bool is_visible) { |
| if (!is_valid()) |
| return false; |
| |
| return sender_->Send(new AutomationMsg_SetShelfVisibility(handle_, |
| is_visible)); |
| } |
| |
| bool BrowserProxy::SetIntPreference(const std::string& name, int value) { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| |
| sender_->Send(new AutomationMsg_SetIntPreference(handle_, name, value, |
| &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::SetStringPreference(const std::string& name, |
| const std::string& value) { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| |
| sender_->Send(new AutomationMsg_SetStringPreference(handle_, name, value, |
| &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::GetBooleanPreference(const std::string& name, |
| bool* value) { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| |
| sender_->Send(new AutomationMsg_GetBooleanPreference(handle_, name, value, |
| &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::SetBooleanPreference(const std::string& name, |
| bool value) { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| |
| sender_->Send(new AutomationMsg_SetBooleanPreference(handle_, name, |
| value, &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::SetDefaultContentSetting(ContentSettingsType content_type, |
| ContentSetting setting) { |
| return SetContentSetting(std::string(), content_type, setting); |
| } |
| |
| bool BrowserProxy::SetContentSetting(const std::string& host, |
| ContentSettingsType content_type, |
| ContentSetting setting) { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| |
| sender_->Send(new AutomationMsg_SetContentSetting(handle_, host, |
| content_type, setting, |
| &result)); |
| return result; |
| } |
| |
| bool BrowserProxy::TerminateSession() { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| |
| sender_->Send(new AutomationMsg_TerminateSession(handle_, &result)); |
| |
| return result; |
| } |
| |
| scoped_refptr<WindowProxy> BrowserProxy::GetWindow() const { |
| if (!is_valid()) |
| return NULL; |
| |
| bool handle_ok = false; |
| int window_handle = 0; |
| |
| sender_->Send(new AutomationMsg_WindowForBrowser(handle_, &handle_ok, |
| &window_handle)); |
| if (!handle_ok) |
| return NULL; |
| |
| WindowProxy* window = |
| static_cast<WindowProxy*>(tracker_->GetResource(window_handle)); |
| if (!window) { |
| window = new WindowProxy(sender_, tracker_, window_handle); |
| window->AddRef(); |
| } |
| |
| // Since there is no scoped_refptr::attach. |
| scoped_refptr<WindowProxy> result; |
| result.swap(&window); |
| return result; |
| } |
| |
| bool BrowserProxy::IsFullscreen(bool* is_fullscreen) { |
| DCHECK(is_fullscreen); |
| |
| if (!is_valid()) |
| return false; |
| |
| return sender_->Send(new AutomationMsg_IsFullscreen(handle_, is_fullscreen)); |
| } |
| |
| bool BrowserProxy::IsFullscreenBubbleVisible(bool* is_visible) { |
| DCHECK(is_visible); |
| |
| if (!is_valid()) |
| return false; |
| |
| return sender_->Send(new AutomationMsg_IsFullscreenBubbleVisible(handle_, |
| is_visible)); |
| } |
| |
| bool BrowserProxy::ShutdownSessionService() { |
| bool did_shutdown = false; |
| bool succeeded = sender_->Send( |
| new AutomationMsg_ShutdownSessionService(handle_, &did_shutdown)); |
| |
| if (!succeeded) { |
| DLOG(ERROR) << |
| "ShutdownSessionService did not complete in a timely fashion"; |
| return false; |
| } |
| |
| return did_shutdown; |
| } |
| |
| bool BrowserProxy::StartTrackingPopupMenus() { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| if (!sender_->Send(new AutomationMsg_StartTrackingPopupMenus( |
| handle_, &result))) |
| return false; |
| return result; |
| } |
| |
| bool BrowserProxy::WaitForPopupMenuToOpen() { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| if (!sender_->Send(new AutomationMsg_WaitForPopupMenuToOpen(&result))) |
| return false; |
| return result; |
| } |
| |
| bool BrowserProxy::SendJSONRequest(const std::string& request, |
| int timeout_ms, |
| std::string* response) { |
| if (!is_valid()) |
| return false; |
| |
| bool result = false; |
| if (!sender_->Send(new AutomationMsg_SendJSONRequest(handle_, |
| request, |
| response, |
| &result), |
| timeout_ms)) |
| return false; |
| return result; |
| } |
| |
| bool BrowserProxy::GetInitialLoadTimes(float* min_start_time, |
| float* max_stop_time, |
| std::vector<float>* stop_times) { |
| std::string json_response; |
| const char* kJSONCommand = "{\"command\": \"GetInitialLoadTimes\"}"; |
| |
| *max_stop_time = 0; |
| *min_start_time = -1; |
| if (!SendJSONRequest(kJSONCommand, |
| TestTimeouts::action_max_timeout_ms(), |
| &json_response)) { |
| // Older browser versions do not support GetInitialLoadTimes. |
| // Fail gracefully and do not record them in this case. |
| return false; |
| } |
| std::string error; |
| base::JSONReader reader; |
| scoped_ptr<Value> values(reader.ReadAndReturnError(json_response, true, |
| NULL, &error)); |
| if (!error.empty() || values->GetType() != Value::TYPE_DICTIONARY) |
| return false; |
| |
| DictionaryValue* values_dict = static_cast<DictionaryValue*>(values.get()); |
| |
| Value* tabs_value; |
| if (!values_dict->Get("tabs", &tabs_value) || |
| tabs_value->GetType() != Value::TYPE_LIST) |
| return false; |
| |
| ListValue* tabs_list = static_cast<ListValue*>(tabs_value); |
| |
| for (size_t i = 0; i < tabs_list->GetSize(); i++) { |
| float stop_ms = 0; |
| float start_ms = 0; |
| Value* tab_value; |
| DictionaryValue* tab_dict; |
| |
| if (!tabs_list->Get(i, &tab_value) || |
| tab_value->GetType() != Value::TYPE_DICTIONARY) |
| return false; |
| tab_dict = static_cast<DictionaryValue*>(tab_value); |
| |
| double temp; |
| if (!tab_dict->GetDouble("load_start_ms", &temp)) |
| return false; |
| start_ms = static_cast<float>(temp); |
| // load_stop_ms can only be null if WaitForInitialLoads did not run. |
| if (!tab_dict->GetDouble("load_stop_ms", &temp)) |
| return false; |
| stop_ms = static_cast<float>(temp); |
| |
| if (i == 0) |
| *min_start_time = start_ms; |
| |
| *min_start_time = std::min(start_ms, *min_start_time); |
| *max_stop_time = std::max(stop_ms, *max_stop_time); |
| stop_times->push_back(stop_ms); |
| } |
| std::sort(stop_times->begin(), stop_times->end()); |
| return true; |
| } |