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/task/cancelable_task_tracker.h"
37#include "base/time/time.h"
38#include "chrome/browser/history/history_service.h"
39#include "chrome/browser/safe_browsing/ui_manager.h"
40#include "content/public/browser/interstitial_page_delegate.h"
41#include "url/gurl.h"
42
43class MalwareDetails;
44class SafeBrowsingBlockingPageFactory;
45
46namespace base {
47class DictionaryValue;
48class MessageLoop;
49}
50
51namespace content {
52class InterstitialPage;
53class WebContents;
54}
55
56#if defined(ENABLE_EXTENSIONS)
57namespace extensions {
58class ExperienceSamplingEvent;
59}
60#endif
61
62class SafeBrowsingBlockingPage : public content::InterstitialPageDelegate {
63 public:
64  typedef SafeBrowsingUIManager::UnsafeResource UnsafeResource;
65  typedef std::vector<UnsafeResource> UnsafeResourceList;
66  typedef std::map<content::WebContents*, UnsafeResourceList> UnsafeResourceMap;
67
68  virtual ~SafeBrowsingBlockingPage();
69
70  // Creates a blocking page. Use ShowBlockingPage if you don't need to access
71  // the blocking page directly.
72  static SafeBrowsingBlockingPage* CreateBlockingPage(
73      SafeBrowsingUIManager* ui_manager,
74      content::WebContents* web_contents,
75      const UnsafeResource& unsafe_resource);
76
77  // Shows a blocking page warning the user about phishing/malware for a
78  // specific resource.
79  // You can call this method several times, if an interstitial is already
80  // showing, the new one will be queued and displayed if the user decides
81  // to proceed on the currently showing interstitial.
82  static void ShowBlockingPage(
83      SafeBrowsingUIManager* ui_manager, const UnsafeResource& resource);
84
85  // Makes the passed |factory| the factory used to instantiate
86  // SafeBrowsingBlockingPage objects. Useful for tests.
87  static void RegisterFactory(SafeBrowsingBlockingPageFactory* factory) {
88    factory_ = factory;
89  }
90
91  // InterstitialPageDelegate method:
92  virtual std::string GetHTMLContents() OVERRIDE;
93  virtual void OnProceed() OVERRIDE;
94  virtual void OnDontProceed() OVERRIDE;
95  virtual void CommandReceived(const std::string& command) OVERRIDE;
96  virtual void OverrideRendererPrefs(
97      content::RendererPreferences* prefs) OVERRIDE;
98
99 protected:
100  friend class SafeBrowsingBlockingPageTest;
101  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageTest,
102                           ProceedThenDontProceed);
103
104  void DontCreateViewForTesting();
105  void Show();
106  void SetReportingPreference(bool report);
107  void UpdateReportingPref();  // Used for the transition from old to new pref.
108
109  // Don't instantiate this class directly, use ShowBlockingPage instead.
110  SafeBrowsingBlockingPage(SafeBrowsingUIManager* ui_manager,
111                           content::WebContents* web_contents,
112                           const UnsafeResourceList& unsafe_resources);
113
114  // After a malware interstitial where the user opted-in to the
115  // report but clicked "proceed anyway", we delay the call to
116  // MalwareDetails::FinishCollection() by this much time (in
117  // milliseconds), in order to get data from the blocked resource itself.
118  int64 malware_details_proceed_delay_ms_;
119  content::InterstitialPage* interstitial_page() const {
120    return interstitial_page_;
121  }
122
123  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageTest,
124      MalwareReportsTransitionDisabled);
125  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageTest,
126      MalwareReportsToggling);
127
128  // These enums are used for histograms.  Don't reorder, delete, or insert
129  // elements.  New elements should be added before MAX_ACTION only.
130  enum Decision {
131    SHOW,
132    PROCEED,
133    DONT_PROCEED,
134    PROCEEDING_DISABLED,
135    MAX_DECISION
136  };
137  enum Interaction {
138    TOTAL_VISITS,
139    SHOW_ADVANCED,
140    SHOW_PRIVACY_POLICY,
141    SHOW_DIAGNOSTIC,
142    SHOW_LEARN_MORE,
143    MAX_INTERACTION
144  };
145
146  // Record a user decision or interaction to the appropriate UMA histogram.
147  void RecordUserDecision(Decision decision);
148  void RecordUserInteraction(Interaction interaction);
149
150  // Used to query the HistoryService to see if the URL is in history. For UMA.
151  void OnGotHistoryCount(bool success, int num_visits, base::Time first_visit);
152
153  // Checks if we should even show the malware details option. For example, we
154  // don't show it in incognito mode.
155  bool CanShowMalwareDetailsOption();
156
157  // Called when the insterstitial is going away. If there is a
158  // pending malware details object, we look at the user's
159  // preferences, and if the option to send malware details is
160  // enabled, the report is scheduled to be sent on the |ui_manager_|.
161  void FinishMalwareDetails(int64 delay_ms);
162
163  // Returns the boolean value of the given |pref| from the PrefService of the
164  // Profile associated with |web_contents_|.
165  bool IsPrefEnabled(const char* pref);
166
167  // A list of SafeBrowsingUIManager::UnsafeResource for a tab that the user
168  // should be warned about.  They are queued when displaying more than one
169  // interstitial at a time.
170  static UnsafeResourceMap* GetUnsafeResourcesMap();
171
172  // Notifies the SafeBrowsingUIManager on the IO thread whether to proceed
173  // or not for the |resources|.
174  static void NotifySafeBrowsingUIManager(
175      SafeBrowsingUIManager* ui_manager,
176      const UnsafeResourceList& resources, bool proceed);
177
178  // Returns true if the passed |unsafe_resources| is blocking the load of
179  // the main page.
180  static bool IsMainPageLoadBlocked(
181      const UnsafeResourceList& unsafe_resources);
182
183  friend class SafeBrowsingBlockingPageFactoryImpl;
184
185  // For reporting back user actions.
186  SafeBrowsingUIManager* ui_manager_;
187  base::MessageLoop* report_loop_;
188
189  // True if the interstitial is blocking the main page because it is on one
190  // of our lists.  False if a subresource is being blocked, or in the case of
191  // client-side detection where the interstitial is shown after page load
192  // finishes.
193  bool is_main_frame_load_blocked_;
194
195  // The index of a navigation entry that should be removed when DontProceed()
196  // is invoked, -1 if not entry should be removed.
197  int navigation_entry_index_to_remove_;
198
199  // The list of unsafe resources this page is warning about.
200  UnsafeResourceList unsafe_resources_;
201
202  // A MalwareDetails object that we start generating when the
203  // blocking page is shown. The object will be sent when the warning
204  // is gone (if the user enables the feature).
205  scoped_refptr<MalwareDetails> malware_details_;
206
207  bool proceeded_;
208
209  content::WebContents* web_contents_;
210  GURL url_;
211  content::InterstitialPage* interstitial_page_;  // Owns us
212
213  // Whether the interstitial should create a view.
214  bool create_view_;
215
216  // Which type of interstitial this is.
217  enum {
218    TYPE_MALWARE,
219    TYPE_HARMFUL,
220    TYPE_PHISHING,
221  } interstitial_type_;
222
223  // The factory used to instantiate SafeBrowsingBlockingPage objects.
224  // Usefull for tests, so they can provide their own implementation of
225  // SafeBrowsingBlockingPage.
226  static SafeBrowsingBlockingPageFactory* factory_;
227
228  // How many times is this same URL in history? Used for histogramming.
229  int num_visits_;
230  base::CancelableTaskTracker request_tracker_;
231
232 private:
233  // Fills the passed dictionary with the values to be passed to the template
234  // when creating the HTML.
235  void PopulateMalwareLoadTimeData(base::DictionaryValue* load_time_data);
236  void PopulateHarmfulLoadTimeData(base::DictionaryValue* load_time_data);
237  void PopulatePhishingLoadTimeData(base::DictionaryValue* load_time_data);
238
239#if defined(ENABLE_EXTENSIONS)
240  scoped_ptr<extensions::ExperienceSamplingEvent> sampling_event_;
241#endif
242
243  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPage);
244};
245
246// Factory for creating SafeBrowsingBlockingPage.  Useful for tests.
247class SafeBrowsingBlockingPageFactory {
248 public:
249  virtual ~SafeBrowsingBlockingPageFactory() { }
250
251  virtual SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
252      SafeBrowsingUIManager* ui_manager,
253      content::WebContents* web_contents,
254      const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources) = 0;
255};
256
257#endif  // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_
258