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_INTRANET_REDIRECT_DETECTOR_H_
6#define CHROME_BROWSER_INTRANET_REDIRECT_DETECTOR_H_
7
8#include <set>
9#include <string>
10#include <vector>
11
12#include "base/memory/weak_ptr.h"
13#include "content/public/browser/notification_observer.h"
14#include "content/public/browser/notification_registrar.h"
15#include "net/base/network_change_notifier.h"
16#include "net/dns/host_resolver_proc.h"
17#include "net/url_request/url_fetcher_delegate.h"
18#include "url/gurl.h"
19
20class PrefRegistrySimple;
21
22// This object is responsible for determining whether the user is on a network
23// that redirects requests for intranet hostnames to another site, and if so,
24// tracking what that site is (including across restarts via a pref).  For
25// example, the user's ISP might convert a request for "http://query/" into a
26// 302 redirect to "http://isp.domain.com/search?q=query" in order to display
27// custom pages on typos, nonexistent sites, etc.
28//
29// We use this information in the OmniboxNavigationObserver to avoid displaying
30// infobars for these cases.  Our infobars are designed to allow users to get at
31// intranet sites when they were erroneously taken to a search result page.  In
32// these cases, however, users would be shown a confusing and useless infobar
33// when they really did mean to do a search.
34//
35// Consumers should call RedirectOrigin(), which is guaranteed to synchronously
36// return a value at all times (even during startup or in unittest mode).  If no
37// redirection is in place, the returned GURL will be empty.
38class IntranetRedirectDetector
39    : public net::URLFetcherDelegate,
40      public net::NetworkChangeNotifier::IPAddressObserver {
41 public:
42  // Only the main browser process loop should call this, when setting up
43  // g_browser_process->intranet_redirect_detector_.  No code other than the
44  // IntranetRedirectDetector itself should actually use
45  // g_browser_process->intranet_redirect_detector() (which shouldn't be hard,
46  // since there aren't useful public functions on this object for consumers to
47  // access anyway).
48  IntranetRedirectDetector();
49  virtual ~IntranetRedirectDetector();
50
51  // Returns the current redirect origin.  This will be empty if no redirection
52  // is in place.
53  static GURL RedirectOrigin();
54
55  static void RegisterPrefs(PrefRegistrySimple* registry);
56
57 private:
58  typedef std::set<net::URLFetcher*> Fetchers;
59
60  // Called when the seven second startup sleep or the one second network
61  // switch sleep has finished.  Runs any pending fetch.
62  void FinishSleep();
63
64  // net::URLFetcherDelegate
65  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
66
67  // NetworkChangeNotifier::IPAddressObserver
68  virtual void OnIPAddressChanged() OVERRIDE;
69
70  GURL redirect_origin_;
71  Fetchers fetchers_;
72  std::vector<GURL> resulting_origins_;
73  bool in_sleep_;  // True if we're in the seven-second "no fetching" period
74                   // that begins at browser start, or the one-second "no
75                   // fetching" period that begins after network switches.
76  base::WeakPtrFactory<IntranetRedirectDetector> weak_ptr_factory_;
77
78  DISALLOW_COPY_AND_ASSIGN(IntranetRedirectDetector);
79};
80
81#endif  // CHROME_BROWSER_INTRANET_REDIRECT_DETECTOR_H_
82