31
31
#include " BrowserFactory.h"
32
32
#include " CommandExecutor.h"
33
33
#include " CommandHandlerRepository.h"
34
+ #include " Element.h"
34
35
#include " ElementFinder.h"
35
36
#include " ElementRepository.h"
36
37
#include " IECommandHandler.h"
37
38
#include " InputManager.h"
38
39
#include " HtmlDialog.h"
39
40
#include " ProxyManager.h"
40
41
#include " StringUtilities.h"
42
+ #include " Script.h"
41
43
42
44
namespace webdriver {
43
45
@@ -350,6 +352,71 @@ LRESULT IECommandExecutor::OnGetQuitStatus(UINT uMsg,
350
352
return this ->is_quitting_ && this ->managed_browsers_ .size () > 0 ? 1 : 0 ;
351
353
}
352
354
355
+ LRESULT IECommandExecutor::OnScriptWait (UINT uMsg,
356
+ WPARAM wParam,
357
+ LPARAM lParam,
358
+ BOOL& bHandled) {
359
+ LOG (TRACE) << " Entering IECommandExecutor::OnScriptWait" ;
360
+
361
+ BrowserHandle browser;
362
+ int status_code = this ->GetCurrentBrowser (&browser);
363
+ if (status_code == WD_SUCCESS && !browser->is_closing ()) {
364
+ if (this ->async_script_timeout_ >= 0 && this ->wait_timeout_ < clock ()) {
365
+ ::SendMessage (browser->script_executor_handle (), WD_ASYNC_SCRIPT_DETACH_LISTENTER, NULL, NULL);
366
+ Response timeout_response;
367
+ timeout_response.SetErrorResponse(ERROR_SCRIPT_TIMEOUT, " Timed out waiting for script to complete." );
368
+ this ->serialized_response_ = timeout_response.Serialize ();
369
+ this ->is_waiting_ = false ;
370
+ browser->set_script_executor_handle (NULL );
371
+ } else {
372
+ HWND alert_handle;
373
+ bool is_execution_finished = ::SendMessage (browser->script_executor_handle (), WD_ASYNC_SCRIPT_IS_EXECUTION_COMPLETE, NULL , NULL ) != 0 ;
374
+ bool is_alert_active = this ->IsAlertActive (browser, &alert_handle);
375
+ this ->is_waiting_ = !is_execution_finished && !is_alert_active;
376
+ if (this ->is_waiting_ ) {
377
+ // If we are still waiting, we need to wait a bit then post a message to
378
+ // ourselves to run the wait again. However, we can't wait using Sleep()
379
+ // on this thread. This call happens in a message loop, and we would be
380
+ // unable to process the COM events in the browser if we put this thread
381
+ // to sleep.
382
+ unsigned int thread_id = 0 ;
383
+ HANDLE thread_handle = reinterpret_cast <HANDLE>(_beginthreadex (NULL ,
384
+ 0 ,
385
+ &IECommandExecutor::ScriptWaitThreadProc,
386
+ (void *)this ->m_hWnd ,
387
+ 0 ,
388
+ &thread_id));
389
+ if (thread_handle != NULL ) {
390
+ ::CloseHandle (thread_handle);
391
+ } else {
392
+ LOGERR (DEBUG) << " Unable to create waiter thread" ;
393
+ }
394
+ } else {
395
+ Response response;
396
+ ::SendMessage (browser->script_executor_handle (), WD_ASYNC_SCRIPT_DETACH_LISTENTER, NULL, NULL);
397
+ int status_code = static_cast <int >(::SendMessage(browser->script_executor_handle (), WD_ASYNC_SCRIPT_GET_RESULT, NULL, NULL));
398
+ if (status_code != WD_SUCCESS) {
399
+ response.SetErrorResponse (status_code, " Error executing JavaScript" );
400
+ } else {
401
+ CComPtr<IHTMLDocument2> doc;
402
+ browser->GetDocument (&doc);
403
+ Script result_retrieval_script (doc,
404
+ " (function() { return function(){ return window.document.__webdriver_script_result; };})();" ,
405
+ 0 );
406
+ status_code = result_retrieval_script.Execute ();
407
+ Json::Value script_result;
408
+ result_retrieval_script.ConvertResultToJsonValue (*this , &script_result);
409
+ response.SetSuccessResponse (script_result);
410
+ }
411
+ this ->serialized_response_ = response.Serialize ();
412
+ }
413
+ }
414
+ } else {
415
+ this ->is_waiting_ = false ;
416
+ }
417
+ return 0 ;
418
+ }
419
+
353
420
LRESULT IECommandExecutor::OnRefreshManagedElements (UINT uMsg,
354
421
WPARAM wParam,
355
422
LPARAM lParam,
@@ -374,6 +441,39 @@ LRESULT IECommandExecutor::OnHandleUnexpectedAlerts(UINT uMsg,
374
441
return 0 ;
375
442
}
376
443
444
+ LRESULT IECommandExecutor::OnGetManagedElement (UINT uMsg,
445
+ WPARAM wParam,
446
+ LPARAM lParam,
447
+ BOOL& bHandled) {
448
+ ElementInfo* info = reinterpret_cast <ElementInfo*>(lParam);
449
+ ElementHandle element_handle;
450
+ int status_code = this ->GetManagedElement (info->element_id , &element_handle);
451
+ if (status_code == WD_SUCCESS) {
452
+ info->element = element_handle->element ();
453
+ }
454
+ return status_code;
455
+ }
456
+
457
+ LRESULT IECommandExecutor::OnAddManagedElement (UINT uMsg,
458
+ WPARAM wParam,
459
+ LPARAM lParam,
460
+ BOOL& bHandled) {
461
+ ElementInfo* info = reinterpret_cast <ElementInfo*>(lParam);
462
+ ElementHandle element_handle;
463
+ this ->AddManagedElement (info->element , &element_handle);
464
+ info->element_id = element_handle->element_id ();
465
+ return WD_SUCCESS;
466
+ }
467
+
468
+ LRESULT IECommandExecutor::OnRemoveManagedElement (UINT uMsg,
469
+ WPARAM wParam,
470
+ LPARAM lParam,
471
+ BOOL& bHandled) {
472
+ ElementInfo* info = reinterpret_cast <ElementInfo*>(lParam);
473
+ this ->RemoveManagedElement (info->element_id );
474
+ return WD_SUCCESS;
475
+ }
476
+
377
477
unsigned int WINAPI IECommandExecutor::WaitThreadProc (LPVOID lpParameter) {
378
478
LOG (TRACE) << " Entering IECommandExecutor::WaitThreadProc" ;
379
479
HWND window_handle = reinterpret_cast <HWND>(lpParameter);
@@ -382,6 +482,13 @@ unsigned int WINAPI IECommandExecutor::WaitThreadProc(LPVOID lpParameter) {
382
482
return 0 ;
383
483
}
384
484
485
+ unsigned int WINAPI IECommandExecutor::ScriptWaitThreadProc (LPVOID lpParameter) {
486
+ LOG (TRACE) << " Entering IECommandExecutor::ScriptWaitThreadProc" ;
487
+ HWND window_handle = reinterpret_cast <HWND>(lpParameter);
488
+ ::Sleep (WAIT_TIME_IN_MILLISECONDS);
489
+ ::PostMessage (window_handle, WD_SCRIPT_WAIT, NULL , NULL );
490
+ return 0 ;
491
+ }
385
492
386
493
unsigned int WINAPI IECommandExecutor::ThreadProc (LPVOID lpParameter) {
387
494
LOG (TRACE) << " Entering IECommandExecutor::ThreadProc" ;
@@ -522,6 +629,16 @@ void IECommandExecutor::DispatchCommand() {
522
629
this ->wait_timeout_ = clock () + (static_cast <int >(this ->page_load_timeout_ ) / 1000 * CLOCKS_PER_SEC);
523
630
}
524
631
::PostMessage (this ->m_hWnd, WD_WAIT, NULL , NULL );
632
+ } else {
633
+ HWND script_executor_handle = browser->script_executor_handle ();
634
+ this ->is_waiting_ = script_executor_handle != NULL ;
635
+ if (this ->is_waiting_ ) {
636
+ if (this ->async_script_timeout_ >= 0 ) {
637
+ this ->wait_timeout_ = clock () + (static_cast <int >(this ->async_script_timeout_ ) / 1000 * CLOCKS_PER_SEC);
638
+ }
639
+ ::PostMessage (this ->m_hWnd, WD_SCRIPT_WAIT, NULL , NULL );
640
+ return ;
641
+ }
525
642
}
526
643
} else {
527
644
if (this ->current_command_ .command_type () != webdriver::CommandType::Quit) {
@@ -677,7 +794,37 @@ int IECommandExecutor::CreateNewBrowser(std::string* error_message) {
677
794
int IECommandExecutor::GetManagedElement (const std::string& element_id,
678
795
ElementHandle* element_wrapper) const {
679
796
LOG (TRACE) << " Entering IECommandExecutor::GetManagedElement" ;
680
- return this ->managed_elements_ ->GetManagedElement (element_id, element_wrapper);
797
+ ElementHandle candidate_wrapper;
798
+ int result = this ->managed_elements_ ->GetManagedElement (element_id, &candidate_wrapper);
799
+ if (result != WD_SUCCESS) {
800
+ LOG (WARN) << " Unable to get managed element, element not found" ;
801
+ return result;
802
+ } else {
803
+ if (!candidate_wrapper->IsAttachedToDom ()) {
804
+ LOG (WARN) << " Found managed element is no longer valid" ;
805
+ this ->managed_elements_ ->RemoveManagedElement (element_id);
806
+ return EOBSOLETEELEMENT;
807
+ } else {
808
+ // If the element is attached to the DOM, validate that its document
809
+ // is the currently-focused document (via frames).
810
+ BrowserHandle current_browser;
811
+ this ->GetCurrentBrowser (¤t_browser);
812
+ CComPtr<IHTMLDocument2> focused_doc;
813
+ current_browser->GetDocument (&focused_doc);
814
+
815
+ CComPtr<IDispatch> parent_doc_dispatch;
816
+ candidate_wrapper->element ()->get_document (&parent_doc_dispatch);
817
+
818
+ if (focused_doc.IsEqualObject (parent_doc_dispatch)) {
819
+ *element_wrapper = candidate_wrapper;
820
+ return WD_SUCCESS;
821
+ } else {
822
+ LOG (WARN) << " Found managed element's document is not currently focused" ;
823
+ }
824
+ }
825
+ }
826
+
827
+ return EOBSOLETEELEMENT;
681
828
}
682
829
683
830
void IECommandExecutor::AddManagedElement (IHTMLElement* element,
0 commit comments