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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |