BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / chrome / browser / net / net_error_tab_helper.cc
blobf0cbcf91c6c3ca2206db93a59365b32a4a7fa629
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.
5 #include "chrome/browser/net/net_error_tab_helper.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/prefs/pref_service.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/io_thread.h"
12 #include "chrome/browser/net/dns_probe_service.h"
13 #include "chrome/browser/net/net_error_diagnostics_dialog.h"
14 #include "chrome/browser/platform_util.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/pref_names.h"
17 #include "chrome/common/render_messages.h"
18 #include "components/error_page/common/net_error_info.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/render_frame_host.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "ipc/ipc_message_macros.h"
23 #include "net/base/net_errors.h"
24 #include "url/gurl.h"
26 using content::BrowserContext;
27 using content::BrowserThread;
28 using content::RenderViewHost;
29 using content::WebContents;
30 using content::WebContentsObserver;
31 using error_page::DnsProbeStatus;
32 using error_page::DnsProbeStatusToString;
33 using ui::PageTransition;
35 DEFINE_WEB_CONTENTS_USER_DATA_KEY(chrome_browser_net::NetErrorTabHelper);
37 namespace chrome_browser_net {
39 namespace {
41 static NetErrorTabHelper::TestingState testing_state_ =
42 NetErrorTabHelper::TESTING_DEFAULT;
44 // Returns whether |net_error| is a DNS-related error (and therefore whether
45 // the tab helper should start a DNS probe after receiving it.)
46 bool IsDnsError(int net_error) {
47 return net_error == net::ERR_NAME_NOT_RESOLVED ||
48 net_error == net::ERR_NAME_RESOLUTION_FAILED;
51 void OnDnsProbeFinishedOnIOThread(
52 const base::Callback<void(DnsProbeStatus)>& callback,
53 DnsProbeStatus result) {
54 DCHECK_CURRENTLY_ON(BrowserThread::IO);
56 BrowserThread::PostTask(
57 BrowserThread::UI,
58 FROM_HERE,
59 base::Bind(callback, result));
62 // Can only access g_browser_process->io_thread() from the browser thread,
63 // so have to pass it in to the callback instead of dereferencing it here.
64 void StartDnsProbeOnIOThread(
65 const base::Callback<void(DnsProbeStatus)>& callback,
66 IOThread* io_thread) {
67 DCHECK_CURRENTLY_ON(BrowserThread::IO);
69 DnsProbeService* probe_service =
70 io_thread->globals()->dns_probe_service.get();
72 probe_service->ProbeDns(base::Bind(&OnDnsProbeFinishedOnIOThread, callback));
75 } // namespace
77 NetErrorTabHelper::~NetErrorTabHelper() {
80 // static
81 void NetErrorTabHelper::set_state_for_testing(TestingState state) {
82 testing_state_ = state;
85 void NetErrorTabHelper::RenderViewCreated(
86 content::RenderViewHost* render_view_host) {
87 content::RenderFrameHost* render_frame_host =
88 render_view_host->GetMainFrame();
89 render_frame_host->Send(new ChromeViewMsg_SetCanShowNetworkDiagnosticsDialog(
90 render_frame_host->GetRoutingID(),
91 CanShowNetworkDiagnosticsDialog()));
94 void NetErrorTabHelper::DidStartNavigationToPendingEntry(
95 const GURL& url,
96 content::NavigationController::ReloadType reload_type) {
97 DCHECK_CURRENTLY_ON(BrowserThread::UI);
99 if (!is_error_page_)
100 return;
102 // Only record reloads.
103 if (reload_type != content::NavigationController::NO_RELOAD) {
104 error_page::RecordEvent(
105 error_page::NETWORK_ERROR_PAGE_BROWSER_INITIATED_RELOAD);
109 void NetErrorTabHelper::DidStartProvisionalLoadForFrame(
110 content::RenderFrameHost* render_frame_host,
111 const GURL& validated_url,
112 bool is_error_page,
113 bool is_iframe_srcdoc) {
114 DCHECK_CURRENTLY_ON(BrowserThread::UI);
116 if (render_frame_host->GetParent())
117 return;
119 is_error_page_ = is_error_page;
122 void NetErrorTabHelper::DidCommitProvisionalLoadForFrame(
123 content::RenderFrameHost* render_frame_host,
124 const GURL& url,
125 PageTransition transition_type) {
126 DCHECK_CURRENTLY_ON(BrowserThread::UI);
128 if (render_frame_host->GetParent())
129 return;
131 // Resend status every time an error page commits; this is somewhat spammy,
132 // but ensures that the status will make it to the real error page, even if
133 // the link doctor loads a blank intermediate page or the tab switches
134 // renderer processes.
135 if (is_error_page_ && dns_error_active_) {
136 dns_error_page_committed_ = true;
137 DVLOG(1) << "Committed error page; resending status.";
138 SendInfo();
139 } else {
140 dns_error_active_ = false;
141 dns_error_page_committed_ = false;
145 void NetErrorTabHelper::DidFailProvisionalLoad(
146 content::RenderFrameHost* render_frame_host,
147 const GURL& validated_url,
148 int error_code,
149 const base::string16& error_description,
150 bool was_ignored_by_handler) {
151 DCHECK_CURRENTLY_ON(BrowserThread::UI);
153 if (render_frame_host->GetParent())
154 return;
156 if (IsDnsError(error_code)) {
157 dns_error_active_ = true;
158 OnMainFrameDnsError();
162 bool NetErrorTabHelper::OnMessageReceived(
163 const IPC::Message& message,
164 content::RenderFrameHost* render_frame_host) {
165 bool handled = true;
166 IPC_BEGIN_MESSAGE_MAP(NetErrorTabHelper, message)
167 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RunNetworkDiagnostics,
168 RunNetworkDiagnostics)
169 IPC_MESSAGE_UNHANDLED(handled = false)
170 IPC_END_MESSAGE_MAP()
172 return handled;
175 NetErrorTabHelper::NetErrorTabHelper(WebContents* contents)
176 : WebContentsObserver(contents),
177 is_error_page_(false),
178 dns_error_active_(false),
179 dns_error_page_committed_(false),
180 dns_probe_status_(error_page::DNS_PROBE_POSSIBLE),
181 weak_factory_(this) {
182 DCHECK_CURRENTLY_ON(BrowserThread::UI);
184 // If this helper is under test, it won't have a WebContents.
185 if (contents)
186 InitializePref(contents);
189 void NetErrorTabHelper::OnMainFrameDnsError() {
190 if (ProbesAllowed()) {
191 // Don't start more than one probe at a time.
192 if (dns_probe_status_ != error_page::DNS_PROBE_STARTED) {
193 StartDnsProbe();
194 dns_probe_status_ = error_page::DNS_PROBE_STARTED;
196 } else {
197 dns_probe_status_ = error_page::DNS_PROBE_NOT_RUN;
201 void NetErrorTabHelper::StartDnsProbe() {
202 DCHECK_CURRENTLY_ON(BrowserThread::UI);
203 DCHECK(dns_error_active_);
204 DCHECK_NE(error_page::DNS_PROBE_STARTED, dns_probe_status_);
206 DVLOG(1) << "Starting DNS probe.";
208 BrowserThread::PostTask(
209 BrowserThread::IO,
210 FROM_HERE,
211 base::Bind(&StartDnsProbeOnIOThread,
212 base::Bind(&NetErrorTabHelper::OnDnsProbeFinished,
213 weak_factory_.GetWeakPtr()),
214 g_browser_process->io_thread()));
217 void NetErrorTabHelper::OnDnsProbeFinished(DnsProbeStatus result) {
218 DCHECK_CURRENTLY_ON(BrowserThread::UI);
219 DCHECK_EQ(error_page::DNS_PROBE_STARTED, dns_probe_status_);
220 DCHECK(error_page::DnsProbeStatusIsFinished(result));
222 DVLOG(1) << "Finished DNS probe with result "
223 << DnsProbeStatusToString(result) << ".";
225 dns_probe_status_ = result;
227 if (dns_error_page_committed_)
228 SendInfo();
231 void NetErrorTabHelper::InitializePref(WebContents* contents) {
232 DCHECK(contents);
234 BrowserContext* browser_context = contents->GetBrowserContext();
235 Profile* profile = Profile::FromBrowserContext(browser_context);
236 resolve_errors_with_web_service_.Init(
237 prefs::kAlternateErrorPagesEnabled,
238 profile->GetPrefs());
241 bool NetErrorTabHelper::ProbesAllowed() const {
242 if (testing_state_ != TESTING_DEFAULT)
243 return testing_state_ == TESTING_FORCE_ENABLED;
245 // TODO(ttuttle): Disable on mobile?
246 return *resolve_errors_with_web_service_;
249 void NetErrorTabHelper::SendInfo() {
250 DCHECK_NE(error_page::DNS_PROBE_POSSIBLE, dns_probe_status_);
251 DCHECK(dns_error_page_committed_);
253 DVLOG(1) << "Sending status " << DnsProbeStatusToString(dns_probe_status_);
254 content::RenderFrameHost* rfh = web_contents()->GetMainFrame();
255 rfh->Send(new ChromeViewMsg_NetErrorInfo(rfh->GetRoutingID(),
256 dns_probe_status_));
258 if (!dns_probe_status_snoop_callback_.is_null())
259 dns_probe_status_snoop_callback_.Run(dns_probe_status_);
262 void NetErrorTabHelper::RunNetworkDiagnostics(const GURL& url) {
263 // Only run diagnostics on HTTP or HTTPS URLs. Shouldn't receive URLs with
264 // any other schemes, but the renderer is not trusted.
265 if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS())
266 return;
267 // Sanitize URL prior to running diagnostics on it.
268 RunNetworkDiagnosticsHelper(url.GetOrigin().spec());
271 void NetErrorTabHelper::RunNetworkDiagnosticsHelper(
272 const std::string& sanitized_url) {
273 ShowNetworkDiagnosticsDialog(web_contents(), sanitized_url);
276 } // namespace chrome_browser_net