Commit e463483d authored by Annie Sullivan's avatar Annie Sullivan Committed by Commit Bot

Add input timestamps to scheduled reload, redirect and form submit.

This will ensure that the InputToFirstContentfulPaint metric tracks
the full latency when these navigations are initiated via user input.

This will also make it easier to debug which types of loads from the
renderer are NOT counted as being from user input in a follow up CL.

Bug: 889220
Change-Id: I2ae48b5ca9d6230c15a4291d03b64945d312f802
Reviewed-on: https://chromium-review.googlesource.com/c/1258242
Commit-Queue: Annie Sullivan <sullivan@chromium.org>
Reviewed-by: default avatarSteve Kobes <skobes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596481}
parent 0c9a9c5d
...@@ -73,11 +73,14 @@ class ScheduledURLNavigation : public ScheduledNavigation { ...@@ -73,11 +73,14 @@ class ScheduledURLNavigation : public ScheduledNavigation {
WebFrameLoadType frame_load_type, WebFrameLoadType frame_load_type,
bool is_location_change, bool is_location_change,
base::TimeTicks input_timestamp) base::TimeTicks input_timestamp)
: ScheduledNavigation(reason, delay, origin_document, is_location_change), : ScheduledNavigation(reason,
delay,
origin_document,
is_location_change,
input_timestamp),
url_(url), url_(url),
should_check_main_world_content_security_policy_( should_check_main_world_content_security_policy_(
kCheckContentSecurityPolicy), kCheckContentSecurityPolicy),
input_timestamp_(input_timestamp),
frame_load_type_(frame_load_type) { frame_load_type_(frame_load_type) {
if (ContentSecurityPolicy::ShouldBypassMainWorld(origin_document)) { if (ContentSecurityPolicy::ShouldBypassMainWorld(origin_document)) {
should_check_main_world_content_security_policy_ = should_check_main_world_content_security_policy_ =
...@@ -97,9 +100,7 @@ class ScheduledURLNavigation : public ScheduledNavigation { ...@@ -97,9 +100,7 @@ class ScheduledURLNavigation : public ScheduledNavigation {
FrameLoadRequest request(OriginDocument(), ResourceRequest(url_), "_self", FrameLoadRequest request(OriginDocument(), ResourceRequest(url_), "_self",
should_check_main_world_content_security_policy_); should_check_main_world_content_security_policy_);
request.SetClientRedirect(ClientRedirectPolicy::kClientRedirect); request.SetClientRedirect(ClientRedirectPolicy::kClientRedirect);
if (!input_timestamp_.is_null()) { request.SetInputStartTime(InputTimestamp());
request.SetInputStartTime(input_timestamp_);
}
if (blob_url_token_) { if (blob_url_token_) {
mojom::blink::BlobURLTokenPtr token_clone; mojom::blink::BlobURLTokenPtr token_clone;
...@@ -119,7 +120,6 @@ class ScheduledURLNavigation : public ScheduledNavigation { ...@@ -119,7 +120,6 @@ class ScheduledURLNavigation : public ScheduledNavigation {
mojom::blink::BlobURLTokenPtr blob_url_token_; mojom::blink::BlobURLTokenPtr blob_url_token_;
ContentSecurityPolicyDisposition ContentSecurityPolicyDisposition
should_check_main_world_content_security_policy_; should_check_main_world_content_security_policy_;
base::TimeTicks input_timestamp_;
WebFrameLoadType frame_load_type_; WebFrameLoadType frame_load_type_;
}; };
...@@ -129,9 +129,10 @@ class ScheduledRedirect final : public ScheduledURLNavigation { ...@@ -129,9 +129,10 @@ class ScheduledRedirect final : public ScheduledURLNavigation {
Document* origin_document, Document* origin_document,
const KURL& url, const KURL& url,
Document::HttpRefreshType http_refresh_type, Document::HttpRefreshType http_refresh_type,
WebFrameLoadType frame_load_type) { WebFrameLoadType frame_load_type,
base::TimeTicks input_timestamp) {
return new ScheduledRedirect(delay, origin_document, url, http_refresh_type, return new ScheduledRedirect(delay, origin_document, url, http_refresh_type,
frame_load_type); frame_load_type, input_timestamp);
} }
bool ShouldStartTimer(LocalFrame* frame) override { bool ShouldStartTimer(LocalFrame* frame) override {
...@@ -142,6 +143,7 @@ class ScheduledRedirect final : public ScheduledURLNavigation { ...@@ -142,6 +143,7 @@ class ScheduledRedirect final : public ScheduledURLNavigation {
std::unique_ptr<UserGestureIndicator> gesture_indicator = std::unique_ptr<UserGestureIndicator> gesture_indicator =
CreateUserGestureIndicator(); CreateUserGestureIndicator();
FrameLoadRequest request(OriginDocument(), ResourceRequest(Url()), "_self"); FrameLoadRequest request(OriginDocument(), ResourceRequest(Url()), "_self");
request.SetInputStartTime(InputTimestamp());
WebFrameLoadType load_type = LoadType(); WebFrameLoadType load_type = LoadType();
if (EqualIgnoringFragmentIdentifier(frame->GetDocument()->Url(), if (EqualIgnoringFragmentIdentifier(frame->GetDocument()->Url(),
request.GetResourceRequest().Url())) { request.GetResourceRequest().Url())) {
...@@ -171,14 +173,15 @@ class ScheduledRedirect final : public ScheduledURLNavigation { ...@@ -171,14 +173,15 @@ class ScheduledRedirect final : public ScheduledURLNavigation {
Document* origin_document, Document* origin_document,
const KURL& url, const KURL& url,
Document::HttpRefreshType http_refresh_type, Document::HttpRefreshType http_refresh_type,
WebFrameLoadType frame_load_type) WebFrameLoadType frame_load_type,
base::TimeTicks input_timestamp)
: ScheduledURLNavigation(ToReason(http_refresh_type), : ScheduledURLNavigation(ToReason(http_refresh_type),
delay, delay,
origin_document, origin_document,
url, url,
frame_load_type, frame_load_type,
false, false,
base::TimeTicks()) { input_timestamp) {
ClearUserGesture(); ClearUserGesture();
} }
}; };
...@@ -209,8 +212,9 @@ class ScheduledFrameNavigation final : public ScheduledURLNavigation { ...@@ -209,8 +212,9 @@ class ScheduledFrameNavigation final : public ScheduledURLNavigation {
class ScheduledReload final : public ScheduledNavigation { class ScheduledReload final : public ScheduledNavigation {
public: public:
static ScheduledReload* Create(LocalFrame* frame) { static ScheduledReload* Create(LocalFrame* frame,
return new ScheduledReload(frame); base::TimeTicks input_timestamp) {
return new ScheduledReload(frame, input_timestamp);
} }
void Fire(LocalFrame* frame) override { void Fire(LocalFrame* frame) override {
...@@ -222,6 +226,7 @@ class ScheduledReload final : public ScheduledNavigation { ...@@ -222,6 +226,7 @@ class ScheduledReload final : public ScheduledNavigation {
return; return;
FrameLoadRequest request = FrameLoadRequest(nullptr, resource_request); FrameLoadRequest request = FrameLoadRequest(nullptr, resource_request);
request.SetClientRedirect(ClientRedirectPolicy::kClientRedirect); request.SetClientRedirect(ClientRedirectPolicy::kClientRedirect);
request.SetInputStartTime(InputTimestamp());
frame->Loader().StartNavigation(request, WebFrameLoadType::kReload); frame->Loader().StartNavigation(request, WebFrameLoadType::kReload);
} }
...@@ -233,11 +238,12 @@ class ScheduledReload final : public ScheduledNavigation { ...@@ -233,11 +238,12 @@ class ScheduledReload final : public ScheduledNavigation {
} }
private: private:
explicit ScheduledReload(LocalFrame* frame) explicit ScheduledReload(LocalFrame* frame, base::TimeTicks input_timestamp)
: ScheduledNavigation(Reason::kReload, : ScheduledNavigation(Reason::kReload,
0.0, 0.0,
nullptr /*origin_document */, nullptr /*origin_document */,
true), true,
input_timestamp),
frame_(frame) { frame_(frame) {
DCHECK(frame->GetDocument()); DCHECK(frame->GetDocument());
} }
...@@ -262,7 +268,8 @@ class ScheduledPageBlock final : public ScheduledNavigation { ...@@ -262,7 +268,8 @@ class ScheduledPageBlock final : public ScheduledNavigation {
: ScheduledNavigation(Reason::kPageBlock, : ScheduledNavigation(Reason::kPageBlock,
0.0, 0.0,
origin_document, origin_document,
true), true,
base::TimeTicks() /* input_timestamp */),
reason_(reason) {} reason_(reason) {}
int reason_; int reason_;
...@@ -272,8 +279,10 @@ class ScheduledFormSubmission final : public ScheduledNavigation { ...@@ -272,8 +279,10 @@ class ScheduledFormSubmission final : public ScheduledNavigation {
public: public:
static ScheduledFormSubmission* Create(Document* document, static ScheduledFormSubmission* Create(Document* document,
FormSubmission* submission, FormSubmission* submission,
WebFrameLoadType frame_load_type) { WebFrameLoadType frame_load_type,
return new ScheduledFormSubmission(document, submission, frame_load_type); base::TimeTicks input_timestamp) {
return new ScheduledFormSubmission(document, submission, frame_load_type,
input_timestamp);
} }
void Fire(LocalFrame* frame) override { void Fire(LocalFrame* frame) override {
...@@ -281,6 +290,7 @@ class ScheduledFormSubmission final : public ScheduledNavigation { ...@@ -281,6 +290,7 @@ class ScheduledFormSubmission final : public ScheduledNavigation {
CreateUserGestureIndicator(); CreateUserGestureIndicator();
FrameLoadRequest frame_request = FrameLoadRequest frame_request =
submission_->CreateFrameLoadRequest(OriginDocument()); submission_->CreateFrameLoadRequest(OriginDocument());
frame_request.SetInputStartTime(InputTimestamp());
frame->Loader().StartNavigation(frame_request, frame_load_type_, frame->Loader().StartNavigation(frame_request, frame_load_type_,
submission_->GetNavigationPolicy()); submission_->GetNavigationPolicy());
} }
...@@ -295,13 +305,15 @@ class ScheduledFormSubmission final : public ScheduledNavigation { ...@@ -295,13 +305,15 @@ class ScheduledFormSubmission final : public ScheduledNavigation {
private: private:
ScheduledFormSubmission(Document* document, ScheduledFormSubmission(Document* document,
FormSubmission* submission, FormSubmission* submission,
WebFrameLoadType frame_load_type) WebFrameLoadType frame_load_type,
base::TimeTicks input_timestamp)
: ScheduledNavigation(submission->Method() == FormSubmission::kGetMethod : ScheduledNavigation(submission->Method() == FormSubmission::kGetMethod
? Reason::kFormSubmissionGet ? Reason::kFormSubmissionGet
: Reason::kFormSubmissionPost, : Reason::kFormSubmissionPost,
0, 0,
document, document,
true), true,
input_timestamp),
submission_(submission), submission_(submission),
frame_load_type_(frame_load_type) { frame_load_type_(frame_load_type) {
DCHECK_NE(submission->Method(), FormSubmission::kDialogMethod); DCHECK_NE(submission->Method(), FormSubmission::kDialogMethod);
...@@ -372,7 +384,8 @@ void NavigationScheduler::ScheduleRedirect( ...@@ -372,7 +384,8 @@ void NavigationScheduler::ScheduleRedirect(
if (delay <= 1) if (delay <= 1)
frame_load_type = WebFrameLoadType::kReplaceCurrentItem; frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
Schedule(ScheduledRedirect::Create(delay, frame_->GetDocument(), url, Schedule(ScheduledRedirect::Create(delay, frame_->GetDocument(), url,
http_refresh_type, frame_load_type)); http_refresh_type, frame_load_type,
InputTimestamp()));
} }
} }
...@@ -394,6 +407,13 @@ bool NavigationScheduler::MustReplaceCurrentItem(LocalFrame* target_frame) { ...@@ -394,6 +407,13 @@ bool NavigationScheduler::MustReplaceCurrentItem(LocalFrame* target_frame) {
!ToLocalFrame(parent_frame)->Loader().AllAncestorsAreComplete(); !ToLocalFrame(parent_frame)->Loader().AllAncestorsAreComplete();
} }
base::TimeTicks NavigationScheduler::InputTimestamp() {
if (const WebInputEvent* input_event = CurrentInputEvent::Get()) {
return input_event->TimeStamp();
}
return base::TimeTicks();
}
void NavigationScheduler::ScheduleFrameNavigation( void NavigationScheduler::ScheduleFrameNavigation(
Document* origin_document, Document* origin_document,
const KURL& url, const KURL& url,
...@@ -401,14 +421,10 @@ void NavigationScheduler::ScheduleFrameNavigation( ...@@ -401,14 +421,10 @@ void NavigationScheduler::ScheduleFrameNavigation(
if (!ShouldScheduleNavigation(url)) if (!ShouldScheduleNavigation(url))
return; return;
base::TimeTicks input_timestamp;
if (const WebInputEvent* input_event = CurrentInputEvent::Get()) {
input_timestamp = input_event->TimeStamp();
}
if (MustReplaceCurrentItem(frame_)) if (MustReplaceCurrentItem(frame_))
frame_load_type = WebFrameLoadType::kReplaceCurrentItem; frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
base::TimeTicks input_timestamp = InputTimestamp();
// If the URL we're going to navigate to is the same as the current one, // If the URL we're going to navigate to is the same as the current one,
// except for the fragment part, we don't need to schedule the location // except for the fragment part, we don't need to schedule the location
// change. We'll skip this optimization for cross-origin navigations to // change. We'll skip this optimization for cross-origin navigations to
...@@ -442,8 +458,8 @@ void NavigationScheduler::ScheduleFormSubmission(Document* document, ...@@ -442,8 +458,8 @@ void NavigationScheduler::ScheduleFormSubmission(Document* document,
WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard;
if (MustReplaceCurrentItem(frame_)) if (MustReplaceCurrentItem(frame_))
frame_load_type = WebFrameLoadType::kReplaceCurrentItem; frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
Schedule( Schedule(ScheduledFormSubmission::Create(document, submission,
ScheduledFormSubmission::Create(document, submission, frame_load_type)); frame_load_type, InputTimestamp()));
} }
void NavigationScheduler::ScheduleReload() { void NavigationScheduler::ScheduleReload() {
...@@ -451,7 +467,7 @@ void NavigationScheduler::ScheduleReload() { ...@@ -451,7 +467,7 @@ void NavigationScheduler::ScheduleReload() {
return; return;
if (frame_->GetDocument()->Url().IsEmpty()) if (frame_->GetDocument()->Url().IsEmpty())
return; return;
Schedule(ScheduledReload::Create(frame_)); Schedule(ScheduledReload::Create(frame_, InputTimestamp()));
} }
void NavigationScheduler::NavigateTask() { void NavigationScheduler::NavigateTask() {
......
...@@ -86,6 +86,7 @@ class CORE_EXPORT NavigationScheduler final ...@@ -86,6 +86,7 @@ class CORE_EXPORT NavigationScheduler final
void Schedule(ScheduledNavigation*); void Schedule(ScheduledNavigation*);
static bool MustReplaceCurrentItem(LocalFrame* target_frame); static bool MustReplaceCurrentItem(LocalFrame* target_frame);
base::TimeTicks InputTimestamp();
Member<LocalFrame> frame_; Member<LocalFrame> frame_;
TaskHandle navigate_task_handle_; TaskHandle navigate_task_handle_;
......
...@@ -15,11 +15,13 @@ namespace blink { ...@@ -15,11 +15,13 @@ namespace blink {
ScheduledNavigation::ScheduledNavigation(Reason reason, ScheduledNavigation::ScheduledNavigation(Reason reason,
double delay, double delay,
Document* origin_document, Document* origin_document,
bool is_location_change) bool is_location_change,
base::TimeTicks input_timestamp)
: reason_(reason), : reason_(reason),
delay_(delay), delay_(delay),
origin_document_(origin_document), origin_document_(origin_document),
is_location_change_(is_location_change) { is_location_change_(is_location_change),
input_timestamp_(input_timestamp) {
if (LocalFrame::HasTransientUserActivation( if (LocalFrame::HasTransientUserActivation(
origin_document ? origin_document->GetFrame() : nullptr)) origin_document ? origin_document->GetFrame() : nullptr))
user_gesture_token_ = UserGestureIndicator::CurrentToken(); user_gesture_token_ = UserGestureIndicator::CurrentToken();
......
...@@ -31,7 +31,8 @@ class ScheduledNavigation ...@@ -31,7 +31,8 @@ class ScheduledNavigation
ScheduledNavigation(Reason, ScheduledNavigation(Reason,
double delay, double delay,
Document* origin_document, Document* origin_document,
bool is_location_change); bool is_location_change,
base::TimeTicks input_timestamp);
virtual ~ScheduledNavigation(); virtual ~ScheduledNavigation();
virtual void Fire(LocalFrame*) = 0; virtual void Fire(LocalFrame*) = 0;
...@@ -45,6 +46,7 @@ class ScheduledNavigation ...@@ -45,6 +46,7 @@ class ScheduledNavigation
Document* OriginDocument() const { return origin_document_.Get(); } Document* OriginDocument() const { return origin_document_.Get(); }
bool IsLocationChange() const { return is_location_change_; } bool IsLocationChange() const { return is_location_change_; }
std::unique_ptr<UserGestureIndicator> CreateUserGestureIndicator(); std::unique_ptr<UserGestureIndicator> CreateUserGestureIndicator();
base::TimeTicks InputTimestamp() const { return input_timestamp_; }
virtual void Trace(blink::Visitor* visitor) { virtual void Trace(blink::Visitor* visitor) {
visitor->Trace(origin_document_); visitor->Trace(origin_document_);
...@@ -59,6 +61,7 @@ class ScheduledNavigation ...@@ -59,6 +61,7 @@ class ScheduledNavigation
Member<Document> origin_document_; Member<Document> origin_document_;
bool is_location_change_; bool is_location_change_;
scoped_refptr<UserGestureToken> user_gesture_token_; scoped_refptr<UserGestureToken> user_gesture_token_;
base::TimeTicks input_timestamp_;
DISALLOW_COPY_AND_ASSIGN(ScheduledNavigation); DISALLOW_COPY_AND_ASSIGN(ScheduledNavigation);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment