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/file_path.h" | 8 #include "base/file_path.h" |
9 #include "base/file_util_proxy.h" | 9 #include "base/file_util_proxy.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/platform_file.h" | 13 #include "base/platform_file.h" |
14 #include "base/scoped_ptr.h" | 14 #include "base/scoped_ptr.h" |
15 #include "base/stl_util-inl.h" | 15 #include "base/stl_util-inl.h" |
16 #include "base/task.h" | 16 #include "base/task.h" |
17 #include "base/time.h" | 17 #include "base/time.h" |
18 #include "chrome/browser/browser_thread.h" | 18 #include "chrome/browser/browser_thread.h" |
| 19 #include "chrome/browser/renderer_host/render_view_host.h" |
19 #include "chrome/browser/safe_browsing/csd.pb.h" | 20 #include "chrome/browser/safe_browsing/csd.pb.h" |
| 21 #include "chrome/browser/tab_contents/provisional_load_details.h" |
| 22 #include "chrome/browser/tab_contents/tab_contents.h" |
20 #include "chrome/common/net/http_return.h" | 23 #include "chrome/common/net/http_return.h" |
21 #include "chrome/common/net/url_fetcher.h" | 24 #include "chrome/common/net/url_fetcher.h" |
22 #include "chrome/common/net/url_request_context_getter.h" | 25 #include "chrome/common/net/url_request_context_getter.h" |
| 26 #include "chrome/common/notification_service.h" |
| 27 #include "chrome/common/notification_type.h" |
| 28 #include "chrome/common/render_messages.h" |
23 #include "googleurl/src/gurl.h" | 29 #include "googleurl/src/gurl.h" |
24 #include "net/base/load_flags.h" | 30 #include "net/base/load_flags.h" |
25 #include "net/url_request/url_request_status.h" | 31 #include "net/url_request/url_request_status.h" |
26 | 32 |
27 namespace safe_browsing { | 33 namespace safe_browsing { |
28 | 34 |
29 const int ClientSideDetectionService::kMaxReportsPerDay = 3; | 35 const int ClientSideDetectionService::kMaxReportsPerDay = 3; |
30 | 36 |
31 const char ClientSideDetectionService::kClientReportPhishingUrl[] = | 37 const char ClientSideDetectionService::kClientReportPhishingUrl[] = |
32 "https://sb-ssl.google.com/safebrowsing/clientreport/phishing"; | 38 "https://sb-ssl.google.com/safebrowsing/clientreport/phishing"; |
33 const char ClientSideDetectionService::kClientModelUrl[] = | 39 const char ClientSideDetectionService::kClientModelUrl[] = |
34 "https://ssl.gstatic.com/safebrowsing/csd/client_model_v0.pb"; | 40 "https://ssl.gstatic.com/safebrowsing/csd/client_model_v0.pb"; |
35 | 41 |
36 struct ClientSideDetectionService::ClientReportInfo { | 42 struct ClientSideDetectionService::ClientReportInfo { |
37 scoped_ptr<ClientReportPhishingRequestCallback> callback; | 43 scoped_ptr<ClientReportPhishingRequestCallback> callback; |
38 GURL phishing_url; | 44 GURL phishing_url; |
39 }; | 45 }; |
40 | 46 |
| 47 // ShouldClassifyUrlRequest tracks the pre-classification checks for a |
| 48 // toplevel URL that has started loading into a renderer. When these |
| 49 // checks are complete, the renderer is notified if it should run |
| 50 // client-side phishing classification, then the ShouldClassifyUrlRequest |
| 51 // deletes itself. |
| 52 class ClientSideDetectionService::ShouldClassifyUrlRequest |
| 53 : public NotificationObserver { |
| 54 public: |
| 55 ShouldClassifyUrlRequest(const GURL& url, TabContents* tab_contents) |
| 56 : url_(url), |
| 57 tab_contents_(tab_contents), |
| 58 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { |
| 59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 60 registrar_.Add(this, |
| 61 NotificationType::TAB_CONTENTS_DESTROYED, |
| 62 Source<TabContents>(tab_contents)); |
| 63 } |
| 64 |
| 65 virtual void Observe(NotificationType type, |
| 66 const NotificationSource& source, |
| 67 const NotificationDetails& details) { |
| 68 switch (type.value) { |
| 69 case NotificationType::TAB_CONTENTS_DESTROYED: |
| 70 Cancel(); |
| 71 break; |
| 72 default: |
| 73 NOTREACHED(); |
| 74 }; |
| 75 } |
| 76 |
| 77 void Start() { |
| 78 // TODO(bryner): add pre-classification checks here. |
| 79 // For now we just call Finish() asynchronously for consistency, |
| 80 // since the pre-classification checks are asynchronous. |
| 81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 82 BrowserThread::PostTask(BrowserThread::UI, |
| 83 FROM_HERE, |
| 84 method_factory_.NewRunnableMethod( |
| 85 &ShouldClassifyUrlRequest::Finish)); |
| 86 } |
| 87 |
| 88 private: |
| 89 // This object always deletes itself, so make the destructor private. |
| 90 virtual ~ShouldClassifyUrlRequest() {} |
| 91 |
| 92 void Cancel() { |
| 93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 94 tab_contents_ = NULL; |
| 95 Finish(); |
| 96 } |
| 97 |
| 98 void Finish() { |
| 99 if (tab_contents_) { |
| 100 RenderViewHost* rvh = tab_contents_->render_view_host(); |
| 101 rvh->Send(new ViewMsg_StartPhishingDetection(rvh->routing_id(), url_)); |
| 102 } |
| 103 delete this; |
| 104 } |
| 105 |
| 106 GURL url_; |
| 107 TabContents* tab_contents_; |
| 108 NotificationRegistrar registrar_; |
| 109 ScopedRunnableMethodFactory<ShouldClassifyUrlRequest> method_factory_; |
| 110 |
| 111 DISALLOW_COPY_AND_ASSIGN(ShouldClassifyUrlRequest); |
| 112 }; |
| 113 |
41 ClientSideDetectionService::ClientSideDetectionService( | 114 ClientSideDetectionService::ClientSideDetectionService( |
42 const FilePath& model_path, | 115 const FilePath& model_path, |
43 URLRequestContextGetter* request_context_getter) | 116 URLRequestContextGetter* request_context_getter) |
44 : model_path_(model_path), | 117 : model_path_(model_path), |
45 model_status_(UNKNOWN_STATUS), | 118 model_status_(UNKNOWN_STATUS), |
46 model_file_(base::kInvalidPlatformFileValue), | 119 model_file_(base::kInvalidPlatformFileValue), |
47 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), | 120 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), |
48 ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), | 121 ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), |
49 request_context_getter_(request_context_getter) { | 122 request_context_getter_(request_context_getter) { |
| 123 // Register to find out when pages begin loading into a renderer. |
| 124 // When this happens, we'll start our pre-classificaton checks. |
| 125 registrar_.Add(this, |
| 126 NotificationType::FRAME_PROVISIONAL_LOAD_COMMITTED, |
| 127 NotificationService::AllSources()); |
50 } | 128 } |
51 | 129 |
52 ClientSideDetectionService::~ClientSideDetectionService() { | 130 ClientSideDetectionService::~ClientSideDetectionService() { |
53 method_factory_.RevokeAll(); | 131 method_factory_.RevokeAll(); |
54 STLDeleteContainerPairPointers(client_phishing_reports_.begin(), | 132 STLDeleteContainerPairPointers(client_phishing_reports_.begin(), |
55 client_phishing_reports_.end()); | 133 client_phishing_reports_.end()); |
56 client_phishing_reports_.clear(); | 134 client_phishing_reports_.clear(); |
57 STLDeleteElements(&open_callbacks_); | 135 STLDeleteElements(&open_callbacks_); |
58 CloseModelFile(); | 136 CloseModelFile(); |
59 } | 137 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 if (source == model_fetcher_.get()) { | 189 if (source == model_fetcher_.get()) { |
112 HandleModelResponse(source, url, status, response_code, cookies, data); | 190 HandleModelResponse(source, url, status, response_code, cookies, data); |
113 } else if (client_phishing_reports_.find(source) != | 191 } else if (client_phishing_reports_.find(source) != |
114 client_phishing_reports_.end()) { | 192 client_phishing_reports_.end()) { |
115 HandlePhishingVerdict(source, url, status, response_code, cookies, data); | 193 HandlePhishingVerdict(source, url, status, response_code, cookies, data); |
116 } else { | 194 } else { |
117 NOTREACHED(); | 195 NOTREACHED(); |
118 } | 196 } |
119 } | 197 } |
120 | 198 |
| 199 void ClientSideDetectionService::Observe(NotificationType type, |
| 200 const NotificationSource& source, |
| 201 const NotificationDetails& details) { |
| 202 switch (type.value) { |
| 203 case NotificationType::FRAME_PROVISIONAL_LOAD_COMMITTED: { |
| 204 // Check whether the load should trigger a phishing classification. |
| 205 // This is true if the navigation happened in the main frame and was |
| 206 // not an in-page navigation. |
| 207 ProvisionalLoadDetails* load_details = |
| 208 Details<ProvisionalLoadDetails>(details).ptr(); |
| 209 |
| 210 if (load_details->main_frame() && !load_details->in_page_navigation()) { |
| 211 NavigationController* controller = |
| 212 Source<NavigationController>(source).ptr(); |
| 213 ShouldClassifyUrlRequest* request = |
| 214 new ShouldClassifyUrlRequest(load_details->url(), |
| 215 controller->tab_contents()); |
| 216 request->Start(); // the request will delete itself on completion |
| 217 } |
| 218 break; |
| 219 } |
| 220 default: |
| 221 NOTREACHED(); |
| 222 }; |
| 223 } |
| 224 |
121 void ClientSideDetectionService::SetModelStatus(ModelStatus status) { | 225 void ClientSideDetectionService::SetModelStatus(ModelStatus status) { |
122 DCHECK_NE(READY_STATUS, model_status_); | 226 DCHECK_NE(READY_STATUS, model_status_); |
123 model_status_ = status; | 227 model_status_ = status; |
124 if (READY_STATUS == status || ERROR_STATUS == status) { | 228 if (READY_STATUS == status || ERROR_STATUS == status) { |
125 for (size_t i = 0; i < open_callbacks_.size(); ++i) { | 229 for (size_t i = 0; i < open_callbacks_.size(); ++i) { |
126 open_callbacks_[i]->Run(model_file_); | 230 open_callbacks_[i]->Run(model_file_); |
127 } | 231 } |
128 STLDeleteElements(&open_callbacks_); | 232 STLDeleteElements(&open_callbacks_); |
129 } else { | 233 } else { |
130 NOTREACHED(); | 234 NOTREACHED(); |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 while (!phishing_report_times_.empty() && | 430 while (!phishing_report_times_.empty() && |
327 phishing_report_times_.front() < cutoff) { | 431 phishing_report_times_.front() < cutoff) { |
328 phishing_report_times_.pop(); | 432 phishing_report_times_.pop(); |
329 } | 433 } |
330 | 434 |
331 // Return the number of elements that are above the cutoff. | 435 // Return the number of elements that are above the cutoff. |
332 return phishing_report_times_.size(); | 436 return phishing_report_times_.size(); |
333 } | 437 } |
334 | 438 |
335 } // namespace safe_browsing | 439 } // namespace safe_browsing |
OLD | NEW |