| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome_frame/chrome_frame_automation.h" | 5 #include "chrome_frame/chrome_frame_automation.h" |
| 6 | 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" |
| 7 #include "base/callback.h" | 9 #include "base/callback.h" |
| 8 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 9 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 10 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
| 11 #include "base/file_util.h" | 13 #include "base/file_util.h" |
| 12 #include "base/file_version_info.h" | 14 #include "base/file_version_info.h" |
| 13 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
| 14 #include "base/logging.h" | 16 #include "base/logging.h" |
| 15 #include "base/path_service.h" | 17 #include "base/path_service.h" |
| 16 #include "base/process_util.h" | 18 #include "base/process_util.h" |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 launch_milliseconds << " ms."; | 191 launch_milliseconds << " ms."; |
| 190 } | 192 } |
| 191 } | 193 } |
| 192 | 194 |
| 193 base::Time launch_time_begin_; | 195 base::Time launch_time_begin_; |
| 194 #else | 196 #else |
| 195 void Dump() {} | 197 void Dump() {} |
| 196 #endif | 198 #endif |
| 197 }; | 199 }; |
| 198 | 200 |
| 199 DISABLE_RUNNABLE_METHOD_REFCOUNT(AutomationProxyCacheEntry); | |
| 200 | |
| 201 AutomationProxyCacheEntry::AutomationProxyCacheEntry( | 201 AutomationProxyCacheEntry::AutomationProxyCacheEntry( |
| 202 ChromeFrameLaunchParams* params, LaunchDelegate* delegate) | 202 ChromeFrameLaunchParams* params, LaunchDelegate* delegate) |
| 203 : profile_name(params->profile_name()), | 203 : profile_name(params->profile_name()), |
| 204 launch_result_(AUTOMATION_LAUNCH_RESULT_INVALID) { | 204 launch_result_(AUTOMATION_LAUNCH_RESULT_INVALID) { |
| 205 DCHECK(delegate); | 205 DCHECK(delegate); |
| 206 thread_.reset(new base::Thread(WideToASCII(profile_name).c_str())); | 206 thread_.reset(new base::Thread(WideToASCII(profile_name).c_str())); |
| 207 thread_->Start(); | 207 thread_->Start(); |
| 208 // Use scoped_refptr so that the params will get released when the task | 208 // Use scoped_refptr so that the params will get released when the task |
| 209 // has been run. | 209 // has been run. |
| 210 scoped_refptr<ChromeFrameLaunchParams> ref_params(params); | 210 scoped_refptr<ChromeFrameLaunchParams> ref_params(params); |
| 211 thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, | 211 thread_->message_loop()->PostTask( |
| 212 &AutomationProxyCacheEntry::CreateProxy, ref_params, delegate)); | 212 FROM_HERE, base::Bind(&AutomationProxyCacheEntry::CreateProxy, |
| 213 base::Unretained(this), ref_params, delegate)); |
| 213 } | 214 } |
| 214 | 215 |
| 215 AutomationProxyCacheEntry::~AutomationProxyCacheEntry() { | 216 AutomationProxyCacheEntry::~AutomationProxyCacheEntry() { |
| 216 DVLOG(1) << __FUNCTION__ << profile_name; | 217 DVLOG(1) << __FUNCTION__ << profile_name; |
| 217 // Attempt to fix chrome_frame_tests crash seen at times on the IE6/IE7 | 218 // Attempt to fix chrome_frame_tests crash seen at times on the IE6/IE7 |
| 218 // builders. It appears that there are cases when we can enter here when the | 219 // builders. It appears that there are cases when we can enter here when the |
| 219 // AtExitManager is tearing down the global ProxyCache which causes a crash | 220 // AtExitManager is tearing down the global ProxyCache which causes a crash |
| 220 // while tearing down the AutomationProxy object due to a NULL MessageLoop | 221 // while tearing down the AutomationProxy object due to a NULL MessageLoop |
| 221 // The AutomationProxy class uses the SyncChannel which assumes the existence | 222 // The AutomationProxy class uses the SyncChannel which assumes the existence |
| 222 // of a MessageLoop instance. | 223 // of a MessageLoop instance. |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 | 403 |
| 403 void AutomationProxyCacheEntry::OnChannelError() { | 404 void AutomationProxyCacheEntry::OnChannelError() { |
| 404 DCHECK(IsSameThread(base::PlatformThread::CurrentId())); | 405 DCHECK(IsSameThread(base::PlatformThread::CurrentId())); |
| 405 launch_result_ = AUTOMATION_SERVER_CRASHED; | 406 launch_result_ = AUTOMATION_SERVER_CRASHED; |
| 406 LaunchDelegates::const_iterator it = launch_delegates_.begin(); | 407 LaunchDelegates::const_iterator it = launch_delegates_.begin(); |
| 407 for (; it != launch_delegates_.end(); ++it) { | 408 for (; it != launch_delegates_.end(); ++it) { |
| 408 (*it)->AutomationServerDied(); | 409 (*it)->AutomationServerDied(); |
| 409 } | 410 } |
| 410 } | 411 } |
| 411 | 412 |
| 412 DISABLE_RUNNABLE_METHOD_REFCOUNT(ProxyFactory); | |
| 413 | |
| 414 ProxyFactory::ProxyFactory() { | 413 ProxyFactory::ProxyFactory() { |
| 415 } | 414 } |
| 416 | 415 |
| 417 ProxyFactory::~ProxyFactory() { | 416 ProxyFactory::~ProxyFactory() { |
| 418 for (size_t i = 0; i < proxies_.container().size(); ++i) { | 417 for (size_t i = 0; i < proxies_.container().size(); ++i) { |
| 419 DWORD result = proxies_[i]->WaitForThread(0); | 418 DWORD result = proxies_[i]->WaitForThread(0); |
| 420 if (WAIT_OBJECT_0 != result) | 419 if (WAIT_OBJECT_0 != result) |
| 421 // TODO(stoyan): Don't leak proxies on exit. | 420 // TODO(stoyan): Don't leak proxies on exit. |
| 422 DLOG(ERROR) << "Proxies leaked on exit."; | 421 DLOG(ERROR) << "Proxies leaked on exit."; |
| 423 } | 422 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 438 } | 437 } |
| 439 } | 438 } |
| 440 | 439 |
| 441 if (entry == NULL) { | 440 if (entry == NULL) { |
| 442 DVLOG(1) << __FUNCTION__ << " creating new proxy entry"; | 441 DVLOG(1) << __FUNCTION__ << " creating new proxy entry"; |
| 443 entry = new AutomationProxyCacheEntry(params, delegate); | 442 entry = new AutomationProxyCacheEntry(params, delegate); |
| 444 proxies_.container().push_back(entry); | 443 proxies_.container().push_back(entry); |
| 445 } else if (delegate) { | 444 } else if (delegate) { |
| 446 // Notify the new delegate of the launch status from the worker thread | 445 // Notify the new delegate of the launch status from the worker thread |
| 447 // and add it to the list of delegates. | 446 // and add it to the list of delegates. |
| 448 entry->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(entry.get(), | 447 entry->message_loop()->PostTask( |
| 449 &AutomationProxyCacheEntry::AddDelegate, delegate)); | 448 FROM_HERE, base::Bind(&AutomationProxyCacheEntry::AddDelegate, |
| 449 base::Unretained(entry.get()), delegate)); |
| 450 } | 450 } |
| 451 | 451 |
| 452 DCHECK(automation_server_id != NULL); | 452 DCHECK(automation_server_id != NULL); |
| 453 DCHECK(!entry->IsSameThread(base::PlatformThread::CurrentId())); | 453 DCHECK(!entry->IsSameThread(base::PlatformThread::CurrentId())); |
| 454 | 454 |
| 455 *automation_server_id = entry; | 455 *automation_server_id = entry; |
| 456 } | 456 } |
| 457 | 457 |
| 458 bool ProxyFactory::ReleaseAutomationServer(void* server_id, | 458 bool ProxyFactory::ReleaseAutomationServer(void* server_id, |
| 459 LaunchDelegate* delegate) { | 459 LaunchDelegate* delegate) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 476 lock_.Release(); | 476 lock_.Release(); |
| 477 #endif | 477 #endif |
| 478 | 478 |
| 479 // AddRef the entry object as we might need to take it out of the proxy | 479 // AddRef the entry object as we might need to take it out of the proxy |
| 480 // stack and then uninitialize the entry. | 480 // stack and then uninitialize the entry. |
| 481 entry->AddRef(); | 481 entry->AddRef(); |
| 482 | 482 |
| 483 bool last_delegate = false; | 483 bool last_delegate = false; |
| 484 if (delegate) { | 484 if (delegate) { |
| 485 base::WaitableEvent done(true, false); | 485 base::WaitableEvent done(true, false); |
| 486 entry->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(entry, | 486 entry->message_loop()->PostTask( |
| 487 &AutomationProxyCacheEntry::RemoveDelegate, delegate, &done, | 487 FROM_HERE, |
| 488 &last_delegate)); | 488 base::Bind(&AutomationProxyCacheEntry::RemoveDelegate, |
| 489 base::Unretained(entry), delegate, &done, &last_delegate)); |
| 489 done.Wait(); | 490 done.Wait(); |
| 490 } | 491 } |
| 491 | 492 |
| 492 if (last_delegate) { | 493 if (last_delegate) { |
| 493 lock_.Acquire(); | 494 lock_.Acquire(); |
| 494 Vector::ContainerType::iterator it = std::find(proxies_.container().begin(), | 495 Vector::ContainerType::iterator it = std::find(proxies_.container().begin(), |
| 495 proxies_.container().end(), | 496 proxies_.container().end(), |
| 496 entry); | 497 entry); |
| 497 proxies_.container().erase(it); | 498 proxies_.container().erase(it); |
| 498 lock_.Release(); | 499 lock_.Release(); |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 875 new AutomationMsg_ConnectExternalTab(external_tab_cookie_, true, | 876 new AutomationMsg_ConnectExternalTab(external_tab_cookie_, true, |
| 876 m_hWnd, NULL, NULL, NULL, 0); | 877 m_hWnd, NULL, NULL, NULL, 0); |
| 877 automation_server_->SendAsAsync(message, | 878 automation_server_->SendAsAsync(message, |
| 878 new CreateExternalTabContext(this), | 879 new CreateExternalTabContext(this), |
| 879 this); | 880 this); |
| 880 DVLOG(1) << __FUNCTION__ << ": sending CreateExternalTabComplete"; | 881 DVLOG(1) << __FUNCTION__ << ": sending CreateExternalTabComplete"; |
| 881 } | 882 } |
| 882 } | 883 } |
| 883 } else { | 884 } else { |
| 884 // Launch failed. Note, we cannot delete proxy here. | 885 // Launch failed. Note, we cannot delete proxy here. |
| 885 PostTask(FROM_HERE, NewRunnableMethod(this, | 886 PostTask(FROM_HERE, |
| 886 &ChromeFrameAutomationClient::InitializeComplete, result)); | 887 base::Bind(&ChromeFrameAutomationClient::InitializeComplete, this, |
| 888 result)); |
| 887 } | 889 } |
| 888 } | 890 } |
| 889 | 891 |
| 890 void ChromeFrameAutomationClient::AutomationServerDied() { | 892 void ChromeFrameAutomationClient::AutomationServerDied() { |
| 891 // Make sure we notify our delegate. | 893 // Make sure we notify our delegate. |
| 892 PostTask(FROM_HERE, NewRunnableMethod(this, | 894 PostTask( |
| 893 &ChromeFrameAutomationClient::InitializeComplete, | 895 FROM_HERE, |
| 894 AUTOMATION_SERVER_CRASHED)); | 896 base::Bind(&ChromeFrameAutomationClient::InitializeComplete, this, |
| 897 AUTOMATION_SERVER_CRASHED)); |
| 895 // Then uninitialize. | 898 // Then uninitialize. |
| 896 PostTask(FROM_HERE, NewRunnableMethod(this, | 899 PostTask( |
| 897 &ChromeFrameAutomationClient::Uninitialize)); | 900 FROM_HERE, base::Bind(&ChromeFrameAutomationClient::Uninitialize, this)); |
| 898 } | 901 } |
| 899 | 902 |
| 900 void ChromeFrameAutomationClient::InitializeComplete( | 903 void ChromeFrameAutomationClient::InitializeComplete( |
| 901 AutomationLaunchResult result) { | 904 AutomationLaunchResult result) { |
| 902 DCHECK_EQ(base::PlatformThread::CurrentId(), ui_thread_id_); | 905 DCHECK_EQ(base::PlatformThread::CurrentId(), ui_thread_id_); |
| 903 if (result != AUTOMATION_SUCCESS) { | 906 if (result != AUTOMATION_SUCCESS) { |
| 904 DLOG(WARNING) << "InitializeComplete: failure " << result; | 907 DLOG(WARNING) << "InitializeComplete: failure " << result; |
| 905 ReleaseAutomationServer(); | 908 ReleaseAutomationServer(); |
| 906 } else { | 909 } else { |
| 907 init_state_ = INITIALIZED; | 910 init_state_ = INITIALIZED; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 case AutomationMsg_SetCookieAsync::ID: | 990 case AutomationMsg_SetCookieAsync::ID: |
| 988 if (ui_thread || (url_fetcher_flags_ & | 991 if (ui_thread || (url_fetcher_flags_ & |
| 989 PluginUrlRequestManager::COOKIE_REQUEST_THREADSAFE)) { | 992 PluginUrlRequestManager::COOKIE_REQUEST_THREADSAFE)) { |
| 990 AutomationMsg_SetCookieAsync::Dispatch(&msg, url_fetcher_, this, | 993 AutomationMsg_SetCookieAsync::Dispatch(&msg, url_fetcher_, this, |
| 991 &PluginUrlRequestManager::SetCookiesInHost); | 994 &PluginUrlRequestManager::SetCookiesInHost); |
| 992 return true; | 995 return true; |
| 993 } | 996 } |
| 994 break; | 997 break; |
| 995 } | 998 } |
| 996 | 999 |
| 997 PostTask(FROM_HERE, NewRunnableMethod(this, | 1000 PostTask(FROM_HERE, |
| 998 &ChromeFrameAutomationClient::ProcessUrlRequestMessage, tab, msg, true)); | 1001 base::Bind(&ChromeFrameAutomationClient::ProcessUrlRequestMessage, |
| 1002 this, tab, msg, true)); |
| 999 return true; | 1003 return true; |
| 1000 } | 1004 } |
| 1001 | 1005 |
| 1002 // These are invoked in channel's background thread. | 1006 // These are invoked in channel's background thread. |
| 1003 // Cannot call any method of the activex here since it is a STA kind of being. | 1007 // Cannot call any method of the activex here since it is a STA kind of being. |
| 1004 // By default we marshal the IPC message to the main/GUI thread and from there | 1008 // By default we marshal the IPC message to the main/GUI thread and from there |
| 1005 // we safely invoke chrome_frame_delegate_->OnMessageReceived(msg). | 1009 // we safely invoke chrome_frame_delegate_->OnMessageReceived(msg). |
| 1006 bool ChromeFrameAutomationClient::OnMessageReceived(TabProxy* tab, | 1010 bool ChromeFrameAutomationClient::OnMessageReceived(TabProxy* tab, |
| 1007 const IPC::Message& msg) { | 1011 const IPC::Message& msg) { |
| 1008 DCHECK(tab == tab_.get()); | 1012 DCHECK(tab == tab_.get()); |
| 1009 // Quickly process network related messages. | 1013 // Quickly process network related messages. |
| 1010 if (url_fetcher_ && ProcessUrlRequestMessage(tab, msg, false)) | 1014 if (url_fetcher_ && ProcessUrlRequestMessage(tab, msg, false)) |
| 1011 return true; | 1015 return true; |
| 1012 | 1016 |
| 1013 // Early check to avoid needless marshaling | 1017 // Early check to avoid needless marshaling |
| 1014 if (chrome_frame_delegate_ == NULL) | 1018 if (chrome_frame_delegate_ == NULL) |
| 1015 return false; | 1019 return false; |
| 1016 | 1020 |
| 1017 PostTask(FROM_HERE, NewRunnableMethod(this, | 1021 PostTask(FROM_HERE, |
| 1018 &ChromeFrameAutomationClient::OnMessageReceivedUIThread, msg)); | 1022 base::Bind(&ChromeFrameAutomationClient::OnMessageReceivedUIThread, |
| 1023 this, msg)); |
| 1019 return true; | 1024 return true; |
| 1020 } | 1025 } |
| 1021 | 1026 |
| 1022 void ChromeFrameAutomationClient::OnChannelError(TabProxy* tab) { | 1027 void ChromeFrameAutomationClient::OnChannelError(TabProxy* tab) { |
| 1023 DCHECK(tab == tab_.get()); | 1028 DCHECK(tab == tab_.get()); |
| 1024 // Early check to avoid needless marshaling | 1029 // Early check to avoid needless marshaling |
| 1025 if (chrome_frame_delegate_ == NULL) | 1030 if (chrome_frame_delegate_ == NULL) |
| 1026 return; | 1031 return; |
| 1027 | 1032 |
| 1028 PostTask(FROM_HERE, NewRunnableMethod(this, | 1033 PostTask( |
| 1029 &ChromeFrameAutomationClient::OnChannelErrorUIThread)); | 1034 FROM_HERE, |
| 1035 base::Bind(&ChromeFrameAutomationClient::OnChannelErrorUIThread, this)); |
| 1030 } | 1036 } |
| 1031 | 1037 |
| 1032 void ChromeFrameAutomationClient::OnMessageReceivedUIThread( | 1038 void ChromeFrameAutomationClient::OnMessageReceivedUIThread( |
| 1033 const IPC::Message& msg) { | 1039 const IPC::Message& msg) { |
| 1034 DCHECK_EQ(base::PlatformThread::CurrentId(), ui_thread_id_); | 1040 DCHECK_EQ(base::PlatformThread::CurrentId(), ui_thread_id_); |
| 1035 // Forward to the delegate. | 1041 // Forward to the delegate. |
| 1036 if (chrome_frame_delegate_) | 1042 if (chrome_frame_delegate_) |
| 1037 chrome_frame_delegate_->OnMessageReceived(msg); | 1043 chrome_frame_delegate_->OnMessageReceived(msg); |
| 1038 } | 1044 } |
| 1039 | 1045 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1051 | 1057 |
| 1052 void ChromeFrameAutomationClient::ReportNavigationError( | 1058 void ChromeFrameAutomationClient::ReportNavigationError( |
| 1053 AutomationMsg_NavigationResponseValues error_code, | 1059 AutomationMsg_NavigationResponseValues error_code, |
| 1054 const std::string& url) { | 1060 const std::string& url) { |
| 1055 if (!chrome_frame_delegate_) | 1061 if (!chrome_frame_delegate_) |
| 1056 return; | 1062 return; |
| 1057 | 1063 |
| 1058 if (ui_thread_id_ == base::PlatformThread::CurrentId()) { | 1064 if (ui_thread_id_ == base::PlatformThread::CurrentId()) { |
| 1059 chrome_frame_delegate_->OnLoadFailed(error_code, url); | 1065 chrome_frame_delegate_->OnLoadFailed(error_code, url); |
| 1060 } else { | 1066 } else { |
| 1061 PostTask(FROM_HERE, NewRunnableMethod(this, | 1067 PostTask(FROM_HERE, |
| 1062 &ChromeFrameAutomationClient::ReportNavigationError, | 1068 base::Bind(&ChromeFrameAutomationClient::ReportNavigationError, |
| 1063 error_code, url)); | 1069 this, error_code, url)); |
| 1064 } | 1070 } |
| 1065 } | 1071 } |
| 1066 | 1072 |
| 1067 void ChromeFrameAutomationClient::Resize(int width, int height, | 1073 void ChromeFrameAutomationClient::Resize(int width, int height, |
| 1068 int flags) { | 1074 int flags) { |
| 1069 if (tab_.get() && ::IsWindow(chrome_window())) { | 1075 if (tab_.get() && ::IsWindow(chrome_window())) { |
| 1070 SetWindowPos(HWND_TOP, 0, 0, width, height, flags); | 1076 SetWindowPos(HWND_TOP, 0, 0, width, height, flags); |
| 1071 tab_->Reposition(chrome_window(), HWND_TOP, 0, 0, width, height, | 1077 tab_->Reposition(chrome_window(), HWND_TOP, 0, 0, width, height, |
| 1072 flags, m_hWnd); | 1078 flags, m_hWnd); |
| 1073 } | 1079 } |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 const net::URLRequestStatus& status) { | 1272 const net::URLRequestStatus& status) { |
| 1267 automation_server_->Send(new AutomationMsg_RequestEnd( | 1273 automation_server_->Send(new AutomationMsg_RequestEnd( |
| 1268 tab_->handle(), request_id, status)); | 1274 tab_->handle(), request_id, status)); |
| 1269 } | 1275 } |
| 1270 | 1276 |
| 1271 void ChromeFrameAutomationClient::OnCookiesRetrieved(bool success, | 1277 void ChromeFrameAutomationClient::OnCookiesRetrieved(bool success, |
| 1272 const GURL& url, const std::string& cookie_string, int cookie_id) { | 1278 const GURL& url, const std::string& cookie_string, int cookie_id) { |
| 1273 automation_server_->Send(new AutomationMsg_GetCookiesHostResponse( | 1279 automation_server_->Send(new AutomationMsg_GetCookiesHostResponse( |
| 1274 tab_->handle(), success, url, cookie_string, cookie_id)); | 1280 tab_->handle(), success, url, cookie_string, cookie_id)); |
| 1275 } | 1281 } |
| OLD | NEW |