| 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_manager.h" | 5 #include "chrome/browser/prerender/prerender_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <functional> | 8 #include <functional> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 if (!source_web_contents) | 341 if (!source_web_contents) |
| 342 return NULL; | 342 return NULL; |
| 343 if (source_web_contents->GetURL().host() == url.host()) | 343 if (source_web_contents->GetURL().host() == url.host()) |
| 344 origin = ORIGIN_LINK_REL_PRERENDER_SAMEDOMAIN; | 344 origin = ORIGIN_LINK_REL_PRERENDER_SAMEDOMAIN; |
| 345 // TODO(ajwong): This does not correctly handle storage for isolated apps. | 345 // TODO(ajwong): This does not correctly handle storage for isolated apps. |
| 346 session_storage_namespace = | 346 session_storage_namespace = |
| 347 source_web_contents->GetController() | 347 source_web_contents->GetController() |
| 348 .GetDefaultSessionStorageNamespace(); | 348 .GetDefaultSessionStorageNamespace(); |
| 349 } | 349 } |
| 350 | 350 |
| 351 // If the prerender request comes from a recently cancelled prerender that | |
| 352 // |this| still owns, then abort the prerender. | |
| 353 for (ScopedVector<PrerenderData>::iterator it = to_delete_prerenders_.begin(); | |
| 354 it != to_delete_prerenders_.end(); ++it) { | |
| 355 PrerenderContents* prerender_contents = (*it)->contents(); | |
| 356 int contents_child_id; | |
| 357 int contents_route_id; | |
| 358 if (prerender_contents->GetChildId(&contents_child_id) && | |
| 359 prerender_contents->GetRouteId(&contents_route_id)) { | |
| 360 if (contents_child_id == process_id && contents_route_id == route_id) | |
| 361 return NULL; | |
| 362 } | |
| 363 } | |
| 364 | |
| 365 if (PrerenderData* parent_prerender_data = | |
| 366 FindPrerenderDataForChildAndRoute(process_id, route_id)) { | |
| 367 // Instead of prerendering from inside of a running prerender, we will defer | |
| 368 // this request until its launcher is made visible. | |
| 369 if (PrerenderContents* contents = parent_prerender_data->contents()) { | |
| 370 PrerenderHandle* prerender_handle = | |
| 371 new PrerenderHandle(static_cast<PrerenderData*>(NULL)); | |
| 372 scoped_ptr<PrerenderContents::PendingPrerenderInfo> | |
| 373 pending_prerender_info(new PrerenderContents::PendingPrerenderInfo( | |
| 374 prerender_handle->weak_ptr_factory_.GetWeakPtr(), | |
| 375 origin, url, referrer, size)); | |
| 376 | |
| 377 contents->AddPendingPrerender(pending_prerender_info.Pass()); | |
| 378 return prerender_handle; | |
| 379 } | |
| 380 } | |
| 381 | |
| 382 return AddPrerender(origin, process_id, url, referrer, size, | 351 return AddPrerender(origin, process_id, url, referrer, size, |
| 383 session_storage_namespace); | 352 session_storage_namespace); |
| 384 } | 353 } |
| 385 | 354 |
| 386 PrerenderHandle* PrerenderManager::AddPrerenderFromOmnibox( | 355 PrerenderHandle* PrerenderManager::AddPrerenderFromOmnibox( |
| 387 const GURL& url, | 356 const GURL& url, |
| 388 SessionStorageNamespace* session_storage_namespace, | 357 SessionStorageNamespace* session_storage_namespace, |
| 389 const gfx::Size& size) { | 358 const gfx::Size& size) { |
| 390 if (!IsOmniboxEnabled(profile_)) | 359 if (!IsOmniboxEnabled(profile_)) |
| 391 return NULL; | 360 return NULL; |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 | 561 |
| 593 // For bookkeeping purposes, we need to mark this WebContents to | 562 // For bookkeeping purposes, we need to mark this WebContents to |
| 594 // reflect that it would have been prerendered. | 563 // reflect that it would have been prerendered. |
| 595 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { | 564 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { |
| 596 MarkWebContentsAsWouldBePrerendered(web_contents, | 565 MarkWebContentsAsWouldBePrerendered(web_contents, |
| 597 prerender_data->contents()->origin()); | 566 prerender_data->contents()->origin()); |
| 598 prerender_data->contents()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); | 567 prerender_data->contents()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); |
| 599 return NULL; | 568 return NULL; |
| 600 } | 569 } |
| 601 | 570 |
| 602 int child_id, route_id; | |
| 603 CHECK(prerender_data->contents()->GetChildId(&child_id)); | |
| 604 CHECK(prerender_data->contents()->GetRouteId(&route_id)); | |
| 605 | |
| 606 // At this point, we've determined that we will use the prerender. | 571 // At this point, we've determined that we will use the prerender. |
| 607 if (prerender_data->pending_swap()) | 572 if (prerender_data->pending_swap()) |
| 608 prerender_data->pending_swap()->set_swap_successful(true); | 573 prerender_data->pending_swap()->set_swap_successful(true); |
| 609 ScopedVector<PrerenderData>::iterator to_erase = | 574 ScopedVector<PrerenderData>::iterator to_erase = |
| 610 FindIteratorForPrerenderContents(prerender_data->contents()); | 575 FindIteratorForPrerenderContents(prerender_data->contents()); |
| 611 DCHECK(active_prerenders_.end() != to_erase); | 576 DCHECK(active_prerenders_.end() != to_erase); |
| 612 DCHECK_EQ(prerender_data, *to_erase); | 577 DCHECK_EQ(prerender_data, *to_erase); |
| 613 scoped_ptr<PrerenderContents> | 578 scoped_ptr<PrerenderContents> |
| 614 prerender_contents(prerender_data->ReleaseContents()); | 579 prerender_contents(prerender_data->ReleaseContents()); |
| 615 active_prerenders_.erase(to_erase); | 580 active_prerenders_.erase(to_erase); |
| 616 | 581 |
| 617 if (!prerender_contents->load_start_time().is_null()) { | 582 if (!prerender_contents->load_start_time().is_null()) { |
| 618 histograms_->RecordTimeUntilUsed( | 583 histograms_->RecordTimeUntilUsed( |
| 619 prerender_contents->origin(), | 584 prerender_contents->origin(), |
| 620 GetCurrentTimeTicks() - prerender_contents->load_start_time()); | 585 GetCurrentTimeTicks() - prerender_contents->load_start_time()); |
| 621 } | 586 } |
| 622 | 587 |
| 623 histograms_->RecordPerSessionCount(prerender_contents->origin(), | 588 histograms_->RecordPerSessionCount(prerender_contents->origin(), |
| 624 ++prerenders_per_session_count_); | 589 ++prerenders_per_session_count_); |
| 625 histograms_->RecordUsedPrerender(prerender_contents->origin()); | 590 histograms_->RecordUsedPrerender(prerender_contents->origin()); |
| 626 prerender_contents->SetFinalStatus(FINAL_STATUS_USED); | |
| 627 | 591 |
| 628 // Start pending prerender requests from the PrerenderContents, if there are | 592 // Mark prerender as used. |
| 629 // any. | |
| 630 prerender_contents->PrepareForUse(); | 593 prerender_contents->PrepareForUse(); |
| 631 | 594 |
| 632 WebContents* new_web_contents = | 595 WebContents* new_web_contents = |
| 633 prerender_contents->ReleasePrerenderContents(); | 596 prerender_contents->ReleasePrerenderContents(); |
| 634 WebContents* old_web_contents = web_contents; | 597 WebContents* old_web_contents = web_contents; |
| 635 DCHECK(new_web_contents); | 598 DCHECK(new_web_contents); |
| 636 DCHECK(old_web_contents); | 599 DCHECK(old_web_contents); |
| 637 | 600 |
| 638 MarkWebContentsAsPrerendered(new_web_contents, prerender_contents->origin()); | 601 MarkWebContentsAsPrerendered(new_web_contents, prerender_contents->origin()); |
| 639 | 602 |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 it != to_delete_prerenders_.end(); ++it) { | 843 it != to_delete_prerenders_.end(); ++it) { |
| 881 WebContents* prerender_web_contents = | 844 WebContents* prerender_web_contents = |
| 882 (*it)->contents()->prerender_contents(); | 845 (*it)->contents()->prerender_contents(); |
| 883 if (prerender_web_contents == web_contents) { | 846 if (prerender_web_contents == web_contents) { |
| 884 return (*it)->contents(); | 847 return (*it)->contents(); |
| 885 } | 848 } |
| 886 } | 849 } |
| 887 return NULL; | 850 return NULL; |
| 888 } | 851 } |
| 889 | 852 |
| 853 PrerenderContents* PrerenderManager::GetPrerenderContentsForRoute( |
| 854 int child_id, |
| 855 int route_id) const { |
| 856 content::WebContents* web_contents = |
| 857 tab_util::GetWebContentsByID(child_id, route_id); |
| 858 if (web_contents == NULL) |
| 859 return NULL; |
| 860 return GetPrerenderContents(web_contents); |
| 861 } |
| 862 |
| 890 const std::vector<WebContents*> | 863 const std::vector<WebContents*> |
| 891 PrerenderManager::GetAllPrerenderingContents() const { | 864 PrerenderManager::GetAllPrerenderingContents() const { |
| 892 DCHECK(CalledOnValidThread()); | 865 DCHECK(CalledOnValidThread()); |
| 893 std::vector<WebContents*> result; | 866 std::vector<WebContents*> result; |
| 894 | 867 |
| 895 for (ScopedVector<PrerenderData>::const_iterator it = | 868 for (ScopedVector<PrerenderData>::const_iterator it = |
| 896 active_prerenders_.begin(); | 869 active_prerenders_.begin(); |
| 897 it != active_prerenders_.end(); ++it) { | 870 it != active_prerenders_.end(); ++it) { |
| 898 if (WebContents* contents = (*it)->contents()->prerender_contents()) | 871 if (WebContents* contents = (*it)->contents()->prerender_contents()) |
| 899 result.push_back(contents); | 872 result.push_back(contents); |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1303 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_TIMED_OUT); | 1276 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_TIMED_OUT); |
| 1304 prerender_data_->ClearPendingSwap(); | 1277 prerender_data_->ClearPendingSwap(); |
| 1305 } | 1278 } |
| 1306 | 1279 |
| 1307 void PrerenderManager::SetPrerenderContentsFactory( | 1280 void PrerenderManager::SetPrerenderContentsFactory( |
| 1308 PrerenderContents::Factory* prerender_contents_factory) { | 1281 PrerenderContents::Factory* prerender_contents_factory) { |
| 1309 DCHECK(CalledOnValidThread()); | 1282 DCHECK(CalledOnValidThread()); |
| 1310 prerender_contents_factory_.reset(prerender_contents_factory); | 1283 prerender_contents_factory_.reset(prerender_contents_factory); |
| 1311 } | 1284 } |
| 1312 | 1285 |
| 1313 | |
| 1314 void PrerenderManager::StartPendingPrerenders( | |
| 1315 const int process_id, | |
| 1316 ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders, | |
| 1317 content::SessionStorageNamespace* session_storage_namespace) { | |
| 1318 for (ScopedVector<PrerenderContents::PendingPrerenderInfo>::iterator | |
| 1319 it = pending_prerenders->begin(); | |
| 1320 it != pending_prerenders->end(); ++it) { | |
| 1321 PrerenderContents::PendingPrerenderInfo* info = *it; | |
| 1322 PrerenderHandle* existing_prerender_handle = | |
| 1323 info->weak_prerender_handle.get(); | |
| 1324 if (!existing_prerender_handle) | |
| 1325 continue; | |
| 1326 | |
| 1327 DCHECK(!existing_prerender_handle->IsPrerendering()); | |
| 1328 DCHECK(process_id == -1 || session_storage_namespace); | |
| 1329 | |
| 1330 scoped_ptr<PrerenderHandle> new_prerender_handle(AddPrerender( | |
| 1331 info->origin, process_id, | |
| 1332 info->url, info->referrer, info->size, | |
| 1333 session_storage_namespace)); | |
| 1334 if (new_prerender_handle) { | |
| 1335 // AddPrerender has returned a new prerender handle to us. We want to make | |
| 1336 // |existing_prerender_handle| active, so move the underlying | |
| 1337 // PrerenderData to our new handle. | |
| 1338 existing_prerender_handle->AdoptPrerenderDataFrom( | |
| 1339 new_prerender_handle.get()); | |
| 1340 continue; | |
| 1341 } | |
| 1342 } | |
| 1343 } | |
| 1344 | |
| 1345 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { | 1286 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { |
| 1346 // The expiry time of our prerender data will likely change because of | 1287 // The expiry time of our prerender data will likely change because of |
| 1347 // this navigation. This requires a resort of active_prerenders_. | 1288 // this navigation. This requires a resort of active_prerenders_. |
| 1348 ScopedVector<PrerenderData>::iterator it = | 1289 ScopedVector<PrerenderData>::iterator it = |
| 1349 std::find(active_prerenders_.begin(), active_prerenders_.end(), | 1290 std::find(active_prerenders_.begin(), active_prerenders_.end(), |
| 1350 prerender_data); | 1291 prerender_data); |
| 1351 if (it == active_prerenders_.end()) | 1292 if (it == active_prerenders_.end()) |
| 1352 return; | 1293 return; |
| 1353 | 1294 |
| 1354 (*it)->set_expiry_time( | 1295 (*it)->set_expiry_time( |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1587 const SessionStorageNamespace* session_storage_namespace) { | 1528 const SessionStorageNamespace* session_storage_namespace) { |
| 1588 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); | 1529 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); |
| 1589 it != active_prerenders_.end(); ++it) { | 1530 it != active_prerenders_.end(); ++it) { |
| 1590 if ((*it)->contents()->Matches(url, session_storage_namespace)) | 1531 if ((*it)->contents()->Matches(url, session_storage_namespace)) |
| 1591 return *it; | 1532 return *it; |
| 1592 } | 1533 } |
| 1593 return NULL; | 1534 return NULL; |
| 1594 } | 1535 } |
| 1595 | 1536 |
| 1596 PrerenderManager::PrerenderData* | 1537 PrerenderManager::PrerenderData* |
| 1597 PrerenderManager::FindPrerenderDataForChildAndRoute( | |
| 1598 const int child_id, const int route_id) { | |
| 1599 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); | |
| 1600 it != active_prerenders_.end(); ++it) { | |
| 1601 PrerenderContents* prerender_contents = (*it)->contents(); | |
| 1602 | |
| 1603 int contents_child_id; | |
| 1604 if (!prerender_contents->GetChildId(&contents_child_id)) | |
| 1605 continue; | |
| 1606 int contents_route_id; | |
| 1607 if (!prerender_contents->GetRouteId(&contents_route_id)) | |
| 1608 continue; | |
| 1609 | |
| 1610 if (contents_child_id == child_id && contents_route_id == route_id) | |
| 1611 return *it; | |
| 1612 } | |
| 1613 return NULL; | |
| 1614 } | |
| 1615 | |
| 1616 PrerenderManager::PrerenderData* | |
| 1617 PrerenderManager::FindPrerenderDataForTargetContents( | 1538 PrerenderManager::FindPrerenderDataForTargetContents( |
| 1618 WebContents* target_contents) { | 1539 WebContents* target_contents) { |
| 1619 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); | 1540 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); |
| 1620 it != active_prerenders_.end(); ++it) { | 1541 it != active_prerenders_.end(); ++it) { |
| 1621 if ((*it)->pending_swap() && | 1542 if ((*it)->pending_swap() && |
| 1622 (*it)->pending_swap()->target_contents() == target_contents) | 1543 (*it)->pending_swap()->target_contents() == target_contents) |
| 1623 return *it; | 1544 return *it; |
| 1624 } | 1545 } |
| 1625 return NULL; | 1546 return NULL; |
| 1626 } | 1547 } |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1957 history::VisitVector* visists) { | 1878 history::VisitVector* visists) { |
| 1958 histograms_->RecordPrerenderPageVisitedStatus(origin, experiment_id, success); | 1879 histograms_->RecordPrerenderPageVisitedStatus(origin, experiment_id, success); |
| 1959 } | 1880 } |
| 1960 | 1881 |
| 1961 // static | 1882 // static |
| 1962 void PrerenderManager::HangSessionStorageMergesForTesting() { | 1883 void PrerenderManager::HangSessionStorageMergesForTesting() { |
| 1963 g_hang_session_storage_merges_for_testing = true; | 1884 g_hang_session_storage_merges_for_testing = true; |
| 1964 } | 1885 } |
| 1965 | 1886 |
| 1966 } // namespace prerender | 1887 } // namespace prerender |
| OLD | NEW |