Chromium Code Reviews| Index: chrome/browser/prerender/prerender_local_predictor.cc |
| =================================================================== |
| --- chrome/browser/prerender/prerender_local_predictor.cc (revision 220426) |
| +++ chrome/browser/prerender/prerender_local_predictor.cc (working copy) |
| @@ -12,8 +12,11 @@ |
| #include <string> |
| #include <utility> |
| +#include "base/json/json_reader.h" |
| +#include "base/json/json_writer.h" |
| #include "base/metrics/field_trial.h" |
| #include "base/metrics/histogram.h" |
| +#include "base/stl_util.h" |
| #include "base/timer/timer.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/history/history_database.h" |
| @@ -36,14 +39,20 @@ |
| #include "content/public/common/page_transition_types.h" |
| #include "crypto/secure_hash.h" |
| #include "grit/browser_resources.h" |
| +#include "net/base/escape.h" |
| +#include "net/url_request/url_fetcher.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "url/url_canon.h" |
| +using base::DictionaryValue; |
| +using base::ListValue; |
| +using base::Value; |
| using content::BrowserThread; |
| using content::PageTransition; |
| using content::SessionStorageNamespace; |
| using content::WebContents; |
| using history::URLID; |
| +using net::URLFetcher; |
| using predictors::LoggedInPredictorTable; |
| using std::string; |
| using std::vector; |
| @@ -66,23 +75,51 @@ |
| bool url_lookup_success; |
| bool logged_in; |
| bool logged_in_lookup_ok; |
| + bool local_history_based; |
| + bool service_whitelist; |
| + bool service_whitelist_lookup_ok; |
| + bool service_whitelist_reported; |
| double priority; |
| }; |
| // A struct consisting of everything needed for launching a potential prerender |
| // on a navigation: The navigation URL (source) triggering potential prerenders, |
| // and a set of candidate URLs. |
| -struct PrerenderLocalPredictor::LocalPredictorURLLookupInfo { |
| +struct PrerenderLocalPredictor::CandidatePrerenderInfo { |
| LocalPredictorURLInfo source_url_; |
| vector<LocalPredictorURLInfo> candidate_urls_; |
| - explicit LocalPredictorURLLookupInfo(URLID source_id) { |
| + scoped_refptr<SessionStorageNamespace> session_storage_namespace_; |
| + scoped_ptr<gfx::Size> size_; |
| + base::Time start_time_; // used for various time measurements |
| + explicit CandidatePrerenderInfo(URLID source_id) { |
| source_url_.id = source_id; |
| } |
| - void MaybeAddCandidateURL(URLID id, double priority) { |
| - // TODO(tburkard): clean up this code, potentially using a list or a heap |
| + void MaybeAddCandidateURLFromLocalData(URLID id, double priority) { |
| LocalPredictorURLInfo info; |
| info.id = id; |
| + info.local_history_based = true; |
| + info.service_whitelist = false; |
| + info.service_whitelist_lookup_ok = false; |
| + info.service_whitelist_reported = false; |
| info.priority = priority; |
| + MaybeAddCandidateURLInternal(info); |
| + } |
| + void MaybeAddCandidateURLFromService(GURL url, double priority, |
| + bool whitelist, |
| + bool whitelist_lookup_ok) { |
| + LocalPredictorURLInfo info; |
| + info.id = kint64max; |
| + info.url = url; |
| + info.url_lookup_success = true; |
| + info.local_history_based = false; |
| + info.service_whitelist = whitelist; |
| + info.service_whitelist_lookup_ok = whitelist_lookup_ok; |
| + info.service_whitelist_reported = true; |
| + info.priority = priority; |
| + MaybeAddCandidateURLInternal(info); |
| + } |
| + void MaybeAddCandidateURLInternal(const LocalPredictorURLInfo& info) { |
| + // TODO(tburkard): clean up this code, potentially using a list or a heap |
| int insert_pos = candidate_urls_.size(); |
| if (insert_pos < kNumPrerenderCandidates) |
| candidate_urls_.push_back(info); |
| @@ -99,11 +136,17 @@ |
| namespace { |
| +#define TIMING_HISTOGRAM(name, value) \ |
| + UMA_HISTOGRAM_CUSTOM_TIMES(name, value, \ |
| + base::TimeDelta::FromMilliseconds(10), \ |
| + base::TimeDelta::FromSeconds(10), \ |
| + 50); |
| + |
| // Task to lookup the URL for a given URLID. |
| class GetURLForURLIDTask : public history::HistoryDBTask { |
| public: |
| GetURLForURLIDTask( |
| - PrerenderLocalPredictor::LocalPredictorURLLookupInfo* request, |
| + PrerenderLocalPredictor::CandidatePrerenderInfo* request, |
| const base::Closure& callback) |
| : request_(request), |
| callback_(callback), |
| @@ -120,11 +163,8 @@ |
| virtual void DoneRunOnMainThread() OVERRIDE { |
| callback_.Run(); |
| - UMA_HISTOGRAM_CUSTOM_TIMES("Prerender.LocalPredictorURLLookupTime", |
| - base::Time::Now() - start_time_, |
| - base::TimeDelta::FromMilliseconds(10), |
| - base::TimeDelta::FromSeconds(10), |
| - 50); |
| + TIMING_HISTOGRAM("Prerender.LocalPredictorURLLookupTime", |
| + base::Time::Now() - start_time_); |
| } |
| private: |
| @@ -138,7 +178,7 @@ |
| request->url = url_row.url(); |
| } |
| - PrerenderLocalPredictor::LocalPredictorURLLookupInfo* request_; |
| + PrerenderLocalPredictor::CandidatePrerenderInfo* request_; |
| base::Closure callback_; |
| base::Time start_time_; |
| DISALLOW_COPY_AND_ASSIGN(GetURLForURLIDTask); |
| @@ -199,7 +239,8 @@ |
| } |
| bool IsFormSubmit(PageTransition transition) { |
| - return (transition & content::PAGE_TRANSITION_FORM_SUBMIT) != 0; |
| + return PageTransitionCoreTypeIs(transition, |
| + content::PAGE_TRANSITION_FORM_SUBMIT); |
| } |
| bool ShouldExcludeTransitionForPrediction(PageTransition transition) { |
| @@ -271,11 +312,11 @@ |
| void LookupLoggedInStatesOnDBThread( |
| scoped_refptr<LoggedInPredictorTable> logged_in_predictor_table, |
| - PrerenderLocalPredictor::LocalPredictorURLLookupInfo* request_) { |
| + PrerenderLocalPredictor::CandidatePrerenderInfo* request) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| - for (int i = 0; i < static_cast<int>(request_->candidate_urls_.size()); i++) { |
| + for (int i = 0; i < static_cast<int>(request->candidate_urls_.size()); i++) { |
| PrerenderLocalPredictor::LocalPredictorURLInfo* info = |
| - &request_->candidate_urls_[i]; |
| + &request->candidate_urls_[i]; |
| if (info->url_lookup_success) { |
| logged_in_predictor_table->HasUserLoggedIn( |
| info->url, &info->logged_in, &info->logged_in_lookup_ok); |
| @@ -386,6 +427,9 @@ |
| if (p->prerender_handle) |
| p->prerender_handle->OnCancel(); |
| } |
| + STLDeleteContainerPairPointers( |
| + outstanding_prerender_service_requests_.begin(), |
| + outstanding_prerender_service_requests_.end()); |
| } |
| void PrerenderLocalPredictor::Shutdown() { |
| @@ -432,8 +476,8 @@ |
| std::map<URLID, int> next_urls_num_found; |
| int num_occurrences_of_current_visit = 0; |
| base::Time last_visited; |
| - scoped_ptr<LocalPredictorURLLookupInfo> lookup_info( |
| - new LocalPredictorURLLookupInfo(info.url_id)); |
| + scoped_ptr<CandidatePrerenderInfo> lookup_info( |
| + new CandidatePrerenderInfo(info.url_id)); |
| const vector<history::BriefVisitInfo>& visits = *(visit_history_.get()); |
| for (int i = 0; i < static_cast<int>(visits.size()); i++) { |
| if (!ShouldExcludeTransitionForPrediction(visits[i].transition)) { |
| @@ -474,20 +518,15 @@ |
| RecordEvent(EVENT_ADD_VISIT_IDENTIFIED_PRERENDER_CANDIDATE); |
| double priority = static_cast<double>(it->second) / |
| static_cast<double>(num_occurrences_of_current_visit); |
| - lookup_info->MaybeAddCandidateURL(it->first, priority); |
| + lookup_info->MaybeAddCandidateURLFromLocalData(it->first, priority); |
| } |
| } |
| - if (lookup_info->candidate_urls_.size() == 0) { |
| - RecordEvent(EVENT_NO_PRERENDER_CANDIDATES); |
| - return; |
| - } |
| - |
| RecordEvent(EVENT_START_URL_LOOKUP); |
| HistoryService* history = GetHistoryIfExists(); |
| if (history) { |
| RecordEvent(EVENT_GOT_HISTORY_ISSUING_LOOKUP); |
| - LocalPredictorURLLookupInfo* lookup_info_ptr = lookup_info.get(); |
| + CandidatePrerenderInfo* lookup_info_ptr = lookup_info.get(); |
| history->ScheduleDBTask( |
| new GetURLForURLIDTask( |
| lookup_info_ptr, |
| @@ -499,17 +538,20 @@ |
| } |
| void PrerenderLocalPredictor::OnLookupURL( |
| - scoped_ptr<LocalPredictorURLLookupInfo> info) { |
| + scoped_ptr<CandidatePrerenderInfo> info) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| RecordEvent(EVENT_PRERENDER_URL_LOOKUP_RESULT); |
| - DCHECK_GE(static_cast<int>(info->candidate_urls_.size()), 1); |
| - |
| if (!info->source_url_.url_lookup_success) { |
| RecordEvent(EVENT_PRERENDER_URL_LOOKUP_FAILED); |
| return; |
| } |
| - LogCandidateURLStats(info->candidate_urls_[0].url); |
| + if (info->candidate_urls_.size() > 0 && |
| + info->candidate_urls_[0].url_lookup_success) { |
| + LogCandidateURLStats(info->candidate_urls_[0].url); |
| + } |
| WebContents* source_web_contents = NULL; |
| bool multiple_source_web_contents_candidates = false; |
| @@ -540,14 +582,285 @@ |
| if (multiple_source_web_contents_candidates) |
| RecordEvent(EVENT_PRERENDER_URL_LOOKUP_MULTIPLE_SOURCE_WEBCONTENTS_FOUND); |
| - |
| - scoped_refptr<SessionStorageNamespace> session_storage_namespace = |
| + info->session_storage_namespace_ = |
| source_web_contents->GetController().GetDefaultSessionStorageNamespace(); |
| gfx::Rect container_bounds; |
| source_web_contents->GetView()->GetContainerBounds(&container_bounds); |
| - scoped_ptr<gfx::Size> size(new gfx::Size(container_bounds.size())); |
| + info->size_.reset(new gfx::Size(container_bounds.size())); |
| + RecordEvent(EVENT_PRERENDER_URL_LOOKUP_SUCCESS); |
| + |
| + DoPrerenderServiceCheck(info.Pass()); |
| +} |
| + |
| +void PrerenderLocalPredictor::DoPrerenderServiceCheck( |
| + scoped_ptr<CandidatePrerenderInfo> info) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + if (!ShouldQueryPrerenderService(prerender_manager_->profile())) { |
| + RecordEvent(EVENT_PRERENDER_SERVICE_DISABLED); |
| + DoLoggedInLookup(info.Pass()); |
| + return; |
| + } |
| + /* |
| + Create a JSON request. |
| + Here is a sample request: |
| + { "prerender_request": { |
| + "version": 1, |
| + "behavior_id": 6, |
| + "hint_request": { |
| + "browse_history": [ |
| + { "url": "http://www.cnn.com/" |
| + } |
| + ] |
| + }, |
| + "candidate_check_request": { |
| + "candidates": [ |
| + { "url": "http://www.cnn.com/sports/" |
| + }, |
| + { "url": "http://www.cnn.com/politics/" |
| + } |
| + ] |
| + } |
| + } |
| + } |
| + */ |
| + DictionaryValue json_data; |
| + DictionaryValue* req = new DictionaryValue(); |
| + req->SetInteger("version", 1); |
| + req->SetInteger("behavior_id", GetPrerenderServiceBehaviorID()); |
| + if (info->source_url_.url_lookup_success) { |
| + ListValue* browse_history = new ListValue(); |
| + DictionaryValue* browse_item = new DictionaryValue(); |
| + browse_item->SetString("url", info->source_url_.url.spec()); |
| + browse_history->Append(browse_item); |
| + DictionaryValue* hint_request = new DictionaryValue(); |
| + hint_request->Set("browse_history", browse_history); |
| + req->Set("hint_request", hint_request); |
| + } |
| + int num_candidate_urls = 0; |
| + for (int i = 0; i < static_cast<int>(info->candidate_urls_.size()); i++) { |
| + if (info->candidate_urls_[i].url_lookup_success) |
| + num_candidate_urls++; |
| + } |
| + if (num_candidate_urls > 0) { |
| + ListValue* candidates = new ListValue(); |
| + DictionaryValue* candidate; |
| + for (int i = 0; i < static_cast<int>(info->candidate_urls_.size()); i++) { |
| + if (info->candidate_urls_[i].url_lookup_success) { |
| + candidate = new DictionaryValue(); |
| + candidate->SetString("url", info->candidate_urls_[i].url.spec()); |
| + candidates->Append(candidate); |
| + } |
| + } |
| + DictionaryValue* candidate_check_request = new DictionaryValue(); |
| + candidate_check_request->Set("candidates", candidates); |
| + req->Set("candidate_check_request", candidate_check_request); |
| + } |
| + json_data.Set("prerender_request", req); |
| + string request_string; |
| + base::JSONWriter::Write(&json_data, &request_string); |
| + GURL fetch_url(GetPrerenderServiceURLPrefix() + |
| + net::EscapeQueryParamValue(request_string, false)); |
| + net::URLFetcher* fetcher = net::URLFetcher::Create( |
| + 0, |
| + fetch_url, |
| + URLFetcher::GET, this); |
| + fetcher->SetRequestContext( |
| + prerender_manager_->profile()->GetRequestContext()); |
| + fetcher->AddExtraRequestHeader("Pragma: no-cache"); |
| + info->start_time_ = base::Time::Now(); |
| + outstanding_prerender_service_requests_.insert( |
| + std::make_pair(fetcher, info.release())); |
| + base::MessageLoop::current()->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&PrerenderLocalPredictor::MaybeCancelURLFetcher, |
| + weak_factory_.GetWeakPtr(), fetcher), |
| + base::TimeDelta::FromMilliseconds(GetPrerenderServiceFetchTimeoutMs())); |
| + RecordEvent(EVENT_PRERENDER_SERVICE_ISSUED_LOOKUP); |
| + fetcher->Start(); |
| +} |
| + |
| +void PrerenderLocalPredictor::MaybeCancelURLFetcher(net::URLFetcher* fetcher) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + OutstandingFetchers::iterator it = |
| + outstanding_prerender_service_requests_.find(fetcher); |
| + if (it == outstanding_prerender_service_requests_.end()) |
| + return; |
| + delete it->first; |
| + scoped_ptr<CandidatePrerenderInfo> info(it->second); |
| + outstanding_prerender_service_requests_.erase(it); |
| + RecordEvent(EVENT_PRERENDER_SERVICE_LOOKUP_TIMED_OUT); |
| + DoLoggedInLookup(info.Pass()); |
| +} |
| + |
| +void PrerenderLocalPredictor::OnURLFetchComplete( |
| + const net::URLFetcher* source) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + RecordEvent(EVENT_PRERENDER_SERVICE_RECEIVED_RESULT); |
| + net::URLFetcher* fetcher = const_cast<net::URLFetcher*>(source); |
| + OutstandingFetchers::iterator it = |
| + outstanding_prerender_service_requests_.find(fetcher); |
| + if (it == outstanding_prerender_service_requests_.end()) { |
| + RecordEvent(EVENT_PRERENDER_SERVICE_NO_RECORD_FOR_RESULT); |
| + return; |
| + } |
| + scoped_ptr<CandidatePrerenderInfo> info(it->second); |
| + outstanding_prerender_service_requests_.erase(it); |
| + TIMING_HISTOGRAM("Prerender.LocalPredictorServiceLookupTime", |
| + base::Time::Now() - info->start_time_); |
| + /* |
| + Read and process the response to our request. |
| + Here is a sample response to illustrate the format. |
| + { |
| + "prerender_response": { |
| + "behavior_id": 6, |
| + "hint_response": { |
| + "hinting_timed_out": 0, |
| + "candidates": [ |
| + { "url": "http://www.cnn.com/story-1", |
| + "in_index": 1, |
| + "likelihood": 0.60, |
| + "in_index_timed_out": 0 |
| + }, |
| + { "url": "http://www.cnn.com/story-2", |
| + "in_index": 1, |
| + "likelihood": 0.30, |
| + "in_index_timed_out": 0 |
| + } |
| + ] |
| + }, |
| + "candidate_check_response": { |
| + "candidates": [ |
| + { "url": "http://www.cnn.com/sports/", |
| + "in_index": 1, |
| + "in_index_timed_out": 0 |
| + }, |
| + { "url": "http://www.cnn.com/politics/", |
| + "in_index": 0, |
| + "in_index_timed_out": "1" |
| + } |
| + ] |
| + } |
| + } |
| + } |
| + */ |
| + string result; |
| + fetcher->GetResponseAsString(&result); |
| + scoped_ptr<Value> root; |
| + root.reset(base::JSONReader::Read(result)); |
| + DictionaryValue* dict = NULL; |
| + ListValue* list = NULL; |
| + bool hinting_timed_out = false; |
| + bool hinting_url_lookup_timed_out = false; |
| + bool candidate_url_lookup_timed_out = false; |
| + if (!root.get() || !root->IsType(Value::TYPE_DICTIONARY)) { |
| + RecordEvent(EVENT_PRERENDER_SERVICE_PARSE_ERROR_INCORRECT_JSON); |
| + goto error; |
| + } |
| + dict = static_cast<DictionaryValue*>(root.get()); |
| + int int_value; |
| + if (!dict->GetInteger("prerender_response.behavior_id", &int_value) || |
| + int_value != GetPrerenderServiceBehaviorID()) { |
| + goto error; |
| + } |
| + if (!dict->GetList("prerender_response.candidate_check_response.candidates", |
| + &list)) { |
| + if (info->candidate_urls_.size() > 0) |
| + goto error; |
| + } else { |
| + for (int i = 0; i < static_cast<int>(list->GetSize()); i++) { |
|
jam
2013/08/30 20:34:30
nit: instead of casting, just use "size_t i", also
tburkard
2013/08/30 20:59:01
Done.
|
| + DictionaryValue* d; |
| + if (!list->GetDictionary(i, &d)) |
| + goto error; |
| + string url_string; |
| + if (!d->GetString("url", &url_string) || !GURL(url_string).is_valid()) { |
| + goto error; |
| + } |
| + GURL url(url_string); |
| + int in_index_timed_out = 0; |
| + int in_index = 0; |
| + if ((!d->GetInteger("in_index_timed_out", &in_index_timed_out) || |
| + in_index_timed_out != 1) && |
| + !d->GetInteger("in_index", &in_index)) { |
| + goto error; |
| + } |
| + if (in_index < 0 || in_index > 1 || |
| + in_index_timed_out < 0 || in_index_timed_out > 1) { |
| + goto error; |
| + } |
| + for (int j = 0; j < static_cast<int>(info->candidate_urls_.size()); j++) { |
| + if (info->candidate_urls_[j].url == url) { |
| + info->candidate_urls_[j].service_whitelist_reported = true; |
| + info->candidate_urls_[j].service_whitelist = (in_index == 1); |
| + info->candidate_urls_[j].service_whitelist_lookup_ok = |
| + ((1 - in_index_timed_out) == 1); |
| + } |
| + } |
| + } |
| + for (int i = 0; i < static_cast<int>(info->candidate_urls_.size()); i++) { |
| + if (!info->candidate_urls_[i].service_whitelist_reported) |
| + goto error; |
| + } |
| + } |
| + |
| + list = NULL; |
| + if (dict->GetInteger("prerender_response.hint_response.hinting_timed_out", |
| + &int_value) && |
| + int_value == 1) { |
| + hinting_timed_out = true; |
| + } else if (!dict->GetList("prerender_response.hint_response.candidates", |
| + &list)) { |
| + goto error; |
| + } else { |
| + for (int i = 0; i < static_cast<int>(list->GetSize()); i++) { |
| + DictionaryValue* d; |
| + if (!list->GetDictionary(i, &d)) |
| + goto error; |
| + string url; |
| + double priority; |
| + if (!d->GetString("url", &url) || !d->GetDouble("likelihood", &priority) |
| + || !GURL(url).is_valid()) { |
| + goto error; |
| + } |
| + int in_index_timed_out = 0; |
| + int in_index = 0; |
| + if ((!d->GetInteger("in_index_timed_out", &in_index_timed_out) || |
| + in_index_timed_out != 1) && |
| + !d->GetInteger("in_index", &in_index)) { |
| + goto error; |
| + } |
| + if (priority < 0.0 || priority > 1.0 || in_index < 0 || in_index > 1 || |
| + in_index_timed_out < 0 || in_index_timed_out > 1) { |
| + goto error; |
| + } |
| + info->MaybeAddCandidateURLFromService(GURL(url), |
| + priority, |
| + in_index == 1, |
| + (1 - in_index_timed_out) == 1); |
| + } |
| + } |
| + |
| + // We finished parsing the result, and found no errors. |
| + RecordEvent(EVENT_PRERENDER_SERVICE_PARSED_CORRECTLY); |
| + if (hinting_timed_out) |
| + RecordEvent(EVENT_PRERENDER_SERVICE_HINTING_TIMED_OUT); |
| + if (hinting_url_lookup_timed_out) |
| + RecordEvent(EVENT_PRERENDER_SERVICE_HINTING_URL_LOOKUP_TIMED_OUT); |
| + if (candidate_url_lookup_timed_out) |
| + RecordEvent(EVENT_PRERENDER_SERVICE_CANDIDATE_URL_LOOKUP_TIMED_OUT); |
| + DoLoggedInLookup(info.Pass()); |
| + return; |
| + |
| + error: |
| + // Parser errors, record this, and continue with LoggedIn Lookup. |
| + RecordEvent(EVENT_PRERENDER_SERVICE_PARSE_ERROR); |
| + DoLoggedInLookup(info.Pass()); |
| +} |
| + |
| +void PrerenderLocalPredictor:: DoLoggedInLookup( |
| + scoped_ptr<CandidatePrerenderInfo> info) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| scoped_refptr<LoggedInPredictorTable> logged_in_table = |
| prerender_manager_->logged_in_predictor_table(); |
| @@ -558,7 +871,9 @@ |
| RecordEvent(EVENT_PRERENDER_URL_LOOKUP_ISSUING_LOGGED_IN_LOOKUP); |
| - LocalPredictorURLLookupInfo* info_ptr = info.get(); |
| + info->start_time_ = base::Time::Now(); |
| + |
| + CandidatePrerenderInfo* info_ptr = info.get(); |
| BrowserThread::PostTaskAndReply( |
| BrowserThread::DB, FROM_HERE, |
| base::Bind(&LookupLoggedInStatesOnDBThread, |
| @@ -566,8 +881,6 @@ |
| info_ptr), |
| base::Bind(&PrerenderLocalPredictor::ContinuePrerenderCheck, |
| weak_factory_.GetWeakPtr(), |
| - session_storage_namespace, |
| - base::Passed(&size), |
| base::Passed(&info))); |
| } |
| @@ -711,10 +1024,15 @@ |
| } |
| void PrerenderLocalPredictor::ContinuePrerenderCheck( |
| - scoped_refptr<SessionStorageNamespace> session_storage_namespace, |
| - scoped_ptr<gfx::Size> size, |
| - scoped_ptr<LocalPredictorURLLookupInfo> info) { |
| + scoped_ptr<CandidatePrerenderInfo> info) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + TIMING_HISTOGRAM("Prerender.LocalPredictorLoggedInLookupTime", |
| + base::Time::Now() - info->start_time_); |
| RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_STARTED); |
| + if (info->candidate_urls_.size() == 0) { |
| + RecordEvent(EVENT_NO_PRERENDER_CANDIDATES); |
| + return; |
| + } |
| scoped_ptr<LocalPredictorURLInfo> url_info; |
| scoped_refptr<SafeBrowsingDatabaseManager> sb_db_manager = |
| g_browser_process->safe_browsing_service()->database_manager(); |
| @@ -779,6 +1097,11 @@ |
| RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_ON_SIDE_EFFECT_FREE_WHITELIST); |
| break; |
| } |
| + if (!SkipLocalPredictorServiceWhitelist() && |
| + url_info->service_whitelist && url_info->service_whitelist_lookup_ok) { |
| + RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_ON_SERVICE_WHITELIST); |
| + break; |
| + } |
| if (!SkipLocalPredictorLoggedIn() && |
| !url_info->logged_in && url_info->logged_in_lookup_ok) { |
| RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_NOT_LOGGED_IN); |
| @@ -796,26 +1119,25 @@ |
| RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_ISSUING_PRERENDER); |
| DCHECK(prerender_properties != NULL); |
| if (IsLocalPredictorPrerenderLaunchEnabled()) { |
| - IssuePrerender(session_storage_namespace, size.Pass(), |
| - url_info.Pass(), prerender_properties); |
| + IssuePrerender(info.Pass(), url_info.Pass(), prerender_properties); |
| } |
| } |
| void PrerenderLocalPredictor::IssuePrerender( |
| - scoped_refptr<SessionStorageNamespace> session_storage_namespace, |
| - scoped_ptr<gfx::Size> size, |
| - scoped_ptr<LocalPredictorURLInfo> info, |
| + scoped_ptr<CandidatePrerenderInfo> info, |
| + scoped_ptr<LocalPredictorURLInfo> url_info, |
| PrerenderProperties* prerender_properties) { |
| - URLID url_id = info->id; |
| - const GURL& url = info->url; |
| - double priority = info->priority; |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + URLID url_id = url_info->id; |
| + const GURL& url = url_info->url; |
| + double priority = url_info->priority; |
| base::Time current_time = GetCurrentTime(); |
| RecordEvent(EVENT_ISSUING_PRERENDER); |
| // Issue the prerender and obtain a new handle. |
| scoped_ptr<prerender::PrerenderHandle> new_prerender_handle( |
| prerender_manager_->AddPrerenderFromLocalPredictor( |
| - url, session_storage_namespace.get(), *size)); |
| + url, info->session_storage_namespace_.get(), *(info->size_))); |
| // Check if this is a duplicate of an existing prerender. If yes, clean up |
| // the new handle. |