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 |