• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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