OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/safe_browsing/client_side_detection_service.h" | 5 #include "chrome/browser/safe_browsing/client_side_detection_service.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/time.h" | 9 #include "base/time.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 scoped_ptr<ClientReportPhishingRequestCallback> callback; | 56 scoped_ptr<ClientReportPhishingRequestCallback> callback; |
57 GURL phishing_url; | 57 GURL phishing_url; |
58 }; | 58 }; |
59 | 59 |
60 ClientSideDetectionService::CacheState::CacheState(bool phish, base::Time time) | 60 ClientSideDetectionService::CacheState::CacheState(bool phish, base::Time time) |
61 : is_phishing(phish), | 61 : is_phishing(phish), |
62 timestamp(time) {} | 62 timestamp(time) {} |
63 | 63 |
64 ClientSideDetectionService::ClientSideDetectionService( | 64 ClientSideDetectionService::ClientSideDetectionService( |
65 net::URLRequestContextGetter* request_context_getter) | 65 net::URLRequestContextGetter* request_context_getter) |
66 : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), | 66 : enabled_(false), |
| 67 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), |
67 request_context_getter_(request_context_getter) { | 68 request_context_getter_(request_context_getter) { |
68 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, | 69 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
69 NotificationService::AllSources()); | 70 NotificationService::AllSources()); |
70 } | 71 } |
71 | 72 |
72 ClientSideDetectionService::~ClientSideDetectionService() { | 73 ClientSideDetectionService::~ClientSideDetectionService() { |
73 method_factory_.RevokeAll(); | 74 method_factory_.RevokeAll(); |
74 STLDeleteContainerPairPointers(client_phishing_reports_.begin(), | 75 STLDeleteContainerPairPointers(client_phishing_reports_.begin(), |
75 client_phishing_reports_.end()); | 76 client_phishing_reports_.end()); |
76 client_phishing_reports_.clear(); | 77 client_phishing_reports_.clear(); |
77 } | 78 } |
78 | 79 |
79 // static | 80 // static |
80 ClientSideDetectionService* ClientSideDetectionService::Create( | 81 ClientSideDetectionService* ClientSideDetectionService::Create( |
81 net::URLRequestContextGetter* request_context_getter) { | 82 net::URLRequestContextGetter* request_context_getter) { |
82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
83 scoped_ptr<ClientSideDetectionService> service( | 84 scoped_ptr<ClientSideDetectionService> service( |
84 new ClientSideDetectionService(request_context_getter)); | 85 new ClientSideDetectionService(request_context_getter)); |
85 if (!service->InitializePrivateNetworks()) { | 86 if (!service->InitializePrivateNetworks()) { |
86 UMA_HISTOGRAM_COUNTS("SBClientPhishing.InitPrivateNetworksFailed", 1); | 87 UMA_HISTOGRAM_COUNTS("SBClientPhishing.InitPrivateNetworksFailed", 1); |
87 return NULL; | 88 return NULL; |
88 } | 89 } |
89 // We fetch the model at every browser restart. In a lot of cases the model | |
90 // will be in the cache so it won't actually be fetched from the network. | |
91 // We delay the first model fetch to avoid slowing down browser startup. | |
92 MessageLoop::current()->PostDelayedTask( | |
93 FROM_HERE, | |
94 service->method_factory_.NewRunnableMethod( | |
95 &ClientSideDetectionService::StartFetchModel), | |
96 kInitialClientModelFetchDelayMs); | |
97 return service.release(); | 90 return service.release(); |
98 } | 91 } |
99 | 92 |
| 93 void ClientSideDetectionService::SetEnabled(bool enabled) { |
| 94 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 95 if (enabled == enabled_) |
| 96 return; |
| 97 enabled_ = enabled; |
| 98 if (enabled_) { |
| 99 // Refresh the model when the service is enabled. This can happen when the |
| 100 // preference is toggled, or early during startup if the preference is |
| 101 // already enabled. In a lot of cases the model will be in the cache so it |
| 102 // won't actually be fetched from the network. |
| 103 // We delay the first model fetch to avoid slowing down browser startup. |
| 104 ScheduleFetchModel(kInitialClientModelFetchDelayMs); |
| 105 } else { |
| 106 // Cancel pending requests. |
| 107 model_fetcher_.reset(); |
| 108 // Invoke pending callbacks with a false verdict. |
| 109 for (std::map<const URLFetcher*, ClientReportInfo*>::iterator it = |
| 110 client_phishing_reports_.begin(); |
| 111 it != client_phishing_reports_.end(); ++it) { |
| 112 ClientReportInfo* info = it->second; |
| 113 if (info->callback.get()) |
| 114 info->callback->Run(info->phishing_url, false); |
| 115 } |
| 116 STLDeleteContainerPairPointers(client_phishing_reports_.begin(), |
| 117 client_phishing_reports_.end()); |
| 118 client_phishing_reports_.clear(); |
| 119 cache_.clear(); |
| 120 } |
| 121 } |
| 122 |
100 void ClientSideDetectionService::SendClientReportPhishingRequest( | 123 void ClientSideDetectionService::SendClientReportPhishingRequest( |
101 ClientPhishingRequest* verdict, | 124 ClientPhishingRequest* verdict, |
102 ClientReportPhishingRequestCallback* callback) { | 125 ClientReportPhishingRequestCallback* callback) { |
103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
104 MessageLoop::current()->PostTask( | 127 MessageLoop::current()->PostTask( |
105 FROM_HERE, | 128 FROM_HERE, |
106 method_factory_.NewRunnableMethod( | 129 method_factory_.NewRunnableMethod( |
107 &ClientSideDetectionService::StartClientReportPhishingRequest, | 130 &ClientSideDetectionService::StartClientReportPhishingRequest, |
108 verdict, callback)); | 131 verdict, callback)); |
109 } | 132 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 process->Send(new SafeBrowsingMsg_SetPhishingModel(model_str_)); | 214 process->Send(new SafeBrowsingMsg_SetPhishingModel(model_str_)); |
192 } | 215 } |
193 | 216 |
194 void ClientSideDetectionService::SendModelToRenderers() { | 217 void ClientSideDetectionService::SendModelToRenderers() { |
195 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); | 218 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); |
196 !i.IsAtEnd(); i.Advance()) { | 219 !i.IsAtEnd(); i.Advance()) { |
197 SendModelToProcess(i.GetCurrentValue()); | 220 SendModelToProcess(i.GetCurrentValue()); |
198 } | 221 } |
199 } | 222 } |
200 | 223 |
| 224 void ClientSideDetectionService::ScheduleFetchModel(int64 delay_ms) { |
| 225 MessageLoop::current()->PostDelayedTask( |
| 226 FROM_HERE, |
| 227 method_factory_.NewRunnableMethod( |
| 228 &ClientSideDetectionService::StartFetchModel), |
| 229 delay_ms); |
| 230 } |
| 231 |
201 void ClientSideDetectionService::StartFetchModel() { | 232 void ClientSideDetectionService::StartFetchModel() { |
202 // Start fetching the model either from the cache or possibly from the | 233 if (enabled_) { |
203 // network if the model isn't in the cache. | 234 // Start fetching the model either from the cache or possibly from the |
204 model_fetcher_.reset(URLFetcher::Create(0 /* ID is not used */, | 235 // network if the model isn't in the cache. |
205 GURL(kClientModelUrl), | 236 model_fetcher_.reset(URLFetcher::Create(0 /* ID is not used */, |
206 URLFetcher::GET, | 237 GURL(kClientModelUrl), |
207 this)); | 238 URLFetcher::GET, |
208 model_fetcher_->set_request_context(request_context_getter_.get()); | 239 this)); |
209 model_fetcher_->Start(); | 240 model_fetcher_->set_request_context(request_context_getter_.get()); |
| 241 model_fetcher_->Start(); |
| 242 } |
210 } | 243 } |
211 | 244 |
212 void ClientSideDetectionService::EndFetchModel(ClientModelStatus status) { | 245 void ClientSideDetectionService::EndFetchModel(ClientModelStatus status) { |
213 UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.ClientModelStatus", | 246 UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.ClientModelStatus", |
214 status, | 247 status, |
215 MODEL_STATUS_MAX); | 248 MODEL_STATUS_MAX); |
216 if (status == MODEL_SUCCESS) { | 249 if (status == MODEL_SUCCESS) { |
217 SetBadSubnets(*model_, &bad_subnets_); | 250 SetBadSubnets(*model_, &bad_subnets_); |
218 SendModelToRenderers(); | 251 SendModelToRenderers(); |
219 } | 252 } |
220 int delay_ms = kClientModelFetchIntervalMs; | 253 int delay_ms = kClientModelFetchIntervalMs; |
221 // If the most recently fetched model had a valid max-age and the model was | 254 // If the most recently fetched model had a valid max-age and the model was |
222 // valid we're scheduling the next model update for after the max-age expired. | 255 // valid we're scheduling the next model update for after the max-age expired. |
223 if (model_max_age_.get() && | 256 if (model_max_age_.get() && |
224 (status == MODEL_SUCCESS || status == MODEL_NOT_CHANGED)) { | 257 (status == MODEL_SUCCESS || status == MODEL_NOT_CHANGED)) { |
225 // We're adding 60s of additional delay to make sure we're past | 258 // We're adding 60s of additional delay to make sure we're past |
226 // the model's age. | 259 // the model's age. |
227 *model_max_age_ += base::TimeDelta::FromMinutes(1); | 260 *model_max_age_ += base::TimeDelta::FromMinutes(1); |
228 delay_ms = model_max_age_->InMilliseconds(); | 261 delay_ms = model_max_age_->InMilliseconds(); |
229 } | 262 } |
230 model_max_age_.reset(); | 263 model_max_age_.reset(); |
231 | 264 |
232 // Schedule the next model reload. | 265 // Schedule the next model reload. |
233 MessageLoop::current()->PostDelayedTask( | 266 ScheduleFetchModel(delay_ms); |
234 FROM_HERE, | |
235 method_factory_.NewRunnableMethod( | |
236 &ClientSideDetectionService::StartFetchModel), | |
237 delay_ms); | |
238 } | 267 } |
239 | 268 |
240 void ClientSideDetectionService::StartClientReportPhishingRequest( | 269 void ClientSideDetectionService::StartClientReportPhishingRequest( |
241 ClientPhishingRequest* verdict, | 270 ClientPhishingRequest* verdict, |
242 ClientReportPhishingRequestCallback* callback) { | 271 ClientReportPhishingRequestCallback* callback) { |
243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
244 scoped_ptr<ClientPhishingRequest> request(verdict); | 273 scoped_ptr<ClientPhishingRequest> request(verdict); |
245 scoped_ptr<ClientReportPhishingRequestCallback> cb(callback); | 274 scoped_ptr<ClientReportPhishingRequestCallback> cb(callback); |
246 | 275 |
| 276 if (!enabled_) { |
| 277 if (cb.get()) |
| 278 cb->Run(GURL(request->url()), false); |
| 279 return; |
| 280 } |
| 281 |
247 std::string request_data; | 282 std::string request_data; |
248 if (!request->SerializeToString(&request_data)) { | 283 if (!request->SerializeToString(&request_data)) { |
249 UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestNotSerialized", 1); | 284 UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestNotSerialized", 1); |
250 VLOG(1) << "Unable to serialize the CSD request. Proto file changed?"; | 285 VLOG(1) << "Unable to serialize the CSD request. Proto file changed?"; |
251 if (cb.get()) { | 286 if (cb.get()) { |
252 cb->Run(GURL(request->url()), false); | 287 cb->Run(GURL(request->url()), false); |
253 } | 288 } |
254 return; | 289 return; |
255 } | 290 } |
256 | 291 |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 } | 515 } |
481 } | 516 } |
482 for (int i = 0; i < model.page_word_size(); ++i) { | 517 for (int i = 0; i < model.page_word_size(); ++i) { |
483 if (model.page_word(i) < 0 || model.page_word(i) > max_index) { | 518 if (model.page_word(i) < 0 || model.page_word(i) > max_index) { |
484 return false; | 519 return false; |
485 } | 520 } |
486 } | 521 } |
487 return true; | 522 return true; |
488 } | 523 } |
489 } // namespace safe_browsing | 524 } // namespace safe_browsing |
OLD | NEW |