1 // Copyright (c) 2012 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 // Classes for managing the SafeBrowsing interstitial pages. 6 // 7 // When a user is about to visit a page the SafeBrowsing system has deemed to 8 // be malicious, either as malware or a phishing page, we show an interstitial 9 // page with some options (go back, continue) to give the user a chance to avoid 10 // the harmful page. 11 // 12 // The SafeBrowsingBlockingPage is created by the SafeBrowsingUIManager on the 13 // UI thread when we've determined that a page is malicious. The operation of 14 // the blocking page occurs on the UI thread, where it waits for the user to 15 // make a decision about what to do: either go back or continue on. 16 // 17 // The blocking page forwards the result of the user's choice back to the 18 // SafeBrowsingUIManager so that we can cancel the request for the new page, 19 // or allow it to continue. 20 // 21 // A web page may contain several resources flagged as malware/phishing. This 22 // results into more than one interstitial being shown. On the first unsafe 23 // resource received we show an interstitial. Any subsequent unsafe resource 24 // notifications while the first interstitial is showing is queued. If the user 25 // decides to proceed in the first interstitial, we display all queued unsafe 26 // resources in a new interstitial. 27 28 #ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_ 29 #define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_ 30 31 #include <map> 32 #include <string> 33 #include <vector> 34 35 #include "base/gtest_prod_util.h" 36 #include "base/time/time.h" 37 #include "chrome/browser/history/history_service.h" 38 #include "chrome/browser/safe_browsing/ui_manager.h" 39 #include "content/public/browser/interstitial_page_delegate.h" 40 #include "url/gurl.h" 41 42 class MalwareDetails; 43 class SafeBrowsingBlockingPageFactory; 44 45 namespace base { 46 class DictionaryValue; 47 class MessageLoop; 48 } 49 50 namespace content { 51 class InterstitialPage; 52 class WebContents; 53 } 54 55 class SafeBrowsingBlockingPage : public content::InterstitialPageDelegate { 56 public: 57 typedef SafeBrowsingUIManager::UnsafeResource UnsafeResource; 58 typedef std::vector<UnsafeResource> UnsafeResourceList; 59 typedef std::map<content::WebContents*, UnsafeResourceList> UnsafeResourceMap; 60 61 virtual ~SafeBrowsingBlockingPage(); 62 63 // Shows a blocking page warning the user about phishing/malware for a 64 // specific resource. 65 // You can call this method several times, if an interstitial is already 66 // showing, the new one will be queued and displayed if the user decides 67 // to proceed on the currently showing interstitial. 68 static void ShowBlockingPage( 69 SafeBrowsingUIManager* ui_manager, const UnsafeResource& resource); 70 71 // Makes the passed |factory| the factory used to instanciate 72 // SafeBrowsingBlockingPage objects. Useful for tests. RegisterFactory(SafeBrowsingBlockingPageFactory * factory)73 static void RegisterFactory(SafeBrowsingBlockingPageFactory* factory) { 74 factory_ = factory; 75 } 76 77 // InterstitialPageDelegate method: 78 virtual void CommandReceived(const std::string& command) OVERRIDE; 79 virtual void OverrideRendererPrefs( 80 content::RendererPreferences* prefs) OVERRIDE; 81 virtual void OnProceed() OVERRIDE; 82 virtual void OnDontProceed() OVERRIDE; 83 84 protected: 85 template <class TestSBInterstitialPage> 86 friend class SafeBrowsingBlockingPageTest; 87 template <class TestSBInterstitialPage> 88 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageTest, 89 ProceedThenDontProceed); 90 91 void SetReportingPreference(bool report); 92 void UpdateReportingPref(); // Used for the transition from old to new pref. 93 94 // Don't instanciate this class directly, use ShowBlockingPage instead. 95 SafeBrowsingBlockingPage(SafeBrowsingUIManager* ui_manager, 96 content::WebContents* web_contents, 97 const UnsafeResourceList& unsafe_resources); 98 99 // After a malware interstitial where the user opted-in to the 100 // report but clicked "proceed anyway", we delay the call to 101 // MalwareDetails::FinishCollection() by this much time (in 102 // milliseconds), in order to get data from the blocked resource itself. 103 int64 malware_details_proceed_delay_ms_; interstitial_page()104 content::InterstitialPage* interstitial_page() const { 105 return interstitial_page_; 106 } 107 108 template <class TestSBInterstitialPage> 109 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageTest, 110 MalwareReportsTransitionDisabled); 111 template <class TestSBInterstitialPage> 112 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageTest, 113 MalwareReportsToggling); 114 115 enum BlockingPageEvent { 116 SHOW, 117 PROCEED, 118 DONT_PROCEED, 119 SHOW_ADVANCED, 120 }; 121 122 // Records a user action for this interstitial, using the form 123 // SBInterstitial[Phishing|Malware|Multiple][Show|Proceed|DontProceed]. 124 void RecordUserAction(BlockingPageEvent event); 125 126 // Used to query the HistoryService to see if the URL is in history. For UMA. 127 void OnGotHistoryCount(HistoryService::Handle handle, 128 bool success, 129 int num_visits, 130 base::Time first_visit); 131 132 // Records the time it took for the user to react to the 133 // interstitial. We won't double-count if this method is called 134 // multiple times. 135 void RecordUserReactionTime(const std::string& command); 136 137 // Checks if we should even show the malware details option. For example, we 138 // don't show it in incognito mode. 139 bool CanShowMalwareDetailsOption(); 140 141 // Called when the insterstitial is going away. If there is a 142 // pending malware details object, we look at the user's 143 // preferences, and if the option to send malware details is 144 // enabled, the report is scheduled to be sent on the |ui_manager_|. 145 void FinishMalwareDetails(int64 delay_ms); 146 147 // Returns the boolean value of the given |pref| from the PrefService of the 148 // Profile associated with |web_contents_|. 149 bool IsPrefEnabled(const char* pref); 150 151 // A list of SafeBrowsingUIManager::UnsafeResource for a tab that the user 152 // should be warned about. They are queued when displaying more than one 153 // interstitial at a time. 154 static UnsafeResourceMap* GetUnsafeResourcesMap(); 155 156 // Notifies the SafeBrowsingUIManager on the IO thread whether to proceed 157 // or not for the |resources|. 158 static void NotifySafeBrowsingUIManager( 159 SafeBrowsingUIManager* ui_manager, 160 const UnsafeResourceList& resources, bool proceed); 161 162 // Returns true if the passed |unsafe_resources| is blocking the load of 163 // the main page. 164 static bool IsMainPageLoadBlocked( 165 const UnsafeResourceList& unsafe_resources); 166 167 friend class SafeBrowsingBlockingPageFactoryImpl; 168 169 // For reporting back user actions. 170 SafeBrowsingUIManager* ui_manager_; 171 base::MessageLoop* report_loop_; 172 173 // True if the interstitial is blocking the main page because it is on one 174 // of our lists. False if a subresource is being blocked, or in the case of 175 // client-side detection where the interstitial is shown after page load 176 // finishes. 177 bool is_main_frame_load_blocked_; 178 179 // The index of a navigation entry that should be removed when DontProceed() 180 // is invoked, -1 if not entry should be removed. 181 int navigation_entry_index_to_remove_; 182 183 // The list of unsafe resources this page is warning about. 184 UnsafeResourceList unsafe_resources_; 185 186 // A MalwareDetails object that we start generating when the 187 // blocking page is shown. The object will be sent when the warning 188 // is gone (if the user enables the feature). 189 scoped_refptr<MalwareDetails> malware_details_; 190 191 bool proceeded_; 192 193 content::WebContents* web_contents_; 194 GURL url_; 195 content::InterstitialPage* interstitial_page_; // Owns us 196 197 // Time when the interstitial was show. This variable is set in 198 // GetHTMLContents() which is called right before the interstitial 199 // is shown to the user. Will return is_null() once we reported the 200 // user action. 201 base::TimeTicks interstitial_show_time_; 202 203 // Whether the user has expanded the "see more" section of the page already 204 // during this interstitial page. 205 bool has_expanded_see_more_section_; 206 207 // Whether the user has left the reporting checkbox checked. 208 bool reporting_checkbox_checked_; 209 210 // Which type of interstitial this is. 211 enum { 212 TYPE_MALWARE, 213 TYPE_PHISHING, 214 TYPE_MALWARE_AND_PHISHING, 215 } interstitial_type_; 216 217 // The factory used to instanciate SafeBrowsingBlockingPage objects. 218 // Usefull for tests, so they can provide their own implementation of 219 // SafeBrowsingBlockingPage. 220 static SafeBrowsingBlockingPageFactory* factory_; 221 222 // How many times is this same URL in history? Used for histogramming. 223 int num_visits_; 224 CancelableRequestConsumer request_consumer_; 225 226 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPage); 227 }; 228 229 class SafeBrowsingBlockingPageV1 : public SafeBrowsingBlockingPage { 230 public: 231 // Don't instanciate this class directly, use ShowBlockingPage instead. 232 SafeBrowsingBlockingPageV1(SafeBrowsingUIManager* ui_manager, 233 content::WebContents* web_contents, 234 const UnsafeResourceList& unsafe_resources); 235 236 // InterstitialPageDelegate method: 237 virtual std::string GetHTMLContents() OVERRIDE; 238 239 private: 240 // Fills the passed dictionary with the strings passed to JS Template when 241 // creating the HTML. 242 void PopulateMultipleThreatStringDictionary(base::DictionaryValue* strings); 243 void PopulateMalwareStringDictionary(base::DictionaryValue* strings); 244 void PopulatePhishingStringDictionary(base::DictionaryValue* strings); 245 246 // A helper method used by the Populate methods above used to populate common 247 // fields. 248 void PopulateStringDictionary(base::DictionaryValue* strings, 249 const base::string16& title, 250 const base::string16& headline, 251 const base::string16& description1, 252 const base::string16& description2, 253 const base::string16& description3); 254 255 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageV1); 256 }; 257 258 class SafeBrowsingBlockingPageV2 : public SafeBrowsingBlockingPage { 259 public: 260 // Don't instanciate this class directly, use ShowBlockingPage instead. 261 SafeBrowsingBlockingPageV2(SafeBrowsingUIManager* ui_manager, 262 content::WebContents* web_contents, 263 const UnsafeResourceList& unsafe_resources); 264 265 // InterstitialPageDelegate method: 266 virtual std::string GetHTMLContents() OVERRIDE; 267 268 private: 269 // Fills the passed dictionary with the strings passed to JS Template when 270 // creating the HTML. 271 void PopulateMultipleThreatStringDictionary(base::DictionaryValue* strings); 272 void PopulateMalwareStringDictionary(base::DictionaryValue* strings); 273 void PopulatePhishingStringDictionary(base::DictionaryValue* strings); 274 275 // A helper method used by the Populate methods above used to populate common 276 // fields. 277 void PopulateStringDictionary(base::DictionaryValue* strings, 278 const base::string16& title, 279 const base::string16& headline, 280 const base::string16& description1, 281 const base::string16& description2, 282 const base::string16& description3); 283 284 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageV2); 285 }; 286 287 class SafeBrowsingBlockingPageV3 : public SafeBrowsingBlockingPage { 288 public: 289 SafeBrowsingBlockingPageV3(SafeBrowsingUIManager* ui_manager, 290 content::WebContents* web_contents, 291 const UnsafeResourceList& unsafe_resources); 292 293 // InterstitialPageDelegate method: 294 virtual std::string GetHTMLContents() OVERRIDE; 295 296 private: 297 // Fills the passed dictionary with the values to be passed to the template 298 // when creating the HTML. 299 void PopulateMalwareLoadTimeData(base::DictionaryValue* load_time_data); 300 void PopulatePhishingLoadTimeData(base::DictionaryValue* load_time_data); 301 302 // For the M37 FieldTrial: this contains the name of the condition. 303 std::string trial_condition_; 304 305 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageV3); 306 }; 307 308 // Factory for creating SafeBrowsingBlockingPage. Useful for tests. 309 class SafeBrowsingBlockingPageFactory { 310 public: ~SafeBrowsingBlockingPageFactory()311 virtual ~SafeBrowsingBlockingPageFactory() { } 312 313 virtual SafeBrowsingBlockingPage* CreateSafeBrowsingPage( 314 SafeBrowsingUIManager* ui_manager, 315 content::WebContents* web_contents, 316 const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources) = 0; 317 }; 318 319 #endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_ 320