| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef CHROME_BROWSER_SAFE_BROWSING_THREAT_DETAILS_H_ | |
| 6 #define CHROME_BROWSER_SAFE_BROWSING_THREAT_DETAILS_H_ | |
| 7 | |
| 8 // A class that encapsulates the detailed threat reports sent when | |
| 9 // users opt-in to do so from the safe browsing warning page. | |
| 10 | |
| 11 // An instance of this class is generated when a safe browsing warning page | |
| 12 // is shown (SafeBrowsingBlockingPage). | |
| 13 | |
| 14 #include <memory> | |
| 15 #include <string> | |
| 16 #include <unordered_set> | |
| 17 #include <vector> | |
| 18 | |
| 19 #include "base/containers/hash_tables.h" | |
| 20 #include "base/gtest_prod_util.h" | |
| 21 #include "base/macros.h" | |
| 22 #include "base/memory/ref_counted.h" | |
| 23 #include "components/safe_browsing/common/safebrowsing_types.h" | |
| 24 #include "components/safe_browsing/csd.pb.h" | |
| 25 #include "components/security_interstitials/content/unsafe_resource.h" | |
| 26 #include "content/public/browser/browser_thread.h" | |
| 27 #include "content/public/browser/web_contents_observer.h" | |
| 28 #include "net/base/completion_callback.h" | |
| 29 | |
| 30 namespace history { | |
| 31 class HistoryService; | |
| 32 } // namespace history | |
| 33 | |
| 34 namespace net { | |
| 35 class URLRequestContextGetter; | |
| 36 } // namespace net | |
| 37 | |
| 38 struct SafeBrowsingHostMsg_ThreatDOMDetails_Node; | |
| 39 | |
| 40 namespace safe_browsing { | |
| 41 | |
| 42 class BaseUIManager; | |
| 43 | |
| 44 // Maps a URL to its Resource. | |
| 45 class ThreatDetailsCacheCollector; | |
| 46 class ThreatDetailsRedirectsCollector; | |
| 47 class ThreatDetailsFactory; | |
| 48 | |
| 49 using ResourceMap = | |
| 50 base::hash_map<std::string, | |
| 51 std::unique_ptr<ClientSafeBrowsingReportRequest::Resource>>; | |
| 52 | |
| 53 // Maps a key of an HTML element to its corresponding HTMLElement proto message. | |
| 54 // HTML Element keys have the form "<frame_id>-<node_id>", where |frame_id| is | |
| 55 // the FrameTree NodeID of the render frame containing the element, and | |
| 56 // |node_id| is a seqeuntial ID for the element generated by the renderer. | |
| 57 using ElementMap = base::hash_map<std::string, std::unique_ptr<HTMLElement>>; | |
| 58 | |
| 59 // Maps a URL to some HTML Elements. Used to maintain parent/child relationship | |
| 60 // for HTML Elements across IFrame boundaries. | |
| 61 // The key is the string URL set as the src attribute of an iframe. The value is | |
| 62 // the HTMLElement proto that represents the iframe element with that URL. | |
| 63 // The HTMLElement protos are not owned by this map. | |
| 64 using UrlToDomElementMap = base::hash_map<std::string, HTMLElement*>; | |
| 65 | |
| 66 // Maps a URL to some Element IDs. Used to maintain parent/child relationship | |
| 67 // for HTML Elements across IFrame boundaries. | |
| 68 // The key is the string URL of a render frame. The value is the set of Element | |
| 69 // IDs that are at the top-level of this render frame. | |
| 70 using UrlToChildIdsMap = base::hash_map<std::string, std::unordered_set<int>>; | |
| 71 | |
| 72 class ThreatDetails : public base::RefCountedThreadSafe< | |
| 73 ThreatDetails, | |
| 74 content::BrowserThread::DeleteOnUIThread>, | |
| 75 public content::WebContentsObserver { | |
| 76 public: | |
| 77 typedef security_interstitials::UnsafeResource UnsafeResource; | |
| 78 | |
| 79 // Constructs a new ThreatDetails instance, using the factory. | |
| 80 static ThreatDetails* NewThreatDetails( | |
| 81 BaseUIManager* ui_manager, | |
| 82 content::WebContents* web_contents, | |
| 83 const UnsafeResource& resource, | |
| 84 net::URLRequestContextGetter* request_context_getter, | |
| 85 history::HistoryService* history_service); | |
| 86 | |
| 87 // Makes the passed |factory| the factory used to instantiate | |
| 88 // SafeBrowsingBlockingPage objects. Useful for tests. | |
| 89 static void RegisterFactory(ThreatDetailsFactory* factory) { | |
| 90 factory_ = factory; | |
| 91 } | |
| 92 | |
| 93 // The SafeBrowsingBlockingPage calls this from the IO thread when | |
| 94 // the user is leaving the blocking page and has opted-in to sending | |
| 95 // the report. We start the redirection urls collection from history service | |
| 96 // in UI thread; then do cache collection back in IO thread. We also record | |
| 97 // if the user did proceed with the warning page, and how many times user | |
| 98 // visited this page before. When we are done, we send the report. | |
| 99 void FinishCollection(bool did_proceed, int num_visits); | |
| 100 | |
| 101 void OnCacheCollectionReady(); | |
| 102 | |
| 103 void OnRedirectionCollectionReady(); | |
| 104 | |
| 105 // content::WebContentsObserver implementation. | |
| 106 bool OnMessageReceived(const IPC::Message& message, | |
| 107 content::RenderFrameHost* render_frame_host) override; | |
| 108 | |
| 109 protected: | |
| 110 friend class ThreatDetailsFactoryImpl; | |
| 111 friend class TestThreatDetailsFactory; | |
| 112 | |
| 113 ThreatDetails(BaseUIManager* ui_manager, | |
| 114 content::WebContents* web_contents, | |
| 115 const UnsafeResource& resource, | |
| 116 net::URLRequestContextGetter* request_context_getter, | |
| 117 history::HistoryService* history_service); | |
| 118 | |
| 119 ~ThreatDetails() override; | |
| 120 | |
| 121 // Called on the IO thread with the DOM details. | |
| 122 virtual void AddDOMDetails( | |
| 123 const int frame_tree_node_id, | |
| 124 const GURL& frame_last_committed_url, | |
| 125 const std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>& params); | |
| 126 | |
| 127 // The report protocol buffer. | |
| 128 std::unique_ptr<ClientSafeBrowsingReportRequest> report_; | |
| 129 | |
| 130 // Used to get a pointer to the HTTP cache. | |
| 131 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; | |
| 132 | |
| 133 private: | |
| 134 friend class base::RefCountedThreadSafe<ThreatDetails>; | |
| 135 friend struct content::BrowserThread::DeleteOnThread< | |
| 136 content::BrowserThread::UI>; | |
| 137 friend class base::DeleteHelper<ThreatDetails>; | |
| 138 | |
| 139 // Starts the collection of the report. | |
| 140 void StartCollection(); | |
| 141 | |
| 142 // Whether the url is "public" so we can add it to the report. | |
| 143 bool IsReportableUrl(const GURL& url) const; | |
| 144 | |
| 145 // Finds an existing Resource for the given url, or creates a new one if not | |
| 146 // found, and adds it to |resources_|. Returns the found/created resource. | |
| 147 ClientSafeBrowsingReportRequest::Resource* FindOrCreateResource( | |
| 148 const GURL& url); | |
| 149 | |
| 150 // Finds an existing HTMLElement for a given key, or creates a new one if not | |
| 151 // found and adds it to |elements_|. Returns the found/created element. | |
| 152 HTMLElement* FindOrCreateElement(const std::string& element_key); | |
| 153 | |
| 154 // Adds a Resource to resources_ with the given parent-child | |
| 155 // relationship. |parent| and |tagname| can be empty, |children| can be NULL. | |
| 156 // Returns the Resource that was affected, or null if no work was done. | |
| 157 ClientSafeBrowsingReportRequest::Resource* AddUrl( | |
| 158 const GURL& url, | |
| 159 const GURL& parent, | |
| 160 const std::string& tagname, | |
| 161 const std::vector<GURL>* children); | |
| 162 | |
| 163 // Message handler. | |
| 164 void OnReceivedThreatDOMDetails( | |
| 165 content::RenderFrameHost* sender, | |
| 166 const std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>& params); | |
| 167 | |
| 168 void AddRedirectUrlList(const std::vector<GURL>& urls); | |
| 169 | |
| 170 // Adds an HTML Element to the DOM structure. | |
| 171 // |frame_tree_node_id| is the unique ID of the render frame the element came | |
| 172 // from. |frame_url| is the URL that the render frame was handling. | |
| 173 // |element_node_id| is a unique ID of the element within the render frame. | |
| 174 // |tag_name| is the tag of the element. |parent_element_node_id| is the | |
| 175 // unique ID of the parent element with the render frame. |attributes| | |
| 176 // containes the names and values of the element's attributes.|resource| is | |
| 177 // set if this element is a resource. | |
| 178 void AddDomElement(const int frame_tree_node_id, | |
| 179 const std::string& frame_url, | |
| 180 const int element_node_id, | |
| 181 const std::string& tag_name, | |
| 182 const int parent_element_node_id, | |
| 183 const std::vector<AttributeNameValue>& attributes, | |
| 184 const ClientSafeBrowsingReportRequest::Resource* resource); | |
| 185 | |
| 186 scoped_refptr<BaseUIManager> ui_manager_; | |
| 187 | |
| 188 const UnsafeResource resource_; | |
| 189 | |
| 190 // For every Url we collect we create a Resource message. We keep | |
| 191 // them in a map so we can avoid duplicates. | |
| 192 ResourceMap resources_; | |
| 193 | |
| 194 // Store all HTML elements collected, keep them in a map for easy lookup. | |
| 195 ElementMap elements_; | |
| 196 | |
| 197 // For each iframe element encountered we map the src of the iframe to the | |
| 198 // iframe element. This is used when we receive elements from a different | |
| 199 // frame whose document URL matches the src of an iframe in this map. We can | |
| 200 // then add all elements from the subframe as children of the iframe element | |
| 201 // stored here. | |
| 202 UrlToDomElementMap iframe_src_to_element_map_; | |
| 203 | |
| 204 // When getting a set of elements from a render frame, we store the frame's | |
| 205 // URL and a collection of all the top-level elements in that frame. When we | |
| 206 // later encounter the parent iframe with the same src URL, we can add all of | |
| 207 // these elements as children of that iframe. | |
| 208 UrlToChildIdsMap document_url_to_children_map_; | |
| 209 | |
| 210 // Result from the cache extractor. | |
| 211 bool cache_result_; | |
| 212 | |
| 213 // Whether user did proceed with the safe browsing blocking page or | |
| 214 // not. | |
| 215 bool did_proceed_; | |
| 216 | |
| 217 // How many times this user has visited this page before. | |
| 218 int num_visits_; | |
| 219 | |
| 220 // Keeps track of whether we have an ambiguous DOM in this report. This can | |
| 221 // happen when the HTML Elements returned by a render frame can't be | |
| 222 // associated with a parent Element in the parent frame. | |
| 223 bool ambiguous_dom_; | |
| 224 | |
| 225 // The factory used to instanciate SafeBrowsingBlockingPage objects. | |
| 226 // Usefull for tests, so they can provide their own implementation of | |
| 227 // SafeBrowsingBlockingPage. | |
| 228 static ThreatDetailsFactory* factory_; | |
| 229 | |
| 230 // Used to collect details from the HTTP Cache. | |
| 231 scoped_refptr<ThreatDetailsCacheCollector> cache_collector_; | |
| 232 | |
| 233 // Used to collect redirect urls from the history service | |
| 234 scoped_refptr<ThreatDetailsRedirectsCollector> redirects_collector_; | |
| 235 | |
| 236 FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, HistoryServiceUrls); | |
| 237 FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, HttpsResourceSanitization); | |
| 238 FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, HTTPCacheNoEntries); | |
| 239 FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, HTTPCache); | |
| 240 FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, ThreatDOMDetails_AmbiguousDOM); | |
| 241 FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, ThreatDOMDetails_MultipleFrames); | |
| 242 FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, ThreatDOMDetails); | |
| 243 | |
| 244 DISALLOW_COPY_AND_ASSIGN(ThreatDetails); | |
| 245 }; | |
| 246 | |
| 247 // Factory for creating ThreatDetails. Useful for tests. | |
| 248 class ThreatDetailsFactory { | |
| 249 public: | |
| 250 virtual ~ThreatDetailsFactory() {} | |
| 251 | |
| 252 virtual ThreatDetails* CreateThreatDetails( | |
| 253 BaseUIManager* ui_manager, | |
| 254 content::WebContents* web_contents, | |
| 255 const security_interstitials::UnsafeResource& unsafe_resource, | |
| 256 net::URLRequestContextGetter* request_context_getter, | |
| 257 history::HistoryService* history_service) = 0; | |
| 258 }; | |
| 259 | |
| 260 } // namespace safe_browsing | |
| 261 | |
| 262 #endif // CHROME_BROWSER_SAFE_BROWSING_THREAT_DETAILS_H_ | |
| OLD | NEW |