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 <memory> 9 #include <string> 10 11 #include "base/callback.h" 12 #include "base/memory/weak_ptr.h" 13 #include "base/timer/timer.h" 14 #include "build/build_config.h" 15 #include "components/error_page/common/error.h" 16 #include "components/error_page/common/localized_error.h" 17 #include "components/error_page/common/net_error_info.h" 18 #include "net/base/net_errors.h" 19 #include "url/gurl.h" 20 21 #if defined(OS_ANDROID) 22 #include "chrome/renderer/net/available_offline_content_helper.h" 23 #include "chrome/renderer/net/page_auto_fetcher_helper_android.h" 24 #endif 25 26 namespace content { 27 class RenderFrame; 28 } 29 namespace error_page { 30 struct ErrorPageParams; 31 } 32 33 // Class that contains the logic for how the NetErrorHelper. This allows for 34 // testing the logic without a RenderView or WebFrame, which are difficult to 35 // mock, and for testing races which are impossible to reliably reproduce 36 // with real RenderViews or WebFrames. 37 class NetErrorHelperCore { 38 public: 39 enum FrameType { 40 MAIN_FRAME, 41 SUB_FRAME, 42 }; 43 44 enum PageType { 45 NON_ERROR_PAGE, 46 ERROR_PAGE, 47 }; 48 49 enum Button { 50 NO_BUTTON, 51 RELOAD_BUTTON, 52 MORE_BUTTON, 53 EASTER_EGG, 54 SHOW_CACHED_COPY_BUTTON, // "Google cached copy" button label experiment. 55 DIAGNOSE_ERROR, 56 DOWNLOAD_BUTTON, // "Download page later" experiment. 57 }; 58 59 // The Delegate handles all interaction with the RenderView, WebFrame, and 60 // the network, as well as the generation of error pages. 61 class Delegate { 62 public: 63 // Generates an error page's HTML for the given error. 64 virtual error_page::LocalizedError::PageState GenerateLocalizedErrorPage( 65 const error_page::Error& error, 66 bool is_failed_post, 67 bool can_show_network_diagnostics_dialog, 68 std::unique_ptr<error_page::ErrorPageParams> params, 69 std::string* html) const = 0; 70 71 // Loads the given HTML in the frame for use as an error page. 72 virtual void LoadErrorPage(const std::string& html, 73 const GURL& failed_url) = 0; 74 75 // Create extra Javascript bindings in the error page. Will only be invoked 76 // after an error page has finished loading. 77 virtual void EnablePageHelperFunctions() = 0; 78 79 // Updates the currently displayed error page with a new error code. The 80 // currently displayed error page must have finished loading, and must have 81 // been generated by a call to GenerateLocalizedErrorPage. 82 virtual error_page::LocalizedError::PageState UpdateErrorPage( 83 const error_page::Error& error, 84 bool is_failed_post, 85 bool can_show_network_diagnostics_dialog) = 0; 86 87 // Tell the currently displayed error page about the user's current easter 88 // egg game high score (from the user's synced preferences). The currently 89 // displayed error page must have finished loading, and must have been 90 // generated by a call to GenerateLocalizedErrorPage. 91 virtual void InitializeErrorPageEasterEggHighScore(int high_score) = 0; 92 93 // Request the current easter egg high score stored in the user's synced 94 // preferences from the browser. The delegate should call 95 // OnEasterEggHighScoreReceived() with the response. 96 virtual void RequestEasterEggHighScore() = 0; 97 98 // Fetches an error page and calls into OnErrorPageFetched when done. Any 99 // previous fetch must either be canceled or finished before calling. Can't 100 // be called synchronously after a previous fetch completes. 101 virtual void FetchNavigationCorrections( 102 const GURL& navigation_correction_url, 103 const std::string& navigation_correction_request_body) = 0; 104 105 // Cancels fetching navigation corrections. Does nothing if no fetch is 106 // ongoing. 107 virtual void CancelFetchNavigationCorrections() = 0; 108 109 // Sends an HTTP request used to track which link on the page was clicked to 110 // the navigation correction service. 111 virtual void SendTrackingRequest( 112 const GURL& tracking_url, 113 const std::string& tracking_request_body) = 0; 114 115 // Starts a reload of the observed frame. 116 virtual void ReloadFrame() = 0; 117 118 // Run the platform diagnostics too for the specified URL. 119 virtual void DiagnoseError(const GURL& page_url) = 0; 120 121 // Schedule to download the page at a later time. 122 virtual void DownloadPageLater() = 0; 123 124 // Inform that download button is being shown in the error page. 125 virtual void SetIsShowingDownloadButton(bool show) = 0; 126 127 // Signals that offline content is available. 128 virtual void OfflineContentAvailable( 129 bool list_visible_by_prefs, 130 const std::string& offline_content_json) = 0; 131 132 // Returns the render frame associated with NetErrorHelper. 133 virtual content::RenderFrame* GetRenderFrame() = 0; 134 135 #if defined(OS_ANDROID) 136 // Called after an attempt to automatically schedule a background fetch for 137 // a page with a network error. 138 virtual void SetAutoFetchState( 139 chrome::mojom::OfflinePageAutoFetcherScheduleResult result) = 0; 140 #endif 141 142 protected: ~Delegate()143 virtual ~Delegate() {} 144 }; 145 146 struct NavigationCorrectionParams { 147 NavigationCorrectionParams(); 148 NavigationCorrectionParams(const NavigationCorrectionParams& other); 149 ~NavigationCorrectionParams(); 150 151 // URL used both for getting the suggestions and tracking clicks. 152 GURL url; 153 154 std::string language; 155 std::string country_code; 156 std::string api_key; 157 GURL search_url; 158 }; 159 160 NetErrorHelperCore(Delegate* delegate, 161 bool auto_reload_enabled, 162 bool is_visible); 163 ~NetErrorHelperCore(); 164 165 // Sets values in |pending_error_page_info_|. If |error_html| is not null, it 166 // initializes |error_html| with the HTML of an error page in response to 167 // |error|. Updates internals state with the assumption the page will be 168 // loaded immediately. 169 void PrepareErrorPage(FrameType frame_type, 170 const error_page::Error& error, 171 bool is_failed_post, 172 std::string* error_html); 173 174 // These methods handle tracking the actual state of the page. 175 void OnStartLoad(FrameType frame_type, PageType page_type); 176 void OnCommitLoad(FrameType frame_type, const GURL& url); 177 void OnFinishLoad(FrameType frame_type); 178 void OnStop(); 179 void OnWasShown(); 180 void OnWasHidden(); 181 182 void CancelPendingFetches(); 183 184 // Called when an error page have has been retrieved over the network. |html| 185 // must be an empty string on error. 186 void OnNavigationCorrectionsFetched(const std::string& corrections, 187 bool is_rtl); 188 189 // Notifies |this| that network error information from the browser process 190 // has been received. 191 void OnNetErrorInfo(error_page::DnsProbeStatus status); 192 193 // Notifies |this| if it can use a local error diagnostics service through its 194 // delegate. 195 void OnSetCanShowNetworkDiagnosticsDialog( 196 bool can_show_network_diagnostics_dialog); 197 198 void OnSetNavigationCorrectionInfo(const GURL& navigation_correction_url, 199 const std::string& language, 200 const std::string& country_code, 201 const std::string& api_key, 202 const GURL& search_url); 203 204 // Notifies |this| about the current high score that's saved in the user's 205 // synced preferences. 206 void OnEasterEggHighScoreReceived(int high_score); 207 208 // Notifies |this| that the network's online status changed. 209 // Handler for NetworkStateChanged notification from the browser process. If 210 // the network state changes to online, this method is responsible for 211 // starting the auto-reload process. 212 // 213 // Warning: if there are many tabs sitting at an error page, this handler will 214 // be run at the same time for each of their top-level renderframes, which can 215 // cause many requests to be started at the same time. There's no current 216 // protection against this kind of "reload storm". 217 // 218 // TODO(rdsmith): prevent the reload storm. 219 void NetworkStateChanged(bool online); 220 auto_reload_count()221 int auto_reload_count() const { return auto_reload_count_; } 222 223 bool ShouldSuppressErrorPage(FrameType frame_type, const GURL& url); 224 set_timer_for_testing(std::unique_ptr<base::OneShotTimer> timer)225 void set_timer_for_testing(std::unique_ptr<base::OneShotTimer> timer) { 226 auto_reload_timer_ = std::move(timer); 227 } 228 229 #if defined(OS_ANDROID) 230 void SetPageAutoFetcherHelperForTesting( 231 std::unique_ptr<PageAutoFetcherHelper> page_auto_fetcher_helper); 232 #endif 233 234 // Execute the effect of pressing the specified button. 235 // Note that the visual effects of the 'MORE' button are taken 236 // care of in JavaScript. 237 void ExecuteButtonPress(Button button); 238 239 // Reports to the correction service that the link with the given tracking 240 // ID was clicked. Only pages generated with information from the service 241 // have links with tracking IDs. Duplicate requests from the same page with 242 // the same tracking ID are ignored. 243 void TrackClick(int tracking_id); 244 245 // Opens a suggested offline item. 246 void LaunchOfflineItem(const std::string& id, const std::string& name_space); 247 248 // Shows all available offline content. 249 void LaunchDownloadsPage(); 250 251 void CancelSavePage(); 252 void SavePageForLater(); 253 254 // Signals the user changed the visibility of the offline content list in the 255 // dino page. 256 void ListVisibilityChanged(bool is_visible); 257 258 private: 259 struct ErrorPageInfo; 260 261 // Sets values in |pending_error_page_info| for a main frame error page. If 262 // |error_html| is not null, it also fetches the string containing the error 263 // page HTML, and sets error_html to it. Depending on 264 // |pending_error_page_info|, may use the navigation correction service, or 265 // show a DNS probe error page. May modify |pending_error_page_info|. 266 void PrepareErrorPageForMainFrame(ErrorPageInfo* pending_error_page_info, 267 std::string* error_html); 268 269 // Updates the currently displayed error page with a new error based on the 270 // most recently received DNS probe result. The page must have finished 271 // loading before this is called. 272 void UpdateErrorPage(); 273 274 // Called after the error page is loaded and is showing the final error code. 275 // This is either called on page load, or after a DNS probe finishes. 276 void ErrorPageLoadedWithFinalErrorCode(); 277 278 error_page::Error GetUpdatedError(const ErrorPageInfo& error_info) const; 279 280 void Reload(); 281 bool MaybeStartAutoReloadTimer(); 282 void StartAutoReloadTimer(); 283 void AutoReloadTimerFired(); 284 void PauseAutoReloadTimer(); 285 286 static bool IsReloadableError(const ErrorPageInfo& info); 287 288 Delegate* delegate_; 289 290 // The last DnsProbeStatus received from the browser. 291 error_page::DnsProbeStatus last_probe_status_; 292 293 // Information for the provisional / "pre-provisional" error page. NULL when 294 // there's no page pending, or the pending page is not an error page. 295 std::unique_ptr<ErrorPageInfo> pending_error_page_info_; 296 297 // Information for the committed error page. NULL when the committed page is 298 // not an error page. 299 std::unique_ptr<ErrorPageInfo> committed_error_page_info_; 300 301 bool can_show_network_diagnostics_dialog_; 302 303 NavigationCorrectionParams navigation_correction_params_; 304 305 // True if auto-reload is enabled at all. 306 const bool auto_reload_enabled_; 307 308 // Timer used to wait for auto-reload attempts. 309 std::unique_ptr<base::OneShotTimer> auto_reload_timer_; 310 311 // True if the auto-reload timer would be running but is waiting for an 312 // offline->online network transition. 313 bool auto_reload_paused_; 314 315 // Whether an auto-reload-initiated Reload() attempt is in flight. 316 bool auto_reload_in_flight_; 317 318 // True if there is an uncommitted-but-started load, error page or not. This 319 // is used to inhibit starting auto-reload when an error page finishes, in 320 // case this happens: 321 // Error page starts 322 // Error page commits 323 // Non-error page starts 324 // Error page finishes 325 bool uncommitted_load_started_; 326 327 // Is the browser online? 328 bool online_; 329 330 // Is the RenderFrame this object is observing visible? 331 bool visible_; 332 333 int auto_reload_count_; 334 335 // This value is set only when a navigation has been initiated from 336 // the error page. It is used to detect when such navigations result 337 // in errors. 338 Button navigation_from_button_; 339 340 #if defined(OS_ANDROID) 341 AvailableOfflineContentHelper available_content_helper_; 342 std::unique_ptr<PageAutoFetcherHelper> page_auto_fetcher_helper_; 343 #endif 344 }; 345 346 #endif // CHROME_RENDERER_NET_NET_ERROR_HELPER_CORE_H_ 347