| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome_frame/chrome_frame_automation.h" | 5 #include "chrome_frame/chrome_frame_automation.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/trace_event.h" | 10 #include "base/trace_event.h" |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 InvokeCallback<GetEnabledExtensionsContext>(msg, context); | 119 InvokeCallback<GetEnabledExtensionsContext>(msg, context); |
| 120 break; | 120 break; |
| 121 default: | 121 default: |
| 122 NOTREACHED(); | 122 NOTREACHED(); |
| 123 } | 123 } |
| 124 return true; | 124 return true; |
| 125 } | 125 } |
| 126 }; | 126 }; |
| 127 | 127 |
| 128 ChromeFrameAutomationProxyImpl::ChromeFrameAutomationProxyImpl( | 128 ChromeFrameAutomationProxyImpl::ChromeFrameAutomationProxyImpl( |
| 129 int launch_timeout) | 129 AutomationProxyCacheEntry* entry, int launch_timeout) |
| 130 : AutomationProxy(launch_timeout) { | 130 : AutomationProxy(launch_timeout), proxy_entry_(entry) { |
| 131 TRACE_EVENT_BEGIN("chromeframe.automationproxy", this, ""); | 131 TRACE_EVENT_BEGIN("chromeframe.automationproxy", this, ""); |
| 132 | 132 |
| 133 sync_ = new CFMsgDispatcher(); | 133 sync_ = new CFMsgDispatcher(); |
| 134 message_filter_ = new TabProxyNotificationMessageFilter(tracker_.get()); | 134 message_filter_ = new TabProxyNotificationMessageFilter(tracker_.get()); |
| 135 |
| 135 // Order of filters is not important. | 136 // Order of filters is not important. |
| 136 channel_->AddFilter(message_filter_.get()); | 137 channel_->AddFilter(message_filter_.get()); |
| 137 channel_->AddFilter(sync_.get()); | 138 channel_->AddFilter(sync_.get()); |
| 138 } | 139 } |
| 139 | 140 |
| 140 ChromeFrameAutomationProxyImpl::~ChromeFrameAutomationProxyImpl() { | 141 ChromeFrameAutomationProxyImpl::~ChromeFrameAutomationProxyImpl() { |
| 141 TRACE_EVENT_END("chromeframe.automationproxy", this, ""); | 142 TRACE_EVENT_END("chromeframe.automationproxy", this, ""); |
| 142 } | 143 } |
| 143 | 144 |
| 144 void ChromeFrameAutomationProxyImpl::SendAsAsync( | 145 void ChromeFrameAutomationProxyImpl::SendAsAsync( |
| 145 IPC::SyncMessage* msg, | 146 IPC::SyncMessage* msg, |
| 146 SyncMessageReplyDispatcher::SyncMessageCallContext* context, void* key) { | 147 SyncMessageReplyDispatcher::SyncMessageCallContext* context, void* key) { |
| 147 sync_->Push(msg, context, key); | 148 sync_->Push(msg, context, key); |
| 148 channel_->ChannelProxy::Send(msg); | 149 channel_->ChannelProxy::Send(msg); |
| 149 } | 150 } |
| 150 | 151 |
| 151 void ChromeFrameAutomationProxyImpl::CancelAsync(void* key) { | 152 void ChromeFrameAutomationProxyImpl::CancelAsync(void* key) { |
| 152 sync_->Cancel(key); | 153 sync_->Cancel(key); |
| 153 } | 154 } |
| 154 | 155 |
| 156 void ChromeFrameAutomationProxyImpl::OnChannelError() { |
| 157 DLOG(ERROR) << "Automation server died"; |
| 158 if (proxy_entry_) { |
| 159 proxy_entry_->OnChannelError(); |
| 160 } else { |
| 161 NOTREACHED(); |
| 162 } |
| 163 } |
| 164 |
| 155 scoped_refptr<TabProxy> ChromeFrameAutomationProxyImpl::CreateTabProxy( | 165 scoped_refptr<TabProxy> ChromeFrameAutomationProxyImpl::CreateTabProxy( |
| 156 int handle) { | 166 int handle) { |
| 157 DCHECK(tracker_->GetResource(handle) == NULL); | 167 DCHECK(tracker_->GetResource(handle) == NULL); |
| 158 TabProxy* tab_proxy = new TabProxy(this, tracker_.get(), handle); | 168 TabProxy* tab_proxy = new TabProxy(this, tracker_.get(), handle); |
| 159 if (tab_proxy != NULL) | 169 if (tab_proxy != NULL) |
| 160 message_filter_->AddTabProxy(handle); | 170 message_filter_->AddTabProxy(handle); |
| 161 return tab_proxy; | 171 return tab_proxy; |
| 162 } | 172 } |
| 163 | 173 |
| 164 void ChromeFrameAutomationProxyImpl::ReleaseTabProxy(AutomationHandle handle) { | 174 void ChromeFrameAutomationProxyImpl::ReleaseTabProxy(AutomationHandle handle) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 181 launch_milliseconds << " ms."; | 191 launch_milliseconds << " ms."; |
| 182 } | 192 } |
| 183 } | 193 } |
| 184 | 194 |
| 185 base::Time launch_time_begin_; | 195 base::Time launch_time_begin_; |
| 186 #else | 196 #else |
| 187 void Dump() {} | 197 void Dump() {} |
| 188 #endif | 198 #endif |
| 189 }; | 199 }; |
| 190 | 200 |
| 191 ProxyFactory::ProxyCacheEntry::ProxyCacheEntry(const std::wstring& profile) | 201 DISABLE_RUNNABLE_METHOD_REFCOUNT(AutomationProxyCacheEntry); |
| 192 : proxy(NULL), profile_name(profile), ref_count(1), | 202 |
| 193 launch_result(AutomationLaunchResult(-1)) { | 203 AutomationProxyCacheEntry::AutomationProxyCacheEntry( |
| 194 thread.reset(new base::Thread(WideToASCII(profile_name).c_str())); | 204 ChromeFrameLaunchParams* params, LaunchDelegate* delegate) |
| 195 thread->Start(); | 205 : profile_name(params->profile_name()), |
| 206 launch_result_(AUTOMATION_LAUNCH_RESULT_INVALID), |
| 207 snapshots_(NULL), uma_send_interval_(1) { |
| 208 DCHECK(delegate); |
| 209 thread_.reset(new base::Thread(WideToASCII(profile_name).c_str())); |
| 210 thread_->Start(); |
| 211 thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, |
| 212 &AutomationProxyCacheEntry::CreateProxy, params, delegate)); |
| 196 } | 213 } |
| 197 | 214 |
| 198 DISABLE_RUNNABLE_METHOD_REFCOUNT(ProxyFactory); | 215 AutomationProxyCacheEntry::~AutomationProxyCacheEntry() { |
| 199 | 216 DLOG(INFO) << __FUNCTION__ << profile_name; |
| 200 ProxyFactory::ProxyFactory() | |
| 201 : uma_send_interval_(0) { | |
| 202 uma_send_interval_ = GetConfigInt(kDefaultSendUMADataInterval, | |
| 203 kUmaSendIntervalValue); | |
| 204 } | 217 } |
| 205 | 218 |
| 206 ProxyFactory::~ProxyFactory() { | 219 void AutomationProxyCacheEntry::StartSendUmaInterval( |
| 207 for (size_t i = 0; i < proxies_.container().size(); ++i) { | 220 ChromeFrameHistogramSnapshots* snapshots, int send_interval) { |
| 208 DWORD result = WaitForSingleObject(proxies_[i]->thread->thread_handle(), 0); | 221 DCHECK(snapshots); |
| 209 if (WAIT_OBJECT_0 != result) | 222 DCHECK(!snapshots_); |
| 210 // TODO(stoyan): Don't leak proxies on exit. | 223 snapshots_ = snapshots; |
| 211 DLOG(ERROR) << "Proxies leaked on exit."; | 224 uma_send_interval_ = send_interval; |
| 212 } | 225 thread_->message_loop()->PostDelayedTask(FROM_HERE, |
| 226 NewRunnableMethod(this, &AutomationProxyCacheEntry::SendUMAData), |
| 227 send_interval); |
| 213 } | 228 } |
| 214 | 229 |
| 215 void ProxyFactory::GetAutomationServer( | 230 void AutomationProxyCacheEntry::CreateProxy(ChromeFrameLaunchParams* params, |
| 216 LaunchDelegate* delegate, const ChromeFrameLaunchParams& params, | 231 LaunchDelegate* delegate) { |
| 217 void** automation_server_id) { | 232 DCHECK(IsSameThread(PlatformThread::CurrentId())); |
| 218 TRACE_EVENT_BEGIN("chromeframe.createproxy", this, ""); | 233 DCHECK(delegate); |
| 219 | 234 DCHECK(params); |
| 220 ProxyCacheEntry* entry = NULL; | 235 DCHECK(proxy_.get() == NULL); |
| 221 // Find already existing launcher thread for given profile | |
| 222 AutoLock lock(lock_); | |
| 223 for (size_t i = 0; i < proxies_.container().size(); ++i) { | |
| 224 if (!lstrcmpiW(proxies_[i]->profile_name.c_str(), | |
| 225 params.profile_name.c_str())) { | |
| 226 entry = proxies_[i]; | |
| 227 DCHECK(entry->thread.get() != NULL); | |
| 228 break; | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 if (entry == NULL) { | |
| 233 entry = new ProxyCacheEntry(params.profile_name); | |
| 234 proxies_.container().push_back(entry); | |
| 235 } else { | |
| 236 entry->ref_count++; | |
| 237 } | |
| 238 | |
| 239 DCHECK(delegate != NULL); | |
| 240 DCHECK(automation_server_id != NULL); | |
| 241 | |
| 242 *automation_server_id = entry; | |
| 243 // Note we always queue request to the launch thread, even if we already | |
| 244 // have established proxy object. A simple lock around entry->proxy = proxy | |
| 245 // would allow calling LaunchDelegate directly from here if | |
| 246 // entry->proxy != NULL. Drawback is that callback may be invoked either in | |
| 247 // main thread or in background thread, which may confuse the client. | |
| 248 entry->thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, | |
| 249 &ProxyFactory::CreateProxy, entry, params, delegate)); | |
| 250 | |
| 251 // IE uses the chrome frame provided UMA data uploading scheme. NPAPI | |
| 252 // continues to use Chrome to upload UMA data. | |
| 253 if (!CrashMetricsReporter::GetInstance()->active()) { | |
| 254 entry->thread->message_loop()->PostDelayedTask(FROM_HERE, | |
| 255 NewRunnableMethod(this, &ProxyFactory::SendUMAData, entry), | |
| 256 uma_send_interval_); | |
| 257 } | |
| 258 } | |
| 259 | |
| 260 void ProxyFactory::CreateProxy(ProxyFactory::ProxyCacheEntry* entry, | |
| 261 const ChromeFrameLaunchParams& params, | |
| 262 LaunchDelegate* delegate) { | |
| 263 DCHECK(entry->thread->thread_id() == PlatformThread::CurrentId()); | |
| 264 if (entry->proxy) { | |
| 265 delegate->LaunchComplete(entry->proxy, entry->launch_result); | |
| 266 return; | |
| 267 } | |
| 268 | 236 |
| 269 // We *must* create automationproxy in a thread that has message loop, | 237 // We *must* create automationproxy in a thread that has message loop, |
| 270 // since SyncChannel::Context construction registers event to be watched | 238 // since SyncChannel::Context construction registers event to be watched |
| 271 // through ObjectWatcher which subscribes for the current thread message loop | 239 // through ObjectWatcher which subscribes for the current thread message loop |
| 272 // destruction notification. | 240 // destruction notification. |
| 273 | 241 |
| 274 // At same time we must destroy/stop the thread from another thread. | 242 // At same time we must destroy/stop the thread from another thread. |
| 275 ChromeFrameAutomationProxyImpl* proxy = | 243 ChromeFrameAutomationProxyImpl* proxy = |
| 276 new ChromeFrameAutomationProxyImpl( | 244 new ChromeFrameAutomationProxyImpl(this, params->launch_timeout()); |
| 277 params.automation_server_launch_timeout); | |
| 278 | 245 |
| 279 // Launch browser | 246 // Launch browser |
| 280 scoped_ptr<CommandLine> command_line( | 247 scoped_ptr<CommandLine> command_line( |
| 281 chrome_launcher::CreateLaunchCommandLine()); | 248 chrome_launcher::CreateLaunchCommandLine()); |
| 282 command_line->AppendSwitchASCII(switches::kAutomationClientChannelID, | 249 command_line->AppendSwitchASCII(switches::kAutomationClientChannelID, |
| 283 proxy->channel_id()); | 250 proxy->channel_id()); |
| 284 | 251 |
| 285 // Run Chrome in Chrome Frame mode. In practice, this modifies the paths | 252 // Run Chrome in Chrome Frame mode. In practice, this modifies the paths |
| 286 // and registry keys that Chrome looks in via the BrowserDistribution | 253 // and registry keys that Chrome looks in via the BrowserDistribution |
| 287 // mechanism. | 254 // mechanism. |
| 288 command_line->AppendSwitch(switches::kChromeFrame); | 255 command_line->AppendSwitch(switches::kChromeFrame); |
| 289 | 256 |
| 290 // Chrome Frame never wants Chrome to start up with a First Run UI. | 257 // Chrome Frame never wants Chrome to start up with a First Run UI. |
| 291 command_line->AppendSwitch(switches::kNoFirstRun); | 258 command_line->AppendSwitch(switches::kNoFirstRun); |
| 292 | 259 |
| 293 command_line->AppendSwitch(switches::kDisablePopupBlocking); | 260 command_line->AppendSwitch(switches::kDisablePopupBlocking); |
| 294 | 261 |
| 295 // Disable the "Whoa! Chrome has crashed." dialog, because that isn't very | 262 // Disable the "Whoa! Chrome has crashed." dialog, because that isn't very |
| 296 // useful for Chrome Frame users. | 263 // useful for Chrome Frame users. |
| 297 #ifndef NDEBUG | 264 #ifndef NDEBUG |
| 298 command_line->AppendSwitch(switches::kNoErrorDialogs); | 265 command_line->AppendSwitch(switches::kNoErrorDialogs); |
| 299 #endif | 266 #endif |
| 300 | 267 |
| 301 // In headless mode runs like reliability test runs we want full crash dumps | 268 // In headless mode runs like reliability test runs we want full crash dumps |
| 302 // from chrome. | 269 // from chrome. |
| 303 if (IsHeadlessMode()) | 270 if (IsHeadlessMode()) |
| 304 command_line->AppendSwitch(switches::kFullMemoryCrashReport); | 271 command_line->AppendSwitch(switches::kFullMemoryCrashReport); |
| 305 | 272 |
| 306 DLOG(INFO) << "Profile path: " << params.profile_path.value(); | 273 DLOG(INFO) << "Profile path: " << params->profile_path().value(); |
| 307 command_line->AppendSwitchPath(switches::kUserDataDir, params.profile_path); | 274 command_line->AppendSwitchPath(switches::kUserDataDir, |
| 275 params->profile_path()); |
| 308 | 276 |
| 309 std::wstring command_line_string(command_line->command_line_string()); | 277 std::wstring command_line_string(command_line->command_line_string()); |
| 310 // If there are any extra arguments, append them to the command line. | 278 // If there are any extra arguments, append them to the command line. |
| 311 if (!params.extra_chrome_arguments.empty()) { | 279 if (!params->extra_arguments().empty()) { |
| 312 command_line_string += L' ' + params.extra_chrome_arguments; | 280 command_line_string += L' ' + params->extra_arguments(); |
| 313 } | 281 } |
| 314 | 282 |
| 315 automation_server_launch_start_time_ = base::TimeTicks::Now(); | 283 automation_server_launch_start_time_ = base::TimeTicks::Now(); |
| 316 | 284 |
| 317 if (!base::LaunchApp(command_line_string, false, false, NULL)) { | 285 if (!base::LaunchApp(command_line_string, false, false, NULL)) { |
| 318 // We have no code for launch failure. | 286 // We have no code for launch failure. |
| 319 entry->launch_result = AutomationLaunchResult(-1); | 287 launch_result_ = AUTOMATION_LAUNCH_RESULT_INVALID; |
| 320 } else { | 288 } else { |
| 321 // Launch timeout may happen if the new instance tries to communicate | 289 // Launch timeout may happen if the new instance tries to communicate |
| 322 // with an existing Chrome instance that is hung and displays msgbox | 290 // with an existing Chrome instance that is hung and displays msgbox |
| 323 // asking to kill the previous one. This could be easily observed if the | 291 // asking to kill the previous one. This could be easily observed if the |
| 324 // already running Chrome instance is running as high-integrity process | 292 // already running Chrome instance is running as high-integrity process |
| 325 // (started with "Run as Administrator" or launched by another high | 293 // (started with "Run as Administrator" or launched by another high |
| 326 // integrity process) hence our medium-integrity process | 294 // integrity process) hence our medium-integrity process |
| 327 // cannot SendMessage to it with request to activate itself. | 295 // cannot SendMessage to it with request to activate itself. |
| 328 | 296 |
| 329 // TODO(stoyan) AutomationProxy eats Hello message, hence installing | 297 // TODO(stoyan) AutomationProxy eats Hello message, hence installing |
| 330 // message filter is pointless, we can leverage ObjectWatcher and use | 298 // message filter is pointless, we can leverage ObjectWatcher and use |
| 331 // system thread pool to notify us when proxy->AppLaunch event is signaled. | 299 // system thread pool to notify us when proxy->AppLaunch event is signaled. |
| 332 LaunchTimeStats launch_stats; | 300 LaunchTimeStats launch_stats; |
| 333 // Wait for the automation server launch result, then stash away the | 301 // Wait for the automation server launch result, then stash away the |
| 334 // version string it reported. | 302 // version string it reported. |
| 335 entry->launch_result = proxy->WaitForAppLaunch(); | 303 launch_result_ = proxy->WaitForAppLaunch(); |
| 336 launch_stats.Dump(); | 304 launch_stats.Dump(); |
| 337 | 305 |
| 338 base::TimeDelta delta = | 306 base::TimeDelta delta = |
| 339 base::TimeTicks::Now() - automation_server_launch_start_time_; | 307 base::TimeTicks::Now() - automation_server_launch_start_time_; |
| 340 | 308 |
| 341 if (entry->launch_result == AUTOMATION_SUCCESS) { | 309 if (launch_result_ == AUTOMATION_SUCCESS) { |
| 342 THREAD_SAFE_UMA_HISTOGRAM_TIMES( | 310 THREAD_SAFE_UMA_HISTOGRAM_TIMES( |
| 343 "ChromeFrame.AutomationServerLaunchSuccessTime", delta); | 311 "ChromeFrame.AutomationServerLaunchSuccessTime", delta); |
| 344 } else { | 312 } else { |
| 345 THREAD_SAFE_UMA_HISTOGRAM_TIMES( | 313 THREAD_SAFE_UMA_HISTOGRAM_TIMES( |
| 346 "ChromeFrame.AutomationServerLaunchFailedTime", delta); | 314 "ChromeFrame.AutomationServerLaunchFailedTime", delta); |
| 347 } | 315 } |
| 348 | 316 |
| 349 THREAD_SAFE_UMA_HISTOGRAM_CUSTOM_COUNTS("ChromeFrame.LaunchResult", | 317 THREAD_SAFE_UMA_HISTOGRAM_CUSTOM_COUNTS("ChromeFrame.LaunchResult", |
| 350 entry->launch_result, | 318 launch_result_, |
| 351 AUTOMATION_SUCCESS, | 319 AUTOMATION_SUCCESS, |
| 352 AUTOMATION_CREATE_TAB_FAILED, | 320 AUTOMATION_CREATE_TAB_FAILED, |
| 353 AUTOMATION_CREATE_TAB_FAILED + 1); | 321 AUTOMATION_CREATE_TAB_FAILED + 1); |
| 354 } | 322 } |
| 355 | 323 |
| 356 TRACE_EVENT_END("chromeframe.createproxy", this, ""); | 324 TRACE_EVENT_END("chromeframe.createproxy", this, ""); |
| 357 | 325 |
| 358 // Finally set the proxy. | 326 // Finally set the proxy. |
| 359 entry->proxy = proxy; | 327 proxy_.reset(proxy); |
| 360 delegate->LaunchComplete(proxy, entry->launch_result); | 328 launch_delegates_.push_back(delegate); |
| 361 } | 329 |
| 362 | 330 delegate->LaunchComplete(proxy_.get(), launch_result_); |
| 363 bool ProxyFactory::ReleaseAutomationServer(void* server_id) { | 331 } |
| 332 |
| 333 void AutomationProxyCacheEntry::RemoveDelegate(LaunchDelegate* delegate, |
| 334 base::WaitableEvent* done, |
| 335 bool* was_last_delegate) { |
| 336 DCHECK(IsSameThread(PlatformThread::CurrentId())); |
| 337 DCHECK(delegate); |
| 338 DCHECK(done); |
| 339 DCHECK(was_last_delegate); |
| 340 |
| 341 *was_last_delegate = false; |
| 342 |
| 343 LaunchDelegates::iterator it = std::find(launch_delegates_.begin(), |
| 344 launch_delegates_.end(), delegate); |
| 345 if (it == launch_delegates_.end()) { |
| 346 NOTREACHED(); |
| 347 } else { |
| 348 if (launch_delegates_.size() == 1) { |
| 349 *was_last_delegate = true; |
| 350 |
| 351 if (snapshots_) |
| 352 SendUMAData(); |
| 353 |
| 354 // Take down the proxy since we no longer have any clients. |
| 355 proxy_.reset(NULL); |
| 356 |
| 357 // Process pending notifications. |
| 358 thread_->message_loop()->RunAllPending(); |
| 359 } |
| 360 // Be careful to remove from the list after running pending |
| 361 // tasks. Otherwise the delegate being removed might miss out |
| 362 // on pending notifications such as LaunchComplete. |
| 363 launch_delegates_.erase(it); |
| 364 } |
| 365 |
| 366 done->Signal(); |
| 367 } |
| 368 |
| 369 void AutomationProxyCacheEntry::AddDelegate(LaunchDelegate* delegate) { |
| 370 DCHECK(IsSameThread(PlatformThread::CurrentId())); |
| 371 DCHECK(std::find(launch_delegates_.begin(), |
| 372 launch_delegates_.end(), |
| 373 delegate) == launch_delegates_.end()) |
| 374 << "Same delegate being added twice"; |
| 375 DCHECK(launch_result_ != AUTOMATION_LAUNCH_RESULT_INVALID); |
| 376 |
| 377 launch_delegates_.push_back(delegate); |
| 378 delegate->LaunchComplete(proxy_.get(), launch_result_); |
| 379 } |
| 380 |
| 381 void AutomationProxyCacheEntry::OnChannelError() { |
| 382 DCHECK(IsSameThread(PlatformThread::CurrentId())); |
| 383 launch_result_ = AUTOMATION_SERVER_CRASHED; |
| 384 LaunchDelegates::const_iterator it = launch_delegates_.begin(); |
| 385 for (; it != launch_delegates_.end(); ++it) { |
| 386 (*it)->AutomationServerDied(); |
| 387 } |
| 388 } |
| 389 |
| 390 void AutomationProxyCacheEntry::SendUMAData() { |
| 391 DCHECK(IsSameThread(PlatformThread::CurrentId())); |
| 392 DCHECK(snapshots_); |
| 393 // IE uses the chrome frame provided UMA data uploading scheme. NPAPI |
| 394 // continues to use Chrome to upload UMA data. |
| 395 if (CrashMetricsReporter::GetInstance()->active()) { |
| 396 return; |
| 397 } |
| 398 |
| 399 if (!proxy_.get()) { |
| 400 NOTREACHED() << __FUNCTION__ << " Invalid proxy entry"; |
| 401 } else { |
| 402 ChromeFrameHistogramSnapshots::HistogramPickledList histograms = |
| 403 snapshots_->GatherAllHistograms(); |
| 404 |
| 405 if (!histograms.empty()) { |
| 406 proxy_->Send(new AutomationMsg_RecordHistograms(0, histograms)); |
| 407 } |
| 408 |
| 409 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 410 NewRunnableMethod(this, &AutomationProxyCacheEntry::SendUMAData), |
| 411 uma_send_interval_); |
| 412 } |
| 413 } |
| 414 |
| 415 |
| 416 DISABLE_RUNNABLE_METHOD_REFCOUNT(ProxyFactory); |
| 417 |
| 418 ProxyFactory::ProxyFactory() |
| 419 : uma_send_interval_(0) { |
| 420 uma_send_interval_ = GetConfigInt(kDefaultSendUMADataInterval, |
| 421 kUmaSendIntervalValue); |
| 422 } |
| 423 |
| 424 ProxyFactory::~ProxyFactory() { |
| 425 for (size_t i = 0; i < proxies_.container().size(); ++i) { |
| 426 DWORD result = proxies_[i]->WaitForThread(0); |
| 427 if (WAIT_OBJECT_0 != result) |
| 428 // TODO(stoyan): Don't leak proxies on exit. |
| 429 DLOG(ERROR) << "Proxies leaked on exit."; |
| 430 } |
| 431 } |
| 432 |
| 433 void ProxyFactory::GetAutomationServer( |
| 434 LaunchDelegate* delegate, ChromeFrameLaunchParams* params, |
| 435 void** automation_server_id) { |
| 436 TRACE_EVENT_BEGIN("chromeframe.createproxy", this, ""); |
| 437 |
| 438 scoped_refptr<AutomationProxyCacheEntry> entry; |
| 439 // Find already existing launcher thread for given profile |
| 440 AutoLock lock(lock_); |
| 441 for (size_t i = 0; i < proxies_.container().size(); ++i) { |
| 442 if (proxies_[i]->IsSameProfile(params->profile_name())) { |
| 443 entry = proxies_[i]; |
| 444 break; |
| 445 } |
| 446 } |
| 447 |
| 448 if (entry == NULL) { |
| 449 DLOG(INFO) << __FUNCTION__ << " creating new proxy entry"; |
| 450 entry = new AutomationProxyCacheEntry(params, delegate); |
| 451 proxies_.container().push_back(entry); |
| 452 |
| 453 // IE uses the chrome frame provided UMA data uploading scheme. NPAPI |
| 454 // continues to use Chrome to upload UMA data. |
| 455 if (!CrashMetricsReporter::GetInstance()->active()) { |
| 456 entry->StartSendUmaInterval(&chrome_frame_histograms_, |
| 457 uma_send_interval_); |
| 458 } |
| 459 } else if (delegate) { |
| 460 // Notify the new delegate of the launch status from the worker thread |
| 461 // and add it to the list of delegates. |
| 462 entry->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(entry.get(), |
| 463 &AutomationProxyCacheEntry::AddDelegate, delegate)); |
| 464 } |
| 465 |
| 466 DCHECK(automation_server_id != NULL); |
| 467 DCHECK(!entry->IsSameThread(PlatformThread::CurrentId())); |
| 468 |
| 469 *automation_server_id = entry; |
| 470 } |
| 471 |
| 472 bool ProxyFactory::ReleaseAutomationServer(void* server_id, |
| 473 LaunchDelegate* delegate) { |
| 364 if (!server_id) { | 474 if (!server_id) { |
| 365 NOTREACHED(); | 475 NOTREACHED(); |
| 366 return false; | 476 return false; |
| 367 } | 477 } |
| 368 | 478 |
| 369 ProxyCacheEntry* entry = reinterpret_cast<ProxyCacheEntry*>(server_id); | 479 AutomationProxyCacheEntry* entry = |
| 480 reinterpret_cast<AutomationProxyCacheEntry*>(server_id); |
| 370 | 481 |
| 371 #ifndef NDEBUG | 482 #ifndef NDEBUG |
| 372 lock_.Acquire(); | 483 lock_.Acquire(); |
| 373 Vector::ContainerType::iterator it = std::find(proxies_.container().begin(), | 484 Vector::ContainerType::iterator it = std::find(proxies_.container().begin(), |
| 374 proxies_.container().end(), | 485 proxies_.container().end(), |
| 375 entry); | 486 entry); |
| 376 DCHECK(it != proxies_.container().end()); | 487 DCHECK(it != proxies_.container().end()); |
| 377 DCHECK(entry->thread->thread_id() != PlatformThread::CurrentId()); | 488 DCHECK(!entry->IsSameThread(PlatformThread::CurrentId())); |
| 378 DCHECK_GT(entry->ref_count, 0); | |
| 379 | 489 |
| 380 lock_.Release(); | 490 lock_.Release(); |
| 381 #endif | 491 #endif |
| 382 | 492 |
| 383 base::WaitableEvent done(true, false); | 493 // AddRef the entry object as we might need to take it out of the proxy |
| 384 entry->thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, | 494 // stack and then uninitialize the entry. |
| 385 &ProxyFactory::ReleaseProxy, entry, &done)); | 495 entry->AddRef(); |
| 386 done.Wait(); | 496 |
| 387 | 497 bool last_delegate = false; |
| 388 // Stop the thread and destroy the entry if there is no more clients. | 498 if (delegate) { |
| 389 if (entry->ref_count == 0) { | 499 base::WaitableEvent done(true, false); |
| 390 DCHECK(entry->proxy == NULL); | 500 entry->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(entry, |
| 391 entry->thread.reset(); | 501 &AutomationProxyCacheEntry::RemoveDelegate, delegate, &done, |
| 392 delete entry; | 502 &last_delegate)); |
| 393 } | 503 done.Wait(); |
| 394 | 504 } |
| 395 return true; | 505 |
| 396 } | 506 if (last_delegate) { |
| 397 | 507 lock_.Acquire(); |
| 398 void ProxyFactory::ReleaseProxy(ProxyCacheEntry* entry, | |
| 399 base::WaitableEvent* done) { | |
| 400 DCHECK(entry->thread->thread_id() == PlatformThread::CurrentId()); | |
| 401 | |
| 402 lock_.Acquire(); | |
| 403 if (!--entry->ref_count) { | |
| 404 Vector::ContainerType::iterator it = std::find(proxies_.container().begin(), | 508 Vector::ContainerType::iterator it = std::find(proxies_.container().begin(), |
| 405 proxies_.container().end(), | 509 proxies_.container().end(), |
| 406 entry); | 510 entry); |
| 407 proxies_->erase(it); | 511 proxies_.container().erase(it); |
| 408 } | 512 lock_.Release(); |
| 409 lock_.Release(); | 513 } |
| 410 | 514 |
| 411 // Send pending UMA data if any. | 515 entry->Release(); |
| 412 if (!entry->ref_count) { | 516 |
| 413 SendUMAData(entry); | 517 return true; |
| 414 delete entry->proxy; | |
| 415 entry->proxy = NULL; | |
| 416 } | |
| 417 | |
| 418 done->Signal(); | |
| 419 } | 518 } |
| 420 | 519 |
| 421 Singleton<ProxyFactory> g_proxy_factory; | 520 Singleton<ProxyFactory> g_proxy_factory; |
| 422 | 521 |
| 423 void ProxyFactory::SendUMAData(ProxyCacheEntry* proxy_entry) { | |
| 424 // IE uses the chrome frame provided UMA data uploading scheme. NPAPI | |
| 425 // continues to use Chrome to upload UMA data. | |
| 426 if (CrashMetricsReporter::GetInstance()->active()) { | |
| 427 return; | |
| 428 } | |
| 429 | |
| 430 if (!proxy_entry) { | |
| 431 NOTREACHED() << __FUNCTION__ << " Invalid proxy entry"; | |
| 432 return; | |
| 433 } | |
| 434 | |
| 435 DCHECK(proxy_entry->thread->thread_id() == PlatformThread::CurrentId()); | |
| 436 | |
| 437 if (proxy_entry->proxy) { | |
| 438 ChromeFrameHistogramSnapshots::HistogramPickledList histograms = | |
| 439 chrome_frame_histograms_.GatherAllHistograms(); | |
| 440 | |
| 441 if (!histograms.empty()) { | |
| 442 proxy_entry->proxy->Send( | |
| 443 new AutomationMsg_RecordHistograms(0, histograms)); | |
| 444 } | |
| 445 } else { | |
| 446 DLOG(INFO) << __FUNCTION__ << " No proxy available to service the request"; | |
| 447 return; | |
| 448 } | |
| 449 | |
| 450 MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod( | |
| 451 this, &ProxyFactory::SendUMAData, proxy_entry), uma_send_interval_); | |
| 452 } | |
| 453 | |
| 454 template <> struct RunnableMethodTraits<ChromeFrameAutomationClient> { | 522 template <> struct RunnableMethodTraits<ChromeFrameAutomationClient> { |
| 455 static void RetainCallee(ChromeFrameAutomationClient* obj) {} | 523 static void RetainCallee(ChromeFrameAutomationClient* obj) {} |
| 456 static void ReleaseCallee(ChromeFrameAutomationClient* obj) {} | 524 static void ReleaseCallee(ChromeFrameAutomationClient* obj) {} |
| 457 }; | 525 }; |
| 458 | 526 |
| 459 ChromeFrameAutomationClient::ChromeFrameAutomationClient() | 527 ChromeFrameAutomationClient::ChromeFrameAutomationClient() |
| 460 : chrome_frame_delegate_(NULL), | 528 : chrome_frame_delegate_(NULL), |
| 461 chrome_window_(NULL), | 529 chrome_window_(NULL), |
| 462 tab_window_(NULL), | 530 tab_window_(NULL), |
| 463 parent_window_(NULL), | 531 parent_window_(NULL), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 475 navigate_after_initialization_(false) { | 543 navigate_after_initialization_(false) { |
| 476 } | 544 } |
| 477 | 545 |
| 478 ChromeFrameAutomationClient::~ChromeFrameAutomationClient() { | 546 ChromeFrameAutomationClient::~ChromeFrameAutomationClient() { |
| 479 // Uninitialize must be called prior to the destructor | 547 // Uninitialize must be called prior to the destructor |
| 480 DCHECK(automation_server_ == NULL); | 548 DCHECK(automation_server_ == NULL); |
| 481 } | 549 } |
| 482 | 550 |
| 483 bool ChromeFrameAutomationClient::Initialize( | 551 bool ChromeFrameAutomationClient::Initialize( |
| 484 ChromeFrameDelegate* chrome_frame_delegate, | 552 ChromeFrameDelegate* chrome_frame_delegate, |
| 485 const ChromeFrameLaunchParams& chrome_launch_params) { | 553 ChromeFrameLaunchParams* chrome_launch_params) { |
| 486 DCHECK(!IsWindow()); | 554 DCHECK(!IsWindow()); |
| 487 chrome_frame_delegate_ = chrome_frame_delegate; | 555 chrome_frame_delegate_ = chrome_frame_delegate; |
| 488 | 556 |
| 557 #ifndef NDEBUG |
| 558 if (chrome_launch_params_ && chrome_launch_params_ != chrome_launch_params) { |
| 559 DCHECK_EQ(chrome_launch_params_->url(), chrome_launch_params->url()); |
| 560 DCHECK_EQ(chrome_launch_params_->referrer(), |
| 561 chrome_launch_params->referrer()); |
| 562 } |
| 563 #endif |
| 564 |
| 489 chrome_launch_params_ = chrome_launch_params; | 565 chrome_launch_params_ = chrome_launch_params; |
| 490 | 566 |
| 491 ui_thread_id_ = PlatformThread::CurrentId(); | 567 ui_thread_id_ = PlatformThread::CurrentId(); |
| 492 #ifndef NDEBUG | 568 #ifndef NDEBUG |
| 493 // In debug mode give more time to work with a debugger. | 569 // In debug mode give more time to work with a debugger. |
| 494 if (IsDebuggerPresent()) { | 570 if (IsDebuggerPresent()) { |
| 495 // Don't use INFINITE (which is -1) or even MAXINT since we will convert | 571 // Don't use INFINITE (which is -1) or even MAXINT since we will convert |
| 496 // from milliseconds to microseconds when stored in a base::TimeDelta, | 572 // from milliseconds to microseconds when stored in a base::TimeDelta, |
| 497 // thus * 1000. An hour should be enough. | 573 // thus * 1000. An hour should be enough. |
| 498 chrome_launch_params_.automation_server_launch_timeout = 60 * 60 * 1000; | 574 chrome_launch_params_->set_launch_timeout(60 * 60 * 1000); |
| 499 } else { | 575 } else { |
| 500 DCHECK_LT(chrome_launch_params_.automation_server_launch_timeout, | 576 DCHECK_LT(chrome_launch_params_->launch_timeout(), |
| 501 MAXINT / 2000); | 577 MAXINT / 2000); |
| 502 chrome_launch_params_.automation_server_launch_timeout *= 2; | 578 chrome_launch_params_->set_launch_timeout( |
| 579 chrome_launch_params_->launch_timeout() * 2); |
| 503 } | 580 } |
| 504 #endif // NDEBUG | 581 #endif // NDEBUG |
| 505 | 582 |
| 506 // Create a window on the UI thread for marshaling messages back and forth | 583 // Create a window on the UI thread for marshaling messages back and forth |
| 507 // from the IPC thread. This window cannot be a message only window as the | 584 // from the IPC thread. This window cannot be a message only window as the |
| 508 // external chrome tab window is created as a child of this window. This | 585 // external chrome tab window is created as a child of this window. This |
| 509 // window is eventually reparented to the ActiveX/NPAPI plugin window. | 586 // window is eventually reparented to the ActiveX/NPAPI plugin window. |
| 510 if (!Create(GetDesktopWindow(), NULL, NULL, | 587 if (!Create(GetDesktopWindow(), NULL, NULL, |
| 511 WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, | 588 WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, |
| 512 WS_EX_TOOLWINDOW)) { | 589 WS_EX_TOOLWINDOW)) { |
| 513 NOTREACHED(); | 590 NOTREACHED(); |
| 514 return false; | 591 return false; |
| 515 } | 592 } |
| 516 | 593 |
| 517 // Keep object in memory, while the window is alive. | 594 // Keep object in memory, while the window is alive. |
| 518 // Corresponsing Release is in OnFinalMessage(); | 595 // Corresponding Release is in OnFinalMessage(); |
| 519 AddRef(); | 596 AddRef(); |
| 520 | 597 |
| 521 // Mark our state as initializing. We'll reach initialized once | 598 // Mark our state as initializing. We'll reach initialized once |
| 522 // InitializeComplete is called successfully. | 599 // InitializeComplete is called successfully. |
| 523 init_state_ = INITIALIZING; | 600 init_state_ = INITIALIZING; |
| 524 | 601 |
| 525 if (chrome_launch_params_.url.is_valid()) | 602 if (chrome_launch_params_->url().is_valid()) |
| 526 navigate_after_initialization_ = false; | 603 navigate_after_initialization_ = false; |
| 527 | 604 |
| 528 proxy_factory_->GetAutomationServer( | 605 proxy_factory_->GetAutomationServer(static_cast<LaunchDelegate*>(this), |
| 529 static_cast<ProxyFactory::LaunchDelegate*>(this), | |
| 530 chrome_launch_params_, &automation_server_id_); | 606 chrome_launch_params_, &automation_server_id_); |
| 531 | 607 |
| 532 return true; | 608 return true; |
| 533 } | 609 } |
| 534 | 610 |
| 535 void ChromeFrameAutomationClient::Uninitialize() { | 611 void ChromeFrameAutomationClient::Uninitialize() { |
| 536 if (init_state_ == UNINITIALIZED) { | 612 if (init_state_ == UNINITIALIZED) { |
| 537 DLOG(WARNING) << __FUNCTION__ << ": Automation client not initialized"; | 613 DLOG(WARNING) << __FUNCTION__ << ": Automation client not initialized"; |
| 538 return; | 614 return; |
| 539 } | 615 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 564 | 640 |
| 565 // Wait for the background thread to exit. | 641 // Wait for the background thread to exit. |
| 566 ReleaseAutomationServer(); | 642 ReleaseAutomationServer(); |
| 567 | 643 |
| 568 // We must destroy the window, since if there are pending tasks | 644 // We must destroy the window, since if there are pending tasks |
| 569 // window procedure may be invoked after DLL is unloaded. | 645 // window procedure may be invoked after DLL is unloaded. |
| 570 // Unfortunately pending tasks are leaked. | 646 // Unfortunately pending tasks are leaked. |
| 571 if (::IsWindow(m_hWnd)) | 647 if (::IsWindow(m_hWnd)) |
| 572 DestroyWindow(); | 648 DestroyWindow(); |
| 573 | 649 |
| 650 DCHECK(navigate_after_initialization_ == false); |
| 651 handle_top_level_requests_ = false; |
| 652 ui_thread_id_ = 0; |
| 574 chrome_frame_delegate_ = NULL; | 653 chrome_frame_delegate_ = NULL; |
| 575 init_state_ = UNINITIALIZED; | 654 init_state_ = UNINITIALIZED; |
| 576 } | 655 } |
| 577 | 656 |
| 578 bool ChromeFrameAutomationClient::InitiateNavigation( | 657 bool ChromeFrameAutomationClient::InitiateNavigation(const std::string& url, |
| 579 const std::string& url, const std::string& referrer, bool is_privileged) { | 658 const std::string& referrer, bool is_privileged) { |
| 580 if (url.empty()) | 659 if (url.empty()) |
| 581 return false; | 660 return false; |
| 582 | 661 |
| 583 GURL parsed_url(url); | 662 GURL parsed_url(url); |
| 584 // Catch invalid URLs early. | 663 // Catch invalid URLs early. |
| 585 if (!parsed_url.is_valid() || | 664 if (!parsed_url.is_valid() || |
| 586 !IsValidUrlScheme(UTF8ToWide(url), is_privileged)) { | 665 !IsValidUrlScheme(UTF8ToWide(url), is_privileged)) { |
| 587 DLOG(ERROR) << "Invalid URL passed to InitiateNavigation: " << url | 666 DLOG(ERROR) << "Invalid URL passed to InitiateNavigation: " << url |
| 588 << " is_privileged=" << is_privileged; | 667 << " is_privileged=" << is_privileged; |
| 589 return false; | 668 return false; |
| 590 } | 669 } |
| 591 | 670 |
| 592 if (parsed_url != chrome_launch_params_.url) { | 671 if (!chrome_launch_params_ || parsed_url != chrome_launch_params_->url()) { |
| 593 // Important: Since we will be using the referrer_ variable from a | 672 // Important: Since we will be using the referrer_ variable from a |
| 594 // different thread, we need to force a new std::string buffer instance for | 673 // different thread, we need to force a new std::string buffer instance for |
| 595 // the referrer_ GURL variable. Otherwise we can run into strangeness when | 674 // the referrer_ GURL variable. Otherwise we can run into strangeness when |
| 596 // the GURL is accessed and it could result in a bad URL that can cause the | 675 // the GURL is accessed and it could result in a bad URL that can cause the |
| 597 // referrer to be dropped or something worse. | 676 // referrer to be dropped or something worse. |
| 598 chrome_launch_params_.referrer = GURL(referrer.c_str()); | 677 GURL referrer_gurl(referrer.c_str()); |
| 599 chrome_launch_params_.url = parsed_url; | 678 if (!chrome_launch_params_) { |
| 679 FilePath profile_path; |
| 680 chrome_launch_params_ = new ChromeFrameLaunchParams(parsed_url, |
| 681 referrer_gurl, profile_path, L"", L"", false, false); |
| 682 } else { |
| 683 chrome_launch_params_->set_referrer(referrer_gurl); |
| 684 chrome_launch_params_->set_url(parsed_url); |
| 685 } |
| 600 | 686 |
| 601 navigate_after_initialization_ = false; | 687 navigate_after_initialization_ = false; |
| 602 | 688 |
| 603 if (is_initialized()) { | 689 if (is_initialized()) { |
| 604 BeginNavigate(chrome_launch_params_.url, chrome_launch_params_.referrer); | 690 BeginNavigate(); |
| 605 } else { | 691 } else { |
| 606 navigate_after_initialization_ = true; | 692 navigate_after_initialization_ = true; |
| 607 } | 693 } |
| 608 } | 694 } |
| 609 | 695 |
| 610 return true; | 696 return true; |
| 611 } | 697 } |
| 612 | 698 |
| 613 bool ChromeFrameAutomationClient::NavigateToIndex(int index) { | 699 bool ChromeFrameAutomationClient::NavigateToIndex(int index) { |
| 614 // Could be NULL if we failed to launch Chrome in LaunchAutomationServer() | 700 // Could be NULL if we failed to launch Chrome in LaunchAutomationServer() |
| (...skipping 22 matching lines...) Expand all Loading... |
| 637 } | 723 } |
| 638 | 724 |
| 639 bool ChromeFrameAutomationClient::SetProxySettings( | 725 bool ChromeFrameAutomationClient::SetProxySettings( |
| 640 const std::string& json_encoded_proxy_settings) { | 726 const std::string& json_encoded_proxy_settings) { |
| 641 if (!is_initialized()) | 727 if (!is_initialized()) |
| 642 return false; | 728 return false; |
| 643 automation_server_->SendProxyConfig(json_encoded_proxy_settings); | 729 automation_server_->SendProxyConfig(json_encoded_proxy_settings); |
| 644 return true; | 730 return true; |
| 645 } | 731 } |
| 646 | 732 |
| 647 void ChromeFrameAutomationClient::BeginNavigate(const GURL& url, | 733 void ChromeFrameAutomationClient::BeginNavigate() { |
| 648 const GURL& referrer) { | |
| 649 // Could be NULL if we failed to launch Chrome in LaunchAutomationServer() | 734 // Could be NULL if we failed to launch Chrome in LaunchAutomationServer() |
| 650 if (!automation_server_ || !tab_.get()) { | 735 if (!automation_server_ || !tab_.get()) { |
| 651 DLOG(WARNING) << "BeginNavigate - can't navigate."; | 736 DLOG(WARNING) << "BeginNavigate - can't navigate."; |
| 652 ReportNavigationError(AUTOMATION_MSG_NAVIGATION_ERROR, | 737 ReportNavigationError(AUTOMATION_MSG_NAVIGATION_ERROR, |
| 653 chrome_launch_params_.url.spec()); | 738 chrome_launch_params_->url().spec()); |
| 654 return; | 739 return; |
| 655 } | 740 } |
| 656 | 741 |
| 657 DCHECK(::IsWindow(chrome_window_)); | 742 DCHECK(::IsWindow(chrome_window_)); |
| 658 | 743 |
| 659 if (!tab_->is_valid()) { | 744 if (!tab_->is_valid()) { |
| 660 DLOG(WARNING) << "BeginNavigate - tab isn't valid."; | 745 DLOG(WARNING) << "BeginNavigate - tab isn't valid."; |
| 661 return; | 746 return; |
| 662 } | 747 } |
| 663 | 748 |
| 664 IPC::SyncMessage* msg = | 749 IPC::SyncMessage* msg = |
| 665 new AutomationMsg_NavigateInExternalTab(0, tab_->handle(), url, | 750 new AutomationMsg_NavigateInExternalTab(0, tab_->handle(), |
| 666 referrer, NULL); | 751 chrome_launch_params_->url(), chrome_launch_params_->referrer(), |
| 752 NULL); |
| 667 automation_server_->SendAsAsync(msg, new BeginNavigateContext(this), this); | 753 automation_server_->SendAsAsync(msg, new BeginNavigateContext(this), this); |
| 668 | 754 |
| 669 RECT client_rect = {0}; | 755 RECT client_rect = {0}; |
| 670 chrome_frame_delegate_->GetBounds(&client_rect); | 756 chrome_frame_delegate_->GetBounds(&client_rect); |
| 671 Resize(client_rect.right - client_rect.left, | 757 Resize(client_rect.right - client_rect.left, |
| 672 client_rect.bottom - client_rect.top, | 758 client_rect.bottom - client_rect.top, |
| 673 SWP_NOACTIVATE | SWP_NOZORDER); | 759 SWP_NOACTIVATE | SWP_NOZORDER); |
| 674 } | 760 } |
| 675 | 761 |
| 676 void ChromeFrameAutomationClient::BeginNavigateCompleted( | 762 void ChromeFrameAutomationClient::BeginNavigateCompleted( |
| 677 AutomationMsg_NavigationResponseValues result) { | 763 AutomationMsg_NavigationResponseValues result) { |
| 678 if (result == AUTOMATION_MSG_NAVIGATION_ERROR) | 764 if (result == AUTOMATION_MSG_NAVIGATION_ERROR) |
| 679 ReportNavigationError(AUTOMATION_MSG_NAVIGATION_ERROR, | 765 ReportNavigationError(AUTOMATION_MSG_NAVIGATION_ERROR, |
| 680 chrome_launch_params_.url.spec()); | 766 chrome_launch_params_->url().spec()); |
| 681 } | 767 } |
| 682 | 768 |
| 683 void ChromeFrameAutomationClient::FindInPage(const std::wstring& search_string, | 769 void ChromeFrameAutomationClient::FindInPage(const std::wstring& search_string, |
| 684 FindInPageDirection forward, | 770 FindInPageDirection forward, |
| 685 FindInPageCase match_case, | 771 FindInPageCase match_case, |
| 686 bool find_next) { | 772 bool find_next) { |
| 687 DCHECK(tab_.get()); | 773 DCHECK(tab_.get()); |
| 688 | 774 |
| 689 // What follows is quite similar to TabProxy::FindInPage() but uses | 775 // What follows is quite similar to TabProxy::FindInPage() but uses |
| 690 // the SyncMessageReplyDispatcher to avoid concerns about blocking | 776 // the SyncMessageReplyDispatcher to avoid concerns about blocking |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 | 876 |
| 791 // The context will delete itself after it is called. | 877 // The context will delete itself after it is called. |
| 792 automation_server_->SendAsAsync(msg, ctx, this); | 878 automation_server_->SendAsAsync(msg, ctx, this); |
| 793 } | 879 } |
| 794 | 880 |
| 795 void ChromeFrameAutomationClient::CreateExternalTab() { | 881 void ChromeFrameAutomationClient::CreateExternalTab() { |
| 796 AutomationLaunchResult launch_result = AUTOMATION_SUCCESS; | 882 AutomationLaunchResult launch_result = AUTOMATION_SUCCESS; |
| 797 DCHECK(IsWindow()); | 883 DCHECK(IsWindow()); |
| 798 DCHECK(automation_server_ != NULL); | 884 DCHECK(automation_server_ != NULL); |
| 799 | 885 |
| 800 if (chrome_launch_params_.url.is_valid()) { | 886 if (chrome_launch_params_->url().is_valid()) { |
| 801 navigate_after_initialization_ = false; | 887 navigate_after_initialization_ = false; |
| 802 } | 888 } |
| 803 | 889 |
| 804 const IPC::ExternalTabSettings settings = { | 890 const IPC::ExternalTabSettings settings = { |
| 805 m_hWnd, | 891 m_hWnd, |
| 806 gfx::Rect(), | 892 gfx::Rect(), |
| 807 WS_CHILD, | 893 WS_CHILD, |
| 808 chrome_launch_params_.incognito_mode, | 894 chrome_launch_params_->incognito(), |
| 809 !use_chrome_network_, | 895 !use_chrome_network_, |
| 810 handle_top_level_requests_, | 896 handle_top_level_requests_, |
| 811 chrome_launch_params_.url, | 897 chrome_launch_params_->url(), |
| 812 chrome_launch_params_.referrer, | 898 chrome_launch_params_->referrer(), |
| 813 !chrome_launch_params_.is_widget_mode // Infobars disabled in widget mode. | 899 !chrome_launch_params_->widget_mode() // Infobars disabled in widget mode. |
| 814 }; | 900 }; |
| 815 | 901 |
| 816 THREAD_SAFE_UMA_HISTOGRAM_CUSTOM_COUNTS( | 902 THREAD_SAFE_UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 817 "ChromeFrame.HostNetworking", !use_chrome_network_, 0, 1, 2); | 903 "ChromeFrame.HostNetworking", !use_chrome_network_, 0, 1, 2); |
| 818 | 904 |
| 819 THREAD_SAFE_UMA_HISTOGRAM_CUSTOM_COUNTS( | 905 THREAD_SAFE_UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 820 "ChromeFrame.HandleTopLevelRequests", handle_top_level_requests_, 0, 1, | 906 "ChromeFrame.HandleTopLevelRequests", handle_top_level_requests_, 0, 1, |
| 821 2); | 907 2); |
| 822 | 908 |
| 823 IPC::SyncMessage* message = | 909 IPC::SyncMessage* message = |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 DLOG(INFO) << __FUNCTION__ << ": sending CreateExternalTabComplete"; | 983 DLOG(INFO) << __FUNCTION__ << ": sending CreateExternalTabComplete"; |
| 898 } | 984 } |
| 899 } | 985 } |
| 900 } else { | 986 } else { |
| 901 // Launch failed. Note, we cannot delete proxy here. | 987 // Launch failed. Note, we cannot delete proxy here. |
| 902 PostTask(FROM_HERE, NewRunnableMethod(this, | 988 PostTask(FROM_HERE, NewRunnableMethod(this, |
| 903 &ChromeFrameAutomationClient::InitializeComplete, result)); | 989 &ChromeFrameAutomationClient::InitializeComplete, result)); |
| 904 } | 990 } |
| 905 } | 991 } |
| 906 | 992 |
| 993 void ChromeFrameAutomationClient::AutomationServerDied() { |
| 994 // Make sure we notify our delegate. |
| 995 PostTask(FROM_HERE, NewRunnableMethod(this, |
| 996 &ChromeFrameAutomationClient::InitializeComplete, |
| 997 AUTOMATION_SERVER_CRASHED)); |
| 998 // Then uninitialize. |
| 999 PostTask(FROM_HERE, NewRunnableMethod(this, |
| 1000 &ChromeFrameAutomationClient::Uninitialize)); |
| 1001 } |
| 1002 |
| 907 void ChromeFrameAutomationClient::InitializeComplete( | 1003 void ChromeFrameAutomationClient::InitializeComplete( |
| 908 AutomationLaunchResult result) { | 1004 AutomationLaunchResult result) { |
| 909 DCHECK_EQ(PlatformThread::CurrentId(), ui_thread_id_); | 1005 DCHECK_EQ(PlatformThread::CurrentId(), ui_thread_id_); |
| 910 std::string version = automation_server_->server_version(); | 1006 std::string version = automation_server_->server_version(); |
| 911 | 1007 |
| 912 if (result != AUTOMATION_SUCCESS) { | 1008 if (result != AUTOMATION_SUCCESS) { |
| 913 DLOG(WARNING) << "InitializeComplete: failure " << result; | 1009 DLOG(WARNING) << "InitializeComplete: failure " << result; |
| 914 ReleaseAutomationServer(); | 1010 ReleaseAutomationServer(); |
| 915 } else { | 1011 } else { |
| 916 init_state_ = INITIALIZED; | 1012 init_state_ = INITIALIZED; |
| 917 | 1013 |
| 918 // If the host already have a window, ask Chrome to re-parent. | 1014 // If the host already have a window, ask Chrome to re-parent. |
| 919 if (parent_window_) | 1015 if (parent_window_) |
| 920 SetParentWindow(parent_window_); | 1016 SetParentWindow(parent_window_); |
| 921 | 1017 |
| 922 // If host specified destination URL - navigate. Apparently we do not use | 1018 // If host specified destination URL - navigate. Apparently we do not use |
| 923 // accelerator table. | 1019 // accelerator table. |
| 924 if (navigate_after_initialization_) { | 1020 if (navigate_after_initialization_) { |
| 925 BeginNavigate(chrome_launch_params_.url, | 1021 navigate_after_initialization_ = false; |
| 926 chrome_launch_params_.referrer); | 1022 BeginNavigate(); |
| 927 } | 1023 } |
| 928 } | 1024 } |
| 929 | 1025 |
| 930 if (chrome_frame_delegate_) { | 1026 if (chrome_frame_delegate_) { |
| 931 if (result == AUTOMATION_SUCCESS) { | 1027 if (result == AUTOMATION_SUCCESS) { |
| 932 chrome_frame_delegate_->OnAutomationServerReady(); | 1028 chrome_frame_delegate_->OnAutomationServerReady(); |
| 933 } else { | 1029 } else { |
| 934 chrome_frame_delegate_->OnAutomationServerLaunchFailed(result, version); | 1030 chrome_frame_delegate_->OnAutomationServerLaunchFailed(result, version); |
| 935 } | 1031 } |
| 936 } | 1032 } |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1119 // Refactor the ChromeFrameAutomationProxy code to not depend on | 1215 // Refactor the ChromeFrameAutomationProxy code to not depend on |
| 1120 // AutomationProxy and simplify the whole mess. | 1216 // AutomationProxy and simplify the whole mess. |
| 1121 void* server_id = automation_server_id_; | 1217 void* server_id = automation_server_id_; |
| 1122 automation_server_id_ = NULL; | 1218 automation_server_id_ = NULL; |
| 1123 | 1219 |
| 1124 if (automation_server_) { | 1220 if (automation_server_) { |
| 1125 // Make sure to clean up any pending sync messages before we go away. | 1221 // Make sure to clean up any pending sync messages before we go away. |
| 1126 automation_server_->CancelAsync(this); | 1222 automation_server_->CancelAsync(this); |
| 1127 } | 1223 } |
| 1128 | 1224 |
| 1129 proxy_factory_->ReleaseAutomationServer(server_id); | 1225 proxy_factory_->ReleaseAutomationServer(server_id, this); |
| 1130 automation_server_ = NULL; | 1226 automation_server_ = NULL; |
| 1131 | 1227 |
| 1132 // automation_server_ must not have been set to non NULL. | 1228 // automation_server_ must not have been set to non NULL. |
| 1133 // (if this regresses, start by looking at LaunchComplete()). | 1229 // (if this regresses, start by looking at LaunchComplete()). |
| 1134 DCHECK(automation_server_ == NULL); | 1230 DCHECK(automation_server_ == NULL); |
| 1135 } else { | 1231 } else { |
| 1136 DCHECK(automation_server_ == NULL); | 1232 DCHECK(automation_server_ == NULL); |
| 1137 } | 1233 } |
| 1138 } | 1234 } |
| 1139 | 1235 |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1289 const URLRequestStatus& status) { | 1385 const URLRequestStatus& status) { |
| 1290 automation_server_->Send(new AutomationMsg_RequestEnd(0, tab_->handle(), | 1386 automation_server_->Send(new AutomationMsg_RequestEnd(0, tab_->handle(), |
| 1291 request_id, status)); | 1387 request_id, status)); |
| 1292 } | 1388 } |
| 1293 | 1389 |
| 1294 void ChromeFrameAutomationClient::OnCookiesRetrieved(bool success, | 1390 void ChromeFrameAutomationClient::OnCookiesRetrieved(bool success, |
| 1295 const GURL& url, const std::string& cookie_string, int cookie_id) { | 1391 const GURL& url, const std::string& cookie_string, int cookie_id) { |
| 1296 automation_server_->Send(new AutomationMsg_GetCookiesHostResponse(0, | 1392 automation_server_->Send(new AutomationMsg_GetCookiesHostResponse(0, |
| 1297 tab_->handle(), success, url, cookie_string, cookie_id)); | 1393 tab_->handle(), success, url, cookie_string, cookie_id)); |
| 1298 } | 1394 } |
| OLD | NEW |