OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |