diff options
author | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-10 14:09:37 +0000 |
---|---|---|
committer | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-10 14:09:37 +0000 |
commit | bbfa9a15797ba107dcae0f7fff85a7f12ffd26b9 (patch) | |
tree | ee15898939e4989b96c6419217696f63d7a5585b /chrome_frame/chrome_frame_automation.cc | |
parent | e721ebe885b159f9b18047392be9a0f5834998fb (diff) | |
download | chromium_src-bbfa9a15797ba107dcae0f7fff85a7f12ffd26b9.zip chromium_src-bbfa9a15797ba107dcae0f7fff85a7f12ffd26b9.tar.gz chromium_src-bbfa9a15797ba107dcae0f7fff85a7f12ffd26b9.tar.bz2 |
Handle automation server crashes. When Chrome crashes, we now handle the case and support document refresh or reload.
When chrome crashes, we draw a poor man's sad tab (":-("), so that can clearly be improved.
Another thing is that if the chrome instance that crashed held several navigational entries, then that history is lost.
TEST=There are a couple of tests included, so run those (*TabCrash*) and also verify that when the chrome automation server is killed that we do the right thing. Also check info in bug report.
BUG=25839
Review URL: http://codereview.chromium.org/3061036
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55565 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/chrome_frame_automation.cc')
-rw-r--r-- | chrome_frame/chrome_frame_automation.cc | 444 |
1 files changed, 270 insertions, 174 deletions
diff --git a/chrome_frame/chrome_frame_automation.cc b/chrome_frame/chrome_frame_automation.cc index ea2c127..32c4749 100644 --- a/chrome_frame/chrome_frame_automation.cc +++ b/chrome_frame/chrome_frame_automation.cc @@ -126,12 +126,13 @@ class ChromeFrameAutomationProxyImpl::CFMsgDispatcher }; ChromeFrameAutomationProxyImpl::ChromeFrameAutomationProxyImpl( - int launch_timeout) - : AutomationProxy(launch_timeout) { + AutomationProxyCacheEntry* entry, int launch_timeout) + : AutomationProxy(launch_timeout), proxy_entry_(entry) { TRACE_EVENT_BEGIN("chromeframe.automationproxy", this, ""); sync_ = new CFMsgDispatcher(); message_filter_ = new TabProxyNotificationMessageFilter(tracker_.get()); + // Order of filters is not important. channel_->AddFilter(message_filter_.get()); channel_->AddFilter(sync_.get()); @@ -152,6 +153,15 @@ void ChromeFrameAutomationProxyImpl::CancelAsync(void* key) { sync_->Cancel(key); } +void ChromeFrameAutomationProxyImpl::OnChannelError() { + DLOG(ERROR) << "Automation server died"; + if (proxy_entry_) { + proxy_entry_->OnChannelError(); + } else { + NOTREACHED(); + } +} + scoped_refptr<TabProxy> ChromeFrameAutomationProxyImpl::CreateTabProxy( int handle) { DCHECK(tracker_->GetResource(handle) == NULL); @@ -188,83 +198,41 @@ struct LaunchTimeStats { #endif }; -ProxyFactory::ProxyCacheEntry::ProxyCacheEntry(const std::wstring& profile) - : proxy(NULL), profile_name(profile), ref_count(1), - launch_result(AutomationLaunchResult(-1)) { - thread.reset(new base::Thread(WideToASCII(profile_name).c_str())); - thread->Start(); +DISABLE_RUNNABLE_METHOD_REFCOUNT(AutomationProxyCacheEntry); + +AutomationProxyCacheEntry::AutomationProxyCacheEntry( + ChromeFrameLaunchParams* params, LaunchDelegate* delegate) + : profile_name(params->profile_name()), + launch_result_(AUTOMATION_LAUNCH_RESULT_INVALID), + snapshots_(NULL), uma_send_interval_(1) { + DCHECK(delegate); + thread_.reset(new base::Thread(WideToASCII(profile_name).c_str())); + thread_->Start(); + thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, + &AutomationProxyCacheEntry::CreateProxy, params, delegate)); } -DISABLE_RUNNABLE_METHOD_REFCOUNT(ProxyFactory); - -ProxyFactory::ProxyFactory() - : uma_send_interval_(0) { - uma_send_interval_ = GetConfigInt(kDefaultSendUMADataInterval, - kUmaSendIntervalValue); +AutomationProxyCacheEntry::~AutomationProxyCacheEntry() { + DLOG(INFO) << __FUNCTION__ << profile_name; } -ProxyFactory::~ProxyFactory() { - for (size_t i = 0; i < proxies_.container().size(); ++i) { - DWORD result = WaitForSingleObject(proxies_[i]->thread->thread_handle(), 0); - if (WAIT_OBJECT_0 != result) - // TODO(stoyan): Don't leak proxies on exit. - DLOG(ERROR) << "Proxies leaked on exit."; - } +void AutomationProxyCacheEntry::StartSendUmaInterval( + ChromeFrameHistogramSnapshots* snapshots, int send_interval) { + DCHECK(snapshots); + DCHECK(!snapshots_); + snapshots_ = snapshots; + uma_send_interval_ = send_interval; + thread_->message_loop()->PostDelayedTask(FROM_HERE, + NewRunnableMethod(this, &AutomationProxyCacheEntry::SendUMAData), + send_interval); } -void ProxyFactory::GetAutomationServer( - LaunchDelegate* delegate, const ChromeFrameLaunchParams& params, - void** automation_server_id) { - TRACE_EVENT_BEGIN("chromeframe.createproxy", this, ""); - - ProxyCacheEntry* entry = NULL; - // Find already existing launcher thread for given profile - AutoLock lock(lock_); - for (size_t i = 0; i < proxies_.container().size(); ++i) { - if (!lstrcmpiW(proxies_[i]->profile_name.c_str(), - params.profile_name.c_str())) { - entry = proxies_[i]; - DCHECK(entry->thread.get() != NULL); - break; - } - } - - if (entry == NULL) { - entry = new ProxyCacheEntry(params.profile_name); - proxies_.container().push_back(entry); - } else { - entry->ref_count++; - } - - DCHECK(delegate != NULL); - DCHECK(automation_server_id != NULL); - - *automation_server_id = entry; - // Note we always queue request to the launch thread, even if we already - // have established proxy object. A simple lock around entry->proxy = proxy - // would allow calling LaunchDelegate directly from here if - // entry->proxy != NULL. Drawback is that callback may be invoked either in - // main thread or in background thread, which may confuse the client. - entry->thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, - &ProxyFactory::CreateProxy, entry, params, delegate)); - - // IE uses the chrome frame provided UMA data uploading scheme. NPAPI - // continues to use Chrome to upload UMA data. - if (!CrashMetricsReporter::GetInstance()->active()) { - entry->thread->message_loop()->PostDelayedTask(FROM_HERE, - NewRunnableMethod(this, &ProxyFactory::SendUMAData, entry), - uma_send_interval_); - } -} - -void ProxyFactory::CreateProxy(ProxyFactory::ProxyCacheEntry* entry, - const ChromeFrameLaunchParams& params, - LaunchDelegate* delegate) { - DCHECK(entry->thread->thread_id() == PlatformThread::CurrentId()); - if (entry->proxy) { - delegate->LaunchComplete(entry->proxy, entry->launch_result); - return; - } +void AutomationProxyCacheEntry::CreateProxy(ChromeFrameLaunchParams* params, + LaunchDelegate* delegate) { + DCHECK(IsSameThread(PlatformThread::CurrentId())); + DCHECK(delegate); + DCHECK(params); + DCHECK(proxy_.get() == NULL); // We *must* create automationproxy in a thread that has message loop, // since SyncChannel::Context construction registers event to be watched @@ -273,8 +241,7 @@ void ProxyFactory::CreateProxy(ProxyFactory::ProxyCacheEntry* entry, // At same time we must destroy/stop the thread from another thread. ChromeFrameAutomationProxyImpl* proxy = - new ChromeFrameAutomationProxyImpl( - params.automation_server_launch_timeout); + new ChromeFrameAutomationProxyImpl(this, params->launch_timeout()); // Launch browser scoped_ptr<CommandLine> command_line( @@ -303,20 +270,21 @@ void ProxyFactory::CreateProxy(ProxyFactory::ProxyCacheEntry* entry, if (IsHeadlessMode()) command_line->AppendSwitch(switches::kFullMemoryCrashReport); - DLOG(INFO) << "Profile path: " << params.profile_path.value(); - command_line->AppendSwitchPath(switches::kUserDataDir, params.profile_path); + DLOG(INFO) << "Profile path: " << params->profile_path().value(); + command_line->AppendSwitchPath(switches::kUserDataDir, + params->profile_path()); std::wstring command_line_string(command_line->command_line_string()); // If there are any extra arguments, append them to the command line. - if (!params.extra_chrome_arguments.empty()) { - command_line_string += L' ' + params.extra_chrome_arguments; + if (!params->extra_arguments().empty()) { + command_line_string += L' ' + params->extra_arguments(); } automation_server_launch_start_time_ = base::TimeTicks::Now(); if (!base::LaunchApp(command_line_string, false, false, NULL)) { // We have no code for launch failure. - entry->launch_result = AutomationLaunchResult(-1); + launch_result_ = AUTOMATION_LAUNCH_RESULT_INVALID; } else { // Launch timeout may happen if the new instance tries to communicate // with an existing Chrome instance that is hung and displays msgbox @@ -332,13 +300,13 @@ void ProxyFactory::CreateProxy(ProxyFactory::ProxyCacheEntry* entry, LaunchTimeStats launch_stats; // Wait for the automation server launch result, then stash away the // version string it reported. - entry->launch_result = proxy->WaitForAppLaunch(); + launch_result_ = proxy->WaitForAppLaunch(); launch_stats.Dump(); base::TimeDelta delta = base::TimeTicks::Now() - automation_server_launch_start_time_; - if (entry->launch_result == AUTOMATION_SUCCESS) { + if (launch_result_ == AUTOMATION_SUCCESS) { THREAD_SAFE_UMA_HISTOGRAM_TIMES( "ChromeFrame.AutomationServerLaunchSuccessTime", delta); } else { @@ -347,7 +315,7 @@ void ProxyFactory::CreateProxy(ProxyFactory::ProxyCacheEntry* entry, } THREAD_SAFE_UMA_HISTOGRAM_CUSTOM_COUNTS("ChromeFrame.LaunchResult", - entry->launch_result, + launch_result_, AUTOMATION_SUCCESS, AUTOMATION_CREATE_TAB_FAILED, AUTOMATION_CREATE_TAB_FAILED + 1); @@ -356,101 +324,201 @@ void ProxyFactory::CreateProxy(ProxyFactory::ProxyCacheEntry* entry, TRACE_EVENT_END("chromeframe.createproxy", this, ""); // Finally set the proxy. - entry->proxy = proxy; - delegate->LaunchComplete(proxy, entry->launch_result); + proxy_.reset(proxy); + launch_delegates_.push_back(delegate); + + delegate->LaunchComplete(proxy_.get(), launch_result_); } -bool ProxyFactory::ReleaseAutomationServer(void* server_id) { - if (!server_id) { - NOTREACHED(); - return false; - } +void AutomationProxyCacheEntry::RemoveDelegate(LaunchDelegate* delegate, + base::WaitableEvent* done, + bool* was_last_delegate) { + DCHECK(IsSameThread(PlatformThread::CurrentId())); + DCHECK(delegate); + DCHECK(done); + DCHECK(was_last_delegate); - ProxyCacheEntry* entry = reinterpret_cast<ProxyCacheEntry*>(server_id); + *was_last_delegate = false; -#ifndef NDEBUG - lock_.Acquire(); - Vector::ContainerType::iterator it = std::find(proxies_.container().begin(), - proxies_.container().end(), - entry); - DCHECK(it != proxies_.container().end()); - DCHECK(entry->thread->thread_id() != PlatformThread::CurrentId()); - DCHECK_GT(entry->ref_count, 0); + LaunchDelegates::iterator it = std::find(launch_delegates_.begin(), + launch_delegates_.end(), delegate); + if (it == launch_delegates_.end()) { + NOTREACHED(); + } else { + if (launch_delegates_.size() == 1) { + *was_last_delegate = true; - lock_.Release(); -#endif + if (snapshots_) + SendUMAData(); - base::WaitableEvent done(true, false); - entry->thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, - &ProxyFactory::ReleaseProxy, entry, &done)); - done.Wait(); + // Take down the proxy since we no longer have any clients. + proxy_.reset(NULL); - // Stop the thread and destroy the entry if there is no more clients. - if (entry->ref_count == 0) { - DCHECK(entry->proxy == NULL); - entry->thread.reset(); - delete entry; + // Process pending notifications. + thread_->message_loop()->RunAllPending(); + } + // Be careful to remove from the list after running pending + // tasks. Otherwise the delegate being removed might miss out + // on pending notifications such as LaunchComplete. + launch_delegates_.erase(it); } - return true; + done->Signal(); } -void ProxyFactory::ReleaseProxy(ProxyCacheEntry* entry, - base::WaitableEvent* done) { - DCHECK(entry->thread->thread_id() == PlatformThread::CurrentId()); +void AutomationProxyCacheEntry::AddDelegate(LaunchDelegate* delegate) { + DCHECK(IsSameThread(PlatformThread::CurrentId())); + DCHECK(std::find(launch_delegates_.begin(), + launch_delegates_.end(), + delegate) == launch_delegates_.end()) + << "Same delegate being added twice"; + DCHECK(launch_result_ != AUTOMATION_LAUNCH_RESULT_INVALID); - lock_.Acquire(); - if (!--entry->ref_count) { - Vector::ContainerType::iterator it = std::find(proxies_.container().begin(), - proxies_.container().end(), - entry); - proxies_->erase(it); - } - lock_.Release(); + launch_delegates_.push_back(delegate); + delegate->LaunchComplete(proxy_.get(), launch_result_); +} - // Send pending UMA data if any. - if (!entry->ref_count) { - SendUMAData(entry); - delete entry->proxy; - entry->proxy = NULL; +void AutomationProxyCacheEntry::OnChannelError() { + DCHECK(IsSameThread(PlatformThread::CurrentId())); + launch_result_ = AUTOMATION_SERVER_CRASHED; + LaunchDelegates::const_iterator it = launch_delegates_.begin(); + for (; it != launch_delegates_.end(); ++it) { + (*it)->AutomationServerDied(); } - - done->Signal(); } -Singleton<ProxyFactory> g_proxy_factory; - -void ProxyFactory::SendUMAData(ProxyCacheEntry* proxy_entry) { +void AutomationProxyCacheEntry::SendUMAData() { + DCHECK(IsSameThread(PlatformThread::CurrentId())); + DCHECK(snapshots_); // IE uses the chrome frame provided UMA data uploading scheme. NPAPI // continues to use Chrome to upload UMA data. if (CrashMetricsReporter::GetInstance()->active()) { return; } - if (!proxy_entry) { + if (!proxy_.get()) { NOTREACHED() << __FUNCTION__ << " Invalid proxy entry"; - return; + } else { + ChromeFrameHistogramSnapshots::HistogramPickledList histograms = + snapshots_->GatherAllHistograms(); + + if (!histograms.empty()) { + proxy_->Send(new AutomationMsg_RecordHistograms(0, histograms)); + } + + MessageLoop::current()->PostDelayedTask(FROM_HERE, + NewRunnableMethod(this, &AutomationProxyCacheEntry::SendUMAData), + uma_send_interval_); } +} - DCHECK(proxy_entry->thread->thread_id() == PlatformThread::CurrentId()); - if (proxy_entry->proxy) { - ChromeFrameHistogramSnapshots::HistogramPickledList histograms = - chrome_frame_histograms_.GatherAllHistograms(); +DISABLE_RUNNABLE_METHOD_REFCOUNT(ProxyFactory); - if (!histograms.empty()) { - proxy_entry->proxy->Send( - new AutomationMsg_RecordHistograms(0, histograms)); +ProxyFactory::ProxyFactory() + : uma_send_interval_(0) { + uma_send_interval_ = GetConfigInt(kDefaultSendUMADataInterval, + kUmaSendIntervalValue); +} + +ProxyFactory::~ProxyFactory() { + for (size_t i = 0; i < proxies_.container().size(); ++i) { + DWORD result = proxies_[i]->WaitForThread(0); + if (WAIT_OBJECT_0 != result) + // TODO(stoyan): Don't leak proxies on exit. + DLOG(ERROR) << "Proxies leaked on exit."; + } +} + +void ProxyFactory::GetAutomationServer( + LaunchDelegate* delegate, ChromeFrameLaunchParams* params, + void** automation_server_id) { + TRACE_EVENT_BEGIN("chromeframe.createproxy", this, ""); + + scoped_refptr<AutomationProxyCacheEntry> entry; + // Find already existing launcher thread for given profile + AutoLock lock(lock_); + for (size_t i = 0; i < proxies_.container().size(); ++i) { + if (proxies_[i]->IsSameProfile(params->profile_name())) { + entry = proxies_[i]; + break; } - } else { - DLOG(INFO) << __FUNCTION__ << " No proxy available to service the request"; - return; } - MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod( - this, &ProxyFactory::SendUMAData, proxy_entry), uma_send_interval_); + if (entry == NULL) { + DLOG(INFO) << __FUNCTION__ << " creating new proxy entry"; + entry = new AutomationProxyCacheEntry(params, delegate); + proxies_.container().push_back(entry); + + // IE uses the chrome frame provided UMA data uploading scheme. NPAPI + // continues to use Chrome to upload UMA data. + if (!CrashMetricsReporter::GetInstance()->active()) { + entry->StartSendUmaInterval(&chrome_frame_histograms_, + uma_send_interval_); + } + } else if (delegate) { + // Notify the new delegate of the launch status from the worker thread + // and add it to the list of delegates. + entry->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(entry.get(), + &AutomationProxyCacheEntry::AddDelegate, delegate)); + } + + DCHECK(automation_server_id != NULL); + DCHECK(!entry->IsSameThread(PlatformThread::CurrentId())); + + *automation_server_id = entry; +} + +bool ProxyFactory::ReleaseAutomationServer(void* server_id, + LaunchDelegate* delegate) { + if (!server_id) { + NOTREACHED(); + return false; + } + + AutomationProxyCacheEntry* entry = + reinterpret_cast<AutomationProxyCacheEntry*>(server_id); + +#ifndef NDEBUG + lock_.Acquire(); + Vector::ContainerType::iterator it = std::find(proxies_.container().begin(), + proxies_.container().end(), + entry); + DCHECK(it != proxies_.container().end()); + DCHECK(!entry->IsSameThread(PlatformThread::CurrentId())); + + lock_.Release(); +#endif + + // AddRef the entry object as we might need to take it out of the proxy + // stack and then uninitialize the entry. + entry->AddRef(); + + bool last_delegate = false; + if (delegate) { + base::WaitableEvent done(true, false); + entry->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(entry, + &AutomationProxyCacheEntry::RemoveDelegate, delegate, &done, + &last_delegate)); + done.Wait(); + } + + if (last_delegate) { + lock_.Acquire(); + Vector::ContainerType::iterator it = std::find(proxies_.container().begin(), + proxies_.container().end(), + entry); + proxies_.container().erase(it); + lock_.Release(); + } + + entry->Release(); + + return true; } +Singleton<ProxyFactory> g_proxy_factory; + template <> struct RunnableMethodTraits<ChromeFrameAutomationClient> { static void RetainCallee(ChromeFrameAutomationClient* obj) {} static void ReleaseCallee(ChromeFrameAutomationClient* obj) {} @@ -482,10 +550,18 @@ ChromeFrameAutomationClient::~ChromeFrameAutomationClient() { bool ChromeFrameAutomationClient::Initialize( ChromeFrameDelegate* chrome_frame_delegate, - const ChromeFrameLaunchParams& chrome_launch_params) { + ChromeFrameLaunchParams* chrome_launch_params) { DCHECK(!IsWindow()); chrome_frame_delegate_ = chrome_frame_delegate; +#ifndef NDEBUG + if (chrome_launch_params_ && chrome_launch_params_ != chrome_launch_params) { + DCHECK_EQ(chrome_launch_params_->url(), chrome_launch_params->url()); + DCHECK_EQ(chrome_launch_params_->referrer(), + chrome_launch_params->referrer()); + } +#endif + chrome_launch_params_ = chrome_launch_params; ui_thread_id_ = PlatformThread::CurrentId(); @@ -495,11 +571,12 @@ bool ChromeFrameAutomationClient::Initialize( // Don't use INFINITE (which is -1) or even MAXINT since we will convert // from milliseconds to microseconds when stored in a base::TimeDelta, // thus * 1000. An hour should be enough. - chrome_launch_params_.automation_server_launch_timeout = 60 * 60 * 1000; + chrome_launch_params_->set_launch_timeout(60 * 60 * 1000); } else { - DCHECK_LT(chrome_launch_params_.automation_server_launch_timeout, + DCHECK_LT(chrome_launch_params_->launch_timeout(), MAXINT / 2000); - chrome_launch_params_.automation_server_launch_timeout *= 2; + chrome_launch_params_->set_launch_timeout( + chrome_launch_params_->launch_timeout() * 2); } #endif // NDEBUG @@ -515,18 +592,17 @@ bool ChromeFrameAutomationClient::Initialize( } // Keep object in memory, while the window is alive. - // Corresponsing Release is in OnFinalMessage(); + // Corresponding Release is in OnFinalMessage(); AddRef(); // Mark our state as initializing. We'll reach initialized once // InitializeComplete is called successfully. init_state_ = INITIALIZING; - if (chrome_launch_params_.url.is_valid()) + if (chrome_launch_params_->url().is_valid()) navigate_after_initialization_ = false; - proxy_factory_->GetAutomationServer( - static_cast<ProxyFactory::LaunchDelegate*>(this), + proxy_factory_->GetAutomationServer(static_cast<LaunchDelegate*>(this), chrome_launch_params_, &automation_server_id_); return true; @@ -571,12 +647,15 @@ void ChromeFrameAutomationClient::Uninitialize() { if (::IsWindow(m_hWnd)) DestroyWindow(); + DCHECK(navigate_after_initialization_ == false); + handle_top_level_requests_ = false; + ui_thread_id_ = 0; chrome_frame_delegate_ = NULL; init_state_ = UNINITIALIZED; } -bool ChromeFrameAutomationClient::InitiateNavigation( - const std::string& url, const std::string& referrer, bool is_privileged) { +bool ChromeFrameAutomationClient::InitiateNavigation(const std::string& url, + const std::string& referrer, bool is_privileged) { if (url.empty()) return false; @@ -589,19 +668,26 @@ bool ChromeFrameAutomationClient::InitiateNavigation( return false; } - if (parsed_url != chrome_launch_params_.url) { + if (!chrome_launch_params_ || parsed_url != chrome_launch_params_->url()) { // Important: Since we will be using the referrer_ variable from a // different thread, we need to force a new std::string buffer instance for // the referrer_ GURL variable. Otherwise we can run into strangeness when // the GURL is accessed and it could result in a bad URL that can cause the // referrer to be dropped or something worse. - chrome_launch_params_.referrer = GURL(referrer.c_str()); - chrome_launch_params_.url = parsed_url; + GURL referrer_gurl(referrer.c_str()); + if (!chrome_launch_params_) { + FilePath profile_path; + chrome_launch_params_ = new ChromeFrameLaunchParams(parsed_url, + referrer_gurl, profile_path, L"", L"", false, false); + } else { + chrome_launch_params_->set_referrer(referrer_gurl); + chrome_launch_params_->set_url(parsed_url); + } navigate_after_initialization_ = false; if (is_initialized()) { - BeginNavigate(chrome_launch_params_.url, chrome_launch_params_.referrer); + BeginNavigate(); } else { navigate_after_initialization_ = true; } @@ -644,13 +730,12 @@ bool ChromeFrameAutomationClient::SetProxySettings( return true; } -void ChromeFrameAutomationClient::BeginNavigate(const GURL& url, - const GURL& referrer) { +void ChromeFrameAutomationClient::BeginNavigate() { // Could be NULL if we failed to launch Chrome in LaunchAutomationServer() if (!automation_server_ || !tab_.get()) { DLOG(WARNING) << "BeginNavigate - can't navigate."; ReportNavigationError(AUTOMATION_MSG_NAVIGATION_ERROR, - chrome_launch_params_.url.spec()); + chrome_launch_params_->url().spec()); return; } @@ -662,8 +747,9 @@ void ChromeFrameAutomationClient::BeginNavigate(const GURL& url, } IPC::SyncMessage* msg = - new AutomationMsg_NavigateInExternalTab(0, tab_->handle(), url, - referrer, NULL); + new AutomationMsg_NavigateInExternalTab(0, tab_->handle(), + chrome_launch_params_->url(), chrome_launch_params_->referrer(), + NULL); automation_server_->SendAsAsync(msg, new BeginNavigateContext(this), this); RECT client_rect = {0}; @@ -677,7 +763,7 @@ void ChromeFrameAutomationClient::BeginNavigateCompleted( AutomationMsg_NavigationResponseValues result) { if (result == AUTOMATION_MSG_NAVIGATION_ERROR) ReportNavigationError(AUTOMATION_MSG_NAVIGATION_ERROR, - chrome_launch_params_.url.spec()); + chrome_launch_params_->url().spec()); } void ChromeFrameAutomationClient::FindInPage(const std::wstring& search_string, @@ -797,7 +883,7 @@ void ChromeFrameAutomationClient::CreateExternalTab() { DCHECK(IsWindow()); DCHECK(automation_server_ != NULL); - if (chrome_launch_params_.url.is_valid()) { + if (chrome_launch_params_->url().is_valid()) { navigate_after_initialization_ = false; } @@ -805,12 +891,12 @@ void ChromeFrameAutomationClient::CreateExternalTab() { m_hWnd, gfx::Rect(), WS_CHILD, - chrome_launch_params_.incognito_mode, + chrome_launch_params_->incognito(), !use_chrome_network_, handle_top_level_requests_, - chrome_launch_params_.url, - chrome_launch_params_.referrer, - !chrome_launch_params_.is_widget_mode // Infobars disabled in widget mode. + chrome_launch_params_->url(), + chrome_launch_params_->referrer(), + !chrome_launch_params_->widget_mode() // Infobars disabled in widget mode. }; THREAD_SAFE_UMA_HISTOGRAM_CUSTOM_COUNTS( @@ -904,6 +990,16 @@ void ChromeFrameAutomationClient::LaunchComplete( } } +void ChromeFrameAutomationClient::AutomationServerDied() { + // Make sure we notify our delegate. + PostTask(FROM_HERE, NewRunnableMethod(this, + &ChromeFrameAutomationClient::InitializeComplete, + AUTOMATION_SERVER_CRASHED)); + // Then uninitialize. + PostTask(FROM_HERE, NewRunnableMethod(this, + &ChromeFrameAutomationClient::Uninitialize)); +} + void ChromeFrameAutomationClient::InitializeComplete( AutomationLaunchResult result) { DCHECK_EQ(PlatformThread::CurrentId(), ui_thread_id_); @@ -922,8 +1018,8 @@ void ChromeFrameAutomationClient::InitializeComplete( // If host specified destination URL - navigate. Apparently we do not use // accelerator table. if (navigate_after_initialization_) { - BeginNavigate(chrome_launch_params_.url, - chrome_launch_params_.referrer); + navigate_after_initialization_ = false; + BeginNavigate(); } } @@ -1126,7 +1222,7 @@ void ChromeFrameAutomationClient::ReleaseAutomationServer() { automation_server_->CancelAsync(this); } - proxy_factory_->ReleaseAutomationServer(server_id); + proxy_factory_->ReleaseAutomationServer(server_id, this); automation_server_ = NULL; // automation_server_ must not have been set to non NULL. |