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

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: Review comments Created 5 years, 9 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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 #endif 113 #endif
114 114
115 #if defined(OS_MACOSX) 115 #if defined(OS_MACOSX)
116 #include "base/mac/foundation_util.h" 116 #include "base/mac/foundation_util.h"
117 #endif 117 #endif
118 118
119 namespace content { 119 namespace content {
120 namespace { 120 namespace {
121 121
122 const int kMinimumDelayBetweenLoadingUpdatesMS = 100; 122 const int kMinimumDelayBetweenLoadingUpdatesMS = 100;
123
124 // This matches what Blink's ProgressTracker has traditionally used for a
125 // minimum progress value.
126 const double kMinimumLoadingProgress = 0.1;
127
128 const char kDotGoogleDotCom[] = ".google.com"; 123 const char kDotGoogleDotCom[] = ".google.com";
129 124
130 #if defined(OS_ANDROID) 125 #if defined(OS_ANDROID)
131 const char kWebContentsAndroidKey[] = "web_contents_android"; 126 const char kWebContentsAndroidKey[] = "web_contents_android";
132 #endif // OS_ANDROID 127 #endif // OS_ANDROID
133 128
134 base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> > 129 base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> >
135 g_created_callbacks = LAZY_INSTANCE_INITIALIZER; 130 g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
136 131
137 static int StartDownload(RenderFrameHost* rfh, 132 static int StartDownload(RenderFrameHost* rfh,
(...skipping 18 matching lines...) Expand all
156 } 151 }
157 152
158 // Helper function for retrieving all the sites in a frame tree. 153 // Helper function for retrieving all the sites in a frame tree.
159 bool CollectSites(BrowserContext* context, 154 bool CollectSites(BrowserContext* context,
160 std::set<GURL>* sites, 155 std::set<GURL>* sites,
161 FrameTreeNode* node) { 156 FrameTreeNode* node) {
162 sites->insert(SiteInstance::GetSiteForURL(context, node->current_url())); 157 sites->insert(SiteInstance::GetSiteForURL(context, node->current_url()));
163 return true; 158 return true;
164 } 159 }
165 160
161 // Helper function used with FrameTree::ForEach() for retrieving the total
162 // loading progress and number of frames in a frame tree.
163 bool ForEachCollectLoadProgress(double* progress,
clamy 2015/03/02 10:30:58 nit: I think I prefered the version without the Fo
Fabrice (no longer in Chrome) 2015/03/02 18:01:39 I noticed the other helper functions below use a F
164 int* frame_count,
165 FrameTreeNode* node) {
166 // Ignore the current frame if it has not started loading.
167 double frame_progress = node->GetLoadingProgress();
168 if (frame_progress == RenderFrameHostImpl::kLoadingProgressNotStarted)
169 return true;
170
171 // Collect progress.
172 *progress += node->GetLoadingProgress();
173 (*frame_count)++;
174 return true;
175 }
176
177 // Helper function used with FrameTree::ForEach() to check if at least one of
178 // the nodes is loading.
179 bool ForEachIsNodeLoading(bool* is_loading, FrameTreeNode* node) {
180 if (node->IsLoading()) {
181 // There is at least one node loading, so abort traversal.
182 *is_loading = true;
183 return false;
184 }
185 return true;
186 }
187
188 // Helper function used with FrameTree::ForEach() to reset the load progress.
189 bool ForEachResetLoadProgress(FrameTreeNode* node) {
190 node->current_frame_host()->set_loading_progress(
191 RenderFrameHostImpl::kLoadingProgressNotStarted);
192 return true;
193 }
194
166 bool ForEachFrameInternal( 195 bool ForEachFrameInternal(
167 const base::Callback<void(RenderFrameHost*)>& on_frame, 196 const base::Callback<void(RenderFrameHost*)>& on_frame,
168 FrameTreeNode* node) { 197 FrameTreeNode* node) {
169 on_frame.Run(node->current_frame_host()); 198 on_frame.Run(node->current_frame_host());
170 return true; 199 return true;
171 } 200 }
172 201
173 bool ForEachPendingFrameInternal( 202 bool ForEachPendingFrameInternal(
174 const base::Callback<void(RenderFrameHost*)>& on_frame, 203 const base::Callback<void(RenderFrameHost*)>& on_frame,
175 FrameTreeNode* node) { 204 FrameTreeNode* node) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 this, 355 this,
327 this, 356 this,
328 this), 357 this),
329 is_loading_(false), 358 is_loading_(false),
330 is_load_to_different_document_(false), 359 is_load_to_different_document_(false),
331 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), 360 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
332 crashed_error_code_(0), 361 crashed_error_code_(0),
333 waiting_for_response_(false), 362 waiting_for_response_(false),
334 load_state_(net::LOAD_STATE_IDLE, base::string16()), 363 load_state_(net::LOAD_STATE_IDLE, base::string16()),
335 loading_total_progress_(0.0), 364 loading_total_progress_(0.0),
336 loading_frames_in_progress_(0),
337 upload_size_(0), 365 upload_size_(0),
338 upload_position_(0), 366 upload_position_(0),
339 displayed_insecure_content_(false), 367 displayed_insecure_content_(false),
340 has_accessed_initial_document_(false), 368 has_accessed_initial_document_(false),
341 capturer_count_(0), 369 capturer_count_(0),
342 should_normally_be_visible_(true), 370 should_normally_be_visible_(true),
343 is_being_destroyed_(false), 371 is_being_destroyed_(false),
344 notify_disconnection_(false), 372 notify_disconnection_(false),
345 dialog_manager_(NULL), 373 dialog_manager_(NULL),
346 is_showing_before_unload_dialog_(false), 374 is_showing_before_unload_dialog_(false),
(...skipping 2492 matching lines...) Expand 10 before | Expand all | Expand 10 after
2839 FOR_EACH_OBSERVER( 2867 FOR_EACH_OBSERVER(
2840 WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url)); 2868 WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url));
2841 } 2869 }
2842 2870
2843 void WebContentsImpl::OnDidStartLoading(bool to_different_document) { 2871 void WebContentsImpl::OnDidStartLoading(bool to_different_document) {
2844 if (!HasValidFrameSource()) 2872 if (!HasValidFrameSource())
2845 return; 2873 return;
2846 2874
2847 RenderFrameHostImpl* rfh = 2875 RenderFrameHostImpl* rfh =
2848 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2876 static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2849 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2850 2877
2851 // Any main frame load to a new document should reset the load progress, since 2878 // Any main frame load to a new document should reset the load progress, since
2852 // it will replace the current page and any frames. 2879 // it will replace the current page and any frames.
2853 if (to_different_document && !rfh->GetParent()) { 2880 if (to_different_document && !rfh->GetParent()) {
2854 ResetLoadProgressState(); 2881 ResetLoadProgressState();
2855 loading_frames_in_progress_ = 0; 2882 rfh->set_is_loading(false);
2856 rfh->frame_tree_node()->set_is_loading(false);
2857 } 2883 }
2858 2884
2859 // It is possible to get multiple calls to OnDidStartLoading that don't have 2885 // This method should never be called when the frame is loading.
2860 // corresponding calls to OnDidStopLoading: 2886 DCHECK(!rfh->is_loading());
2861 // - With "swappedout://" URLs, this happens when a RenderView gets swapped
2862 // out for a cross-process navigation, and it turns into a placeholder for
2863 // one being rendered in a different process.
2864 // - Also, there might be more than one RenderFrameHost sharing the same
2865 // FrameTreeNode (and thus sharing its ID) each sending a start.
2866 // - But in the future, once clamy@ moves navigation network requests to the
2867 // browser process, there's a good chance that callbacks about starting and
2868 // stopping will all be handled by the browser. When that happens, there
2869 // should no longer be a start/stop call imbalance. TODO(avi): When this
2870 // future arrives, update this code to not allow this case.
2871 if (rfh->frame_tree_node()->is_loading())
2872 return;
2873 2887
2874 DCHECK_GE(loading_frames_in_progress_, 0); 2888 if (!IsFrameTreeLoading())
2875 if (loading_frames_in_progress_ == 0)
2876 DidStartLoading(rfh, to_different_document); 2889 DidStartLoading(rfh, to_different_document);
2877 2890
2878 ++loading_frames_in_progress_; 2891 rfh->set_is_loading(true);
2879 rfh->frame_tree_node()->set_is_loading(true); 2892 rfh->set_loading_progress(RenderFrameHostImpl::kLoadingProgressMinimum);
2880 2893
2881 // Notify the RenderFrameHostManager of the event. 2894 // Notify the RenderFrameHostManager of the event.
2882 rfh->frame_tree_node()->render_manager()->OnDidStartLoading(); 2895 rfh->frame_tree_node()->render_manager()->OnDidStartLoading();
2883 2896
2884 loading_progresses_[render_frame_id] = kMinimumLoadingProgress;
2885 SendLoadProgressChanged(); 2897 SendLoadProgressChanged();
2886 } 2898 }
2887 2899
2888 void WebContentsImpl::OnDidStopLoading() { 2900 void WebContentsImpl::OnDidStopLoading() {
2889 if (!HasValidFrameSource()) 2901 if (!HasValidFrameSource())
2890 return; 2902 return;
2891 2903
2892 RenderFrameHostImpl* rfh = 2904 RenderFrameHostImpl* rfh =
2893 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2905 static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2894 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2895 rfh->frame_tree_node()->set_is_loading(false);
2896 2906
2897 if (loading_progresses_.find(render_frame_id) != loading_progresses_.end()) { 2907 // This method should never be called when the frame is not loading.
2898 // Load stopped while we were still tracking load. Make sure we update 2908 DCHECK(rfh->is_loading());
2899 // progress based on this frame's completion. 2909 rfh->set_is_loading(false);
2900 loading_progresses_[render_frame_id] = 1.0; 2910 rfh->set_loading_progress(RenderFrameHostImpl::kLoadingProgressDone);
2901 SendLoadProgressChanged(); 2911
2902 // Then we clean-up our states. 2912 // Update progress based on this frame's completion.
2903 if (loading_total_progress_ == 1.0) 2913 SendLoadProgressChanged();
2904 ResetLoadProgressState(); 2914
2905 } 2915 // Then clean-up the states.
2916 if (loading_total_progress_ == 1.0)
2917 ResetLoadProgressState();
2906 2918
2907 // Notify the RenderFrameHostManager of the event. 2919 // Notify the RenderFrameHostManager of the event.
2908 rfh->frame_tree_node()->render_manager()->OnDidStopLoading(); 2920 rfh->frame_tree_node()->render_manager()->OnDidStopLoading();
2909 2921
2910 // TODO(japhet): This should be a DCHECK, but the pdf plugin sometimes 2922 if (!IsFrameTreeLoading())
2911 // calls DidStopLoading() without a matching DidStartLoading().
2912 if (loading_frames_in_progress_ == 0)
2913 return;
2914 --loading_frames_in_progress_;
2915 if (loading_frames_in_progress_ == 0)
2916 DidStopLoading(rfh); 2923 DidStopLoading(rfh);
2917 } 2924 }
2918 2925
2919 void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) { 2926 void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) {
2920 if (!HasValidFrameSource()) 2927 if (!HasValidFrameSource())
2921 return; 2928 return;
2922 2929
2923 RenderFrameHostImpl* rfh = 2930 RenderFrameHostImpl* rfh =
2924 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2931 static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2925 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2926 2932
2927 loading_progresses_[render_frame_id] = load_progress; 2933 rfh->set_loading_progress(load_progress);
2928 2934
2929 // We notify progress change immediately for the first and last updates. 2935 // We notify progress change immediately for the first and last updates.
2930 // Also, since the message loop may be pretty busy when a page is loaded, it 2936 // Also, since the message loop may be pretty busy when a page is loaded, it
2931 // might not execute a posted task in a timely manner so we make sure to 2937 // might not execute a posted task in a timely manner so we make sure to
2932 // immediately send progress report if enough time has passed. 2938 // immediately send progress report if enough time has passed.
2933 base::TimeDelta min_delay = 2939 base::TimeDelta min_delay =
2934 base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS); 2940 base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS);
2935 if (load_progress == 1.0 || loading_last_progress_update_.is_null() || 2941 if (load_progress == 1.0 || loading_last_progress_update_.is_null() ||
2936 base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) { 2942 base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) {
2937 // If there is a pending task to send progress, it is now obsolete. 2943 // If there is a pending task to send progress, it is now obsolete.
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
3395 Details<std::pair<NavigationEntry*, bool> >(&details)); 3401 Details<std::pair<NavigationEntry*, bool> >(&details));
3396 3402
3397 return true; 3403 return true;
3398 } 3404 }
3399 3405
3400 void WebContentsImpl::SendLoadProgressChanged() { 3406 void WebContentsImpl::SendLoadProgressChanged() {
3401 loading_last_progress_update_ = base::TimeTicks::Now(); 3407 loading_last_progress_update_ = base::TimeTicks::Now();
3402 double progress = 0.0; 3408 double progress = 0.0;
3403 int frame_count = 0; 3409 int frame_count = 0;
3404 3410
3405 for (LoadingProgressMap::iterator it = loading_progresses_.begin(); 3411 frame_tree_.ForEach(
3406 it != loading_progresses_.end(); 3412 base::Bind(&ForEachCollectLoadProgress, &progress, &frame_count));
3407 ++it) { 3413 if (frame_count != 0)
3408 progress += it->second; 3414 progress /= frame_count;
3409 ++frame_count; 3415 DCHECK_LE(progress, 1.0);
3410 }
3411 if (frame_count == 0)
3412 return;
3413 progress /= frame_count;
3414 DCHECK(progress <= 1.0);
3415 3416
3416 if (progress <= loading_total_progress_) 3417 if (progress <= loading_total_progress_)
3417 return; 3418 return;
3418 loading_total_progress_ = progress; 3419 loading_total_progress_ = progress;
3419 3420
3420 if (delegate_) 3421 if (delegate_)
3421 delegate_->LoadProgressChanged(this, progress); 3422 delegate_->LoadProgressChanged(this, progress);
3422 } 3423 }
3423 3424
3424 void WebContentsImpl::ResetLoadProgressState() { 3425 void WebContentsImpl::ResetLoadProgressState() {
3425 loading_progresses_.clear(); 3426 frame_tree_.ForEach(base::Bind(&ForEachResetLoadProgress));
3426 loading_total_progress_ = 0.0; 3427 loading_total_progress_ = 0.0;
3427 loading_weak_factory_.InvalidateWeakPtrs(); 3428 loading_weak_factory_.InvalidateWeakPtrs();
3428 loading_last_progress_update_ = base::TimeTicks(); 3429 loading_last_progress_update_ = base::TimeTicks();
3429 } 3430 }
3430 3431
3432 bool WebContentsImpl::IsFrameTreeLoading() {
3433 bool is_loading = false;
3434 frame_tree_.ForEach(base::Bind(&ForEachIsNodeLoading, &is_loading));
3435 return is_loading;
3436 }
3437
3431 void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host, 3438 void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
3432 RenderViewHost* new_host) { 3439 RenderViewHost* new_host) {
3433 // After sending out a swap notification, we need to send a disconnect 3440 // After sending out a swap notification, we need to send a disconnect
3434 // notification so that clients that pick up a pointer to |this| can NULL the 3441 // notification so that clients that pick up a pointer to |this| can NULL the
3435 // pointer. See Bug 1230284. 3442 // pointer. See Bug 1230284.
3436 notify_disconnection_ = true; 3443 notify_disconnection_ = true;
3437 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3444 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3438 RenderViewHostChanged(old_host, new_host)); 3445 RenderViewHostChanged(old_host, new_host));
3439 3446
3440 // TODO(avi): Remove. http://crbug.com/170921 3447 // TODO(avi): Remove. http://crbug.com/170921
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
3720 3727
3721 SetIsLoading(rvh, false, true, NULL); 3728 SetIsLoading(rvh, false, true, NULL);
3722 NotifyDisconnected(); 3729 NotifyDisconnected();
3723 SetIsCrashed(status, error_code); 3730 SetIsCrashed(status, error_code);
3724 3731
3725 // Reset the loading progress. TODO(avi): What does it mean to have a 3732 // Reset the loading progress. TODO(avi): What does it mean to have a
3726 // "renderer crash" when there is more than one renderer process serving a 3733 // "renderer crash" when there is more than one renderer process serving a
3727 // webpage? Once this function is called at a more granular frame level, we 3734 // webpage? Once this function is called at a more granular frame level, we
3728 // probably will need to more granularly reset the state here. 3735 // probably will need to more granularly reset the state here.
3729 ResetLoadProgressState(); 3736 ResetLoadProgressState();
3730 loading_frames_in_progress_ = 0;
3731 3737
3732 FOR_EACH_OBSERVER(WebContentsObserver, 3738 FOR_EACH_OBSERVER(WebContentsObserver,
3733 observers_, 3739 observers_,
3734 RenderProcessGone(GetCrashedStatus())); 3740 RenderProcessGone(GetCrashedStatus()));
3735 } 3741 }
3736 3742
3737 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { 3743 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
3738 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh)); 3744 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
3739 } 3745 }
3740 3746
(...skipping 772 matching lines...) Expand 10 before | Expand all | Expand 10 after
4513 node->render_manager()->ResumeResponseDeferredAtStart(); 4519 node->render_manager()->ResumeResponseDeferredAtStart();
4514 } 4520 }
4515 4521
4516 void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) { 4522 void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) {
4517 force_disable_overscroll_content_ = force_disable; 4523 force_disable_overscroll_content_ = force_disable;
4518 if (view_) 4524 if (view_)
4519 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); 4525 view_->SetOverscrollControllerEnabled(CanOverscrollContent());
4520 } 4526 }
4521 4527
4522 } // namespace content 4528 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698