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

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

Issue 11348357: Add observer interface to PrerenderContents. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: final review remediation, clear to land version Created 8 years 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 <functional> 8 #include <functional>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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 29 matching lines...) Expand all
253 } 257 }
254 258
255 // static 259 // static
256 PrerenderContents::Factory* PrerenderContents::CreateFactory() { 260 PrerenderContents::Factory* PrerenderContents::CreateFactory() {
257 return new PrerenderContentsFactoryImpl(); 261 return new PrerenderContentsFactoryImpl();
258 } 262 }
259 263
260 void PrerenderContents::StartPrerendering( 264 void PrerenderContents::StartPrerendering(
261 int creator_child_id, 265 int creator_child_id,
262 const gfx::Size& size, 266 const gfx::Size& size,
263 SessionStorageNamespace* session_storage_namespace, 267 SessionStorageNamespace* session_storage_namespace) {
264 bool is_control_group) {
265 DCHECK(profile_ != NULL); 268 DCHECK(profile_ != NULL);
266 DCHECK(!size.IsEmpty()); 269 DCHECK(!size.IsEmpty());
267 DCHECK(!prerendering_has_started_); 270 DCHECK(!prerendering_has_started_);
268 DCHECK(prerender_contents_.get() == NULL); 271 DCHECK(prerender_contents_.get() == NULL);
269 DCHECK_EQ(-1, creator_child_id_); 272 DCHECK_EQ(-1, creator_child_id_);
270 DCHECK(size_.IsEmpty()); 273 DCHECK(size_.IsEmpty());
271 DCHECK_EQ(1U, alias_urls_.size()); 274 DCHECK_EQ(1U, alias_urls_.size());
272 275
273 creator_child_id_ = creator_child_id; 276 creator_child_id_ = creator_child_id;
274 session_storage_namespace_id_ = session_storage_namespace->id(); 277 session_storage_namespace_id_ = session_storage_namespace->id();
275 size_ = size; 278 size_ = size;
276 279
277 InformRenderProcessAboutPrerender(prerender_url_, true, 280 InformRenderProcessAboutPrerender(prerender_url_, true,
278 creator_child_id_); 281 creator_child_id_);
279 282
280 DCHECK(load_start_time_.is_null()); 283 DCHECK(load_start_time_.is_null());
281 load_start_time_ = base::TimeTicks::Now(); 284 load_start_time_ = base::TimeTicks::Now();
282 285
283 // Everything after this point sets up the WebContents object and associated 286 // 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 287 // RenderView for the prerender page. Don't do this for members of the
285 // control group. 288 // control group.
286 if (is_control_group) 289 if (prerender_manager_->IsControlGroup(experiment_id()))
287 return; 290 return;
288 291
289 prerendering_has_started_ = true; 292 prerendering_has_started_ = true;
290 293
291 WebContents* new_contents = CreateWebContents(session_storage_namespace); 294 WebContents* new_contents = CreateWebContents(session_storage_namespace);
292 prerender_contents_.reset( 295 prerender_contents_.reset(
293 TabContents::Factory::CreateTabContents(new_contents)); 296 TabContents::Factory::CreateTabContents(new_contents));
294 content::WebContentsObserver::Observe(new_contents); 297 content::WebContentsObserver::Observe(new_contents);
295 298
296 tab_contents_delegate_.reset(new TabContentsDelegateImpl(this)); 299 tab_contents_delegate_.reset(new TabContentsDelegateImpl(this));
297 new_contents->SetDelegate(tab_contents_delegate_.get()); 300 new_contents->SetDelegate(tab_contents_delegate_.get());
298 // Set the size of the prerender WebContents. 301 // Set the size of the prerender WebContents.
299 prerender_contents_->web_contents()->GetView()->SizeContents(size_); 302 prerender_contents_->web_contents()->GetView()->SizeContents(size_);
300 303
301 // Register as an observer of the RenderViewHost so we get messages. 304 // Register as an observer of the RenderViewHost so we get messages.
302 render_view_host_observer_.reset( 305 render_view_host_observer_.reset(
303 new PrerenderRenderViewHostObserver(this, GetRenderViewHostMutable())); 306 new PrerenderRenderViewHostObserver(this, GetRenderViewHostMutable()));
304 307
305 child_id_ = GetRenderViewHost()->GetProcess()->GetID(); 308 child_id_ = GetRenderViewHost()->GetProcess()->GetID();
306 route_id_ = GetRenderViewHost()->GetRoutingID(); 309 route_id_ = GetRenderViewHost()->GetRoutingID();
307 310
308 // Register this with the ResourceDispatcherHost as a prerender 311 // Register this with the ResourceDispatcherHost as a prerender
309 // RenderViewHost. This must be done before the Navigate message to catch all 312 // RenderViewHost. This must be done before the Navigate message to catch all
310 // resource requests, but as it is on the same thread as the Navigate message 313 // resource requests, but as it is on the same thread as the Navigate message
311 // (IO) there is no race condition. 314 // (IO) there is no race condition.
312 prerender_tracker_->OnPrerenderingStarted( 315 AddObserver(prerender_manager()->prerender_tracker());
313 child_id_, 316 NotifyPrerenderStart();
314 route_id_,
315 prerender_manager_);
316 317
317 // Close ourselves when the application is shutting down. 318 // Close ourselves when the application is shutting down.
318 notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, 319 notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
319 content::NotificationService::AllSources()); 320 content::NotificationService::AllSources());
320 321
321 // Register for our parent profile to shutdown, so we can shut ourselves down 322 // Register for our parent profile to shutdown, so we can shut ourselves down
322 // as well (should only be called for OTR profiles, as we should receive 323 // as well (should only be called for OTR profiles, as we should receive
323 // APP_TERMINATING before non-OTR profiles are destroyed). 324 // APP_TERMINATING before non-OTR profiles are destroyed).
324 // TODO(tburkard): figure out if this is needed. 325 // TODO(tburkard): figure out if this is needed.
325 notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 326 notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 return child_id_ != -1; 359 return child_id_ != -1;
359 } 360 }
360 361
361 bool PrerenderContents::GetRouteId(int* route_id) const { 362 bool PrerenderContents::GetRouteId(int* route_id) const {
362 CHECK(route_id); 363 CHECK(route_id);
363 DCHECK_GE(route_id_, -1); 364 DCHECK_GE(route_id_, -1);
364 *route_id = route_id_; 365 *route_id = route_id_;
365 return route_id_ != -1; 366 return route_id_ != -1;
366 } 367 }
367 368
368 void PrerenderContents::set_final_status(FinalStatus final_status) { 369 void PrerenderContents::SetFinalStatus(FinalStatus final_status) {
369 DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX); 370 DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX);
370 DCHECK(final_status_ == FINAL_STATUS_MAX); 371 DCHECK(final_status_ == FINAL_STATUS_MAX);
371 372
372 final_status_ = final_status; 373 final_status_ = final_status;
374
375 if (!prerender_manager_->IsControlGroup(experiment_id()) &&
376 prerendering_has_started()) {
377 NotifyPrerenderStop();
378 }
373 } 379 }
374 380
375 PrerenderContents::~PrerenderContents() { 381 PrerenderContents::~PrerenderContents() {
376 DCHECK(final_status_ != FINAL_STATUS_MAX); 382 DCHECK_NE(FINAL_STATUS_MAX, final_status());
377 DCHECK(prerendering_has_been_cancelled_ || 383 DCHECK(
378 final_status_ == FINAL_STATUS_USED); 384 prerendering_has_been_cancelled() || final_status() == FINAL_STATUS_USED);
379 DCHECK(origin_ != ORIGIN_MAX); 385 DCHECK_NE(ORIGIN_MAX, origin());
380 386
381 prerender_manager_->RecordFinalStatusWithMatchCompleteStatus( 387 prerender_manager_->RecordFinalStatusWithMatchCompleteStatus(
382 origin_, 388 origin(), experiment_id(), match_complete_status(), final_status());
383 experiment_id_,
384 match_complete_status_,
385 final_status_);
386 389
387 if (child_id_ != -1 && route_id_ != -1) { 390 if (child_id_ != -1 && route_id_ != -1) {
388 prerender_tracker_->OnPrerenderingFinished(child_id_, route_id_);
389 for (std::vector<GURL>::const_iterator it = alias_urls_.begin(); 391 for (std::vector<GURL>::const_iterator it = alias_urls_.begin();
390 it != alias_urls_.end(); 392 it != alias_urls_.end();
391 ++it) { 393 ++it) {
392 InformRenderProcessAboutPrerender(*it, false, creator_child_id_); 394 InformRenderProcessAboutPrerender(*it, false, creator_child_id_);
393 } 395 }
394 } 396 }
395 397
396 // 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
397 // destroy it. 399 // destroy it.
398 if (prerender_contents_.get()) 400 if (prerender_contents_.get())
399 delete ReleasePrerenderContents(); 401 delete ReleasePrerenderContents();
400 } 402 }
401 403
404 void PrerenderContents::AddObserver(Observer* observer) {
405 DCHECK_EQ(FINAL_STATUS_MAX, final_status_);
406 observer_list_.AddObserver(observer);
407 }
408
402 void PrerenderContents::Observe(int type, 409 void PrerenderContents::Observe(int type,
403 const content::NotificationSource& source, 410 const content::NotificationSource& source,
404 const content::NotificationDetails& details) { 411 const content::NotificationDetails& details) {
405 switch (type) { 412 switch (type) {
406 case chrome::NOTIFICATION_PROFILE_DESTROYED: 413 case chrome::NOTIFICATION_PROFILE_DESTROYED:
407 Destroy(FINAL_STATUS_PROFILE_DESTROYED); 414 Destroy(FINAL_STATUS_PROFILE_DESTROYED);
408 return; 415 return;
409 416
410 case chrome::NOTIFICATION_APP_TERMINATING: 417 case chrome::NOTIFICATION_APP_TERMINATING:
411 Destroy(FINAL_STATUS_APP_TERMINATING); 418 Destroy(FINAL_STATUS_APP_TERMINATING);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 WebContents* PrerenderContents::CreateWebContents( 483 WebContents* PrerenderContents::CreateWebContents(
477 SessionStorageNamespace* session_storage_namespace) { 484 SessionStorageNamespace* session_storage_namespace) {
478 // TODO(ajwong): Remove the temporary map once prerendering is aware of 485 // TODO(ajwong): Remove the temporary map once prerendering is aware of
479 // multiple session storage namespaces per tab. 486 // multiple session storage namespaces per tab.
480 content::SessionStorageNamespaceMap session_storage_namespace_map; 487 content::SessionStorageNamespaceMap session_storage_namespace_map;
481 session_storage_namespace_map[""] = session_storage_namespace; 488 session_storage_namespace_map[""] = session_storage_namespace;
482 return WebContents::CreateWithSessionStorage( 489 return WebContents::CreateWithSessionStorage(
483 profile_, NULL, MSG_ROUTING_NONE, NULL, session_storage_namespace_map); 490 profile_, NULL, MSG_ROUTING_NONE, NULL, session_storage_namespace_map);
484 } 491 }
485 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
486 void PrerenderContents::DidUpdateFaviconURL( 504 void PrerenderContents::DidUpdateFaviconURL(
487 int32 page_id, 505 int32 page_id,
488 const std::vector<content::FaviconURL>& urls) { 506 const std::vector<content::FaviconURL>& urls) {
489 VLOG(1) << "PrerenderContents::OnUpdateFaviconURL" << icon_url_; 507 VLOG(1) << "PrerenderContents::OnUpdateFaviconURL" << icon_url_;
490 for (std::vector<content::FaviconURL>::const_iterator it = urls.begin(); 508 for (std::vector<content::FaviconURL>::const_iterator it = urls.begin();
491 it != urls.end(); ++it) { 509 it != urls.end(); ++it) {
492 if (it->icon_type == content::FaviconURL::FAVICON) { 510 if (it->icon_type == content::FaviconURL::FAVICON) {
493 icon_url_ = it->icon_url; 511 icon_url_ = it->icon_url;
494 VLOG(1) << icon_url_; 512 VLOG(1) << icon_url_;
495 return; 513 return;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 590
573 void PrerenderContents::Destroy(FinalStatus final_status) { 591 void PrerenderContents::Destroy(FinalStatus final_status) {
574 if (prerendering_has_been_cancelled_) 592 if (prerendering_has_been_cancelled_)
575 return; 593 return;
576 594
577 if (child_id_ != -1 && route_id_ != -1) { 595 if (child_id_ != -1 && route_id_ != -1) {
578 // Cancel the prerender in the PrerenderTracker. This is needed 596 // Cancel the prerender in the PrerenderTracker. This is needed
579 // 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
580 // TryCancel(). This is difficult to completely avoid, since prerendering 598 // TryCancel(). This is difficult to completely avoid, since prerendering
581 // can be cancelled before a RenderView is created. 599 // can be cancelled before a RenderView is created.
582 bool is_cancelled = prerender_tracker_->TryCancel( 600 bool is_cancelled = prerender_manager()->prerender_tracker()->TryCancel(
583 child_id_, route_id_, final_status); 601 child_id_, route_id_, final_status);
584 CHECK(is_cancelled); 602 CHECK(is_cancelled);
585 603
586 // 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.
587 // If so, use it instead. 605 // If so, use it instead.
588 if (!prerender_tracker_->GetFinalStatus(child_id_, route_id_, 606 if (!prerender_manager()->prerender_tracker()->
589 &final_status)) { 607 GetFinalStatus(child_id_, route_id_, &final_status)) {
590 NOTREACHED(); 608 NOTREACHED();
591 } 609 }
592 } 610 }
593 set_final_status(final_status); 611 SetFinalStatus(final_status);
594 612
595 prerendering_has_been_cancelled_ = true; 613 prerendering_has_been_cancelled_ = true;
596 prerender_manager_->AddToHistory(this); 614 prerender_manager_->AddToHistory(this);
597 prerender_manager_->MoveEntryToPendingDelete(this, final_status); 615 prerender_manager_->MoveEntryToPendingDelete(this, final_status);
598 616
599 // We may destroy the PrerenderContents before we have initialized the 617 // We may destroy the PrerenderContents before we have initialized the
600 // RenderViewHost. Otherwise set the Observer's PrerenderContents to NULL to 618 // RenderViewHost. Otherwise set the Observer's PrerenderContents to NULL to
601 // avoid any more messages being sent. 619 // avoid any more messages being sent.
602 if (render_view_host_observer_) 620 if (render_view_host_observer_)
603 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
684 bool PrerenderContents::IsCrossSiteNavigationPending() const { 702 bool PrerenderContents::IsCrossSiteNavigationPending() const {
685 if (!prerender_contents_.get() || !prerender_contents_->web_contents()) 703 if (!prerender_contents_.get() || !prerender_contents_->web_contents())
686 return false; 704 return false;
687 const WebContents* web_contents = prerender_contents_->web_contents(); 705 const WebContents* web_contents = prerender_contents_->web_contents();
688 return (web_contents->GetSiteInstance() != 706 return (web_contents->GetSiteInstance() !=
689 web_contents->GetPendingSiteInstance()); 707 web_contents->GetPendingSiteInstance());
690 } 708 }
691 709
692 710
693 } // namespace prerender 711 } // namespace prerender
OLDNEW
« no previous file with comments | « chrome/browser/prerender/prerender_contents.h ('k') | chrome/browser/prerender/prerender_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698