Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/safe_browsing/off_domain_inclusion_detector.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/metrics/histogram.h" | |
| 10 #include "content/public/browser/resource_request_info.h" | |
| 11 #include "net/url_request/url_request.h" | |
| 12 #include "url/gurl.h" | |
| 13 | |
| 14 namespace safe_browsing { | |
|
mattm
2014/09/09 21:20:16
Can you add tests? I found one example of testing
| |
| 15 | |
| 16 void OffDomainInclusionDetector::OnResourceRequest( | |
| 17 const net::URLRequest* request, | |
| 18 content::ResourceType resource_type) { | |
| 19 // Only look at actual net requests (e.g., not chrome-extensions://id/foo.js). | |
| 20 if (!request->url().SchemeIsHTTPOrHTTPS()) | |
| 21 return; | |
| 22 | |
| 23 const content::ResourceRequestInfo* request_info = | |
| 24 content::ResourceRequestInfo::ForRequest(request); | |
| 25 | |
| 26 // Make an explicit decision about every resource type (causing compiler | |
| 27 // errors should a new resource type be added). | |
| 28 switch (resource_type) { | |
| 29 case content::RESOURCE_TYPE_MAIN_FRAME: | |
| 30 // Analyze inclusions in the main frame, not the main frame itself. | |
| 31 return; | |
| 32 case content::RESOURCE_TYPE_SUB_FRAME: | |
| 33 DCHECK(!request_info->IsMainFrame()); | |
| 34 // Only analyze top-level frames within the main frame. | |
| 35 if (!request_info->ParentIsMainFrame()) | |
| 36 return; | |
| 37 break; | |
| 38 case content::RESOURCE_TYPE_STYLESHEET: | |
| 39 case content::RESOURCE_TYPE_SCRIPT: | |
| 40 case content::RESOURCE_TYPE_IMAGE: | |
| 41 case content::RESOURCE_TYPE_FONT_RESOURCE: | |
| 42 case content::RESOURCE_TYPE_SUB_RESOURCE: | |
| 43 case content::RESOURCE_TYPE_OBJECT: | |
| 44 case content::RESOURCE_TYPE_MEDIA: | |
| 45 case content::RESOURCE_TYPE_XHR: | |
| 46 // Types above are to be analyzed for off-domain inclusion if they are | |
| 47 // loaded as part of the main frame. | |
| 48 if (!request_info->IsMainFrame()) | |
| 49 return; | |
| 50 break; | |
| 51 case content::RESOURCE_TYPE_WORKER: | |
| 52 case content::RESOURCE_TYPE_SHARED_WORKER: | |
| 53 case content::RESOURCE_TYPE_PREFETCH: | |
| 54 case content::RESOURCE_TYPE_FAVICON: | |
| 55 case content::RESOURCE_TYPE_PING: | |
| 56 case content::RESOURCE_TYPE_SERVICE_WORKER: | |
| 57 // Types above are not to be analyzed for off-domain inclusion. | |
| 58 return; | |
| 59 case content::RESOURCE_TYPE_LAST_TYPE: | |
| 60 NOTREACHED(); | |
| 61 return; | |
| 62 } | |
| 63 | |
| 64 // Record the type of request analyzed to be able to do ratio analysis w.r.t | |
| 65 // other histograms below. | |
| 66 UMA_HISTOGRAM_ENUMERATION("SBOffDomainInclusion.RequestAnalyzed", | |
| 67 resource_type, | |
| 68 content::RESOURCE_TYPE_LAST_TYPE); | |
| 69 | |
| 70 const GURL main_frame_url(request->referrer()); | |
| 71 if (!main_frame_url.is_valid()) { | |
| 72 if (main_frame_url.is_empty()) { | |
| 73 // This can happen in a few scenarios where the referer is dropped (e.g., | |
| 74 // HTTPS => HTTP requests). Consider adding the original referer to | |
| 75 // ResourceRequestInfo if that's an issue. | |
|
mattm
2014/09/09 21:20:16
I also have a todo about looking into keeping thes
gab
2014/11/12 20:49:34
Acknowledged.
| |
| 76 UMA_HISTOGRAM_ENUMERATION("SBOffDomainInclusion.EmptyMainFrameURL", | |
| 77 resource_type, | |
| 78 content::RESOURCE_TYPE_LAST_TYPE); | |
| 79 } else { | |
| 80 // There is no reason for the main frame to start loading resources if its | |
| 81 // own URL is invalid but measure this in the wild to make sure. | |
| 82 UMA_HISTOGRAM_ENUMERATION("SBOffDomainInclusion.InvalidMainFrameURL", | |
| 83 resource_type, | |
| 84 content::RESOURCE_TYPE_LAST_TYPE); | |
| 85 } | |
| 86 } else { | |
| 87 // Cut |main_frame_url| down to its host's second-level domain. | |
|
mattm
2014/09/09 21:20:16
Should use registry_controlled_domains::GetDomainA
gab
2014/11/12 20:49:34
Oh awesome!!! I was looking for exactly that, I ha
| |
| 88 std::string second_level_host_domain = main_frame_url.host(); | |
| 89 | |
| 90 const char kDomainPartDelimiter = '.'; | |
| 91 size_t tld_delim = | |
| 92 second_level_host_domain.find_last_of(kDomainPartDelimiter); | |
| 93 if (tld_delim != std::string::npos && tld_delim != 0U) { | |
| 94 size_t sld_delim = second_level_host_domain.find_last_of( | |
| 95 kDomainPartDelimiter, tld_delim - 1); | |
| 96 if (sld_delim != std::string::npos) | |
| 97 second_level_host_domain.erase(0U, sld_delim + 1U); | |
| 98 } | |
| 99 | |
| 100 if (!request->url().DomainIs(second_level_host_domain.c_str())) { | |
| 101 UMA_HISTOGRAM_ENUMERATION("SBOffDomainInclusion.Detected", | |
| 102 resource_type, | |
| 103 content::RESOURCE_TYPE_LAST_TYPE); | |
| 104 } | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 } // namespace safe_browsing | |
| OLD | NEW |