| 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 #include "chrome/common/prerender_types.h" | 51 #include "chrome/common/prerender_types.h" |
| 52 #include "content/public/browser/browser_thread.h" | 52 #include "content/public/browser/browser_thread.h" |
| 53 #include "content/public/browser/devtools_agent_host.h" | 53 #include "content/public/browser/devtools_agent_host.h" |
| 54 #include "content/public/browser/navigation_controller.h" | 54 #include "content/public/browser/navigation_controller.h" |
| 55 #include "content/public/browser/notification_service.h" | 55 #include "content/public/browser/notification_service.h" |
| 56 #include "content/public/browser/notification_source.h" | 56 #include "content/public/browser/notification_source.h" |
| 57 #include "content/public/browser/render_frame_host.h" | 57 #include "content/public/browser/render_frame_host.h" |
| 58 #include "content/public/browser/render_process_host.h" | 58 #include "content/public/browser/render_process_host.h" |
| 59 #include "content/public/browser/render_view_host.h" | 59 #include "content/public/browser/render_view_host.h" |
| 60 #include "content/public/browser/session_storage_namespace.h" | 60 #include "content/public/browser/session_storage_namespace.h" |
| 61 #include "content/public/browser/storage_partition.h" |
| 61 #include "content/public/browser/web_contents.h" | 62 #include "content/public/browser/web_contents.h" |
| 62 #include "content/public/browser/web_contents_delegate.h" | 63 #include "content/public/browser/web_contents_delegate.h" |
| 63 #include "content/public/common/url_constants.h" | 64 #include "content/public/common/url_constants.h" |
| 64 #include "extensions/common/constants.h" | 65 #include "extensions/common/constants.h" |
| 65 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 66 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| 66 #include "net/url_request/url_request_context.h" | 67 #include "net/url_request/url_request_context.h" |
| 67 #include "net/url_request/url_request_context_getter.h" | 68 #include "net/url_request/url_request_context_getter.h" |
| 68 | 69 |
| 69 using content::BrowserThread; | 70 using content::BrowserThread; |
| 70 using content::RenderViewHost; | 71 using content::RenderViewHost; |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 : enabled_(profile && profile->GetPrefs() && | 239 : enabled_(profile && profile->GetPrefs() && |
| 239 profile->GetPrefs()->GetBoolean(prefs::kNetworkPredictionEnabled)), | 240 profile->GetPrefs()->GetBoolean(prefs::kNetworkPredictionEnabled)), |
| 240 profile_(profile), | 241 profile_(profile), |
| 241 prerender_tracker_(prerender_tracker), | 242 prerender_tracker_(prerender_tracker), |
| 242 prerender_contents_factory_(PrerenderContents::CreateFactory()), | 243 prerender_contents_factory_(PrerenderContents::CreateFactory()), |
| 243 last_prerender_start_time_(GetCurrentTimeTicks() - | 244 last_prerender_start_time_(GetCurrentTimeTicks() - |
| 244 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)), | 245 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)), |
| 245 prerender_history_(new PrerenderHistory(kHistoryLength)), | 246 prerender_history_(new PrerenderHistory(kHistoryLength)), |
| 246 histograms_(new PrerenderHistograms()), | 247 histograms_(new PrerenderHistograms()), |
| 247 profile_network_bytes_(0), | 248 profile_network_bytes_(0), |
| 248 last_recorded_profile_network_bytes_(0) { | 249 last_recorded_profile_network_bytes_(0), |
| 250 cookie_store_loaded_(false) { |
| 249 // There are some assumptions that the PrerenderManager is on the UI thread. | 251 // There are some assumptions that the PrerenderManager is on the UI thread. |
| 250 // Any other checks simply make sure that the PrerenderManager is accessed on | 252 // Any other checks simply make sure that the PrerenderManager is accessed on |
| 251 // the same thread that it was created on. | 253 // the same thread that it was created on. |
| 252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 253 | 255 |
| 254 if (IsLocalPredictorEnabled()) | 256 if (IsLocalPredictorEnabled()) |
| 255 local_predictor_.reset(new PrerenderLocalPredictor(this)); | 257 local_predictor_.reset(new PrerenderLocalPredictor(this)); |
| 256 | 258 |
| 257 if (IsLoggedInPredictorEnabled() && !profile_->IsOffTheRecord()) { | 259 if (IsLoggedInPredictorEnabled() && !profile_->IsOffTheRecord()) { |
| 258 predictors::PredictorDatabase* predictor_db = | 260 predictors::PredictorDatabase* predictor_db = |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this); | 298 MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this); |
| 297 } | 299 } |
| 298 | 300 |
| 299 PrerenderManager::~PrerenderManager() { | 301 PrerenderManager::~PrerenderManager() { |
| 300 MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this); | 302 MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this); |
| 301 | 303 |
| 302 // The earlier call to KeyedService::Shutdown() should have | 304 // The earlier call to KeyedService::Shutdown() should have |
| 303 // emptied these vectors already. | 305 // emptied these vectors already. |
| 304 DCHECK(active_prerenders_.empty()); | 306 DCHECK(active_prerenders_.empty()); |
| 305 DCHECK(to_delete_prerenders_.empty()); | 307 DCHECK(to_delete_prerenders_.empty()); |
| 308 |
| 309 for (PrerenderProcessSet::const_iterator it = |
| 310 prerender_process_hosts_.begin(); |
| 311 it != prerender_process_hosts_.end(); |
| 312 ++it) { |
| 313 (*it)->RemoveObserver(this); |
| 314 } |
| 306 } | 315 } |
| 307 | 316 |
| 308 void PrerenderManager::Shutdown() { | 317 void PrerenderManager::Shutdown() { |
| 309 DestroyAllContents(FINAL_STATUS_MANAGER_SHUTDOWN); | 318 DestroyAllContents(FINAL_STATUS_MANAGER_SHUTDOWN); |
| 310 STLDeleteElements(&prerender_conditions_); | 319 STLDeleteElements(&prerender_conditions_); |
| 311 on_close_web_contents_deleters_.clear(); | 320 on_close_web_contents_deleters_.clear(); |
| 312 // Must happen before |profile_| is set to NULL as | 321 // Must happen before |profile_| is set to NULL as |
| 313 // |local_predictor_| accesses it. | 322 // |local_predictor_| accesses it. |
| 314 if (local_predictor_) | 323 if (local_predictor_) |
| 315 local_predictor_->Shutdown(); | 324 local_predictor_->Shutdown(); |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 // For bookkeeping purposes, we need to mark this WebContents to | 579 // For bookkeeping purposes, we need to mark this WebContents to |
| 571 // reflect that it would have been prerendered. | 580 // reflect that it would have been prerendered. |
| 572 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { | 581 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { |
| 573 target_tab_helper->WouldHavePrerenderedNextLoad( | 582 target_tab_helper->WouldHavePrerenderedNextLoad( |
| 574 prerender_data->contents()->origin()); | 583 prerender_data->contents()->origin()); |
| 575 prerender_data->contents()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); | 584 prerender_data->contents()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); |
| 576 return NULL; | 585 return NULL; |
| 577 } | 586 } |
| 578 | 587 |
| 579 // At this point, we've determined that we will use the prerender. | 588 // At this point, we've determined that we will use the prerender. |
| 589 content::RenderProcessHost* process_host = |
| 590 prerender_data->contents()->GetRenderViewHost()->GetProcess(); |
| 591 prerender_process_hosts_.erase(process_host); |
| 592 BrowserThread::PostTask( |
| 593 BrowserThread::IO, FROM_HERE, |
| 594 base::Bind(&PrerenderTracker::RemovePrerenderCookieStoreOnIOThread, |
| 595 base::Unretained(prerender_tracker()), process_host->GetID(), |
| 596 true)); |
| 580 if (!prerender_data->contents()->load_start_time().is_null()) { | 597 if (!prerender_data->contents()->load_start_time().is_null()) { |
| 581 histograms_->RecordTimeUntilUsed( | 598 histograms_->RecordTimeUntilUsed( |
| 582 prerender_data->contents()->origin(), | 599 prerender_data->contents()->origin(), |
| 583 GetCurrentTimeTicks() - prerender_data->contents()->load_start_time()); | 600 GetCurrentTimeTicks() - prerender_data->contents()->load_start_time()); |
| 584 } | 601 } |
| 585 histograms_->RecordAbandonTimeUntilUsed( | 602 histograms_->RecordAbandonTimeUntilUsed( |
| 586 prerender_data->contents()->origin(), | 603 prerender_data->contents()->origin(), |
| 587 prerender_data->abandon_time().is_null() ? | 604 prerender_data->abandon_time().is_null() ? |
| 588 base::TimeDelta() : | 605 base::TimeDelta() : |
| 589 GetCurrentTimeTicks() - prerender_data->abandon_time()); | 606 GetCurrentTimeTicks() - prerender_data->abandon_time()); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 case PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP: | 758 case PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP: |
| 742 return "_Multi"; | 759 return "_Multi"; |
| 743 case PRERENDER_MODE_EXPERIMENT_15MIN_TTL_GROUP: | 760 case PRERENDER_MODE_EXPERIMENT_15MIN_TTL_GROUP: |
| 744 return "_15MinTTL"; | 761 return "_15MinTTL"; |
| 745 case PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP: | 762 case PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP: |
| 746 return "_NoUse"; | 763 return "_NoUse"; |
| 747 case PRERENDER_MODE_MAX: | 764 case PRERENDER_MODE_MAX: |
| 748 default: | 765 default: |
| 749 NOTREACHED() << "Invalid PrerenderManager mode."; | 766 NOTREACHED() << "Invalid PrerenderManager mode."; |
| 750 break; | 767 break; |
| 751 }; | 768 } |
| 752 return ""; | 769 return ""; |
| 753 } | 770 } |
| 754 | 771 |
| 755 // static | 772 // static |
| 756 bool PrerenderManager::IsPrerenderingPossible() { | 773 bool PrerenderManager::IsPrerenderingPossible() { |
| 757 return GetMode() != PRERENDER_MODE_DISABLED; | 774 return GetMode() != PRERENDER_MODE_DISABLED; |
| 758 } | 775 } |
| 759 | 776 |
| 760 // static | 777 // static |
| 761 bool PrerenderManager::ActuallyPrerendering() { | 778 bool PrerenderManager::ActuallyPrerendering() { |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1209 prerender_data); | 1226 prerender_data); |
| 1210 if (it == active_prerenders_.end()) | 1227 if (it == active_prerenders_.end()) |
| 1211 return; | 1228 return; |
| 1212 | 1229 |
| 1213 (*it)->set_expiry_time( | 1230 (*it)->set_expiry_time( |
| 1214 std::min((*it)->expiry_time(), | 1231 std::min((*it)->expiry_time(), |
| 1215 GetExpiryTimeForNavigatedAwayPrerender())); | 1232 GetExpiryTimeForNavigatedAwayPrerender())); |
| 1216 SortActivePrerenders(); | 1233 SortActivePrerenders(); |
| 1217 } | 1234 } |
| 1218 | 1235 |
| 1236 net::URLRequestContextGetter* PrerenderManager::GetURLRequestContext() { |
| 1237 return content::BrowserContext::GetDefaultStoragePartition(profile_)-> |
| 1238 GetURLRequestContext(); |
| 1239 } |
| 1240 |
| 1241 |
| 1219 // private | 1242 // private |
| 1220 PrerenderHandle* PrerenderManager::AddPrerender( | 1243 PrerenderHandle* PrerenderManager::AddPrerender( |
| 1221 Origin origin, | 1244 Origin origin, |
| 1222 int process_id, | 1245 int process_id, |
| 1223 const GURL& url_arg, | 1246 const GURL& url_arg, |
| 1224 const content::Referrer& referrer, | 1247 const content::Referrer& referrer, |
| 1225 const gfx::Size& size, | 1248 const gfx::Size& size, |
| 1226 SessionStorageNamespace* session_storage_namespace) { | 1249 SessionStorageNamespace* session_storage_namespace) { |
| 1227 DCHECK(CalledOnValidThread()); | 1250 DCHECK(CalledOnValidThread()); |
| 1228 | 1251 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1273 | 1296 |
| 1274 // Check if enough time has passed since the last prerender. | 1297 // Check if enough time has passed since the last prerender. |
| 1275 if (!DoesRateLimitAllowPrerender(origin)) { | 1298 if (!DoesRateLimitAllowPrerender(origin)) { |
| 1276 // Cancel the prerender. We could add it to the pending prerender list but | 1299 // Cancel the prerender. We could add it to the pending prerender list but |
| 1277 // this doesn't make sense as the next prerender request will be triggered | 1300 // this doesn't make sense as the next prerender request will be triggered |
| 1278 // by a navigation and is unlikely to be the same site. | 1301 // by a navigation and is unlikely to be the same site. |
| 1279 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); | 1302 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); |
| 1280 return NULL; | 1303 return NULL; |
| 1281 } | 1304 } |
| 1282 | 1305 |
| 1306 if (!cookie_store_loaded()) { |
| 1307 // Only prerender if the cookie store for this profile has been loaded. |
| 1308 // This is required by PrerenderCookieMonster. |
| 1309 RecordFinalStatus(origin, experiment, FINAL_STATUS_COOKIE_STORE_NOT_LOADED); |
| 1310 return NULL; |
| 1311 } |
| 1312 |
| 1283 PrerenderContents* prerender_contents = CreatePrerenderContents( | 1313 PrerenderContents* prerender_contents = CreatePrerenderContents( |
| 1284 url, referrer, origin, experiment); | 1314 url, referrer, origin, experiment); |
| 1285 DCHECK(prerender_contents); | 1315 DCHECK(prerender_contents); |
| 1286 active_prerenders_.push_back( | 1316 active_prerenders_.push_back( |
| 1287 new PrerenderData(this, prerender_contents, | 1317 new PrerenderData(this, prerender_contents, |
| 1288 GetExpiryTimeForNewPrerender(origin))); | 1318 GetExpiryTimeForNewPrerender(origin))); |
| 1289 if (!prerender_contents->Init()) { | 1319 if (!prerender_contents->Init()) { |
| 1290 DCHECK(active_prerenders_.end() == | 1320 DCHECK(active_prerenders_.end() == |
| 1291 FindIteratorForPrerenderContents(prerender_contents)); | 1321 FindIteratorForPrerenderContents(prerender_contents)); |
| 1292 return NULL; | 1322 return NULL; |
| 1293 } | 1323 } |
| 1294 | 1324 |
| 1295 histograms_->RecordPrerenderStarted(origin); | 1325 histograms_->RecordPrerenderStarted(origin); |
| 1296 DCHECK(!prerender_contents->prerendering_has_started()); | 1326 DCHECK(!prerender_contents->prerendering_has_started()); |
| 1297 | 1327 |
| 1298 PrerenderHandle* prerender_handle = | 1328 PrerenderHandle* prerender_handle = |
| 1299 new PrerenderHandle(active_prerenders_.back()); | 1329 new PrerenderHandle(active_prerenders_.back()); |
| 1300 SortActivePrerenders(); | 1330 SortActivePrerenders(); |
| 1301 | 1331 |
| 1302 last_prerender_start_time_ = GetCurrentTimeTicks(); | 1332 last_prerender_start_time_ = GetCurrentTimeTicks(); |
| 1303 | 1333 |
| 1304 gfx::Size contents_size = | 1334 gfx::Size contents_size = |
| 1305 size.IsEmpty() ? config_.default_tab_bounds.size() : size; | 1335 size.IsEmpty() ? config_.default_tab_bounds.size() : size; |
| 1306 | 1336 |
| 1337 net::URLRequestContextGetter* request_context = GetURLRequestContext(); |
| 1338 |
| 1307 prerender_contents->StartPrerendering(process_id, contents_size, | 1339 prerender_contents->StartPrerendering(process_id, contents_size, |
| 1308 session_storage_namespace); | 1340 session_storage_namespace, |
| 1341 request_context); |
| 1309 | 1342 |
| 1310 DCHECK(IsControlGroup(experiment) || | 1343 DCHECK(IsControlGroup(experiment) || |
| 1311 prerender_contents->prerendering_has_started()); | 1344 prerender_contents->prerendering_has_started() || |
| 1345 (origin == ORIGIN_LOCAL_PREDICTOR && |
| 1346 IsLocalPredictorPrerenderAlwaysControlEnabled())); |
| 1312 | 1347 |
| 1313 if (GetMode() == PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP) | 1348 if (GetMode() == PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP) |
| 1314 histograms_->RecordConcurrency(active_prerenders_.size()); | 1349 histograms_->RecordConcurrency(active_prerenders_.size()); |
| 1315 | 1350 |
| 1316 // Query the history to see if the URL being prerendered has ever been | 1351 // Query the history to see if the URL being prerendered has ever been |
| 1317 // visited before. | 1352 // visited before. |
| 1318 HistoryService* history_service = HistoryServiceFactory::GetForProfile( | 1353 HistoryService* history_service = HistoryServiceFactory::GetForProfile( |
| 1319 profile_, Profile::EXPLICIT_ACCESS); | 1354 profile_, Profile::EXPLICIT_ACCESS); |
| 1320 if (history_service) { | 1355 if (history_service) { |
| 1321 history_service->QueryURL( | 1356 history_service->QueryURL( |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1819 DCHECK_GE(recent_profile_bytes, 0); | 1854 DCHECK_GE(recent_profile_bytes, 0); |
| 1820 histograms_->RecordNetworkBytes(used, prerender_bytes, recent_profile_bytes); | 1855 histograms_->RecordNetworkBytes(used, prerender_bytes, recent_profile_bytes); |
| 1821 } | 1856 } |
| 1822 | 1857 |
| 1823 void PrerenderManager::AddProfileNetworkBytesIfEnabled(int64 bytes) { | 1858 void PrerenderManager::AddProfileNetworkBytesIfEnabled(int64 bytes) { |
| 1824 DCHECK_GE(bytes, 0); | 1859 DCHECK_GE(bytes, 0); |
| 1825 if (IsEnabled() && ActuallyPrerendering()) | 1860 if (IsEnabled() && ActuallyPrerendering()) |
| 1826 profile_network_bytes_ += bytes; | 1861 profile_network_bytes_ += bytes; |
| 1827 } | 1862 } |
| 1828 | 1863 |
| 1864 void PrerenderManager::OnCookieStoreLoaded() { |
| 1865 cookie_store_loaded_ = true; |
| 1866 if (!on_cookie_store_loaded_cb_for_testing_.is_null()) |
| 1867 on_cookie_store_loaded_cb_for_testing_.Run(); |
| 1868 } |
| 1869 |
| 1870 void PrerenderManager::AddPrerenderProcessHost( |
| 1871 content::RenderProcessHost* process_host) { |
| 1872 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1873 DCHECK(prerender_process_hosts_.find(process_host) == |
| 1874 prerender_process_hosts_.end()); |
| 1875 prerender_process_hosts_.insert(process_host); |
| 1876 process_host->AddObserver(this); |
| 1877 } |
| 1878 |
| 1879 bool PrerenderManager::IsProcessPrerendering( |
| 1880 content::RenderProcessHost* process_host) { |
| 1881 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1882 return (prerender_process_hosts_.find(process_host) != |
| 1883 prerender_process_hosts_.end()); |
| 1884 } |
| 1885 |
| 1886 void PrerenderManager::RenderProcessHostDestroyed( |
| 1887 content::RenderProcessHost* host) { |
| 1888 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1889 prerender_process_hosts_.erase(host); |
| 1890 BrowserThread::PostTask( |
| 1891 BrowserThread::IO, FROM_HERE, |
| 1892 base::Bind(&PrerenderTracker::RemovePrerenderCookieStoreOnIOThread, |
| 1893 base::Unretained(prerender_tracker()), host->GetID(), false)); |
| 1894 } |
| 1895 |
| 1829 } // namespace prerender | 1896 } // namespace prerender |
| OLD | NEW |