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 18namespace base { 19class ListValue; 20} 21 22namespace blink { 23struct 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. 30class 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