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#ifndef CHROME_BROWSER_NET_NET_ERROR_TAB_HELPER_H_
6#define CHROME_BROWSER_NET_NET_ERROR_TAB_HELPER_H_
7
8#include "base/basictypes.h"
9#include "base/bind.h"
10#include "base/compiler_specific.h"
11#include "base/memory/weak_ptr.h"
12#include "base/prefs/pref_member.h"
13#include "chrome/browser/net/dns_probe_service.h"
14#include "chrome/common/net/net_error_info.h"
15#include "content/public/browser/web_contents_observer.h"
16#include "content/public/browser/web_contents_user_data.h"
17
18namespace chrome_browser_net {
19
20// A TabHelper that monitors loads for certain types of network errors and
21// does interesting things with them.  Currently, starts DNS probes using the
22// DnsProbeService whenever a page fails to load with a DNS-related error.
23class NetErrorTabHelper
24    : public content::WebContentsObserver,
25      public content::WebContentsUserData<NetErrorTabHelper> {
26 public:
27  enum TestingState {
28    TESTING_DEFAULT,
29    TESTING_FORCE_DISABLED,
30    TESTING_FORCE_ENABLED
31  };
32
33  typedef base::Callback<void(chrome_common_net::DnsProbeStatus)>
34      DnsProbeStatusSnoopCallback;
35
36  virtual ~NetErrorTabHelper();
37
38  static void set_state_for_testing(TestingState testing_state);
39
40  // Sets a callback that will be called immediately after the helper sends
41  // a NetErrorHelper IPC.  (Used by the DNS probe browser test to know when to
42  // check the error page for updates, instead of polling.)
43  void set_dns_probe_status_snoop_callback_for_testing(
44      const DnsProbeStatusSnoopCallback& dns_probe_status_snoop_callback) {
45    dns_probe_status_snoop_callback_ = dns_probe_status_snoop_callback;
46  }
47
48  // content::WebContentsObserver implementation.
49  virtual void DidStartNavigationToPendingEntry(
50      const GURL& url,
51      content::NavigationController::ReloadType reload_type) OVERRIDE;
52
53  virtual void DidStartProvisionalLoadForFrame(
54      content::RenderFrameHost* render_frame_host,
55      const GURL& validated_url,
56      bool is_error_page,
57      bool is_iframe_srcdoc) OVERRIDE;
58
59  virtual void DidCommitProvisionalLoadForFrame(
60      content::RenderFrameHost* render_frame_host,
61      const GURL& url,
62      ui::PageTransition transition_type) OVERRIDE;
63
64  virtual void DidFailProvisionalLoad(
65      content::RenderFrameHost* render_frame_host,
66      const GURL& validated_url,
67      int error_code,
68      const base::string16& error_description) OVERRIDE;
69
70 protected:
71  // |contents| is the WebContents of the tab this NetErrorTabHelper is
72  // attached to.
73  explicit NetErrorTabHelper(content::WebContents* contents);
74  virtual void StartDnsProbe();
75  virtual void SendInfo();
76  void OnDnsProbeFinished(chrome_common_net::DnsProbeStatus result);
77
78  chrome_common_net::DnsProbeStatus dns_probe_status() const {
79    return dns_probe_status_;
80  }
81
82 private:
83  friend class content::WebContentsUserData<NetErrorTabHelper>;
84
85  void OnMainFrameDnsError();
86
87  void InitializePref(content::WebContents* contents);
88  bool ProbesAllowed() const;
89
90  // True if the last provisional load that started was for an error page.
91  bool is_error_page_;
92
93  // True if the helper has seen a main frame page load fail with a DNS error,
94  // but has not yet seen a new page commit successfully afterwards.
95  bool dns_error_active_;
96
97  // True if the helper has seen an error page commit while |dns_error_active_|
98  // is true.  (This should never be true if |dns_error_active_| is false.)
99  bool dns_error_page_committed_;
100
101  // The status of a DNS probe that may or may not have started or finished.
102  // Since the renderer can change out from under the helper (in cross-process
103  // navigations), it re-sends the status whenever an error page commits.
104  chrome_common_net::DnsProbeStatus dns_probe_status_;
105
106  // Optional callback for browser test to snoop on outgoing NetErrorInfo IPCs.
107  DnsProbeStatusSnoopCallback dns_probe_status_snoop_callback_;
108
109  // "Use a web service to resolve navigation errors" preference is required
110  // to allow probes.
111  BooleanPrefMember resolve_errors_with_web_service_;
112
113  base::WeakPtrFactory<NetErrorTabHelper> weak_factory_;
114
115  DISALLOW_COPY_AND_ASSIGN(NetErrorTabHelper);
116};
117
118}  // namespace chrome_browser_net
119
120#endif  // CHROME_BROWSER_NET_NET_ERROR_TAB_HELPER_H_
121