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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1276 // Check if enough time has passed since the last prerender. | 1299 // Check if enough time has passed since the last prerender. |
1277 if (!DoesRateLimitAllowPrerender(origin)) { | 1300 if (!DoesRateLimitAllowPrerender(origin)) { |
1278 // Cancel the prerender. We could add it to the pending prerender list but | 1301 // Cancel the prerender. We could add it to the pending prerender list but |
1279 // this doesn't make sense as the next prerender request will be triggered | 1302 // this doesn't make sense as the next prerender request will be triggered |
1280 // by a navigation and is unlikely to be the same site. | 1303 // by a navigation and is unlikely to be the same site. |
1281 RecordFinalStatusWithoutCreatingPrerenderContents( | 1304 RecordFinalStatusWithoutCreatingPrerenderContents( |
1282 url, origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); | 1305 url, origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); |
1283 return NULL; | 1306 return NULL; |
1284 } | 1307 } |
1285 | 1308 |
| 1309 if (!cookie_store_loaded()) { |
| 1310 // Only prerender if the cookie store for this profile has been loaded. |
| 1311 // This is required by PrerenderCookieMonster. |
| 1312 RecordFinalStatusWithoutCreatingPrerenderContents( |
| 1313 url, origin, experiment, FINAL_STATUS_COOKIE_STORE_NOT_LOADED); |
| 1314 return NULL; |
| 1315 } |
| 1316 |
1286 PrerenderContents* prerender_contents = CreatePrerenderContents( | 1317 PrerenderContents* prerender_contents = CreatePrerenderContents( |
1287 url, referrer, origin, experiment); | 1318 url, referrer, origin, experiment); |
1288 DCHECK(prerender_contents); | 1319 DCHECK(prerender_contents); |
1289 active_prerenders_.push_back( | 1320 active_prerenders_.push_back( |
1290 new PrerenderData(this, prerender_contents, | 1321 new PrerenderData(this, prerender_contents, |
1291 GetExpiryTimeForNewPrerender(origin))); | 1322 GetExpiryTimeForNewPrerender(origin))); |
1292 if (!prerender_contents->Init()) { | 1323 if (!prerender_contents->Init()) { |
1293 DCHECK(active_prerenders_.end() == | 1324 DCHECK(active_prerenders_.end() == |
1294 FindIteratorForPrerenderContents(prerender_contents)); | 1325 FindIteratorForPrerenderContents(prerender_contents)); |
1295 return NULL; | 1326 return NULL; |
1296 } | 1327 } |
1297 | 1328 |
1298 histograms_->RecordPrerenderStarted(origin); | 1329 histograms_->RecordPrerenderStarted(origin); |
1299 DCHECK(!prerender_contents->prerendering_has_started()); | 1330 DCHECK(!prerender_contents->prerendering_has_started()); |
1300 | 1331 |
1301 PrerenderHandle* prerender_handle = | 1332 PrerenderHandle* prerender_handle = |
1302 new PrerenderHandle(active_prerenders_.back()); | 1333 new PrerenderHandle(active_prerenders_.back()); |
1303 SortActivePrerenders(); | 1334 SortActivePrerenders(); |
1304 | 1335 |
1305 last_prerender_start_time_ = GetCurrentTimeTicks(); | 1336 last_prerender_start_time_ = GetCurrentTimeTicks(); |
1306 | 1337 |
1307 gfx::Size contents_size = | 1338 gfx::Size contents_size = |
1308 size.IsEmpty() ? config_.default_tab_bounds.size() : size; | 1339 size.IsEmpty() ? config_.default_tab_bounds.size() : size; |
1309 | 1340 |
| 1341 net::URLRequestContextGetter* request_context = GetURLRequestContext(); |
| 1342 |
1310 prerender_contents->StartPrerendering(process_id, contents_size, | 1343 prerender_contents->StartPrerendering(process_id, contents_size, |
1311 session_storage_namespace); | 1344 session_storage_namespace, |
| 1345 request_context); |
1312 | 1346 |
1313 DCHECK(IsControlGroup(experiment) || | 1347 DCHECK(IsControlGroup(experiment) || |
1314 prerender_contents->prerendering_has_started()); | 1348 prerender_contents->prerendering_has_started() || |
| 1349 (origin == ORIGIN_LOCAL_PREDICTOR && |
| 1350 IsLocalPredictorPrerenderAlwaysControlEnabled())); |
1315 | 1351 |
1316 if (GetMode() == PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP) | 1352 if (GetMode() == PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP) |
1317 histograms_->RecordConcurrency(active_prerenders_.size()); | 1353 histograms_->RecordConcurrency(active_prerenders_.size()); |
1318 | 1354 |
1319 // Query the history to see if the URL being prerendered has ever been | 1355 // Query the history to see if the URL being prerendered has ever been |
1320 // visited before. | 1356 // visited before. |
1321 HistoryService* history_service = HistoryServiceFactory::GetForProfile( | 1357 HistoryService* history_service = HistoryServiceFactory::GetForProfile( |
1322 profile_, Profile::EXPLICIT_ACCESS); | 1358 profile_, Profile::EXPLICIT_ACCESS); |
1323 if (history_service) { | 1359 if (history_service) { |
1324 history_service->QueryURL( | 1360 history_service->QueryURL( |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1824 DCHECK_GE(recent_profile_bytes, 0); | 1860 DCHECK_GE(recent_profile_bytes, 0); |
1825 histograms_->RecordNetworkBytes(used, prerender_bytes, recent_profile_bytes); | 1861 histograms_->RecordNetworkBytes(used, prerender_bytes, recent_profile_bytes); |
1826 } | 1862 } |
1827 | 1863 |
1828 void PrerenderManager::AddProfileNetworkBytesIfEnabled(int64 bytes) { | 1864 void PrerenderManager::AddProfileNetworkBytesIfEnabled(int64 bytes) { |
1829 DCHECK_GE(bytes, 0); | 1865 DCHECK_GE(bytes, 0); |
1830 if (IsEnabled() && ActuallyPrerendering()) | 1866 if (IsEnabled() && ActuallyPrerendering()) |
1831 profile_network_bytes_ += bytes; | 1867 profile_network_bytes_ += bytes; |
1832 } | 1868 } |
1833 | 1869 |
| 1870 void PrerenderManager::OnCookieStoreLoaded() { |
| 1871 cookie_store_loaded_ = true; |
| 1872 if (!on_cookie_store_loaded_cb_for_testing_.is_null()) |
| 1873 on_cookie_store_loaded_cb_for_testing_.Run(); |
| 1874 } |
| 1875 |
| 1876 void PrerenderManager::AddPrerenderProcessHost( |
| 1877 content::RenderProcessHost* process_host) { |
| 1878 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1879 DCHECK(prerender_process_hosts_.find(process_host) == |
| 1880 prerender_process_hosts_.end()); |
| 1881 prerender_process_hosts_.insert(process_host); |
| 1882 process_host->AddObserver(this); |
| 1883 } |
| 1884 |
| 1885 bool PrerenderManager::IsProcessPrerendering( |
| 1886 content::RenderProcessHost* process_host) { |
| 1887 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1888 return (prerender_process_hosts_.find(process_host) != |
| 1889 prerender_process_hosts_.end()); |
| 1890 } |
| 1891 |
| 1892 void PrerenderManager::RenderProcessHostDestroyed( |
| 1893 content::RenderProcessHost* host) { |
| 1894 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1895 prerender_process_hosts_.erase(host); |
| 1896 BrowserThread::PostTask( |
| 1897 BrowserThread::IO, FROM_HERE, |
| 1898 base::Bind(&PrerenderTracker::RemovePrerenderCookieStoreOnIOThread, |
| 1899 base::Unretained(prerender_tracker()), host->GetID(), false)); |
| 1900 } |
| 1901 |
1834 } // namespace prerender | 1902 } // namespace prerender |
OLD | NEW |