Chromium Code Reviews| 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 DCHECK_GE(child_id_, -1); |
| 303 if (prerender_render_view_host) { | 285 *child_id = child_id_; |
| 304 *child_id = prerender_render_view_host->process()->id(); | 286 return child_id_ != -1; |
| 305 return true; | |
| 306 } | |
| 307 return false; | |
| 308 } | 287 } |
| 309 | 288 |
| 310 bool PrerenderContents::GetRouteId(int* route_id) const { | 289 bool PrerenderContents::GetRouteId(int* route_id) const { |
| 311 CHECK(route_id); | 290 CHECK(route_id); |
| 312 const RenderViewHost* prerender_render_view_host = render_view_host(); | 291 DCHECK_GE(route_id_, -1); |
| 313 if (prerender_render_view_host) { | 292 *route_id = route_id_; |
| 314 *route_id = prerender_render_view_host->routing_id(); | 293 return route_id_ != -1; |
| 315 return true; | |
| 316 } | |
| 317 return false; | |
| 318 } | 294 } |
| 319 | 295 |
| 320 void PrerenderContents::set_final_status(FinalStatus final_status) { | 296 void PrerenderContents::set_final_status(FinalStatus final_status) { |
| 321 DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX); | 297 DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX); |
| 322 DCHECK(final_status_ == FINAL_STATUS_MAX || | 298 DCHECK(final_status_ == FINAL_STATUS_MAX || |
| 323 final_status_ == FINAL_STATUS_CONTROL_GROUP); | 299 final_status_ == FINAL_STATUS_CONTROL_GROUP); |
| 324 | 300 |
| 325 // Don't override final_status_ if it's FINAL_STATUS_CONTROL_GROUP, | 301 // Don't override final_status_ if it's FINAL_STATUS_CONTROL_GROUP, |
| 326 // otherwise data will be collected in the Prerender.FinalStatus histogram. | 302 // otherwise data will be collected in the Prerender.FinalStatus histogram. |
| 327 if (final_status_ == FINAL_STATUS_CONTROL_GROUP) | 303 if (final_status_ == FINAL_STATUS_CONTROL_GROUP) |
| 328 return; | 304 return; |
| 329 | 305 |
| 330 final_status_ = final_status; | 306 final_status_ = final_status; |
| 331 } | 307 } |
| 332 | 308 |
| 333 FinalStatus PrerenderContents::final_status() const { | 309 FinalStatus PrerenderContents::final_status() const { |
| 334 return final_status_; | 310 return final_status_; |
| 335 } | 311 } |
| 336 | 312 |
| 337 PrerenderContents::~PrerenderContents() { | 313 PrerenderContents::~PrerenderContents() { |
| 338 DCHECK(final_status_ != FINAL_STATUS_MAX); | 314 DCHECK(final_status_ != FINAL_STATUS_MAX); |
| 339 | 315 |
| 340 // If we haven't even started prerendering, we were just in the control | 316 // 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. | 317 // group, which means we do not want to record the status. |
| 342 if (prerendering_has_started()) | 318 if (prerendering_has_started()) |
| 343 RecordFinalStatus(final_status_); | 319 RecordFinalStatus(final_status_); |
| 344 | 320 |
| 345 if (render_view_host_ || prerender_contents_.get()) { | 321 if (render_view_host_ || prerender_contents_.get()) { |
|
dominich
2011/05/19 16:55:47
there's no need for this prerender_contents_.get()
mmenke
2011/05/19 17:09:24
Good point.
| |
| 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. | 322 // Only delete the RenderViewHost if we own it. |
| 358 if (render_view_host_) | 323 if (render_view_host_) |
| 359 render_view_host_->Shutdown(); | 324 render_view_host_->Shutdown(); |
| 360 } | 325 } |
| 326 | |
| 327 if (child_id_ != -1 && route_id_ != -1) { | |
| 328 PrerenderTracker::GetInstance()->OnPrerenderingFinished( | |
| 329 child_id_, route_id_); | |
| 330 } | |
| 361 } | 331 } |
| 362 | 332 |
| 363 RenderViewHostDelegate::View* PrerenderContents::GetViewDelegate() { | 333 RenderViewHostDelegate::View* PrerenderContents::GetViewDelegate() { |
| 364 return this; | 334 return this; |
| 365 } | 335 } |
| 366 | 336 |
| 367 const GURL& PrerenderContents::GetURL() const { | 337 const GURL& PrerenderContents::GetURL() const { |
| 368 return url_; | 338 return url_; |
| 369 } | 339 } |
| 370 | 340 |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 } | 644 } |
| 675 | 645 |
| 676 void PrerenderContents::DidStopLoading() { | 646 void PrerenderContents::DidStopLoading() { |
| 677 has_stopped_loading_ = true; | 647 has_stopped_loading_ = true; |
| 678 } | 648 } |
| 679 | 649 |
| 680 void PrerenderContents::Destroy(FinalStatus final_status) { | 650 void PrerenderContents::Destroy(FinalStatus final_status) { |
| 681 if (prerender_manager_->IsPendingDelete(this)) | 651 if (prerender_manager_->IsPendingDelete(this)) |
| 682 return; | 652 return; |
| 683 | 653 |
| 654 if (child_id_ != -1 && route_id_ != -1) { | |
| 655 // Cancel the prerender in the PrerenderTracker. This is needed | |
| 656 // because destroy may be called directly from the UI thread without calling | |
| 657 // TryCancel(). This is difficult to completely avoid, since prerendering | |
| 658 // can be cancelled before a RenderView is created. | |
| 659 bool is_cancelled = | |
| 660 PrerenderTracker::GetInstance()->TryCancel(child_id_, route_id_, | |
| 661 final_status); | |
| 662 DCHECK(is_cancelled); | |
|
dominich
2011/05/19 16:55:47
Consider making this a CHECK if it should never be
mmenke
2011/05/19 17:09:24
Done. If it ever happens, I suspect we'd crash a
| |
| 663 | |
| 664 // A different final status may have been set already from another thread. | |
| 665 // If so, use it instead. | |
| 666 if (!PrerenderTracker::GetInstance()->GetFinalStatus(child_id_, route_id_, | |
| 667 &final_status)) { | |
| 668 NOTREACHED(); | |
| 669 } | |
| 670 } | |
| 671 | |
| 684 prerender_manager_->MoveEntryToPendingDelete(this); | 672 prerender_manager_->MoveEntryToPendingDelete(this); |
| 685 set_final_status(final_status); | 673 set_final_status(final_status); |
| 686 // We may destroy the PrerenderContents before we have initialized the | 674 // We may destroy the PrerenderContents before we have initialized the |
| 687 // RenderViewHost. Otherwise set the Observer's PrerenderContents to NULL to | 675 // RenderViewHost. Otherwise set the Observer's PrerenderContents to NULL to |
| 688 // avoid any more messages being sent. | 676 // avoid any more messages being sent. |
| 689 if (render_view_host_observer_.get()) | 677 if (render_view_host_observer_.get()) |
| 690 render_view_host_observer_->set_prerender_contents(NULL); | 678 render_view_host_observer_->set_prerender_contents(NULL); |
| 691 } | 679 } |
| 692 | 680 |
| 693 void PrerenderContents::RendererUnresponsive(RenderViewHost* render_view_host, | 681 void PrerenderContents::RendererUnresponsive(RenderViewHost* render_view_host, |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 754 // used. | 742 // used. |
| 755 if (UseTabContents()) { | 743 if (UseTabContents()) { |
| 756 if (!prerender_contents_.get()) | 744 if (!prerender_contents_.get()) |
| 757 return NULL; | 745 return NULL; |
| 758 return prerender_contents_->render_view_host(); | 746 return prerender_contents_->render_view_host(); |
| 759 } | 747 } |
| 760 return render_view_host_; | 748 return render_view_host_; |
| 761 } | 749 } |
| 762 | 750 |
| 763 } // namespace prerender | 751 } // namespace prerender |
| OLD | NEW |