| 424 | } |
| 425 | |
| 426 | int Script::CreateAsyncScriptExecutor(HWND element_repository_handle, |
| 427 | const std::wstring& serialized_args, |
| 428 | HWND* async_executor_handle) { |
| 429 | LOG(TRACE) << "Entering Script::CreateAsyncScriptExecutor"; |
| 430 | CComVariant result = L""; |
| 431 | CComBSTR error_description = L""; |
| 432 | |
| 433 | AsyncScriptExecutorThreadContext thread_context; |
| 434 | thread_context.script_source = this->source_code_.c_str(); |
| 435 | thread_context.script_argument_count = this->argument_count_; |
| 436 | thread_context.main_element_repository_handle = element_repository_handle; |
| 437 | thread_context.serialized_script_args = serialized_args.c_str(); |
| 438 | |
| 439 | // We need exclusive access to this event. If it's already created, |
| 440 | // OpenEvent returns non-NULL, so we need to wait a bit and retry |
| 441 | // until OpenEvent returns NULL. |
| 442 | int retry_counter = 50; |
| 443 | HANDLE event_handle = ::OpenEvent(SYNCHRONIZE, FALSE, ASYNC_SCRIPT_EVENT_NAME); |
| 444 | while (event_handle != NULL && --retry_counter > 0) { |
| 445 | ::CloseHandle(event_handle); |
| 446 | ::Sleep(50); |
| 447 | event_handle = ::OpenEvent(SYNCHRONIZE, FALSE, ASYNC_SCRIPT_EVENT_NAME); |
| 448 | } |
| 449 | |
| 450 | // Failure condition here. |
| 451 | if (event_handle != NULL) { |
| 452 | ::CloseHandle(event_handle); |
| 453 | LOG(WARN) << "OpenEvent() returned non-NULL, event already exists."; |
| 454 | result.Clear(); |
| 455 | result.vt = VT_BSTR; |
| 456 | error_description = L"Couldn't create an event for synchronizing the creation of the thread. This generally means that you were trying to click on an option in two different instances."; |
| 457 | result.bstrVal = error_description; |
| 458 | this->result_.Copy(&result); |
| 459 | return EUNEXPECTEDJSERROR; |
| 460 | } |
| 461 | |
| 462 | LOG(DEBUG) << "Creating synchronization event for new thread"; |
| 463 | event_handle = ::CreateEvent(NULL, TRUE, FALSE, ASYNC_SCRIPT_EVENT_NAME); |
| 464 | if (event_handle == NULL || ::GetLastError() == ERROR_ALREADY_EXISTS) { |
| 465 | if (event_handle == NULL) { |
| 466 | LOG(WARN) << "CreateEvent() failed."; |
| 467 | error_description = L"Couldn't create an event for synchronizing the creation of the thread. This is an internal failure at the Windows OS level, and is generally not due to an error in the IE driver."; |
| 468 | } else { |
| 469 | ::CloseHandle(event_handle); |
| 470 | LOG(WARN) << "Synchronization event is already created in another instance."; |
| 471 | error_description = L"Couldn't create an event for synchronizing the creation of the thread. This generally means that you were trying to click on an option in multiple different instances."; |
| 472 | } |
| 473 | result.Clear(); |
| 474 | result.vt = VT_BSTR; |
| 475 | result.bstrVal = error_description; |
| 476 | this->result_.Copy(&result); |
| 477 | return EUNEXPECTEDJSERROR; |
| 478 | } |
| 479 | |
| 480 | // Start the thread and wait up to 1 second to be signaled that it is ready |
| 481 | // to receive messages, then close the event handle. |
| 482 | LOG(DEBUG) << "Starting new thread"; |
| 483 | unsigned int thread_id = 0; |
no test coverage detected