OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome/browser/prerender/prerender_contents.h" | 5 #include "chrome/browser/prerender/prerender_contents.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/process_util.h" | 10 #include "base/process_util.h" |
11 #include "base/task.h" | 11 #include "base/task.h" |
12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 #include "chrome/browser/background_contents_service.h" | 13 #include "chrome/browser/background_contents_service.h" |
14 #include "chrome/browser/browser_process.h" | 14 #include "chrome/browser/browser_process.h" |
15 #include "chrome/browser/prerender/prerender_final_status.h" | 15 #include "chrome/browser/prerender/prerender_final_status.h" |
16 #include "chrome/browser/prerender/prerender_manager.h" | 16 #include "chrome/browser/prerender/prerender_manager.h" |
17 #include "chrome/browser/prerender/prerender_render_widget_host_view.h" | 17 #include "chrome/browser/prerender/prerender_render_widget_host_view.h" |
18 #include "chrome/browser/prerender/prerender_tracker.h" | |
18 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
19 #include "chrome/browser/renderer_preferences_util.h" | 20 #include "chrome/browser/renderer_preferences_util.h" |
20 #include "chrome/browser/ui/login/login_prompt.h" | 21 #include "chrome/browser/ui/login/login_prompt.h" |
21 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 22 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
22 #include "chrome/common/extensions/extension_constants.h" | 23 #include "chrome/common/extensions/extension_constants.h" |
23 #include "chrome/common/extensions/extension_messages.h" | 24 #include "chrome/common/extensions/extension_messages.h" |
24 #include "chrome/common/icon_messages.h" | 25 #include "chrome/common/icon_messages.h" |
25 #include "chrome/common/render_messages.h" | 26 #include "chrome/common/render_messages.h" |
26 #include "chrome/common/url_constants.h" | 27 #include "chrome/common/url_constants.h" |
27 #include "content/browser/browsing_instance.h" | 28 #include "content/browser/browsing_instance.h" |
(...skipping 24 matching lines...) Expand all Loading... | |
52 bool operator()(const GURL& url) const { | 53 bool operator()(const GURL& url) const { |
53 return url.scheme() == url_.scheme() && | 54 return url.scheme() == url_.scheme() && |
54 url.host() == url_.host() && | 55 url.host() == url_.host() && |
55 url.port() == url_.port() && | 56 url.port() == url_.port() && |
56 url.path() == url_.path() && | 57 url.path() == url_.path() && |
57 url.query() == url_.query(); | 58 url.query() == url_.query(); |
58 } | 59 } |
59 GURL url_; | 60 GURL url_; |
60 }; | 61 }; |
61 | 62 |
62 void AddChildRoutePair(ResourceDispatcherHost* resource_dispatcher_host, | |
63 int child_id, int route_id) { | |
64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
65 resource_dispatcher_host->AddPrerenderChildRoutePair(child_id, route_id); | |
66 } | |
67 | |
68 void RemoveChildRoutePair(ResourceDispatcherHost* resource_dispatcher_host, | |
69 int child_id, int route_id) { | |
70 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
71 resource_dispatcher_host->RemovePrerenderChildRoutePair(child_id, route_id); | |
72 } | |
73 | |
74 } // end namespace | 63 } // end namespace |
75 | 64 |
76 class PrerenderContentsFactoryImpl : public PrerenderContents::Factory { | 65 class PrerenderContentsFactoryImpl : public PrerenderContents::Factory { |
77 public: | 66 public: |
78 virtual PrerenderContents* CreatePrerenderContents( | 67 virtual PrerenderContents* CreatePrerenderContents( |
79 PrerenderManager* prerender_manager, Profile* profile, const GURL& url, | 68 PrerenderManager* prerender_manager, Profile* profile, const GURL& url, |
80 const GURL& referrer) OVERRIDE { | 69 const GURL& referrer) OVERRIDE { |
81 return new PrerenderContents(prerender_manager, profile, url, referrer); | 70 return new PrerenderContents(prerender_manager, profile, url, referrer); |
82 } | 71 } |
83 }; | 72 }; |
84 | 73 |
85 PrerenderContents::PrerenderContents(PrerenderManager* prerender_manager, | 74 PrerenderContents::PrerenderContents(PrerenderManager* prerender_manager, |
86 Profile* profile, | 75 Profile* profile, |
87 const GURL& url, | 76 const GURL& url, |
88 const GURL& referrer) | 77 const GURL& referrer) |
89 : prerender_manager_(prerender_manager), | 78 : prerender_manager_(prerender_manager), |
90 render_view_host_(NULL), | 79 render_view_host_(NULL), |
91 prerender_url_(url), | 80 prerender_url_(url), |
92 referrer_(referrer), | 81 referrer_(referrer), |
93 profile_(profile), | 82 profile_(profile), |
94 page_id_(0), | 83 page_id_(0), |
95 ALLOW_THIS_IN_INITIALIZER_LIST(tab_contents_observer_registrar_(this)), | 84 ALLOW_THIS_IN_INITIALIZER_LIST(tab_contents_observer_registrar_(this)), |
96 has_stopped_loading_(false), | 85 has_stopped_loading_(false), |
97 final_status_(FINAL_STATUS_MAX), | 86 final_status_(FINAL_STATUS_MAX), |
98 prerendering_has_started_(false) { | 87 prerendering_has_started_(false), |
88 child_id_(-1), | |
89 route_id_(-1) { | |
99 DCHECK(prerender_manager != NULL); | 90 DCHECK(prerender_manager != NULL); |
100 } | 91 } |
101 | 92 |
102 bool PrerenderContents::Init() { | 93 bool PrerenderContents::Init() { |
103 if (!AddAliasURL(prerender_url_)) | 94 if (!AddAliasURL(prerender_url_)) |
104 return false; | 95 return false; |
105 return true; | 96 return true; |
106 } | 97 } |
107 | 98 |
108 // static | 99 // static |
(...skipping 20 matching lines...) Expand all Loading... | |
129 render_view_host_->CreateRenderView(string16()); | 120 render_view_host_->CreateRenderView(string16()); |
130 | 121 |
131 OnRenderViewHostCreated(render_view_host_); | 122 OnRenderViewHostCreated(render_view_host_); |
132 | 123 |
133 // Give the RVH a PrerenderRenderWidgetHostView, both so its size can be set | 124 // Give the RVH a PrerenderRenderWidgetHostView, both so its size can be set |
134 // and so that the prerender can be cancelled under certain circumstances. | 125 // and so that the prerender can be cancelled under certain circumstances. |
135 PrerenderRenderWidgetHostView* view = | 126 PrerenderRenderWidgetHostView* view = |
136 new PrerenderRenderWidgetHostView(render_view_host_, this); | 127 new PrerenderRenderWidgetHostView(render_view_host_, this); |
137 view->Init(source_render_view_host->view()); | 128 view->Init(source_render_view_host->view()); |
138 | 129 |
139 // Register this with the ResourceDispatcherHost as a prerender | 130 child_id_ = render_view_host_->process()->id(); |
140 // RenderViewHost. This must be done before the Navigate message to catch all | 131 route_id_ = render_view_host_->routing_id(); |
141 // resource requests, but as it is on the same thread as the Navigate message | |
142 // (IO) there is no race condition. | |
143 int process_id = render_view_host_->process()->id(); | |
144 int view_id = render_view_host_->routing_id(); | |
145 | 132 |
146 BrowserThread::PostTask( | 133 // Register this with the PrerenderTracker as a prerendering RenderViewHost. |
147 BrowserThread::IO, FROM_HERE, | 134 // This must be done before the Navigate message to catch all resource |
148 NewRunnableFunction(&AddChildRoutePair, | 135 // requests. |
149 g_browser_process->resource_dispatcher_host(), | 136 PrerenderTracker::GetInstance()->OnPrerenderingStarted(child_id_, route_id_, |
150 process_id, view_id)); | 137 prerender_manager_); |
151 | 138 |
152 // Close ourselves when the application is shutting down. | 139 // Close ourselves when the application is shutting down. |
153 notification_registrar_.Add(this, NotificationType::APP_TERMINATING, | 140 notification_registrar_.Add(this, NotificationType::APP_TERMINATING, |
154 NotificationService::AllSources()); | 141 NotificationService::AllSources()); |
155 | 142 |
156 // Register for our parent profile to shutdown, so we can shut ourselves down | 143 // Register for our parent profile to shutdown, so we can shut ourselves down |
157 // as well (should only be called for OTR profiles, as we should receive | 144 // as well (should only be called for OTR profiles, as we should receive |
158 // APP_TERMINATING before non-OTR profiles are destroyed). | 145 // APP_TERMINATING before non-OTR profiles are destroyed). |
159 // TODO(tburkard): figure out if this is needed. | 146 // TODO(tburkard): figure out if this is needed. |
160 notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, | 147 notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
231 // Set the size of the new TC to that of the old TC. | 218 // Set the size of the new TC to that of the old TC. |
232 gfx::Rect tab_bounds; | 219 gfx::Rect tab_bounds; |
233 source_tc->view()->GetContainerBounds(&tab_bounds); | 220 source_tc->view()->GetContainerBounds(&tab_bounds); |
234 prerender_contents_->view()->SizeContents(tab_bounds.size()); | 221 prerender_contents_->view()->SizeContents(tab_bounds.size()); |
235 } | 222 } |
236 | 223 |
237 // Register as an observer of the RenderViewHost so we get messages. | 224 // Register as an observer of the RenderViewHost so we get messages. |
238 render_view_host_observer_.reset( | 225 render_view_host_observer_.reset( |
239 new PrerenderRenderViewHostObserver(this, render_view_host_mutable())); | 226 new PrerenderRenderViewHostObserver(this, render_view_host_mutable())); |
240 | 227 |
241 int process_id; | 228 child_id_ = render_view_host()->process()->id(); |
242 int view_id; | 229 route_id_ = render_view_host()->routing_id(); |
243 CHECK(GetChildId(&process_id)); | |
244 CHECK(GetRouteId(&view_id)); | |
245 | 230 |
246 // Register this with the ResourceDispatcherHost as a prerender | 231 // Register this with the ResourceDispatcherHost as a prerender |
247 // RenderViewHost. This must be done before the Navigate message to catch all | 232 // RenderViewHost. This must be done before the Navigate message to catch all |
248 // resource requests, but as it is on the same thread as the Navigate message | 233 // resource requests, but as it is on the same thread as the Navigate message |
249 // (IO) there is no race condition. | 234 // (IO) there is no race condition. |
250 BrowserThread::PostTask( | 235 PrerenderTracker::GetInstance()->OnPrerenderingStarted(child_id_, route_id_, |
251 BrowserThread::IO, FROM_HERE, | 236 prerender_manager_); |
252 NewRunnableFunction(&AddChildRoutePair, | |
253 g_browser_process->resource_dispatcher_host(), | |
254 process_id, view_id)); | |
255 | 237 |
256 // Close ourselves when the application is shutting down. | 238 // Close ourselves when the application is shutting down. |
257 notification_registrar_.Add(this, NotificationType::APP_TERMINATING, | 239 notification_registrar_.Add(this, NotificationType::APP_TERMINATING, |
258 NotificationService::AllSources()); | 240 NotificationService::AllSources()); |
259 | 241 |
260 // Register for our parent profile to shutdown, so we can shut ourselves down | 242 // Register for our parent profile to shutdown, so we can shut ourselves down |
261 // as well (should only be called for OTR profiles, as we should receive | 243 // as well (should only be called for OTR profiles, as we should receive |
262 // APP_TERMINATING before non-OTR profiles are destroyed). | 244 // APP_TERMINATING before non-OTR profiles are destroyed). |
263 // TODO(tburkard): figure out if this is needed. | 245 // TODO(tburkard): figure out if this is needed. |
264 notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, | 246 notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, |
(...skipping 27 matching lines...) Expand all Loading... | |
292 | 274 |
293 DCHECK(load_start_time_.is_null()); | 275 DCHECK(load_start_time_.is_null()); |
294 load_start_time_ = base::TimeTicks::Now(); | 276 load_start_time_ = base::TimeTicks::Now(); |
295 | 277 |
296 new_contents->controller().LoadURL(prerender_url_, | 278 new_contents->controller().LoadURL(prerender_url_, |
297 referrer_, PageTransition::LINK); | 279 referrer_, PageTransition::LINK); |
298 } | 280 } |
299 | 281 |
300 bool PrerenderContents::GetChildId(int* child_id) const { | 282 bool PrerenderContents::GetChildId(int* child_id) const { |
301 CHECK(child_id); | 283 CHECK(child_id); |
302 const RenderViewHost* prerender_render_view_host = render_view_host(); | 284 *child_id = child_id_; |
303 if (prerender_render_view_host) { | 285 return child_id_ >= 0; |
dominich
2011/05/19 15:49:33
This should be a != -1 as you never expect a value
mmenke
2011/05/19 16:40:42
Done (for all the checks in this file, also update
| |
304 *child_id = prerender_render_view_host->process()->id(); | |
305 return true; | |
306 } | |
307 return false; | |
308 } | 286 } |
309 | 287 |
310 bool PrerenderContents::GetRouteId(int* route_id) const { | 288 bool PrerenderContents::GetRouteId(int* route_id) const { |
311 CHECK(route_id); | 289 CHECK(route_id); |
312 const RenderViewHost* prerender_render_view_host = render_view_host(); | 290 *route_id = route_id_; |
313 if (prerender_render_view_host) { | 291 return route_id_ >= 0; |
dominich
2011/05/19 15:49:33
See above comment re != -1.
| |
314 *route_id = prerender_render_view_host->routing_id(); | |
315 return true; | |
316 } | |
317 return false; | |
318 } | 292 } |
319 | 293 |
320 void PrerenderContents::set_final_status(FinalStatus final_status) { | 294 void PrerenderContents::set_final_status(FinalStatus final_status) { |
321 DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX); | 295 DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX); |
322 DCHECK(final_status_ == FINAL_STATUS_MAX || | 296 DCHECK(final_status_ == FINAL_STATUS_MAX || |
323 final_status_ == FINAL_STATUS_CONTROL_GROUP); | 297 final_status_ == FINAL_STATUS_CONTROL_GROUP); |
324 | 298 |
325 // Don't override final_status_ if it's FINAL_STATUS_CONTROL_GROUP, | 299 // Don't override final_status_ if it's FINAL_STATUS_CONTROL_GROUP, |
326 // otherwise data will be collected in the Prerender.FinalStatus histogram. | 300 // otherwise data will be collected in the Prerender.FinalStatus histogram. |
327 if (final_status_ == FINAL_STATUS_CONTROL_GROUP) | 301 if (final_status_ == FINAL_STATUS_CONTROL_GROUP) |
328 return; | 302 return; |
329 | 303 |
330 final_status_ = final_status; | 304 final_status_ = final_status; |
331 } | 305 } |
332 | 306 |
333 FinalStatus PrerenderContents::final_status() const { | 307 FinalStatus PrerenderContents::final_status() const { |
334 return final_status_; | 308 return final_status_; |
335 } | 309 } |
336 | 310 |
337 PrerenderContents::~PrerenderContents() { | 311 PrerenderContents::~PrerenderContents() { |
338 DCHECK(final_status_ != FINAL_STATUS_MAX); | 312 DCHECK(final_status_ != FINAL_STATUS_MAX); |
339 | 313 |
340 // If we haven't even started prerendering, we were just in the control | 314 // If we haven't even started prerendering, we were just in the control |
341 // group, which means we do not want to record the status. | 315 // group, which means we do not want to record the status. |
342 if (prerendering_has_started()) | 316 if (prerendering_has_started()) |
343 RecordFinalStatus(final_status_); | 317 RecordFinalStatus(final_status_); |
344 | 318 |
345 if (render_view_host_ || prerender_contents_.get()) { | 319 if (render_view_host_ || prerender_contents_.get()) { |
346 RenderViewHost* prerender_render_view_host = render_view_host_mutable(); | |
347 | |
348 int process_id = prerender_render_view_host->process()->id(); | |
349 int view_id = prerender_render_view_host->routing_id(); | |
350 | |
351 BrowserThread::PostTask( | |
352 BrowserThread::IO, FROM_HERE, | |
353 NewRunnableFunction(&RemoveChildRoutePair, | |
354 g_browser_process->resource_dispatcher_host(), | |
355 process_id, view_id)); | |
356 | |
357 // Only delete the RenderViewHost if we own it. | 320 // Only delete the RenderViewHost if we own it. |
358 if (render_view_host_) | 321 if (render_view_host_) |
359 render_view_host_->Shutdown(); | 322 render_view_host_->Shutdown(); |
360 } | 323 } |
324 | |
325 if (child_id_ >= 0 && route_id_ >= 0) { | |
326 PrerenderTracker::GetInstance()->OnPrerenderingFinished( | |
327 child_id_, route_id_); | |
328 } | |
361 } | 329 } |
362 | 330 |
363 RenderViewHostDelegate::View* PrerenderContents::GetViewDelegate() { | 331 RenderViewHostDelegate::View* PrerenderContents::GetViewDelegate() { |
364 return this; | 332 return this; |
365 } | 333 } |
366 | 334 |
367 const GURL& PrerenderContents::GetURL() const { | 335 const GURL& PrerenderContents::GetURL() const { |
368 return url_; | 336 return url_; |
369 } | 337 } |
370 | 338 |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 } | 642 } |
675 | 643 |
676 void PrerenderContents::DidStopLoading() { | 644 void PrerenderContents::DidStopLoading() { |
677 has_stopped_loading_ = true; | 645 has_stopped_loading_ = true; |
678 } | 646 } |
679 | 647 |
680 void PrerenderContents::Destroy(FinalStatus final_status) { | 648 void PrerenderContents::Destroy(FinalStatus final_status) { |
681 if (prerender_manager_->IsPendingDelete(this)) | 649 if (prerender_manager_->IsPendingDelete(this)) |
682 return; | 650 return; |
683 | 651 |
652 if (child_id_ >= 0 && route_id_ >= 0) { | |
653 // Cancel the prerender in the PrerenderTracker. This is needed | |
654 // because destroy may be called directly from the UI thread without calling | |
655 // TryCancel(). This is difficult to completely avoid, since prerendering | |
656 // can be cancelled before a RenderView is created. | |
657 bool is_cancelled = | |
658 PrerenderTracker::GetInstance()->TryCancel(child_id_, route_id_, | |
659 final_status); | |
660 DCHECK(is_cancelled); | |
661 | |
662 // A different final status may have been set already from another thread. | |
663 // If so, use it instead. | |
664 if (!PrerenderTracker::GetInstance()->GetFinalStatus(child_id_, route_id_, | |
665 &final_status)) { | |
666 NOTREACHED(); | |
dominich
2011/05/19 15:49:33
Can this not be CHECK(PrerenderTracker::GetInstanc
mmenke
2011/05/19 16:40:42
A CHECK results in a crash in release builds, whic
dominich
2011/05/19 16:55:47
I thought NOTREACHED was a CHECK rather than a DCH
| |
667 } | |
668 } | |
669 | |
684 prerender_manager_->MoveEntryToPendingDelete(this); | 670 prerender_manager_->MoveEntryToPendingDelete(this); |
685 set_final_status(final_status); | 671 set_final_status(final_status); |
686 // We may destroy the PrerenderContents before we have initialized the | 672 // We may destroy the PrerenderContents before we have initialized the |
687 // RenderViewHost. Otherwise set the Observer's PrerenderContents to NULL to | 673 // RenderViewHost. Otherwise set the Observer's PrerenderContents to NULL to |
688 // avoid any more messages being sent. | 674 // avoid any more messages being sent. |
689 if (render_view_host_observer_.get()) | 675 if (render_view_host_observer_.get()) |
690 render_view_host_observer_->set_prerender_contents(NULL); | 676 render_view_host_observer_->set_prerender_contents(NULL); |
691 } | 677 } |
692 | 678 |
693 void PrerenderContents::RendererUnresponsive(RenderViewHost* render_view_host, | 679 void PrerenderContents::RendererUnresponsive(RenderViewHost* render_view_host, |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
754 // used. | 740 // used. |
755 if (UseTabContents()) { | 741 if (UseTabContents()) { |
756 if (!prerender_contents_.get()) | 742 if (!prerender_contents_.get()) |
757 return NULL; | 743 return NULL; |
758 return prerender_contents_->render_view_host(); | 744 return prerender_contents_->render_view_host(); |
759 } | 745 } |
760 return render_view_host_; | 746 return render_view_host_; |
761 } | 747 } |
762 | 748 |
763 } // namespace prerender | 749 } // namespace prerender |
OLD | NEW |