diff options
Diffstat (limited to 'chrome/test/accessibility/browser_impl.cc')
-rw-r--r-- | chrome/test/accessibility/browser_impl.cc | 512 |
1 files changed, 512 insertions, 0 deletions
diff --git a/chrome/test/accessibility/browser_impl.cc b/chrome/test/accessibility/browser_impl.cc new file mode 100644 index 0000000..f1ea023 --- /dev/null +++ b/chrome/test/accessibility/browser_impl.cc @@ -0,0 +1,512 @@ +// Copyright (c) 2006-2008 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/accessibility/browser_impl.h" + +#include <shellapi.h> + +#include "chrome/test/accessibility/accessibility_util.h" +#include "chrome/test/accessibility/keyboard_util.h" +#include "chrome/test/accessibility/registry_util.h" + +bool BrowserImpl::Launch(void) { + // TODO(klink): Check if chrome already running. + BSTR chrome_path = SysAllocString(GetChromeExePath()); + BOOL success = FALSE; + + // Initialize and fill up structure. + SHELLEXECUTEINFO shell_execute_info; + memset(&shell_execute_info, 0, sizeof(SHELLEXECUTEINFO)); + shell_execute_info.cbSize = sizeof(SHELLEXECUTEINFO); + // To get Process handle. + shell_execute_info.fMask = SEE_MASK_NOCLOSEPROCESS; + shell_execute_info.nShow = SW_SHOW; + shell_execute_info.lpFile = + reinterpret_cast<TCHAR*>(malloc(sizeof(TCHAR) * + SysStringLen(chrome_path))); + _tcscpy_s((TCHAR*)(shell_execute_info.lpFile), SysStringLen(chrome_path), + chrome_path); + + // Execute. + success = ShellExecuteEx(&shell_execute_info); + + if (success && (INT64(shell_execute_info.hInstApp) > 32)) { + // TODO(klink): Maintain instance and process handle. + + // Maintain active tab index. + SetActiveTabIndex(1); + + // Create initial tab collection. + UpdateTabCollection(); + + // Chrome launched. + SysFreeString(chrome_path); + return true; + } + + SysFreeString(chrome_path); + return false; +} + +bool BrowserImpl::Quit(void) { + // Cleanup. + EraseTabCollection(); + + // Send close message to browser window. + HWND hwnd = GetChromeBrowserWnd(NULL); + if (!hwnd) + return false; + SendMessage(hwnd, WM_CLOSE, 0, 0); + return true; +} + +bool BrowserImpl::ActivateTab(const INT64 index) { + // Validate index specified. + if (index < 1) + return false; + + // Goto next tab till focused at desired tab. + while (active_tab_index_ != index) { + GoToNextTab(NULL); + } + return true; +} + +bool BrowserImpl::GetActiveTabURL(BSTR* url) { + // Validate input. + if (!url) + return false; + + return true; +} + +bool BrowserImpl::GetActiveTabTitle(BSTR* title) { + if (!title) + return false; + + *title = SysAllocString(GetTabName(active_tab_index_)); + return true; +} + +bool BrowserImpl::GetActiveTabIndex(INT64* index) { + if (!index) + return false; + + *index = active_tab_index_; + return true; +} + +void BrowserImpl::SetActiveTabIndex(INT64 index) { + if ((index >= MIN_TAB_INDEX_DIGIT) && (index <= GetTabCnt())) + active_tab_index_ = index; + return; +} + +bool BrowserImpl::GetActiveTab(TabImpl** tab) { + return GetTab(active_tab_index_, tab); +} + +bool BrowserImpl::GetTabCount(INT64* count) { + if (!count) + return false; + + *count = GetTabCnt(); + return true; +} + +bool BrowserImpl::GetBrowserProcessCount(INT64* count) { + if (!count) + return false; + + return true; +} + +bool BrowserImpl::GetBrowserTitle(BSTR* title) { + if (!title) + return false; + + HWND hwnd = GetChromeBrowserWnd(NULL); + if (!hwnd) + return false; + + int text_length = GetWindowTextLength(hwnd); + *title = SysAllocStringLen(NULL, text_length); + GetWindowText(hwnd, *title, text_length); + return true; +} + +bool BrowserImpl::AddTab(TabImpl** tab) { + // Add new tab. + HWND hwnd = GetChromeBrowserWnd(NULL); + if (!hwnd) + return false; + ClickKey(hwnd, VK_CONTROL, 'T'); + + // Update active tab index. + INT64 new_tab_index = GetTabCnt(); + if (-1 == new_tab_index) + return false; + SetActiveTabIndex(new_tab_index); + + // Fill object. + TabImpl* new_tab = new TabImpl(); + if (!new_tab) + return false; + ChromeTab* tab_data = new_tab->InitTabData(); + new_tab->set_index(new_tab_index); + new_tab->set_title(GetTabName(new_tab_index)); + new_tab->set_browser(this); + + // Create a copy for storage, in case the caller deletes this newly created + // TabImpl before [tab_collection_] is done using [tab_data]. + ChromeTab* tab_data_copy = tab_data; + + // Update tab collection. + tab_collection_.push_back(linked_ptr<ChromeTab>(tab_data_copy)); + + // Create tab object, if requested. + if (tab) + *tab = new_tab; + + return true; +} + +bool BrowserImpl::GetTab(const INT64 index, TabImpl** tab) { + // Create tab object, if requested. + if (!tab) + return false; + + if (index > GetTabCnt()) + return false; + + *tab = new TabImpl(); + if (!*tab) + return false; + + // Fill object. + ChromeTab* tab_data = (*tab)->InitTabData(); + (*tab)->set_index(index); + (*tab)->set_title(GetTabName(index)); + (*tab)->set_browser(this); + + return true; +} + +bool BrowserImpl::GoToTab(const INT64 index, TabImpl** tab) { + // Validate input. + if (index > MAX_TAB_INDEX_DIGIT) + return false; + + // Stay on current tab, if index doesnot exist. + if ((0 == index) || (GetTabCnt() < index)) + return true; + + // Move to a tab (indexed 1 to 9). + IAccessible* acc_obj = NULL; + HWND hwnd = GetChromeBrowserWnd(&acc_obj); + if (acc_obj && hwnd) { + // Activate main window and operate key Ctrl+digit. + ActivateWnd(acc_obj, hwnd); + ClickKey(hwnd, VK_CONTROL, WORD('0'+index)); + CHK_RELEASE(acc_obj); + + // Set focused tab index. + active_tab_index_ = index; + // Return tab object. + if (tab) { + return GetTab(active_tab_index_, tab); + } + } + + return false; +} + +bool BrowserImpl::GoToNextTab(TabImpl** tab) { + IAccessible* acc_obj = NULL; + HWND hwnd = GetChromeBrowserWnd(&acc_obj); + if (acc_obj && hwnd) { + // Activate main window and operate key Ctrl+Tab. + ActivateWnd(acc_obj, hwnd); + ClickKey(hwnd, VK_CONTROL, VK_TAB); + CHK_RELEASE(acc_obj); + + // Set focused tab index. + if (active_tab_index_ == GetTabCnt()) { + active_tab_index_ = 1; + } else { + active_tab_index_ = active_tab_index_ + 1; + } + + // Return tab object. + if (tab) { + return GetTab(active_tab_index_, tab); + } + } + + return false; +} + +bool BrowserImpl::GoToPrevTab(TabImpl** tab) { + IAccessible* acc_obj = NULL; + HWND hwnd = GetChromeBrowserWnd(&acc_obj); + if (acc_obj && hwnd) { + // Activate main window and operate key Ctrl+Tab. + ActivateWnd(acc_obj, hwnd); + ClickKey(hwnd, VK_SHIFT, VK_CONTROL, VK_TAB); + CHK_RELEASE(acc_obj); + + // Set focused tab index. + if (active_tab_index_ == 1) { + active_tab_index_ = GetTabCnt(); + } else { + active_tab_index_ = active_tab_index_ - 1; + } + + // Return tab object. + if (tab) { + return GetTab(active_tab_index_, tab); + } + } + + return false; +} + +bool BrowserImpl::WaitForChromeToBeVisible(const INT64 interval, + const INT64 timeout, bool* visible) { + IAccessible* acc_obj = NULL; + INT64 time_elapsed = 0; + *visible = false; + + // Check and wait. + while (timeout >= time_elapsed) { + GetTabStripAccessible(&acc_obj); + if (acc_obj) { + *visible = true; + CHK_RELEASE(acc_obj); + return true; + } + Sleep(DWORD(interval)); + time_elapsed = time_elapsed + interval; + } + + return false; +} + +bool BrowserImpl::WaitForTabCountToChange(const INT64 interval, + const INT64 timeout, bool* changed) { + return true; +} + +bool BrowserImpl::WaitForTabToBecomeActive(const INT64 index, + const INT64 interval, + const INT64 timeout, + bool* activated) { + return true; +} + +bool BrowserImpl::ApplyAccelerator(VARIANT keys) { + // Input should be -array of enum or strings or -IDispatch (jscript array + // object). + if ((keys.vt != (VT_ARRAY|VT_BSTR)) && // Array of string values. + (keys.vt != (VT_ARRAY|VT_I4)) && // Array of enum values. + (!(keys.vt & VT_DISPATCH)) ) { // Object. + return false; + } + + // Array to store keys in a single combination. Currently, valid keyboard + // -input combination can constitute of at the most 3 keys. + KEYBD_KEYS key_value[3]; + // Initialize key count. + int key_cnt = 0; + // Get variant array from object. + IDispatch* disp = NULL; + + // Not array of string values or integers. + if ((keys.vt != (VT_ARRAY|VT_BSTR)) && + (keys.vt != (VT_ARRAY|VT_I4)) ) { + // Retrive IDispatch. + if (keys.vt & VT_BYREF) + disp = *(keys.ppdispVal); + else + disp = keys.pdispVal; + + // Get array length. + DISPPARAMS params; + FillMemory(¶ms, sizeof(DISPPARAMS), 0); + VARIANT res; + DISPID id; + LPOLESTR ln = L"length"; + if (S_OK != disp->GetIDsOfNames(IID_NULL, &ln, 1, LOCALE_USER_DEFAULT, + &id)) { + return false; + } + + if (S_OK != disp->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, + DISPATCH_PROPERTYGET, ¶ms, &res, NULL, + NULL)) { + return false; + } + + VARIANT len; + VariantInit(&len); + VariantChangeType(&len, &res, 0, VT_I4); + if (len.lVal > 3) + return false; + key_cnt = len.lVal; + + // Add elements to safe array. + for (int i = 0; i < len.lVal; i++) { + // Fetch element. + wchar_t wstr[5]; + memset(wstr, 0, 5*sizeof(wchar_t)); + wsprintf(wstr, L"%d", i); + LPOLESTR olestr = wstr; + + if (S_OK != disp->GetIDsOfNames(IID_NULL, &olestr, 1, + LOCALE_USER_DEFAULT, &id)) { + return false; + } + + if (S_OK != disp->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, + DISPATCH_PROPERTYGET, ¶ms, &res, NULL, + NULL)) { + return false; + } + + VARIANT value; + VariantInit(&value); + VariantChangeType(&value, &res, 0, VT_BSTR); + + // Translate and add key to array. + key_value[i] = GetKeybdKeysVal(value.bstrVal); + + VariantClear(&value); + } + + VariantClear(&len); + } else { + // Directly fetch array. + SAFEARRAY* key_safe = NULL; + key_safe = V_ARRAY(&keys); + + // Operate on Variant Array. + HRESULT hr = S_OK; + LONG num_elements, lower_bound, upper_bound; + + // Array is not 1-dimentional. + if (SafeArrayGetDim(key_safe) != 1) + return false; + + // Get array bounds. + hr = SafeArrayGetLBound(key_safe, 1, &lower_bound); + if (S_OK !=hr) + return false; + hr = SafeArrayGetUBound(key_safe, 1, &upper_bound); + if (S_OK !=hr) + return false; + + // Key combination can be of maximum 3 keys. + num_elements = upper_bound - lower_bound + 1; + if (num_elements > 3) + return false; + key_cnt = num_elements; + + // Read the data in array. + if (keys.vt == (VT_ARRAY|VT_I4)) { + KEYBD_KEYS* read_keys; + hr = SafeArrayAccessData(key_safe, reinterpret_cast<void **>(&read_keys)); + if (S_OK != hr) + return false; + for (int i = 0; i < num_elements; i++) { + key_value[i] = read_keys[i]; + } + } else if (keys.vt == (VT_ARRAY|VT_BSTR)) { + BSTR* key_str_value; + hr = SafeArrayAccessData(key_safe, + reinterpret_cast<void **>(&key_str_value)); + if (S_OK != hr) + return false; + + // Translate and add key to array. + for (int i = 0; i < num_elements; i++) { + key_value[i] = GetKeybdKeysVal(key_str_value[i]); + } + } + } + + // Focus on main window and operate keys. + IAccessible* acc_obj = NULL; + HWND hwnd = GetChromeBrowserWnd(&acc_obj); + if (acc_obj || hwnd) + ActivateWnd(acc_obj, hwnd); + + if (1 == key_cnt) + ClickKey(hwnd, key_value[0]); + else if (2 == key_cnt) + ClickKey(hwnd, key_value[0], key_value[1]); + else if (3 == key_cnt) + ClickKey(hwnd, key_value[0], key_value[1], key_value[2]); + + CHK_RELEASE(acc_obj); + + return true; +} + +void BrowserImpl::UpdateTabCollection(void) { + // Get tab count and browser title. + INT64 tab_cnt = GetTabCnt(); + BSTR browser_title; + GetBrowserTitle(&browser_title); + + // Check tab-collection size and number of existing tabs, work accordingly. + + // First time creation. + if (0 == tab_collection_.size()) { + EraseTabCollection(); + for (int i = 0; i < tab_cnt; i++) { + tab_collection_[i]->index_ = i + 1; + tab_collection_[i]->title_ = + SysAllocString(GetTabName(tab_collection_[i]->index_)); + if (browser_title == tab_collection_[i]->title_) { + active_tab_index_ = tab_collection_[i]->index_; + } + } + } + SysFreeString(browser_title); + + // TODO(klink): Add implementation here to handle if tabs are reordered, + // rather than created. +} + +void BrowserImpl::EraseTabCollection(void) { + tab_collection_.clear(); +} + +void BrowserImpl::CloseTabFromCollection(INT64 index) { + std::vector <ChromeTab*>::size_type collection_size = tab_collection_.size(); + // Validate tab index. + if ((index < MIN_TAB_INDEX_DIGIT) || + (static_cast<unsigned int>(index) > collection_size)) { + return; + } + + // Index starts from 1. + tab_collection_.erase(tab_collection_.begin() + static_cast<int>(index) - 1); + + // Now update tab collection data. + collection_size = tab_collection_.size(); + + // Check if tab deleted is last tab. + if (index-1 == collection_size) { + // Change active tab index, only if tab deleted is last tab. + active_tab_index_ = index - 1; + } else { + for (std::vector <ChromeTab*>::size_type i = + static_cast<unsigned int>(index) - 1; + i < collection_size; + i++) { + tab_collection_[i]->index_--; + } + } +} |