Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 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 // Implementation of the MalwareDetails class. | 5 // Implementation of the MalwareDetails class. |
| 6 | 6 |
| 7 #include "chrome/browser/safe_browsing/malware_details.h" | 7 #include "chrome/browser/safe_browsing/malware_details.h" |
| 8 | 8 |
| 9 #include "base/callback.h" | |
| 9 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/md5.h" | |
| 12 #include "chrome/browser/net/chrome_url_request_context.h" | |
| 13 #include "chrome/browser/profiles/profile.h" | |
| 14 #include "chrome/browser/safe_browsing/malware_details_cache.h" | |
| 15 #include "chrome/browser/safe_browsing/report.pb.h" | |
| 10 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 16 #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
| 11 #include "chrome/browser/safe_browsing/report.pb.h" | 17 #include "chrome/common/net/url_request_context_getter.h" |
| 12 #include "chrome/common/safebrowsing_messages.h" | 18 #include "chrome/common/safebrowsing_messages.h" |
| 13 #include "content/browser/browser_thread.h" | 19 #include "content/browser/browser_thread.h" |
| 14 #include "content/browser/renderer_host/render_view_host.h" | 20 #include "content/browser/renderer_host/render_view_host.h" |
| 15 #include "content/browser/tab_contents/navigation_entry.h" | 21 #include "content/browser/tab_contents/navigation_entry.h" |
| 16 #include "content/browser/tab_contents/tab_contents.h" | 22 #include "content/browser/tab_contents/tab_contents.h" |
| 23 #include "net/base/io_buffer.h" | |
| 24 #include "net/disk_cache/disk_cache.h" | |
| 25 #include "net/http/http_cache.h" | |
| 26 #include "net/http/http_response_headers.h" | |
| 27 #include "net/http/http_response_info.h" | |
| 17 | 28 |
| 18 using safe_browsing::ClientMalwareReportRequest; | 29 using safe_browsing::ClientMalwareReportRequest; |
| 19 | 30 |
| 20 // Keep in sync with KMaxNodes in renderer/safe_browsing/malware_dom_details | 31 // Keep in sync with KMaxNodes in renderer/safe_browsing/malware_dom_details |
| 21 static const uint32 kMaxDomNodes = 500; | 32 static const uint32 kMaxDomNodes = 500; |
| 22 | 33 |
| 34 // Only send tiny files for now, a better strategy would use the size | |
| 35 // of the whole report and the user's bandwidth. | |
| 36 static const int kMaxBodySize = 1024; | |
| 37 | |
| 23 // static | 38 // static |
| 24 MalwareDetailsFactory* MalwareDetails::factory_ = NULL; | 39 MalwareDetailsFactory* MalwareDetails::factory_ = NULL; |
| 25 | 40 |
| 26 // The default MalwareDetailsFactory. Global, made a singleton so we | 41 // The default MalwareDetailsFactory. Global, made a singleton so we |
| 27 // don't leak it. | 42 // don't leak it. |
| 28 class MalwareDetailsFactoryImpl | 43 class MalwareDetailsFactoryImpl |
| 29 : public MalwareDetailsFactory { | 44 : public MalwareDetailsFactory { |
| 30 public: | 45 public: |
| 31 MalwareDetails* CreateMalwareDetails( | 46 MalwareDetails* CreateMalwareDetails( |
| 47 SafeBrowsingService* sb_service, | |
| 32 TabContents* tab_contents, | 48 TabContents* tab_contents, |
| 33 const SafeBrowsingService::UnsafeResource& unsafe_resource) { | 49 const SafeBrowsingService::UnsafeResource& unsafe_resource) { |
| 34 return new MalwareDetails(tab_contents, unsafe_resource); | 50 return new MalwareDetails(sb_service, tab_contents, unsafe_resource); |
| 35 } | 51 } |
| 36 | 52 |
| 37 private: | 53 private: |
| 38 friend struct base::DefaultLazyInstanceTraits< | 54 friend struct base::DefaultLazyInstanceTraits< |
| 39 MalwareDetailsFactoryImpl>; | 55 MalwareDetailsFactoryImpl>; |
| 40 | 56 |
| 41 MalwareDetailsFactoryImpl() { } | 57 MalwareDetailsFactoryImpl() { } |
| 42 | 58 |
| 43 DISALLOW_COPY_AND_ASSIGN(MalwareDetailsFactoryImpl); | 59 DISALLOW_COPY_AND_ASSIGN(MalwareDetailsFactoryImpl); |
| 44 }; | 60 }; |
| 45 | 61 |
| 46 static base::LazyInstance<MalwareDetailsFactoryImpl> | 62 static base::LazyInstance<MalwareDetailsFactoryImpl> |
| 47 g_malware_details_factory_impl(base::LINKER_INITIALIZED); | 63 g_malware_details_factory_impl(base::LINKER_INITIALIZED); |
| 48 | 64 |
| 49 // Create a MalwareDetails for the given tab. | 65 // Create a MalwareDetails for the given tab. |
| 50 /* static */ | 66 /* static */ |
| 51 MalwareDetails* MalwareDetails::NewMalwareDetails( | 67 MalwareDetails* MalwareDetails::NewMalwareDetails( |
| 68 SafeBrowsingService* sb_service, | |
| 52 TabContents* tab_contents, | 69 TabContents* tab_contents, |
| 53 const SafeBrowsingService::UnsafeResource& resource) { | 70 const SafeBrowsingService::UnsafeResource& resource) { |
| 54 // Set up the factory if this has not been done already (tests do that | 71 // Set up the factory if this has not been done already (tests do that |
| 55 // before this method is called). | 72 // before this method is called). |
| 56 if (!factory_) | 73 if (!factory_) |
| 57 factory_ = g_malware_details_factory_impl.Pointer(); | 74 factory_ = g_malware_details_factory_impl.Pointer(); |
| 58 return factory_->CreateMalwareDetails(tab_contents, resource); | 75 return factory_->CreateMalwareDetails(sb_service, tab_contents, resource); |
| 59 } | 76 } |
| 60 | 77 |
| 61 // Create a MalwareDetails for the given tab. Runs in the UI thread. | 78 // Create a MalwareDetails for the given tab. Runs in the UI thread. |
| 62 MalwareDetails::MalwareDetails( | 79 MalwareDetails::MalwareDetails( |
| 80 SafeBrowsingService* sb_service, | |
| 63 TabContents* tab_contents, | 81 TabContents* tab_contents, |
| 64 const SafeBrowsingService::UnsafeResource& resource) | 82 const SafeBrowsingService::UnsafeResource& resource) |
| 65 : TabContentsObserver(tab_contents), | 83 : TabContentsObserver(tab_contents), |
| 66 resource_(resource) { | 84 request_context_getter_(tab_contents->profile()->GetRequestContext()), |
| 85 sb_service_(sb_service), | |
| 86 resource_(resource), | |
| 87 cache_collector_(new MalwareDetailsCacheCollector) { | |
| 67 StartCollection(); | 88 StartCollection(); |
| 68 } | 89 } |
| 69 | 90 |
| 70 MalwareDetails::~MalwareDetails() {} | 91 MalwareDetails::~MalwareDetails() { |
| 92 } | |
| 71 | 93 |
| 72 bool MalwareDetails::OnMessageReceived(const IPC::Message& message) { | 94 bool MalwareDetails::OnMessageReceived(const IPC::Message& message) { |
| 73 bool handled = true; | 95 bool handled = true; |
| 74 IPC_BEGIN_MESSAGE_MAP(MalwareDetails, message) | 96 IPC_BEGIN_MESSAGE_MAP(MalwareDetails, message) |
| 75 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_MalwareDOMDetails, | 97 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_MalwareDOMDetails, |
| 76 OnReceivedMalwareDOMDetails) | 98 OnReceivedMalwareDOMDetails) |
| 77 IPC_MESSAGE_UNHANDLED(handled = false) | 99 IPC_MESSAGE_UNHANDLED(handled = false) |
| 78 IPC_END_MESSAGE_MAP() | 100 IPC_END_MESSAGE_MAP() |
| 79 return handled; | 101 return handled; |
| 80 } | 102 } |
| 81 | 103 |
| 82 bool MalwareDetails::IsPublicUrl(const GURL& url) const { | 104 bool MalwareDetails::IsPublicUrl(const GURL& url) const { |
| 83 return url.SchemeIs("http"); // TODO(panayiotis): also skip internal urls. | 105 return url.SchemeIs("http"); // TODO(panayiotis): also skip internal urls. |
| 84 } | 106 } |
| 85 | 107 |
| 86 // Looks for a Resource for the given url in resources_. If found, it | 108 // Looks for a Resource for the given url in resources_. If found, it |
| 87 // updates |resource|. Otherwise, it creates a new message, adds it to | 109 // updates |resource|. Otherwise, it creates a new message, adds it to |
| 88 // resources_ and updates |resource| to point to it. | 110 // resources_ and updates |resource| to point to it. |
| 89 ClientMalwareReportRequest::Resource* MalwareDetails::FindOrCreateResource( | 111 ClientMalwareReportRequest::Resource* MalwareDetails::FindOrCreateResource( |
| 90 const GURL& url) { | 112 const GURL& url) { |
| 91 ResourceMap::iterator it = resources_.find(url.spec()); | 113 safe_browsing::ResourceMap::iterator it = resources_.find(url.spec()); |
| 92 if (it != resources_.end()) { | 114 if (it != resources_.end()) { |
| 93 return it->second.get(); | 115 return it->second.get(); |
| 94 } | 116 } |
| 95 | 117 |
| 96 // Create the resource for |url|. | 118 // Create the resource for |url|. |
| 97 int id = resources_.size(); | 119 int id = resources_.size(); |
| 98 linked_ptr<ClientMalwareReportRequest::Resource> new_resource( | 120 linked_ptr<ClientMalwareReportRequest::Resource> new_resource( |
| 99 new ClientMalwareReportRequest::Resource()); | 121 new ClientMalwareReportRequest::Resource()); |
| 100 new_resource->set_url(url.spec()); | 122 new_resource->set_url(url.spec()); |
| 101 new_resource->set_id(id); | 123 new_resource->set_id(id); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 // of our data structures (eg GetSerializedReport). | 222 // of our data structures (eg GetSerializedReport). |
| 201 BrowserThread::PostTask( | 223 BrowserThread::PostTask( |
| 202 BrowserThread::IO, FROM_HERE, | 224 BrowserThread::IO, FROM_HERE, |
| 203 NewRunnableMethod( | 225 NewRunnableMethod( |
| 204 this, &MalwareDetails::AddDOMDetails, params)); | 226 this, &MalwareDetails::AddDOMDetails, params)); |
| 205 } | 227 } |
| 206 | 228 |
| 207 void MalwareDetails::AddDOMDetails( | 229 void MalwareDetails::AddDOMDetails( |
| 208 const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>& params) { | 230 const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>& params) { |
| 209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 232 DVLOG(1) << "Nodes from the DOM: " << params.size(); | |
| 233 | |
| 234 // If we have already started collecting data from the HTTP cache, don't | |
| 235 // modify our state. | |
| 236 if (cache_collector_->InProgress()) | |
| 237 return; | |
| 238 | |
| 210 // Add the urls from the DOM to |resources_|. The renderer could be | 239 // Add the urls from the DOM to |resources_|. The renderer could be |
| 211 // sending bogus messages, so limit the number of nodes we accept. | 240 // sending bogus messages, so limit the number of nodes we accept. |
| 212 DVLOG(1) << "Nodes from the DOM: " << params.size(); | |
| 213 for (uint32 i = 0; i < params.size() && i < kMaxDomNodes; ++i) { | 241 for (uint32 i = 0; i < params.size() && i < kMaxDomNodes; ++i) { |
| 214 SafeBrowsingHostMsg_MalwareDOMDetails_Node node = params[i]; | 242 SafeBrowsingHostMsg_MalwareDOMDetails_Node node = params[i]; |
| 215 DVLOG(1) << node.url << ", " << node.tag_name << ", " << node.parent; | 243 DVLOG(1) << node.url << ", " << node.tag_name << ", " << node.parent; |
| 216 AddUrl(node.url, node.parent, node.tag_name, &(node.children)); | 244 AddUrl(node.url, node.parent, node.tag_name, &(node.children)); |
| 217 } | 245 } |
| 218 } | 246 } |
| 219 | 247 |
| 220 // Called from the SB Service on the IO thread, after the user has | 248 // Called from the SB Service on the IO thread, after the user has |
| 221 // closed the tab, or clicked proceed or goback. Since the user needs | 249 // closed the tab, or clicked proceed or goback. Since the user needs |
| 222 // to take an action, we expect this to be called after | 250 // to take an action, we expect this to be called after |
| 223 // OnReceivedMalwareDOMDetails in most cases. If not, we don't include | 251 // OnReceivedMalwareDOMDetails in most cases. If not, we don't include |
| 224 // the DOM data in our report. | 252 // the DOM data in our report. |
| 225 const std::string* MalwareDetails::GetSerializedReport() { | 253 void MalwareDetails::FinishCollection() { |
| 226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 227 // The |report_| protocol buffer is now generated: We add all the | 255 |
| 228 // urls in our |resources_| maps. | 256 AddRef(); // Ensures we remain alive during cache collection. |
|
panayiotis
2011/03/29 21:18:17
I was able to get rid of this AddRef. Now the only
| |
| 229 for (ResourceMap::const_iterator it = resources_.begin(); | 257 cache_collector_->StartCacheCollection( |
| 258 request_context_getter_, | |
| 259 &resources_, | |
| 260 NewCallback(this, &MalwareDetails::OnCacheCollectionReady)); | |
| 261 } | |
| 262 | |
| 263 void MalwareDetails::OnCacheCollectionReady(int result) { | |
| 264 DVLOG(1) << "OnCacheCollectionReady."; | |
| 265 // Add all the urls in our |resources_| maps to the |report_| protocol buffer. | |
| 266 for (safe_browsing::ResourceMap::const_iterator it = resources_.begin(); | |
| 230 it != resources_.end(); it++) { | 267 it != resources_.end(); it++) { |
| 231 ClientMalwareReportRequest::Resource* pb_resource = | 268 ClientMalwareReportRequest::Resource* pb_resource = |
| 232 report_->add_resources(); | 269 report_->add_resources(); |
| 233 pb_resource->CopyFrom(*(it->second)); | 270 pb_resource->CopyFrom(*(it->second)); |
| 234 } | 271 } |
| 272 report_->set_complete(result == net::OK); | |
| 235 | 273 |
| 236 scoped_ptr<std::string> request_data(new std::string()); | 274 // Send the report, using the SafeBrowsingService. |
| 237 if (!report_->SerializeToString(request_data.get())) { | 275 std::string serialized; |
| 276 if (!report_->SerializeToString(&serialized)) { | |
| 238 DLOG(ERROR) << "Unable to serialize the malware report."; | 277 DLOG(ERROR) << "Unable to serialize the malware report."; |
| 239 } | 278 } |
| 240 | 279 |
| 241 return request_data.release(); | 280 sb_service_->SendSerializedMalwareDetails(serialized); |
| 281 Release(); | |
| 242 } | 282 } |
| OLD | NEW |