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/safe_browsing/ui_manager.h" 38#include "content/public/browser/interstitial_page_delegate.h" 39#include "url/gurl.h" 40 41class MalwareDetails; 42class SafeBrowsingBlockingPageFactory; 43 44namespace base { 45class DictionaryValue; 46class MessageLoop; 47} 48 49namespace content { 50class InterstitialPage; 51class WebContents; 52} 53 54class SafeBrowsingBlockingPage : public content::InterstitialPageDelegate { 55 public: 56 typedef SafeBrowsingUIManager::UnsafeResource UnsafeResource; 57 typedef std::vector<UnsafeResource> UnsafeResourceList; 58 typedef std::map<content::WebContents*, UnsafeResourceList> UnsafeResourceMap; 59 60 virtual ~SafeBrowsingBlockingPage(); 61 62 // Shows a blocking page warning the user about phishing/malware for a 63 // specific resource. 64 // You can call this method several times, if an interstitial is already 65 // showing, the new one will be queued and displayed if the user decides 66 // to proceed on the currently showing interstitial. 67 static void ShowBlockingPage( 68 SafeBrowsingUIManager* ui_manager, const UnsafeResource& resource); 69 70 // Makes the passed |factory| the factory used to instanciate 71 // SafeBrowsingBlockingPage objects. Useful for tests. 72 static void RegisterFactory(SafeBrowsingBlockingPageFactory* factory) { 73 factory_ = factory; 74 } 75 76 // InterstitialPageDelegate method: 77 virtual void CommandReceived(const std::string& command) OVERRIDE; 78 virtual void OverrideRendererPrefs( 79 content::RendererPreferences* prefs) OVERRIDE; 80 virtual void OnProceed() OVERRIDE; 81 virtual void OnDontProceed() OVERRIDE; 82 83 protected: 84 friend class SafeBrowsingBlockingPageTest; 85 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageTest, 86 ProceedThenDontProceed); 87 friend class SafeBrowsingBlockingPageV2Test; 88 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageV2Test, 89 ProceedThenDontProceed); 90 91 void SetReportingPreference(bool report); 92 93 // Don't instanciate this class directly, use ShowBlockingPage instead. 94 SafeBrowsingBlockingPage(SafeBrowsingUIManager* ui_manager, 95 content::WebContents* web_contents, 96 const UnsafeResourceList& unsafe_resources); 97 98 // After a malware interstitial where the user opted-in to the 99 // report but clicked "proceed anyway", we delay the call to 100 // MalwareDetails::FinishCollection() by this much time (in 101 // milliseconds), in order to get data from the blocked resource itself. 102 int64 malware_details_proceed_delay_ms_; 103 content::InterstitialPage* interstitial_page() const { 104 return interstitial_page_; 105 } 106 107 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageTest, MalwareReports); 108 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageV2Test, MalwareReports); 109 110 enum BlockingPageEvent { 111 SHOW, 112 PROCEED, 113 DONT_PROCEED, 114 SHOW_ADVANCED, 115 }; 116 117 // Records a user action for this interstitial, using the form 118 // SBInterstitial[Phishing|Malware|Multiple][Show|Proceed|DontProceed]. 119 void RecordUserAction(BlockingPageEvent event); 120 121 // Records the time it took for the user to react to the 122 // interstitial. We won't double-count if this method is called 123 // multiple times. 124 void RecordUserReactionTime(const std::string& command); 125 126 // Checks if we should even show the malware details option. For example, we 127 // don't show it in incognito mode. 128 bool CanShowMalwareDetailsOption(); 129 130 // Called when the insterstitial is going away. If there is a 131 // pending malware details object, we look at the user's 132 // preferences, and if the option to send malware details is 133 // enabled, the report is scheduled to be sent on the |ui_manager_|. 134 void FinishMalwareDetails(int64 delay_ms); 135 136 // Returns the boolean value of the given |pref| from the PrefService of the 137 // Profile associated with |web_contents_|. 138 bool IsPrefEnabled(const char* pref); 139 140 // A list of SafeBrowsingUIManager::UnsafeResource for a tab that the user 141 // should be warned about. They are queued when displaying more than one 142 // interstitial at a time. 143 static UnsafeResourceMap* GetUnsafeResourcesMap(); 144 145 // Notifies the SafeBrowsingUIManager on the IO thread whether to proceed 146 // or not for the |resources|. 147 static void NotifySafeBrowsingUIManager( 148 SafeBrowsingUIManager* ui_manager, 149 const UnsafeResourceList& resources, bool proceed); 150 151 // Returns true if the passed |unsafe_resources| is blocking the load of 152 // the main page. 153 static bool IsMainPageLoadBlocked( 154 const UnsafeResourceList& unsafe_resources); 155 156 friend class SafeBrowsingBlockingPageFactoryImpl; 157 158 // For reporting back user actions. 159 SafeBrowsingUIManager* ui_manager_; 160 base::MessageLoop* report_loop_; 161 162 // True if the interstitial is blocking the main page because it is on one 163 // of our lists. False if a subresource is being blocked, or in the case of 164 // client-side detection where the interstitial is shown after page load 165 // finishes. 166 bool is_main_frame_load_blocked_; 167 168 // The index of a navigation entry that should be removed when DontProceed() 169 // is invoked, -1 if not entry should be removed. 170 int navigation_entry_index_to_remove_; 171 172 // The list of unsafe resources this page is warning about. 173 UnsafeResourceList unsafe_resources_; 174 175 // A MalwareDetails object that we start generating when the 176 // blocking page is shown. The object will be sent when the warning 177 // is gone (if the user enables the feature). 178 scoped_refptr<MalwareDetails> malware_details_; 179 180 bool proceeded_; 181 182 content::WebContents* web_contents_; 183 GURL url_; 184 content::InterstitialPage* interstitial_page_; // Owns us 185 186 // Time when the interstitial was show. This variable is set in 187 // GetHTMLContents() which is called right before the interstitial 188 // is shown to the user. Will return is_null() once we reported the 189 // user action. 190 base::TimeTicks interstitial_show_time_; 191 192 // Whether the user has expanded the "see more" section of the page already 193 // during this interstitial page. 194 bool has_expanded_see_more_section_; 195 196 // Which type of interstitial this is. 197 enum { 198 TYPE_MALWARE, 199 TYPE_PHISHING, 200 TYPE_MALWARE_AND_PHISHING, 201 } interstitial_type_; 202 203 // The factory used to instanciate SafeBrowsingBlockingPage objects. 204 // Usefull for tests, so they can provide their own implementation of 205 // SafeBrowsingBlockingPage. 206 static SafeBrowsingBlockingPageFactory* factory_; 207 208 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPage); 209}; 210 211class SafeBrowsingBlockingPageV1 : public SafeBrowsingBlockingPage { 212 public: 213 // Don't instanciate this class directly, use ShowBlockingPage instead. 214 SafeBrowsingBlockingPageV1(SafeBrowsingUIManager* ui_manager, 215 content::WebContents* web_contents, 216 const UnsafeResourceList& unsafe_resources); 217 218 // InterstitialPageDelegate method: 219 virtual std::string GetHTMLContents() OVERRIDE; 220 221 private: 222 // Fills the passed dictionary with the strings passed to JS Template when 223 // creating the HTML. 224 void PopulateMultipleThreatStringDictionary(base::DictionaryValue* strings); 225 void PopulateMalwareStringDictionary(base::DictionaryValue* strings); 226 void PopulatePhishingStringDictionary(base::DictionaryValue* strings); 227 228 // A helper method used by the Populate methods above used to populate common 229 // fields. 230 void PopulateStringDictionary(base::DictionaryValue* strings, 231 const string16& title, 232 const string16& headline, 233 const string16& description1, 234 const string16& description2, 235 const string16& description3); 236 237 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageV1); 238}; 239 240class SafeBrowsingBlockingPageV2 : public SafeBrowsingBlockingPage { 241 public: 242 // Don't instanciate this class directly, use ShowBlockingPage instead. 243 SafeBrowsingBlockingPageV2(SafeBrowsingUIManager* ui_manager, 244 content::WebContents* web_contents, 245 const UnsafeResourceList& unsafe_resources); 246 247 // InterstitialPageDelegate method: 248 virtual std::string GetHTMLContents() OVERRIDE; 249 250 private: 251 // Fills the passed dictionary with the strings passed to JS Template when 252 // creating the HTML. 253 void PopulateMultipleThreatStringDictionary(base::DictionaryValue* strings); 254 void PopulateMalwareStringDictionary(base::DictionaryValue* strings); 255 void PopulatePhishingStringDictionary(base::DictionaryValue* strings); 256 257 // A helper method used by the Populate methods above used to populate common 258 // fields. 259 void PopulateStringDictionary(base::DictionaryValue* strings, 260 const string16& title, 261 const string16& headline, 262 const string16& description1, 263 const string16& description2, 264 const string16& description3); 265 266 // For the FieldTrial: this contains the name of the condition. 267 std::string trialCondition_; 268 269 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageV2); 270}; 271 272// Factory for creating SafeBrowsingBlockingPage. Useful for tests. 273class SafeBrowsingBlockingPageFactory { 274 public: 275 virtual ~SafeBrowsingBlockingPageFactory() { } 276 277 virtual SafeBrowsingBlockingPage* CreateSafeBrowsingPage( 278 SafeBrowsingUIManager* ui_manager, 279 content::WebContents* web_contents, 280 const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources) = 0; 281}; 282 283#endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_ 284