OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/browser/ui/hung_plugin_tab_helper.h" | 5 #include "chrome/browser/ui/hung_plugin_tab_helper.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/process/process.h" | 10 #include "base/process/process.h" |
11 #include "base/rand_util.h" | 11 #include "base/rand_util.h" |
12 #include "build/build_config.h" | 12 #include "build/build_config.h" |
13 #include "chrome/browser/chrome_notification_types.h" | |
14 #include "chrome/browser/infobars/infobar_service.h" | 13 #include "chrome/browser/infobars/infobar_service.h" |
15 #include "chrome/common/chrome_version_info.h" | 14 #include "chrome/common/chrome_version_info.h" |
16 #include "components/infobars/core/confirm_infobar_delegate.h" | 15 #include "components/infobars/core/confirm_infobar_delegate.h" |
17 #include "components/infobars/core/infobar.h" | 16 #include "components/infobars/core/infobar.h" |
18 #include "content/public/browser/browser_child_process_host_iterator.h" | 17 #include "content/public/browser/browser_child_process_host_iterator.h" |
19 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
20 #include "content/public/browser/child_process_data.h" | 19 #include "content/public/browser/child_process_data.h" |
21 #include "content/public/browser/notification_details.h" | |
22 #include "content/public/browser/notification_service.h" | |
23 #include "content/public/browser/plugin_service.h" | 20 #include "content/public/browser/plugin_service.h" |
24 #include "content/public/browser/render_process_host.h" | 21 #include "content/public/browser/render_process_host.h" |
25 #include "content/public/common/process_type.h" | 22 #include "content/public/common/process_type.h" |
26 #include "content/public/common/result_codes.h" | 23 #include "content/public/common/result_codes.h" |
27 #include "grit/chromium_strings.h" | 24 #include "grit/chromium_strings.h" |
28 #include "grit/generated_resources.h" | 25 #include "grit/generated_resources.h" |
29 #include "grit/locale_settings.h" | 26 #include "grit/locale_settings.h" |
30 #include "grit/theme_resources.h" | 27 #include "grit/theme_resources.h" |
31 #include "ui/base/l10n/l10n_util.h" | 28 #include "ui/base/l10n/l10n_util.h" |
32 | 29 |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
254 | 251 |
255 HungPluginTabHelper::PluginState::~PluginState() { | 252 HungPluginTabHelper::PluginState::~PluginState() { |
256 } | 253 } |
257 | 254 |
258 | 255 |
259 // HungPluginTabHelper -------------------------------------------------------- | 256 // HungPluginTabHelper -------------------------------------------------------- |
260 | 257 |
261 DEFINE_WEB_CONTENTS_USER_DATA_KEY(HungPluginTabHelper); | 258 DEFINE_WEB_CONTENTS_USER_DATA_KEY(HungPluginTabHelper); |
262 | 259 |
263 HungPluginTabHelper::HungPluginTabHelper(content::WebContents* contents) | 260 HungPluginTabHelper::HungPluginTabHelper(content::WebContents* contents) |
264 : content::WebContentsObserver(contents) { | 261 : content::WebContentsObserver(contents), |
265 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, | 262 observer_installed_(false) { |
266 content::NotificationService::AllSources()); | |
267 } | 263 } |
268 | 264 |
269 HungPluginTabHelper::~HungPluginTabHelper() { | 265 HungPluginTabHelper::~HungPluginTabHelper() { |
270 } | 266 } |
271 | 267 |
272 void HungPluginTabHelper::PluginCrashed(const base::FilePath& plugin_path, | 268 void HungPluginTabHelper::PluginCrashed(const base::FilePath& plugin_path, |
273 base::ProcessId plugin_pid) { | 269 base::ProcessId plugin_pid) { |
274 // TODO(brettw) ideally this would take the child process ID. When we do this | 270 // TODO(brettw) ideally this would take the child process ID. When we do this |
275 // for NaCl plugins, we'll want to know exactly which process it was since | 271 // for NaCl plugins, we'll want to know exactly which process it was since |
276 // the path won't be useful. | 272 // the path won't be useful. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
314 | 310 |
315 base::string16 plugin_name = | 311 base::string16 plugin_name = |
316 content::PluginService::GetInstance()->GetPluginDisplayNameByPath( | 312 content::PluginService::GetInstance()->GetPluginDisplayNameByPath( |
317 plugin_path); | 313 plugin_path); |
318 | 314 |
319 linked_ptr<PluginState> state(new PluginState(plugin_path, plugin_name)); | 315 linked_ptr<PluginState> state(new PluginState(plugin_path, plugin_name)); |
320 hung_plugins_[plugin_child_id] = state; | 316 hung_plugins_[plugin_child_id] = state; |
321 ShowBar(plugin_child_id, state.get()); | 317 ShowBar(plugin_child_id, state.get()); |
322 } | 318 } |
323 | 319 |
324 void HungPluginTabHelper::Observe( | |
325 int type, | |
326 const content::NotificationSource& source, | |
327 const content::NotificationDetails& details) { | |
328 DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type); | |
329 infobars::InfoBar* infobar = | |
330 content::Details<infobars::InfoBar::RemovedDetails>(details)->first; | |
331 for (PluginStateMap::iterator i = hung_plugins_.begin(); | |
332 i != hung_plugins_.end(); ++i) { | |
333 PluginState* state = i->second.get(); | |
334 if (state->infobar == infobar) { | |
335 state->infobar = NULL; | |
336 | |
337 // Schedule the timer to re-show the infobar if the plugin continues to be | |
338 // hung. | |
339 state->timer.Start(FROM_HERE, state->next_reshow_delay, | |
340 base::Bind(&HungPluginTabHelper::OnReshowTimer, | |
341 base::Unretained(this), | |
342 i->first)); | |
343 | |
344 // Next time we do this, delay it twice as long to avoid being annoying. | |
345 state->next_reshow_delay *= 2; | |
346 return; | |
347 } | |
348 } | |
349 } | |
350 | |
351 void HungPluginTabHelper::KillPlugin(int child_id) { | 320 void HungPluginTabHelper::KillPlugin(int child_id) { |
352 #if defined(OS_WIN) | 321 #if defined(OS_WIN) |
353 // Dump renderers that are sending or receiving pepper messages, in order to | 322 // Dump renderers that are sending or receiving pepper messages, in order to |
354 // diagnose inter-process deadlocks. | 323 // diagnose inter-process deadlocks. |
355 // Only do that on the Canary channel, for 20% of pepper plugin hangs. | 324 // Only do that on the Canary channel, for 20% of pepper plugin hangs. |
356 if (base::RandInt(0, 100) < 20) { | 325 if (base::RandInt(0, 100) < 20) { |
357 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); | 326 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); |
358 if (channel == chrome::VersionInfo::CHANNEL_CANARY) { | 327 if (channel == chrome::VersionInfo::CHANNEL_CANARY) { |
359 scoped_ptr<OwnedHandleVector> renderer_handles(new OwnedHandleVector); | 328 scoped_ptr<OwnedHandleVector> renderer_handles(new OwnedHandleVector); |
360 HANDLE current_process = ::GetCurrentProcess(); | 329 HANDLE current_process = ::GetCurrentProcess(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
402 DCHECK(!found->second->infobar); | 371 DCHECK(!found->second->infobar); |
403 ShowBar(child_id, found->second.get()); | 372 ShowBar(child_id, found->second.get()); |
404 } | 373 } |
405 | 374 |
406 void HungPluginTabHelper::ShowBar(int child_id, PluginState* state) { | 375 void HungPluginTabHelper::ShowBar(int child_id, PluginState* state) { |
407 InfoBarService* infobar_service = | 376 InfoBarService* infobar_service = |
408 InfoBarService::FromWebContents(web_contents()); | 377 InfoBarService::FromWebContents(web_contents()); |
409 if (!infobar_service) | 378 if (!infobar_service) |
410 return; | 379 return; |
411 | 380 |
381 if (!observer_installed_) { | |
382 observer_installed_ = true; | |
383 infobar_service->AddObserver(this); | |
384 } | |
385 | |
412 DCHECK(!state->infobar); | 386 DCHECK(!state->infobar); |
413 state->infobar = HungPluginInfoBarDelegate::Create(infobar_service, this, | 387 state->infobar = HungPluginInfoBarDelegate::Create(infobar_service, this, |
414 child_id, state->name); | 388 child_id, state->name); |
415 } | 389 } |
416 | 390 |
417 void HungPluginTabHelper::CloseBar(PluginState* state) { | 391 void HungPluginTabHelper::CloseBar(PluginState* state) { |
418 InfoBarService* infobar_service = | 392 InfoBarService* infobar_service = |
419 InfoBarService::FromWebContents(web_contents()); | 393 InfoBarService::FromWebContents(web_contents()); |
420 if (infobar_service && state->infobar) { | 394 if (infobar_service && state->infobar) { |
421 infobar_service->RemoveInfoBar(state->infobar); | 395 infobar_service->RemoveInfoBar(state->infobar); |
422 state->infobar = NULL; | 396 state->infobar = NULL; |
397 | |
398 if (observer_installed_) { | |
399 observer_installed_ = false; | |
400 infobar_service->RemoveObserver(this); | |
Peter Kasting
2014/05/30 18:54:47
This still doesn't seem right.
(1) What if the ba
tfarina
2014/05/30 21:14:03
Not sure if that answers your question. But the bi
| |
401 } | |
423 } | 402 } |
424 } | 403 } |
404 | |
405 void HungPluginTabHelper::OnInfoBarRemoved(infobars::InfoBar* infobar, | |
406 bool animate) { | |
407 for (PluginStateMap::iterator i = hung_plugins_.begin(); | |
408 i != hung_plugins_.end(); ++i) { | |
409 PluginState* state = i->second.get(); | |
410 if (state->infobar == infobar) { | |
411 state->infobar = NULL; | |
412 | |
413 // Schedule the timer to re-show the infobar if the plugin continues to be | |
414 // hung. | |
415 state->timer.Start(FROM_HERE, | |
416 state->next_reshow_delay, | |
417 base::Bind(&HungPluginTabHelper::OnReshowTimer, | |
418 base::Unretained(this), | |
419 i->first)); | |
420 | |
421 // Next time we do this, delay it twice as long to avoid being annoying. | |
422 state->next_reshow_delay *= 2; | |
423 return; | |
424 } | |
425 } | |
426 } | |
427 | |
428 void HungPluginTabHelper::OnManagerShuttingDown( | |
429 infobars::InfoBarManager* manager) { | |
430 InfoBarService* infobar_service = | |
431 InfoBarService::FromWebContents(web_contents()); | |
432 if (!infobar_service) | |
433 return; | |
434 | |
435 if (observer_installed_) { | |
436 observer_installed_ = false; | |
437 infobar_service->RemoveObserver(this); | |
438 } | |
439 } | |
OLD | NEW |