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

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

Powered by Google App Engine
This is Rietveld 408576698