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

Side by Side Diff: content/browser/web_contents/web_contents_impl.cc

Issue 925623002: Refactor the loading tracking logic in WebContentsImpl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: WIP (Fix tests) Created 5 years, 10 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/web_contents/web_contents_impl.h" 5 #include "content/browser/web_contents/web_contents_impl.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 115
116 #if defined(OS_MACOSX) 116 #if defined(OS_MACOSX)
117 #include "base/mac/foundation_util.h" 117 #include "base/mac/foundation_util.h"
118 #endif 118 #endif
119 119
120 namespace content { 120 namespace content {
121 namespace { 121 namespace {
122 122
123 const int kMinimumDelayBetweenLoadingUpdatesMS = 100; 123 const int kMinimumDelayBetweenLoadingUpdatesMS = 100;
124 124
125 // This matches what Blink's ProgressTracker has traditionally used for a
126 // minimum progress value.
127 const double kMinimumLoadingProgress = 0.1;
128 125
129 const char kDotGoogleDotCom[] = ".google.com"; 126 const char kDotGoogleDotCom[] = ".google.com";
130 127
131 #if defined(OS_ANDROID) 128 #if defined(OS_ANDROID)
132 const char kWebContentsAndroidKey[] = "web_contents_android"; 129 const char kWebContentsAndroidKey[] = "web_contents_android";
133 #endif // OS_ANDROID 130 #endif // OS_ANDROID
134 131
135 base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> > 132 base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> >
136 g_created_callbacks = LAZY_INSTANCE_INITIALIZER; 133 g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
137 134
(...skipping 19 matching lines...) Expand all
157 } 154 }
158 155
159 // Helper function for retrieving all the sites in a frame tree. 156 // Helper function for retrieving all the sites in a frame tree.
160 bool CollectSites(BrowserContext* context, 157 bool CollectSites(BrowserContext* context,
161 std::set<GURL>* sites, 158 std::set<GURL>* sites,
162 FrameTreeNode* node) { 159 FrameTreeNode* node) {
163 sites->insert(SiteInstance::GetSiteForURL(context, node->current_url())); 160 sites->insert(SiteInstance::GetSiteForURL(context, node->current_url()));
164 return true; 161 return true;
165 } 162 }
166 163
164 // Helper function for retrieving the total loading progress and number of
Charlie Reis 2015/02/20 23:42:12 nit: Helper function used with FrameTree::ForEach(
Fabrice (no longer in Chrome) 2015/02/23 20:02:06 Done.
165 // frames in a frame tree.
166 bool CollectLoadProgress(double* progress,
167 int* frame_count,
168 FrameTreeNode* node) {
169 *progress += node->loading_progress();
170 (*frame_count)++;
171 return true;
172 }
173
174 // Helper function used with FrameTree::ForEach() to check if at least one of
175 // the nodes is loading.
176 bool IsNodeLoading(bool* is_loading, FrameTreeNode* node) {
177 if (node->is_loading()) {
178 // There is at least one node loading, abort traversal.
Charlie Reis 2015/02/20 23:42:12 nit: This is a run-on sentence. Use a semicolon o
Fabrice (no longer in Chrome) 2015/02/23 20:02:06 Done.
179 *is_loading = true;
180 return false;
181 }
182 return true;
183 }
184
167 bool ForEachFrameInternal( 185 bool ForEachFrameInternal(
168 const base::Callback<void(RenderFrameHost*)>& on_frame, 186 const base::Callback<void(RenderFrameHost*)>& on_frame,
169 FrameTreeNode* node) { 187 FrameTreeNode* node) {
170 on_frame.Run(node->current_frame_host()); 188 on_frame.Run(node->current_frame_host());
171 return true; 189 return true;
172 } 190 }
173 191
174 bool ForEachPendingFrameInternal( 192 bool ForEachPendingFrameInternal(
175 const base::Callback<void(RenderFrameHost*)>& on_frame, 193 const base::Callback<void(RenderFrameHost*)>& on_frame,
176 FrameTreeNode* node) { 194 FrameTreeNode* node) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 this, 345 this,
328 this, 346 this,
329 this), 347 this),
330 is_loading_(false), 348 is_loading_(false),
331 is_load_to_different_document_(false), 349 is_load_to_different_document_(false),
332 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), 350 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
333 crashed_error_code_(0), 351 crashed_error_code_(0),
334 waiting_for_response_(false), 352 waiting_for_response_(false),
335 load_state_(net::LOAD_STATE_IDLE, base::string16()), 353 load_state_(net::LOAD_STATE_IDLE, base::string16()),
336 loading_total_progress_(0.0), 354 loading_total_progress_(0.0),
337 loading_frames_in_progress_(0),
338 upload_size_(0), 355 upload_size_(0),
339 upload_position_(0), 356 upload_position_(0),
340 displayed_insecure_content_(false), 357 displayed_insecure_content_(false),
341 has_accessed_initial_document_(false), 358 has_accessed_initial_document_(false),
342 capturer_count_(0), 359 capturer_count_(0),
343 should_normally_be_visible_(true), 360 should_normally_be_visible_(true),
344 is_being_destroyed_(false), 361 is_being_destroyed_(false),
345 notify_disconnection_(false), 362 notify_disconnection_(false),
346 dialog_manager_(NULL), 363 dialog_manager_(NULL),
347 is_showing_before_unload_dialog_(false), 364 is_showing_before_unload_dialog_(false),
(...skipping 2476 matching lines...) Expand 10 before | Expand all | Expand 10 after
2824 FOR_EACH_OBSERVER( 2841 FOR_EACH_OBSERVER(
2825 WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url)); 2842 WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url));
2826 } 2843 }
2827 2844
2828 void WebContentsImpl::OnDidStartLoading(bool to_different_document) { 2845 void WebContentsImpl::OnDidStartLoading(bool to_different_document) {
2829 if (!HasValidFrameSource()) 2846 if (!HasValidFrameSource())
2830 return; 2847 return;
2831 2848
2832 RenderFrameHostImpl* rfh = 2849 RenderFrameHostImpl* rfh =
2833 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2850 static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2834 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2835 2851
2836 // Any main frame load to a new document should reset the load progress, since 2852 // Any main frame load to a new document should reset the load progress, since
2837 // it will replace the current page and any frames. 2853 // it will replace the current page and any frames.
2838 if (to_different_document && !rfh->GetParent()) { 2854 if (to_different_document && !rfh->GetParent()) {
2839 ResetLoadProgressState(); 2855 ResetLoadProgressState();
2840 loading_frames_in_progress_ = 0;
2841 rfh->frame_tree_node()->set_is_loading(false); 2856 rfh->frame_tree_node()->set_is_loading(false);
2857 rfh->frame_tree_node()->set_loading_progress(
clamy 2015/02/20 14:00:24 It seems a bit weird to have a call to ResetLoadPr
Fabrice (no longer in Chrome) 2015/02/24 13:14:47 Answered in another comment in patch set 4, ResetL
2858 FrameTreeNode::kNotStartedLoadingProgress);
Charlie Reis 2015/02/20 23:42:12 It looks wrong to me to have this here at all. We
Fabrice (no longer in Chrome) 2015/02/24 13:14:47 Latter patch sets no longer return early, so it is
2842 } 2859 }
2843 2860
2844 // It is possible to get multiple calls to OnDidStartLoading that don't have 2861 // It is possible to get multiple calls to OnDidStartLoading that don't have
2845 // corresponding calls to OnDidStopLoading: 2862 // corresponding calls to OnDidStopLoading:
2846 // - With "swappedout://" URLs, this happens when a RenderView gets swapped 2863 // - With "swappedout://" URLs, this happens when a RenderView gets swapped
2847 // out for a cross-process navigation, and it turns into a placeholder for 2864 // out for a cross-process navigation, and it turns into a placeholder for
2848 // one being rendered in a different process. 2865 // one being rendered in a different process.
2849 // - Also, there might be more than one RenderFrameHost sharing the same 2866 // - Also, there might be more than one RenderFrameHost sharing the same
2850 // FrameTreeNode (and thus sharing its ID) each sending a start. 2867 // FrameTreeNode (and thus sharing its ID) each sending a start.
2851 // - But in the future, once clamy@ moves navigation network requests to the 2868 // - But in the future, once clamy@ moves navigation network requests to the
2852 // browser process, there's a good chance that callbacks about starting and 2869 // browser process, there's a good chance that callbacks about starting and
2853 // stopping will all be handled by the browser. When that happens, there 2870 // stopping will all be handled by the browser. When that happens, there
2854 // should no longer be a start/stop call imbalance. TODO(avi): When this 2871 // should no longer be a start/stop call imbalance. TODO(avi): When this
2855 // future arrives, update this code to not allow this case. 2872 // future arrives, update this code to not allow this case.
2856 if (rfh->frame_tree_node()->is_loading()) 2873 if (rfh->frame_tree_node()->is_loading())
2857 return; 2874 return;
2858 2875
2859 DCHECK_GE(loading_frames_in_progress_, 0); 2876 if (!IsFrameTreeLoading())
2860 if (loading_frames_in_progress_ == 0)
2861 DidStartLoading(rfh, to_different_document); 2877 DidStartLoading(rfh, to_different_document);
2862 2878
2863 ++loading_frames_in_progress_;
2864 rfh->frame_tree_node()->set_is_loading(true); 2879 rfh->frame_tree_node()->set_is_loading(true);
2880 rfh->frame_tree_node()->set_loading_progress(
2881 FrameTreeNode::kMinimumLoadingProgress);
2865 2882
2866 // Notify the RenderFrameHostManager of the event. 2883 // Notify the RenderFrameHostManager of the event.
2867 rfh->frame_tree_node()->render_manager()->OnDidStartLoading(); 2884 rfh->frame_tree_node()->render_manager()->OnDidStartLoading();
2868 2885
2869 loading_progresses_[render_frame_id] = kMinimumLoadingProgress;
2870 SendLoadProgressChanged(); 2886 SendLoadProgressChanged();
2871 } 2887 }
2872 2888
2873 void WebContentsImpl::OnDidStopLoading() { 2889 void WebContentsImpl::OnDidStopLoading() {
2874 if (!HasValidFrameSource()) 2890 if (!HasValidFrameSource())
2875 return; 2891 return;
2876 2892
2877 RenderFrameHostImpl* rfh = 2893 RenderFrameHostImpl* rfh =
2878 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2894 static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2879 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); 2895
2896 // StopLoading was called for an older navigation, ignore.
Charlie Reis 2015/02/20 23:42:12 Same nit about run-on sentence.
Fabrice (no longer in Chrome) 2015/02/23 20:02:06 Done.
2897 if (rfh->frame_tree_node()->current_frame_host() != rfh)
clamy 2015/02/20 14:00:24 We want to remove mention of the RenderFrameHost f
Charlie Reis 2015/02/20 23:42:12 Let's not worry about the RFH->FTN switch or OnDid
Fabrice (no longer in Chrome) 2015/02/24 13:14:47 This is no longer relevant as we now track the loa
2898 return;
2899
2900 // This method should never be called when the frame is not loading.
2901 DCHECK(rfh->frame_tree_node()->is_loading());
2880 rfh->frame_tree_node()->set_is_loading(false); 2902 rfh->frame_tree_node()->set_is_loading(false);
2903 rfh->frame_tree_node()->set_loading_progress(
2904 FrameTreeNode::kDoneLoadingProgress);
2881 2905
2882 if (loading_progresses_.find(render_frame_id) != loading_progresses_.end()) { 2906 // Update progress based on this frame's completion.
2883 // Load stopped while we were still tracking load. Make sure we update 2907 SendLoadProgressChanged();
2884 // progress based on this frame's completion. 2908 // Then clean-up the states.
2885 loading_progresses_[render_frame_id] = 1.0; 2909 if (loading_total_progress_ == 1.0)
2886 SendLoadProgressChanged(); 2910 ResetLoadProgressState();
2887 // Then we clean-up our states.
2888 if (loading_total_progress_ == 1.0)
2889 ResetLoadProgressState();
2890 }
2891 2911
2892 // Notify the RenderFrameHostManager of the event. 2912 // Notify the RenderFrameHostManager of the event.
2893 rfh->frame_tree_node()->render_manager()->OnDidStopLoading(); 2913 rfh->frame_tree_node()->render_manager()->OnDidStopLoading();
2894 2914
2895 // TODO(japhet): This should be a DCHECK, but the pdf plugin sometimes 2915 if (!IsFrameTreeLoading())
2896 // calls DidStopLoading() without a matching DidStartLoading().
2897 if (loading_frames_in_progress_ == 0)
2898 return;
2899 --loading_frames_in_progress_;
2900 if (loading_frames_in_progress_ == 0)
2901 DidStopLoading(rfh); 2916 DidStopLoading(rfh);
2902 } 2917 }
2903 2918
2904 void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) { 2919 void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) {
2905 if (!HasValidFrameSource()) 2920 if (!HasValidFrameSource())
2906 return; 2921 return;
2907 2922
2908 RenderFrameHostImpl* rfh = 2923 RenderFrameHostImpl* rfh =
2909 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2924 static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2910 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2911 2925
2912 loading_progresses_[render_frame_id] = load_progress; 2926 rfh->frame_tree_node()->set_loading_progress(load_progress);
2913 2927
2914 // We notify progress change immediately for the first and last updates. 2928 // We notify progress change immediately for the first and last updates.
2915 // Also, since the message loop may be pretty busy when a page is loaded, it 2929 // Also, since the message loop may be pretty busy when a page is loaded, it
2916 // might not execute a posted task in a timely manner so we make sure to 2930 // might not execute a posted task in a timely manner so we make sure to
2917 // immediately send progress report if enough time has passed. 2931 // immediately send progress report if enough time has passed.
2918 base::TimeDelta min_delay = 2932 base::TimeDelta min_delay =
2919 base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS); 2933 base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS);
2920 if (load_progress == 1.0 || loading_last_progress_update_.is_null() || 2934 if (load_progress == 1.0 || loading_last_progress_update_.is_null() ||
2921 base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) { 2935 base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) {
2922 // If there is a pending task to send progress, it is now obsolete. 2936 // If there is a pending task to send progress, it is now obsolete.
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
3384 Details<std::pair<NavigationEntry*, bool> >(&details)); 3398 Details<std::pair<NavigationEntry*, bool> >(&details));
3385 3399
3386 return true; 3400 return true;
3387 } 3401 }
3388 3402
3389 void WebContentsImpl::SendLoadProgressChanged() { 3403 void WebContentsImpl::SendLoadProgressChanged() {
3390 loading_last_progress_update_ = base::TimeTicks::Now(); 3404 loading_last_progress_update_ = base::TimeTicks::Now();
3391 double progress = 0.0; 3405 double progress = 0.0;
3392 int frame_count = 0; 3406 int frame_count = 0;
3393 3407
3394 for (LoadingProgressMap::iterator it = loading_progresses_.begin(); 3408 frame_tree_.ForEach(
3395 it != loading_progresses_.end(); 3409 base::Bind(&CollectLoadProgress, &progress, &frame_count));
3396 ++it) {
3397 progress += it->second;
3398 ++frame_count;
3399 }
3400 if (frame_count == 0)
3401 return;
carlosk 2015/02/23 10:41:15 You *might* be able replace this if-check with |(p
Fabrice (no longer in Chrome) 2015/02/24 13:14:47 The loading progress tracking that is done here is
carlosk 2015/03/02 14:17:28 Acknowledged.
3402 progress /= frame_count; 3410 progress /= frame_count;
Charlie Reis 2015/02/20 23:42:12 Hmm, it's a little subtle to assume that we will a
Fabrice (no longer in Chrome) 2015/02/23 20:02:06 Done.
3403 DCHECK(progress <= 1.0); 3411 DCHECK(progress <= 1.0);
3404 3412
3405 if (progress <= loading_total_progress_) 3413 if (progress <= loading_total_progress_)
3406 return; 3414 return;
carlosk 2015/02/23 10:41:15 This is a minor/usability issue and should be sort
Fabrice (no longer in Chrome) 2015/02/24 13:14:47 I did not want to change the logic in here so I le
3407 loading_total_progress_ = progress; 3415 loading_total_progress_ = progress;
3408 3416
3409 if (delegate_) 3417 if (delegate_)
3410 delegate_->LoadProgressChanged(this, progress); 3418 delegate_->LoadProgressChanged(this, progress);
3411 } 3419 }
3412 3420
3413 void WebContentsImpl::ResetLoadProgressState() { 3421 void WebContentsImpl::ResetLoadProgressState() {
3414 loading_progresses_.clear();
clamy 2015/02/20 14:00:24 Is it okay to not reset the load progress for each
Charlie Reis 2015/02/20 23:42:12 No. We should be resetting each node in the tree
Fabrice (no longer in Chrome) 2015/02/23 20:02:06 I do not think we should actually, because this me
3415 loading_total_progress_ = 0.0; 3422 loading_total_progress_ = 0.0;
3416 loading_weak_factory_.InvalidateWeakPtrs(); 3423 loading_weak_factory_.InvalidateWeakPtrs();
3417 loading_last_progress_update_ = base::TimeTicks(); 3424 loading_last_progress_update_ = base::TimeTicks();
3418 } 3425 }
3419 3426
3420 void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host, 3427 void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
3421 RenderViewHost* new_host) { 3428 RenderViewHost* new_host) {
3422 // After sending out a swap notification, we need to send a disconnect 3429 // After sending out a swap notification, we need to send a disconnect
3423 // notification so that clients that pick up a pointer to |this| can NULL the 3430 // notification so that clients that pick up a pointer to |this| can NULL the
3424 // pointer. See Bug 1230284. 3431 // pointer. See Bug 1230284.
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
3721 3728
3722 SetIsLoading(rvh, false, true, NULL); 3729 SetIsLoading(rvh, false, true, NULL);
3723 NotifyDisconnected(); 3730 NotifyDisconnected();
3724 SetIsCrashed(status, error_code); 3731 SetIsCrashed(status, error_code);
3725 3732
3726 // Reset the loading progress. TODO(avi): What does it mean to have a 3733 // Reset the loading progress. TODO(avi): What does it mean to have a
3727 // "renderer crash" when there is more than one renderer process serving a 3734 // "renderer crash" when there is more than one renderer process serving a
3728 // webpage? Once this function is called at a more granular frame level, we 3735 // webpage? Once this function is called at a more granular frame level, we
3729 // probably will need to more granularly reset the state here. 3736 // probably will need to more granularly reset the state here.
3730 ResetLoadProgressState(); 3737 ResetLoadProgressState();
3731 loading_frames_in_progress_ = 0;
3732 3738
3733 FOR_EACH_OBSERVER(WebContentsObserver, 3739 FOR_EACH_OBSERVER(WebContentsObserver,
3734 observers_, 3740 observers_,
3735 RenderProcessGone(GetCrashedStatus())); 3741 RenderProcessGone(GetCrashedStatus()));
3736 } 3742 }
3737 3743
3738 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { 3744 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
3739 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh)); 3745 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
3740 } 3746 }
3741 3747
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after
4505 FrameTreeNode* node = frame_tree_.root(); 4511 FrameTreeNode* node = frame_tree_.root();
4506 node->render_manager()->ResumeResponseDeferredAtStart(); 4512 node->render_manager()->ResumeResponseDeferredAtStart();
4507 } 4513 }
4508 4514
4509 void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) { 4515 void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) {
4510 force_disable_overscroll_content_ = force_disable; 4516 force_disable_overscroll_content_ = force_disable;
4511 if (view_) 4517 if (view_)
4512 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); 4518 view_->SetOverscrollControllerEnabled(CanOverscrollContent());
4513 } 4519 }
4514 4520
4521 bool WebContentsImpl::IsFrameTreeLoading() {
4522 bool is_loading = false;
4523 frame_tree_.ForEach(base::Bind(&IsNodeLoading, &is_loading));
4524 return is_loading;
4525 }
4526
4515 } // namespace content 4527 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698