Index: content/renderer/render_frame_impl.cc |
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc |
index 483608675455914e4ace741ab0db7531516795a2..b9e484c55739a3f9ac56ec39005bd6b56aa92a18 100644 |
--- a/content/renderer/render_frame_impl.cc |
+++ b/content/renderer/render_frame_impl.cc |
@@ -456,23 +456,32 @@ WebURLRequest CreateURLRequestForNavigation( |
return request; |
} |
-void UpdateFrameNavigationTiming(WebFrame* frame, |
- base::TimeTicks browser_navigation_start, |
- base::TimeTicks renderer_navigation_start) { |
+base::TimeTicks SanitizeNavigationTiming( |
+ base::TimeTicks browser_navigation_start) { |
// The browser provides the navigation_start time to bootstrap the |
// Navigation Timing information for the browser-initiated navigations. In |
// case of cross-process navigations, this carries over the time of |
// finishing the onbeforeunload handler of the previous page. |
+ // |browser_navigation_start| is likely before this process existed, so we |
+ // can't use InterProcessTimeTicksConverter. We need at least to ensure |
+ // that the browser-side navigation start we set is not later than the one |
+ // on the renderer side. |
+ base::TimeTicks renderer_navigation_start = base::TimeTicks::Now(); |
DCHECK(!browser_navigation_start.is_null()); |
- if (frame->provisionalDataSource()) { |
- // |browser_navigation_start| is likely before this process existed, so we |
- // can't use InterProcessTimeTicksConverter. We need at least to ensure |
- // that the browser-side navigation start we set is not later than the one |
- // on the renderer side. |
- base::TimeTicks navigation_start = std::min( |
- browser_navigation_start, renderer_navigation_start); |
+ base::TimeTicks navigation_start = |
+ std::min(browser_navigation_start, renderer_navigation_start); |
+ // TODO(csharrison) UMA log: |
+ // |renderer_navigation_start - browser_navigation_start| |
+ return navigation_start; |
+} |
+ |
+// Update the navigation start based on a better value recieved from the |
+// browser. This can be null if the timestamp should not be updated. |
+void UpdateFrameNavigationTiming(WebFrame* frame, |
+ base::TimeTicks updated_navigation_start) { |
+ if (frame->provisionalDataSource() && !updated_navigation_start.is_null()) { |
double navigation_start_seconds = |
- (navigation_start - base::TimeTicks()).InSecondsF(); |
+ (updated_navigation_start - base::TimeTicks()).InSecondsF(); |
frame->provisionalDataSource()->setNavigationStartTime( |
navigation_start_seconds); |
// TODO(clamy): We need to provide additional timing values for the |
@@ -480,10 +489,12 @@ void UpdateFrameNavigationTiming(WebFrame* frame, |
} |
} |
+ |
// PlzNavigate |
CommonNavigationParams MakeCommonNavigationParams( |
blink::WebURLRequest* request, |
- bool should_replace_current_entry) { |
+ bool should_replace_current_entry, |
+ const base::TimeTicks& navigation_start) { |
const RequestExtraData kEmptyData; |
const RequestExtraData* extra_data = |
static_cast<RequestExtraData*>(request->extraData()); |
@@ -507,7 +518,8 @@ CommonNavigationParams MakeCommonNavigationParams( |
return CommonNavigationParams( |
request->url(), referrer, extra_data->transition_type(), |
FrameMsg_Navigate_Type::NORMAL, true, should_replace_current_entry, |
- ui_timestamp, report_type, GURL(), GURL(), LOFI_UNSPECIFIED); |
+ ui_timestamp, report_type, GURL(), GURL(), LOFI_UNSPECIFIED, |
+ navigation_start); |
} |
#if !defined(OS_ANDROID) || defined(ENABLE_MEDIA_PIPELINE_ON_ANDROID) |
@@ -2699,12 +2711,28 @@ void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame, |
->set_transition_type(ui::PAGE_TRANSITION_AUTO_SUBFRAME); |
} |
+ // Get the renderer navigation start in TimeTicks format. This will be |
+ // lossy because blink converts TimeTicks internal int64 representation to a |
+ // double. |
+ DCHECK(ds->getNavigationStartTime()); |
+ base::TimeTicks navigation_start = base::TimeTicks::FromInternalValue( |
+ ds->getNavigationStartTime() * base::Time::kMicrosecondsPerSecond); |
+ // See if we have a better timestamp from a browser initiated navigation. |
+ // If so, override it. This will be propogated to blink after the request has |
+ // been issued. |
+ if (ds->request().extraData()) { |
+ RequestExtraData* extra_data = |
+ static_cast<RequestExtraData*>(ds->request().extraData()); |
+ if (!extra_data->browser_navigation_start().is_null()) |
+ navigation_start = extra_data->browser_navigation_start(); |
+ } |
+ |
FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(), |
DidStartProvisionalLoad(frame)); |
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidStartProvisionalLoad()); |
Send(new FrameHostMsg_DidStartProvisionalLoadForFrame( |
- routing_id_, ds->request().url())); |
+ routing_id_, ds->request().url(), navigation_start)); |
} |
void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad( |
@@ -3352,10 +3380,12 @@ void RenderFrameImpl::willSendRequest( |
WebString custom_user_agent; |
WebString requested_with; |
scoped_ptr<StreamOverrideParameters> stream_override; |
+ base::TimeTicks navigation_start; |
if (request.extraData()) { |
RequestExtraData* old_extra_data = |
static_cast<RequestExtraData*>(request.extraData()); |
+ navigation_start = old_extra_data->browser_navigation_start(); |
custom_user_agent = old_extra_data->custom_user_agent(); |
if (!custom_user_agent.isNull()) { |
if (custom_user_agent.isEmpty()) |
@@ -3450,6 +3480,7 @@ void RenderFrameImpl::willSendRequest( |
navigation_state->start_params().transferred_request_request_id); |
extra_data->set_service_worker_provider_id(provider_id); |
extra_data->set_stream_override(stream_override.Pass()); |
+ extra_data->set_browser_navigation_start(navigation_start); |
if (request.loFiState() != WebURLRequest::LoFiUnspecified) |
extra_data->set_lofi_state(static_cast<LoFiState>(request.loFiState())); |
else if (is_main_frame_ && !navigation_state->request_committed()) |
@@ -4304,10 +4335,8 @@ void RenderFrameImpl::OnFailedNavigation( |
pending_navigation_params_.reset(new NavigationParams( |
common_params, StartNavigationParams(), request_params)); |
- // Inform the browser of the start of the provisional load. This is needed so |
- // that the load is properly tracked by the WebNavigation API. |
Send(new FrameHostMsg_DidStartProvisionalLoadForFrame( |
- routing_id_, common_params.url)); |
+ routing_id_, common_params.url, common_params.navigation_start)); |
// Send the provisional load failure. |
blink::WebURLError error = |
@@ -4649,7 +4678,8 @@ void RenderFrameImpl::NavigateInternal( |
bool should_load_request = false; |
WebHistoryItem item_for_history_navigation; |
WebURLRequest request = CreateURLRequestForNavigation( |
- common_params, stream_params.Pass(), frame_->isViewSourceModeEnabled()); |
+ common_params, stream_params.Pass(), |
+ frame_->isViewSourceModeEnabled()); |
#if defined(OS_ANDROID) |
request.setHasUserGesture(start_params.has_user_gesture); |
#endif |
@@ -4774,9 +4804,13 @@ void RenderFrameImpl::NavigateInternal( |
} |
if (should_load_request) { |
- // Record this before starting the load. We need a lower bound of this |
- // time to sanitize the navigationStart override set below. |
- base::TimeTicks renderer_navigation_start = base::TimeTicks::Now(); |
+ base::TimeTicks updated_navigation_start; |
+ if (load_type == blink::WebFrameLoadType::Standard) { |
+ updated_navigation_start = |
+ SanitizeNavigationTiming(common_params.navigation_start); |
+ static_cast<RequestExtraData*>(request.extraData()) |
+ ->set_browser_navigation_start(updated_navigation_start); |
+ } |
// Perform a navigation to a data url if needed. |
if (!common_params.base_url_for_data_url.is_empty() || |
@@ -4788,12 +4822,8 @@ void RenderFrameImpl::NavigateInternal( |
frame_->toWebLocalFrame()->load(request, load_type, |
item_for_history_navigation); |
} |
- |
- if (load_type == blink::WebFrameLoadType::Standard) { |
- UpdateFrameNavigationTiming(frame_, |
- request_params.browser_navigation_start, |
- renderer_navigation_start); |
- } |
+ // Update the navigationStart value after the request has been made. |
+ UpdateFrameNavigationTiming(frame_, updated_navigation_start); |
} |
// In case LoadRequest failed before didCreateDataSource was called. |
@@ -4984,6 +5014,9 @@ void RenderFrameImpl::BeginNavigation(blink::WebURLRequest* request) { |
// TODO(clamy): Apply devtools override. |
// TODO(clamy): Make sure that navigation requests are not modified somewhere |
// else in blink. |
+ |
+ base::TimeTicks navigation_start = base::TimeTicks::Now(); |
+ |
willSendRequest(frame_, 0, *request, blink::WebURLResponse()); |
// TODO(clamy): Same-document navigations should not be sent back to the |
@@ -5017,8 +5050,8 @@ void RenderFrameImpl::BeginNavigation(blink::WebURLRequest* request) { |
REQUEST_CONTEXT_FRAME_TYPE_NESTED); |
Send(new FrameHostMsg_BeginNavigation( |
- routing_id_, |
- MakeCommonNavigationParams(request, should_replace_current_entry), |
+ routing_id_, MakeCommonNavigationParams( |
+ request, should_replace_current_entry, navigation_start), |
BeginNavigationParams( |
request->httpMethod().latin1(), GetWebURLRequestHeaders(*request), |
GetLoadFlagsForWebURLRequest(*request), request->hasUserGesture(), |