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 "content/browser/renderer_host/render_view_host_impl.h" | 5 #include "content/browser/renderer_host/render_view_host_impl.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/i18n/rtl.h" | 12 #include "base/i18n/rtl.h" |
13 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
14 #include "base/json/json_writer.h" | 14 #include "base/json/json_writer.h" |
15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
16 #include "base/message_loop.h" | 16 #include "base/message_loop.h" |
| 17 #include "base/metrics/histogram.h" |
17 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
18 #include "base/string_util.h" | 19 #include "base/string_util.h" |
19 #include "base/time.h" | 20 #include "base/time.h" |
20 #include "base/utf_string_conversions.h" | 21 #include "base/utf_string_conversions.h" |
21 #include "base/values.h" | 22 #include "base/values.h" |
22 #include "content/browser/accessibility/browser_accessibility_state_impl.h" | 23 #include "content/browser/accessibility/browser_accessibility_state_impl.h" |
23 #include "content/browser/child_process_security_policy_impl.h" | 24 #include "content/browser/child_process_security_policy_impl.h" |
24 #include "content/browser/cross_site_request_manager.h" | 25 #include "content/browser/cross_site_request_manager.h" |
25 #include "content/browser/dom_storage/session_storage_namespace_impl.h" | 26 #include "content/browser/dom_storage/session_storage_namespace_impl.h" |
26 #include "content/browser/gpu/gpu_surface_tracker.h" | 27 #include "content/browser/gpu/gpu_surface_tracker.h" |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 waiting_for_drag_context_response_(false), | 164 waiting_for_drag_context_response_(false), |
164 enabled_bindings_(0), | 165 enabled_bindings_(0), |
165 pending_request_id_(-1), | 166 pending_request_id_(-1), |
166 navigations_suspended_(false), | 167 navigations_suspended_(false), |
167 suspended_nav_message_(NULL), | 168 suspended_nav_message_(NULL), |
168 is_swapped_out_(swapped_out), | 169 is_swapped_out_(swapped_out), |
169 run_modal_reply_msg_(NULL), | 170 run_modal_reply_msg_(NULL), |
170 run_modal_opener_id_(MSG_ROUTING_NONE), | 171 run_modal_opener_id_(MSG_ROUTING_NONE), |
171 is_waiting_for_beforeunload_ack_(false), | 172 is_waiting_for_beforeunload_ack_(false), |
172 is_waiting_for_unload_ack_(false), | 173 is_waiting_for_unload_ack_(false), |
| 174 has_timed_out_on_unload_(false), |
173 unload_ack_is_for_cross_site_transition_(false), | 175 unload_ack_is_for_cross_site_transition_(false), |
174 are_javascript_messages_suppressed_(false), | 176 are_javascript_messages_suppressed_(false), |
175 sudden_termination_allowed_(false), | 177 sudden_termination_allowed_(false), |
176 session_storage_namespace_( | 178 session_storage_namespace_( |
177 static_cast<SessionStorageNamespaceImpl*>(session_storage)), | 179 static_cast<SessionStorageNamespaceImpl*>(session_storage)), |
178 save_accessibility_tree_for_testing_(false), | 180 save_accessibility_tree_for_testing_(false), |
179 render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) { | 181 render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) { |
180 DCHECK(session_storage_namespace_); | 182 DCHECK(session_storage_namespace_); |
181 DCHECK(instance_); | 183 DCHECK(instance_); |
182 CHECK(delegate_); // http://crbug.com/82827 | 184 CHECK(delegate_); // http://crbug.com/82827 |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 // which we will do through the RenderProcessHost's widget helper. | 443 // which we will do through the RenderProcessHost's widget helper. |
442 GetProcess()->SimulateSwapOutACK(params); | 444 GetProcess()->SimulateSwapOutACK(params); |
443 } | 445 } |
444 } | 446 } |
445 | 447 |
446 void RenderViewHostImpl::OnSwapOutACK(bool timed_out) { | 448 void RenderViewHostImpl::OnSwapOutACK(bool timed_out) { |
447 // Stop the hang monitor now that the unload handler has finished. | 449 // Stop the hang monitor now that the unload handler has finished. |
448 decrement_in_flight_event_count(); | 450 decrement_in_flight_event_count(); |
449 StopHangMonitorTimeout(); | 451 StopHangMonitorTimeout(); |
450 is_waiting_for_unload_ack_ = false; | 452 is_waiting_for_unload_ack_ = false; |
| 453 has_timed_out_on_unload_ = timed_out; |
451 delegate_->SwappedOut(this); | 454 delegate_->SwappedOut(this); |
452 } | 455 } |
453 | 456 |
454 void RenderViewHostImpl::WasSwappedOut() { | 457 void RenderViewHostImpl::WasSwappedOut() { |
455 // Don't bother reporting hung state anymore. | 458 // Don't bother reporting hung state anymore. |
456 StopHangMonitorTimeout(); | 459 StopHangMonitorTimeout(); |
457 | 460 |
| 461 // If we have timed out on running the unload handler, we consider |
| 462 // the process hung and we should terminate it if there are no other tabs |
| 463 // using the process. If there are other views using this process, the |
| 464 // unresponsive renderer timeout will catch it. |
| 465 bool hung = has_timed_out_on_unload_; |
| 466 |
458 // Now that we're no longer the active RVH in the tab, start filtering out | 467 // Now that we're no longer the active RVH in the tab, start filtering out |
459 // most IPC messages. Usually the renderer will have stopped sending | 468 // most IPC messages. Usually the renderer will have stopped sending |
460 // messages as of OnSwapOutACK. However, we may have timed out waiting | 469 // messages as of OnSwapOutACK. However, we may have timed out waiting |
461 // for that message, and additional IPC messages may keep streaming in. | 470 // for that message, and additional IPC messages may keep streaming in. |
462 // We filter them out, as long as that won't cause problems (e.g., we | 471 // We filter them out, as long as that won't cause problems (e.g., we |
463 // still allow synchronous messages through). | 472 // still allow synchronous messages through). |
464 SetSwappedOut(true); | 473 SetSwappedOut(true); |
465 | 474 |
| 475 // If we are not running the renderer in process and no other tab is using |
| 476 // the hung process, consider it eligible to be killed, assuming it is a real |
| 477 // process (unit tests don't have real processes). |
| 478 if (hung) { |
| 479 base::ProcessHandle process_handle = GetProcess()->GetHandle(); |
| 480 int views = 0; |
| 481 |
| 482 // Count the number of widget hosts for the process, which is equivalent to |
| 483 // views using the process as of this writing. |
| 484 content::RenderProcessHost::RenderWidgetHostsIterator iter( |
| 485 GetProcess()->GetRenderWidgetHostsIterator()); |
| 486 for (; !iter.IsAtEnd(); iter.Advance()) |
| 487 ++views; |
| 488 |
| 489 if (!content::RenderProcessHost::run_renderer_in_process() && |
| 490 process_handle && views <= 1) { |
| 491 // The process can safely be terminated, only if WebContents sets |
| 492 // SuddenTerminationAllowed, which indicates that the timer has expired. |
| 493 // This is not the case if we load data URLs or about:blank. The reason |
| 494 // is that those have no network requests and this code is hit without |
| 495 // setting the unresponsiveness timer. This allows a corner case where a |
| 496 // navigation to a data URL will leave a process running, if the |
| 497 // beforeunload handler completes fine, but the unload handler hangs. |
| 498 // At this time, the complexity to solve this edge case is not worthwhile. |
| 499 if (SuddenTerminationAllowed()) { |
| 500 // We should kill the process, but for now, just log the data so we can |
| 501 // diagnose the kill rate and investigate if separate timer is needed. |
| 502 // http://crbug.com/104346. |
| 503 |
| 504 // Log a histogram point to help us diagnose how many of those kills |
| 505 // we have performed. 1 is the enum value for RendererType Normal for |
| 506 // the histogram. |
| 507 UMA_HISTOGRAM_PERCENTAGE( |
| 508 "BrowserRenderProcessHost.ChildKillsUnresponsive", 1); |
| 509 } |
| 510 } |
| 511 } |
| 512 |
466 // Inform the renderer that it can exit if no one else is using it. | 513 // Inform the renderer that it can exit if no one else is using it. |
467 Send(new ViewMsg_WasSwappedOut(GetRoutingID())); | 514 Send(new ViewMsg_WasSwappedOut(GetRoutingID())); |
468 } | 515 } |
469 | 516 |
470 void RenderViewHostImpl::ClosePage() { | 517 void RenderViewHostImpl::ClosePage() { |
471 // Start the hang monitor in case the renderer hangs in the unload handler. | 518 // Start the hang monitor in case the renderer hangs in the unload handler. |
472 is_waiting_for_unload_ack_ = true; | 519 is_waiting_for_unload_ack_ = true; |
473 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS)); | 520 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS)); |
474 | 521 |
475 if (IsRenderViewLive()) { | 522 if (IsRenderViewLive()) { |
(...skipping 1480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1956 } | 2003 } |
1957 | 2004 |
1958 void RenderViewHostImpl::SetSwappedOut(bool is_swapped_out) { | 2005 void RenderViewHostImpl::SetSwappedOut(bool is_swapped_out) { |
1959 is_swapped_out_ = is_swapped_out; | 2006 is_swapped_out_ = is_swapped_out; |
1960 | 2007 |
1961 // Whenever we change swap out state, we should not be waiting for | 2008 // Whenever we change swap out state, we should not be waiting for |
1962 // beforeunload or unload acks. We clear them here to be safe, since they | 2009 // beforeunload or unload acks. We clear them here to be safe, since they |
1963 // can cause navigations to be ignored in OnMsgNavigate. | 2010 // can cause navigations to be ignored in OnMsgNavigate. |
1964 is_waiting_for_beforeunload_ack_ = false; | 2011 is_waiting_for_beforeunload_ack_ = false; |
1965 is_waiting_for_unload_ack_ = false; | 2012 is_waiting_for_unload_ack_ = false; |
| 2013 has_timed_out_on_unload_ = false; |
1966 } | 2014 } |
1967 | 2015 |
1968 void RenderViewHostImpl::ClearPowerSaveBlockers() { | 2016 void RenderViewHostImpl::ClearPowerSaveBlockers() { |
1969 STLDeleteValues(&power_save_blockers_); | 2017 STLDeleteValues(&power_save_blockers_); |
1970 } | 2018 } |
1971 | 2019 |
1972 } // namespace content | 2020 } // namespace content |
OLD | NEW |