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
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_ERROR_PAGE_CONTENT_BROWSER_NET_ERROR_AUTO_RELOADER_H_
#define COMPONENTS_ERROR_PAGE_CONTENT_BROWSER_NET_ERROR_AUTO_RELOADER_H_
#include <stddef.h>
#include <memory>
#include <optional>
#include <set>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "net/base/net_errors.h"
#include "services/network/public/cpp/network_connection_tracker.h"
#include "services/network/public/mojom/network_change_manager.mojom.h"
#include "url/gurl.h"
namespace content {
class NavigationHandle;
class NavigationThrottleRegistry;
class WebContents;
} // namespace content
namespace error_page {
// This class implements support for automatic reload attempts with backoff
// whenever a WebContents' main frame lands on common network error pages. This
// excludes errors that aren't connectivity related since a reload doesn't
// generally fix them (e.g. SSL errors or when the client blocked the request).
// To use this behavior as a Content embedder, simply call the static
// `MaybeCreateAndAddNavigationThrottle()` method from within your
// implementation of ContentBrowserClient::CreateThrottlesForNavigation.
class NetErrorAutoReloader
: public content::WebContentsObserver,
public content::WebContentsUserData<NetErrorAutoReloader>,
public network::NetworkConnectionTracker::NetworkConnectionObserver {
public:
NetErrorAutoReloader(const NetErrorAutoReloader&) = delete;
NetErrorAutoReloader& operator=(const NetErrorAutoReloader&) = delete;
~NetErrorAutoReloader() override;
// Maybe installs a throttle for the given navigation, lazily initializing the
// appropriate WebContents' NetErrorAutoReloader instance if necessary. For
// embedders wanting to use NetErrorAutoReload's behavior, it's sufficient to
// call this from ContentBrowserClient::CreateThrottlesForNavigation for each
// navigation processed.
static void MaybeCreateAndAddNavigationThrottle(
content::NavigationThrottleRegistry& registry);
// content::WebContentsObserver:
void DidStartNavigation(content::NavigationHandle* handle) override;
void DidFinishNavigation(content::NavigationHandle* handle) override;
void NavigationStopped() override;
void OnVisibilityChanged(content::Visibility visibility) override;
// network::NetworkConnectionTracker::NetworkConnectionObserver:
void OnConnectionChanged(network::mojom::ConnectionType type) override;
// Returns the delay applied when scheduling the next auto-reload of a page
// after it's already been auto-reloaded `reload_count` times.
static base::TimeDelta GetNextReloadDelayForTesting(size_t reload_count);
// Permanently unsubscribes this object from receiving OnConnectionChanged
// notifications. Used in tests which want to drive this behavior explicitly.
void DisableConnectionChangeObservationForTesting();
// Returns the timer used internally to schedule the next auto-reload task,
// or null if no auto-reload task is currently scheduled.
std::optional<base::OneShotTimer>& next_reload_timer_for_testing() {
return next_reload_timer_;
}
private:
friend class content::WebContentsUserData<NetErrorAutoReloader>;
explicit NetErrorAutoReloader(content::WebContents* web_contents);
void SetInitialConnectionType(network::mojom::ConnectionType type);
bool IsWebContentsVisible();
void Reset();
void PauseAutoReloadTimerIfRunning();
void ResumeAutoReloadIfPaused();
void ScheduleNextAutoReload();
void ReloadMainFrame();
void MaybeCreateAndAdd(
content::NavigationThrottleRegistry& registry);
bool ShouldSuppressErrorPage(content::NavigationHandle* handle);
struct ErrorPageInfo {
ErrorPageInfo(const GURL& url, net::Error error);
~ErrorPageInfo();
GURL url;
net::Error error;
};
raw_ptr<network::NetworkConnectionTracker> connection_tracker_;
bool is_online_ = true;
std::set<raw_ptr<content::NavigationHandle, SetExperimental>>
pending_navigations_;
std::optional<base::OneShotTimer> next_reload_timer_;
std::optional<ErrorPageInfo> current_reloadable_error_page_info_;
size_t num_reloads_for_current_error_ = 0;
bool is_auto_reload_in_progress_ = false;
base::WeakPtrFactory<NetErrorAutoReloader> weak_ptr_factory_{this};
WEB_CONTENTS_USER_DATA_KEY_DECL();
};
} // namespace error_page
#endif // COMPONENTS_ERROR_PAGE_CONTENT_BROWSER_NET_ERROR_AUTO_RELOADER_H_
|