| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "win8/test/ui_automation_client.h" | 5 #include "win8/test/ui_automation_client.h" |
| 6 | 6 |
| 7 #include <atlbase.h> | 7 #include <atlbase.h> |
| 8 #include <atlcom.h> | 8 #include <atlcom.h> |
| 9 #include <oleauto.h> | 9 #include <oleauto.h> |
| 10 #include <uiautomation.h> | 10 #include <uiautomation.h> |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 | 33 |
| 34 // Deletes the instance. | 34 // Deletes the instance. |
| 35 void DeleteOnAutomationThread(); | 35 void DeleteOnAutomationThread(); |
| 36 | 36 |
| 37 // Initializes the context, invoking |init_callback| via |client_runner| when | 37 // Initializes the context, invoking |init_callback| via |client_runner| when |
| 38 // done. On success, |result_callback| will eventually be called after the | 38 // done. On success, |result_callback| will eventually be called after the |
| 39 // window has been processed. On failure, this instance self-destructs after | 39 // window has been processed. On failure, this instance self-destructs after |
| 40 // posting |init_callback|. | 40 // posting |init_callback|. |
| 41 void Initialize( | 41 void Initialize( |
| 42 scoped_refptr<base::SingleThreadTaskRunner> client_runner, | 42 scoped_refptr<base::SingleThreadTaskRunner> client_runner, |
| 43 string16 class_name, | 43 base::string16 class_name, |
| 44 string16 item_name, | 44 base::string16 item_name, |
| 45 UIAutomationClient::InitializedCallback init_callback, | 45 UIAutomationClient::InitializedCallback init_callback, |
| 46 UIAutomationClient::ResultCallback result_callback); | 46 UIAutomationClient::ResultCallback result_callback); |
| 47 | 47 |
| 48 // Methods invoked by event handlers via weak pointers. | 48 // Methods invoked by event handlers via weak pointers. |
| 49 void HandleAutomationEvent( | 49 void HandleAutomationEvent( |
| 50 base::win::ScopedComPtr<IUIAutomationElement> sender, | 50 base::win::ScopedComPtr<IUIAutomationElement> sender, |
| 51 EVENTID eventId); | 51 EVENTID eventId); |
| 52 | 52 |
| 53 private: | 53 private: |
| 54 class EventHandler; | 54 class EventHandler; |
| 55 | 55 |
| 56 // The only and only method that may be called from outside of the automation | 56 // The only and only method that may be called from outside of the automation |
| 57 // thread. | 57 // thread. |
| 58 Context(); | 58 Context(); |
| 59 ~Context(); | 59 ~Context(); |
| 60 | 60 |
| 61 HRESULT InstallWindowObserver(); | 61 HRESULT InstallWindowObserver(); |
| 62 HRESULT RemoveWindowObserver(); | 62 HRESULT RemoveWindowObserver(); |
| 63 | 63 |
| 64 void HandleWindowOpen( | 64 void HandleWindowOpen( |
| 65 const base::win::ScopedComPtr<IUIAutomationElement>& window); | 65 const base::win::ScopedComPtr<IUIAutomationElement>& window); |
| 66 void ProcessWindow( | 66 void ProcessWindow( |
| 67 const base::win::ScopedComPtr<IUIAutomationElement>& window); | 67 const base::win::ScopedComPtr<IUIAutomationElement>& window); |
| 68 HRESULT InvokeDesiredItem( | 68 HRESULT InvokeDesiredItem( |
| 69 const base::win::ScopedComPtr<IUIAutomationElement>& element); | 69 const base::win::ScopedComPtr<IUIAutomationElement>& element); |
| 70 HRESULT GetInvokableItems( | 70 HRESULT GetInvokableItems( |
| 71 const base::win::ScopedComPtr<IUIAutomationElement>& element, | 71 const base::win::ScopedComPtr<IUIAutomationElement>& element, |
| 72 std::vector<string16>* choices); | 72 std::vector<base::string16>* choices); |
| 73 void CloseWindow(const base::win::ScopedComPtr<IUIAutomationElement>& window); | 73 void CloseWindow(const base::win::ScopedComPtr<IUIAutomationElement>& window); |
| 74 | 74 |
| 75 base::ThreadChecker thread_checker_; | 75 base::ThreadChecker thread_checker_; |
| 76 | 76 |
| 77 // The loop on which the client itself lives. | 77 // The loop on which the client itself lives. |
| 78 scoped_refptr<base::SingleThreadTaskRunner> client_runner_; | 78 scoped_refptr<base::SingleThreadTaskRunner> client_runner_; |
| 79 | 79 |
| 80 // The class name of the window for which the client waits. | 80 // The class name of the window for which the client waits. |
| 81 string16 class_name_; | 81 base::string16 class_name_; |
| 82 | 82 |
| 83 // The name of the item to invoke. | 83 // The name of the item to invoke. |
| 84 string16 item_name_; | 84 base::string16 item_name_; |
| 85 | 85 |
| 86 // The consumer's result callback. | 86 // The consumer's result callback. |
| 87 ResultCallback result_callback_; | 87 ResultCallback result_callback_; |
| 88 | 88 |
| 89 // The automation client. | 89 // The automation client. |
| 90 base::win::ScopedComPtr<IUIAutomation> automation_; | 90 base::win::ScopedComPtr<IUIAutomation> automation_; |
| 91 | 91 |
| 92 // A handler of Window open events. | 92 // A handler of Window open events. |
| 93 base::win::ScopedComPtr<IUIAutomationEventHandler> event_handler_; | 93 base::win::ScopedComPtr<IUIAutomationEventHandler> event_handler_; |
| 94 | 94 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 | 173 |
| 174 if (event_handler_.get()) { | 174 if (event_handler_.get()) { |
| 175 event_handler_ = NULL; | 175 event_handler_ = NULL; |
| 176 HRESULT result = automation_->RemoveAllEventHandlers(); | 176 HRESULT result = automation_->RemoveAllEventHandlers(); |
| 177 LOG_IF(ERROR, FAILED(result)) << std::hex << result; | 177 LOG_IF(ERROR, FAILED(result)) << std::hex << result; |
| 178 } | 178 } |
| 179 } | 179 } |
| 180 | 180 |
| 181 void UIAutomationClient::Context::Initialize( | 181 void UIAutomationClient::Context::Initialize( |
| 182 scoped_refptr<base::SingleThreadTaskRunner> client_runner, | 182 scoped_refptr<base::SingleThreadTaskRunner> client_runner, |
| 183 string16 class_name, | 183 base::string16 class_name, |
| 184 string16 item_name, | 184 base::string16 item_name, |
| 185 UIAutomationClient::InitializedCallback init_callback, | 185 UIAutomationClient::InitializedCallback init_callback, |
| 186 UIAutomationClient::ResultCallback result_callback) { | 186 UIAutomationClient::ResultCallback result_callback) { |
| 187 // This and all other methods must be called on the automation thread. | 187 // This and all other methods must be called on the automation thread. |
| 188 DCHECK(!client_runner->BelongsToCurrentThread()); | 188 DCHECK(!client_runner->BelongsToCurrentThread()); |
| 189 // Bind the checker to this thread. | 189 // Bind the checker to this thread. |
| 190 thread_checker_.DetachFromThread(); | 190 thread_checker_.DetachFromThread(); |
| 191 DCHECK(thread_checker_.CalledOnValidThread()); | 191 DCHECK(thread_checker_.CalledOnValidThread()); |
| 192 | 192 |
| 193 client_runner_ = client_runner; | 193 client_runner_ = client_runner; |
| 194 class_name_ = class_name; | 194 class_name_ = class_name; |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 if (FAILED(hr)) { | 318 if (FAILED(hr)) { |
| 319 LOG(ERROR) << std::hex << hr; | 319 LOG(ERROR) << std::hex << hr; |
| 320 return; | 320 return; |
| 321 } | 321 } |
| 322 | 322 |
| 323 if (V_VT(&var) != VT_BSTR) { | 323 if (V_VT(&var) != VT_BSTR) { |
| 324 LOG(ERROR) << __FUNCTION__ " class name is not a BSTR: " << V_VT(&var); | 324 LOG(ERROR) << __FUNCTION__ " class name is not a BSTR: " << V_VT(&var); |
| 325 return; | 325 return; |
| 326 } | 326 } |
| 327 | 327 |
| 328 string16 class_name(V_BSTR(&var)); | 328 base::string16 class_name(V_BSTR(&var)); |
| 329 | 329 |
| 330 // Window class names are atoms, which are case-insensitive. | 330 // Window class names are atoms, which are case-insensitive. |
| 331 if (class_name.size() == class_name_.size() && | 331 if (class_name.size() == class_name_.size() && |
| 332 std::equal(class_name.begin(), class_name.end(), class_name_.begin(), | 332 std::equal(class_name.begin(), class_name.end(), class_name_.begin(), |
| 333 base::CaseInsensitiveCompare<wchar_t>())) { | 333 base::CaseInsensitiveCompare<wchar_t>())) { |
| 334 RemoveWindowObserver(); | 334 RemoveWindowObserver(); |
| 335 ProcessWindow(window); | 335 ProcessWindow(window); |
| 336 } | 336 } |
| 337 } | 337 } |
| 338 | 338 |
| 339 // Processes |window| by invoking the desired child item. If the item cannot be | 339 // Processes |window| by invoking the desired child item. If the item cannot be |
| 340 // found or invoked, an attempt is made to get a list of all invokable children. | 340 // found or invoked, an attempt is made to get a list of all invokable children. |
| 341 // The results are posted back to the client on |client_runner_|, and this | 341 // The results are posted back to the client on |client_runner_|, and this |
| 342 // instance self-destructs. | 342 // instance self-destructs. |
| 343 void UIAutomationClient::Context::ProcessWindow( | 343 void UIAutomationClient::Context::ProcessWindow( |
| 344 const base::win::ScopedComPtr<IUIAutomationElement>& window) { | 344 const base::win::ScopedComPtr<IUIAutomationElement>& window) { |
| 345 DCHECK(thread_checker_.CalledOnValidThread()); | 345 DCHECK(thread_checker_.CalledOnValidThread()); |
| 346 | 346 |
| 347 HRESULT result = S_OK; | 347 HRESULT result = S_OK; |
| 348 std::vector<string16> choices; | 348 std::vector<base::string16> choices; |
| 349 result = InvokeDesiredItem(window); | 349 result = InvokeDesiredItem(window); |
| 350 if (FAILED(result)) { | 350 if (FAILED(result)) { |
| 351 GetInvokableItems(window, &choices); | 351 GetInvokableItems(window, &choices); |
| 352 CloseWindow(window); | 352 CloseWindow(window); |
| 353 } | 353 } |
| 354 | 354 |
| 355 client_runner_->PostTask(FROM_HERE, | 355 client_runner_->PostTask(FROM_HERE, |
| 356 base::Bind(result_callback_, result, choices)); | 356 base::Bind(result_callback_, result, choices)); |
| 357 | 357 |
| 358 // Self-destruct since there's nothing more to be done here. | 358 // Self-destruct since there's nothing more to be done here. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 LOG(ERROR) << std::hex << result; | 450 LOG(ERROR) << std::hex << result; |
| 451 return result; | 451 return result; |
| 452 } | 452 } |
| 453 | 453 |
| 454 return S_OK; | 454 return S_OK; |
| 455 } | 455 } |
| 456 | 456 |
| 457 // Populates |choices| with the names of all invokable children of |element|. | 457 // Populates |choices| with the names of all invokable children of |element|. |
| 458 HRESULT UIAutomationClient::Context::GetInvokableItems( | 458 HRESULT UIAutomationClient::Context::GetInvokableItems( |
| 459 const base::win::ScopedComPtr<IUIAutomationElement>& element, | 459 const base::win::ScopedComPtr<IUIAutomationElement>& element, |
| 460 std::vector<string16>* choices) { | 460 std::vector<base::string16>* choices) { |
| 461 DCHECK(choices); | 461 DCHECK(choices); |
| 462 DCHECK(thread_checker_.CalledOnValidThread()); | 462 DCHECK(thread_checker_.CalledOnValidThread()); |
| 463 | 463 |
| 464 HRESULT result = S_OK; | 464 HRESULT result = S_OK; |
| 465 base::win::ScopedVariant var; | 465 base::win::ScopedVariant var; |
| 466 base::win::ScopedComPtr<IUIAutomationCondition> invokable_condition; | 466 base::win::ScopedComPtr<IUIAutomationCondition> invokable_condition; |
| 467 base::win::ScopedComPtr<IUIAutomationCondition> control_view_condition; | 467 base::win::ScopedComPtr<IUIAutomationCondition> control_view_condition; |
| 468 base::win::ScopedComPtr<IUIAutomationCondition> condition; | 468 base::win::ScopedComPtr<IUIAutomationCondition> condition; |
| 469 base::win::ScopedComPtr<IUIAutomationCacheRequest> cache_request; | 469 base::win::ScopedComPtr<IUIAutomationCacheRequest> cache_request; |
| 470 base::win::ScopedComPtr<IUIAutomationElementArray> element_array; | 470 base::win::ScopedComPtr<IUIAutomationElementArray> element_array; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 result = child_element->GetCachedPropertyValueEx(UIA_NamePropertyId, TRUE, | 538 result = child_element->GetCachedPropertyValueEx(UIA_NamePropertyId, TRUE, |
| 539 var.Receive()); | 539 var.Receive()); |
| 540 if (FAILED(result)) { | 540 if (FAILED(result)) { |
| 541 LOG(ERROR) << std::hex << result; | 541 LOG(ERROR) << std::hex << result; |
| 542 continue; | 542 continue; |
| 543 } | 543 } |
| 544 if (V_VT(&var) != VT_BSTR) { | 544 if (V_VT(&var) != VT_BSTR) { |
| 545 LOG(ERROR) << __FUNCTION__ " name is not a BSTR: " << V_VT(&var); | 545 LOG(ERROR) << __FUNCTION__ " name is not a BSTR: " << V_VT(&var); |
| 546 continue; | 546 continue; |
| 547 } | 547 } |
| 548 choices->push_back(string16(V_BSTR(&var))); | 548 choices->push_back(base::string16(V_BSTR(&var))); |
| 549 var.Reset(); | 549 var.Reset(); |
| 550 } | 550 } |
| 551 | 551 |
| 552 return result; | 552 return result; |
| 553 } | 553 } |
| 554 | 554 |
| 555 // Closes the element |window| by sending it an escape key. | 555 // Closes the element |window| by sending it an escape key. |
| 556 void UIAutomationClient::Context::CloseWindow( | 556 void UIAutomationClient::Context::CloseWindow( |
| 557 const base::win::ScopedComPtr<IUIAutomationElement>& window) { | 557 const base::win::ScopedComPtr<IUIAutomationElement>& window) { |
| 558 DCHECK(thread_checker_.CalledOnValidThread()); | 558 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 // context_ is still valid when the caller destroys the instance before the | 595 // context_ is still valid when the caller destroys the instance before the |
| 596 // callback(s) have fired. In this case, delete the context on the automation | 596 // callback(s) have fired. In this case, delete the context on the automation |
| 597 // thread before joining with it. | 597 // thread before joining with it. |
| 598 automation_thread_.message_loop()->PostTask( | 598 automation_thread_.message_loop()->PostTask( |
| 599 FROM_HERE, | 599 FROM_HERE, |
| 600 base::Bind(&UIAutomationClient::Context::DeleteOnAutomationThread, | 600 base::Bind(&UIAutomationClient::Context::DeleteOnAutomationThread, |
| 601 context_)); | 601 context_)); |
| 602 } | 602 } |
| 603 | 603 |
| 604 void UIAutomationClient::Begin(const wchar_t* class_name, | 604 void UIAutomationClient::Begin(const wchar_t* class_name, |
| 605 const string16& item_name, | 605 const base::string16& item_name, |
| 606 const InitializedCallback& init_callback, | 606 const InitializedCallback& init_callback, |
| 607 const ResultCallback& result_callback) { | 607 const ResultCallback& result_callback) { |
| 608 DCHECK(thread_checker_.CalledOnValidThread()); | 608 DCHECK(thread_checker_.CalledOnValidThread()); |
| 609 DCHECK_EQ(context_.get(), static_cast<Context*>(NULL)); | 609 DCHECK_EQ(context_.get(), static_cast<Context*>(NULL)); |
| 610 | 610 |
| 611 // Start the automation thread and initialize our automation client on it. | 611 // Start the automation thread and initialize our automation client on it. |
| 612 context_ = Context::Create(); | 612 context_ = Context::Create(); |
| 613 automation_thread_.init_com_with_mta(true); | 613 automation_thread_.init_com_with_mta(true); |
| 614 automation_thread_.Start(); | 614 automation_thread_.Start(); |
| 615 automation_thread_.message_loop()->PostTask( | 615 automation_thread_.message_loop()->PostTask( |
| 616 FROM_HERE, | 616 FROM_HERE, |
| 617 base::Bind(&UIAutomationClient::Context::Initialize, | 617 base::Bind(&UIAutomationClient::Context::Initialize, |
| 618 context_, | 618 context_, |
| 619 base::ThreadTaskRunnerHandle::Get(), | 619 base::ThreadTaskRunnerHandle::Get(), |
| 620 string16(class_name), | 620 base::string16(class_name), |
| 621 item_name, | 621 item_name, |
| 622 init_callback, | 622 init_callback, |
| 623 result_callback)); | 623 result_callback)); |
| 624 } | 624 } |
| 625 | 625 |
| 626 } // namespace internal | 626 } // namespace internal |
| 627 } // namespace win8 | 627 } // namespace win8 |
| OLD | NEW |