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 |