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

Side by Side Diff: chrome/browser/google/google_url_tracker.cc

Issue 283413002: Turn GoogleURLTrackerNavigationHelper(Impl) into a per-tab object. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Unittest fix Created 6 years, 7 months 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 | Annotate | Revision Log
OLDNEW
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
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 ? 42 google_url_(mode == UNIT_TEST_MODE ?
46 kDefaultGoogleHomepage : 43 kDefaultGoogleHomepage :
47 profile->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)), 44 profile->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)),
48 fetcher_id_(0), 45 fetcher_id_(0),
49 in_startup_sleep_(true), 46 in_startup_sleep_(true),
50 already_fetched_(false), 47 already_fetched_(false),
51 need_to_fetch_(false), 48 need_to_fetch_(false),
52 need_to_prompt_(false), 49 need_to_prompt_(false),
53 search_committed_(false), 50 search_committed_(false),
54 weak_ptr_factory_(this) { 51 weak_ptr_factory_(this) {
55 net::NetworkChangeNotifier::AddIPAddressObserver(this); 52 net::NetworkChangeNotifier::AddIPAddressObserver(this);
56 client_->set_google_url_tracker(this); 53 client_->set_google_url_tracker(this);
57 nav_helper_->SetGoogleURLTracker(this);
58 54
59 // 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
60 // 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
61 // 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.
62 // 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
63 // 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
64 // no function to do this. 60 // no function to do this.
65 // 61 //
66 // 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
67 // "wakes up", we do nothing at all. 63 // "wakes up", we do nothing at all.
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 } 194 }
199 } 195 }
200 196
201 void GoogleURLTracker::OnIPAddressChanged() { 197 void GoogleURLTracker::OnIPAddressChanged() {
202 already_fetched_ = false; 198 already_fetched_ = false;
203 StartFetchIfDesirable(); 199 StartFetchIfDesirable();
204 } 200 }
205 201
206 void GoogleURLTracker::Shutdown() { 202 void GoogleURLTracker::Shutdown() {
207 client_.reset(); 203 client_.reset();
208 nav_helper_.reset();
209 fetcher_.reset(); 204 fetcher_.reset();
210 weak_ptr_factory_.InvalidateWeakPtrs(); 205 weak_ptr_factory_.InvalidateWeakPtrs();
211 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 206 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
212 } 207 }
213 208
214 void GoogleURLTracker::DeleteMapEntryForService( 209 void GoogleURLTracker::DeleteMapEntryForService(
215 const InfoBarService* infobar_service) { 210 const InfoBarService* infobar_service) {
216 // WARNING: |infobar_service| may point to a deleted object. Do not 211 // WARNING: |infobar_service| may point to a deleted object. Do not
217 // dereference it! See OnTabClosed(). 212 // dereference it! See OnTabClosed().
218 EntryMap::iterator i(entry_map_.find(infobar_service)); 213 EntryMap::iterator i(entry_map_.find(infobar_service));
219 DCHECK(i != entry_map_.end()); 214 DCHECK(i != entry_map_.end());
220 GoogleURLTrackerMapEntry* map_entry = i->second; 215 GoogleURLTrackerMapEntry* map_entry = i->second;
221 216
222 UnregisterForEntrySpecificNotifications(*map_entry, false); 217 UnregisterForEntrySpecificNotifications(map_entry, false);
223 entry_map_.erase(i); 218 entry_map_.erase(i);
224 delete map_entry; 219 delete map_entry;
225 } 220 }
226 221
227 void GoogleURLTracker::SetNeedToFetch() { 222 void GoogleURLTracker::SetNeedToFetch() {
228 need_to_fetch_ = true; 223 need_to_fetch_ = true;
229 StartFetchIfDesirable(); 224 StartFetchIfDesirable();
230 } 225 }
231 226
232 void GoogleURLTracker::FinishSleep() { 227 void GoogleURLTracker::FinishSleep() {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 if (need_to_prompt_) { 269 if (need_to_prompt_) {
275 search_committed_ = true; 270 search_committed_ = true;
276 // These notifications will fire a bit later in the same call chain we're 271 // These notifications will fire a bit later in the same call chain we're
277 // currently in. 272 // currently in.
278 if (!client_->IsListeningForNavigationStart()) 273 if (!client_->IsListeningForNavigationStart())
279 client_->SetListeningForNavigationStart(true); 274 client_->SetListeningForNavigationStart(true);
280 } 275 }
281 } 276 }
282 277
283 void GoogleURLTracker::OnNavigationPending( 278 void GoogleURLTracker::OnNavigationPending(
284 content::NavigationController* navigation_controller, 279 scoped_ptr<GoogleURLTrackerNavigationHelper> nav_helper,
285 InfoBarService* infobar_service, 280 InfoBarService* infobar_service,
286 int pending_id) { 281 int pending_id) {
282 GoogleURLTrackerMapEntry* map_entry = NULL;
283
287 EntryMap::iterator i(entry_map_.find(infobar_service)); 284 EntryMap::iterator i(entry_map_.find(infobar_service));
285 if (i != entry_map_.end())
286 map_entry = i->second;
288 287
289 if (search_committed_) { 288 if (search_committed_) {
290 search_committed_ = false; 289 search_committed_ = false;
291 // Whether there's an existing infobar or not, we need to listen for the 290 if (!map_entry) {
292 // load to commit, so we can show and/or update the infobar when it does.
293 // (We may already be registered for this if there is an existing infobar
294 // that had a previous pending search that hasn't yet committed.)
295 if (!nav_helper_->IsListeningForNavigationCommit(navigation_controller)) {
296 nav_helper_->SetListeningForNavigationCommit(navigation_controller,
297 true);
298 }
299 if (i == entry_map_.end()) {
300 // This is a search on a tab that doesn't have one of our infobars, so 291 // This is a search on a tab that doesn't have one of our infobars, so
301 // prepare to add one. Note that we only listen for the tab's destruction 292 // prepare to add one. Note that we only listen for the tab's destruction
302 // on this path; if there was already a map entry, then either it doesn't 293 // on this path; if there was already a map entry, then either it doesn't
303 // yet have an infobar and we're already registered for this, or it has an 294 // yet have an infobar and we're already registered for this, or it has an
304 // infobar and the infobar's owner will handle tearing it down when the 295 // infobar and the infobar's owner will handle tearing it down when the
305 // tab is destroyed. 296 // tab is destroyed.
306 nav_helper_->SetListeningForTabDestruction(navigation_controller, true); 297 map_entry = new GoogleURLTrackerMapEntry(
307 entry_map_.insert(std::make_pair( 298 this, infobar_service, nav_helper.Pass());
308 infobar_service, 299 map_entry->navigation_helper()->SetListeningForTabDestruction(true);
309 new GoogleURLTrackerMapEntry(this, infobar_service, 300 entry_map_.insert(std::make_pair(infobar_service, map_entry));
310 navigation_controller))); 301 } else if (map_entry->infobar_delegate()) {
311 } else if (i->second->has_infobar_delegate()) {
312 // This is a new search on a tab where we already have an infobar. 302 // This is a new search on a tab where we already have an infobar.
313 i->second->infobar_delegate()->set_pending_id(pending_id); 303 map_entry->infobar_delegate()->set_pending_id(pending_id);
314 } 304 }
315 } else if (i != entry_map_.end()){ 305
316 if (i->second->has_infobar_delegate()) { 306 // Whether there's an existing infobar or not, we need to listen for the
307 // load to commit, so we can show and/or update the infobar when it does.
308 // (We may already be registered for this if there is an existing infobar
309 // that had a previous pending search that hasn't yet committed.)
310 if (!map_entry->navigation_helper()->IsListeningForNavigationCommit())
311 map_entry->navigation_helper()->SetListeningForNavigationCommit(true);
312 } else if (map_entry) {
313 if (map_entry->has_infobar_delegate()) {
317 // This is a non-search navigation on a tab with an infobar. If there was 314 // This is a non-search navigation on a tab with an infobar. If there was
318 // a previous pending search on this tab, this means it won't commit, so 315 // a previous pending search on this tab, this means it won't commit, so
319 // undo anything we did in response to seeing that. Note that if there 316 // undo anything we did in response to seeing that. Note that if there
320 // was no pending search on this tab, these statements are effectively a 317 // was no pending search on this tab, these statements are effectively a
321 // no-op. 318 // no-op.
322 // 319 //
323 // If this navigation actually commits, that will trigger the infobar's 320 // If this navigation actually commits, that will trigger the infobar's
324 // owner to expire the infobar if need be. If it doesn't commit, then 321 // owner to expire the infobar if need be. If it doesn't commit, then
325 // simply leaving the infobar as-is will have been the right thing. 322 // simply leaving the infobar as-is will have been the right thing.
326 UnregisterForEntrySpecificNotifications(*i->second, false); 323 UnregisterForEntrySpecificNotifications(map_entry, false);
327 i->second->infobar_delegate()->set_pending_id(0); 324 map_entry->infobar_delegate()->set_pending_id(0);
328 } else { 325 } else {
329 // Non-search navigation on a tab with an entry that has not yet created 326 // Non-search navigation on a tab with an entry that has not yet created
330 // an infobar. This means the original search won't commit, so delete the 327 // an infobar. This means the original search won't commit, so delete the
331 // entry. 328 // entry.
332 i->second->Close(false); 329 map_entry->Close(false);
333 } 330 }
334 } else { 331 } else {
335 // Non-search navigation on a tab without an infobars. This is irrelevant 332 // Non-search navigation on a tab without an infobars. This is irrelevant
336 // to us. 333 // to us.
337 } 334 }
338 } 335 }
339 336
340 void GoogleURLTracker::OnNavigationCommitted(InfoBarService* infobar_service, 337 void GoogleURLTracker::OnNavigationCommitted(InfoBarService* infobar_service,
341 const GURL& search_url) { 338 const GURL& search_url) {
342 EntryMap::iterator i(entry_map_.find(infobar_service)); 339 EntryMap::iterator i(entry_map_.find(infobar_service));
343 DCHECK(i != entry_map_.end()); 340 DCHECK(i != entry_map_.end());
344 GoogleURLTrackerMapEntry* map_entry = i->second; 341 GoogleURLTrackerMapEntry* map_entry = i->second;
345 DCHECK(search_url.is_valid()); 342 DCHECK(search_url.is_valid());
346 343
347 UnregisterForEntrySpecificNotifications(*map_entry, true); 344 UnregisterForEntrySpecificNotifications(map_entry, true);
348 if (map_entry->has_infobar_delegate()) { 345 if (map_entry->has_infobar_delegate()) {
349 map_entry->infobar_delegate()->Update(search_url); 346 map_entry->infobar_delegate()->Update(search_url);
350 } else { 347 } else {
351 infobars::InfoBar* infobar = 348 infobars::InfoBar* infobar =
352 infobar_creator_.Run(infobar_service, this, search_url); 349 infobar_creator_.Run(infobar_service, this, search_url);
353 if (infobar) { 350 if (infobar) {
354 map_entry->SetInfoBarDelegate( 351 map_entry->SetInfoBarDelegate(
355 static_cast<GoogleURLTrackerInfoBarDelegate*>(infobar->delegate())); 352 static_cast<GoogleURLTrackerInfoBarDelegate*>(infobar->delegate()));
356 } else { 353 } else {
357 map_entry->Close(false); 354 map_entry->Close(false);
358 } 355 }
359 } 356 }
360 } 357 }
361 358
362 void GoogleURLTracker::OnTabClosed( 359 void GoogleURLTracker::OnTabClosed(
363 content::NavigationController* navigation_controller) { 360 GoogleURLTrackerNavigationHelper* nav_helper) {
364 // Because InfoBarService tears itself down on tab destruction, it's possible 361 // Because InfoBarService tears itself down on tab destruction, it's possible
365 // to get a non-NULL InfoBarService pointer here, depending on which order 362 // to get a non-NULL InfoBarService pointer here, depending on which order
366 // notifications fired in. Likewise, the pointer in |entry_map_| (and in its 363 // notifications fired in. Likewise, the pointer in |entry_map_| (and in its
367 // associated MapEntry) may point to deleted memory. Therefore, if we were to 364 // associated MapEntry) may point to deleted memory. Therefore, if we were to
368 // access the InfoBarService* we have for this tab, we'd need to ensure we 365 // access the InfoBarService* we have for this tab, we'd need to ensure we
369 // just looked at the raw pointer value, and never dereferenced it. This 366 // just looked at the raw pointer value, and never dereferenced it. This
370 // function doesn't need to do even that, but others in the call chain from 367 // function doesn't need to do even that, but others in the call chain from
371 // here might (and have comments pointing back here). 368 // here might (and have comments pointing back here).
372 for (EntryMap::iterator i(entry_map_.begin()); i != entry_map_.end(); ++i) { 369 for (EntryMap::iterator i(entry_map_.begin()); i != entry_map_.end(); ++i) {
373 if (i->second->navigation_controller() == navigation_controller) { 370 if (i->second->navigation_helper() == nav_helper) {
374 i->second->Close(false); 371 i->second->Close(false);
375 return; 372 return;
376 } 373 }
377 } 374 }
378 NOTREACHED(); 375 NOTREACHED();
379 } 376 }
380 377
381 scoped_ptr<GoogleURLTracker::Subscription> GoogleURLTracker::RegisterCallback( 378 scoped_ptr<GoogleURLTracker::Subscription> GoogleURLTracker::RegisterCallback(
382 const OnGoogleURLUpdatedCallback& cb) { 379 const OnGoogleURLUpdatedCallback& cb) {
383 return callback_list_.Add(cb); 380 return callback_list_.Add(cb);
384 } 381 }
385 382
386 void GoogleURLTracker::CloseAllEntries(bool redo_searches) { 383 void GoogleURLTracker::CloseAllEntries(bool redo_searches) {
387 // Delete all entries, whether they have infobars or not. 384 // Delete all entries, whether they have infobars or not.
388 while (!entry_map_.empty()) 385 while (!entry_map_.empty())
389 entry_map_.begin()->second->Close(redo_searches); 386 entry_map_.begin()->second->Close(redo_searches);
390 } 387 }
391 388
392 void GoogleURLTracker::UnregisterForEntrySpecificNotifications( 389 void GoogleURLTracker::UnregisterForEntrySpecificNotifications(
393 const GoogleURLTrackerMapEntry& map_entry, 390 GoogleURLTrackerMapEntry* map_entry,
394 bool must_be_listening_for_commit) { 391 bool must_be_listening_for_commit) {
395 // For tabs with map entries but no infobars, we should always be listening 392 // For tabs with map entries but no infobars, we should always be listening
396 // for both these notifications. For tabs with infobars, we may be listening 393 // for both these notifications. For tabs with infobars, we may be listening
397 // for navigation commits if the user has performed a new search on this tab. 394 // for navigation commits if the user has performed a new search on this tab.
398 if (nav_helper_->IsListeningForNavigationCommit( 395 if (map_entry->navigation_helper()->IsListeningForNavigationCommit()) {
399 map_entry.navigation_controller())) { 396 map_entry->navigation_helper()->SetListeningForNavigationCommit(false);
400 nav_helper_->SetListeningForNavigationCommit(
401 map_entry.navigation_controller(), false);
402 } else { 397 } else {
403 DCHECK(!must_be_listening_for_commit); 398 DCHECK(!must_be_listening_for_commit);
404 DCHECK(map_entry.has_infobar_delegate()); 399 DCHECK(map_entry->has_infobar_delegate());
405 } 400 }
406 const bool registered_for_tab_destruction = 401 const bool registered_for_tab_destruction =
407 nav_helper_->IsListeningForTabDestruction( 402 map_entry->navigation_helper()->IsListeningForTabDestruction();
408 map_entry.navigation_controller()); 403 DCHECK_NE(registered_for_tab_destruction, map_entry->has_infobar_delegate());
409 DCHECK_NE(registered_for_tab_destruction, map_entry.has_infobar_delegate());
410 if (registered_for_tab_destruction) { 404 if (registered_for_tab_destruction) {
411 nav_helper_->SetListeningForTabDestruction( 405 map_entry->navigation_helper()->SetListeningForTabDestruction(false);
412 map_entry.navigation_controller(), false);
413 } 406 }
414 407
415 // Our global listeners for these other notifications should be in place iff 408 // Our global listeners for these other notifications should be in place iff
416 // we have any tabs still listening for commits. These tabs either have no 409 // we have any tabs still listening for commits. These tabs either have no
417 // infobars or have received new pending searches atop existing infobars; in 410 // infobars or have received new pending searches atop existing infobars; in
418 // either case we want to catch subsequent pending non-search navigations. 411 // either case we want to catch subsequent pending non-search navigations.
419 // See the various cases inside OnNavigationPending(). 412 // See the various cases inside OnNavigationPending().
420 for (EntryMap::const_iterator i(entry_map_.begin()); i != entry_map_.end(); 413 for (EntryMap::const_iterator i(entry_map_.begin()); i != entry_map_.end();
421 ++i) { 414 ++i) {
422 if (nav_helper_->IsListeningForNavigationCommit( 415 if (i->second->navigation_helper()->IsListeningForNavigationCommit()) {
423 i->second->navigation_controller())) {
424 DCHECK(client_->IsListeningForNavigationStart()); 416 DCHECK(client_->IsListeningForNavigationStart());
425 return; 417 return;
426 } 418 }
427 } 419 }
428 if (client_->IsListeningForNavigationStart()) { 420 if (client_->IsListeningForNavigationStart()) {
429 DCHECK(!search_committed_); 421 DCHECK(!search_committed_);
430 client_->SetListeningForNavigationStart(false); 422 client_->SetListeningForNavigationStart(false);
431 } 423 }
432 } 424 }
433 425
434 void GoogleURLTracker::NotifyGoogleURLUpdated(GURL old_url, GURL new_url) { 426 void GoogleURLTracker::NotifyGoogleURLUpdated(GURL old_url, GURL new_url) {
435 callback_list_.Notify(old_url, new_url); 427 callback_list_.Notify(old_url, new_url);
436 } 428 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698