PageRenderTime 197ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/chrome/test/accessibility/browser_impl.cc

https://github.com/akesling/chromium
C++ | 512 lines | 352 code | 92 blank | 68 comment | 100 complexity | a3ce8a078ae507b4ba2e2e826e1d0e88 MD5 | raw file
  1. // Copyright (c) 2006-2008 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. #include "chrome/test/accessibility/browser_impl.h"
  5. #include <shellapi.h>
  6. #include "chrome/test/accessibility/accessibility_util.h"
  7. #include "chrome/test/accessibility/keyboard_util.h"
  8. #include "chrome/test/accessibility/registry_util.h"
  9. bool BrowserImpl::Launch(void) {
  10. // TODO(klink): Check if chrome already running.
  11. BSTR chrome_path = SysAllocString(GetChromeExePath());
  12. BOOL success = FALSE;
  13. // Initialize and fill up structure.
  14. SHELLEXECUTEINFO shell_execute_info;
  15. memset(&shell_execute_info, 0, sizeof(SHELLEXECUTEINFO));
  16. shell_execute_info.cbSize = sizeof(SHELLEXECUTEINFO);
  17. // To get Process handle.
  18. shell_execute_info.fMask = SEE_MASK_NOCLOSEPROCESS;
  19. shell_execute_info.nShow = SW_SHOW;
  20. shell_execute_info.lpFile =
  21. reinterpret_cast<TCHAR*>(malloc(sizeof(TCHAR) *
  22. SysStringLen(chrome_path)));
  23. _tcscpy_s((TCHAR*)(shell_execute_info.lpFile), SysStringLen(chrome_path),
  24. chrome_path);
  25. // Execute.
  26. success = ShellExecuteEx(&shell_execute_info);
  27. if (success && (INT64(shell_execute_info.hInstApp) > 32)) {
  28. // TODO(klink): Maintain instance and process handle.
  29. // Maintain active tab index.
  30. SetActiveTabIndex(1);
  31. // Create initial tab collection.
  32. UpdateTabCollection();
  33. // Chrome launched.
  34. SysFreeString(chrome_path);
  35. return true;
  36. }
  37. SysFreeString(chrome_path);
  38. return false;
  39. }
  40. bool BrowserImpl::Quit(void) {
  41. // Cleanup.
  42. EraseTabCollection();
  43. // Send close message to browser window.
  44. HWND hwnd = GetChromeBrowserWnd(NULL);
  45. if (!hwnd)
  46. return false;
  47. SendMessage(hwnd, WM_CLOSE, 0, 0);
  48. return true;
  49. }
  50. bool BrowserImpl::ActivateTab(const INT64 index) {
  51. // Validate index specified.
  52. if (index < 1)
  53. return false;
  54. // Goto next tab till focused at desired tab.
  55. while (active_tab_index_ != index) {
  56. GoToNextTab(NULL);
  57. }
  58. return true;
  59. }
  60. bool BrowserImpl::GetActiveTabURL(BSTR* url) {
  61. // Validate input.
  62. if (!url)
  63. return false;
  64. return true;
  65. }
  66. bool BrowserImpl::GetActiveTabTitle(BSTR* title) {
  67. if (!title)
  68. return false;
  69. *title = SysAllocString(GetTabName(active_tab_index_));
  70. return true;
  71. }
  72. bool BrowserImpl::GetActiveTabIndex(INT64* index) {
  73. if (!index)
  74. return false;
  75. *index = active_tab_index_;
  76. return true;
  77. }
  78. void BrowserImpl::SetActiveTabIndex(INT64 index) {
  79. if ((index >= MIN_TAB_INDEX_DIGIT) && (index <= GetTabCnt()))
  80. active_tab_index_ = index;
  81. return;
  82. }
  83. bool BrowserImpl::GetActiveTab(TabImpl** tab) {
  84. return GetTab(active_tab_index_, tab);
  85. }
  86. bool BrowserImpl::GetTabCount(INT64* count) {
  87. if (!count)
  88. return false;
  89. *count = GetTabCnt();
  90. return true;
  91. }
  92. bool BrowserImpl::GetBrowserProcessCount(INT64* count) {
  93. if (!count)
  94. return false;
  95. return true;
  96. }
  97. bool BrowserImpl::GetBrowserTitle(BSTR* title) {
  98. if (!title)
  99. return false;
  100. HWND hwnd = GetChromeBrowserWnd(NULL);
  101. if (!hwnd)
  102. return false;
  103. int text_length = GetWindowTextLength(hwnd);
  104. *title = SysAllocStringLen(NULL, text_length);
  105. GetWindowText(hwnd, *title, text_length);
  106. return true;
  107. }
  108. bool BrowserImpl::AddTab(TabImpl** tab) {
  109. // Add new tab.
  110. HWND hwnd = GetChromeBrowserWnd(NULL);
  111. if (!hwnd)
  112. return false;
  113. ClickKey(hwnd, VK_CONTROL, 'T');
  114. // Update active tab index.
  115. INT64 new_tab_index = GetTabCnt();
  116. if (-1 == new_tab_index)
  117. return false;
  118. SetActiveTabIndex(new_tab_index);
  119. // Fill object.
  120. TabImpl* new_tab = new TabImpl();
  121. if (!new_tab)
  122. return false;
  123. ChromeTab* tab_data = new_tab->InitTabData();
  124. new_tab->set_index(new_tab_index);
  125. new_tab->set_title(GetTabName(new_tab_index));
  126. new_tab->set_browser(this);
  127. // Create a copy for storage, in case the caller deletes this newly created
  128. // TabImpl before [tab_collection_] is done using [tab_data].
  129. ChromeTab* tab_data_copy = tab_data;
  130. // Update tab collection.
  131. tab_collection_.push_back(linked_ptr<ChromeTab>(tab_data_copy));
  132. // Create tab object, if requested.
  133. if (tab)
  134. *tab = new_tab;
  135. return true;
  136. }
  137. bool BrowserImpl::GetTab(const INT64 index, TabImpl** tab) {
  138. // Create tab object, if requested.
  139. if (!tab)
  140. return false;
  141. if (index > GetTabCnt())
  142. return false;
  143. *tab = new TabImpl();
  144. if (!*tab)
  145. return false;
  146. // Fill object.
  147. ChromeTab* tab_data = (*tab)->InitTabData();
  148. (*tab)->set_index(index);
  149. (*tab)->set_title(GetTabName(index));
  150. (*tab)->set_browser(this);
  151. return true;
  152. }
  153. bool BrowserImpl::GoToTab(const INT64 index, TabImpl** tab) {
  154. // Validate input.
  155. if (index > MAX_TAB_INDEX_DIGIT)
  156. return false;
  157. // Stay on current tab, if index doesnot exist.
  158. if ((0 == index) || (GetTabCnt() < index))
  159. return true;
  160. // Move to a tab (indexed 1 to 9).
  161. IAccessible* acc_obj = NULL;
  162. HWND hwnd = GetChromeBrowserWnd(&acc_obj);
  163. if (acc_obj && hwnd) {
  164. // Activate main window and operate key Ctrl+digit.
  165. ActivateWnd(acc_obj, hwnd);
  166. ClickKey(hwnd, VK_CONTROL, WORD('0'+index));
  167. CHK_RELEASE(acc_obj);
  168. // Set focused tab index.
  169. active_tab_index_ = index;
  170. // Return tab object.
  171. if (tab) {
  172. return GetTab(active_tab_index_, tab);
  173. }
  174. }
  175. return false;
  176. }
  177. bool BrowserImpl::GoToNextTab(TabImpl** tab) {
  178. IAccessible* acc_obj = NULL;
  179. HWND hwnd = GetChromeBrowserWnd(&acc_obj);
  180. if (acc_obj && hwnd) {
  181. // Activate main window and operate key Ctrl+Tab.
  182. ActivateWnd(acc_obj, hwnd);
  183. ClickKey(hwnd, VK_CONTROL, VK_TAB);
  184. CHK_RELEASE(acc_obj);
  185. // Set focused tab index.
  186. if (active_tab_index_ == GetTabCnt()) {
  187. active_tab_index_ = 1;
  188. } else {
  189. active_tab_index_ = active_tab_index_ + 1;
  190. }
  191. // Return tab object.
  192. if (tab) {
  193. return GetTab(active_tab_index_, tab);
  194. }
  195. }
  196. return false;
  197. }
  198. bool BrowserImpl::GoToPrevTab(TabImpl** tab) {
  199. IAccessible* acc_obj = NULL;
  200. HWND hwnd = GetChromeBrowserWnd(&acc_obj);
  201. if (acc_obj && hwnd) {
  202. // Activate main window and operate key Ctrl+Tab.
  203. ActivateWnd(acc_obj, hwnd);
  204. ClickKey(hwnd, VK_SHIFT, VK_CONTROL, VK_TAB);
  205. CHK_RELEASE(acc_obj);
  206. // Set focused tab index.
  207. if (active_tab_index_ == 1) {
  208. active_tab_index_ = GetTabCnt();
  209. } else {
  210. active_tab_index_ = active_tab_index_ - 1;
  211. }
  212. // Return tab object.
  213. if (tab) {
  214. return GetTab(active_tab_index_, tab);
  215. }
  216. }
  217. return false;
  218. }
  219. bool BrowserImpl::WaitForChromeToBeVisible(const INT64 interval,
  220. const INT64 timeout, bool* visible) {
  221. IAccessible* acc_obj = NULL;
  222. INT64 time_elapsed = 0;
  223. *visible = false;
  224. // Check and wait.
  225. while (timeout >= time_elapsed) {
  226. GetTabStripAccessible(&acc_obj);
  227. if (acc_obj) {
  228. *visible = true;
  229. CHK_RELEASE(acc_obj);
  230. return true;
  231. }
  232. Sleep(DWORD(interval));
  233. time_elapsed = time_elapsed + interval;
  234. }
  235. return false;
  236. }
  237. bool BrowserImpl::WaitForTabCountToChange(const INT64 interval,
  238. const INT64 timeout, bool* changed) {
  239. return true;
  240. }
  241. bool BrowserImpl::WaitForTabToBecomeActive(const INT64 index,
  242. const INT64 interval,
  243. const INT64 timeout,
  244. bool* activated) {
  245. return true;
  246. }
  247. bool BrowserImpl::ApplyAccelerator(VARIANT keys) {
  248. // Input should be -array of enum or strings or -IDispatch (jscript array
  249. // object).
  250. if ((keys.vt != (VT_ARRAY|VT_BSTR)) && // Array of string values.
  251. (keys.vt != (VT_ARRAY|VT_I4)) && // Array of enum values.
  252. (!(keys.vt & VT_DISPATCH)) ) { // Object.
  253. return false;
  254. }
  255. // Array to store keys in a single combination. Currently, valid keyboard
  256. // -input combination can constitute of at the most 3 keys.
  257. KEYBD_KEYS key_value[3];
  258. // Initialize key count.
  259. int key_cnt = 0;
  260. // Get variant array from object.
  261. IDispatch* disp = NULL;
  262. // Not array of string values or integers.
  263. if ((keys.vt != (VT_ARRAY|VT_BSTR)) &&
  264. (keys.vt != (VT_ARRAY|VT_I4)) ) {
  265. // Retrive IDispatch.
  266. if (keys.vt & VT_BYREF)
  267. disp = *(keys.ppdispVal);
  268. else
  269. disp = keys.pdispVal;
  270. // Get array length.
  271. DISPPARAMS params;
  272. FillMemory(&params, sizeof(DISPPARAMS), 0);
  273. VARIANT res;
  274. DISPID id;
  275. LPOLESTR ln = L"length";
  276. if (S_OK != disp->GetIDsOfNames(IID_NULL, &ln, 1, LOCALE_USER_DEFAULT,
  277. &id)) {
  278. return false;
  279. }
  280. if (S_OK != disp->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT,
  281. DISPATCH_PROPERTYGET, &params, &res, NULL,
  282. NULL)) {
  283. return false;
  284. }
  285. VARIANT len;
  286. VariantInit(&len);
  287. VariantChangeType(&len, &res, 0, VT_I4);
  288. if (len.lVal > 3)
  289. return false;
  290. key_cnt = len.lVal;
  291. // Add elements to safe array.
  292. for (int i = 0; i < len.lVal; i++) {
  293. // Fetch element.
  294. wchar_t wstr[5];
  295. memset(wstr, 0, 5*sizeof(wchar_t));
  296. wsprintf(wstr, L"%d", i);
  297. LPOLESTR olestr = wstr;
  298. if (S_OK != disp->GetIDsOfNames(IID_NULL, &olestr, 1,
  299. LOCALE_USER_DEFAULT, &id)) {
  300. return false;
  301. }
  302. if (S_OK != disp->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT,
  303. DISPATCH_PROPERTYGET, &params, &res, NULL,
  304. NULL)) {
  305. return false;
  306. }
  307. VARIANT value;
  308. VariantInit(&value);
  309. VariantChangeType(&value, &res, 0, VT_BSTR);
  310. // Translate and add key to array.
  311. key_value[i] = GetKeybdKeysVal(value.bstrVal);
  312. VariantClear(&value);
  313. }
  314. VariantClear(&len);
  315. } else {
  316. // Directly fetch array.
  317. SAFEARRAY* key_safe = NULL;
  318. key_safe = V_ARRAY(&keys);
  319. // Operate on Variant Array.
  320. HRESULT hr = S_OK;
  321. LONG num_elements, lower_bound, upper_bound;
  322. // Array is not 1-dimentional.
  323. if (SafeArrayGetDim(key_safe) != 1)
  324. return false;
  325. // Get array bounds.
  326. hr = SafeArrayGetLBound(key_safe, 1, &lower_bound);
  327. if (S_OK !=hr)
  328. return false;
  329. hr = SafeArrayGetUBound(key_safe, 1, &upper_bound);
  330. if (S_OK !=hr)
  331. return false;
  332. // Key combination can be of maximum 3 keys.
  333. num_elements = upper_bound - lower_bound + 1;
  334. if (num_elements > 3)
  335. return false;
  336. key_cnt = num_elements;
  337. // Read the data in array.
  338. if (keys.vt == (VT_ARRAY|VT_I4)) {
  339. KEYBD_KEYS* read_keys;
  340. hr = SafeArrayAccessData(key_safe, reinterpret_cast<void **>(&read_keys));
  341. if (S_OK != hr)
  342. return false;
  343. for (int i = 0; i < num_elements; i++) {
  344. key_value[i] = read_keys[i];
  345. }
  346. } else if (keys.vt == (VT_ARRAY|VT_BSTR)) {
  347. BSTR* key_str_value;
  348. hr = SafeArrayAccessData(key_safe,
  349. reinterpret_cast<void **>(&key_str_value));
  350. if (S_OK != hr)
  351. return false;
  352. // Translate and add key to array.
  353. for (int i = 0; i < num_elements; i++) {
  354. key_value[i] = GetKeybdKeysVal(key_str_value[i]);
  355. }
  356. }
  357. }
  358. // Focus on main window and operate keys.
  359. IAccessible* acc_obj = NULL;
  360. HWND hwnd = GetChromeBrowserWnd(&acc_obj);
  361. if (acc_obj || hwnd)
  362. ActivateWnd(acc_obj, hwnd);
  363. if (1 == key_cnt)
  364. ClickKey(hwnd, key_value[0]);
  365. else if (2 == key_cnt)
  366. ClickKey(hwnd, key_value[0], key_value[1]);
  367. else if (3 == key_cnt)
  368. ClickKey(hwnd, key_value[0], key_value[1], key_value[2]);
  369. CHK_RELEASE(acc_obj);
  370. return true;
  371. }
  372. void BrowserImpl::UpdateTabCollection(void) {
  373. // Get tab count and browser title.
  374. INT64 tab_cnt = GetTabCnt();
  375. BSTR browser_title;
  376. GetBrowserTitle(&browser_title);
  377. // Check tab-collection size and number of existing tabs, work accordingly.
  378. // First time creation.
  379. if (0 == tab_collection_.size()) {
  380. EraseTabCollection();
  381. for (int i = 0; i < tab_cnt; i++) {
  382. tab_collection_[i]->index_ = i + 1;
  383. tab_collection_[i]->title_ =
  384. SysAllocString(GetTabName(tab_collection_[i]->index_));
  385. if (browser_title == tab_collection_[i]->title_) {
  386. active_tab_index_ = tab_collection_[i]->index_;
  387. }
  388. }
  389. }
  390. SysFreeString(browser_title);
  391. // TODO(klink): Add implementation here to handle if tabs are reordered,
  392. // rather than created.
  393. }
  394. void BrowserImpl::EraseTabCollection(void) {
  395. tab_collection_.clear();
  396. }
  397. void BrowserImpl::CloseTabFromCollection(INT64 index) {
  398. std::vector <ChromeTab*>::size_type collection_size = tab_collection_.size();
  399. // Validate tab index.
  400. if ((index < MIN_TAB_INDEX_DIGIT) ||
  401. (static_cast<unsigned int>(index) > collection_size)) {
  402. return;
  403. }
  404. // Index starts from 1.
  405. tab_collection_.erase(tab_collection_.begin() + static_cast<int>(index) - 1);
  406. // Now update tab collection data.
  407. collection_size = tab_collection_.size();
  408. // Check if tab deleted is last tab.
  409. if (index-1 == collection_size) {
  410. // Change active tab index, only if tab deleted is last tab.
  411. active_tab_index_ = index - 1;
  412. } else {
  413. for (std::vector <ChromeTab*>::size_type i =
  414. static_cast<unsigned int>(index) - 1;
  415. i < collection_size;
  416. i++) {
  417. tab_collection_[i]->index_--;
  418. }
  419. }
  420. }