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 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 if (!source_web_contents) | 338 if (!source_web_contents) |
339 return NULL; | 339 return NULL; |
340 if (source_web_contents->GetURL().host() == url.host()) | 340 if (source_web_contents->GetURL().host() == url.host()) |
341 origin = ORIGIN_LINK_REL_PRERENDER_SAMEDOMAIN; | 341 origin = ORIGIN_LINK_REL_PRERENDER_SAMEDOMAIN; |
342 // TODO(ajwong): This does not correctly handle storage for isolated apps. | 342 // TODO(ajwong): This does not correctly handle storage for isolated apps. |
343 session_storage_namespace = | 343 session_storage_namespace = |
344 source_web_contents->GetController() | 344 source_web_contents->GetController() |
345 .GetDefaultSessionStorageNamespace(); | 345 .GetDefaultSessionStorageNamespace(); |
346 } | 346 } |
347 | 347 |
348 // If the prerender request comes from a recently cancelled prerender that | |
349 // |this| still owns, then abort the prerender. | |
350 for (ScopedVector<PrerenderData>::iterator it = to_delete_prerenders_.begin(); | |
351 it != to_delete_prerenders_.end(); ++it) { | |
352 PrerenderContents* prerender_contents = (*it)->contents(); | |
353 int contents_child_id; | |
354 int contents_route_id; | |
355 if (prerender_contents->GetChildId(&contents_child_id) && | |
356 prerender_contents->GetRouteId(&contents_route_id)) { | |
357 if (contents_child_id == process_id && contents_route_id == route_id) | |
358 return NULL; | |
359 } | |
360 } | |
361 | |
362 if (PrerenderData* parent_prerender_data = | |
363 FindPrerenderDataForChildAndRoute(process_id, route_id)) { | |
364 // Instead of prerendering from inside of a running prerender, we will defer | |
365 // this request until its launcher is made visible. | |
366 if (PrerenderContents* contents = parent_prerender_data->contents()) { | |
367 PrerenderHandle* prerender_handle = | |
368 new PrerenderHandle(static_cast<PrerenderData*>(NULL)); | |
369 scoped_ptr<PrerenderContents::PendingPrerenderInfo> | |
370 pending_prerender_info(new PrerenderContents::PendingPrerenderInfo( | |
371 prerender_handle->weak_ptr_factory_.GetWeakPtr(), | |
372 origin, url, referrer, size)); | |
373 | |
374 contents->AddPendingPrerender(pending_prerender_info.Pass()); | |
375 return prerender_handle; | |
376 } | |
377 } | |
378 | |
379 return AddPrerender(origin, process_id, url, referrer, size, | 348 return AddPrerender(origin, process_id, url, referrer, size, |
380 session_storage_namespace); | 349 session_storage_namespace); |
381 } | 350 } |
382 | 351 |
383 PrerenderHandle* PrerenderManager::AddPrerenderFromOmnibox( | 352 PrerenderHandle* PrerenderManager::AddPrerenderFromOmnibox( |
384 const GURL& url, | 353 const GURL& url, |
385 SessionStorageNamespace* session_storage_namespace, | 354 SessionStorageNamespace* session_storage_namespace, |
386 const gfx::Size& size) { | 355 const gfx::Size& size) { |
387 if (!IsOmniboxEnabled(profile_)) | 356 if (!IsOmniboxEnabled(profile_)) |
388 return NULL; | 357 return NULL; |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 | 552 |
584 // For bookkeeping purposes, we need to mark this WebContents to | 553 // For bookkeeping purposes, we need to mark this WebContents to |
585 // reflect that it would have been prerendered. | 554 // reflect that it would have been prerendered. |
586 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { | 555 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { |
587 MarkWebContentsAsWouldBePrerendered(web_contents, | 556 MarkWebContentsAsWouldBePrerendered(web_contents, |
588 prerender_data->contents()->origin()); | 557 prerender_data->contents()->origin()); |
589 prerender_data->contents()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); | 558 prerender_data->contents()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); |
590 return NULL; | 559 return NULL; |
591 } | 560 } |
592 | 561 |
593 int child_id, route_id; | |
594 CHECK(prerender_data->contents()->GetChildId(&child_id)); | |
595 CHECK(prerender_data->contents()->GetRouteId(&route_id)); | |
596 | |
597 // At this point, we've determined that we will use the prerender. | 562 // At this point, we've determined that we will use the prerender. |
598 if (prerender_data->pending_swap()) | 563 if (prerender_data->pending_swap()) |
599 prerender_data->pending_swap()->set_swap_successful(true); | 564 prerender_data->pending_swap()->set_swap_successful(true); |
600 ScopedVector<PrerenderData>::iterator to_erase = | 565 ScopedVector<PrerenderData>::iterator to_erase = |
601 FindIteratorForPrerenderContents(prerender_data->contents()); | 566 FindIteratorForPrerenderContents(prerender_data->contents()); |
602 DCHECK(active_prerenders_.end() != to_erase); | 567 DCHECK(active_prerenders_.end() != to_erase); |
603 DCHECK_EQ(prerender_data, *to_erase); | 568 DCHECK_EQ(prerender_data, *to_erase); |
604 scoped_ptr<PrerenderContents> | 569 scoped_ptr<PrerenderContents> |
605 prerender_contents(prerender_data->ReleaseContents()); | 570 prerender_contents(prerender_data->ReleaseContents()); |
606 active_prerenders_.erase(to_erase); | 571 active_prerenders_.erase(to_erase); |
607 | 572 |
608 if (!prerender_contents->load_start_time().is_null()) { | 573 if (!prerender_contents->load_start_time().is_null()) { |
609 histograms_->RecordTimeUntilUsed( | 574 histograms_->RecordTimeUntilUsed( |
610 prerender_contents->origin(), | 575 prerender_contents->origin(), |
611 GetCurrentTimeTicks() - prerender_contents->load_start_time()); | 576 GetCurrentTimeTicks() - prerender_contents->load_start_time()); |
612 } | 577 } |
613 | 578 |
614 histograms_->RecordPerSessionCount(prerender_contents->origin(), | 579 histograms_->RecordPerSessionCount(prerender_contents->origin(), |
615 ++prerenders_per_session_count_); | 580 ++prerenders_per_session_count_); |
616 histograms_->RecordUsedPrerender(prerender_contents->origin()); | 581 histograms_->RecordUsedPrerender(prerender_contents->origin()); |
617 prerender_contents->SetFinalStatus(FINAL_STATUS_USED); | |
618 | 582 |
619 // Start pending prerender requests from the PrerenderContents, if there are | 583 // Mark prerender as used. |
620 // any. | |
621 prerender_contents->PrepareForUse(); | 584 prerender_contents->PrepareForUse(); |
622 | 585 |
623 WebContents* new_web_contents = | 586 WebContents* new_web_contents = |
624 prerender_contents->ReleasePrerenderContents(); | 587 prerender_contents->ReleasePrerenderContents(); |
625 WebContents* old_web_contents = web_contents; | 588 WebContents* old_web_contents = web_contents; |
626 DCHECK(new_web_contents); | 589 DCHECK(new_web_contents); |
627 DCHECK(old_web_contents); | 590 DCHECK(old_web_contents); |
628 | 591 |
629 MarkWebContentsAsPrerendered(new_web_contents, prerender_contents->origin()); | 592 MarkWebContentsAsPrerendered(new_web_contents, prerender_contents->origin()); |
630 | 593 |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
867 it != to_delete_prerenders_.end(); ++it) { | 830 it != to_delete_prerenders_.end(); ++it) { |
868 WebContents* prerender_web_contents = | 831 WebContents* prerender_web_contents = |
869 (*it)->contents()->prerender_contents(); | 832 (*it)->contents()->prerender_contents(); |
870 if (prerender_web_contents == web_contents) { | 833 if (prerender_web_contents == web_contents) { |
871 return (*it)->contents(); | 834 return (*it)->contents(); |
872 } | 835 } |
873 } | 836 } |
874 return NULL; | 837 return NULL; |
875 } | 838 } |
876 | 839 |
| 840 PrerenderContents* PrerenderManager::GetPrerenderContentsForRoute( |
| 841 int child_id, |
| 842 int route_id) const { |
| 843 content::WebContents* web_contents = |
| 844 tab_util::GetWebContentsByID(child_id, route_id); |
| 845 if (web_contents == NULL) |
| 846 return NULL; |
| 847 return GetPrerenderContents(web_contents); |
| 848 } |
| 849 |
877 const std::vector<WebContents*> | 850 const std::vector<WebContents*> |
878 PrerenderManager::GetAllPrerenderingContents() const { | 851 PrerenderManager::GetAllPrerenderingContents() const { |
879 DCHECK(CalledOnValidThread()); | 852 DCHECK(CalledOnValidThread()); |
880 std::vector<WebContents*> result; | 853 std::vector<WebContents*> result; |
881 | 854 |
882 for (ScopedVector<PrerenderData>::const_iterator it = | 855 for (ScopedVector<PrerenderData>::const_iterator it = |
883 active_prerenders_.begin(); | 856 active_prerenders_.begin(); |
884 it != active_prerenders_.end(); ++it) { | 857 it != active_prerenders_.end(); ++it) { |
885 if (WebContents* contents = (*it)->contents()->prerender_contents()) | 858 if (WebContents* contents = (*it)->contents()->prerender_contents()) |
886 result.push_back(contents); | 859 result.push_back(contents); |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1282 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_TIMED_OUT); | 1255 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_TIMED_OUT); |
1283 prerender_data_->ClearPendingSwap(); | 1256 prerender_data_->ClearPendingSwap(); |
1284 } | 1257 } |
1285 | 1258 |
1286 void PrerenderManager::SetPrerenderContentsFactory( | 1259 void PrerenderManager::SetPrerenderContentsFactory( |
1287 PrerenderContents::Factory* prerender_contents_factory) { | 1260 PrerenderContents::Factory* prerender_contents_factory) { |
1288 DCHECK(CalledOnValidThread()); | 1261 DCHECK(CalledOnValidThread()); |
1289 prerender_contents_factory_.reset(prerender_contents_factory); | 1262 prerender_contents_factory_.reset(prerender_contents_factory); |
1290 } | 1263 } |
1291 | 1264 |
1292 | |
1293 void PrerenderManager::StartPendingPrerenders( | |
1294 const int process_id, | |
1295 ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders, | |
1296 content::SessionStorageNamespace* session_storage_namespace) { | |
1297 for (ScopedVector<PrerenderContents::PendingPrerenderInfo>::iterator | |
1298 it = pending_prerenders->begin(); | |
1299 it != pending_prerenders->end(); ++it) { | |
1300 PrerenderContents::PendingPrerenderInfo* info = *it; | |
1301 PrerenderHandle* existing_prerender_handle = | |
1302 info->weak_prerender_handle.get(); | |
1303 if (!existing_prerender_handle) | |
1304 continue; | |
1305 | |
1306 DCHECK(!existing_prerender_handle->IsPrerendering()); | |
1307 DCHECK(process_id == -1 || session_storage_namespace); | |
1308 | |
1309 scoped_ptr<PrerenderHandle> new_prerender_handle(AddPrerender( | |
1310 info->origin, process_id, | |
1311 info->url, info->referrer, info->size, | |
1312 session_storage_namespace)); | |
1313 if (new_prerender_handle) { | |
1314 // AddPrerender has returned a new prerender handle to us. We want to make | |
1315 // |existing_prerender_handle| active, so move the underlying | |
1316 // PrerenderData to our new handle. | |
1317 existing_prerender_handle->AdoptPrerenderDataFrom( | |
1318 new_prerender_handle.get()); | |
1319 continue; | |
1320 } | |
1321 } | |
1322 } | |
1323 | |
1324 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { | 1265 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { |
1325 // The expiry time of our prerender data will likely change because of | 1266 // The expiry time of our prerender data will likely change because of |
1326 // this navigation. This requires a resort of active_prerenders_. | 1267 // this navigation. This requires a resort of active_prerenders_. |
1327 ScopedVector<PrerenderData>::iterator it = | 1268 ScopedVector<PrerenderData>::iterator it = |
1328 std::find(active_prerenders_.begin(), active_prerenders_.end(), | 1269 std::find(active_prerenders_.begin(), active_prerenders_.end(), |
1329 prerender_data); | 1270 prerender_data); |
1330 if (it == active_prerenders_.end()) | 1271 if (it == active_prerenders_.end()) |
1331 return; | 1272 return; |
1332 | 1273 |
1333 (*it)->set_expiry_time( | 1274 (*it)->set_expiry_time( |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1565 const GURL& url, | 1506 const GURL& url, |
1566 const SessionStorageNamespace* session_storage_namespace) { | 1507 const SessionStorageNamespace* session_storage_namespace) { |
1567 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); | 1508 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); |
1568 it != active_prerenders_.end(); ++it) { | 1509 it != active_prerenders_.end(); ++it) { |
1569 if ((*it)->contents()->Matches(url, session_storage_namespace)) | 1510 if ((*it)->contents()->Matches(url, session_storage_namespace)) |
1570 return *it; | 1511 return *it; |
1571 } | 1512 } |
1572 return NULL; | 1513 return NULL; |
1573 } | 1514 } |
1574 | 1515 |
1575 PrerenderManager::PrerenderData* | |
1576 PrerenderManager::FindPrerenderDataForChildAndRoute( | |
1577 const int child_id, const int route_id) { | |
1578 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); | |
1579 it != active_prerenders_.end(); ++it) { | |
1580 PrerenderContents* prerender_contents = (*it)->contents(); | |
1581 | |
1582 int contents_child_id; | |
1583 if (!prerender_contents->GetChildId(&contents_child_id)) | |
1584 continue; | |
1585 int contents_route_id; | |
1586 if (!prerender_contents->GetRouteId(&contents_route_id)) | |
1587 continue; | |
1588 | |
1589 if (contents_child_id == child_id && contents_route_id == route_id) | |
1590 return *it; | |
1591 } | |
1592 return NULL; | |
1593 } | |
1594 | |
1595 ScopedVector<PrerenderManager::PrerenderData>::iterator | 1516 ScopedVector<PrerenderManager::PrerenderData>::iterator |
1596 PrerenderManager::FindIteratorForPrerenderContents( | 1517 PrerenderManager::FindIteratorForPrerenderContents( |
1597 PrerenderContents* prerender_contents) { | 1518 PrerenderContents* prerender_contents) { |
1598 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); | 1519 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); |
1599 it != active_prerenders_.end(); ++it) { | 1520 it != active_prerenders_.end(); ++it) { |
1600 if (prerender_contents == (*it)->contents()) | 1521 if (prerender_contents == (*it)->contents()) |
1601 return it; | 1522 return it; |
1602 } | 1523 } |
1603 return active_prerenders_.end(); | 1524 return active_prerenders_.end(); |
1604 } | 1525 } |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1919 Origin origin, | 1840 Origin origin, |
1920 uint8 experiment_id, | 1841 uint8 experiment_id, |
1921 CancelableRequestProvider::Handle handle, | 1842 CancelableRequestProvider::Handle handle, |
1922 bool success, | 1843 bool success, |
1923 const history::URLRow* url_row, | 1844 const history::URLRow* url_row, |
1924 history::VisitVector* visists) { | 1845 history::VisitVector* visists) { |
1925 histograms_->RecordPrerenderPageVisitedStatus(origin, experiment_id, success); | 1846 histograms_->RecordPrerenderPageVisitedStatus(origin, experiment_id, success); |
1926 } | 1847 } |
1927 | 1848 |
1928 } // namespace prerender | 1849 } // namespace prerender |
OLD | NEW |