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 "chrome/browser/prerender/prerender_contents.h" | 5 #include "chrome/browser/prerender/prerender_contents.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <functional> | 8 #include <functional> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 else | 66 else |
67 message = new PrerenderMsg_RemovePrerenderURL(url); | 67 message = new PrerenderMsg_RemovePrerenderURL(url); |
68 render_process_host->Send(message); | 68 render_process_host->Send(message); |
69 } | 69 } |
70 | 70 |
71 } // namespace | 71 } // namespace |
72 | 72 |
73 class PrerenderContentsFactoryImpl : public PrerenderContents::Factory { | 73 class PrerenderContentsFactoryImpl : public PrerenderContents::Factory { |
74 public: | 74 public: |
75 virtual PrerenderContents* CreatePrerenderContents( | 75 virtual PrerenderContents* CreatePrerenderContents( |
76 PrerenderManager* prerender_manager, PrerenderTracker* prerender_tracker, | 76 PrerenderManager* prerender_manager, Profile* profile, |
77 Profile* profile, const GURL& url, const content::Referrer& referrer, | 77 const GURL& url, const content::Referrer& referrer, |
78 Origin origin, uint8 experiment_id) OVERRIDE { | 78 Origin origin, uint8 experiment_id) OVERRIDE { |
79 return new PrerenderContents(prerender_manager, prerender_tracker, profile, | 79 return new PrerenderContents(prerender_manager, profile, |
80 url, referrer, origin, experiment_id); | 80 url, referrer, origin, experiment_id); |
81 } | 81 } |
82 }; | 82 }; |
83 | 83 |
84 // TabContentsDelegateImpl ----------------------------------------------------- | 84 // TabContentsDelegateImpl ----------------------------------------------------- |
85 | 85 |
86 class PrerenderContents::TabContentsDelegateImpl | 86 class PrerenderContents::TabContentsDelegateImpl |
87 : public content::WebContentsDelegate { | 87 : public content::WebContentsDelegate { |
88 public: | 88 public: |
89 explicit TabContentsDelegateImpl(PrerenderContents* prerender_contents) : | 89 explicit TabContentsDelegateImpl(PrerenderContents* prerender_contents) : |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
160 bool user_gesture) OVERRIDE { | 160 bool user_gesture) OVERRIDE { |
161 // TODO(mmenke): Consider supporting this if it is a common case during | 161 // TODO(mmenke): Consider supporting this if it is a common case during |
162 // prerenders. | 162 // prerenders. |
163 prerender_contents_->Destroy(FINAL_STATUS_REGISTER_PROTOCOL_HANDLER); | 163 prerender_contents_->Destroy(FINAL_STATUS_REGISTER_PROTOCOL_HANDLER); |
164 } | 164 } |
165 | 165 |
166 private: | 166 private: |
167 PrerenderContents* prerender_contents_; | 167 PrerenderContents* prerender_contents_; |
168 }; | 168 }; |
169 | 169 |
170 PrerenderContents::Observer::Observer() { | |
171 } | |
172 | |
173 PrerenderContents::Observer::~Observer() { | |
174 } | |
175 | |
170 PrerenderContents::PendingPrerenderInfo::PendingPrerenderInfo( | 176 PrerenderContents::PendingPrerenderInfo::PendingPrerenderInfo( |
171 base::WeakPtr<PrerenderHandle> weak_prerender_handle, | 177 base::WeakPtr<PrerenderHandle> weak_prerender_handle, |
172 Origin origin, | 178 Origin origin, |
173 const GURL& url, | 179 const GURL& url, |
174 const content::Referrer& referrer, | 180 const content::Referrer& referrer, |
175 const gfx::Size& size) : weak_prerender_handle(weak_prerender_handle), | 181 const gfx::Size& size) : weak_prerender_handle(weak_prerender_handle), |
176 origin(origin), | 182 origin(origin), |
177 url(url), | 183 url(url), |
178 referrer(referrer), | 184 referrer(referrer), |
179 size(size) { | 185 size(size) { |
(...skipping 15 matching lines...) Expand all Loading... | |
195 prerender_contents_->web_contents()->GetController() | 201 prerender_contents_->web_contents()->GetController() |
196 .GetDefaultSessionStorageNamespace(); | 202 .GetDefaultSessionStorageNamespace(); |
197 } | 203 } |
198 prerender_manager_->StartPendingPrerenders( | 204 prerender_manager_->StartPendingPrerenders( |
199 child_id_, &pending_prerenders_, session_storage_namespace); | 205 child_id_, &pending_prerenders_, session_storage_namespace); |
200 pending_prerenders_.clear(); | 206 pending_prerenders_.clear(); |
201 } | 207 } |
202 | 208 |
203 PrerenderContents::PrerenderContents( | 209 PrerenderContents::PrerenderContents( |
204 PrerenderManager* prerender_manager, | 210 PrerenderManager* prerender_manager, |
205 PrerenderTracker* prerender_tracker, | |
206 Profile* profile, | 211 Profile* profile, |
207 const GURL& url, | 212 const GURL& url, |
208 const content::Referrer& referrer, | 213 const content::Referrer& referrer, |
209 Origin origin, | 214 Origin origin, |
210 uint8 experiment_id) | 215 uint8 experiment_id) |
211 : prerendering_has_started_(false), | 216 : prerendering_has_started_(false), |
212 prerender_manager_(prerender_manager), | 217 prerender_manager_(prerender_manager), |
213 prerender_tracker_(prerender_tracker), | |
214 prerender_url_(url), | 218 prerender_url_(url), |
215 referrer_(referrer), | 219 referrer_(referrer), |
216 profile_(profile), | 220 profile_(profile), |
217 page_id_(0), | 221 page_id_(0), |
218 session_storage_namespace_id_(-1), | 222 session_storage_namespace_id_(-1), |
219 has_stopped_loading_(false), | 223 has_stopped_loading_(false), |
220 has_finished_loading_(false), | 224 has_finished_loading_(false), |
221 final_status_(FINAL_STATUS_MAX), | 225 final_status_(FINAL_STATUS_MAX), |
222 match_complete_status_(MATCH_COMPLETE_DEFAULT), | 226 match_complete_status_(MATCH_COMPLETE_DEFAULT), |
223 prerendering_has_been_cancelled_(false), | 227 prerendering_has_been_cancelled_(false), |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
277 InformRenderProcessAboutPrerender(prerender_url_, true, | 281 InformRenderProcessAboutPrerender(prerender_url_, true, |
278 creator_child_id_); | 282 creator_child_id_); |
279 | 283 |
280 DCHECK(load_start_time_.is_null()); | 284 DCHECK(load_start_time_.is_null()); |
281 load_start_time_ = base::TimeTicks::Now(); | 285 load_start_time_ = base::TimeTicks::Now(); |
282 | 286 |
283 // Everything after this point sets up the WebContents object and associated | 287 // Everything after this point sets up the WebContents object and associated |
284 // RenderView for the prerender page. Don't do this for members of the | 288 // RenderView for the prerender page. Don't do this for members of the |
285 // control group. | 289 // control group. |
286 if (is_control_group) | 290 if (is_control_group) |
287 return; | 291 return; |
mmenke
2012/12/06 19:54:22
This is Weird. We use prerender_manager_->IsContr
gavinp
2012/12/07 17:37:04
Done.
| |
288 | 292 |
289 prerendering_has_started_ = true; | 293 prerendering_has_started_ = true; |
290 | 294 |
291 WebContents* new_contents = CreateWebContents(session_storage_namespace); | 295 WebContents* new_contents = CreateWebContents(session_storage_namespace); |
292 prerender_contents_.reset( | 296 prerender_contents_.reset( |
293 TabContents::Factory::CreateTabContents(new_contents)); | 297 TabContents::Factory::CreateTabContents(new_contents)); |
294 content::WebContentsObserver::Observe(new_contents); | 298 content::WebContentsObserver::Observe(new_contents); |
295 | 299 |
296 tab_contents_delegate_.reset(new TabContentsDelegateImpl(this)); | 300 tab_contents_delegate_.reset(new TabContentsDelegateImpl(this)); |
297 new_contents->SetDelegate(tab_contents_delegate_.get()); | 301 new_contents->SetDelegate(tab_contents_delegate_.get()); |
298 | 302 |
299 // Set the size of the prerender WebContents. | 303 // Set the size of the prerender WebContents. |
300 prerender_contents_->web_contents()->GetView()->SizeContents(size_); | 304 prerender_contents_->web_contents()->GetView()->SizeContents(size_); |
301 | 305 |
302 // Register as an observer of the RenderViewHost so we get messages. | 306 // Register as an observer of the RenderViewHost so we get messages. |
303 render_view_host_observer_.reset( | 307 render_view_host_observer_.reset( |
304 new PrerenderRenderViewHostObserver(this, GetRenderViewHostMutable())); | 308 new PrerenderRenderViewHostObserver(this, GetRenderViewHostMutable())); |
305 | 309 |
306 child_id_ = GetRenderViewHost()->GetProcess()->GetID(); | 310 child_id_ = GetRenderViewHost()->GetProcess()->GetID(); |
307 route_id_ = GetRenderViewHost()->GetRoutingID(); | 311 route_id_ = GetRenderViewHost()->GetRoutingID(); |
308 | 312 |
309 // Register this with the ResourceDispatcherHost as a prerender | 313 // Register this with the ResourceDispatcherHost as a prerender |
310 // RenderViewHost. This must be done before the Navigate message to catch all | 314 // RenderViewHost. This must be done before the Navigate message to catch all |
311 // resource requests, but as it is on the same thread as the Navigate message | 315 // resource requests, but as it is on the same thread as the Navigate message |
312 // (IO) there is no race condition. | 316 // (IO) there is no race condition. |
313 prerender_tracker_->OnPrerenderingStarted( | 317 AddObserver(prerender_manager()->prerender_tracker()); |
314 child_id_, | 318 NotifyPrerenderStart(); |
315 route_id_, | |
316 prerender_manager_); | |
317 | 319 |
318 // Close ourselves when the application is shutting down. | 320 // Close ourselves when the application is shutting down. |
319 notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, | 321 notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, |
320 content::NotificationService::AllSources()); | 322 content::NotificationService::AllSources()); |
321 | 323 |
322 // Register for our parent profile to shutdown, so we can shut ourselves down | 324 // Register for our parent profile to shutdown, so we can shut ourselves down |
323 // as well (should only be called for OTR profiles, as we should receive | 325 // as well (should only be called for OTR profiles, as we should receive |
324 // APP_TERMINATING before non-OTR profiles are destroyed). | 326 // APP_TERMINATING before non-OTR profiles are destroyed). |
325 // TODO(tburkard): figure out if this is needed. | 327 // TODO(tburkard): figure out if this is needed. |
326 notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 328 notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
359 return child_id_ != -1; | 361 return child_id_ != -1; |
360 } | 362 } |
361 | 363 |
362 bool PrerenderContents::GetRouteId(int* route_id) const { | 364 bool PrerenderContents::GetRouteId(int* route_id) const { |
363 CHECK(route_id); | 365 CHECK(route_id); |
364 DCHECK_GE(route_id_, -1); | 366 DCHECK_GE(route_id_, -1); |
365 *route_id = route_id_; | 367 *route_id = route_id_; |
366 return route_id_ != -1; | 368 return route_id_ != -1; |
367 } | 369 } |
368 | 370 |
369 void PrerenderContents::set_final_status(FinalStatus final_status) { | 371 void PrerenderContents::SetFinalStatus(FinalStatus final_status) { |
370 DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX); | 372 DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX); |
371 DCHECK(final_status_ == FINAL_STATUS_MAX); | 373 DCHECK(final_status_ == FINAL_STATUS_MAX); |
372 | 374 |
373 final_status_ = final_status; | 375 final_status_ = final_status; |
376 | |
377 if (!prerender_manager_->IsControlGroup() && prerendering_has_started()) | |
378 NotifyPrerenderStop(); | |
374 } | 379 } |
375 | 380 |
376 PrerenderContents::~PrerenderContents() { | 381 PrerenderContents::~PrerenderContents() { |
377 DCHECK(final_status_ != FINAL_STATUS_MAX); | 382 DCHECK_NE(FINAL_STATUS_MAX, final_status_); |
378 DCHECK(prerendering_has_been_cancelled_ || | 383 DCHECK( |
379 final_status_ == FINAL_STATUS_USED); | 384 prerendering_has_been_cancelled_ || final_status_ == FINAL_STATUS_USED); |
380 DCHECK(origin_ != ORIGIN_MAX); | 385 DCHECK_NE(ORIGIN_MAX, origin_); |
381 | 386 |
382 prerender_manager_->RecordFinalStatusWithMatchCompleteStatus( | 387 prerender_manager_->RecordFinalStatusWithMatchCompleteStatus( |
383 origin_, | 388 origin_, experiment_id_, match_complete_status_, final_status_); |
384 experiment_id_, | |
385 match_complete_status_, | |
386 final_status_); | |
387 | 389 |
388 if (child_id_ != -1 && route_id_ != -1) { | 390 if (child_id_ != -1 && route_id_ != -1) { |
389 prerender_tracker_->OnPrerenderingFinished(child_id_, route_id_); | |
390 for (std::vector<GURL>::const_iterator it = alias_urls_.begin(); | 391 for (std::vector<GURL>::const_iterator it = alias_urls_.begin(); |
391 it != alias_urls_.end(); | 392 it != alias_urls_.end(); |
392 ++it) { | 393 ++it) { |
393 InformRenderProcessAboutPrerender(*it, false, creator_child_id_); | 394 InformRenderProcessAboutPrerender(*it, false, creator_child_id_); |
394 } | 395 } |
395 } | 396 } |
396 | 397 |
397 // If we still have a WebContents, clean up anything we need to and then | 398 // If we still have a WebContents, clean up anything we need to and then |
398 // destroy it. | 399 // destroy it. |
399 if (prerender_contents_.get()) | 400 if (prerender_contents_.get()) |
400 delete ReleasePrerenderContents(); | 401 delete ReleasePrerenderContents(); |
401 } | 402 } |
402 | 403 |
404 void PrerenderContents::AddObserver(Observer* observer) { | |
405 DCHECK_EQ(FINAL_STATUS_MAX, final_status_); | |
406 observer_list_.AddObserver(observer); | |
407 } | |
408 | |
403 void PrerenderContents::Observe(int type, | 409 void PrerenderContents::Observe(int type, |
404 const content::NotificationSource& source, | 410 const content::NotificationSource& source, |
405 const content::NotificationDetails& details) { | 411 const content::NotificationDetails& details) { |
406 switch (type) { | 412 switch (type) { |
407 case chrome::NOTIFICATION_PROFILE_DESTROYED: | 413 case chrome::NOTIFICATION_PROFILE_DESTROYED: |
408 Destroy(FINAL_STATUS_PROFILE_DESTROYED); | 414 Destroy(FINAL_STATUS_PROFILE_DESTROYED); |
409 return; | 415 return; |
410 | 416 |
411 case chrome::NOTIFICATION_APP_TERMINATING: | 417 case chrome::NOTIFICATION_APP_TERMINATING: |
412 Destroy(FINAL_STATUS_APP_TERMINATING); | 418 Destroy(FINAL_STATUS_APP_TERMINATING); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
477 WebContents* PrerenderContents::CreateWebContents( | 483 WebContents* PrerenderContents::CreateWebContents( |
478 SessionStorageNamespace* session_storage_namespace) { | 484 SessionStorageNamespace* session_storage_namespace) { |
479 // TODO(ajwong): Remove the temporary map once prerendering is aware of | 485 // TODO(ajwong): Remove the temporary map once prerendering is aware of |
480 // multiple session storage namespaces per tab. | 486 // multiple session storage namespaces per tab. |
481 content::SessionStorageNamespaceMap session_storage_namespace_map; | 487 content::SessionStorageNamespaceMap session_storage_namespace_map; |
482 session_storage_namespace_map[""] = session_storage_namespace; | 488 session_storage_namespace_map[""] = session_storage_namespace; |
483 return WebContents::CreateWithSessionStorage( | 489 return WebContents::CreateWithSessionStorage( |
484 profile_, NULL, MSG_ROUTING_NONE, NULL, session_storage_namespace_map); | 490 profile_, NULL, MSG_ROUTING_NONE, NULL, session_storage_namespace_map); |
485 } | 491 } |
486 | 492 |
493 void PrerenderContents::NotifyPrerenderStart() { | |
494 DCHECK_EQ(FINAL_STATUS_MAX, final_status_); | |
495 FOR_EACH_OBSERVER(Observer, observer_list_, OnPrerenderStart(this)); | |
496 } | |
497 | |
498 void PrerenderContents::NotifyPrerenderStop() { | |
499 DCHECK_NE(FINAL_STATUS_MAX, final_status_); | |
500 FOR_EACH_OBSERVER(Observer, observer_list_, OnPrerenderStop(this)); | |
501 observer_list_.Clear(); | |
502 } | |
503 | |
487 void PrerenderContents::OnUpdateFaviconURL( | 504 void PrerenderContents::OnUpdateFaviconURL( |
488 int32 page_id, | 505 int32 page_id, |
489 const std::vector<FaviconURL>& urls) { | 506 const std::vector<FaviconURL>& urls) { |
490 VLOG(1) << "PrerenderContents::OnUpdateFaviconURL" << icon_url_; | 507 VLOG(1) << "PrerenderContents::OnUpdateFaviconURL" << icon_url_; |
491 for (std::vector<FaviconURL>::const_iterator it = urls.begin(); | 508 for (std::vector<FaviconURL>::const_iterator it = urls.begin(); |
492 it != urls.end(); ++it) { | 509 it != urls.end(); ++it) { |
493 if (it->icon_type == FaviconURL::FAVICON) { | 510 if (it->icon_type == FaviconURL::FAVICON) { |
494 icon_url_ = it->icon_url; | 511 icon_url_ = it->icon_url; |
495 VLOG(1) << icon_url_; | 512 VLOG(1) << icon_url_; |
496 return; | 513 return; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
573 | 590 |
574 void PrerenderContents::Destroy(FinalStatus final_status) { | 591 void PrerenderContents::Destroy(FinalStatus final_status) { |
575 if (prerendering_has_been_cancelled_) | 592 if (prerendering_has_been_cancelled_) |
576 return; | 593 return; |
577 | 594 |
578 if (child_id_ != -1 && route_id_ != -1) { | 595 if (child_id_ != -1 && route_id_ != -1) { |
579 // Cancel the prerender in the PrerenderTracker. This is needed | 596 // Cancel the prerender in the PrerenderTracker. This is needed |
580 // because destroy may be called directly from the UI thread without calling | 597 // because destroy may be called directly from the UI thread without calling |
581 // TryCancel(). This is difficult to completely avoid, since prerendering | 598 // TryCancel(). This is difficult to completely avoid, since prerendering |
582 // can be cancelled before a RenderView is created. | 599 // can be cancelled before a RenderView is created. |
583 bool is_cancelled = prerender_tracker_->TryCancel( | 600 bool is_cancelled = prerender_manager()->prerender_tracker()->TryCancel( |
584 child_id_, route_id_, final_status); | 601 child_id_, route_id_, final_status); |
585 CHECK(is_cancelled); | 602 CHECK(is_cancelled); |
586 | 603 |
587 // A different final status may have been set already from another thread. | 604 // A different final status may have been set already from another thread. |
588 // If so, use it instead. | 605 // If so, use it instead. |
589 if (!prerender_tracker_->GetFinalStatus(child_id_, route_id_, | 606 if (!prerender_manager()->prerender_tracker()-> |
590 &final_status)) { | 607 GetFinalStatus(child_id_, route_id_, &final_status)) { |
591 NOTREACHED(); | 608 NOTREACHED(); |
592 } | 609 } |
593 } | 610 } |
594 set_final_status(final_status); | 611 SetFinalStatus(final_status); |
595 | 612 |
596 prerendering_has_been_cancelled_ = true; | 613 prerendering_has_been_cancelled_ = true; |
597 prerender_manager_->AddToHistory(this); | 614 prerender_manager_->AddToHistory(this); |
598 prerender_manager_->MoveEntryToPendingDelete(this, final_status); | 615 prerender_manager_->MoveEntryToPendingDelete(this, final_status); |
599 | 616 |
600 // We may destroy the PrerenderContents before we have initialized the | 617 // We may destroy the PrerenderContents before we have initialized the |
601 // RenderViewHost. Otherwise set the Observer's PrerenderContents to NULL to | 618 // RenderViewHost. Otherwise set the Observer's PrerenderContents to NULL to |
602 // avoid any more messages being sent. | 619 // avoid any more messages being sent. |
603 if (render_view_host_observer_) | 620 if (render_view_host_observer_) |
604 render_view_host_observer_->set_prerender_contents(NULL); | 621 render_view_host_observer_->set_prerender_contents(NULL); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
685 bool PrerenderContents::IsCrossSiteNavigationPending() const { | 702 bool PrerenderContents::IsCrossSiteNavigationPending() const { |
686 if (!prerender_contents_.get() || !prerender_contents_->web_contents()) | 703 if (!prerender_contents_.get() || !prerender_contents_->web_contents()) |
687 return false; | 704 return false; |
688 const WebContents* web_contents = prerender_contents_->web_contents(); | 705 const WebContents* web_contents = prerender_contents_->web_contents(); |
689 return (web_contents->GetSiteInstance() != | 706 return (web_contents->GetSiteInstance() != |
690 web_contents->GetPendingSiteInstance()); | 707 web_contents->GetPendingSiteInstance()); |
691 } | 708 } |
692 | 709 |
693 | 710 |
694 } // namespace prerender | 711 } // namespace prerender |
OLD | NEW |