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 |