Home | History | Annotate | Download | only in net
      1 // Copyright 2013 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 #ifndef CHROME_RENDERER_NET_NET_ERROR_HELPER_CORE_H_
      6 #define CHROME_RENDERER_NET_NET_ERROR_HELPER_CORE_H_
      7 
      8 #include <string>
      9 
     10 #include "base/callback.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/memory/weak_ptr.h"
     13 #include "base/timer/timer.h"
     14 #include "chrome/common/localized_error.h"
     15 #include "chrome/common/net/net_error_info.h"
     16 #include "url/gurl.h"
     17 
     18 namespace base {
     19 class ListValue;
     20 }
     21 
     22 namespace blink {
     23 struct WebURLError;
     24 }
     25 
     26 // Class that contains the logic for how the NetErrorHelper.  This allows for
     27 // testing the logic without a RenderView or WebFrame, which are difficult to
     28 // mock, and for testing races which are impossible to reliably reproduce
     29 // with real RenderViews or WebFrames.
     30 class NetErrorHelperCore {
     31  public:
     32   enum FrameType {
     33     MAIN_FRAME,
     34     SUB_FRAME,
     35   };
     36 
     37   enum PageType {
     38     NON_ERROR_PAGE,
     39     ERROR_PAGE,
     40   };
     41 
     42   enum Button {
     43     NO_BUTTON,
     44     RELOAD_BUTTON,
     45     LOAD_STALE_BUTTON,
     46     MORE_BUTTON,
     47   };
     48 
     49   // The Delegate handles all interaction with the RenderView, WebFrame, and
     50   // the network, as well as the generation of error pages.
     51   class Delegate {
     52    public:
     53     // Generates an error page's HTML for the given error.
     54     virtual void GenerateLocalizedErrorPage(
     55         const blink::WebURLError& error,
     56         bool is_failed_post,
     57         scoped_ptr<LocalizedError::ErrorPageParams> params,
     58         bool* reload_button_shown,
     59         bool* load_stale_button_shown,
     60         std::string* html) const = 0;
     61 
     62     // Loads the given HTML in the main frame for use as an error page.
     63     virtual void LoadErrorPageInMainFrame(const std::string& html,
     64                                           const GURL& failed_url) = 0;
     65 
     66     // Create extra Javascript bindings in the error page.
     67     virtual void EnablePageHelperFunctions() = 0;
     68 
     69     // Updates the currently displayed error page with a new error code.  The
     70     // currently displayed error page must have finished loading, and must have
     71     // been generated by a call to GenerateLocalizedErrorPage.
     72     virtual void UpdateErrorPage(const blink::WebURLError& error,
     73                                  bool is_failed_post) = 0;
     74 
     75     // Fetches an error page and calls into OnErrorPageFetched when done.  Any
     76     // previous fetch must either be canceled or finished before calling.  Can't
     77     // be called synchronously after a previous fetch completes.
     78     virtual void FetchNavigationCorrections(
     79         const GURL& navigation_correction_url,
     80         const std::string& navigation_correction_request_body) = 0;
     81 
     82     // Cancels fetching navigation corrections.  Does nothing if no fetch is
     83     // ongoing.
     84     virtual void CancelFetchNavigationCorrections() = 0;
     85 
     86     // Sends an HTTP request used to track which link on the page was clicked to
     87     // the navigation correction service.
     88     virtual void SendTrackingRequest(
     89         const GURL& tracking_url,
     90         const std::string& tracking_request_body) = 0;
     91 
     92     // Starts a reload of the page in the observed frame.
     93     virtual void ReloadPage() = 0;
     94 
     95     // Load the original page from cache.
     96     virtual void LoadPageFromCache(const GURL& page_url) = 0;
     97 
     98    protected:
     99     virtual ~Delegate() {}
    100   };
    101 
    102   struct NavigationCorrectionParams {
    103     NavigationCorrectionParams();
    104     ~NavigationCorrectionParams();
    105 
    106     // URL used both for getting the suggestions and tracking clicks.
    107     GURL url;
    108 
    109     std::string language;
    110     std::string country_code;
    111     std::string api_key;
    112     GURL search_url;
    113   };
    114 
    115   NetErrorHelperCore(Delegate* delegate,
    116                      bool auto_reload_enabled,
    117                      bool auto_reload_visible_only,
    118                      bool is_visible);
    119   ~NetErrorHelperCore();
    120 
    121   // Examines |frame| and |error| to see if this is an error worthy of a DNS
    122   // probe.  If it is, initializes |error_strings| based on |error|,
    123   // |is_failed_post|, and |locale| with suitable strings and returns true.
    124   // If not, returns false, in which case the caller should look up error
    125   // strings directly using LocalizedError::GetNavigationErrorStrings.
    126   //
    127   // Updates the NetErrorHelper with the assumption the page will be loaded
    128   // immediately.
    129   void GetErrorHTML(FrameType frame_type,
    130                     const blink::WebURLError& error,
    131                     bool is_failed_post,
    132                     std::string* error_html);
    133 
    134   // These methods handle tracking the actual state of the page.
    135   void OnStartLoad(FrameType frame_type, PageType page_type);
    136   void OnCommitLoad(FrameType frame_type, const GURL& url);
    137   void OnFinishLoad(FrameType frame_type);
    138   void OnStop();
    139   void OnWasShown();
    140   void OnWasHidden();
    141 
    142   void CancelPendingFetches();
    143 
    144   // Called when an error page have has been retrieved over the network.  |html|
    145   // must be an empty string on error.
    146   void OnNavigationCorrectionsFetched(const std::string& corrections,
    147                                       const std::string& accept_languages,
    148                                       bool is_rtl);
    149 
    150   // Notifies |this| that network error information from the browser process
    151   // has been received.
    152   void OnNetErrorInfo(chrome_common_net::DnsProbeStatus status);
    153 
    154   void OnSetNavigationCorrectionInfo(const GURL& navigation_correction_url,
    155                                      const std::string& language,
    156                                      const std::string& country_code,
    157                                      const std::string& api_key,
    158                                      const GURL& search_url);
    159   // Notifies |this| that the network's online status changed.
    160   // Handler for NetworkStateChanged notification from the browser process. If
    161   // the network state changes to online, this method is responsible for
    162   // starting the auto-reload process.
    163   //
    164   // Warning: if there are many tabs sitting at an error page, this handler will
    165   // be run at the same time for each of their top-level renderframes, which can
    166   // cause many requests to be started at the same time. There's no current
    167   // protection against this kind of "reload storm".
    168   //
    169   // TODO(rdsmith): prevent the reload storm.
    170   void NetworkStateChanged(bool online);
    171 
    172   int auto_reload_count() const { return auto_reload_count_; }
    173 
    174   bool ShouldSuppressErrorPage(FrameType frame_type, const GURL& url);
    175 
    176   void set_timer_for_testing(scoped_ptr<base::Timer> timer) {
    177     auto_reload_timer_.reset(timer.release());
    178   }
    179 
    180   // Execute the effect of pressing the specified button.
    181   // Note that the visual effects of the 'MORE' button are taken
    182   // care of in JavaScript.
    183   void ExecuteButtonPress(Button button);
    184 
    185   // Reports to the correction service that the link with the given tracking
    186   // ID was clicked.  Only pages generated with information from the service
    187   // have links with tracking IDs.  Duplicate requests from the same page with
    188   // the same tracking ID are ignored.
    189   void TrackClick(int tracking_id);
    190 
    191  private:
    192   struct ErrorPageInfo;
    193 
    194   // Gets HTML for a main frame error page.  Depending on
    195   // |pending_error_page_info|, may use the navigation correction service, or
    196   // show a DNS probe error page.  May modify |pending_error_page_info|.
    197   void GetErrorHtmlForMainFrame(ErrorPageInfo* pending_error_page_info,
    198                                 std::string* error_html);
    199 
    200   // Updates the currently displayed error page with a new error based on the
    201   // most recently received DNS probe result.  The page must have finished
    202   // loading before this is called.
    203   void UpdateErrorPage();
    204 
    205   blink::WebURLError GetUpdatedError(const blink::WebURLError& error) const;
    206 
    207   void Reload();
    208   bool MaybeStartAutoReloadTimer();
    209   void StartAutoReloadTimer();
    210   void AutoReloadTimerFired();
    211   void PauseAutoReloadTimer();
    212 
    213   static bool IsReloadableError(const ErrorPageInfo& info);
    214 
    215   Delegate* delegate_;
    216 
    217   // The last DnsProbeStatus received from the browser.
    218   chrome_common_net::DnsProbeStatus last_probe_status_;
    219 
    220   // Information for the provisional / "pre-provisional" error page.  NULL when
    221   // there's no page pending, or the pending page is not an error page.
    222   scoped_ptr<ErrorPageInfo> pending_error_page_info_;
    223 
    224   // Information for the committed error page.  NULL when the committed page is
    225   // not an error page.
    226   scoped_ptr<ErrorPageInfo> committed_error_page_info_;
    227 
    228   NavigationCorrectionParams navigation_correction_params_;
    229 
    230   // True if auto-reload is enabled at all.
    231   const bool auto_reload_enabled_;
    232 
    233   // True if auto-reload should only run when the observed frame is visible.
    234   const bool auto_reload_visible_only_;
    235 
    236   // Timer used to wait for auto-reload attempts.
    237   scoped_ptr<base::Timer> auto_reload_timer_;
    238 
    239   // True if the auto-reload timer would be running but is waiting for an
    240   // offline->online network transition.
    241   bool auto_reload_paused_;
    242 
    243   // True if there is an uncommitted-but-started load, error page or not. This
    244   // is used to inhibit starting auto-reload when an error page finishes, in
    245   // case this happens:
    246   //   Error page starts
    247   //   Error page commits
    248   //   Non-error page starts
    249   //   Error page finishes
    250   bool uncommitted_load_started_;
    251 
    252   // Is the browser online?
    253   bool online_;
    254 
    255   // Is the RenderFrame this object is observing visible?
    256   bool visible_;
    257 
    258   int auto_reload_count_;
    259 
    260   // This value is set only when a navigation has been initiated from
    261   // the error page.  It is used to detect when such navigations result
    262   // in errors.
    263   Button navigation_from_button_;
    264 };
    265 
    266 #endif  // CHROME_RENDERER_NET_NET_ERROR_HELPER_CORE_H_
    267