Home | History | Annotate | Download | only in safe_browsing
      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.
     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_;
    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:
    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