summaryrefslogtreecommitdiffstats
path: root/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
blob: 43ac464b57d8d2d4d8769e630e575e4fd5cf2d53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Classes for managing the SafeBrowsing interstitial pages.
//
// When a user is about to visit a page the SafeBrowsing system has deemed to
// be malicious, either as malware or a phishing page, we show an interstitial
// page with some options (go back, continue) to give the user a chance to avoid
// the harmful page.
//
// The SafeBrowsingBlockingPage is created by the SafeBrowsingUIManager on the
// UI thread when we've determined that a page is malicious. The operation of
// the blocking page occurs on the UI thread, where it waits for the user to
// make a decision about what to do: either go back or continue on.
//
// The blocking page forwards the result of the user's choice back to the
// SafeBrowsingUIManager so that we can cancel the request for the new page,
// or allow it to continue.
//
// A web page may contain several resources flagged as malware/phishing.  This
// results into more than one interstitial being shown.  On the first unsafe
// resource received we show an interstitial.  Any subsequent unsafe resource
// notifications while the first interstitial is showing is queued.  If the user
// decides to proceed in the first interstitial, we display all queued unsafe
// resources in a new interstitial.

#ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_
#define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_

#include <map>
#include <string>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/time/time.h"
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/safe_browsing/ui_manager.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "url/gurl.h"

class MalwareDetails;
class SafeBrowsingBlockingPageFactory;

namespace base {
class DictionaryValue;
class MessageLoop;
}

namespace content {
class InterstitialPage;
class WebContents;
}

class SafeBrowsingBlockingPage : public content::InterstitialPageDelegate {
 public:
  typedef SafeBrowsingUIManager::UnsafeResource UnsafeResource;
  typedef std::vector<UnsafeResource> UnsafeResourceList;
  typedef std::map<content::WebContents*, UnsafeResourceList> UnsafeResourceMap;

  virtual ~SafeBrowsingBlockingPage();

  // Shows a blocking page warning the user about phishing/malware for a
  // specific resource.
  // You can call this method several times, if an interstitial is already
  // showing, the new one will be queued and displayed if the user decides
  // to proceed on the currently showing interstitial.
  static void ShowBlockingPage(
      SafeBrowsingUIManager* ui_manager, const UnsafeResource& resource);

  // Makes the passed |factory| the factory used to instanciate
  // SafeBrowsingBlockingPage objects. Useful for tests.
  static void RegisterFactory(SafeBrowsingBlockingPageFactory* factory) {
    factory_ = factory;
  }

  // InterstitialPageDelegate method:
  virtual void CommandReceived(const std::string& command) OVERRIDE;
  virtual void OverrideRendererPrefs(
      content::RendererPreferences* prefs) OVERRIDE;
  virtual void OnProceed() OVERRIDE;
  virtual void OnDontProceed() OVERRIDE;

 protected:
  friend class SafeBrowsingBlockingPageTest;
  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageTest,
                           ProceedThenDontProceed);
  friend class SafeBrowsingBlockingPageV2Test;
  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageV2Test,
                           ProceedThenDontProceed);

  void SetReportingPreference(bool report);

  // Don't instanciate this class directly, use ShowBlockingPage instead.
  SafeBrowsingBlockingPage(SafeBrowsingUIManager* ui_manager,
                           content::WebContents* web_contents,
                           const UnsafeResourceList& unsafe_resources);

  // After a malware interstitial where the user opted-in to the
  // report but clicked "proceed anyway", we delay the call to
  // MalwareDetails::FinishCollection() by this much time (in
  // milliseconds), in order to get data from the blocked resource itself.
  int64 malware_details_proceed_delay_ms_;
  content::InterstitialPage* interstitial_page() const {
    return interstitial_page_;
  }

  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageTest, MalwareReports);
  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageV2Test, MalwareReports);

  enum BlockingPageEvent {
    SHOW,
    PROCEED,
    DONT_PROCEED,
    SHOW_ADVANCED,
  };

  // Records a user action for this interstitial, using the form
  // SBInterstitial[Phishing|Malware|Multiple][Show|Proceed|DontProceed].
  void RecordUserAction(BlockingPageEvent event);

  // Used to query the HistoryService to see if the URL is in history. For UMA.
  void OnGotHistoryCount(HistoryService::Handle handle,
                         bool success,
                         int num_visits,
                         base::Time first_visit);

  // Records the time it took for the user to react to the
  // interstitial.  We won't double-count if this method is called
  // multiple times.
  void RecordUserReactionTime(const std::string& command);

  // Checks if we should even show the malware details option. For example, we
  // don't show it in incognito mode.
  bool CanShowMalwareDetailsOption();

  // Called when the insterstitial is going away. If there is a
  // pending malware details object, we look at the user's
  // preferences, and if the option to send malware details is
  // enabled, the report is scheduled to be sent on the |ui_manager_|.
  void FinishMalwareDetails(int64 delay_ms);

  // Returns the boolean value of the given |pref| from the PrefService of the
  // Profile associated with |web_contents_|.
  bool IsPrefEnabled(const char* pref);

  // A list of SafeBrowsingUIManager::UnsafeResource for a tab that the user
  // should be warned about.  They are queued when displaying more than one
  // interstitial at a time.
  static UnsafeResourceMap* GetUnsafeResourcesMap();

  // Notifies the SafeBrowsingUIManager on the IO thread whether to proceed
  // or not for the |resources|.
  static void NotifySafeBrowsingUIManager(
      SafeBrowsingUIManager* ui_manager,
      const UnsafeResourceList& resources, bool proceed);

  // Returns true if the passed |unsafe_resources| is blocking the load of
  // the main page.
  static bool IsMainPageLoadBlocked(
      const UnsafeResourceList& unsafe_resources);

  friend class SafeBrowsingBlockingPageFactoryImpl;

  // For reporting back user actions.
  SafeBrowsingUIManager* ui_manager_;
  base::MessageLoop* report_loop_;

  // True if the interstitial is blocking the main page because it is on one
  // of our lists.  False if a subresource is being blocked, or in the case of
  // client-side detection where the interstitial is shown after page load
  // finishes.
  bool is_main_frame_load_blocked_;

  // The index of a navigation entry that should be removed when DontProceed()
  // is invoked, -1 if not entry should be removed.
  int navigation_entry_index_to_remove_;

  // The list of unsafe resources this page is warning about.
  UnsafeResourceList unsafe_resources_;

  // A MalwareDetails object that we start generating when the
  // blocking page is shown. The object will be sent when the warning
  // is gone (if the user enables the feature).
  scoped_refptr<MalwareDetails> malware_details_;

  bool proceeded_;

  content::WebContents* web_contents_;
  GURL url_;
  content::InterstitialPage* interstitial_page_;  // Owns us

  // Time when the interstitial was show.  This variable is set in
  // GetHTMLContents() which is called right before the interstitial
  // is shown to the user. Will return is_null() once we reported the
  // user action.
  base::TimeTicks interstitial_show_time_;

  // Whether the user has expanded the "see more" section of the page already
  // during this interstitial page.
  bool has_expanded_see_more_section_;

  // Which type of interstitial this is.
  enum {
    TYPE_MALWARE,
    TYPE_PHISHING,
    TYPE_MALWARE_AND_PHISHING,
  } interstitial_type_;

  // The factory used to instanciate SafeBrowsingBlockingPage objects.
  // Usefull for tests, so they can provide their own implementation of
  // SafeBrowsingBlockingPage.
  static SafeBrowsingBlockingPageFactory* factory_;

  // How many times is this same URL in history? Used for histogramming.
  int num_visits_;
  CancelableRequestConsumer request_consumer_;

  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPage);
};

class SafeBrowsingBlockingPageV1 : public SafeBrowsingBlockingPage {
 public:
  // Don't instanciate this class directly, use ShowBlockingPage instead.
  SafeBrowsingBlockingPageV1(SafeBrowsingUIManager* ui_manager,
                             content::WebContents* web_contents,
                             const UnsafeResourceList& unsafe_resources);

  // InterstitialPageDelegate method:
  virtual std::string GetHTMLContents() OVERRIDE;

 private:
  // Fills the passed dictionary with the strings passed to JS Template when
  // creating the HTML.
  void PopulateMultipleThreatStringDictionary(base::DictionaryValue* strings);
  void PopulateMalwareStringDictionary(base::DictionaryValue* strings);
  void PopulatePhishingStringDictionary(base::DictionaryValue* strings);

  // A helper method used by the Populate methods above used to populate common
  // fields.
  void PopulateStringDictionary(base::DictionaryValue* strings,
                                const base::string16& title,
                                const base::string16& headline,
                                const base::string16& description1,
                                const base::string16& description2,
                                const base::string16& description3);

  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageV1);
};

class SafeBrowsingBlockingPageV2 : public SafeBrowsingBlockingPage {
 public:
  // Don't instanciate this class directly, use ShowBlockingPage instead.
  SafeBrowsingBlockingPageV2(SafeBrowsingUIManager* ui_manager,
                             content::WebContents* web_contents,
                             const UnsafeResourceList& unsafe_resources);

  // InterstitialPageDelegate method:
  virtual std::string GetHTMLContents() OVERRIDE;

 private:
  // Fills the passed dictionary with the strings passed to JS Template when
  // creating the HTML.
  void PopulateMultipleThreatStringDictionary(base::DictionaryValue* strings);
  void PopulateMalwareStringDictionary(base::DictionaryValue* strings);
  void PopulatePhishingStringDictionary(base::DictionaryValue* strings);

  // A helper method used by the Populate methods above used to populate common
  // fields.
  void PopulateStringDictionary(base::DictionaryValue* strings,
                                const base::string16& title,
                                const base::string16& headline,
                                const base::string16& description1,
                                const base::string16& description2,
                                const base::string16& description3);

  // For the FieldTrial: this contains the name of the condition.
  std::string trialCondition_;

  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingBlockingPageV2);
};

// Factory for creating SafeBrowsingBlockingPage.  Useful for tests.
class SafeBrowsingBlockingPageFactory {
 public:
  virtual ~SafeBrowsingBlockingPageFactory() { }

  virtual SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
      SafeBrowsingUIManager* ui_manager,
      content::WebContents* web_contents,
      const SafeBrowsingBlockingPage::UnsafeResourceList& unsafe_resources) = 0;
};

#endif  // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_