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

Side by Side Diff: content/renderer/render_frame_impl.cc

Issue 2103733004: Set navigationStart correctly for all load types. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Don't call beforeunload on empty frames. Created 4 years, 5 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/renderer/render_frame_impl.h" 5 #include "content/renderer/render_frame_impl.h"
6 6
7 #include <map> 7 #include <map>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 // Sanitizes the navigation_start timestamp for browser-initiated navigations, 558 // Sanitizes the navigation_start timestamp for browser-initiated navigations,
559 // where the browser possibly has a better notion of start time than the 559 // where the browser possibly has a better notion of start time than the
560 // renderer. In the case of cross-process navigations, this carries over the 560 // renderer. In the case of cross-process navigations, this carries over the
561 // time of finishing the onbeforeunload handler of the previous page. 561 // time of finishing the onbeforeunload handler of the previous page.
562 // TimeTicks is sometimes not monotonic across processes, and because 562 // TimeTicks is sometimes not monotonic across processes, and because
563 // |browser_navigation_start| is likely before this process existed, 563 // |browser_navigation_start| is likely before this process existed,
564 // InterProcessTimeTicksConverter won't help. The timestamp is sanitized by 564 // InterProcessTimeTicksConverter won't help. The timestamp is sanitized by
565 // clamping it to renderer_navigation_start, initialized earlier in the call 565 // clamping it to renderer_navigation_start, initialized earlier in the call
566 // stack. 566 // stack.
567 base::TimeTicks SanitizeNavigationTiming( 567 base::TimeTicks SanitizeNavigationTiming(
568 blink::WebFrameLoadType load_type,
569 const base::TimeTicks& browser_navigation_start, 568 const base::TimeTicks& browser_navigation_start,
570 const base::TimeTicks& renderer_navigation_start) { 569 const base::TimeTicks& renderer_navigation_start) {
571 if (load_type != blink::WebFrameLoadType::Standard)
572 return base::TimeTicks();
573 DCHECK(!browser_navigation_start.is_null()); 570 DCHECK(!browser_navigation_start.is_null());
574 base::TimeTicks navigation_start = 571 base::TimeTicks navigation_start =
575 std::min(browser_navigation_start, renderer_navigation_start); 572 std::min(browser_navigation_start, renderer_navigation_start);
576 base::TimeDelta difference = 573 base::TimeDelta difference =
577 renderer_navigation_start - browser_navigation_start; 574 renderer_navigation_start - browser_navigation_start;
578 if (difference > base::TimeDelta()) { 575 if (difference > base::TimeDelta()) {
579 UMA_HISTOGRAM_TIMES("Navigation.Start.RendererBrowserDifference.Positive", 576 UMA_HISTOGRAM_TIMES("Navigation.Start.RendererBrowserDifference.Positive",
580 difference); 577 difference);
581 } else { 578 } else {
582 UMA_HISTOGRAM_TIMES("Navigation.Start.RendererBrowserDifference.Negative", 579 UMA_HISTOGRAM_TIMES("Navigation.Start.RendererBrowserDifference.Negative",
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 1053
1057 // RenderFrameImpl ---------------------------------------------------------- 1054 // RenderFrameImpl ----------------------------------------------------------
1058 RenderFrameImpl::RenderFrameImpl(const CreateParams& params) 1055 RenderFrameImpl::RenderFrameImpl(const CreateParams& params)
1059 : frame_(NULL), 1056 : frame_(NULL),
1060 is_main_frame_(true), 1057 is_main_frame_(true),
1061 in_browser_initiated_detach_(false), 1058 in_browser_initiated_detach_(false),
1062 in_frame_tree_(false), 1059 in_frame_tree_(false),
1063 render_view_(params.render_view->AsWeakPtr()), 1060 render_view_(params.render_view->AsWeakPtr()),
1064 routing_id_(params.routing_id), 1061 routing_id_(params.routing_id),
1065 proxy_routing_id_(MSG_ROUTING_NONE), 1062 proxy_routing_id_(MSG_ROUTING_NONE),
1063 did_access_initial_document_(false),
1066 #if defined(ENABLE_PLUGINS) 1064 #if defined(ENABLE_PLUGINS)
1067 plugin_power_saver_helper_(nullptr), 1065 plugin_power_saver_helper_(nullptr),
1068 plugin_find_handler_(nullptr), 1066 plugin_find_handler_(nullptr),
1069 #endif 1067 #endif
1070 cookie_jar_(this), 1068 cookie_jar_(this),
1071 selection_text_offset_(0), 1069 selection_text_offset_(0),
1072 selection_range_(gfx::Range::InvalidRange()), 1070 selection_range_(gfx::Range::InvalidRange()),
1073 handling_select_range_(false), 1071 handling_select_range_(false),
1074 notification_permission_dispatcher_(NULL), 1072 notification_permission_dispatcher_(NULL),
1075 web_user_media_client_(NULL), 1073 web_user_media_client_(NULL),
(...skipping 1673 matching lines...) Expand 10 before | Expand all | Expand 10 after
2749 if (!provider->context()) { 2747 if (!provider->context()) {
2750 // The context can be null when the frame is sandboxed. 2748 // The context can be null when the frame is sandboxed.
2751 return nullptr; 2749 return nullptr;
2752 } 2750 }
2753 return new WebServiceWorkerProviderImpl( 2751 return new WebServiceWorkerProviderImpl(
2754 ChildThreadImpl::current()->thread_safe_sender(), 2752 ChildThreadImpl::current()->thread_safe_sender(),
2755 provider->context()); 2753 provider->context());
2756 } 2754 }
2757 2755
2758 void RenderFrameImpl::didAccessInitialDocument() { 2756 void RenderFrameImpl::didAccessInitialDocument() {
2757 did_access_initial_document_ = true;
2758
2759 // If the request hasn't yet committed, notify the browser process that it is 2759 // If the request hasn't yet committed, notify the browser process that it is
2760 // no longer safe to show the pending URL of the main frame, since a URL spoof 2760 // no longer safe to show the pending URL of the main frame, since a URL spoof
2761 // is now possible. (If the request has committed, the browser already knows.) 2761 // is now possible. (If the request has committed, the browser already knows.)
2762 if (!frame_->parent()) { 2762 if (!frame_->parent()) {
2763 DocumentState* document_state = 2763 DocumentState* document_state =
2764 DocumentState::FromDataSource(frame_->dataSource()); 2764 DocumentState::FromDataSource(frame_->dataSource());
2765 NavigationStateImpl* navigation_state = 2765 NavigationStateImpl* navigation_state =
2766 static_cast<NavigationStateImpl*>(document_state->navigation_state()); 2766 static_cast<NavigationStateImpl*>(document_state->navigation_state());
2767 2767
2768 if (!navigation_state->request_committed()) { 2768 if (!navigation_state->request_committed()) {
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after
3369 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { 3369 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
3370 SendUpdateState(); 3370 SendUpdateState();
3371 } else { 3371 } else {
3372 render_view_->SendUpdateState(); 3372 render_view_->SendUpdateState();
3373 render_view_->history_controller()->UpdateForCommit( 3373 render_view_->history_controller()->UpdateForCommit(
3374 this, item, commit_type, navigation_state->WasWithinSamePage()); 3374 this, item, commit_type, navigation_state->WasWithinSamePage());
3375 } 3375 }
3376 // Update the current history item for this frame (both in default Chrome and 3376 // Update the current history item for this frame (both in default Chrome and
3377 // subframe FrameNavigationEntry modes). 3377 // subframe FrameNavigationEntry modes).
3378 current_history_item_ = item; 3378 current_history_item_ = item;
3379 did_access_initial_document_ = false;
3379 3380
3380 InternalDocumentStateData* internal_data = 3381 InternalDocumentStateData* internal_data =
3381 InternalDocumentStateData::FromDocumentState(document_state); 3382 InternalDocumentStateData::FromDocumentState(document_state);
3382 3383
3383 if (document_state->commit_load_time().is_null()) 3384 if (document_state->commit_load_time().is_null())
3384 document_state->set_commit_load_time(Time::Now()); 3385 document_state->set_commit_load_time(Time::Now());
3385 3386
3386 if (internal_data->must_reset_scroll_and_scale_state()) { 3387 if (internal_data->must_reset_scroll_and_scale_state()) {
3387 render_view_->webview()->resetScrollAndScaleState(); 3388 render_view_->webview()->resetScrollAndScaleState();
3388 internal_data->set_must_reset_scroll_and_scale_state(false); 3389 internal_data->set_must_reset_scroll_and_scale_state(false);
(...skipping 1644 matching lines...) Expand 10 before | Expand all | Expand 10 after
5033 info.navigationType == blink::WebNavigationTypeOther; 5034 info.navigationType == blink::WebNavigationTypeOther;
5034 5035
5035 if (is_fork) { 5036 if (is_fork) {
5036 // Open the URL via the browser, not via WebKit. 5037 // Open the URL via the browser, not via WebKit.
5037 OpenURL(url, IsHttpPost(info.urlRequest), 5038 OpenURL(url, IsHttpPost(info.urlRequest),
5038 GetRequestBodyForWebURLRequest(info.urlRequest), Referrer(), 5039 GetRequestBodyForWebURLRequest(info.urlRequest), Referrer(),
5039 info.defaultPolicy, info.replacesCurrentHistoryItem, false); 5040 info.defaultPolicy, info.replacesCurrentHistoryItem, false);
5040 return blink::WebNavigationPolicyIgnore; 5041 return blink::WebNavigationPolicyIgnore;
5041 } 5042 }
5042 5043
5043 // Execute the BeforeUnload event. If asked not to proceed or the frame is 5044 bool should_dispatch_before_unload =
5044 // destroyed, ignore the navigation. There is no need to execute the 5045 info.defaultPolicy == blink::WebNavigationPolicyCurrentTab &&
5045 // BeforeUnload event during a redirect, since it was already executed at the 5046 // There is no need to execute the BeforeUnload event during a redirect,
5046 // start of the navigation. 5047 // since it was already executed at the start of the navigation.
5047 // PlzNavigate: this is not executed when commiting the navigation. 5048 !is_redirect &&
5048 if (info.defaultPolicy == blink::WebNavigationPolicyCurrentTab && 5049 // PlzNavigate: this should not be executed when commiting the navigation.
5049 !is_redirect && (!IsBrowserSideNavigationEnabled() || 5050 (!IsBrowserSideNavigationEnabled() ||
5050 info.urlRequest.checkForBrowserSideNavigation())) { 5051 info.urlRequest.checkForBrowserSideNavigation()) &&
5052 // No need to dispatch beforeunload if the frame has not committed a
5053 // navigation and contains an empty initial document.
5054 (did_access_initial_document_ || !current_history_item_.isNull());
5055
5056 if (should_dispatch_before_unload) {
5057 // Execute the BeforeUnload event. If asked not to proceed or the frame is
5058 // destroyed, ignore the navigation.
5051 // Keep a WeakPtr to this RenderFrameHost to detect if executing the 5059 // Keep a WeakPtr to this RenderFrameHost to detect if executing the
5052 // BeforeUnload event destriyed this frame. 5060 // BeforeUnload event destriyed this frame.
5053 base::WeakPtr<RenderFrameImpl> weak_self = weak_factory_.GetWeakPtr(); 5061 base::WeakPtr<RenderFrameImpl> weak_self = weak_factory_.GetWeakPtr();
5054 5062
5055 if (!frame_->dispatchBeforeUnloadEvent(info.navigationType == 5063 if (!frame_->dispatchBeforeUnloadEvent(info.navigationType ==
5056 blink::WebNavigationTypeReload) || 5064 blink::WebNavigationTypeReload) ||
5057 !weak_self) { 5065 !weak_self) {
5058 return blink::WebNavigationPolicyIgnore; 5066 return blink::WebNavigationPolicyIgnore;
5059 } 5067 }
5068 // navigation_start must be recorded immediately after dispatching the
5069 // beforeunload event.
5070 if (pending_navigation_params_) {
5071 pending_navigation_params_->common_params.navigation_start =
5072 base::TimeTicks::Now();
5073 }
5060 } 5074 }
5061 5075
5062 // PlzNavigate: if the navigation is not synchronous, send it to the browser. 5076 // PlzNavigate: if the navigation is not synchronous, send it to the browser.
5063 // This includes navigations with no request being sent to the network stack. 5077 // This includes navigations with no request being sent to the network stack.
5064 if (IsBrowserSideNavigationEnabled() && 5078 if (IsBrowserSideNavigationEnabled() &&
5065 info.urlRequest.checkForBrowserSideNavigation() && 5079 info.urlRequest.checkForBrowserSideNavigation() &&
5066 ShouldMakeNetworkRequestForURL(url)) { 5080 ShouldMakeNetworkRequestForURL(url)) {
5067 BeginNavigation(&info.urlRequest, info.replacesCurrentHistoryItem, 5081 BeginNavigation(&info.urlRequest, info.replacesCurrentHistoryItem,
5068 info.isClientRedirect); 5082 info.isClientRedirect);
5069 return blink::WebNavigationPolicyHandledByClient; 5083 return blink::WebNavigationPolicyHandledByClient;
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
5447 } 5461 }
5448 5462
5449 // If the navigation is for "view source", the WebLocalFrame needs to be put 5463 // If the navigation is for "view source", the WebLocalFrame needs to be put
5450 // in a special mode. 5464 // in a special mode.
5451 if (request_params.is_view_source) 5465 if (request_params.is_view_source)
5452 frame_->enableViewSourceMode(true); 5466 frame_->enableViewSourceMode(true);
5453 5467
5454 pending_navigation_params_.reset( 5468 pending_navigation_params_.reset(
5455 new NavigationParams(common_params, start_params, request_params)); 5469 new NavigationParams(common_params, start_params, request_params));
5456 5470
5457 // Unless the load is a WebFrameLoadType::Standard, this should remain 5471 // Sanitize navigation start and store in |pending_navigation_params_|.
5458 // uninitialized. It will be updated when the load type is determined to be 5472 // It will be picked up in UpdateNavigationState.
5459 // Standard, or after the previous document's unload handler has been
5460 // triggered. This occurs in UpdateNavigationState.
5461 // TODO(csharrison) See if we can always use the browser timestamp.
5462 pending_navigation_params_->common_params.navigation_start = 5473 pending_navigation_params_->common_params.navigation_start =
5463 base::TimeTicks(); 5474 SanitizeNavigationTiming(common_params.navigation_start,
5475 renderer_navigation_start);
5464 5476
5465 // Create parameters for a standard navigation, indicating whether it should 5477 // Create parameters for a standard navigation, indicating whether it should
5466 // replace the current NavigationEntry. 5478 // replace the current NavigationEntry.
5467 blink::WebFrameLoadType load_type = 5479 blink::WebFrameLoadType load_type =
5468 common_params.should_replace_current_entry 5480 common_params.should_replace_current_entry
5469 ? blink::WebFrameLoadType::ReplaceCurrentItem 5481 ? blink::WebFrameLoadType::ReplaceCurrentItem
5470 : blink::WebFrameLoadType::Standard; 5482 : blink::WebFrameLoadType::Standard;
5471 blink::WebHistoryLoadType history_load_type = 5483 blink::WebHistoryLoadType history_load_type =
5472 blink::WebHistoryDifferentDocumentLoad; 5484 blink::WebHistoryDifferentDocumentLoad;
5473 bool should_load_request = false; 5485 bool should_load_request = false;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
5576 GetWebHTTPBodyForRequestBody(common_params.post_data)); 5588 GetWebHTTPBodyForRequestBody(common_params.post_data));
5577 } 5589 }
5578 5590
5579 // A session history navigation should have been accompanied by state. 5591 // A session history navigation should have been accompanied by state.
5580 CHECK_EQ(request_params.page_id, -1); 5592 CHECK_EQ(request_params.page_id, -1);
5581 5593
5582 should_load_request = true; 5594 should_load_request = true;
5583 } 5595 }
5584 5596
5585 if (should_load_request) { 5597 if (should_load_request) {
5586 // Sanitize navigation start now that we know the load_type.
5587 pending_navigation_params_->common_params.navigation_start =
5588 SanitizeNavigationTiming(load_type, common_params.navigation_start,
5589 renderer_navigation_start);
5590
5591 // PlzNavigate: check if the navigation being committed originated as a 5598 // PlzNavigate: check if the navigation being committed originated as a
5592 // client redirect. 5599 // client redirect.
5593 bool is_client_redirect = 5600 bool is_client_redirect =
5594 browser_side_navigation 5601 browser_side_navigation
5595 ? !!(common_params.transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT) 5602 ? !!(common_params.transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT)
5596 : false; 5603 : false;
5597 5604
5598 // Perform a navigation to a data url if needed. 5605 // Perform a navigation to a data url if needed.
5599 // Note: the base URL might be invalid, so also check the data URL string. 5606 // Note: the base URL might be invalid, so also check the data URL string.
5600 bool should_load_data_url = !common_params.base_url_for_data_url.is_empty(); 5607 bool should_load_data_url = !common_params.base_url_for_data_url.is_empty();
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
6020 // If this was a browser-initiated navigation, then there could be pending 6027 // If this was a browser-initiated navigation, then there could be pending
6021 // navigation params, so use them. Otherwise, just reset the document state 6028 // navigation params, so use them. Otherwise, just reset the document state
6022 // here, since if pending navigation params exist they are for some other 6029 // here, since if pending navigation params exist they are for some other
6023 // navigation <https://crbug.com/597239>. 6030 // navigation <https://crbug.com/597239>.
6024 if (!pending_navigation_params_ || content_initiated) { 6031 if (!pending_navigation_params_ || content_initiated) {
6025 document_state->set_navigation_state( 6032 document_state->set_navigation_state(
6026 NavigationStateImpl::CreateContentInitiated()); 6033 NavigationStateImpl::CreateContentInitiated());
6027 return; 6034 return;
6028 } 6035 }
6029 6036
6030 // If this is a browser-initiated load that doesn't override 6037 DCHECK(!pending_navigation_params_->common_params.navigation_start.is_null());
6031 // navigation_start, set it here.
6032 if (pending_navigation_params_->common_params.navigation_start.is_null()) {
6033 pending_navigation_params_->common_params.navigation_start =
6034 base::TimeTicks::Now();
6035 }
6036 document_state->set_navigation_state(CreateNavigationStateFromPending()); 6038 document_state->set_navigation_state(CreateNavigationStateFromPending());
6037 6039
6038 // The |set_was_load_data_with_base_url_request| state should not change for 6040 // The |set_was_load_data_with_base_url_request| state should not change for
6039 // an in-page navigation, so skip updating it from the in-page navigation 6041 // an in-page navigation, so skip updating it from the in-page navigation
6040 // params in this case. 6042 // params in this case.
6041 if (!was_within_same_page) { 6043 if (!was_within_same_page) {
6042 const CommonNavigationParams& common_params = 6044 const CommonNavigationParams& common_params =
6043 pending_navigation_params_->common_params; 6045 pending_navigation_params_->common_params;
6044 bool load_data = !common_params.base_url_for_data_url.is_empty() && 6046 bool load_data = !common_params.base_url_for_data_url.is_empty() &&
6045 !common_params.history_url_for_data_url.is_empty() && 6047 !common_params.history_url_for_data_url.is_empty() &&
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
6328 // event target. Potentially a Pepper plugin will receive the event. 6330 // event target. Potentially a Pepper plugin will receive the event.
6329 // In order to tell whether a plugin gets the last mouse event and which it 6331 // In order to tell whether a plugin gets the last mouse event and which it
6330 // is, we set |pepper_last_mouse_event_target_| to null here. If a plugin gets 6332 // is, we set |pepper_last_mouse_event_target_| to null here. If a plugin gets
6331 // the event, it will notify us via DidReceiveMouseEvent() and set itself as 6333 // the event, it will notify us via DidReceiveMouseEvent() and set itself as
6332 // |pepper_last_mouse_event_target_|. 6334 // |pepper_last_mouse_event_target_|.
6333 pepper_last_mouse_event_target_ = nullptr; 6335 pepper_last_mouse_event_target_ = nullptr;
6334 #endif 6336 #endif
6335 } 6337 }
6336 6338
6337 } // namespace content 6339 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698