Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(467)

Side by Side Diff: components/google/core/browser/google_url_tracker.cc

Issue 808253006: Remove the GoogleURLTracker infobar functionality entirely. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Compile fixes Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/google/core/browser/google_url_tracker.h" 5 #include "components/google/core/browser/google_url_tracker.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/prefs/pref_service.h" 9 #include "base/prefs/pref_service.h"
10 #include "base/strings/string_util.h" 10 #include "base/strings/string_util.h"
11 #include "components/google/core/browser/google_pref_names.h" 11 #include "components/google/core/browser/google_pref_names.h"
12 #include "components/google/core/browser/google_switches.h" 12 #include "components/google/core/browser/google_switches.h"
13 #include "components/google/core/browser/google_url_tracker_infobar_delegate.h"
14 #include "components/google/core/browser/google_url_tracker_navigation_helper.h"
15 #include "components/google/core/browser/google_util.h" 13 #include "components/google/core/browser/google_util.h"
16 #include "components/infobars/core/infobar.h"
17 #include "components/infobars/core/infobar_manager.h"
18 #include "net/base/load_flags.h" 14 #include "net/base/load_flags.h"
19 #include "net/base/net_util.h"
20 #include "net/url_request/url_fetcher.h" 15 #include "net/url_request/url_fetcher.h"
21 #include "net/url_request/url_request_status.h" 16 #include "net/url_request/url_request_status.h"
22 17
23 18
24 const char GoogleURLTracker::kDefaultGoogleHomepage[] = 19 const char GoogleURLTracker::kDefaultGoogleHomepage[] =
25 "http://www.google.com/"; 20 "http://www.google.com/";
26 const char GoogleURLTracker::kSearchDomainCheckURL[] = 21 const char GoogleURLTracker::kSearchDomainCheckURL[] =
27 "https://www.google.com/searchdomaincheck?format=url&type=chrome"; 22 "https://www.google.com/searchdomaincheck?format=url&type=chrome";
28 23
29 GoogleURLTracker::GoogleURLTracker(scoped_ptr<GoogleURLTrackerClient> client, 24 GoogleURLTracker::GoogleURLTracker(scoped_ptr<GoogleURLTrackerClient> client,
30 Mode mode) 25 Mode mode)
31 : client_(client.Pass()), 26 : client_(client.Pass()),
32 google_url_(mode == UNIT_TEST_MODE ? 27 google_url_(mode == UNIT_TEST_MODE ?
33 kDefaultGoogleHomepage : 28 kDefaultGoogleHomepage :
34 client_->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)), 29 client_->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)),
35 fetcher_id_(0), 30 fetcher_id_(0),
36 in_startup_sleep_(true), 31 in_startup_sleep_(true),
37 already_fetched_(false), 32 already_fetched_(false),
38 need_to_fetch_(false), 33 need_to_fetch_(false),
39 need_to_prompt_(false),
40 search_committed_(false),
41 weak_ptr_factory_(this) { 34 weak_ptr_factory_(this) {
42 net::NetworkChangeNotifier::AddNetworkChangeObserver(this); 35 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
43 client_->set_google_url_tracker(this); 36 client_->set_google_url_tracker(this);
44 37
45 // Because this function can be called during startup, when kicking off a URL 38 // Because this function can be called during startup, when kicking off a URL
46 // fetch can eat up 20 ms of time, we delay five seconds, which is hopefully 39 // fetch can eat up 20 ms of time, we delay five seconds, which is hopefully
47 // long enough to be after startup, but still get results back quickly. 40 // long enough to be after startup, but still get results back quickly.
48 // Ideally, instead of this timer, we'd do something like "check if the 41 // Ideally, instead of this timer, we'd do something like "check if the
49 // browser is starting up, and if so, come back later", but there is currently 42 // browser is starting up, and if so, come back later", but there is currently
50 // no function to do this. 43 // no function to do this.
51 // 44 //
52 // In UNIT_TEST_MODE, where we want to explicitly control when the tracker 45 // In UNIT_TEST_MODE, where we want to explicitly control when the tracker
53 // "wakes up", we do nothing at all. 46 // "wakes up", we do nothing at all.
54 if (mode == NORMAL_MODE) { 47 if (mode == NORMAL_MODE) {
55 static const int kStartFetchDelayMS = 5000; 48 static const int kStartFetchDelayMS = 5000;
56 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, 49 base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
57 base::Bind(&GoogleURLTracker::FinishSleep, 50 base::Bind(&GoogleURLTracker::FinishSleep,
58 weak_ptr_factory_.GetWeakPtr()), 51 weak_ptr_factory_.GetWeakPtr()),
59 base::TimeDelta::FromMilliseconds(kStartFetchDelayMS)); 52 base::TimeDelta::FromMilliseconds(kStartFetchDelayMS));
60 } 53 }
61 } 54 }
62 55
63 GoogleURLTracker::~GoogleURLTracker() { 56 GoogleURLTracker::~GoogleURLTracker() {
64 // We should only reach here after any tabs and their infobars have been torn
65 // down.
66 DCHECK(entry_map_.empty());
67 } 57 }
68 58
69 void GoogleURLTracker::RequestServerCheck(bool force) { 59 void GoogleURLTracker::RequestServerCheck(bool force) {
70 // If this instance already has a fetcher, SetNeedToFetch() is unnecessary, 60 // If this instance already has a fetcher, SetNeedToFetch() is unnecessary,
71 // and changing |already_fetched_| is wrong. 61 // and changing |already_fetched_| is wrong.
72 if (!fetcher_) { 62 if (!fetcher_) {
73 if (force) 63 if (force)
74 already_fetched_ = false; 64 already_fetched_ = false;
75 SetNeedToFetch(); 65 SetNeedToFetch();
76 } 66 }
77 } 67 }
78 68
79 void GoogleURLTracker::SearchCommitted() { 69 scoped_ptr<GoogleURLTracker::Subscription> GoogleURLTracker::RegisterCallback(
80 if (need_to_prompt_) { 70 const OnGoogleURLUpdatedCallback& cb) {
81 search_committed_ = true; 71 return callback_list_.Add(cb);
Peter Kasting 2014/12/20 02:18:07 Same code as before, just moved up here to match t
82 // These notifications will fire a bit later in the same call chain we're
83 // currently in.
84 if (!client_->IsListeningForNavigationStart())
85 client_->SetListeningForNavigationStart(true);
86 }
87 }
88
89 void GoogleURLTracker::AcceptGoogleURL(bool redo_searches) {
90 GURL old_google_url = google_url_;
91 google_url_ = fetched_google_url_;
92 PrefService* prefs = client_->GetPrefs();
93 prefs->SetString(prefs::kLastKnownGoogleURL, google_url_.spec());
94 prefs->SetString(prefs::kLastPromptedGoogleURL, google_url_.spec());
95 NotifyGoogleURLUpdated();
96
97 need_to_prompt_ = false;
98 CloseAllEntries(redo_searches);
99 }
100
101 void GoogleURLTracker::CancelGoogleURL() {
102 client_->GetPrefs()->SetString(prefs::kLastPromptedGoogleURL,
103 fetched_google_url_.spec());
104 need_to_prompt_ = false;
105 CloseAllEntries(false);
106 } 72 }
107 73
108 void GoogleURLTracker::OnURLFetchComplete(const net::URLFetcher* source) { 74 void GoogleURLTracker::OnURLFetchComplete(const net::URLFetcher* source) {
109 // Delete the fetcher on this function's exit. 75 // Delete the fetcher on this function's exit.
110 scoped_ptr<net::URLFetcher> clean_up_fetcher(fetcher_.release()); 76 scoped_ptr<net::URLFetcher> clean_up_fetcher(fetcher_.release());
111 77
112 // Don't update the URL if the request didn't succeed. 78 // Don't update the URL if the request didn't succeed.
113 if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200)) { 79 if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200)) {
114 already_fetched_ = false; 80 already_fetched_ = false;
115 return; 81 return;
116 } 82 }
117 83
118 // See if the response data was valid. It should be 84 // See if the response data was valid. It should be
119 // "<scheme>://[www.]google.<TLD>/". 85 // "<scheme>://[www.]google.<TLD>/".
120 std::string url_str; 86 std::string url_str;
121 source->GetResponseAsString(&url_str); 87 source->GetResponseAsString(&url_str);
122 base::TrimWhitespace(url_str, base::TRIM_ALL, &url_str); 88 base::TrimWhitespace(url_str, base::TRIM_ALL, &url_str);
123 GURL url(url_str); 89 GURL url(url_str);
124 if (!url.is_valid() || (url.path().length() > 1) || url.has_query() || 90 if (!url.is_valid() || (url.path().length() > 1) || url.has_query() ||
125 url.has_ref() || 91 url.has_ref() ||
126 !google_util::IsGoogleDomainUrl(url, 92 !google_util::IsGoogleDomainUrl(url,
127 google_util::DISALLOW_SUBDOMAIN, 93 google_util::DISALLOW_SUBDOMAIN,
128 google_util::DISALLOW_NON_STANDARD_PORTS)) 94 google_util::DISALLOW_NON_STANDARD_PORTS))
129 return; 95 return;
130 96
131 std::swap(url, fetched_google_url_); 97 if (url != google_url_) {
132 GURL last_prompted_url( 98 google_url_ = url;
133 client_->GetPrefs()->GetString(prefs::kLastPromptedGoogleURL)); 99 client_->GetPrefs()->SetString(prefs::kLastKnownGoogleURL,
134 100 google_url_.spec());
135 if (last_prompted_url.is_empty()) { 101 callback_list_.Notify();
136 // On the very first run of Chrome, when we've never looked up the URL at
137 // all, we should just silently switch over to whatever we get immediately.
138 AcceptGoogleURL(true); // Arg is irrelevant.
139 return;
140 }
141
142 base::string16 fetched_host(net::StripWWWFromHost(fetched_google_url_));
143 if (fetched_google_url_ == google_url_) {
144 // Either the user has continually been on this URL, or we prompted for a
145 // different URL but have now changed back before they responded to any of
146 // the prompts. In this latter case we want to close any infobars and stop
147 // prompting.
148 CancelGoogleURL();
149 } else if (fetched_host == net::StripWWWFromHost(google_url_)) {
150 // Similar to the above case, but this time the new URL differs from the
151 // existing one, probably due to switching between HTTP and HTTPS searching.
152 // Like before we want to close any infobars and stop prompting; we also
153 // want to silently accept the change in scheme. We don't redo open
154 // searches so as to avoid suddenly changing a page the user might be
155 // interacting with; it's enough to simply get future searches right.
156 AcceptGoogleURL(false);
157 } else if (fetched_host == net::StripWWWFromHost(last_prompted_url)) {
158 // We've re-fetched a TLD the user previously turned down. Although the new
159 // URL might have a different scheme than the old, we want to preserve the
160 // user's decision. Note that it's possible that, like in the above two
161 // cases, we fetched yet another different URL in the meantime, which we
162 // have infobars prompting about; in this case, as in those above, we want
163 // to go ahead and close the infobars and stop prompting, since we've
164 // switched back away from that URL.
165 CancelGoogleURL();
166 } else {
167 // We've fetched a URL with a different TLD than the user is currently using
168 // or was previously prompted about. This means we need to prompt again.
169 need_to_prompt_ = true;
170
171 // As in all the above cases, there could be infobars prompting about some
172 // URL. If these URLs have the same TLD (e.g. for scheme changes), we can
173 // simply leave the existing infobars open as their messages will still be
174 // accurate. Otherwise we go ahead and close them because we need to
175 // display a new message.
176 // Note: |url| is the previous |fetched_google_url_|.
177 if (url.is_valid() && (fetched_host != net::StripWWWFromHost(url)))
178 CloseAllEntries(false);
179 } 102 }
180 } 103 }
181 104
182 void GoogleURLTracker::OnNetworkChanged( 105 void GoogleURLTracker::OnNetworkChanged(
183 net::NetworkChangeNotifier::ConnectionType type) { 106 net::NetworkChangeNotifier::ConnectionType type) {
184 // Ignore destructive signals. 107 // Ignore destructive signals.
185 if (type == net::NetworkChangeNotifier::CONNECTION_NONE) 108 if (type == net::NetworkChangeNotifier::CONNECTION_NONE)
186 return; 109 return;
187 already_fetched_ = false; 110 already_fetched_ = false;
188 StartFetchIfDesirable(); 111 StartFetchIfDesirable();
189 } 112 }
190 113
191 void GoogleURLTracker::Shutdown() { 114 void GoogleURLTracker::Shutdown() {
192 client_.reset(); 115 client_.reset();
193 fetcher_.reset(); 116 fetcher_.reset();
194 weak_ptr_factory_.InvalidateWeakPtrs(); 117 weak_ptr_factory_.InvalidateWeakPtrs();
195 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); 118 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
196 } 119 }
197 120
198 void GoogleURLTracker::DeleteMapEntryForManager(
199 const infobars::InfoBarManager* infobar_manager) {
200 // WARNING: |infobar_manager| may point to a deleted object. Do not
201 // dereference it! See OnTabClosed().
202 EntryMap::iterator i(entry_map_.find(infobar_manager));
203 DCHECK(i != entry_map_.end());
204 GoogleURLTrackerMapEntry* map_entry = i->second;
205
206 UnregisterForEntrySpecificNotifications(map_entry, false);
207 entry_map_.erase(i);
208 delete map_entry;
209 }
210
211 void GoogleURLTracker::SetNeedToFetch() { 121 void GoogleURLTracker::SetNeedToFetch() {
212 need_to_fetch_ = true; 122 need_to_fetch_ = true;
213 StartFetchIfDesirable(); 123 StartFetchIfDesirable();
214 } 124 }
215 125
216 void GoogleURLTracker::FinishSleep() { 126 void GoogleURLTracker::FinishSleep() {
217 in_startup_sleep_ = false; 127 in_startup_sleep_ = false;
218 StartFetchIfDesirable(); 128 StartFetchIfDesirable();
219 } 129 }
220 130
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 // Also retry kMaxRetries times on network change errors. A network change can 164 // Also retry kMaxRetries times on network change errors. A network change can
255 // propagate through Chrome in various stages, so it's possible for this code 165 // propagate through Chrome in various stages, so it's possible for this code
256 // to be reached via OnNetworkChanged(), and then have the fetch we kick off 166 // to be reached via OnNetworkChanged(), and then have the fetch we kick off
257 // be canceled due to e.g. the DNS server changing at a later time. In general 167 // be canceled due to e.g. the DNS server changing at a later time. In general
258 // it's not possible to ensure that by the time we reach here any requests we 168 // it's not possible to ensure that by the time we reach here any requests we
259 // start won't be canceled in this fashion, so retrying is the best we can do. 169 // start won't be canceled in this fashion, so retrying is the best we can do.
260 fetcher_->SetAutomaticallyRetryOnNetworkChanges(kMaxRetries); 170 fetcher_->SetAutomaticallyRetryOnNetworkChanges(kMaxRetries);
261 171
262 fetcher_->Start(); 172 fetcher_->Start();
263 } 173 }
264
265 void GoogleURLTracker::OnNavigationPending(
266 scoped_ptr<GoogleURLTrackerNavigationHelper> nav_helper,
267 infobars::InfoBarManager* infobar_manager,
268 int pending_id) {
269 GoogleURLTrackerMapEntry* map_entry = NULL;
270
271 EntryMap::iterator i(entry_map_.find(infobar_manager));
272 if (i != entry_map_.end())
273 map_entry = i->second;
274
275 if (search_committed_) {
276 search_committed_ = false;
277 if (!map_entry) {
278 // This is a search on a tab that doesn't have one of our infobars, so
279 // prepare to add one. Note that we only listen for the tab's destruction
280 // on this path; if there was already a map entry, then either it doesn't
281 // yet have an infobar and we're already registered for this, or it has an
282 // infobar and the infobar's owner will handle tearing it down when the
283 // tab is destroyed.
284 map_entry = new GoogleURLTrackerMapEntry(
285 this, infobar_manager, nav_helper.Pass());
286 map_entry->navigation_helper()->SetListeningForTabDestruction(true);
287 entry_map_.insert(std::make_pair(infobar_manager, map_entry));
288 } else if (map_entry->infobar_delegate()) {
289 // This is a new search on a tab where we already have an infobar.
290 map_entry->infobar_delegate()->set_pending_id(pending_id);
291 }
292
293 // Whether there's an existing infobar or not, we need to listen for the
294 // load to commit, so we can show and/or update the infobar when it does.
295 // (We may already be registered for this if there is an existing infobar
296 // that had a previous pending search that hasn't yet committed.)
297 if (!map_entry->navigation_helper()->IsListeningForNavigationCommit())
298 map_entry->navigation_helper()->SetListeningForNavigationCommit(true);
299 } else if (map_entry) {
300 if (map_entry->has_infobar_delegate()) {
301 // This is a non-search navigation on a tab with an infobar. If there was
302 // a previous pending search on this tab, this means it won't commit, so
303 // undo anything we did in response to seeing that. Note that if there
304 // was no pending search on this tab, these statements are effectively a
305 // no-op.
306 //
307 // If this navigation actually commits, that will trigger the infobar's
308 // owner to expire the infobar if need be. If it doesn't commit, then
309 // simply leaving the infobar as-is will have been the right thing.
310 UnregisterForEntrySpecificNotifications(map_entry, false);
311 map_entry->infobar_delegate()->set_pending_id(0);
312 } else {
313 // Non-search navigation on a tab with an entry that has not yet created
314 // an infobar. This means the original search won't commit, so delete the
315 // entry.
316 map_entry->Close(false);
317 }
318 } else {
319 // Non-search navigation on a tab without an infobars. This is irrelevant
320 // to us.
321 }
322 }
323
324 void GoogleURLTracker::OnNavigationCommitted(
325 infobars::InfoBarManager* infobar_manager,
326 const GURL& search_url) {
327 EntryMap::iterator i(entry_map_.find(infobar_manager));
328 DCHECK(i != entry_map_.end());
329 GoogleURLTrackerMapEntry* map_entry = i->second;
330 DCHECK(search_url.is_valid());
331
332 UnregisterForEntrySpecificNotifications(map_entry, true);
333 if (map_entry->has_infobar_delegate()) {
334 map_entry->infobar_delegate()->Update(search_url);
335 } else {
336 infobars::InfoBar* infobar = GoogleURLTrackerInfoBarDelegate::Create(
337 infobar_manager, this, search_url);
338 if (infobar) {
339 map_entry->SetInfoBarDelegate(
340 static_cast<GoogleURLTrackerInfoBarDelegate*>(infobar->delegate()));
341 } else {
342 map_entry->Close(false);
343 }
344 }
345 }
346
347 void GoogleURLTracker::OnTabClosed(
348 GoogleURLTrackerNavigationHelper* nav_helper) {
349 // Because InfoBarManager tears itself down on tab destruction, it's possible
350 // to get a non-NULL InfoBarManager pointer here, depending on which order
351 // notifications fired in. Likewise, the pointer in |entry_map_| (and in its
352 // associated MapEntry) may point to deleted memory. Therefore, if we were
353 // to access the InfoBarManager* we have for this tab, we'd need to ensure we
354 // just looked at the raw pointer value, and never dereferenced it. This
355 // function doesn't need to do even that, but others in the call chain from
356 // here might (and have comments pointing back here).
357 for (EntryMap::iterator i(entry_map_.begin()); i != entry_map_.end(); ++i) {
358 if (i->second->navigation_helper() == nav_helper) {
359 i->second->Close(false);
360 return;
361 }
362 }
363 NOTREACHED();
364 }
365
366 scoped_ptr<GoogleURLTracker::Subscription> GoogleURLTracker::RegisterCallback(
367 const OnGoogleURLUpdatedCallback& cb) {
368 return callback_list_.Add(cb);
369 }
370
371 void GoogleURLTracker::CloseAllEntries(bool redo_searches) {
372 // Delete all entries, whether they have infobars or not.
373 while (!entry_map_.empty())
374 entry_map_.begin()->second->Close(redo_searches);
375 }
376
377 void GoogleURLTracker::UnregisterForEntrySpecificNotifications(
378 GoogleURLTrackerMapEntry* map_entry,
379 bool must_be_listening_for_commit) {
380 // For tabs with map entries but no infobars, we should always be listening
381 // for both these notifications. For tabs with infobars, we may be listening
382 // for navigation commits if the user has performed a new search on this tab.
383 if (map_entry->navigation_helper()->IsListeningForNavigationCommit()) {
384 map_entry->navigation_helper()->SetListeningForNavigationCommit(false);
385 } else {
386 DCHECK(!must_be_listening_for_commit);
387 DCHECK(map_entry->has_infobar_delegate());
388 }
389 const bool registered_for_tab_destruction =
390 map_entry->navigation_helper()->IsListeningForTabDestruction();
391 DCHECK_NE(registered_for_tab_destruction, map_entry->has_infobar_delegate());
392 if (registered_for_tab_destruction) {
393 map_entry->navigation_helper()->SetListeningForTabDestruction(false);
394 }
395
396 // Our global listeners for these other notifications should be in place iff
397 // we have any tabs still listening for commits. These tabs either have no
398 // infobars or have received new pending searches atop existing infobars; in
399 // either case we want to catch subsequent pending non-search navigations.
400 // See the various cases inside OnNavigationPending().
401 for (EntryMap::const_iterator i(entry_map_.begin()); i != entry_map_.end();
402 ++i) {
403 if (i->second->navigation_helper()->IsListeningForNavigationCommit()) {
404 DCHECK(client_->IsListeningForNavigationStart());
405 return;
406 }
407 }
408 if (client_->IsListeningForNavigationStart()) {
409 DCHECK(!search_committed_);
410 client_->SetListeningForNavigationStart(false);
411 }
412 }
413
414 void GoogleURLTracker::NotifyGoogleURLUpdated() {
415 callback_list_.Notify();
416 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698