OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/google/google_url_tracker.h" | 5 #include "chrome/browser/google/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" |
(...skipping 15 matching lines...) Expand all Loading... | |
26 #include "net/base/net_util.h" | 26 #include "net/base/net_util.h" |
27 #include "net/url_request/url_fetcher.h" | 27 #include "net/url_request/url_fetcher.h" |
28 #include "net/url_request/url_request_status.h" | 28 #include "net/url_request/url_request_status.h" |
29 | 29 |
30 | 30 |
31 const char GoogleURLTracker::kDefaultGoogleHomepage[] = | 31 const char GoogleURLTracker::kDefaultGoogleHomepage[] = |
32 "http://www.google.com/"; | 32 "http://www.google.com/"; |
33 const char GoogleURLTracker::kSearchDomainCheckURL[] = | 33 const char GoogleURLTracker::kSearchDomainCheckURL[] = |
34 "https://www.google.com/searchdomaincheck?format=url&type=chrome"; | 34 "https://www.google.com/searchdomaincheck?format=url&type=chrome"; |
35 | 35 |
36 GoogleURLTracker::GoogleURLTracker( | 36 GoogleURLTracker::GoogleURLTracker(Profile* profile, |
37 Profile* profile, | 37 scoped_ptr<GoogleURLTrackerClient> client, |
38 scoped_ptr<GoogleURLTrackerClient> client, | 38 Mode mode) |
39 scoped_ptr<GoogleURLTrackerNavigationHelper> nav_helper, | |
40 Mode mode) | |
41 : profile_(profile), | 39 : profile_(profile), |
42 client_(client.Pass()), | 40 client_(client.Pass()), |
43 nav_helper_(nav_helper.Pass()), | |
44 infobar_creator_(base::Bind(&GoogleURLTrackerInfoBarDelegate::Create)), | 41 infobar_creator_(base::Bind(&GoogleURLTrackerInfoBarDelegate::Create)), |
45 google_url_(mode == UNIT_TEST_MODE ? kDefaultGoogleHomepage : | 42 google_url_(mode == UNIT_TEST_MODE ? kDefaultGoogleHomepage |
46 profile->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)), | 43 : profile->GetPrefs()->GetString( |
44 prefs::kLastKnownGoogleURL)), | |
Peter Kasting
2014/05/15 21:29:52
Nit: Wrap like this:
google_url_((mode == U
blundell
2014/05/16 11:54:18
Done.
| |
47 fetcher_id_(0), | 45 fetcher_id_(0), |
48 in_startup_sleep_(true), | 46 in_startup_sleep_(true), |
49 already_fetched_(false), | 47 already_fetched_(false), |
50 need_to_fetch_(false), | 48 need_to_fetch_(false), |
51 need_to_prompt_(false), | 49 need_to_prompt_(false), |
52 search_committed_(false), | 50 search_committed_(false), |
53 weak_ptr_factory_(this) { | 51 weak_ptr_factory_(this) { |
54 net::NetworkChangeNotifier::AddIPAddressObserver(this); | 52 net::NetworkChangeNotifier::AddIPAddressObserver(this); |
55 client_->set_google_url_tracker(this); | 53 client_->set_google_url_tracker(this); |
56 nav_helper_->SetGoogleURLTracker(this); | |
57 | 54 |
58 // Because this function can be called during startup, when kicking off a URL | 55 // Because this function can be called during startup, when kicking off a URL |
59 // fetch can eat up 20 ms of time, we delay five seconds, which is hopefully | 56 // fetch can eat up 20 ms of time, we delay five seconds, which is hopefully |
60 // long enough to be after startup, but still get results back quickly. | 57 // long enough to be after startup, but still get results back quickly. |
61 // Ideally, instead of this timer, we'd do something like "check if the | 58 // Ideally, instead of this timer, we'd do something like "check if the |
62 // browser is starting up, and if so, come back later", but there is currently | 59 // browser is starting up, and if so, come back later", but there is currently |
63 // no function to do this. | 60 // no function to do this. |
64 // | 61 // |
65 // In UNIT_TEST mode, where we want to explicitly control when the tracker | 62 // In UNIT_TEST mode, where we want to explicitly control when the tracker |
66 // "wakes up", we do nothing at all. | 63 // "wakes up", we do nothing at all. |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
199 } | 196 } |
200 } | 197 } |
201 | 198 |
202 void GoogleURLTracker::OnIPAddressChanged() { | 199 void GoogleURLTracker::OnIPAddressChanged() { |
203 already_fetched_ = false; | 200 already_fetched_ = false; |
204 StartFetchIfDesirable(); | 201 StartFetchIfDesirable(); |
205 } | 202 } |
206 | 203 |
207 void GoogleURLTracker::Shutdown() { | 204 void GoogleURLTracker::Shutdown() { |
208 client_.reset(); | 205 client_.reset(); |
209 nav_helper_.reset(); | |
210 fetcher_.reset(); | 206 fetcher_.reset(); |
211 weak_ptr_factory_.InvalidateWeakPtrs(); | 207 weak_ptr_factory_.InvalidateWeakPtrs(); |
212 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); | 208 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); |
213 } | 209 } |
214 | 210 |
215 void GoogleURLTracker::DeleteMapEntryForService( | 211 void GoogleURLTracker::DeleteMapEntryForService( |
216 const InfoBarService* infobar_service) { | 212 const InfoBarService* infobar_service) { |
217 // WARNING: |infobar_service| may point to a deleted object. Do not | 213 // WARNING: |infobar_service| may point to a deleted object. Do not |
218 // dereference it! See OnTabClosed(). | 214 // dereference it! See OnTabClosed(). |
219 EntryMap::iterator i(entry_map_.find(infobar_service)); | 215 EntryMap::iterator i(entry_map_.find(infobar_service)); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
275 if (need_to_prompt_) { | 271 if (need_to_prompt_) { |
276 search_committed_ = true; | 272 search_committed_ = true; |
277 // These notifications will fire a bit later in the same call chain we're | 273 // These notifications will fire a bit later in the same call chain we're |
278 // currently in. | 274 // currently in. |
279 if (!client_->IsListeningForNavigationStart()) | 275 if (!client_->IsListeningForNavigationStart()) |
280 client_->SetListeningForNavigationStart(true); | 276 client_->SetListeningForNavigationStart(true); |
281 } | 277 } |
282 } | 278 } |
283 | 279 |
284 void GoogleURLTracker::OnNavigationPending( | 280 void GoogleURLTracker::OnNavigationPending( |
285 content::NavigationController* navigation_controller, | 281 GoogleURLTrackerNavigationHelper* nav_helper, |
286 InfoBarService* infobar_service, | 282 InfoBarService* infobar_service, |
287 int pending_id) { | 283 int pending_id) { |
288 EntryMap::iterator i(entry_map_.find(infobar_service)); | 284 EntryMap::iterator i(entry_map_.find(infobar_service)); |
289 | 285 |
290 if (search_committed_) { | 286 if (search_committed_) { |
291 search_committed_ = false; | 287 search_committed_ = false; |
292 // Whether there's an existing infobar or not, we need to listen for the | 288 // Whether there's an existing infobar or not, we need to listen for the |
293 // load to commit, so we can show and/or update the infobar when it does. | 289 // load to commit, so we can show and/or update the infobar when it does. |
294 // (We may already be registered for this if there is an existing infobar | 290 // (We may already be registered for this if there is an existing infobar |
295 // that had a previous pending search that hasn't yet committed.) | 291 // that had a previous pending search that hasn't yet committed.) |
296 if (!nav_helper_->IsListeningForNavigationCommit(navigation_controller)) { | 292 if (!nav_helper->IsListeningForNavigationCommit()) { |
297 nav_helper_->SetListeningForNavigationCommit(navigation_controller, | 293 nav_helper->SetListeningForNavigationCommit(true); |
298 true); | |
299 } | 294 } |
300 if (i == entry_map_.end()) { | 295 if (i == entry_map_.end()) { |
301 // This is a search on a tab that doesn't have one of our infobars, so | 296 // This is a search on a tab that doesn't have one of our infobars, so |
302 // prepare to add one. Note that we only listen for the tab's destruction | 297 // prepare to add one. Note that we only listen for the tab's destruction |
303 // on this path; if there was already a map entry, then either it doesn't | 298 // on this path; if there was already a map entry, then either it doesn't |
304 // yet have an infobar and we're already registered for this, or it has an | 299 // yet have an infobar and we're already registered for this, or it has an |
305 // infobar and the infobar's owner will handle tearing it down when the | 300 // infobar and the infobar's owner will handle tearing it down when the |
306 // tab is destroyed. | 301 // tab is destroyed. |
307 nav_helper_->SetListeningForTabDestruction(navigation_controller, true); | 302 nav_helper->SetListeningForTabDestruction(true); |
308 entry_map_.insert(std::make_pair( | 303 entry_map_.insert(std::make_pair( |
309 infobar_service, | 304 infobar_service, |
310 new GoogleURLTrackerMapEntry(this, infobar_service, | 305 new GoogleURLTrackerMapEntry(this, infobar_service, nav_helper))); |
311 navigation_controller))); | |
312 } else if (i->second->has_infobar_delegate()) { | 306 } else if (i->second->has_infobar_delegate()) { |
313 // This is a new search on a tab where we already have an infobar. | 307 // This is a new search on a tab where we already have an infobar. |
314 i->second->infobar_delegate()->set_pending_id(pending_id); | 308 i->second->infobar_delegate()->set_pending_id(pending_id); |
315 } | 309 } |
316 } else if (i != entry_map_.end()){ | 310 } else if (i != entry_map_.end()){ |
317 if (i->second->has_infobar_delegate()) { | 311 if (i->second->has_infobar_delegate()) { |
318 // This is a non-search navigation on a tab with an infobar. If there was | 312 // This is a non-search navigation on a tab with an infobar. If there was |
319 // a previous pending search on this tab, this means it won't commit, so | 313 // a previous pending search on this tab, this means it won't commit, so |
320 // undo anything we did in response to seeing that. Note that if there | 314 // undo anything we did in response to seeing that. Note that if there |
321 // was no pending search on this tab, these statements are effectively a | 315 // was no pending search on this tab, these statements are effectively a |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
354 if (infobar) { | 348 if (infobar) { |
355 map_entry->SetInfoBarDelegate( | 349 map_entry->SetInfoBarDelegate( |
356 static_cast<GoogleURLTrackerInfoBarDelegate*>(infobar->delegate())); | 350 static_cast<GoogleURLTrackerInfoBarDelegate*>(infobar->delegate())); |
357 } else { | 351 } else { |
358 map_entry->Close(false); | 352 map_entry->Close(false); |
359 } | 353 } |
360 } | 354 } |
361 } | 355 } |
362 | 356 |
363 void GoogleURLTracker::OnTabClosed( | 357 void GoogleURLTracker::OnTabClosed( |
364 content::NavigationController* navigation_controller) { | 358 GoogleURLTrackerNavigationHelper* nav_helper) { |
365 // Because InfoBarService tears itself down on tab destruction, it's possible | 359 // Because InfoBarService tears itself down on tab destruction, it's possible |
366 // to get a non-NULL InfoBarService pointer here, depending on which order | 360 // to get a non-NULL InfoBarService pointer here, depending on which order |
367 // notifications fired in. Likewise, the pointer in |entry_map_| (and in its | 361 // notifications fired in. Likewise, the pointer in |entry_map_| (and in its |
368 // associated MapEntry) may point to deleted memory. Therefore, if we were to | 362 // associated MapEntry) may point to deleted memory. Therefore, if we were to |
369 // access the InfoBarService* we have for this tab, we'd need to ensure we | 363 // access the InfoBarService* we have for this tab, we'd need to ensure we |
370 // just looked at the raw pointer value, and never dereferenced it. This | 364 // just looked at the raw pointer value, and never dereferenced it. This |
371 // function doesn't need to do even that, but others in the call chain from | 365 // function doesn't need to do even that, but others in the call chain from |
372 // here might (and have comments pointing back here). | 366 // here might (and have comments pointing back here). |
373 for (EntryMap::iterator i(entry_map_.begin()); i != entry_map_.end(); ++i) { | 367 for (EntryMap::iterator i(entry_map_.begin()); i != entry_map_.end(); ++i) { |
374 if (i->second->navigation_controller() == navigation_controller) { | 368 if (i->second->navigation_helper() == nav_helper) { |
375 i->second->Close(false); | 369 i->second->Close(false); |
376 return; | 370 return; |
377 } | 371 } |
378 } | 372 } |
379 NOTREACHED(); | 373 NOTREACHED(); |
380 } | 374 } |
381 | 375 |
382 void GoogleURLTracker::CloseAllEntries(bool redo_searches) { | 376 void GoogleURLTracker::CloseAllEntries(bool redo_searches) { |
383 // Delete all entries, whether they have infobars or not. | 377 // Delete all entries, whether they have infobars or not. |
384 while (!entry_map_.empty()) | 378 while (!entry_map_.empty()) |
385 entry_map_.begin()->second->Close(redo_searches); | 379 entry_map_.begin()->second->Close(redo_searches); |
386 } | 380 } |
387 | 381 |
388 void GoogleURLTracker::UnregisterForEntrySpecificNotifications( | 382 void GoogleURLTracker::UnregisterForEntrySpecificNotifications( |
389 const GoogleURLTrackerMapEntry& map_entry, | 383 GoogleURLTrackerMapEntry& map_entry, |
390 bool must_be_listening_for_commit) { | 384 bool must_be_listening_for_commit) { |
391 // For tabs with map entries but no infobars, we should always be listening | 385 // For tabs with map entries but no infobars, we should always be listening |
392 // for both these notifications. For tabs with infobars, we may be listening | 386 // for both these notifications. For tabs with infobars, we may be listening |
393 // for navigation commits if the user has performed a new search on this tab. | 387 // for navigation commits if the user has performed a new search on this tab. |
394 if (nav_helper_->IsListeningForNavigationCommit( | 388 if (map_entry.navigation_helper()->IsListeningForNavigationCommit()) { |
blundell
2014/05/15 15:24:14
This is the core of the change: rather than there
| |
395 map_entry.navigation_controller())) { | 389 map_entry.navigation_helper()->SetListeningForNavigationCommit(false); |
396 nav_helper_->SetListeningForNavigationCommit( | |
397 map_entry.navigation_controller(), false); | |
398 } else { | 390 } else { |
399 DCHECK(!must_be_listening_for_commit); | 391 DCHECK(!must_be_listening_for_commit); |
400 DCHECK(map_entry.has_infobar_delegate()); | 392 DCHECK(map_entry.has_infobar_delegate()); |
401 } | 393 } |
402 const bool registered_for_tab_destruction = | 394 const bool registered_for_tab_destruction = |
403 nav_helper_->IsListeningForTabDestruction( | 395 map_entry.navigation_helper()->IsListeningForTabDestruction(); |
404 map_entry.navigation_controller()); | |
405 DCHECK_NE(registered_for_tab_destruction, map_entry.has_infobar_delegate()); | 396 DCHECK_NE(registered_for_tab_destruction, map_entry.has_infobar_delegate()); |
406 if (registered_for_tab_destruction) { | 397 if (registered_for_tab_destruction) { |
407 nav_helper_->SetListeningForTabDestruction( | 398 map_entry.navigation_helper()->SetListeningForTabDestruction(false); |
408 map_entry.navigation_controller(), false); | |
409 } | 399 } |
410 | 400 |
411 // Our global listeners for these other notifications should be in place iff | 401 // Our global listeners for these other notifications should be in place iff |
412 // we have any tabs still listening for commits. These tabs either have no | 402 // we have any tabs still listening for commits. These tabs either have no |
413 // infobars or have received new pending searches atop existing infobars; in | 403 // infobars or have received new pending searches atop existing infobars; in |
414 // either case we want to catch subsequent pending non-search navigations. | 404 // either case we want to catch subsequent pending non-search navigations. |
415 // See the various cases inside OnNavigationPending(). | 405 // See the various cases inside OnNavigationPending(). |
416 for (EntryMap::const_iterator i(entry_map_.begin()); i != entry_map_.end(); | 406 for (EntryMap::const_iterator i(entry_map_.begin()); i != entry_map_.end(); |
417 ++i) { | 407 ++i) { |
418 if (nav_helper_->IsListeningForNavigationCommit( | 408 if (i->second->navigation_helper()->IsListeningForNavigationCommit()) { |
419 i->second->navigation_controller())) { | |
420 DCHECK(client_->IsListeningForNavigationStart()); | 409 DCHECK(client_->IsListeningForNavigationStart()); |
421 return; | 410 return; |
422 } | 411 } |
423 } | 412 } |
424 if (client_->IsListeningForNavigationStart()) { | 413 if (client_->IsListeningForNavigationStart()) { |
425 DCHECK(!search_committed_); | 414 DCHECK(!search_committed_); |
426 client_->SetListeningForNavigationStart(false); | 415 client_->SetListeningForNavigationStart(false); |
427 } | 416 } |
428 } | 417 } |
OLD | NEW |