summaryrefslogtreecommitdiffstats
path: root/chrome_frame/chrome_frame_automation.cc
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-10 14:09:37 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-10 14:09:37 +0000
commitbbfa9a15797ba107dcae0f7fff85a7f12ffd26b9 (patch)
treeee15898939e4989b96c6419217696f63d7a5585b /chrome_frame/chrome_frame_automation.cc
parente721ebe885b159f9b18047392be9a0f5834998fb (diff)
downloadchromium_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.cc444
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.