Index: content/renderer/render_frame_impl.cc |
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc |
index a7492bb2d872e90fc04cf365e47c633da40d5260..a3535b105165f5e5965693f03bf1f1f34756faf0 100644 |
--- a/content/renderer/render_frame_impl.cc |
+++ b/content/renderer/render_frame_impl.cc |
@@ -457,34 +457,33 @@ WebURLRequest CreateURLRequestForNavigation( |
return request; |
} |
-void UpdateFrameNavigationTiming(WebFrame* frame, |
- base::TimeTicks browser_navigation_start, |
- base::TimeTicks renderer_navigation_start) { |
+base::TimeTicks SanitizeNavigationTiming( |
+ blink::WebFrameLoadType load_type, |
+ const base::TimeTicks& browser_navigation_start, |
+ const base::TimeTicks& renderer_navigation_start) { |
+ if (load_type != blink::WebFrameLoadType::Standard) |
+ return base::TimeTicks(); |
// 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. |
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); |
- double navigation_start_seconds = |
- (navigation_start - base::TimeTicks()).InSecondsF(); |
- frame->provisionalDataSource()->setNavigationStartTime( |
- navigation_start_seconds); |
- // TODO(clamy): We need to provide additional timing values for the |
- // Navigation Timing API to work with browser-side navigations. |
- } |
+ 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; |
} |
// 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()); |
@@ -508,7 +507,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) |
@@ -2562,12 +2562,18 @@ void RenderFrameImpl::didCreateDataSource(blink::WebLocalFrame* frame, |
} |
} |
+ bool was_same_page = false; |
+ |
DocumentState* document_state = DocumentState::FromDataSource(datasource); |
if (!document_state) { |
document_state = new DocumentState; |
datasource->setExtraData(document_state); |
if (!content_initiated) |
PopulateDocumentStateFromPending(document_state); |
+ } else if(document_state->navigation_state()) { |
+ // We set was_within_same_page in didNavigateWithinPage, to properly |
+ // set navigationStart in blink and update the new NavigationState. |
+ was_same_page = document_state->navigation_state()->WasWithinSamePage(); |
} |
// Carry over the user agent override flag, if it exists. |
@@ -2586,15 +2592,31 @@ void RenderFrameImpl::didCreateDataSource(blink::WebLocalFrame* frame, |
old_internal_data->is_overriding_user_agent()); |
} |
} |
+ // Note for some browser initiated navigations (i.e. not |
+ // WebFrameLoadType::Standard), we want to record their start time now. These |
+ // navigations will have had common_params.navigation_start set to null. |
+ if (!content_initiated && |
+ pending_navigation_params_->common_params.navigation_start.is_null()) { |
+ pending_navigation_params_->common_params.navigation_start = |
+ base::TimeTicks::Now(); |
+ } |
// The rest of RenderView assumes that a WebDataSource will always have a |
// non-null NavigationState. |
- if (content_initiated) { |
- document_state->set_navigation_state( |
- NavigationStateImpl::CreateContentInitiated()); |
- } else { |
- document_state->set_navigation_state(CreateNavigationStateFromPending()); |
- pending_navigation_params_.reset(); |
+ NavigationStateImpl* navigation_state = |
+ content_initiated ? NavigationStateImpl::CreateContentInitiated() |
+ : CreateNavigationStateFromPending(); |
+ pending_navigation_params_.reset(); |
+ document_state->set_navigation_state(navigation_state); |
+ static_cast<NavigationStateImpl*>(document_state->navigation_state()) |
+ ->set_was_within_same_page(was_same_page); |
+ |
+ // Set the navigation start time in blink. |
+ if (!was_same_page) { |
+ base::TimeTicks navigation_start = |
+ navigation_state->common_params().navigation_start; |
+ datasource->setNavigationStartTime( |
+ (navigation_start - base::TimeTicks()).InSecondsF()); |
} |
// DocumentState::referred_by_prefetcher_ is true if we are |
@@ -2652,9 +2674,6 @@ void RenderFrameImpl::didCreateDataSource(blink::WebLocalFrame* frame, |
DocumentState::FromDataSource(datasource))) |
return; |
- NavigationStateImpl* navigation_state = static_cast<NavigationStateImpl*>( |
- DocumentState::FromDataSource(datasource)->navigation_state()); |
- |
ServiceWorkerNetworkProvider::AttachToDocumentState( |
DocumentState::FromDataSource(datasource), |
ServiceWorkerNetworkProvider::CreateForNavigation( |
@@ -2703,12 +2722,20 @@ void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame, |
->set_transition_type(ui::PAGE_TRANSITION_AUTO_SUBFRAME); |
} |
+ // Get the navigation start in TimeTicks format. This will be |
+ // lossy because blink converts TimeTicks internal int64 representation to a |
+ // double. TODO(csharrison) Do we want to override this with the TimeTicks |
+ // timestamp in document_state->navigation_params for browser loads? |
+ DCHECK(ds->getNavigationStartTime()); |
+ base::TimeTicks navigation_start = base::TimeTicks::FromInternalValue( |
+ ds->getNavigationStartTime() * base::Time::kMicrosecondsPerSecond); |
+ |
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( |
@@ -3124,6 +3151,15 @@ void RenderFrameImpl::didNavigateWithinPage(blink::WebLocalFrame* frame, |
TRACE_EVENT1("navigation", "RenderFrameImpl::didNavigateWithinPage", |
"id", routing_id_); |
DCHECK(!frame_ || frame_ == frame); |
+ |
+ DCHECK(frame->dataSource() && frame->dataSource()->extraData()); |
+ // Set was_within_same_page here, so that didCreateDataSource knows not to |
+ // update navigationStart in blink. We propogate the boolean in the newly |
+ // created NavigationState. |
+ DocumentState* document_state = |
+ DocumentState::FromDataSource(frame->dataSource()); |
+ static_cast<NavigationStateImpl*>(document_state->navigation_state()) |
+ ->set_was_within_same_page(true); |
// If this was a reference fragment navigation that we initiated, then we |
// could end up having a non-null pending navigation params. We just need to |
// update the ExtraData on the datasource so that others who read the |
@@ -3132,12 +3168,6 @@ void RenderFrameImpl::didNavigateWithinPage(blink::WebLocalFrame* frame, |
// existing navigation state to a content-initiated navigation state. |
// didCreateDataSource conveniently takes care of this for us. |
didCreateDataSource(frame, frame->dataSource()); |
- |
- DocumentState* document_state = |
- DocumentState::FromDataSource(frame->dataSource()); |
- static_cast<NavigationStateImpl*>(document_state->navigation_state()) |
- ->set_was_within_same_page(true); |
- |
didCommitProvisionalLoad(frame, item, commit_type); |
} |
@@ -4317,7 +4347,7 @@ void RenderFrameImpl::OnFailedNavigation( |
// 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 = |
@@ -4621,6 +4651,8 @@ void RenderFrameImpl::NavigateInternal( |
bool browser_side_navigation = |
base::CommandLine::ForCurrentProcess()->HasSwitch( |
switches::kEnableBrowserSideNavigation); |
+ // Upper bound for browser initiated navigation start time. |
+ base::TimeTicks renderer_navigation_start = base::TimeTicks::Now(); |
bool is_reload = IsReload(common_params.navigation_type); |
bool is_history_navigation = request_params.page_state.IsValid(); |
WebURLRequest::CachePolicy cache_policy = |
@@ -4646,6 +4678,11 @@ void RenderFrameImpl::NavigateInternal( |
pending_navigation_params_.reset( |
new NavigationParams(common_params, start_params, request_params)); |
+ // We don't know for sure that this load type is WebFrameLoadType::Standard. |
+ // For now, set this to null, and update it when we are sure of the right |
+ // value. |
+ pending_navigation_params_->common_params.navigation_start = |
+ base::TimeTicks(); |
// Create parameters for a standard navigation. |
blink::WebFrameLoadType load_type = blink::WebFrameLoadType::Standard; |
@@ -4777,10 +4814,10 @@ 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(); |
- |
+ // Sanitize navigation start now that we know the load_type. |
+ pending_navigation_params_->common_params.navigation_start = |
+ SanitizeNavigationTiming(load_type, common_params.navigation_start, |
+ renderer_navigation_start); |
// Perform a navigation to a data url if needed. |
if (!common_params.base_url_for_data_url.is_empty() || |
(browser_side_navigation && |
@@ -4791,12 +4828,6 @@ 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); |
- } |
} |
// In case LoadRequest failed before didCreateDataSource was called. |
@@ -4987,6 +5018,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 |
@@ -5020,8 +5054,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(), |
@@ -5147,7 +5181,7 @@ void RenderFrameImpl::PopulateDocumentStateFromPending( |
pending_navigation_params_->request_params.can_load_local_resources); |
} |
-NavigationState* RenderFrameImpl::CreateNavigationStateFromPending() { |
+NavigationStateImpl* RenderFrameImpl::CreateNavigationStateFromPending() { |
if (IsBrowserInitiated(pending_navigation_params_.get())) { |
return NavigationStateImpl::CreateBrowserInitiated( |
pending_navigation_params_->common_params, |