| Index: chrome_frame/chrome_frame_automation.cc
|
| ===================================================================
|
| --- chrome_frame/chrome_frame_automation.cc (revision 55540)
|
| +++ chrome_frame/chrome_frame_automation.cc (working copy)
|
| @@ -126,12 +126,13 @@
|
| };
|
|
|
| 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 @@
|
| 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 @@
|
| #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);
|
|
|
| -DISABLE_RUNNABLE_METHOD_REFCOUNT(ProxyFactory);
|
| -
|
| -ProxyFactory::ProxyFactory()
|
| - : uma_send_interval_(0) {
|
| - uma_send_interval_ = GetConfigInt(kDefaultSendUMADataInterval,
|
| - kUmaSendIntervalValue);
|
| +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));
|
| }
|
|
|
| -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.";
|
| - }
|
| +AutomationProxyCacheEntry::~AutomationProxyCacheEntry() {
|
| + DLOG(INFO) << __FUNCTION__ << profile_name;
|
| }
|
|
|
| -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 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::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 @@
|
|
|
| // 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 @@
|
| 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 @@
|
| 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 @@
|
| }
|
|
|
| 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 @@
|
| 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 @@
|
|
|
| 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 @@
|
| // 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 @@
|
| }
|
|
|
| // 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 @@
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| }
|
|
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| 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::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 @@
|
| // 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 @@
|
| 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.
|
|
|