| 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 |
| 11 #include "base/process_util.h" | |
| 12 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
| 13 #include "chrome/browser/history/history_tab_helper.h" | 12 #include "chrome/browser/history/history_tab_helper.h" |
| 14 #include "chrome/browser/history/history_types.h" | 13 #include "chrome/browser/history/history_types.h" |
| 15 #include "chrome/browser/prerender/prerender_final_status.h" | 14 #include "chrome/browser/prerender/prerender_final_status.h" |
| 16 #include "chrome/browser/prerender/prerender_handle.h" | 15 #include "chrome/browser/prerender/prerender_handle.h" |
| 17 #include "chrome/browser/prerender/prerender_manager.h" | 16 #include "chrome/browser/prerender/prerender_manager.h" |
| 18 #include "chrome/browser/prerender/prerender_render_view_host_observer.h" | 17 #include "chrome/browser/prerender/prerender_render_view_host_observer.h" |
| 19 #include "chrome/browser/prerender/prerender_tracker.h" | 18 #include "chrome/browser/prerender/prerender_tracker.h" |
| 20 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
| 21 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 20 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 36 | 35 |
| 37 using content::DownloadItem; | 36 using content::DownloadItem; |
| 38 using content::OpenURLParams; | 37 using content::OpenURLParams; |
| 39 using content::RenderViewHost; | 38 using content::RenderViewHost; |
| 40 using content::ResourceRedirectDetails; | 39 using content::ResourceRedirectDetails; |
| 41 using content::SessionStorageNamespace; | 40 using content::SessionStorageNamespace; |
| 42 using content::WebContents; | 41 using content::WebContents; |
| 43 | 42 |
| 44 namespace prerender { | 43 namespace prerender { |
| 45 | 44 |
| 46 namespace { | |
| 47 | |
| 48 // Tells the render process at |child_id| whether |url| is a new prerendered | |
| 49 // page, or whether |url| is being removed as a prerendered page. Currently | |
| 50 // this will only inform the render process that created the prerendered page | |
| 51 // with <link rel="prerender"> tags about it. This means that if the user | |
| 52 // clicks on a link for a prerendered URL in a different page, the prerender | |
| 53 // will not be swapped in. | |
| 54 void InformRenderProcessAboutPrerender(const GURL& url, | |
| 55 bool is_add, | |
| 56 int child_id) { | |
| 57 if (child_id < 0) | |
| 58 return; | |
| 59 content::RenderProcessHost* render_process_host = | |
| 60 content::RenderProcessHost::FromID(child_id); | |
| 61 if (!render_process_host) | |
| 62 return; | |
| 63 IPC::Message* message = NULL; | |
| 64 if (is_add) | |
| 65 message = new PrerenderMsg_AddPrerenderURL(url); | |
| 66 else | |
| 67 message = new PrerenderMsg_RemovePrerenderURL(url); | |
| 68 render_process_host->Send(message); | |
| 69 } | |
| 70 | |
| 71 } // namespace | |
| 72 | |
| 73 class PrerenderContentsFactoryImpl : public PrerenderContents::Factory { | 45 class PrerenderContentsFactoryImpl : public PrerenderContents::Factory { |
| 74 public: | 46 public: |
| 75 virtual PrerenderContents* CreatePrerenderContents( | 47 virtual PrerenderContents* CreatePrerenderContents( |
| 76 PrerenderManager* prerender_manager, Profile* profile, | 48 PrerenderManager* prerender_manager, Profile* profile, |
| 77 const GURL& url, const content::Referrer& referrer, | 49 const GURL& url, const content::Referrer& referrer, |
| 78 Origin origin, uint8 experiment_id) OVERRIDE { | 50 Origin origin, uint8 experiment_id) OVERRIDE { |
| 79 return new PrerenderContents(prerender_manager, profile, | 51 return new PrerenderContents(prerender_manager, profile, |
| 80 url, referrer, origin, experiment_id); | 52 url, referrer, origin, experiment_id); |
| 81 } | 53 } |
| 82 }; | 54 }; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 bool user_gesture) OVERRIDE { | 132 bool user_gesture) OVERRIDE { |
| 161 // TODO(mmenke): Consider supporting this if it is a common case during | 133 // TODO(mmenke): Consider supporting this if it is a common case during |
| 162 // prerenders. | 134 // prerenders. |
| 163 prerender_contents_->Destroy(FINAL_STATUS_REGISTER_PROTOCOL_HANDLER); | 135 prerender_contents_->Destroy(FINAL_STATUS_REGISTER_PROTOCOL_HANDLER); |
| 164 } | 136 } |
| 165 | 137 |
| 166 private: | 138 private: |
| 167 PrerenderContents* prerender_contents_; | 139 PrerenderContents* prerender_contents_; |
| 168 }; | 140 }; |
| 169 | 141 |
| 142 void PrerenderContents::Observer::OnPrerenderAddAlias( |
| 143 PrerenderContents* contents, |
| 144 const GURL& alias_url) { |
| 145 } |
| 146 |
| 170 PrerenderContents::Observer::Observer() { | 147 PrerenderContents::Observer::Observer() { |
| 171 } | 148 } |
| 172 | 149 |
| 173 PrerenderContents::Observer::~Observer() { | 150 PrerenderContents::Observer::~Observer() { |
| 174 } | 151 } |
| 175 | 152 |
| 176 PrerenderContents::PendingPrerenderInfo::PendingPrerenderInfo( | 153 PrerenderContents::PendingPrerenderInfo::PendingPrerenderInfo( |
| 177 base::WeakPtr<PrerenderHandle> weak_prerender_handle, | 154 base::WeakPtr<PrerenderHandle> weak_prerender_handle, |
| 178 Origin origin, | 155 Origin origin, |
| 179 const GURL& url, | 156 const GURL& url, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 DCHECK(!prerendering_has_started_); | 247 DCHECK(!prerendering_has_started_); |
| 271 DCHECK(prerender_contents_.get() == NULL); | 248 DCHECK(prerender_contents_.get() == NULL); |
| 272 DCHECK_EQ(-1, creator_child_id_); | 249 DCHECK_EQ(-1, creator_child_id_); |
| 273 DCHECK(size_.IsEmpty()); | 250 DCHECK(size_.IsEmpty()); |
| 274 DCHECK_EQ(1U, alias_urls_.size()); | 251 DCHECK_EQ(1U, alias_urls_.size()); |
| 275 | 252 |
| 276 creator_child_id_ = creator_child_id; | 253 creator_child_id_ = creator_child_id; |
| 277 session_storage_namespace_id_ = session_storage_namespace->id(); | 254 session_storage_namespace_id_ = session_storage_namespace->id(); |
| 278 size_ = size; | 255 size_ = size; |
| 279 | 256 |
| 280 InformRenderProcessAboutPrerender(prerender_url_, true, | |
| 281 creator_child_id_); | |
| 282 | |
| 283 DCHECK(load_start_time_.is_null()); | 257 DCHECK(load_start_time_.is_null()); |
| 284 load_start_time_ = base::TimeTicks::Now(); | 258 load_start_time_ = base::TimeTicks::Now(); |
| 285 | 259 |
| 286 // Everything after this point sets up the WebContents object and associated | 260 // Everything after this point sets up the WebContents object and associated |
| 287 // RenderView for the prerender page. Don't do this for members of the | 261 // RenderView for the prerender page. Don't do this for members of the |
| 288 // control group. | 262 // control group. |
| 289 if (prerender_manager_->IsControlGroup(experiment_id())) | 263 if (prerender_manager_->IsControlGroup(experiment_id())) |
| 290 return; | 264 return; |
| 291 | 265 |
| 292 prerendering_has_started_ = true; | 266 prerendering_has_started_ = true; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 | 353 |
| 380 PrerenderContents::~PrerenderContents() { | 354 PrerenderContents::~PrerenderContents() { |
| 381 DCHECK_NE(FINAL_STATUS_MAX, final_status_); | 355 DCHECK_NE(FINAL_STATUS_MAX, final_status_); |
| 382 DCHECK( | 356 DCHECK( |
| 383 prerendering_has_been_cancelled_ || final_status_ == FINAL_STATUS_USED); | 357 prerendering_has_been_cancelled_ || final_status_ == FINAL_STATUS_USED); |
| 384 DCHECK_NE(ORIGIN_MAX, origin_); | 358 DCHECK_NE(ORIGIN_MAX, origin_); |
| 385 | 359 |
| 386 prerender_manager_->RecordFinalStatusWithMatchCompleteStatus( | 360 prerender_manager_->RecordFinalStatusWithMatchCompleteStatus( |
| 387 origin_, experiment_id_, match_complete_status_, final_status_); | 361 origin_, experiment_id_, match_complete_status_, final_status_); |
| 388 | 362 |
| 389 if (child_id_ != -1 && route_id_ != -1) { | |
| 390 for (std::vector<GURL>::const_iterator it = alias_urls_.begin(); | |
| 391 it != alias_urls_.end(); | |
| 392 ++it) { | |
| 393 InformRenderProcessAboutPrerender(*it, false, creator_child_id_); | |
| 394 } | |
| 395 } | |
| 396 | |
| 397 // If we still have a WebContents, clean up anything we need to and then | 363 // If we still have a WebContents, clean up anything we need to and then |
| 398 // destroy it. | 364 // destroy it. |
| 399 if (prerender_contents_.get()) | 365 if (prerender_contents_.get()) |
| 400 delete ReleasePrerenderContents(); | 366 delete ReleasePrerenderContents(); |
| 401 } | 367 } |
| 402 | 368 |
| 403 void PrerenderContents::AddObserver(Observer* observer) { | 369 void PrerenderContents::AddObserver(Observer* observer) { |
| 404 DCHECK_EQ(FINAL_STATUS_MAX, final_status_); | 370 DCHECK_EQ(FINAL_STATUS_MAX, final_status_); |
| 405 observer_list_.AddObserver(observer); | 371 observer_list_.AddObserver(observer); |
| 406 } | 372 } |
| 407 | 373 |
| 374 void PrerenderContents::RemoveObserver(Observer* observer) { |
| 375 observer_list_.RemoveObserver(observer); |
| 376 } |
| 377 |
| 408 void PrerenderContents::Observe(int type, | 378 void PrerenderContents::Observe(int type, |
| 409 const content::NotificationSource& source, | 379 const content::NotificationSource& source, |
| 410 const content::NotificationDetails& details) { | 380 const content::NotificationDetails& details) { |
| 411 switch (type) { | 381 switch (type) { |
| 412 case chrome::NOTIFICATION_PROFILE_DESTROYED: | 382 case chrome::NOTIFICATION_PROFILE_DESTROYED: |
| 413 Destroy(FINAL_STATUS_PROFILE_DESTROYED); | 383 Destroy(FINAL_STATUS_PROFILE_DESTROYED); |
| 414 return; | 384 return; |
| 415 | 385 |
| 416 case chrome::NOTIFICATION_APP_TERMINATING: | 386 case chrome::NOTIFICATION_APP_TERMINATING: |
| 417 Destroy(FINAL_STATUS_APP_TERMINATING); | 387 Destroy(FINAL_STATUS_APP_TERMINATING); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 DCHECK_EQ(FINAL_STATUS_MAX, final_status_); | 463 DCHECK_EQ(FINAL_STATUS_MAX, final_status_); |
| 494 FOR_EACH_OBSERVER(Observer, observer_list_, OnPrerenderStart(this)); | 464 FOR_EACH_OBSERVER(Observer, observer_list_, OnPrerenderStart(this)); |
| 495 } | 465 } |
| 496 | 466 |
| 497 void PrerenderContents::NotifyPrerenderStop() { | 467 void PrerenderContents::NotifyPrerenderStop() { |
| 498 DCHECK_NE(FINAL_STATUS_MAX, final_status_); | 468 DCHECK_NE(FINAL_STATUS_MAX, final_status_); |
| 499 FOR_EACH_OBSERVER(Observer, observer_list_, OnPrerenderStop(this)); | 469 FOR_EACH_OBSERVER(Observer, observer_list_, OnPrerenderStop(this)); |
| 500 observer_list_.Clear(); | 470 observer_list_.Clear(); |
| 501 } | 471 } |
| 502 | 472 |
| 473 void PrerenderContents::NotifyPrerenderAddAlias(const GURL& alias_url) { |
| 474 FOR_EACH_OBSERVER(Observer, observer_list_, OnPrerenderAddAlias(this, |
| 475 alias_url)); |
| 476 } |
| 477 |
| 503 void PrerenderContents::DidUpdateFaviconURL( | 478 void PrerenderContents::DidUpdateFaviconURL( |
| 504 int32 page_id, | 479 int32 page_id, |
| 505 const std::vector<content::FaviconURL>& urls) { | 480 const std::vector<content::FaviconURL>& urls) { |
| 506 VLOG(1) << "PrerenderContents::OnUpdateFaviconURL" << icon_url_; | 481 VLOG(1) << "PrerenderContents::OnUpdateFaviconURL" << icon_url_; |
| 507 for (std::vector<content::FaviconURL>::const_iterator it = urls.begin(); | 482 for (std::vector<content::FaviconURL>::const_iterator it = urls.begin(); |
| 508 it != urls.end(); ++it) { | 483 it != urls.end(); ++it) { |
| 509 if (it->icon_type == content::FaviconURL::FAVICON) { | 484 if (it->icon_type == content::FaviconURL::FAVICON) { |
| 510 icon_url_ = it->icon_url; | 485 icon_url_ = it->icon_url; |
| 511 VLOG(1) << icon_url_; | 486 VLOG(1) << icon_url_; |
| 512 return; | 487 return; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 527 Destroy(FINAL_STATUS_HTTPS); | 502 Destroy(FINAL_STATUS_HTTPS); |
| 528 return false; | 503 return false; |
| 529 } | 504 } |
| 530 if (match_complete_status_ != MATCH_COMPLETE_REPLACEMENT_PENDING && | 505 if (match_complete_status_ != MATCH_COMPLETE_REPLACEMENT_PENDING && |
| 531 prerender_manager_->HasRecentlyBeenNavigatedTo(origin(), url)) { | 506 prerender_manager_->HasRecentlyBeenNavigatedTo(origin(), url)) { |
| 532 Destroy(FINAL_STATUS_RECENTLY_VISITED); | 507 Destroy(FINAL_STATUS_RECENTLY_VISITED); |
| 533 return false; | 508 return false; |
| 534 } | 509 } |
| 535 | 510 |
| 536 alias_urls_.push_back(url); | 511 alias_urls_.push_back(url); |
| 537 InformRenderProcessAboutPrerender(url, true, creator_child_id_); | 512 NotifyPrerenderAddAlias(url); |
| 538 return true; | 513 return true; |
| 539 } | 514 } |
| 540 | 515 |
| 541 bool PrerenderContents::Matches( | 516 bool PrerenderContents::Matches( |
| 542 const GURL& url, | 517 const GURL& url, |
| 543 const SessionStorageNamespace* session_storage_namespace) const { | 518 const SessionStorageNamespace* session_storage_namespace) const { |
| 544 DCHECK(child_id_ == -1 || session_storage_namespace); | 519 DCHECK(child_id_ == -1 || session_storage_namespace); |
| 545 if (session_storage_namespace && | 520 if (session_storage_namespace && |
| 546 session_storage_namespace_id_ != session_storage_namespace->id()) | 521 session_storage_namespace_id_ != session_storage_namespace->id()) |
| 547 return false; | 522 return false; |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 bool PrerenderContents::IsCrossSiteNavigationPending() const { | 676 bool PrerenderContents::IsCrossSiteNavigationPending() const { |
| 702 if (!prerender_contents_.get() || !prerender_contents_->web_contents()) | 677 if (!prerender_contents_.get() || !prerender_contents_->web_contents()) |
| 703 return false; | 678 return false; |
| 704 const WebContents* web_contents = prerender_contents_->web_contents(); | 679 const WebContents* web_contents = prerender_contents_->web_contents(); |
| 705 return (web_contents->GetSiteInstance() != | 680 return (web_contents->GetSiteInstance() != |
| 706 web_contents->GetPendingSiteInstance()); | 681 web_contents->GetPendingSiteInstance()); |
| 707 } | 682 } |
| 708 | 683 |
| 709 | 684 |
| 710 } // namespace prerender | 685 } // namespace prerender |
| OLD | NEW |