Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(909)

Side by Side Diff: chrome/browser/prerender/prerender_contents.cc

Issue 10553029: Handle interface to prerenders. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698