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

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, just to run 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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 123
124 // This matches what Blink's ProgressTracker has traditionally used for a
125 // minimum progress value.
126 const double kMinimumLoadingProgress = 0.1;
127 124
128 const char kDotGoogleDotCom[] = ".google.com"; 125 const char kDotGoogleDotCom[] = ".google.com";
129 126
130 #if defined(OS_ANDROID) 127 #if defined(OS_ANDROID)
131 const char kWebContentsAndroidKey[] = "web_contents_android"; 128 const char kWebContentsAndroidKey[] = "web_contents_android";
132 #endif // OS_ANDROID 129 #endif // OS_ANDROID
133 130
134 base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> > 131 base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> >
135 g_created_callbacks = LAZY_INSTANCE_INITIALIZER; 132 g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
136 133
(...skipping 19 matching lines...) Expand all
156 } 153 }
157 154
158 // Helper function for retrieving all the sites in a frame tree. 155 // Helper function for retrieving all the sites in a frame tree.
159 bool CollectSites(BrowserContext* context, 156 bool CollectSites(BrowserContext* context,
160 std::set<GURL>* sites, 157 std::set<GURL>* sites,
161 FrameTreeNode* node) { 158 FrameTreeNode* node) {
162 sites->insert(SiteInstance::GetSiteForURL(context, node->current_url())); 159 sites->insert(SiteInstance::GetSiteForURL(context, node->current_url()));
163 return true; 160 return true;
164 } 161 }
165 162
163 // Helper function for retrieving the total loading progress and number of
nasko 2015/02/23 16:54:43 nit: I like the "used with FrameTree::ForEach()" p
Fabrice (no longer in Chrome) 2015/02/23 20:02:06 Done.
164 // frames in a frame tree.
165 bool CollectLoadProgress(double* progress,
166 int* frame_count,
167 FrameTreeNode* node) {
168 *progress += node->loading_progress();
169 (*frame_count)++;
170 return true;
171 }
172
173 // Helper function used with FrameTree::ForEach() to check if at least one of
174 // the nodes is loading.
175 bool IsNodeLoading(bool* is_loading, FrameTreeNode* node) {
176 if (node->is_loading()) {
177 // There is at least one node loading, abort traversal.
178 *is_loading = true;
179 return false;
180 }
181 return true;
182 }
183
166 bool ForEachFrameInternal( 184 bool ForEachFrameInternal(
167 const base::Callback<void(RenderFrameHost*)>& on_frame, 185 const base::Callback<void(RenderFrameHost*)>& on_frame,
168 FrameTreeNode* node) { 186 FrameTreeNode* node) {
169 on_frame.Run(node->current_frame_host()); 187 on_frame.Run(node->current_frame_host());
170 return true; 188 return true;
171 } 189 }
172 190
173 bool ForEachPendingFrameInternal( 191 bool ForEachPendingFrameInternal(
174 const base::Callback<void(RenderFrameHost*)>& on_frame, 192 const base::Callback<void(RenderFrameHost*)>& on_frame,
175 FrameTreeNode* node) { 193 FrameTreeNode* node) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 this, 344 this,
327 this, 345 this,
328 this), 346 this),
329 is_loading_(false), 347 is_loading_(false),
330 is_load_to_different_document_(false), 348 is_load_to_different_document_(false),
331 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), 349 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
332 crashed_error_code_(0), 350 crashed_error_code_(0),
333 waiting_for_response_(false), 351 waiting_for_response_(false),
334 load_state_(net::LOAD_STATE_IDLE, base::string16()), 352 load_state_(net::LOAD_STATE_IDLE, base::string16()),
335 loading_total_progress_(0.0), 353 loading_total_progress_(0.0),
336 loading_frames_in_progress_(0),
337 upload_size_(0), 354 upload_size_(0),
338 upload_position_(0), 355 upload_position_(0),
339 displayed_insecure_content_(false), 356 displayed_insecure_content_(false),
340 has_accessed_initial_document_(false), 357 has_accessed_initial_document_(false),
341 capturer_count_(0), 358 capturer_count_(0),
342 should_normally_be_visible_(true), 359 should_normally_be_visible_(true),
343 is_being_destroyed_(false), 360 is_being_destroyed_(false),
344 notify_disconnection_(false), 361 notify_disconnection_(false),
345 dialog_manager_(NULL), 362 dialog_manager_(NULL),
346 is_showing_before_unload_dialog_(false), 363 is_showing_before_unload_dialog_(false),
(...skipping 2476 matching lines...) Expand 10 before | Expand all | Expand 10 after
2823 FOR_EACH_OBSERVER( 2840 FOR_EACH_OBSERVER(
2824 WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url)); 2841 WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url));
2825 } 2842 }
2826 2843
2827 void WebContentsImpl::OnDidStartLoading(bool to_different_document) { 2844 void WebContentsImpl::OnDidStartLoading(bool to_different_document) {
2828 if (!HasValidFrameSource()) 2845 if (!HasValidFrameSource())
2829 return; 2846 return;
2830 2847
2831 RenderFrameHostImpl* rfh = 2848 RenderFrameHostImpl* rfh =
2832 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2849 static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2833 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); 2850
2851 // Update pending rfh in the frame tree node if necessary.
2852 if (rfh->frame_tree_node()->pending_frame_host() != rfh) {
nasko 2015/02/23 16:54:43 Pending RFH has a very precise meaning and it does
Fabrice (no longer in Chrome) 2015/02/23 20:02:06 Done.
2853 rfh->frame_tree_node()->set_pending_frame_host(rfh);
2854 rfh->frame_tree_node()->set_is_loading(false);
2855 rfh->frame_tree_node()->set_loading_progress(
2856 FrameTreeNode::kLoadingProgressNotStarted);
2857 }
2834 2858
2835 // Any main frame load to a new document should reset the load progress, since 2859 // Any main frame load to a new document should reset the load progress, since
2836 // it will replace the current page and any frames. 2860 // it will replace the current page and any frames.
2837 if (to_different_document && !rfh->GetParent()) { 2861 if (to_different_document && !rfh->GetParent()) {
2838 ResetLoadProgressState(); 2862 ResetLoadProgressState();
2839 loading_frames_in_progress_ = 0;
2840 rfh->frame_tree_node()->set_is_loading(false); 2863 rfh->frame_tree_node()->set_is_loading(false);
2864 rfh->frame_tree_node()->set_loading_progress(
2865 FrameTreeNode::kLoadingProgressNotStarted);
2841 } 2866 }
2842 2867
2843 // It is possible to get multiple calls to OnDidStartLoading that don't have 2868 // It is possible to get multiple calls to OnDidStartLoading that don't have
2844 // corresponding calls to OnDidStopLoading: 2869 // corresponding calls to OnDidStopLoading:
2845 // - With "swappedout://" URLs, this happens when a RenderView gets swapped 2870 // - With "swappedout://" URLs, this happens when a RenderView gets swapped
2846 // out for a cross-process navigation, and it turns into a placeholder for 2871 // out for a cross-process navigation, and it turns into a placeholder for
2847 // one being rendered in a different process. 2872 // one being rendered in a different process.
2848 // - Also, there might be more than one RenderFrameHost sharing the same 2873 // - Also, there might be more than one RenderFrameHost sharing the same
2849 // FrameTreeNode (and thus sharing its ID) each sending a start. 2874 // FrameTreeNode (and thus sharing its ID) each sending a start.
2850 // - But in the future, once clamy@ moves navigation network requests to the 2875 // - But in the future, once clamy@ moves navigation network requests to the
2851 // browser process, there's a good chance that callbacks about starting and 2876 // browser process, there's a good chance that callbacks about starting and
2852 // stopping will all be handled by the browser. When that happens, there 2877 // stopping will all be handled by the browser. When that happens, there
2853 // should no longer be a start/stop call imbalance. TODO(avi): When this 2878 // should no longer be a start/stop call imbalance. TODO(avi): When this
2854 // future arrives, update this code to not allow this case. 2879 // future arrives, update this code to not allow this case.
2855 if (rfh->frame_tree_node()->is_loading()) 2880 if (rfh->frame_tree_node()->is_loading())
2856 return; 2881 return;
2857 2882
2858 DCHECK_GE(loading_frames_in_progress_, 0); 2883 if (!IsFrameTreeLoading())
2859 if (loading_frames_in_progress_ == 0)
2860 DidStartLoading(rfh, to_different_document); 2884 DidStartLoading(rfh, to_different_document);
2861 2885
2862 ++loading_frames_in_progress_;
2863 rfh->frame_tree_node()->set_is_loading(true); 2886 rfh->frame_tree_node()->set_is_loading(true);
2887 rfh->frame_tree_node()->set_loading_progress(
2888 FrameTreeNode::kLoadingProgressMinimum);
2864 2889
2865 // Notify the RenderFrameHostManager of the event. 2890 // Notify the RenderFrameHostManager of the event.
2866 rfh->frame_tree_node()->render_manager()->OnDidStartLoading(); 2891 rfh->frame_tree_node()->render_manager()->OnDidStartLoading();
2867 2892
2868 loading_progresses_[render_frame_id] = kMinimumLoadingProgress;
2869 SendLoadProgressChanged(); 2893 SendLoadProgressChanged();
2870 } 2894 }
2871 2895
2872 void WebContentsImpl::OnDidStopLoading() { 2896 void WebContentsImpl::OnDidStopLoading() {
2873 if (!HasValidFrameSource()) 2897 if (!HasValidFrameSource())
2874 return; 2898 return;
2875 2899
2876 RenderFrameHostImpl* rfh = 2900 RenderFrameHostImpl* rfh =
2877 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2901 static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2878 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); 2902
2903 // StopLoading was called for an older navigation, ignore.
2904 if (rfh->frame_tree_node()->pending_frame_host() != rfh)
2905 return;
2906
2907 DCHECK(rfh->frame_tree_node()->is_loading());
2879 rfh->frame_tree_node()->set_is_loading(false); 2908 rfh->frame_tree_node()->set_is_loading(false);
2880 2909
2881 if (loading_progresses_.find(render_frame_id) != loading_progresses_.end()) { 2910 // This method should never be called when the frame is not loading.
nasko 2015/02/23 16:54:43 A DCHECK is warranted every time we have a "should
Fabrice (no longer in Chrome) 2015/02/23 20:02:06 This got shuffled around, the comment is at the pr
2882 // Load stopped while we were still tracking load. Make sure we update 2911 rfh->frame_tree_node()->set_loading_progress(
2883 // progress based on this frame's completion. 2912 FrameTreeNode::kLoadingProgressDone);
2884 loading_progresses_[render_frame_id] = 1.0; 2913
2885 SendLoadProgressChanged(); 2914 // Update progress based on this frame's completion.
2886 // Then we clean-up our states. 2915 SendLoadProgressChanged();
2887 if (loading_total_progress_ == 1.0) 2916 // Then clean-up the states.
2888 ResetLoadProgressState(); 2917 if (loading_total_progress_ == 1.0)
2889 } 2918 ResetLoadProgressState();
2890 2919
2891 // Notify the RenderFrameHostManager of the event. 2920 // Notify the RenderFrameHostManager of the event.
2892 rfh->frame_tree_node()->render_manager()->OnDidStopLoading(); 2921 rfh->frame_tree_node()->render_manager()->OnDidStopLoading();
2893 2922
2894 // TODO(japhet): This should be a DCHECK, but the pdf plugin sometimes 2923 if (!IsFrameTreeLoading())
2895 // calls DidStopLoading() without a matching DidStartLoading().
2896 if (loading_frames_in_progress_ == 0)
2897 return;
2898 --loading_frames_in_progress_;
2899 if (loading_frames_in_progress_ == 0)
2900 DidStopLoading(rfh); 2924 DidStopLoading(rfh);
2901 } 2925 }
2902 2926
2903 void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) { 2927 void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) {
2904 if (!HasValidFrameSource()) 2928 if (!HasValidFrameSource())
2905 return; 2929 return;
2906 2930
2907 RenderFrameHostImpl* rfh = 2931 RenderFrameHostImpl* rfh =
2908 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2932 static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2909 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2910 2933
2911 loading_progresses_[render_frame_id] = load_progress; 2934 rfh->frame_tree_node()->set_loading_progress(load_progress);
2912 2935
2913 // We notify progress change immediately for the first and last updates. 2936 // We notify progress change immediately for the first and last updates.
2914 // Also, since the message loop may be pretty busy when a page is loaded, it 2937 // Also, since the message loop may be pretty busy when a page is loaded, it
2915 // might not execute a posted task in a timely manner so we make sure to 2938 // might not execute a posted task in a timely manner so we make sure to
2916 // immediately send progress report if enough time has passed. 2939 // immediately send progress report if enough time has passed.
2917 base::TimeDelta min_delay = 2940 base::TimeDelta min_delay =
2918 base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS); 2941 base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS);
2919 if (load_progress == 1.0 || loading_last_progress_update_.is_null() || 2942 if (load_progress == 1.0 || loading_last_progress_update_.is_null() ||
2920 base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) { 2943 base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) {
2921 // If there is a pending task to send progress, it is now obsolete. 2944 // 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
3383 Details<std::pair<NavigationEntry*, bool> >(&details)); 3406 Details<std::pair<NavigationEntry*, bool> >(&details));
3384 3407
3385 return true; 3408 return true;
3386 } 3409 }
3387 3410
3388 void WebContentsImpl::SendLoadProgressChanged() { 3411 void WebContentsImpl::SendLoadProgressChanged() {
3389 loading_last_progress_update_ = base::TimeTicks::Now(); 3412 loading_last_progress_update_ = base::TimeTicks::Now();
3390 double progress = 0.0; 3413 double progress = 0.0;
3391 int frame_count = 0; 3414 int frame_count = 0;
3392 3415
3393 for (LoadingProgressMap::iterator it = loading_progresses_.begin(); 3416 frame_tree_.ForEach(
3394 it != loading_progresses_.end(); 3417 base::Bind(&CollectLoadProgress, &progress, &frame_count));
3395 ++it) {
3396 progress += it->second;
3397 ++frame_count;
3398 }
3399 if (frame_count == 0)
3400 return;
3401 progress /= frame_count; 3418 progress /= frame_count;
3402 DCHECK(progress <= 1.0); 3419 DCHECK(progress <= 1.0);
3403 3420
3404 if (progress <= loading_total_progress_) 3421 if (progress <= loading_total_progress_)
3405 return; 3422 return;
3406 loading_total_progress_ = progress; 3423 loading_total_progress_ = progress;
3407 3424
3408 if (delegate_) 3425 if (delegate_)
3409 delegate_->LoadProgressChanged(this, progress); 3426 delegate_->LoadProgressChanged(this, progress);
3410 } 3427 }
3411 3428
3412 void WebContentsImpl::ResetLoadProgressState() { 3429 void WebContentsImpl::ResetLoadProgressState() {
3413 loading_progresses_.clear();
3414 loading_total_progress_ = 0.0; 3430 loading_total_progress_ = 0.0;
3415 loading_weak_factory_.InvalidateWeakPtrs(); 3431 loading_weak_factory_.InvalidateWeakPtrs();
3416 loading_last_progress_update_ = base::TimeTicks(); 3432 loading_last_progress_update_ = base::TimeTicks();
3417 } 3433 }
3418 3434
3419 void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host, 3435 void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
3420 RenderViewHost* new_host) { 3436 RenderViewHost* new_host) {
3421 // After sending out a swap notification, we need to send a disconnect 3437 // After sending out a swap notification, we need to send a disconnect
3422 // notification so that clients that pick up a pointer to |this| can NULL the 3438 // notification so that clients that pick up a pointer to |this| can NULL the
3423 // pointer. See Bug 1230284. 3439 // pointer. See Bug 1230284.
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
3720 3736
3721 SetIsLoading(rvh, false, true, NULL); 3737 SetIsLoading(rvh, false, true, NULL);
3722 NotifyDisconnected(); 3738 NotifyDisconnected();
3723 SetIsCrashed(status, error_code); 3739 SetIsCrashed(status, error_code);
3724 3740
3725 // Reset the loading progress. TODO(avi): What does it mean to have a 3741 // 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 3742 // "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 3743 // webpage? Once this function is called at a more granular frame level, we
3728 // probably will need to more granularly reset the state here. 3744 // probably will need to more granularly reset the state here.
3729 ResetLoadProgressState(); 3745 ResetLoadProgressState();
3730 loading_frames_in_progress_ = 0;
3731 3746
3732 FOR_EACH_OBSERVER(WebContentsObserver, 3747 FOR_EACH_OBSERVER(WebContentsObserver,
3733 observers_, 3748 observers_,
3734 RenderProcessGone(GetCrashedStatus())); 3749 RenderProcessGone(GetCrashedStatus()));
3735 } 3750 }
3736 3751
3737 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { 3752 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
3738 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh)); 3753 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
3739 } 3754 }
3740 3755
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after
4512 FrameTreeNode* node = frame_tree_.root(); 4527 FrameTreeNode* node = frame_tree_.root();
4513 node->render_manager()->ResumeResponseDeferredAtStart(); 4528 node->render_manager()->ResumeResponseDeferredAtStart();
4514 } 4529 }
4515 4530
4516 void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) { 4531 void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) {
4517 force_disable_overscroll_content_ = force_disable; 4532 force_disable_overscroll_content_ = force_disable;
4518 if (view_) 4533 if (view_)
4519 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); 4534 view_->SetOverscrollControllerEnabled(CanOverscrollContent());
4520 } 4535 }
4521 4536
4537 bool WebContentsImpl::IsFrameTreeLoading() {
4538 bool is_loading = false;
4539 frame_tree_.ForEach(base::Bind(&IsNodeLoading, &is_loading));
4540 return is_loading;
4541 }
4542
4522 } // namespace content 4543 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698