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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 #endif | 114 #endif |
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 | |
125 // This matches what Blink's ProgressTracker has traditionally used for a | |
126 // minimum progress value. | |
127 const double kMinimumLoadingProgress = 0.1; | |
128 | |
129 const char kDotGoogleDotCom[] = ".google.com"; | 124 const char kDotGoogleDotCom[] = ".google.com"; |
130 | 125 |
131 #if defined(OS_ANDROID) | 126 #if defined(OS_ANDROID) |
132 const char kWebContentsAndroidKey[] = "web_contents_android"; | 127 const char kWebContentsAndroidKey[] = "web_contents_android"; |
133 #endif // OS_ANDROID | 128 #endif // OS_ANDROID |
134 | 129 |
135 base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> > | 130 base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> > |
136 g_created_callbacks = LAZY_INSTANCE_INITIALIZER; | 131 g_created_callbacks = LAZY_INSTANCE_INITIALIZER; |
137 | 132 |
138 static int StartDownload(RenderFrameHost* rfh, | 133 static int StartDownload(RenderFrameHost* rfh, |
(...skipping 18 matching lines...) Expand all Loading... | |
157 } | 152 } |
158 | 153 |
159 // Helper function for retrieving all the sites in a frame tree. | 154 // Helper function for retrieving all the sites in a frame tree. |
160 bool CollectSites(BrowserContext* context, | 155 bool CollectSites(BrowserContext* context, |
161 std::set<GURL>* sites, | 156 std::set<GURL>* sites, |
162 FrameTreeNode* node) { | 157 FrameTreeNode* node) { |
163 sites->insert(SiteInstance::GetSiteForURL(context, node->current_url())); | 158 sites->insert(SiteInstance::GetSiteForURL(context, node->current_url())); |
164 return true; | 159 return true; |
165 } | 160 } |
166 | 161 |
162 // Helper function used with FrameTree::ForEach() for retrieving the total | |
163 // loading progress and number of frames in a frame tree. | |
164 bool CollectLoadProgress(double* progress, | |
165 int* frame_count, | |
Charlie Reis
2015/03/05 04:46:18
nit: Wrong indent.
Fabrice (no longer in Chrome)
2015/03/05 12:37:43
Done.
| |
166 FrameTreeNode* node) { | |
167 // Ignore the current frame if it has not started loading. | |
168 double frame_progress = node->GetLoadingProgress(); | |
169 if (frame_progress == RenderFrameHostImpl::kLoadingProgressNotStarted) | |
170 return true; | |
171 | |
172 // Collect progress. | |
173 *progress += node->GetLoadingProgress(); | |
174 (*frame_count)++; | |
175 return true; | |
176 } | |
177 | |
178 // Helper function used with FrameTree::ForEach() to check if at least one of | |
179 // the nodes is loading. | |
180 bool IsNodeLoading(bool* is_loading, FrameTreeNode* node) { | |
181 if (node->IsLoading()) { | |
182 // There is at least one node loading, so abort traversal. | |
183 *is_loading = true; | |
184 return false; | |
185 } | |
186 return true; | |
187 } | |
188 | |
189 // Helper function used with FrameTree::ForEach() to reset the load progress. | |
190 bool ResetLoadProgress(FrameTreeNode* node) { | |
191 node->current_frame_host()->set_loading_progress( | |
192 RenderFrameHostImpl::kLoadingProgressNotStarted); | |
193 return true; | |
194 } | |
195 | |
167 bool ForEachFrameInternal( | 196 bool ForEachFrameInternal( |
168 const base::Callback<void(RenderFrameHost*)>& on_frame, | 197 const base::Callback<void(RenderFrameHost*)>& on_frame, |
169 FrameTreeNode* node) { | 198 FrameTreeNode* node) { |
170 on_frame.Run(node->current_frame_host()); | 199 on_frame.Run(node->current_frame_host()); |
171 return true; | 200 return true; |
172 } | 201 } |
173 | 202 |
174 bool ForEachPendingFrameInternal( | 203 bool ForEachPendingFrameInternal( |
175 const base::Callback<void(RenderFrameHost*)>& on_frame, | 204 const base::Callback<void(RenderFrameHost*)>& on_frame, |
176 FrameTreeNode* node) { | 205 FrameTreeNode* node) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
218 // termination is not allowed for the current RenderFrameHost of | 247 // termination is not allowed for the current RenderFrameHost of |
219 // |frame_tree_node|. Used with FrameTree::ForEach. | 248 // |frame_tree_node|. Used with FrameTree::ForEach. |
220 bool SuddenTerminationAllowed(bool* sudden_termination_allowed, | 249 bool SuddenTerminationAllowed(bool* sudden_termination_allowed, |
221 FrameTreeNode* frame_tree_node) { | 250 FrameTreeNode* frame_tree_node) { |
222 if (frame_tree_node->current_frame_host()->SuddenTerminationAllowed()) | 251 if (frame_tree_node->current_frame_host()->SuddenTerminationAllowed()) |
223 return true; | 252 return true; |
224 *sudden_termination_allowed = false; | 253 *sudden_termination_allowed = false; |
225 return false; | 254 return false; |
226 } | 255 } |
227 | 256 |
257 // Returns true if at least one of the nodes in the |frame_tree| is loading. | |
258 bool IsFrameTreeLoading(FrameTree& frame_tree) { | |
259 bool is_loading = false; | |
260 frame_tree.ForEach(base::Bind(&IsNodeLoading, &is_loading)); | |
261 return is_loading; | |
262 } | |
263 | |
228 } // namespace | 264 } // namespace |
229 | 265 |
230 WebContents* WebContents::Create(const WebContents::CreateParams& params) { | 266 WebContents* WebContents::Create(const WebContents::CreateParams& params) { |
231 return WebContentsImpl::CreateWithOpener( | 267 return WebContentsImpl::CreateWithOpener( |
232 params, static_cast<WebContentsImpl*>(params.opener)); | 268 params, static_cast<WebContentsImpl*>(params.opener)); |
233 } | 269 } |
234 | 270 |
235 WebContents* WebContents::CreateWithSessionStorage( | 271 WebContents* WebContents::CreateWithSessionStorage( |
236 const WebContents::CreateParams& params, | 272 const WebContents::CreateParams& params, |
237 const SessionStorageNamespaceMap& session_storage_namespace_map) { | 273 const SessionStorageNamespaceMap& session_storage_namespace_map) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
327 this, | 363 this, |
328 this, | 364 this, |
329 this), | 365 this), |
330 is_loading_(false), | 366 is_loading_(false), |
331 is_load_to_different_document_(false), | 367 is_load_to_different_document_(false), |
332 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), | 368 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), |
333 crashed_error_code_(0), | 369 crashed_error_code_(0), |
334 waiting_for_response_(false), | 370 waiting_for_response_(false), |
335 load_state_(net::LOAD_STATE_IDLE, base::string16()), | 371 load_state_(net::LOAD_STATE_IDLE, base::string16()), |
336 loading_total_progress_(0.0), | 372 loading_total_progress_(0.0), |
337 loading_frames_in_progress_(0), | |
338 upload_size_(0), | 373 upload_size_(0), |
339 upload_position_(0), | 374 upload_position_(0), |
340 displayed_insecure_content_(false), | 375 displayed_insecure_content_(false), |
341 has_accessed_initial_document_(false), | 376 has_accessed_initial_document_(false), |
342 capturer_count_(0), | 377 capturer_count_(0), |
343 should_normally_be_visible_(true), | 378 should_normally_be_visible_(true), |
344 is_being_destroyed_(false), | 379 is_being_destroyed_(false), |
345 notify_disconnection_(false), | 380 notify_disconnection_(false), |
346 dialog_manager_(NULL), | 381 dialog_manager_(NULL), |
347 is_showing_before_unload_dialog_(false), | 382 is_showing_before_unload_dialog_(false), |
(...skipping 2507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2855 FOR_EACH_OBSERVER( | 2890 FOR_EACH_OBSERVER( |
2856 WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url)); | 2891 WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url)); |
2857 } | 2892 } |
2858 | 2893 |
2859 void WebContentsImpl::OnDidStartLoading(bool to_different_document) { | 2894 void WebContentsImpl::OnDidStartLoading(bool to_different_document) { |
2860 if (!HasValidFrameSource()) | 2895 if (!HasValidFrameSource()) |
2861 return; | 2896 return; |
2862 | 2897 |
2863 RenderFrameHostImpl* rfh = | 2898 RenderFrameHostImpl* rfh = |
2864 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); | 2899 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); |
2865 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); | |
2866 | 2900 |
2867 // Any main frame load to a new document should reset the load progress, since | 2901 // Any main frame load to a new document should reset the load progress, since |
2868 // it will replace the current page and any frames. | 2902 // it will replace the current page and any frames. |
2869 if (to_different_document && !rfh->GetParent()) { | 2903 if (to_different_document && !rfh->GetParent()) { |
2870 ResetLoadProgressState(); | 2904 ResetLoadProgressState(); |
2871 loading_frames_in_progress_ = 0; | 2905 rfh->set_is_loading(false); |
2872 rfh->frame_tree_node()->set_is_loading(false); | |
2873 } | 2906 } |
2874 | 2907 |
2875 // It is possible to get multiple calls to OnDidStartLoading that don't have | 2908 // This method should never be called when the frame is loading. |
2876 // corresponding calls to OnDidStopLoading: | 2909 DCHECK(!rfh->is_loading()); |
2877 // - With "swappedout://" URLs, this happens when a RenderView gets swapped | |
2878 // out for a cross-process navigation, and it turns into a placeholder for | |
2879 // one being rendered in a different process. | |
2880 // - Also, there might be more than one RenderFrameHost sharing the same | |
2881 // FrameTreeNode (and thus sharing its ID) each sending a start. | |
2882 // - But in the future, once clamy@ moves navigation network requests to the | |
2883 // browser process, there's a good chance that callbacks about starting and | |
2884 // stopping will all be handled by the browser. When that happens, there | |
2885 // should no longer be a start/stop call imbalance. TODO(avi): When this | |
2886 // future arrives, update this code to not allow this case. | |
2887 if (rfh->frame_tree_node()->is_loading()) | |
2888 return; | |
2889 | 2910 |
2890 DCHECK_GE(loading_frames_in_progress_, 0); | 2911 if (!IsFrameTreeLoading(frame_tree_)) |
2891 if (loading_frames_in_progress_ == 0) | |
2892 DidStartLoading(rfh, to_different_document); | 2912 DidStartLoading(rfh, to_different_document); |
2893 | 2913 |
2894 ++loading_frames_in_progress_; | 2914 rfh->set_is_loading(true); |
2895 rfh->frame_tree_node()->set_is_loading(true); | 2915 rfh->set_loading_progress(RenderFrameHostImpl::kLoadingProgressMinimum); |
2896 | 2916 |
2897 // Notify the RenderFrameHostManager of the event. | 2917 // Notify the RenderFrameHostManager of the event. |
2898 rfh->frame_tree_node()->render_manager()->OnDidStartLoading(); | 2918 rfh->frame_tree_node()->render_manager()->OnDidStartLoading(); |
2899 | 2919 |
2900 loading_progresses_[render_frame_id] = kMinimumLoadingProgress; | |
2901 SendLoadProgressChanged(); | 2920 SendLoadProgressChanged(); |
2902 } | 2921 } |
2903 | 2922 |
2904 void WebContentsImpl::OnDidStopLoading() { | 2923 void WebContentsImpl::OnDidStopLoading() { |
2905 if (!HasValidFrameSource()) | 2924 if (!HasValidFrameSource()) |
2906 return; | 2925 return; |
2907 | 2926 |
2908 RenderFrameHostImpl* rfh = | 2927 RenderFrameHostImpl* rfh = |
2909 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); | 2928 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); |
2910 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); | |
2911 rfh->frame_tree_node()->set_is_loading(false); | |
2912 | 2929 |
2913 if (loading_progresses_.find(render_frame_id) != loading_progresses_.end()) { | 2930 // This method should never be called when the frame is not loading. |
2914 // Load stopped while we were still tracking load. Make sure we update | 2931 DCHECK(rfh->is_loading()); |
2915 // progress based on this frame's completion. | 2932 rfh->set_is_loading(false); |
2916 loading_progresses_[render_frame_id] = 1.0; | 2933 rfh->set_loading_progress(RenderFrameHostImpl::kLoadingProgressDone); |
2917 SendLoadProgressChanged(); | 2934 |
2918 // Then we clean-up our states. | 2935 // Update progress based on this frame's completion. |
2919 if (loading_total_progress_ == 1.0) | 2936 SendLoadProgressChanged(); |
2920 ResetLoadProgressState(); | 2937 |
2921 } | 2938 // Then clean-up the states. |
2939 if (loading_total_progress_ == 1.0) | |
2940 ResetLoadProgressState(); | |
2922 | 2941 |
2923 // Notify the RenderFrameHostManager of the event. | 2942 // Notify the RenderFrameHostManager of the event. |
2924 rfh->frame_tree_node()->render_manager()->OnDidStopLoading(); | 2943 rfh->frame_tree_node()->render_manager()->OnDidStopLoading(); |
2925 | 2944 |
2926 // TODO(japhet): This should be a DCHECK, but the pdf plugin sometimes | 2945 if (!IsFrameTreeLoading(frame_tree_)) |
2927 // calls DidStopLoading() without a matching DidStartLoading(). | |
2928 if (loading_frames_in_progress_ == 0) | |
2929 return; | |
2930 --loading_frames_in_progress_; | |
2931 if (loading_frames_in_progress_ == 0) | |
2932 DidStopLoading(rfh); | 2946 DidStopLoading(rfh); |
2933 } | 2947 } |
2934 | 2948 |
2935 void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) { | 2949 void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) { |
2936 if (!HasValidFrameSource()) | 2950 if (!HasValidFrameSource()) |
2937 return; | 2951 return; |
2938 | 2952 |
2939 RenderFrameHostImpl* rfh = | 2953 RenderFrameHostImpl* rfh = |
2940 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); | 2954 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); |
2941 int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); | |
2942 | 2955 |
2943 loading_progresses_[render_frame_id] = load_progress; | 2956 rfh->set_loading_progress(load_progress); |
2944 | 2957 |
2945 // We notify progress change immediately for the first and last updates. | 2958 // We notify progress change immediately for the first and last updates. |
2946 // Also, since the message loop may be pretty busy when a page is loaded, it | 2959 // Also, since the message loop may be pretty busy when a page is loaded, it |
2947 // might not execute a posted task in a timely manner so we make sure to | 2960 // might not execute a posted task in a timely manner so we make sure to |
2948 // immediately send progress report if enough time has passed. | 2961 // immediately send progress report if enough time has passed. |
2949 base::TimeDelta min_delay = | 2962 base::TimeDelta min_delay = |
2950 base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS); | 2963 base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS); |
2951 if (load_progress == 1.0 || loading_last_progress_update_.is_null() || | 2964 if (load_progress == 1.0 || loading_last_progress_update_.is_null() || |
2952 base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) { | 2965 base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) { |
2953 // If there is a pending task to send progress, it is now obsolete. | 2966 // 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... | |
3411 Details<std::pair<NavigationEntry*, bool> >(&details)); | 3424 Details<std::pair<NavigationEntry*, bool> >(&details)); |
3412 | 3425 |
3413 return true; | 3426 return true; |
3414 } | 3427 } |
3415 | 3428 |
3416 void WebContentsImpl::SendLoadProgressChanged() { | 3429 void WebContentsImpl::SendLoadProgressChanged() { |
3417 loading_last_progress_update_ = base::TimeTicks::Now(); | 3430 loading_last_progress_update_ = base::TimeTicks::Now(); |
3418 double progress = 0.0; | 3431 double progress = 0.0; |
3419 int frame_count = 0; | 3432 int frame_count = 0; |
3420 | 3433 |
3421 for (LoadingProgressMap::iterator it = loading_progresses_.begin(); | 3434 frame_tree_.ForEach( |
3422 it != loading_progresses_.end(); | 3435 base::Bind(&CollectLoadProgress, &progress, &frame_count)); |
3423 ++it) { | 3436 if (frame_count != 0) |
3424 progress += it->second; | 3437 progress /= frame_count; |
3425 ++frame_count; | 3438 DCHECK_LE(progress, 1.0); |
3426 } | |
3427 if (frame_count == 0) | |
3428 return; | |
3429 progress /= frame_count; | |
3430 DCHECK(progress <= 1.0); | |
3431 | 3439 |
3432 if (progress <= loading_total_progress_) | 3440 if (progress <= loading_total_progress_) |
3433 return; | 3441 return; |
3434 loading_total_progress_ = progress; | 3442 loading_total_progress_ = progress; |
3435 | 3443 |
3436 if (delegate_) | 3444 if (delegate_) |
3437 delegate_->LoadProgressChanged(this, progress); | 3445 delegate_->LoadProgressChanged(this, progress); |
3438 } | 3446 } |
3439 | 3447 |
3440 void WebContentsImpl::ResetLoadProgressState() { | 3448 void WebContentsImpl::ResetLoadProgressState() { |
3441 loading_progresses_.clear(); | 3449 frame_tree_.ForEach(base::Bind(&ResetLoadProgress)); |
3442 loading_total_progress_ = 0.0; | 3450 loading_total_progress_ = 0.0; |
3443 loading_weak_factory_.InvalidateWeakPtrs(); | 3451 loading_weak_factory_.InvalidateWeakPtrs(); |
3444 loading_last_progress_update_ = base::TimeTicks(); | 3452 loading_last_progress_update_ = base::TimeTicks(); |
3445 } | 3453 } |
3446 | 3454 |
3447 void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host, | 3455 void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host, |
3448 RenderViewHost* new_host) { | 3456 RenderViewHost* new_host) { |
3449 // After sending out a swap notification, we need to send a disconnect | 3457 // After sending out a swap notification, we need to send a disconnect |
3450 // notification so that clients that pick up a pointer to |this| can NULL the | 3458 // notification so that clients that pick up a pointer to |this| can NULL the |
3451 // pointer. See Bug 1230284. | 3459 // pointer. See Bug 1230284. |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3736 | 3744 |
3737 SetIsLoading(rvh, false, true, NULL); | 3745 SetIsLoading(rvh, false, true, NULL); |
3738 NotifyDisconnected(); | 3746 NotifyDisconnected(); |
3739 SetIsCrashed(status, error_code); | 3747 SetIsCrashed(status, error_code); |
3740 | 3748 |
3741 // Reset the loading progress. TODO(avi): What does it mean to have a | 3749 // Reset the loading progress. TODO(avi): What does it mean to have a |
3742 // "renderer crash" when there is more than one renderer process serving a | 3750 // "renderer crash" when there is more than one renderer process serving a |
3743 // webpage? Once this function is called at a more granular frame level, we | 3751 // webpage? Once this function is called at a more granular frame level, we |
3744 // probably will need to more granularly reset the state here. | 3752 // probably will need to more granularly reset the state here. |
3745 ResetLoadProgressState(); | 3753 ResetLoadProgressState(); |
3746 loading_frames_in_progress_ = 0; | |
3747 | 3754 |
3748 FOR_EACH_OBSERVER(WebContentsObserver, | 3755 FOR_EACH_OBSERVER(WebContentsObserver, |
3749 observers_, | 3756 observers_, |
3750 RenderProcessGone(GetCrashedStatus())); | 3757 RenderProcessGone(GetCrashedStatus())); |
3751 } | 3758 } |
3752 | 3759 |
3753 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { | 3760 void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { |
3754 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh)); | 3761 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh)); |
3755 } | 3762 } |
3756 | 3763 |
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4535 node->render_manager()->ResumeResponseDeferredAtStart(); | 4542 node->render_manager()->ResumeResponseDeferredAtStart(); |
4536 } | 4543 } |
4537 | 4544 |
4538 void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) { | 4545 void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) { |
4539 force_disable_overscroll_content_ = force_disable; | 4546 force_disable_overscroll_content_ = force_disable; |
4540 if (view_) | 4547 if (view_) |
4541 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); | 4548 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); |
4542 } | 4549 } |
4543 | 4550 |
4544 } // namespace content | 4551 } // namespace content |
OLD | NEW |