Chromium Code Reviews| 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 <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/process_util.h" | 10 #include "base/process_util.h" |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 36 using content::DownloadItem; | 36 using content::DownloadItem; |
| 37 using content::OpenURLParams; | 37 using content::OpenURLParams; |
| 38 using content::RenderViewHost; | 38 using content::RenderViewHost; |
| 39 using content::ResourceRedirectDetails; | 39 using content::ResourceRedirectDetails; |
| 40 using content::WebContents; | 40 using content::WebContents; |
| 41 | 41 |
| 42 namespace prerender { | 42 namespace prerender { |
| 43 | 43 |
| 44 namespace { | 44 namespace { |
| 45 | 45 |
| 46 // Compares URLs ignoring any ref for the purposes of matching URLs when | 46 // A prerender handle that embeds another prerender and acts as a pass-through. |
| 47 // prerendering. | 47 class PendingPrerender : public PrerenderHandleInterface { |
|
dominich
2012/06/18 15:32:44
I think you're conflating two things here. There's
gavinp
2012/06/18 16:40:48
This class is gone in the next upload. The questio
| |
| 48 struct PrerenderURLPredicate { | 48 public: |
| 49 explicit PrerenderURLPredicate(const GURL& url) | 49 PendingPrerender(); |
| 50 : url_(url) { | |
| 51 } | |
| 52 | 50 |
| 53 bool operator()(const GURL& url) const { | 51 bool is_destroyed() const { return is_destroyed_; } |
| 54 return url.scheme() == url_.scheme() && | 52 void set_prerender(PrerenderHandle prerender) { prerender_ = prerender; } |
| 55 url.host() == url_.host() && | 53 |
| 56 url.port() == url_.port() && | 54 virtual bool DidFinishLoading() const OVERRIDE; |
| 57 url.path() == url_.path() && | 55 virtual bool IsPending() const OVERRIDE; |
| 58 url.query() == url_.query(); | 56 |
| 59 } | 57 private: |
| 60 GURL url_; | 58 virtual ~PendingPrerender() OVERRIDE; |
| 59 virtual void Destroy() OVERRIDE; | |
| 60 | |
| 61 bool is_destroyed_; | |
| 62 PrerenderHandle prerender_; | |
| 61 }; | 63 }; |
| 62 | 64 |
| 65 PendingPrerender::PendingPrerender() : is_destroyed_(false) { } | |
| 66 | |
| 67 bool PendingPrerender::DidFinishLoading() const { | |
| 68 if (!prerender_) | |
| 69 return false; | |
| 70 return prerender_->DidFinishLoading(); | |
| 71 } | |
| 72 | |
| 73 bool PendingPrerender::IsPending() const { | |
| 74 if (!prerender_) | |
| 75 return true; | |
| 76 return prerender_->IsPending(); | |
| 77 } | |
| 78 | |
| 79 PendingPrerender::~PendingPrerender() { | |
| 80 Destroy(); | |
| 81 } | |
| 82 | |
| 83 void PendingPrerender::Destroy() { | |
| 84 is_destroyed_ = true; | |
| 85 } | |
| 86 | |
| 63 // Tells the render process at |child_id| whether |url| is a new prerendered | 87 // Tells the render process at |child_id| whether |url| is a new prerendered |
| 64 // page, or whether |url| is being removed as a prerendered page. Currently | 88 // page, or whether |url| is being removed as a prerendered page. Currently |
| 65 // this will only inform the render process that created the prerendered page | 89 // this will only inform the render process that created the prerendered page |
| 66 // with <link rel="prerender"> tags about it. This means that if the user | 90 // with <link rel="prerender"> tags about it. This means that if the user |
| 67 // clicks on a link for a prerendered URL in a different page, the prerender | 91 // clicks on a link for a prerendered URL in a different page, the prerender |
| 68 // will not be swapped in. | 92 // will not be swapped in. |
| 69 void InformRenderProcessAboutPrerender(const GURL& url, | 93 void InformRenderProcessAboutPrerender(const GURL& url, |
| 70 bool is_add, | 94 bool is_add, |
| 71 int child_id) { | 95 int child_id) { |
| 72 if (child_id < 0) | 96 if (child_id < 0) |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 90 virtual PrerenderContents* CreatePrerenderContents( | 114 virtual PrerenderContents* CreatePrerenderContents( |
| 91 PrerenderManager* prerender_manager, PrerenderTracker* prerender_tracker, | 115 PrerenderManager* prerender_manager, PrerenderTracker* prerender_tracker, |
| 92 Profile* profile, const GURL& url, const content::Referrer& referrer, | 116 Profile* profile, const GURL& url, const content::Referrer& referrer, |
| 93 Origin origin, uint8 experiment_id) OVERRIDE { | 117 Origin origin, uint8 experiment_id) OVERRIDE { |
| 94 return new PrerenderContents(prerender_manager, prerender_tracker, profile, | 118 return new PrerenderContents(prerender_manager, prerender_tracker, profile, |
| 95 url, referrer, origin, experiment_id); | 119 url, referrer, origin, experiment_id); |
| 96 } | 120 } |
| 97 }; | 121 }; |
| 98 | 122 |
| 99 struct PrerenderContents::PendingPrerenderInfo { | 123 struct PrerenderContents::PendingPrerenderInfo { |
| 100 PendingPrerenderInfo(const GURL& url, | 124 PendingPrerenderInfo(scoped_refptr<PendingPrerender> prerender, |
| 125 const GURL& url, | |
| 101 const content::Referrer& referrer, | 126 const content::Referrer& referrer, |
| 102 const gfx::Size& size); | 127 const gfx::Size& size); |
| 128 scoped_refptr<PendingPrerender> prerender; | |
| 103 const GURL url; | 129 const GURL url; |
| 104 const content::Referrer referrer; | 130 const content::Referrer referrer; |
| 105 const gfx::Size size; | 131 const gfx::Size size; |
| 106 }; | 132 }; |
| 107 | 133 |
| 108 PrerenderContents::PendingPrerenderInfo::PendingPrerenderInfo( | 134 PrerenderContents::PendingPrerenderInfo::PendingPrerenderInfo( |
| 135 scoped_refptr<PendingPrerender> prerender, | |
| 109 const GURL& url, | 136 const GURL& url, |
| 110 const content::Referrer& referrer, | 137 const content::Referrer& referrer, |
| 111 const gfx::Size& size) | 138 const gfx::Size& size) |
| 112 : url(url), | 139 : prerender(prerender), |
| 140 url(url), | |
| 113 referrer(referrer), | 141 referrer(referrer), |
| 114 size(size) { | 142 size(size) { |
| 115 } | 143 } |
| 116 | 144 |
| 117 // TabContentsDelegateImpl ----------------------------------------------------- | 145 // TabContentsDelegateImpl ----------------------------------------------------- |
| 118 | 146 |
| 119 class PrerenderContents::TabContentsDelegateImpl | 147 class PrerenderContents::TabContentsDelegateImpl |
| 120 : public content::WebContentsDelegate { | 148 : public content::WebContentsDelegate { |
| 121 public: | 149 public: |
| 122 explicit TabContentsDelegateImpl(PrerenderContents* prerender_contents) : | 150 explicit TabContentsDelegateImpl(PrerenderContents* prerender_contents) : |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 private: | 227 private: |
| 200 typedef std::vector<scoped_refptr<history::HistoryAddPageArgs> > | 228 typedef std::vector<scoped_refptr<history::HistoryAddPageArgs> > |
| 201 AddPageVector; | 229 AddPageVector; |
| 202 | 230 |
| 203 // Caches pages to be added to the history. | 231 // Caches pages to be added to the history. |
| 204 AddPageVector add_page_vector_; | 232 AddPageVector add_page_vector_; |
| 205 | 233 |
| 206 PrerenderContents* prerender_contents_; | 234 PrerenderContents* prerender_contents_; |
| 207 }; | 235 }; |
| 208 | 236 |
| 209 void PrerenderContents::AddPendingPrerender(const GURL& url, | 237 PrerenderHandle PrerenderContents::AddPendingPrerender( |
| 210 const content::Referrer& referrer, | 238 const GURL& url, |
| 211 const gfx::Size& size) { | 239 const content::Referrer& referrer, |
| 212 pending_prerender_list_.push_back(PendingPrerenderInfo(url, referrer, size)); | 240 const gfx::Size& size) { |
| 241 scoped_refptr<PendingPrerender> pending_prerender(new PendingPrerender); | |
| 242 pending_prerender_list_.push_back( | |
| 243 PendingPrerenderInfo(pending_prerender, url, referrer, size)); | |
| 244 return pending_prerender; | |
| 213 } | 245 } |
| 214 | 246 |
| 215 bool PrerenderContents::IsPendingEntry(const GURL& url) const { | 247 bool PrerenderContents::IsPendingEntry(const GURL& url) const { |
| 216 for (PendingPrerenderList::const_iterator it = | 248 for (PendingPrerenderList::const_iterator it = |
| 217 pending_prerender_list_.begin(); | 249 pending_prerender_list_.begin(); |
| 218 it != pending_prerender_list_.end(); | 250 it != pending_prerender_list_.end(); |
| 219 ++it) { | 251 ++it) { |
| 220 if (it->url == url) | 252 if (it->url == url) |
| 221 return true; | 253 return true; |
| 222 } | 254 } |
| 223 return false; | 255 return false; |
| 224 } | 256 } |
| 225 | 257 |
| 226 void PrerenderContents::StartPendingPrerenders() { | 258 void PrerenderContents::StartPendingPrerenders() { |
| 227 PendingPrerenderList pending_prerender_list; | 259 PendingPrerenderList pending_prerender_list; |
| 228 pending_prerender_list.swap(pending_prerender_list_); | 260 pending_prerender_list.swap(pending_prerender_list_); |
| 229 for (PendingPrerenderList::iterator it = pending_prerender_list.begin(); | 261 for (PendingPrerenderList::iterator it = pending_prerender_list.begin(); |
| 230 it != pending_prerender_list.end(); | 262 it != pending_prerender_list.end(); ++it) { |
| 231 ++it) { | 263 if (it->prerender->is_destroyed()) continue; |
| 232 prerender_manager_->AddPrerenderFromLinkRelPrerender( | 264 it->prerender->set_prerender( |
|
dominich
2012/06/18 15:32:44
Why don't we clear the list of pending prerenders
gavinp
2012/06/18 16:40:48
Also gone in the new approach.
| |
| 233 child_id_, route_id_, it->url, it->referrer, it->size); | 265 prerender_manager_->AddPrerenderFromLinkRelPrerender( |
| 266 child_id_, route_id_, it->url, it->referrer, it->size)); | |
| 234 } | 267 } |
| 235 } | 268 } |
| 236 | 269 |
| 237 PrerenderContents::PrerenderContents( | 270 PrerenderContents::PrerenderContents( |
| 238 PrerenderManager* prerender_manager, | 271 PrerenderManager* prerender_manager, |
| 239 PrerenderTracker* prerender_tracker, | 272 PrerenderTracker* prerender_tracker, |
| 240 Profile* profile, | 273 Profile* profile, |
| 241 const GURL& url, | 274 const GURL& url, |
| 242 const content::Referrer& referrer, | 275 const content::Referrer& referrer, |
| 243 Origin origin, | 276 Origin origin, |
| 244 uint8 experiment_id) | 277 uint8 experiment_id) |
| 245 : prerendering_has_started_(false), | 278 : prerendering_has_started_(false), |
| 246 prerender_manager_(prerender_manager), | 279 prerender_manager_(prerender_manager), |
| 247 prerender_tracker_(prerender_tracker), | 280 prerender_tracker_(prerender_tracker), |
| 248 prerender_url_(url), | 281 prerender_url_(url), |
| 249 referrer_(referrer), | 282 referrer_(referrer), |
| 250 profile_(profile), | 283 profile_(profile), |
| 251 page_id_(0), | 284 page_id_(0), |
| 252 has_stopped_loading_(false), | 285 has_stopped_loading_(false), |
| 253 has_finished_loading_(false), | 286 has_finished_loading_(false), |
| 254 final_status_(FINAL_STATUS_MAX), | 287 final_status_(FINAL_STATUS_MAX), |
| 255 match_complete_status_(MATCH_COMPLETE_DEFAULT), | 288 match_complete_status_(MATCH_COMPLETE_DEFAULT), |
| 256 prerendering_has_been_cancelled_(false), | 289 prerendering_has_been_cancelled_(false), |
| 257 child_id_(-1), | 290 child_id_(-1), |
| 258 route_id_(-1), | 291 route_id_(-1), |
| 259 origin_(origin), | 292 origin_(origin), |
| 260 experiment_id_(experiment_id), | 293 experiment_id_(experiment_id), |
| 261 creator_child_id_(-1) { | 294 creator_child_id_(-1) { |
| 262 DCHECK(prerender_manager != NULL); | 295 DCHECK(prerender_manager != NULL); |
| 296 DVLOG(2) << "PrerenderContents constructor\n"; | |
| 297 DVLOG(3) << " url = " << url.spec(); | |
| 263 } | 298 } |
| 264 | 299 |
| 265 bool PrerenderContents::Init() { | 300 bool PrerenderContents::Init(WeakPrerenderHandle prerender) { |
| 301 prerender_ = prerender; | |
| 266 return AddAliasURL(prerender_url_); | 302 return AddAliasURL(prerender_url_); |
| 267 } | 303 } |
| 268 | 304 |
| 269 // static | 305 // static |
| 270 PrerenderContents::Factory* PrerenderContents::CreateFactory() { | 306 PrerenderContents::Factory* PrerenderContents::CreateFactory() { |
| 271 return new PrerenderContentsFactoryImpl(); | 307 return new PrerenderContentsFactoryImpl(); |
| 272 } | 308 } |
| 273 | 309 |
| 274 void PrerenderContents::StartPrerendering( | 310 void PrerenderContents::StartPrerendering( |
| 275 int creator_child_id, | 311 int creator_child_id, |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 385 } | 421 } |
| 386 | 422 |
| 387 bool PrerenderContents::GetRouteId(int* route_id) const { | 423 bool PrerenderContents::GetRouteId(int* route_id) const { |
| 388 CHECK(route_id); | 424 CHECK(route_id); |
| 389 DCHECK_GE(route_id_, -1); | 425 DCHECK_GE(route_id_, -1); |
| 390 *route_id = route_id_; | 426 *route_id = route_id_; |
| 391 return route_id_ != -1; | 427 return route_id_ != -1; |
| 392 } | 428 } |
| 393 | 429 |
| 394 void PrerenderContents::set_final_status(FinalStatus final_status) { | 430 void PrerenderContents::set_final_status(FinalStatus final_status) { |
| 395 DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX); | 431 DCHECK_LE(FINAL_STATUS_USED, final_status); |
| 396 DCHECK(final_status_ == FINAL_STATUS_MAX); | 432 DCHECK_GT(FINAL_STATUS_MAX, final_status); |
| 433 | |
| 434 DCHECK_EQ(FINAL_STATUS_MAX, final_status_); | |
| 397 | 435 |
| 398 final_status_ = final_status; | 436 final_status_ = final_status; |
| 399 } | 437 } |
| 400 | 438 |
| 401 PrerenderContents::~PrerenderContents() { | 439 PrerenderContents::~PrerenderContents() { |
| 402 DCHECK(final_status_ != FINAL_STATUS_MAX); | 440 DVLOG(4) << "PrerenderContents::~PrerenderContents()"; |
| 441 DCHECK_NE(FINAL_STATUS_MAX, final_status_); | |
| 403 DCHECK(prerendering_has_been_cancelled_ || | 442 DCHECK(prerendering_has_been_cancelled_ || |
| 404 final_status_ == FINAL_STATUS_USED); | 443 final_status_ == FINAL_STATUS_USED); |
| 405 DCHECK(origin_ != ORIGIN_MAX); | 444 DCHECK_NE(ORIGIN_MAX, origin_); |
| 406 | 445 |
| 407 prerender_manager_->RecordFinalStatusWithMatchCompleteStatus( | 446 prerender_manager_->RecordFinalStatusWithMatchCompleteStatus( |
| 408 origin_, | 447 origin_, |
| 409 experiment_id_, | 448 experiment_id_, |
| 410 match_complete_status_, | 449 match_complete_status_, |
| 411 final_status_); | 450 final_status_); |
| 412 | 451 |
| 413 if (child_id_ != -1 && route_id_ != -1) { | 452 if (child_id_ != -1 && route_id_ != -1) { |
| 414 prerender_tracker_->OnPrerenderingFinished(child_id_, route_id_); | 453 prerender_tracker_->OnPrerenderingFinished(child_id_, route_id_); |
| 415 for (std::vector<GURL>::const_iterator it = alias_urls_.begin(); | 454 for (std::vector<GURL>::const_iterator it = alias_urls_.begin(); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 541 | 580 |
| 542 void PrerenderContents::AddAliasURLsFromOtherPrerenderContents( | 581 void PrerenderContents::AddAliasURLsFromOtherPrerenderContents( |
| 543 PrerenderContents* other_pc) { | 582 PrerenderContents* other_pc) { |
| 544 for (std::vector<GURL>::const_iterator it = other_pc->alias_urls_.begin(); | 583 for (std::vector<GURL>::const_iterator it = other_pc->alias_urls_.begin(); |
| 545 it != other_pc->alias_urls_.end(); | 584 it != other_pc->alias_urls_.end(); |
| 546 ++it) { | 585 ++it) { |
| 547 alias_urls_.push_back(*it); | 586 alias_urls_.push_back(*it); |
| 548 } | 587 } |
| 549 } | 588 } |
| 550 | 589 |
| 551 bool PrerenderContents::MatchesURL(const GURL& url, GURL* matching_url) const { | 590 bool PrerenderContents::Matches( |
| 552 std::vector<GURL>::const_iterator matching_url_iterator = | 591 const GURL& url, |
| 553 std::find_if(alias_urls_.begin(), | 592 const content::SessionStorageNamespace* session_storage_namespace) const { |
| 554 alias_urls_.end(), | 593 DVLOG(4) << "PrerenderContents::Matches"; |
| 555 PrerenderURLPredicate(url)); | 594 if (child_id_ != -1) { |
| 556 if (matching_url_iterator != alias_urls_.end()) { | 595 RenderViewHost* render_view_host = |
| 557 if (matching_url) | 596 RenderViewHost::FromID(child_id_, route_id_); |
| 558 *matching_url = *matching_url_iterator; | 597 if (!render_view_host || !render_view_host->GetView() || |
| 559 return true; | 598 session_storage_namespace != |
| 599 render_view_host->GetSessionStorageNamespace()) { | |
| 600 return false; | |
| 601 } | |
| 560 } | 602 } |
| 561 return false; | 603 DCHECK_LE(1, std::count(alias_urls_.begin(), alias_urls_.end(), url)); |
| 604 std::vector<GURL>::const_iterator it = std::find(alias_urls_.begin(), | |
| 605 alias_urls_.end(), url); | |
| 606 return it != alias_urls_.end(); | |
| 562 } | 607 } |
| 563 | 608 |
| 564 void PrerenderContents::OnJSOutOfMemory() { | 609 void PrerenderContents::OnJSOutOfMemory() { |
| 565 Destroy(FINAL_STATUS_JS_OUT_OF_MEMORY); | 610 Destroy(FINAL_STATUS_JS_OUT_OF_MEMORY); |
| 566 } | 611 } |
| 567 | 612 |
| 568 void PrerenderContents::RenderViewGone(base::TerminationStatus status) { | 613 void PrerenderContents::RenderViewGone(base::TerminationStatus status) { |
| 569 Destroy(FINAL_STATUS_RENDERER_CRASHED); | 614 Destroy(FINAL_STATUS_RENDERER_CRASHED); |
| 570 } | 615 } |
| 571 | 616 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 627 if (!prerender_tracker_->GetFinalStatus(child_id_, route_id_, | 672 if (!prerender_tracker_->GetFinalStatus(child_id_, route_id_, |
| 628 &final_status)) { | 673 &final_status)) { |
| 629 NOTREACHED(); | 674 NOTREACHED(); |
| 630 } | 675 } |
| 631 } | 676 } |
| 632 set_final_status(final_status); | 677 set_final_status(final_status); |
| 633 | 678 |
| 634 prerendering_has_been_cancelled_ = true; | 679 prerendering_has_been_cancelled_ = true; |
| 635 // This has to be done after setting the final status, as it adds the | 680 // This has to be done after setting the final status, as it adds the |
| 636 // prerender to the history. | 681 // prerender to the history. |
| 637 prerender_manager_->MoveEntryToPendingDelete(this, final_status); | 682 if (prerendering_has_started_ && prerender_) { |
| 683 prerender_manager_->MoveEntryToPendingDelete(prerender_, final_status); | |
| 684 } | |
| 638 | 685 |
| 639 // We may destroy the PrerenderContents before we have initialized the | 686 // We may destroy the PrerenderContents before we have initialized the |
| 640 // RenderViewHost. Otherwise set the Observer's PrerenderContents to NULL to | 687 // RenderViewHost. Otherwise set the Observer's PrerenderContents to NULL to |
| 641 // avoid any more messages being sent. | 688 // avoid any more messages being sent. |
| 642 if (render_view_host_observer_.get()) | 689 if (render_view_host_observer_.get()) |
| 643 render_view_host_observer_->set_prerender_contents(NULL); | 690 render_view_host_observer_->set_prerender_contents(NULL); |
| 644 } | 691 } |
| 645 | 692 |
| 646 base::ProcessMetrics* PrerenderContents::MaybeGetProcessMetrics() { | 693 base::ProcessMetrics* PrerenderContents::MaybeGetProcessMetrics() { |
| 647 if (process_metrics_.get() == NULL) { | 694 if (process_metrics_.get() == NULL) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 715 } | 762 } |
| 716 | 763 |
| 717 bool PrerenderContents::IsCrossSiteNavigationPending() const { | 764 bool PrerenderContents::IsCrossSiteNavigationPending() const { |
| 718 if (!prerender_contents_.get() || !prerender_contents_->web_contents()) | 765 if (!prerender_contents_.get() || !prerender_contents_->web_contents()) |
| 719 return false; | 766 return false; |
| 720 const WebContents* web_contents = prerender_contents_->web_contents(); | 767 const WebContents* web_contents = prerender_contents_->web_contents(); |
| 721 return (web_contents->GetSiteInstance() != | 768 return (web_contents->GetSiteInstance() != |
| 722 web_contents->GetPendingSiteInstance()); | 769 web_contents->GetPendingSiteInstance()); |
| 723 } | 770 } |
| 724 | 771 |
| 725 | |
| 726 } // namespace prerender | 772 } // namespace prerender |
| OLD | NEW |