Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // ExecutorsManager implementation. | 5 // ExecutorsManager implementation. |
| 6 | 6 |
| 7 #include "ceee/ie/broker/executors_manager.h" | 7 #include "ceee/ie/broker/executors_manager.h" |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "ceee/ie/broker/broker_module_util.h" | 10 #include "ceee/ie/broker/broker_module_util.h" |
| 11 #include "ceee/ie/broker/chrome_postman.h" | |
| 11 #include "ceee/ie/broker/common_api_module.h" | 12 #include "ceee/ie/broker/common_api_module.h" |
| 12 #include "ceee/common/com_utils.h" | 13 #include "ceee/common/com_utils.h" |
| 13 | 14 |
| 14 namespace { | 15 namespace { |
| 15 | 16 |
| 16 // The timeout we set before accepting a failure when we wait for events. | 17 // The timeout we set before accepting a failure when we wait for events. |
| 17 const DWORD kTimeOut = 20000; | 18 const DWORD kTimeOut = 20000; |
| 18 | 19 |
| 19 // Utility class to ensure the setting of an event before we exit a method. | 20 // Utility class to ensure the setting of an event before we exit a method. |
| 20 class AutoSetEvent { | 21 class AutoSetEvent { |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 185 } | 186 } |
| 186 | 187 |
| 187 // Update the list of handles that our thread is waiting on. | 188 // Update the list of handles that our thread is waiting on. |
| 188 BOOL success = ::SetEvent(update_threads_list_gate_); | 189 BOOL success = ::SetEvent(update_threads_list_gate_); |
| 189 DCHECK(success); | 190 DCHECK(success); |
| 190 return S_OK; | 191 return S_OK; |
| 191 } | 192 } |
| 192 | 193 |
| 193 HRESULT ExecutorsManager::GetExecutor(ThreadId thread_id, HWND window, | 194 HRESULT ExecutorsManager::GetExecutor(ThreadId thread_id, HWND window, |
| 194 REFIID riid, void** executor) { | 195 REFIID riid, void** executor) { |
| 196 VLOG(1) << "Thread: " << thread_id << ", window: " << window; | |
| 195 DCHECK(executor != NULL); | 197 DCHECK(executor != NULL); |
| 196 // We may need to wait for either a currently pending | 198 // We may need to wait for either a currently pending |
| 197 // or own newly created registration of a new executor. | 199 // or own newly created registration of a new executor. |
| 198 CHandle executor_registration_gate; | 200 CHandle executor_registration_gate; |
| 199 | 201 |
| 200 // We need to remember if we must create a new one or not. | 202 // We need to remember if we must create a new one or not. |
| 201 // But we must create the executor creator outside of the lock. | 203 // But we must create the executor creator outside of the lock. |
| 202 bool create_executor = false; | 204 bool create_executor = false; |
| 203 { | 205 { |
| 204 AutoLock lock(lock_); | 206 AutoLock lock(lock_); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 HWND frame_window = window_utils::GetTopLevelParent(handle); | 394 HWND frame_window = window_utils::GetTopLevelParent(handle); |
| 393 // There are cases where it's too late to get the parent, | 395 // There are cases where it's too late to get the parent, |
| 394 // so we will need to dig for it deeper later. | 396 // so we will need to dig for it deeper later. |
| 395 if (!common_api::CommonApiResult::IsIeFrameClass(frame_window)) | 397 if (!common_api::CommonApiResult::IsIeFrameClass(frame_window)) |
| 396 frame_window = NULL; | 398 frame_window = NULL; |
| 397 | 399 |
| 398 bool send_on_removed = false; | 400 bool send_on_removed = false; |
| 399 AutoLock lock(lock_); | 401 AutoLock lock(lock_); |
| 400 { | 402 { |
| 401 HandleMap::iterator handle_it = handle_map_.find(handle); | 403 HandleMap::iterator handle_it = handle_map_.find(handle); |
| 402 DCHECK(handle_map_.end() != handle_it); | 404 // Don't DCHECK, we may be called more than once, but it's fine, |
| 405 // we just ignore subsequent calls. | |
| 403 if (handle_map_.end() != handle_it) { | 406 if (handle_map_.end() != handle_it) { |
| 404 TabIdMap::iterator tab_id_it = tab_id_map_.find(handle_it->second); | 407 TabIdMap::iterator tab_id_it = tab_id_map_.find(handle_it->second); |
| 408 // But if we have it in one map, we must have it in the reverse map. | |
| 405 DCHECK(tab_id_map_.end() != tab_id_it); | 409 DCHECK(tab_id_map_.end() != tab_id_it); |
| 406 if (tab_id_map_.end() != tab_id_it) { | 410 if (tab_id_map_.end() != tab_id_it) { |
| 407 #ifdef DEBUG | 411 #ifdef DEBUG |
| 408 tab_id_map_[handle_it->second] = | 412 tab_id_map_[handle_it->second] = |
| 409 reinterpret_cast<HWND>(INVALID_HANDLE_VALUE); | 413 reinterpret_cast<HWND>(INVALID_HANDLE_VALUE); |
| 410 handle_map_[handle] = kInvalidChromeSessionId; | 414 handle_map_[handle] = kInvalidChromeSessionId; |
| 411 #else | 415 #else |
| 412 tab_id_map_.erase(handle_it->second); | 416 tab_id_map_.erase(handle_it->second); |
| 413 handle_map_.erase(handle); | 417 handle_map_.erase(handle); |
| 414 #endif // DEBUG | 418 #endif // DEBUG |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 456 frame_window_families_.erase(frame_window); | 460 frame_window_families_.erase(frame_window); |
| 457 send_on_removed = true; | 461 send_on_removed = true; |
| 458 } | 462 } |
| 459 } // End of lock | 463 } // End of lock |
| 460 | 464 |
| 461 // Safer to send notifications outside of our lock. | 465 // Safer to send notifications outside of our lock. |
| 462 if (send_on_removed) | 466 if (send_on_removed) |
| 463 windows_events_funnel().OnRemoved(frame_window); | 467 windows_events_funnel().OnRemoved(frame_window); |
| 464 } | 468 } |
| 465 | 469 |
| 470 // This is for using CleanupMapsForThread() into a runnable object without | |
| 471 // the need to AddRef/Release the ExecutorsManager which is a Singleton. | |
| 472 DISABLE_RUNNABLE_METHOD_REFCOUNT(ExecutorsManager); | |
| 473 | |
| 474 void ExecutorsManager::CleanupMapsForThread(DWORD thread_id) { | |
| 475 // We collect the tab handles to remove so that we can do it outside of lock. | |
| 476 // This is because 1) it's not trivial to do it while we loop through the map, | |
| 477 // since there are multiple maps to deal with and the DeleteHandle takes care | |
| 478 // of that for us, and 2) we can't call DeleteHandle from within a lock. | |
| 479 std::vector<HWND> tab_handles_to_remove; | |
| 480 { | |
| 481 AutoLock lock(lock_); | |
| 482 HandleMap::iterator handle_it = handle_map_.begin(); | |
| 483 for (; handle_it != handle_map_.end(); ++ handle_it) { | |
| 484 if (::GetWindowThreadProcessId(handle_it->first, NULL) == thread_id) | |
| 485 tab_handles_to_remove.push_back(handle_it->first); | |
| 486 } | |
| 487 } // AutoLock end | |
| 488 | |
| 489 std::vector<HWND>::iterator tab_handle_it = tab_handles_to_remove.begin(); | |
| 490 for (; tab_handle_it != tab_handles_to_remove.end(); ++tab_handle_it) { | |
| 491 DeleteTabHandle(*tab_handle_it); | |
| 492 } | |
| 493 } | |
| 494 | |
| 466 bool ExecutorsManager::IsTabIdValid(int tab_id) { | 495 bool ExecutorsManager::IsTabIdValid(int tab_id) { |
| 467 AutoLock lock(lock_); | 496 AutoLock lock(lock_); |
| 468 TabIdMap::const_iterator it = tab_id_map_.find(tab_id); | 497 TabIdMap::const_iterator it = tab_id_map_.find(tab_id); |
| 469 #ifdef DEBUG | 498 #ifdef DEBUG |
| 470 return it != tab_id_map_.end() && it->second != INVALID_HANDLE_VALUE; | 499 return it != tab_id_map_.end() && it->second != INVALID_HANDLE_VALUE; |
| 471 #else | 500 #else |
| 472 return it != tab_id_map_.end(); | 501 return it != tab_id_map_.end(); |
| 473 #endif | 502 #endif |
| 474 } | 503 } |
| 475 | 504 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 589 size_t num_handles = num_threads + kExtraHandles; | 618 size_t num_handles = num_threads + kExtraHandles; |
| 590 DWORD result = me->WaitForMultipleObjects(num_handles, handles, FALSE, | 619 DWORD result = me->WaitForMultipleObjects(num_handles, handles, FALSE, |
| 591 INFINITE); | 620 INFINITE); |
| 592 if (result == WAIT_OBJECT_0 + num_threads + | 621 if (result == WAIT_OBJECT_0 + num_threads + |
| 593 kUpdateHandleIndexOffset) { | 622 kUpdateHandleIndexOffset) { |
| 594 // We got a new thread added, | 623 // We got a new thread added, |
| 595 // simply let the loop turn to add it to our watch list. | 624 // simply let the loop turn to add it to our watch list. |
| 596 } else if (result >= WAIT_OBJECT_0 && | 625 } else if (result >= WAIT_OBJECT_0 && |
| 597 result < WAIT_OBJECT_0 + num_threads) { | 626 result < WAIT_OBJECT_0 + num_threads) { |
| 598 // One of our threads have died, cleanup time. | 627 // One of our threads have died, cleanup time. |
| 599 me->RemoveExecutor(thread_ids[result - WAIT_OBJECT_0]); | 628 DWORD thread_id = thread_ids[result - WAIT_OBJECT_0]; |
| 629 VLOG(1) << "Thread: " << thread_id << " is dying on us!"; | |
| 630 me->RemoveExecutor(thread_id); | |
| 631 // We must asynchronously post this change in case there are pending | |
|
Sigurður Ásgeirsson
2010/12/03 20:40:42
Interesting.
Doesn't this leave us with another r
| |
| 632 // asynchronous notifications (e.g., tabs.onRemoved) that would still | |
| 633 // need the handle to tab id mapping. | |
| 634 // NOTE: No need to worry about the lifespan of the executors manager | |
| 635 // referred by the me variable since it's a singleton released at exit. | |
| 636 ChromePostman* single_instance = ChromePostman::GetInstance(); | |
| 637 // This is not intialized in unittests yet. | |
| 638 if (single_instance) { | |
| 639 single_instance->QueueApiInvocationThreadTask( | |
| 640 NewRunnableMethod(me, &ExecutorsManager::CleanupMapsForThread, | |
| 641 thread_id)); | |
| 642 } | |
| 600 } else if (result == WAIT_OBJECT_0 + num_threads + | 643 } else if (result == WAIT_OBJECT_0 + num_threads + |
| 601 kTerminationHandleIndexOffset) { | 644 kTerminationHandleIndexOffset) { |
| 602 // we are being terminated, break the cycle. | 645 // we are being terminated, break the cycle. |
| 603 break; | 646 break; |
| 604 } else { | 647 } else { |
| 605 DCHECK(result == WAIT_FAILED); | 648 DCHECK(result == WAIT_FAILED); |
| 606 LOG(ERROR) << "ExecutorsManager::ThreadProc " << com::LogWe(); | 649 LOG(ERROR) << "ExecutorsManager::ThreadProc " << com::LogWe(); |
| 607 break; | 650 break; |
| 608 } | 651 } |
| 609 } | 652 } |
| 610 // Merci... Bonsoir... | 653 // Merci... Bonsoir... |
| 611 ::CoUninitialize(); | 654 ::CoUninitialize(); |
| 612 return 1; | 655 return 1; |
| 613 } | 656 } |
| OLD | NEW |