Chromium Code Reviews| Index: chrome/browser/safe_browsing/incident_reporting/script_request_detector.cc |
| diff --git a/chrome/browser/safe_browsing/incident_reporting/script_request_detector.cc b/chrome/browser/safe_browsing/incident_reporting/script_request_detector.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..572b7cd8aedc94d9e9c84cad58819cbfb0e98178 |
| --- /dev/null |
| +++ b/chrome/browser/safe_browsing/incident_reporting/script_request_detector.cc |
| @@ -0,0 +1,176 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
|
grt (UTC plus 2)
2015/01/28 14:49:05
here, too
robertshield
2015/01/28 22:20:32
It's 2015 you say, that's just like your opinion m
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/safe_browsing/incident_reporting/script_request_detector.h" |
| + |
| +#include "base/base64.h" |
| +#include "chrome/browser/profiles/profile.h" |
| +#include "chrome/browser/safe_browsing/incident_reporting/script_request_incident.h" |
| +#include "chrome/common/safe_browsing/csd.pb.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/render_process_host.h" |
| +#include "content/public/browser/resource_request_info.h" |
| +#include "crypto/sha2.h" |
| +#include "net/url_request/url_request.h" |
| +#include "url/gurl.h" |
| + |
| +namespace { |
| +const char* kBase64Hashes[] = { |
|
grt (UTC plus 2)
2015/01/28 14:49:04
hex-encode these (and make it "const char* const k
robertshield
2015/01/28 22:20:32
Done.
|
| + "K0XA2nlMZRlNeJiFbOi9lfWaWvRO+Z9PkzU7qFLAAvs=", |
| + "Bc5b2v8oF/nJOGJqORt2VuPv7Ugf466TT9PSlodTRfA=", |
| + "OmU9cS06xDUQ1wG2u/tJ2hLOCf1IRXZkEv/UfGFHPAs=", |
| + "lY5NZazqluUR2frMzLfNs8uPTfD4cqDFhwKt5B89+vI=", |
| + "K49YOOuHXaAUkJWJBNPlicXXerZIUxj+cTpq/fCzbqg=", |
| + "qRhlTdP13wn25/4hDxE1mlO/tKheI7EMPGSU9QibKRU=", |
| + "WiubRYFcS6X1m1R4IXN5hzfbiJfZdtkhgPxUg3fbF38=", |
| + "1auT3DrSQO53ghJc93+RXFZiF7tOarg4Yp0KvtOPUNs=", |
| + "23NQ01hQLvwAyu+daPS1dysA+X34iZZuNSIXNU2yibM=", |
| + "3PELsymYrEAkFglLUDzip3/eX992SilUvEnWZxGSFt8=", |
| + "mCgmeqnJi6vWZOTWiXBnl4Q3kosbpN9PSckKEhX/bpE=", |
| + "MKVlQa9gnSqEOJjwQalPl705IK2UOgs+Q6ThkZCf3yU=", |
| + "e0hybUDBL6z3n3OExSp6mG6Yh7fgZb0SxieJVoc9Nkc=", |
| + "e1dI3gh+jrrpYajsqRRw629wPde3c0ueHAGAOWRqHu4=", |
| + "HYa4Wg4iQay/ezUmiZhGHp3CWWwz47dj7Sn5SSzsk7U=", |
| + "LvME011LWMcvi7jpdwGoeBtO6hbKhtt2BI7GhBAVPOY=", |
| + "7AYWqtyW5Lv5drRMbhx6VcZvFQAux12+gWt0AOYpjk4=", |
| + "ukvOtVIrCsYTh1bSLYBvd1qdfSQE/UHkOhrTz3b1IUs=", |
| + "qqv9jYpDm5mYrQHsxbtAgHhE5OxElF/issLTh+Eh0B8=", |
| + "eGSDgcqPCJLSlTard//L9LlcwKHX+vJubKDF++FJSn4=", |
| + "kR4ruWsSMsN0q/Frr/pAHCVQPy9uJZUJX37EkVZWvTQ=", |
| + "oa9o+NwtUmro0hPNcwX3PrGLUrFp6mQkLHl2gRGdoHE=", |
| + "jjzmL8vqehoxEadS/T9oynvwItlv1yFi5LkFhZPQ6vs=", |
| + "qxP8KGcmsDWTgrpw2i3MqY4L7tjRk4mbU5/4EoMTlX0=", |
| + "6XogyJgENOk2m5s8GSvg9d/Hf06UG4oK9jW677wYeSY=", |
| + "JBVCdk0prk4bK9WK24V36ubEISaDFz5/4fTc6NHuOKw=", |
| + "u0T+dus3T07SmXCeIH8IMOx76TpZgYI+RQFBjeUydGg=", |
| + "WhgIubjDFl9LlmqBT+vB4EQF9eqpNOuqfpfR8dTTnDA=", |
| + "rJPqDdXbpOkvot0aSUvbVIqwky9tSFQ5MPGMiYfyS5c=", |
| + "kFVN58yPbzql+ZC3Ivjm+TOeti1Hl0I811+JHjK5zFk=", |
| + "37Dgg/3RPwut1gidR5EQulnch9No8VzcZPnd8OjV3QI=", |
| + "OqCTjHx/m5oqh2Bt1XNtpMashAdoukOUJB+cXxuHVII=", |
| + "dl+tybYA8Cg3Pr77NSuVrMNUCSsEcpK7Om5ceLSoh1g=", |
| + "7DPxOIXwHB7uygUtm9NPilRrkTYQZPZkvh30paEijpc=", |
| + "daPTU7BXvpKc9fnBMJUQ7pPATkidSqGNQOWiQtfywnc=", |
| + "IWYz/8P64XqhBvKeL8bMkx5iF/HMAi85gO40SoXIme0=", |
| + "m2LGK8mw+b2TGv3t+2igwhX+NOrEiXOecJPhH0p1vgk=", |
| + "ueRmROp34XQ9ks9sIH6/Rv1PToIXqH09GdTa3nV08RM=", |
| + "iy4w+i7hoY62ALnjwsmkrXADcuqoaNyVQ23fQCZY3uY=", |
| +}; |
| + |
| +Profile* GetProfileForRenderProcessId(int render_process_id) { |
| + // How to get a profile from a RenderProcess id: |
| + // 1) Get the RenderProcessHost |
| + // 2) From 1) Get the BrowserContext |
| + // 3) From 2) Get the Profile. |
| + Profile* profile = nullptr; |
| + content::RenderProcessHost* render_process_host = |
| + content::RenderProcessHost::FromID(render_process_id); |
| + if (render_process_host) { |
| + content::BrowserContext* browser_context = |
| + render_process_host->GetBrowserContext(); |
| + if (browser_context) { |
| + profile = Profile::FromBrowserContext(browser_context); |
| + } |
| + } |
| + |
| + return profile; |
| +} |
| + |
| +} // namespace |
| + |
| +namespace safe_browsing { |
| + |
| +ScriptRequestDetector::ScriptRequestDetector( |
| + IncidentReportingService* incident_reporting_service) |
| + : incident_reporting_service_(incident_reporting_service), |
| + weak_ptr_factory_(this) { |
| + InitializeScriptSet(); |
| +} |
| + |
| +ScriptRequestDetector::~ScriptRequestDetector() { |
| +} |
| + |
| +void ScriptRequestDetector::OnResourceRequest(const net::URLRequest* request) { |
| + // Only look at actual net requests (e.g., not chrome-extensions://id/foo.js). |
| + if (!request->url().SchemeIsHTTPOrHTTPS()) |
| + return; |
| + |
| + const content::ResourceRequestInfo* request_info = |
| + content::ResourceRequestInfo::ForRequest(request); |
| + const content::ResourceType resource_type = request_info->GetResourceType(); |
|
grt (UTC plus 2)
2015/01/28 14:49:05
only used once, remove
robertshield
2015/01/28 22:20:32
Done.
|
| + |
| + if (resource_type == content::RESOURCE_TYPE_SCRIPT) { |
|
grt (UTC plus 2)
2015/01/28 14:49:05
to reduce indentation below, how about:
if (requ
robertshield
2015/01/28 22:20:32
Done.
|
| + VLOG(1) << "Script request: " << request->url().spec(); |
|
grt (UTC plus 2)
2015/01/28 14:49:05
DVLOG
robertshield
2015/01/28 22:20:32
Done.
|
| + |
| + std::string url(request->url().host() + request->url().path()); |
| + std::string raw_hash; |
|
grt (UTC plus 2)
2015/01/28 14:49:05
std::string raw_hash(crypto::kSHA256Length, '\0');
robertshield
2015/01/28 22:20:32
Done.
|
| + raw_hash.resize(crypto::kSHA256Length); |
| + crypto::SHA256HashString(url.c_str(), &raw_hash[0], crypto::kSHA256Length); |
| + |
| + if (script_set_.find(raw_hash) != script_set_.end()) { |
|
grt (UTC plus 2)
2015/01/28 14:49:05
if (script_set_.count(raw_hash)) {
robertshield
2015/01/28 22:20:32
Done.
|
| + VLOG(1) << "Script detector match found."; |
|
grt (UTC plus 2)
2015/01/28 14:49:05
DVLOG
robertshield
2015/01/28 22:20:32
Done.
|
| + |
| + scoped_ptr<ClientIncidentReport_IncidentData_ScriptRequestIncident> |
| + incident_data( |
| + new ClientIncidentReport_IncidentData_ScriptRequestIncident()); |
| + incident_data->set_script_hash(raw_hash); |
| + // TODO(robertshield): Set the domain of the parent frame: |
| + // incident_data->set_inclusion_domain(<something>); |
| + |
| + // This next bit of work needs a profile, so has to happen on the UI |
| + // thread. |
| + int render_frame_id = 0; |
| + int render_process_id = 0; |
| + content::ResourceRequestInfo::GetRenderFrameForRequest( |
| + request, &render_frame_id, &render_process_id); |
| + |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ScriptRequestDetector::ReportIncidentOnUIThread, |
| + weak_ptr_factory_.GetWeakPtr(), render_process_id, |
| + base::Passed(incident_data.Pass()))); |
| + } |
| + } |
| +} |
| + |
| +void ScriptRequestDetector::AddScriptHashForTesting( |
| + const std::string& raw_hash) { |
| + script_set_.insert(raw_hash); |
| +} |
| + |
| +bool ScriptRequestDetector::ContainsScriptHashForTesting( |
| + const std::string& raw_hash) { |
| + return script_set_.find(raw_hash) != script_set_.end(); |
| +} |
| + |
| +bool ScriptRequestDetector::AllowNullProfileForTesting() { |
| + return false; |
| +} |
| + |
| +void ScriptRequestDetector::InitializeScriptSet() { |
| + // Store a hashed set of decoded string hashes. Probably slower than a linear |
| + // search for this size list, but this is only temporary. |
| + for (int i = 0; i < arraysize(kBase64Hashes); ++i) { |
| + std::string raw_hash; |
|
grt (UTC plus 2)
2015/01/28 14:49:05
move this out of the loop (as above)
robertshield
2015/01/28 22:20:32
Done.
|
| + if (base::Base64Decode(kBase64Hashes[i], &raw_hash)) |
| + script_set_.insert(raw_hash); |
| + } |
| +} |
| + |
| +void ScriptRequestDetector::ReportIncidentOnUIThread( |
| + int render_process_id, |
| + scoped_ptr<ClientIncidentReport_IncidentData_ScriptRequestIncident> |
| + incident_data) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + |
| + Profile* profile = GetProfileForRenderProcessId(render_process_id); |
| + if (profile || AllowNullProfileForTesting()) { |
| + AddIncidentCallback incident_callback = |
| + incident_reporting_service_->GetAddIncidentCallback(profile); |
| + incident_callback.Run( |
| + make_scoped_ptr(new ScriptRequestIncident(incident_data.Pass()))); |
| + } |
| +} |
| + |
| +} // namespace safe_browsing |