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

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

Issue 659773002: New histogram to track overhead time spent around beforeunload event + fixes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed CR comments Created 6 years, 1 month 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
« no previous file with comments | « content/browser/frame_host/navigator_impl.cc ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/containers/hash_tables.h" 9 #include "base/containers/hash_tables.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 700
701 // If we're waiting for a cross-site beforeunload ack from this renderer and 701 // If we're waiting for a cross-site beforeunload ack from this renderer and
702 // we receive a Navigate message from the main frame, then the renderer was 702 // we receive a Navigate message from the main frame, then the renderer was
703 // navigating already and sent it before hearing the FrameMsg_Stop message. 703 // navigating already and sent it before hearing the FrameMsg_Stop message.
704 // We do not want to cancel the pending navigation in this case, since the 704 // We do not want to cancel the pending navigation in this case, since the
705 // old page will soon be stopped. Instead, treat this as a beforeunload ack 705 // old page will soon be stopped. Instead, treat this as a beforeunload ack
706 // to allow the pending navigation to continue. 706 // to allow the pending navigation to continue.
707 if (is_waiting_for_beforeunload_ack_ && 707 if (is_waiting_for_beforeunload_ack_ &&
708 unload_ack_is_for_cross_site_transition_ && 708 unload_ack_is_for_cross_site_transition_ &&
709 ui::PageTransitionIsMainFrame(validated_params.transition)) { 709 ui::PageTransitionIsMainFrame(validated_params.transition)) {
710 OnBeforeUnloadACK(true, send_before_unload_start_time_, 710 base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
carlosk 2014/10/21 13:07:09 I'm making this copy because it was unsafe to pass
Charlie Reis 2014/10/21 18:21:48 "Could be reset anytime" doesn't seem relevant her
carlosk 2014/10/22 09:08:56 Yeah I agree with that: it isn't really required.
711 base::TimeTicks::Now()); 711 OnBeforeUnloadACK(true, approx_renderer_start_time, base::TimeTicks::Now());
712 return; 712 return;
713 } 713 }
714 714
715 // If we're waiting for an unload ack from this renderer and we receive a 715 // If we're waiting for an unload ack from this renderer and we receive a
716 // Navigate message, then the renderer was navigating before it received the 716 // Navigate message, then the renderer was navigating before it received the
717 // unload request. It will either respond to the unload request soon or our 717 // unload request. It will either respond to the unload request soon or our
718 // timer will expire. Either way, we should ignore this message, because we 718 // timer will expire. Either way, we should ignore this message, because we
719 // have already committed to closing this renderer. 719 // have already committed to closing this renderer.
720 if (IsWaitingForUnloadACK()) 720 if (IsWaitingForUnloadACK())
721 return; 721 return;
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 if (!GetParent()) 823 if (!GetParent())
824 delegate_->SwappedOut(this); 824 delegate_->SwappedOut(this);
825 } 825 }
826 826
827 void RenderFrameHostImpl::OnBeforeUnloadACK( 827 void RenderFrameHostImpl::OnBeforeUnloadACK(
828 bool proceed, 828 bool proceed,
829 const base::TimeTicks& renderer_before_unload_start_time, 829 const base::TimeTicks& renderer_before_unload_start_time,
830 const base::TimeTicks& renderer_before_unload_end_time) { 830 const base::TimeTicks& renderer_before_unload_end_time) {
831 TRACE_EVENT_ASYNC_END0( 831 TRACE_EVENT_ASYNC_END0(
832 "navigation", "RenderFrameHostImpl::BeforeUnload", this); 832 "navigation", "RenderFrameHostImpl::BeforeUnload", this);
833 // TODO(creis): Support beforeunload on subframes. For now just pretend that 833 DCHECK(!GetParent());
834 // the handler ran and allowed the navigation to proceed.
835 if (GetParent()) {
836 is_waiting_for_beforeunload_ack_ = false;
837 frame_tree_node_->render_manager()->OnBeforeUnloadACK(
838 unload_ack_is_for_cross_site_transition_, proceed,
839 renderer_before_unload_end_time);
840 return;
841 }
842
843 render_view_host_->decrement_in_flight_event_count(); 834 render_view_host_->decrement_in_flight_event_count();
844 render_view_host_->StopHangMonitorTimeout(); 835 render_view_host_->StopHangMonitorTimeout();
845 // If this renderer navigated while the beforeunload request was in flight, we 836 // If this renderer navigated while the beforeunload request was in flight, we
846 // may have cleared this state in OnDidCommitProvisionalLoad, in which case we 837 // may have cleared this state in OnDidCommitProvisionalLoad, in which case we
847 // can ignore this message. 838 // can ignore this message.
848 // However renderer might also be swapped out but we still want to proceed 839 // However renderer might also be swapped out but we still want to proceed
849 // with navigation, otherwise it would block future navigations. This can 840 // with navigation, otherwise it would block future navigations. This can
850 // happen when pending cross-site navigation is canceled by a second one just 841 // happen when pending cross-site navigation is canceled by a second one just
851 // before OnDidCommitProvisionalLoad while current RVH is waiting for commit 842 // before OnDidCommitProvisionalLoad while current RVH is waiting for commit
852 // but second navigation is started from the beginning. 843 // but second navigation is started from the beginning.
853 if (!is_waiting_for_beforeunload_ack_) { 844 if (!is_waiting_for_beforeunload_ack_) {
854 return; 845 return;
855 } 846 }
847 DCHECK(!send_before_unload_start_time_.is_null());
856 848
857 is_waiting_for_beforeunload_ack_ = false; 849 // Sets a default value for before_unload_end_time so that the browser
858 850 // survives a hacked renderer.
859 base::TimeTicks before_unload_end_time; 851 base::TimeTicks before_unload_end_time = renderer_before_unload_end_time;
carlosk 2014/10/21 13:07:09 So finally, this initialization was not the correc
860 if (!send_before_unload_start_time_.is_null() && 852 if (!renderer_before_unload_start_time.is_null() &&
861 !renderer_before_unload_start_time.is_null() &&
862 !renderer_before_unload_end_time.is_null()) { 853 !renderer_before_unload_end_time.is_null()) {
863 // When passing TimeTicks across process boundaries, we need to compensate 854 // When passing TimeTicks across process boundaries, we need to compensate
864 // for any skew between the processes. Here we are converting the 855 // for any skew between the processes. Here we are converting the
865 // renderer's notion of before_unload_end_time to TimeTicks in the browser 856 // renderer's notion of before_unload_end_time to TimeTicks in the browser
866 // process. See comments in inter_process_time_ticks_converter.h for more. 857 // process. See comments in inter_process_time_ticks_converter.h for more.
858 base::TimeTicks receive_before_unload_ack_time = base::TimeTicks::Now();
867 InterProcessTimeTicksConverter converter( 859 InterProcessTimeTicksConverter converter(
868 LocalTimeTicks::FromTimeTicks(send_before_unload_start_time_), 860 LocalTimeTicks::FromTimeTicks(send_before_unload_start_time_),
869 LocalTimeTicks::FromTimeTicks(base::TimeTicks::Now()), 861 LocalTimeTicks::FromTimeTicks(receive_before_unload_ack_time),
870 RemoteTimeTicks::FromTimeTicks(renderer_before_unload_start_time), 862 RemoteTimeTicks::FromTimeTicks(renderer_before_unload_start_time),
871 RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time)); 863 RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
872 LocalTimeTicks browser_before_unload_end_time = 864 LocalTimeTicks browser_before_unload_end_time =
873 converter.ToLocalTimeTicks( 865 converter.ToLocalTimeTicks(
874 RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time)); 866 RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
875 before_unload_end_time = browser_before_unload_end_time.ToTimeTicks(); 867 before_unload_end_time = browser_before_unload_end_time.ToTimeTicks();
876 868
877 // Collect UMA on the inter-process skew. 869 // Collect UMA on the inter-process skew.
878 bool is_skew_additive = false; 870 bool is_skew_additive = false;
879 if (converter.IsSkewAdditiveForMetrics()) { 871 if (converter.IsSkewAdditiveForMetrics()) {
880 is_skew_additive = true; 872 is_skew_additive = true;
881 base::TimeDelta skew = converter.GetSkewForMetrics(); 873 base::TimeDelta skew = converter.GetSkewForMetrics();
882 if (skew >= base::TimeDelta()) { 874 if (skew >= base::TimeDelta()) {
883 UMA_HISTOGRAM_TIMES( 875 UMA_HISTOGRAM_TIMES(
884 "InterProcessTimeTicks.BrowserBehind_RendererToBrowser", skew); 876 "InterProcessTimeTicks.BrowserBehind_RendererToBrowser", skew);
885 } else { 877 } else {
886 UMA_HISTOGRAM_TIMES( 878 UMA_HISTOGRAM_TIMES(
887 "InterProcessTimeTicks.BrowserAhead_RendererToBrowser", -skew); 879 "InterProcessTimeTicks.BrowserAhead_RendererToBrowser", -skew);
888 } 880 }
889 } 881 }
890 UMA_HISTOGRAM_BOOLEAN( 882 UMA_HISTOGRAM_BOOLEAN(
891 "InterProcessTimeTicks.IsSkewAdditive_RendererToBrowser", 883 "InterProcessTimeTicks.IsSkewAdditive_RendererToBrowser",
892 is_skew_additive); 884 is_skew_additive);
893 885
886 base::TimeDelta on_before_unload_overhead_time =
887 (receive_before_unload_ack_time - send_before_unload_start_time_) -
888 (renderer_before_unload_end_time - renderer_before_unload_start_time);
889 UMA_HISTOGRAM_TIMES("Navigation.OnBeforeUnloadOverheadTime",
890 on_before_unload_overhead_time);
891
894 frame_tree_node_->navigator()->LogBeforeUnloadTime( 892 frame_tree_node_->navigator()->LogBeforeUnloadTime(
895 renderer_before_unload_start_time, renderer_before_unload_end_time); 893 renderer_before_unload_start_time, renderer_before_unload_end_time);
896 } 894 }
895 // Resets beforeunload waiting state.
Charlie Reis 2014/10/21 18:21:48 nit: There should have been a blank line before th
carlosk 2014/10/22 09:08:56 Acknowledged.
896 is_waiting_for_beforeunload_ack_ = false;
897 send_before_unload_start_time_ = base::TimeTicks();
carlosk 2014/10/21 13:07:09 I moved the state reset down here so that both var
Charlie Reis 2014/10/21 18:21:48 Acknowledged.
898
897 frame_tree_node_->render_manager()->OnBeforeUnloadACK( 899 frame_tree_node_->render_manager()->OnBeforeUnloadACK(
898 unload_ack_is_for_cross_site_transition_, proceed, 900 unload_ack_is_for_cross_site_transition_, proceed,
899 before_unload_end_time); 901 before_unload_end_time);
900 902
901 // If canceled, notify the delegate to cancel its pending navigation entry. 903 // If canceled, notify the delegate to cancel its pending navigation entry.
902 if (!proceed) 904 if (!proceed)
903 render_view_host_->GetDelegate()->DidCancelLoading(); 905 render_view_host_->GetDelegate()->DidCancelLoading();
904 } 906 }
905 907
906 bool RenderFrameHostImpl::IsWaitingForUnloadACK() const { 908 bool RenderFrameHostImpl::IsWaitingForUnloadACK() const {
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
1217 // Whenever we change the RFH state to and from active or swapped out state, 1219 // Whenever we change the RFH state to and from active or swapped out state,
1218 // we should not be waiting for beforeunload or close acks. We clear them 1220 // we should not be waiting for beforeunload or close acks. We clear them
1219 // here to be safe, since they can cause navigations to be ignored in 1221 // here to be safe, since they can cause navigations to be ignored in
1220 // OnDidCommitProvisionalLoad. 1222 // OnDidCommitProvisionalLoad.
1221 // TODO(creis): Move is_waiting_for_beforeunload_ack_ into the state machine. 1223 // TODO(creis): Move is_waiting_for_beforeunload_ack_ into the state machine.
1222 if (rfh_state == STATE_DEFAULT || 1224 if (rfh_state == STATE_DEFAULT ||
1223 rfh_state == STATE_SWAPPED_OUT || 1225 rfh_state == STATE_SWAPPED_OUT ||
1224 rfh_state_ == STATE_DEFAULT || 1226 rfh_state_ == STATE_DEFAULT ||
1225 rfh_state_ == STATE_SWAPPED_OUT) { 1227 rfh_state_ == STATE_SWAPPED_OUT) {
1226 is_waiting_for_beforeunload_ack_ = false; 1228 is_waiting_for_beforeunload_ack_ = false;
1229 send_before_unload_start_time_ = base::TimeTicks();
1227 render_view_host_->is_waiting_for_close_ack_ = false; 1230 render_view_host_->is_waiting_for_close_ack_ = false;
1228 } 1231 }
1229 rfh_state_ = rfh_state; 1232 rfh_state_ = rfh_state;
1230 } 1233 }
1231 1234
1232 bool RenderFrameHostImpl::CanCommitURL(const GURL& url) { 1235 bool RenderFrameHostImpl::CanCommitURL(const GURL& url) {
1233 // TODO(creis): We should also check for WebUI pages here. Also, when the 1236 // TODO(creis): We should also check for WebUI pages here. Also, when the
1234 // out-of-process iframes implementation is ready, we should check for 1237 // out-of-process iframes implementation is ready, we should check for
1235 // cross-site URLs that are not allowed to commit in this process. 1238 // cross-site URLs that are not allowed to commit in this process.
1236 1239
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1301 1304
1302 void RenderFrameHostImpl::OpenURL(const FrameHostMsg_OpenURL_Params& params) { 1305 void RenderFrameHostImpl::OpenURL(const FrameHostMsg_OpenURL_Params& params) {
1303 OnOpenURL(params); 1306 OnOpenURL(params);
1304 } 1307 }
1305 1308
1306 void RenderFrameHostImpl::Stop() { 1309 void RenderFrameHostImpl::Stop() {
1307 Send(new FrameMsg_Stop(routing_id_)); 1310 Send(new FrameMsg_Stop(routing_id_));
1308 } 1311 }
1309 1312
1310 void RenderFrameHostImpl::DispatchBeforeUnload(bool for_cross_site_transition) { 1313 void RenderFrameHostImpl::DispatchBeforeUnload(bool for_cross_site_transition) {
1314 // TODO(creis): Support beforeunload on subframes. For now just pretend that
1315 // the handler ran and allowed the navigation to proceed.
1316 if (GetParent() || !IsRenderFrameLive()) {
1317 // We don't have a live renderer, so just skip running beforeunload.
1318 frame_tree_node_->render_manager()->OnBeforeUnloadACK(
1319 for_cross_site_transition, true, base::TimeTicks::Now());
1320 return;
1321 }
1311 TRACE_EVENT_ASYNC_BEGIN0( 1322 TRACE_EVENT_ASYNC_BEGIN0(
1312 "navigation", "RenderFrameHostImpl::BeforeUnload", this); 1323 "navigation", "RenderFrameHostImpl::BeforeUnload", this);
1313 // TODO(creis): Support subframes.
1314 if (GetParent() || !IsRenderFrameLive()) {
1315 // We don't have a live renderer, so just skip running beforeunload.
1316 is_waiting_for_beforeunload_ack_ = true;
1317 unload_ack_is_for_cross_site_transition_ = for_cross_site_transition;
1318 base::TimeTicks now = base::TimeTicks::Now();
1319 OnBeforeUnloadACK(true, now, now);
1320 return;
1321 }
1322 1324
1323 // This may be called more than once (if the user clicks the tab close button 1325 // This may be called more than once (if the user clicks the tab close button
1324 // several times, or if she clicks the tab close button then the browser close 1326 // several times, or if she clicks the tab close button then the browser close
1325 // button), and we only send the message once. 1327 // button), and we only send the message once.
1326 if (is_waiting_for_beforeunload_ack_) { 1328 if (is_waiting_for_beforeunload_ack_) {
1327 // Some of our close messages could be for the tab, others for cross-site 1329 // Some of our close messages could be for the tab, others for cross-site
1328 // transitions. We always want to think it's for closing the tab if any 1330 // transitions. We always want to think it's for closing the tab if any
1329 // of the messages were, since otherwise it might be impossible to close 1331 // of the messages were, since otherwise it might be impossible to close
1330 // (if there was a cross-site "close" request pending when the user clicked 1332 // (if there was a cross-site "close" request pending when the user clicked
1331 // the close button). We want to keep the "for cross site" flag only if 1333 // the close button). We want to keep the "for cross site" flag only if
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
1562 // Clear any state if a pending navigation is canceled or preempted. 1564 // Clear any state if a pending navigation is canceled or preempted.
1563 if (suspended_nav_params_) 1565 if (suspended_nav_params_)
1564 suspended_nav_params_.reset(); 1566 suspended_nav_params_.reset();
1565 1567
1566 TRACE_EVENT_ASYNC_END0("navigation", 1568 TRACE_EVENT_ASYNC_END0("navigation",
1567 "RenderFrameHostImpl navigation suspended", this); 1569 "RenderFrameHostImpl navigation suspended", this);
1568 navigations_suspended_ = false; 1570 navigations_suspended_ = false;
1569 } 1571 }
1570 1572
1571 } // namespace content 1573 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/frame_host/navigator_impl.cc ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698