Update V8 to version 4.6.62.
[chromium-blink-merge.git] / components / google / core / browser / google_url_tracker.cc
blob2ead3643b3d199f29fef070df9d7c0abcfb9a9a4
1 // Copyright 2014 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 "components/google/core/browser/google_url_tracker.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/location.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/strings/string_util.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "components/google/core/browser/google_pref_names.h"
15 #include "components/google/core/browser/google_switches.h"
16 #include "components/google/core/browser/google_util.h"
17 #include "components/pref_registry/pref_registry_syncable.h"
18 #include "net/base/load_flags.h"
19 #include "net/url_request/url_fetcher.h"
20 #include "net/url_request/url_request_status.h"
23 const char GoogleURLTracker::kDefaultGoogleHomepage[] =
24 "https://www.google.com/";
25 const char GoogleURLTracker::kSearchDomainCheckURL[] =
26 "https://www.google.com/searchdomaincheck?format=domain&type=chrome";
28 GoogleURLTracker::GoogleURLTracker(scoped_ptr<GoogleURLTrackerClient> client,
29 Mode mode)
30 : client_(client.Pass()),
31 google_url_(mode == UNIT_TEST_MODE ?
32 kDefaultGoogleHomepage :
33 client_->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)),
34 fetcher_id_(0),
35 in_startup_sleep_(true),
36 already_fetched_(false),
37 need_to_fetch_(false),
38 weak_ptr_factory_(this) {
39 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
40 client_->set_google_url_tracker(this);
42 // Because this function can be called during startup, when kicking off a URL
43 // fetch can eat up 20 ms of time, we delay five seconds, which is hopefully
44 // long enough to be after startup, but still get results back quickly.
45 // Ideally, instead of this timer, we'd do something like "check if the
46 // browser is starting up, and if so, come back later", but there is currently
47 // no function to do this.
49 // In UNIT_TEST_MODE, where we want to explicitly control when the tracker
50 // "wakes up", we do nothing at all.
51 if (mode == NORMAL_MODE) {
52 static const int kStartFetchDelayMS = 5000;
53 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
54 FROM_HERE, base::Bind(&GoogleURLTracker::FinishSleep,
55 weak_ptr_factory_.GetWeakPtr()),
56 base::TimeDelta::FromMilliseconds(kStartFetchDelayMS));
60 GoogleURLTracker::~GoogleURLTracker() {
63 // static
64 void GoogleURLTracker::RegisterProfilePrefs(
65 user_prefs::PrefRegistrySyncable* registry) {
66 registry->RegisterStringPref(prefs::kLastKnownGoogleURL,
67 GoogleURLTracker::kDefaultGoogleHomepage);
68 registry->RegisterStringPref(prefs::kLastPromptedGoogleURL, std::string());
71 void GoogleURLTracker::RequestServerCheck(bool force) {
72 // If this instance already has a fetcher, SetNeedToFetch() is unnecessary,
73 // and changing |already_fetched_| is wrong.
74 if (!fetcher_) {
75 if (force)
76 already_fetched_ = false;
77 SetNeedToFetch();
81 scoped_ptr<GoogleURLTracker::Subscription> GoogleURLTracker::RegisterCallback(
82 const OnGoogleURLUpdatedCallback& cb) {
83 return callback_list_.Add(cb);
86 void GoogleURLTracker::OnURLFetchComplete(const net::URLFetcher* source) {
87 // Delete the fetcher on this function's exit.
88 scoped_ptr<net::URLFetcher> clean_up_fetcher(fetcher_.release());
90 // Don't update the URL if the request didn't succeed.
91 if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200)) {
92 already_fetched_ = false;
93 return;
96 // See if the response data was valid. It should be ".google.<TLD>".
97 std::string url_str;
98 source->GetResponseAsString(&url_str);
99 base::TrimWhitespace(url_str, base::TRIM_ALL, &url_str);
100 if (!base::StartsWith(url_str, ".google.",
101 base::CompareCase::INSENSITIVE_ASCII))
102 return;
103 GURL url("https://www" + url_str);
104 if (!url.is_valid() || (url.path().length() > 1) || url.has_query() ||
105 url.has_ref() ||
106 !google_util::IsGoogleDomainUrl(url, google_util::DISALLOW_SUBDOMAIN,
107 google_util::DISALLOW_NON_STANDARD_PORTS))
108 return;
110 if (url != google_url_) {
111 google_url_ = url;
112 client_->GetPrefs()->SetString(prefs::kLastKnownGoogleURL,
113 google_url_.spec());
114 callback_list_.Notify();
118 void GoogleURLTracker::OnNetworkChanged(
119 net::NetworkChangeNotifier::ConnectionType type) {
120 // Ignore destructive signals.
121 if (type == net::NetworkChangeNotifier::CONNECTION_NONE)
122 return;
123 already_fetched_ = false;
124 StartFetchIfDesirable();
127 void GoogleURLTracker::Shutdown() {
128 client_.reset();
129 fetcher_.reset();
130 weak_ptr_factory_.InvalidateWeakPtrs();
131 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
134 void GoogleURLTracker::SetNeedToFetch() {
135 need_to_fetch_ = true;
136 StartFetchIfDesirable();
139 void GoogleURLTracker::FinishSleep() {
140 in_startup_sleep_ = false;
141 StartFetchIfDesirable();
144 void GoogleURLTracker::StartFetchIfDesirable() {
145 // Bail if a fetch isn't appropriate right now. This function will be called
146 // again each time one of the preconditions changes, so we'll fetch
147 // immediately once all of them are met.
149 // See comments in header on the class, on RequestServerCheck(), and on the
150 // various members here for more detail on exactly what the conditions are.
151 if (in_startup_sleep_ || already_fetched_ || !need_to_fetch_)
152 return;
154 // Some switches should disable the Google URL tracker entirely. If we can't
155 // do background networking, we can't do the necessary fetch, and if the user
156 // specified a Google base URL manually, we shouldn't bother to look up any
157 // alternatives or offer to switch to them.
158 if (!client_->IsBackgroundNetworkingEnabled() ||
159 base::CommandLine::ForCurrentProcess()->HasSwitch(
160 switches::kGoogleBaseURL))
161 return;
163 already_fetched_ = true;
164 fetcher_ = net::URLFetcher::Create(fetcher_id_, GURL(kSearchDomainCheckURL),
165 net::URLFetcher::GET, this);
166 ++fetcher_id_;
167 // We don't want this fetch to set new entries in the cache or cookies, lest
168 // we alarm the user.
169 fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE |
170 net::LOAD_DO_NOT_SAVE_COOKIES);
171 fetcher_->SetRequestContext(client_->GetRequestContext());
173 // Configure to retry at most kMaxRetries times for 5xx errors.
174 static const int kMaxRetries = 5;
175 fetcher_->SetMaxRetriesOn5xx(kMaxRetries);
177 // Also retry kMaxRetries times on network change errors. A network change can
178 // propagate through Chrome in various stages, so it's possible for this code
179 // to be reached via OnNetworkChanged(), and then have the fetch we kick off
180 // be canceled due to e.g. the DNS server changing at a later time. In general
181 // it's not possible to ensure that by the time we reach here any requests we
182 // start won't be canceled in this fashion, so retrying is the best we can do.
183 fetcher_->SetAutomaticallyRetryOnNetworkChanges(kMaxRetries);
185 fetcher_->Start();