Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: content/browser/frame_host/render_frame_host_impl.cc

Issue 2782443002: Revert of Move beforeunload hang timer duties to its own timer.
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/frame_host/render_frame_host_impl.h" 5 #include "content/browser/frame_host/render_frame_host_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 enabled_bindings_ = parent_->GetEnabledBindings(); 369 enabled_bindings_ = parent_->GetEnabledBindings();
370 370
371 // New child frames should inherit the nav_entry_id of their parent. 371 // New child frames should inherit the nav_entry_id of their parent.
372 set_nav_entry_id( 372 set_nav_entry_id(
373 frame_tree_node_->parent()->current_frame_host()->nav_entry_id()); 373 frame_tree_node_->parent()->current_frame_host()->nav_entry_id());
374 } 374 }
375 375
376 SetUpMojoIfNeeded(); 376 SetUpMojoIfNeeded();
377 swapout_event_monitor_timeout_.reset(new TimeoutMonitor(base::Bind( 377 swapout_event_monitor_timeout_.reset(new TimeoutMonitor(base::Bind(
378 &RenderFrameHostImpl::OnSwappedOut, weak_ptr_factory_.GetWeakPtr()))); 378 &RenderFrameHostImpl::OnSwappedOut, weak_ptr_factory_.GetWeakPtr())));
379 beforeunload_timeout_.reset(
380 new TimeoutMonitor(base::Bind(&RenderFrameHostImpl::BeforeUnloadTimeout,
381 weak_ptr_factory_.GetWeakPtr())));
382 379
383 if (widget_routing_id != MSG_ROUTING_NONE) { 380 if (widget_routing_id != MSG_ROUTING_NONE) {
384 // TODO(avi): Once RenderViewHostImpl has-a RenderWidgetHostImpl, the main 381 // TODO(avi): Once RenderViewHostImpl has-a RenderWidgetHostImpl, the main
385 // render frame should probably start owning the RenderWidgetHostImpl, 382 // render frame should probably start owning the RenderWidgetHostImpl,
386 // so this logic checking for an already existing RWHI should be removed. 383 // so this logic checking for an already existing RWHI should be removed.
387 // https://crbug.com/545684 384 // https://crbug.com/545684
388 render_widget_host_ = 385 render_widget_host_ =
389 RenderWidgetHostImpl::FromID(GetProcess()->GetID(), widget_routing_id); 386 RenderWidgetHostImpl::FromID(GetProcess()->GetID(), widget_routing_id);
390 if (!render_widget_host_) { 387 if (!render_widget_host_) {
391 DCHECK(frame_tree_node->parent()); 388 DCHECK(frame_tree_node->parent());
(...skipping 1085 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 (receive_before_unload_ack_time - send_before_unload_start_time_) - 1474 (receive_before_unload_ack_time - send_before_unload_start_time_) -
1478 (renderer_before_unload_end_time - renderer_before_unload_start_time); 1475 (renderer_before_unload_end_time - renderer_before_unload_start_time);
1479 UMA_HISTOGRAM_TIMES("Navigation.OnBeforeUnloadOverheadTime", 1476 UMA_HISTOGRAM_TIMES("Navigation.OnBeforeUnloadOverheadTime",
1480 on_before_unload_overhead_time); 1477 on_before_unload_overhead_time);
1481 1478
1482 frame_tree_node_->navigator()->LogBeforeUnloadTime( 1479 frame_tree_node_->navigator()->LogBeforeUnloadTime(
1483 renderer_before_unload_start_time, renderer_before_unload_end_time); 1480 renderer_before_unload_start_time, renderer_before_unload_end_time);
1484 } 1481 }
1485 // Resets beforeunload waiting state. 1482 // Resets beforeunload waiting state.
1486 is_waiting_for_beforeunload_ack_ = false; 1483 is_waiting_for_beforeunload_ack_ = false;
1487 beforeunload_timeout_->Stop(); 1484 render_view_host_->GetWidget()->decrement_in_flight_event_count();
1485 render_view_host_->GetWidget()->StopHangMonitorTimeout();
1488 send_before_unload_start_time_ = base::TimeTicks(); 1486 send_before_unload_start_time_ = base::TimeTicks();
1489 1487
1490 // PlzNavigate: if the ACK is for a navigation, send it to the Navigator to 1488 // PlzNavigate: if the ACK is for a navigation, send it to the Navigator to
1491 // have the current navigation stop/proceed. Otherwise, send it to the 1489 // have the current navigation stop/proceed. Otherwise, send it to the
1492 // RenderFrameHostManager which handles closing. 1490 // RenderFrameHostManager which handles closing.
1493 if (IsBrowserSideNavigationEnabled() && unload_ack_is_for_navigation_) { 1491 if (IsBrowserSideNavigationEnabled() && unload_ack_is_for_navigation_) {
1494 // TODO(clamy): see if before_unload_end_time should be transmitted to the 1492 // TODO(clamy): see if before_unload_end_time should be transmitted to the
1495 // Navigator. 1493 // Navigator.
1496 frame_tree_node_->navigator()->OnBeforeUnloadACK( 1494 frame_tree_node_->navigator()->OnBeforeUnloadACK(
1497 frame_tree_node_, proceed); 1495 frame_tree_node_, proceed);
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1699 } 1697 }
1700 1698
1701 void RenderFrameHostImpl::OnRunBeforeUnloadConfirm( 1699 void RenderFrameHostImpl::OnRunBeforeUnloadConfirm(
1702 const GURL& frame_url, 1700 const GURL& frame_url,
1703 bool is_reload, 1701 bool is_reload,
1704 IPC::Message* reply_msg) { 1702 IPC::Message* reply_msg) {
1705 // While a JS beforeunload dialog is showing, tabs in the same process 1703 // While a JS beforeunload dialog is showing, tabs in the same process
1706 // shouldn't process input events. 1704 // shouldn't process input events.
1707 GetProcess()->SetIgnoreInputEvents(true); 1705 GetProcess()->SetIgnoreInputEvents(true);
1708 render_view_host_->GetWidget()->StopHangMonitorTimeout(); 1706 render_view_host_->GetWidget()->StopHangMonitorTimeout();
1709
1710 // The beforeunload dialog for this frame may have been triggered by a
1711 // browser-side request to this frame or a frame up in the frame hierarchy.
1712 // Stop any timers that are waiting.
1713 for (RenderFrameHostImpl* frame = this; frame; frame = frame->GetParent())
1714 frame->beforeunload_timeout_->Stop();
1715
1716 delegate_->RunBeforeUnloadConfirm(this, is_reload, reply_msg); 1707 delegate_->RunBeforeUnloadConfirm(this, is_reload, reply_msg);
1717 } 1708 }
1718 1709
1719 void RenderFrameHostImpl::OnRunFileChooser(const FileChooserParams& params) { 1710 void RenderFrameHostImpl::OnRunFileChooser(const FileChooserParams& params) {
1720 // Do not allow messages with absolute paths in them as this can permit a 1711 // Do not allow messages with absolute paths in them as this can permit a
1721 // renderer to coerce the browser to perform I/O on a renderer controlled 1712 // renderer to coerce the browser to perform I/O on a renderer controlled
1722 // path. 1713 // path.
1723 if (params.default_file_name != params.default_file_name.BaseName()) { 1714 if (params.default_file_name != params.default_file_name.BaseName()) {
1724 bad_message::ReceivedBadMessage(GetProcess(), 1715 bad_message::ReceivedBadMessage(GetProcess(),
1725 bad_message::RFH_FILE_CHOOSER_PATH); 1716 bad_message::RFH_FILE_CHOOSER_PATH);
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after
2422 } 2413 }
2423 2414
2424 void RenderFrameHostImpl::ResetWaitingState() { 2415 void RenderFrameHostImpl::ResetWaitingState() {
2425 DCHECK(is_active()); 2416 DCHECK(is_active());
2426 2417
2427 // Whenever we reset the RFH state, we should not be waiting for beforeunload 2418 // Whenever we reset the RFH state, we should not be waiting for beforeunload
2428 // or close acks. We clear them here to be safe, since they can cause 2419 // or close acks. We clear them here to be safe, since they can cause
2429 // navigations to be ignored in OnDidCommitProvisionalLoad. 2420 // navigations to be ignored in OnDidCommitProvisionalLoad.
2430 if (is_waiting_for_beforeunload_ack_) { 2421 if (is_waiting_for_beforeunload_ack_) {
2431 is_waiting_for_beforeunload_ack_ = false; 2422 is_waiting_for_beforeunload_ack_ = false;
2432 beforeunload_timeout_->Stop(); 2423 render_view_host_->GetWidget()->decrement_in_flight_event_count();
2424 render_view_host_->GetWidget()->StopHangMonitorTimeout();
2433 } 2425 }
2434 send_before_unload_start_time_ = base::TimeTicks(); 2426 send_before_unload_start_time_ = base::TimeTicks();
2435 render_view_host_->is_waiting_for_close_ack_ = false; 2427 render_view_host_->is_waiting_for_close_ack_ = false;
2436 } 2428 }
2437 2429
2438 bool RenderFrameHostImpl::CanCommitOrigin( 2430 bool RenderFrameHostImpl::CanCommitOrigin(
2439 const url::Origin& origin, 2431 const url::Origin& origin,
2440 const GURL& url) { 2432 const GURL& url) {
2441 // If the --disable-web-security flag is specified, all bets are off and the 2433 // If the --disable-web-security flag is specified, all bets are off and the
2442 // renderer process can send any origin it wishes. 2434 // renderer process can send any origin it wishes.
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
2568 // Start the hang monitor in case the renderer hangs in the beforeunload 2560 // Start the hang monitor in case the renderer hangs in the beforeunload
2569 // handler. 2561 // handler.
2570 is_waiting_for_beforeunload_ack_ = true; 2562 is_waiting_for_beforeunload_ack_ = true;
2571 unload_ack_is_for_navigation_ = for_navigation; 2563 unload_ack_is_for_navigation_ = for_navigation;
2572 if (render_view_host_->GetDelegate()->IsJavaScriptDialogShowing()) { 2564 if (render_view_host_->GetDelegate()->IsJavaScriptDialogShowing()) {
2573 // If there is a JavaScript dialog up, don't bother sending the renderer 2565 // If there is a JavaScript dialog up, don't bother sending the renderer
2574 // the unload event because it is known unresponsive, waiting for the 2566 // the unload event because it is known unresponsive, waiting for the
2575 // reply from the dialog. 2567 // reply from the dialog.
2576 SimulateBeforeUnloadAck(); 2568 SimulateBeforeUnloadAck();
2577 } else { 2569 } else {
2578 beforeunload_timeout_->Start( 2570 // Increment the in-flight event count, to ensure that input events won't
2579 TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS)); 2571 // cancel the timeout timer.
2572 render_view_host_->GetWidget()->increment_in_flight_event_count();
2573 render_view_host_->GetWidget()->StartHangMonitorTimeout(
2574 TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS),
2575 blink::WebInputEvent::Undefined);
2580 send_before_unload_start_time_ = base::TimeTicks::Now(); 2576 send_before_unload_start_time_ = base::TimeTicks::Now();
2581 Send(new FrameMsg_BeforeUnload(routing_id_, is_reload)); 2577 Send(new FrameMsg_BeforeUnload(routing_id_, is_reload));
2582 } 2578 }
2583 } 2579 }
2584 } 2580 }
2585 2581
2586 void RenderFrameHostImpl::SimulateBeforeUnloadAck() { 2582 void RenderFrameHostImpl::SimulateBeforeUnloadAck() {
2587 DCHECK(is_waiting_for_beforeunload_ack_); 2583 DCHECK(is_waiting_for_beforeunload_ack_);
2588 base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_; 2584 base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
2589 OnBeforeUnloadACK(true, approx_renderer_start_time, base::TimeTicks::Now()); 2585 OnBeforeUnloadACK(true, approx_renderer_start_time, base::TimeTicks::Now());
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2634 void RenderFrameHostImpl::DeleteSurroundingTextInCodePoints(int before, 2630 void RenderFrameHostImpl::DeleteSurroundingTextInCodePoints(int before,
2635 int after) { 2631 int after) {
2636 Send(new InputMsg_DeleteSurroundingTextInCodePoints(routing_id_, before, 2632 Send(new InputMsg_DeleteSurroundingTextInCodePoints(routing_id_, before,
2637 after)); 2633 after));
2638 } 2634 }
2639 2635
2640 void RenderFrameHostImpl::JavaScriptDialogClosed( 2636 void RenderFrameHostImpl::JavaScriptDialogClosed(
2641 IPC::Message* reply_msg, 2637 IPC::Message* reply_msg,
2642 bool success, 2638 bool success,
2643 const base::string16& user_input, 2639 const base::string16& user_input,
2640 bool is_before_unload_dialog,
2644 bool dialog_was_suppressed) { 2641 bool dialog_was_suppressed) {
2645 GetProcess()->SetIgnoreInputEvents(false); 2642 GetProcess()->SetIgnoreInputEvents(false);
2646 2643
2644 // If we are executing as part of beforeunload event handling, we don't
2645 // want to use the regular hung_renderer_delay_ms_ if the user has agreed to
2646 // leave the current page. In this case, use the regular timeout value used
2647 // during the beforeunload handling.
2648 if (is_before_unload_dialog) {
2649 render_view_host_->GetWidget()->StartHangMonitorTimeout(
2650 success
2651 ? TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS)
2652 : render_view_host_->GetWidget()->hung_renderer_delay(),
2653 blink::WebInputEvent::Undefined);
2654 }
2655
2647 SendJavaScriptDialogReply(reply_msg, success, user_input); 2656 SendJavaScriptDialogReply(reply_msg, success, user_input);
2648 2657
2649 // If executing as part of beforeunload event handling, there may have been 2658 // If we are waiting for a beforeunload ack and the user has suppressed
2650 // timers stopped in this frame or a frame up in the frame hierarchy. Restart 2659 // messages, kill the tab immediately; a page that's spamming alerts in
2651 // any timers that were stopped in OnRunBeforeUnloadConfirm(). 2660 // onbeforeunload is presumably malicious, so there's no point in continuing
2652 for (RenderFrameHostImpl* frame = this; frame; frame = frame->GetParent()) { 2661 // to run its script and dragging out the process. This must be done after
2653 if (frame->is_waiting_for_beforeunload_ack_) { 2662 // sending the reply since RenderView can't close correctly while waiting for
2654 // If we are waiting for a beforeunload ack and the user has suppressed 2663 // a response.
2655 // messages, kill the tab immediately. A page that's spamming is 2664 if (is_before_unload_dialog && dialog_was_suppressed) {
2656 // presumably malicious, so there's no point in continuing to run its 2665 render_view_host_->GetWidget()->delegate()->RendererUnresponsive(
2657 // script and dragging out the process. 2666 render_view_host_->GetWidget());
2658 if (dialog_was_suppressed) {
2659 frame->SimulateBeforeUnloadAck();
2660 } else {
2661 frame->beforeunload_timeout_->Start(
2662 TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS));
2663 }
2664 }
2665 } 2667 }
2666 } 2668 }
2667 2669
2668 void RenderFrameHostImpl::SendJavaScriptDialogReply( 2670 void RenderFrameHostImpl::SendJavaScriptDialogReply(
2669 IPC::Message* reply_msg, 2671 IPC::Message* reply_msg,
2670 bool success, 2672 bool success,
2671 const base::string16& user_input) { 2673 const base::string16& user_input) {
2672 FrameHostMsg_RunJavaScriptDialog::WriteReplyParams(reply_msg, success, 2674 FrameHostMsg_RunJavaScriptDialog::WriteReplyParams(reply_msg, success,
2673 user_input); 2675 user_input);
2674 Send(reply_msg); 2676 Send(reply_msg);
(...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after
3481 3483
3482 // There is no pending NavigationEntry in these cases, so pass 0 as the 3484 // There is no pending NavigationEntry in these cases, so pass 0 as the
3483 // pending_nav_entry_id. If the previous handle was a prematurely aborted 3485 // pending_nav_entry_id. If the previous handle was a prematurely aborted
3484 // navigation loaded via LoadDataWithBaseURL, propagate the entry id. 3486 // navigation loaded via LoadDataWithBaseURL, propagate the entry id.
3485 return NavigationHandleImpl::Create( 3487 return NavigationHandleImpl::Create(
3486 params.url, params.redirects, frame_tree_node_, is_renderer_initiated, 3488 params.url, params.redirects, frame_tree_node_, is_renderer_initiated,
3487 params.was_within_same_page, base::TimeTicks::Now(), 3489 params.was_within_same_page, base::TimeTicks::Now(),
3488 entry_id_for_data_nav, false); // started_from_context_menu 3490 entry_id_for_data_nav, false); // started_from_context_menu
3489 } 3491 }
3490 3492
3491 void RenderFrameHostImpl::BeforeUnloadTimeout() {
3492 if (render_view_host_->GetDelegate()->ShouldIgnoreUnresponsiveRenderer())
3493 return;
3494
3495 SimulateBeforeUnloadAck();
3496 }
3497
3498 #if defined(OS_ANDROID) 3493 #if defined(OS_ANDROID)
3499 base::android::ScopedJavaLocalRef<jobject> 3494 base::android::ScopedJavaLocalRef<jobject>
3500 RenderFrameHostImpl::GetJavaRenderFrameHost() { 3495 RenderFrameHostImpl::GetJavaRenderFrameHost() {
3501 RenderFrameHostAndroid* render_frame_host_android = 3496 RenderFrameHostAndroid* render_frame_host_android =
3502 static_cast<RenderFrameHostAndroid*>( 3497 static_cast<RenderFrameHostAndroid*>(
3503 GetUserData(kRenderFrameHostAndroidKey)); 3498 GetUserData(kRenderFrameHostAndroidKey));
3504 if (!render_frame_host_android) { 3499 if (!render_frame_host_android) {
3505 render_frame_host_android = new RenderFrameHostAndroid(this); 3500 render_frame_host_android = new RenderFrameHostAndroid(this);
3506 SetUserData(kRenderFrameHostAndroidKey, render_frame_host_android); 3501 SetUserData(kRenderFrameHostAndroidKey, render_frame_host_android);
3507 } 3502 }
3508 return render_frame_host_android->GetJavaObject(); 3503 return render_frame_host_android->GetJavaObject();
3509 } 3504 }
3510 #endif 3505 #endif
3511 3506
3512 } // namespace content 3507 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/frame_host/render_frame_host_impl.h ('k') | content/browser/frame_host/render_frame_host_impl_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698