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