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

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

Issue 10753019: Merge 144201 - More comprehensive handling of NOTIFICATION_NAV_ENTRY_PENDING for GoogleURLTracker. (Closed) Base URL: svn://svn.chromium.org/chrome/branches/1180/src/
Patch Set: Created 8 years, 5 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 <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/string_util.h" 12 #include "base/string_util.h"
13 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
14 #include "chrome/browser/browser_process.h" 14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/google/google_url_tracker_factory.h" 15 #include "chrome/browser/google/google_url_tracker_factory.h"
16 #include "chrome/browser/google/google_util.h" 16 #include "chrome/browser/google/google_util.h"
17 #include "chrome/browser/infobars/infobar_tab_helper.h" 17 #include "chrome/browser/infobars/infobar_tab_helper.h"
18 #include "chrome/browser/prefs/pref_service.h" 18 #include "chrome/browser/prefs/pref_service.h"
19 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/search_engines/template_url.h" 20 #include "chrome/browser/search_engines/template_url.h"
21 #include "chrome/browser/ui/tab_contents/tab_contents.h" 21 #include "chrome/browser/ui/tab_contents/tab_contents.h"
22 #include "chrome/common/chrome_notification_types.h" 22 #include "chrome/common/chrome_notification_types.h"
23 #include "chrome/common/chrome_switches.h" 23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/pref_names.h" 24 #include "chrome/common/pref_names.h"
25 #include "content/public/browser/navigation_controller.h" 25 #include "content/public/browser/navigation_controller.h"
26 #include "content/public/browser/navigation_details.h"
26 #include "content/public/browser/navigation_entry.h" 27 #include "content/public/browser/navigation_entry.h"
27 #include "content/public/browser/notification_service.h" 28 #include "content/public/browser/notification_service.h"
28 #include "content/public/browser/web_contents.h" 29 #include "content/public/browser/web_contents.h"
29 #include "content/public/common/url_fetcher.h" 30 #include "content/public/common/url_fetcher.h"
30 #include "grit/generated_resources.h" 31 #include "grit/generated_resources.h"
31 #include "net/base/load_flags.h" 32 #include "net/base/load_flags.h"
32 #include "net/base/net_util.h" 33 #include "net/base/net_util.h"
33 #include "net/url_request/url_request_context_getter.h" 34 #include "net/url_request/url_request_context_getter.h"
34 #include "net/url_request/url_request_status.h" 35 #include "net/url_request/url_request_status.h"
35 #include "ui/base/l10n/l10n_util.h" 36 #include "ui/base/l10n/l10n_util.h"
36 37
37 namespace { 38 namespace {
38 39
39 GoogleURLTrackerInfoBarDelegate* CreateInfoBar( 40 GoogleURLTrackerInfoBarDelegate* CreateInfoBar(
40 InfoBarTabHelper* infobar_helper, 41 InfoBarTabHelper* infobar_helper,
41 const GURL& search_url,
42 GoogleURLTracker* google_url_tracker, 42 GoogleURLTracker* google_url_tracker,
43 const GURL& new_google_url) { 43 const GURL& new_google_url) {
44 return new GoogleURLTrackerInfoBarDelegate(infobar_helper, search_url, 44 return new GoogleURLTrackerInfoBarDelegate(infobar_helper, google_url_tracker,
45 google_url_tracker, new_google_url); 45 new_google_url);
46 } 46 }
47 47
48 string16 GetHost(const GURL& url) { 48 string16 GetHost(const GURL& url) {
49 DCHECK(url.is_valid()); 49 DCHECK(url.is_valid());
50 return net::StripWWW(UTF8ToUTF16(url.host())); 50 return net::StripWWW(UTF8ToUTF16(url.host()));
51 } 51 }
52 52
53 } // namespace 53 } // namespace
54 54
55 // GoogleURLTrackerInfoBarDelegate -------------------------------------------- 55 // GoogleURLTrackerInfoBarDelegate --------------------------------------------
56 56
57 GoogleURLTrackerInfoBarDelegate::GoogleURLTrackerInfoBarDelegate( 57 GoogleURLTrackerInfoBarDelegate::GoogleURLTrackerInfoBarDelegate(
58 InfoBarTabHelper* infobar_helper, 58 InfoBarTabHelper* infobar_helper,
59 const GURL& search_url,
60 GoogleURLTracker* google_url_tracker, 59 GoogleURLTracker* google_url_tracker,
61 const GURL& new_google_url) 60 const GURL& new_google_url)
62 : ConfirmInfoBarDelegate(infobar_helper), 61 : ConfirmInfoBarDelegate(infobar_helper),
63 map_key_(infobar_helper), 62 map_key_(infobar_helper),
64 search_url_(search_url),
65 google_url_tracker_(google_url_tracker), 63 google_url_tracker_(google_url_tracker),
66 new_google_url_(new_google_url), 64 new_google_url_(new_google_url),
67 showing_(false) { 65 showing_(false),
66 pending_id_(0) {
68 } 67 }
69 68
70 bool GoogleURLTrackerInfoBarDelegate::Accept() { 69 bool GoogleURLTrackerInfoBarDelegate::Accept() {
71 google_url_tracker_->AcceptGoogleURL(new_google_url_, true); 70 google_url_tracker_->AcceptGoogleURL(new_google_url_, true);
72 return false; 71 return false;
73 } 72 }
74 73
75 bool GoogleURLTrackerInfoBarDelegate::Cancel() { 74 bool GoogleURLTrackerInfoBarDelegate::Cancel() {
76 google_url_tracker_->CancelGoogleURL(new_google_url_); 75 google_url_tracker_->CancelGoogleURL(new_google_url_);
77 return false; 76 return false;
78 } 77 }
79 78
80 string16 GoogleURLTrackerInfoBarDelegate::GetLinkText() const { 79 string16 GoogleURLTrackerInfoBarDelegate::GetLinkText() const {
81 return l10n_util::GetStringUTF16(IDS_LEARN_MORE); 80 return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
82 } 81 }
83 82
84 bool GoogleURLTrackerInfoBarDelegate::LinkClicked( 83 bool GoogleURLTrackerInfoBarDelegate::LinkClicked(
85 WindowOpenDisposition disposition) { 84 WindowOpenDisposition disposition) {
86 content::OpenURLParams params(google_util::AppendGoogleLocaleParam(GURL( 85 content::OpenURLParams params(google_util::AppendGoogleLocaleParam(GURL(
87 "https://www.google.com/support/chrome/bin/answer.py?answer=1618699")), 86 "https://www.google.com/support/chrome/bin/answer.py?answer=1618699")),
88 content::Referrer(), 87 content::Referrer(),
89 (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition, 88 (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
90 content::PAGE_TRANSITION_LINK, false); 89 content::PAGE_TRANSITION_LINK, false);
91 owner()->web_contents()->OpenURL(params); 90 owner()->web_contents()->OpenURL(params);
92 return false; 91 return false;
93 } 92 }
94 93
94 bool GoogleURLTrackerInfoBarDelegate::ShouldExpireInternal(
95 const content::LoadCommittedDetails& details) const {
96 int unique_id = details.entry->GetUniqueID();
97 return (unique_id != contents_unique_id()) && (unique_id != pending_id_);
98 }
99
95 void GoogleURLTrackerInfoBarDelegate::SetGoogleURL(const GURL& new_google_url) { 100 void GoogleURLTrackerInfoBarDelegate::SetGoogleURL(const GURL& new_google_url) {
96 DCHECK_EQ(GetHost(new_google_url_), GetHost(new_google_url)); 101 DCHECK_EQ(GetHost(new_google_url_), GetHost(new_google_url));
97 new_google_url_ = new_google_url; 102 new_google_url_ = new_google_url;
98 } 103 }
99 104
100 void GoogleURLTrackerInfoBarDelegate::Show() { 105 void GoogleURLTrackerInfoBarDelegate::Show(const GURL& search_url) {
101 showing_ = true; 106 if (!owner())
102 owner()->AddInfoBar(this); // May delete |this| on failure! 107 return;
108 StoreActiveEntryUniqueID(owner());
109 search_url_ = search_url;
110 pending_id_ = 0;
111 if (!showing_) {
112 showing_ = true;
113 owner()->AddInfoBar(this); // May delete |this| on failure!
114 }
103 } 115 }
104 116
105 void GoogleURLTrackerInfoBarDelegate::Close(bool redo_search) { 117 void GoogleURLTrackerInfoBarDelegate::Close(bool redo_search) {
106 if (redo_search && owner()) {
107 // Re-do the user's search on the new domain.
108 url_canon::Replacements<char> replacements;
109 const std::string& host(new_google_url_.host());
110 replacements.SetHost(host.data(), url_parse::Component(0, host.length()));
111 GURL new_search_url(search_url_.ReplaceComponents(replacements));
112 if (new_search_url.is_valid()) {
113 content::OpenURLParams params(new_search_url, content::Referrer(),
114 CURRENT_TAB, content::PAGE_TRANSITION_GENERATED, false);
115 owner()->web_contents()->OpenURL(params);
116 }
117 }
118
119 if (!showing_) { 118 if (!showing_) {
120 // We haven't been added to a tab, so just delete ourselves. 119 // We haven't been added to a tab, so just delete ourselves.
121 delete this; 120 delete this;
122 return; 121 return;
123 } 122 }
124 123
125 // Synchronously remove ourselves from the URL tracker's list, because the 124 // Synchronously remove ourselves from the URL tracker's list, because the
126 // RemoveInfoBar() call below may result in either a synchronous or an 125 // RemoveInfoBar() call below may result in either a synchronous or an
127 // asynchronous call back to InfoBarClosed(), and it's easier to handle when 126 // asynchronous call back to InfoBarClosed(), and it's easier to handle when
128 // we just guarantee the removal is synchronous. 127 // we just guarantee the removal is synchronous.
129 google_url_tracker_->InfoBarClosed(map_key_); 128 google_url_tracker_->InfoBarClosed(map_key_);
130 google_url_tracker_ = NULL; 129 google_url_tracker_ = NULL;
131 130
132 // If we're already animating closed, we won't have an owner. Do nothing in 131 // If we're already animating closed, we won't have an owner. Do nothing in
133 // this case. 132 // this case.
134 // TODO(pkasting): For now, this can also happen if we were showing in a 133 // TODO(pkasting): For now, this can also happen if we were showing in a
135 // background tab that was then closed, in which case we'll have leaked and 134 // background tab that was then closed, in which case we'll have leaked and
136 // subsequently reached here due to GoogleURLTracker::CloseAllInfoBars(). 135 // subsequently reached here due to GoogleURLTracker::CloseAllInfoBars().
137 // This case will no longer happen once infobars are refactored to own their 136 // This case will no longer happen once infobars are refactored to own their
138 // delegates. 137 // delegates.
139 if (owner()) 138 if (!owner())
140 owner()->RemoveInfoBar(this); 139 return;
140
141 if (redo_search) {
142 // Re-do the user's search on the new domain.
143 DCHECK(search_url_.is_valid());
144 url_canon::Replacements<char> replacements;
145 const std::string& host(new_google_url_.host());
146 replacements.SetHost(host.data(), url_parse::Component(0, host.length()));
147 GURL new_search_url(search_url_.ReplaceComponents(replacements));
148 if (new_search_url.is_valid()) {
149 content::OpenURLParams params(new_search_url, content::Referrer(),
150 CURRENT_TAB, content::PAGE_TRANSITION_GENERATED, false);
151 owner()->web_contents()->OpenURL(params);
152 }
153 }
154
155 owner()->RemoveInfoBar(this);
141 } 156 }
142 157
143 GoogleURLTrackerInfoBarDelegate::~GoogleURLTrackerInfoBarDelegate() { 158 GoogleURLTrackerInfoBarDelegate::~GoogleURLTrackerInfoBarDelegate() {
144 if (google_url_tracker_) 159 if (google_url_tracker_)
145 google_url_tracker_->InfoBarClosed(map_key_); 160 google_url_tracker_->InfoBarClosed(map_key_);
146 } 161 }
147 162
148 string16 GoogleURLTrackerInfoBarDelegate::GetMessageText() const { 163 string16 GoogleURLTrackerInfoBarDelegate::GetMessageText() const {
149 return l10n_util::GetStringFUTF16(IDS_GOOGLE_URL_TRACKER_INFOBAR_MESSAGE, 164 return l10n_util::GetStringFUTF16(IDS_GOOGLE_URL_TRACKER_INFOBAR_MESSAGE,
150 GetHost(new_google_url_), GetHost(google_url_tracker_->google_url_)); 165 GetHost(new_google_url_), GetHost(google_url_tracker_->google_url_));
151 } 166 }
152 167
153 string16 GoogleURLTrackerInfoBarDelegate::GetButtonLabel( 168 string16 GoogleURLTrackerInfoBarDelegate::GetButtonLabel(
154 InfoBarButton button) const { 169 InfoBarButton button) const {
155 bool new_host = (button == BUTTON_OK); 170 bool new_host = (button == BUTTON_OK);
156 return l10n_util::GetStringFUTF16(new_host ? 171 return l10n_util::GetStringFUTF16(new_host ?
157 IDS_GOOGLE_URL_TRACKER_INFOBAR_SWITCH : 172 IDS_GOOGLE_URL_TRACKER_INFOBAR_SWITCH :
158 IDS_GOOGLE_URL_TRACKER_INFOBAR_DONT_SWITCH, 173 IDS_GOOGLE_URL_TRACKER_INFOBAR_DONT_SWITCH,
159 GetHost(new_host ? new_google_url_ : google_url_tracker_->google_url_)); 174 GetHost(new_host ? new_google_url_ : google_url_tracker_->google_url_));
160 } 175 }
161 176
162 177
178 // GoogleURLTracker::MapEntry -------------------------------------------------
179
180 // Note that we have to initialize at least the NotificationSources explicitly
181 // lest this not compile, because NotificationSource has no null constructor.
182 GoogleURLTracker::MapEntry::MapEntry()
183 : navigation_controller_source(
184 content::Source<content::NavigationController>(NULL)),
185 tab_contents_source(content::Source<TabContents>(NULL)) {
186 NOTREACHED();
187 }
188
189 GoogleURLTracker::MapEntry::MapEntry(
190 GoogleURLTrackerInfoBarDelegate* infobar,
191 const content::NotificationSource& navigation_controller_source,
192 const content::NotificationSource& tab_contents_source)
193 : infobar(infobar),
194 navigation_controller_source(navigation_controller_source),
195 tab_contents_source(tab_contents_source) {
196 }
197
198 GoogleURLTracker::MapEntry::~MapEntry() {
199 }
200
201
163 // GoogleURLTracker ----------------------------------------------------------- 202 // GoogleURLTracker -----------------------------------------------------------
164 203
165 const char GoogleURLTracker::kDefaultGoogleHomepage[] = 204 const char GoogleURLTracker::kDefaultGoogleHomepage[] =
166 "http://www.google.com/"; 205 "http://www.google.com/";
167 const char GoogleURLTracker::kSearchDomainCheckURL[] = 206 const char GoogleURLTracker::kSearchDomainCheckURL[] =
168 "https://www.google.com/searchdomaincheck?format=url&type=chrome"; 207 "https://www.google.com/searchdomaincheck?format=url&type=chrome";
169 208
170 GoogleURLTracker::GoogleURLTracker(Profile* profile, Mode mode) 209 GoogleURLTracker::GoogleURLTracker(Profile* profile, Mode mode)
171 : profile_(profile), 210 : profile_(profile),
172 infobar_creator_(&CreateInfoBar), 211 infobar_creator_(&CreateInfoBar),
173 google_url_(mode == UNIT_TEST_MODE ? kDefaultGoogleHomepage : 212 google_url_(mode == UNIT_TEST_MODE ? kDefaultGoogleHomepage :
174 profile->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)), 213 profile->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)),
175 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), 214 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
176 fetcher_id_(0), 215 fetcher_id_(0),
177 in_startup_sleep_(true), 216 in_startup_sleep_(true),
178 already_fetched_(false), 217 already_fetched_(false),
179 need_to_fetch_(false), 218 need_to_fetch_(false),
180 need_to_prompt_(false) { 219 need_to_prompt_(false),
220 search_committed_(false) {
181 net::NetworkChangeNotifier::AddIPAddressObserver(this); 221 net::NetworkChangeNotifier::AddIPAddressObserver(this);
182 222
183 // Because this function can be called during startup, when kicking off a URL 223 // Because this function can be called during startup, when kicking off a URL
184 // fetch can eat up 20 ms of time, we delay five seconds, which is hopefully 224 // fetch can eat up 20 ms of time, we delay five seconds, which is hopefully
185 // long enough to be after startup, but still get results back quickly. 225 // long enough to be after startup, but still get results back quickly.
186 // Ideally, instead of this timer, we'd do something like "check if the 226 // Ideally, instead of this timer, we'd do something like "check if the
187 // browser is starting up, and if so, come back later", but there is currently 227 // browser is starting up, and if so, come back later", but there is currently
188 // no function to do this. 228 // no function to do this.
189 // 229 //
190 // In UNIT_TEST mode, where we want to explicitly control when the tracker 230 // In UNIT_TEST mode, where we want to explicitly control when the tracker
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 // existing infobars open and quietly point their "new Google URL"s at the 332 // existing infobars open and quietly point their "new Google URL"s at the
293 // new URL (for e.g. scheme changes). Otherwise we go ahead and close the 333 // new URL (for e.g. scheme changes). Otherwise we go ahead and close the
294 // existing infobars since their message is out-of-date. 334 // existing infobars since their message is out-of-date.
295 if (!url.is_valid()) // Note: |url| is the previous |fetched_google_url_|. 335 if (!url.is_valid()) // Note: |url| is the previous |fetched_google_url_|.
296 return; 336 return;
297 if (fetched_host != GetHost(url)) { 337 if (fetched_host != GetHost(url)) {
298 CloseAllInfoBars(false); 338 CloseAllInfoBars(false);
299 } else if (fetched_google_url_ != url) { 339 } else if (fetched_google_url_ != url) {
300 for (InfoBarMap::iterator i(infobar_map_.begin()); 340 for (InfoBarMap::iterator i(infobar_map_.begin());
301 i != infobar_map_.end(); ++i) 341 i != infobar_map_.end(); ++i)
302 i->second->SetGoogleURL(fetched_google_url_); 342 i->second.infobar->SetGoogleURL(fetched_google_url_);
303 } 343 }
304 } 344 }
305 } 345 }
306 346
307 void GoogleURLTracker::Observe(int type, 347 void GoogleURLTracker::Observe(int type,
308 const content::NotificationSource& source, 348 const content::NotificationSource& source,
309 const content::NotificationDetails& details) { 349 const content::NotificationDetails& details) {
310 switch (type) { 350 switch (type) {
311 case content::NOTIFICATION_NAV_ENTRY_PENDING: { 351 case content::NOTIFICATION_NAV_ENTRY_PENDING: {
312 content::NavigationController* controller = 352 content::NavigationController* controller =
313 content::Source<content::NavigationController>(source).ptr(); 353 content::Source<content::NavigationController>(source).ptr();
314 TabContents* tab_contents = 354 TabContents* tab_contents =
315 TabContents::FromWebContents(controller->GetWebContents()); 355 TabContents::FromWebContents(controller->GetWebContents());
316 OnNavigationPending(source, 356 OnNavigationPending(source, content::Source<TabContents>(tab_contents),
317 content::Source<TabContents>(tab_contents),
318 tab_contents->infobar_tab_helper(), 357 tab_contents->infobar_tab_helper(),
319 controller->GetPendingEntry()->GetURL()); 358 controller->GetPendingEntry()->GetUniqueID());
320 break; 359 break;
321 } 360 }
322 361
323 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { 362 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: {
324 TabContents* tab_contents = TabContents::FromWebContents( 363 content::NavigationController* controller =
325 content::Source<content::NavigationController>(source)-> 364 content::Source<content::NavigationController>(source).ptr();
326 GetWebContents()); 365 OnNavigationCommittedOrTabClosed(
327 OnNavigationCommittedOrTabClosed(source, 366 TabContents::FromWebContents(controller->GetWebContents())->
328 content::Source<TabContents>(tab_contents), 367 infobar_tab_helper(),
329 tab_contents->infobar_tab_helper(), true); 368 controller->GetActiveEntry()->GetURL());
330 break; 369 break;
331 } 370 }
332 371
333 case chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED: { 372 case chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED: {
334 TabContents* tab_contents = content::Source<TabContents>(source).ptr();
335 OnNavigationCommittedOrTabClosed( 373 OnNavigationCommittedOrTabClosed(
336 content::Source<content::NavigationController>( 374 content::Source<TabContents>(source)->infobar_tab_helper(), GURL());
337 &tab_contents->web_contents()->GetController()), source,
338 tab_contents->infobar_tab_helper(), false);
339 break; 375 break;
340 } 376 }
341 377
342 case chrome::NOTIFICATION_INSTANT_COMMITTED: { 378 case chrome::NOTIFICATION_INSTANT_COMMITTED: {
343 TabContents* tab_contents = content::Source<TabContents>(source).ptr(); 379 TabContents* tab_contents = content::Source<TabContents>(source).ptr();
344 content::WebContents* web_contents = tab_contents->web_contents(); 380 content::WebContents* web_contents = tab_contents->web_contents();
345 content::Source<content::NavigationController> source( 381 content::Source<content::NavigationController> source(
346 &web_contents->GetController()); 382 &web_contents->GetController());
347 content::Source<TabContents> tab_contents_source(tab_contents);
348 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper(); 383 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper();
349 OnNavigationPending(source, tab_contents_source, infobar_helper, 384 OnNavigationPending(source, content::Source<TabContents>(tab_contents),
350 web_contents->GetURL()); 385 infobar_helper, 0);
351 OnNavigationCommittedOrTabClosed(source, tab_contents_source, 386 OnNavigationCommittedOrTabClosed(infobar_helper, web_contents->GetURL());
352 infobar_helper, true);
353 break; 387 break;
354 } 388 }
355 389
356 default: 390 default:
357 NOTREACHED() << "Unknown notification received:" << type; 391 NOTREACHED() << "Unknown notification received:" << type;
358 } 392 }
359 } 393 }
360 394
361 void GoogleURLTracker::OnIPAddressChanged() { 395 void GoogleURLTracker::OnIPAddressChanged() {
362 already_fetched_ = false; 396 already_fetched_ = false;
(...skipping 23 matching lines...) Expand all
386 } 420 }
387 421
388 void GoogleURLTracker::CancelGoogleURL(const GURL& new_google_url) { 422 void GoogleURLTracker::CancelGoogleURL(const GURL& new_google_url) {
389 profile_->GetPrefs()->SetString(prefs::kLastPromptedGoogleURL, 423 profile_->GetPrefs()->SetString(prefs::kLastPromptedGoogleURL,
390 new_google_url.spec()); 424 new_google_url.spec());
391 need_to_prompt_ = false; 425 need_to_prompt_ = false;
392 CloseAllInfoBars(false); 426 CloseAllInfoBars(false);
393 } 427 }
394 428
395 void GoogleURLTracker::InfoBarClosed(const InfoBarTabHelper* infobar_helper) { 429 void GoogleURLTracker::InfoBarClosed(const InfoBarTabHelper* infobar_helper) {
430 DCHECK(!search_committed_);
396 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); 431 InfoBarMap::iterator i(infobar_map_.find(infobar_helper));
397 DCHECK(i != infobar_map_.end()); 432 DCHECK(i != infobar_map_.end());
433 const MapEntry& map_entry = i->second;
434
435 UnregisterForEntrySpecificNotifications(map_entry, false);
398 infobar_map_.erase(i); 436 infobar_map_.erase(i);
437
438 // Our global listeners for these other notifications should be in place iff
439 // we have any non-showing infobars.
440 for (InfoBarMap::const_iterator i(infobar_map_.begin());
441 i != infobar_map_.end(); ++i) {
442 if (!i->second.infobar->showing()) {
443 DCHECK(registrar_.IsRegistered(this,
444 content::NOTIFICATION_NAV_ENTRY_PENDING,
445 content::NotificationService::AllBrowserContextsAndSources()));
446 return;
447 }
448 }
449 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
450 content::NotificationService::AllBrowserContextsAndSources())) {
451 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
452 content::NotificationService::AllBrowserContextsAndSources());
453 registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
454 content::NotificationService::AllBrowserContextsAndSources());
455 }
399 } 456 }
400 457
401 void GoogleURLTracker::SetNeedToFetch() { 458 void GoogleURLTracker::SetNeedToFetch() {
402 need_to_fetch_ = true; 459 need_to_fetch_ = true;
403 StartFetchIfDesirable(); 460 StartFetchIfDesirable();
404 } 461 }
405 462
406 void GoogleURLTracker::FinishSleep() { 463 void GoogleURLTracker::FinishSleep() {
407 in_startup_sleep_ = false; 464 in_startup_sleep_ = false;
408 StartFetchIfDesirable(); 465 StartFetchIfDesirable();
(...skipping 30 matching lines...) Expand all
439 496
440 // Configure to max_retries at most kMaxRetries times for 5xx errors. 497 // Configure to max_retries at most kMaxRetries times for 5xx errors.
441 static const int kMaxRetries = 5; 498 static const int kMaxRetries = 5;
442 fetcher_->SetMaxRetries(kMaxRetries); 499 fetcher_->SetMaxRetries(kMaxRetries);
443 500
444 fetcher_->Start(); 501 fetcher_->Start();
445 } 502 }
446 503
447 void GoogleURLTracker::SearchCommitted() { 504 void GoogleURLTracker::SearchCommitted() {
448 if (need_to_prompt_) { 505 if (need_to_prompt_) {
449 // This notification will fire a bit later in the same call chain we're 506 search_committed_ = true;
507 // These notifications will fire a bit later in the same call chain we're
450 // currently in. 508 // currently in.
451 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING, 509 if (!registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
452 content::NotificationService::AllBrowserContextsAndSources()); 510 content::NotificationService::AllBrowserContextsAndSources())) {
453 registrar_.Add(this, chrome::NOTIFICATION_INSTANT_COMMITTED, 511 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
454 content::NotificationService::AllBrowserContextsAndSources()); 512 content::NotificationService::AllBrowserContextsAndSources());
513 registrar_.Add(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
514 content::NotificationService::AllBrowserContextsAndSources());
515 }
455 } 516 }
456 } 517 }
457 518
458 void GoogleURLTracker::OnNavigationPending( 519 void GoogleURLTracker::OnNavigationPending(
459 const content::NotificationSource& navigation_controller_source, 520 const content::NotificationSource& navigation_controller_source,
460 const content::NotificationSource& tab_contents_source, 521 const content::NotificationSource& tab_contents_source,
461 InfoBarTabHelper* infobar_helper, 522 InfoBarTabHelper* infobar_helper,
462 const GURL& search_url) { 523 int pending_id) {
463 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING, 524 InfoBarMap::iterator i(infobar_map_.find(infobar_helper));
464 content::NotificationService::AllBrowserContextsAndSources());
465 registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
466 content::NotificationService::AllBrowserContextsAndSources());
467 525
468 if (registrar_.IsRegistered(this, 526 if (search_committed_) {
469 chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, tab_contents_source)) { 527 search_committed_ = false;
470 // If the previous load hasn't committed and the user triggers a new load, 528 // Whether there's an existing infobar or not, we need to listen for the
471 // we don't need to re-register our listeners; just kill the old, 529 // load to commit, so we can show and/or update the infobar when it does.
472 // never-shown infobar (to be replaced by a new one below). 530 // (We may already be registered for this if there is an existing infobar
473 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); 531 // that had a previous pending search that hasn't yet committed.)
474 DCHECK(i != infobar_map_.end()); 532 if (!registrar_.IsRegistered(this,
475 i->second->Close(false); 533 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
534 navigation_controller_source)) {
535 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
536 navigation_controller_source);
537 }
538 if (i == infobar_map_.end()) {
539 // This is a search on a tab that doesn't have one of our infobars, so add
540 // one. Note that we only listen for the tab's destruction on this path;
541 // if there was already an infobar, then either it's not yet showing and
542 // we're already registered for this, or it is showing and its owner will
543 // handle tearing it down when the tab is destroyed.
544 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
545 tab_contents_source);
546 infobar_map_.insert(std::make_pair(infobar_helper, MapEntry(
547 (*infobar_creator_)(infobar_helper, this, fetched_google_url_),
548 navigation_controller_source, tab_contents_source)));
549 } else {
550 // This is a new search on a tab where we already have an infobar (which
551 // may or may not be showing).
552 i->second.infobar->set_pending_id(pending_id);
553 }
554 } else if (i != infobar_map_.end()){
555 if (i->second.infobar->showing()) {
556 // This is a non-search navigation on a tab with a visible infobar. If
557 // there was a previous pending search on this tab, this means it won't
558 // commit, so undo anything we did in response to seeing that. Note that
559 // if there was no pending search on this tab, these statements are
560 // effectively a no-op.
561 //
562 // If this navigation actually commits, that will trigger the infobar's
563 // owner to expire the infobar if need be. If it doesn't commit, then
564 // simply leaving the infobar as-is will have been the right thing.
565 UnregisterForEntrySpecificNotifications(i->second, false);
566 i->second.infobar->set_pending_id(0);
567 } else {
568 // Non-search navigation on a tab with a not-yet-shown infobar. This
569 // means the original search won't commit, so close the infobar.
570 i->second.infobar->Close(false);
571 }
476 } else { 572 } else {
477 // Start listening for the commit notification. We also need to listen for 573 // Non-search navigation on a tab without one of our infobars. This is
478 // the tab close command since that means the load will never commit. Note 574 // irrelevant to us.
479 // that in this case we don't need to close any previous infobar for this
480 // tab since this navigation will close it.
481 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
482 navigation_controller_source);
483 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
484 tab_contents_source);
485 } 575 }
486
487 infobar_map_[infobar_helper] = (*infobar_creator_)(infobar_helper, search_url,
488 this, fetched_google_url_);
489 } 576 }
490 577
491 void GoogleURLTracker::OnNavigationCommittedOrTabClosed( 578 void GoogleURLTracker::OnNavigationCommittedOrTabClosed(
492 const content::NotificationSource& navigation_controller_source,
493 const content::NotificationSource& tab_contents_source,
494 const InfoBarTabHelper* infobar_helper, 579 const InfoBarTabHelper* infobar_helper,
495 bool navigated) { 580 const GURL& search_url) {
496 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
497 navigation_controller_source);
498 registrar_.Remove(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
499 tab_contents_source);
500
501 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); 581 InfoBarMap::iterator i(infobar_map_.find(infobar_helper));
502 DCHECK(i != infobar_map_.end()); 582 DCHECK(i != infobar_map_.end());
503 DCHECK(need_to_prompt_); 583 const MapEntry& map_entry = i->second;
504 if (navigated) 584
505 i->second->Show(); 585 if (!search_url.is_valid()) {
506 else 586 // Tab closed, or we somehow tried to navigate to an invalid URL (?!).
507 i->second->Close(false); // Close manually since it's not added to a tab. 587 // InfoBarClosed() will take care of unregistering the notifications for
588 // this tab.
589 map_entry.infobar->Close(false);
590 return;
591 }
592
593 // We're getting called because of a commit notification, so pass true for
594 // |must_be_listening_for_commit|.
595 UnregisterForEntrySpecificNotifications(map_entry, true);
596 map_entry.infobar->Show(search_url);
508 } 597 }
509 598
510 void GoogleURLTracker::CloseAllInfoBars(bool redo_searches) { 599 void GoogleURLTracker::CloseAllInfoBars(bool redo_searches) {
511 // Close all infobars, whether they've been added to tabs or not. 600 // Close all infobars, whether they've been added to tabs or not.
512 while (!infobar_map_.empty()) 601 while (!infobar_map_.empty())
513 infobar_map_.begin()->second->Close(redo_searches); 602 infobar_map_.begin()->second.infobar->Close(redo_searches);
603 }
514 604
515 // Any registered listeners for NAV_ENTRY_COMMITTED and TAB_CLOSED are now 605 void GoogleURLTracker::UnregisterForEntrySpecificNotifications(
516 // irrelevant as the associated infobars are gone. 606 const MapEntry& map_entry,
517 registrar_.RemoveAll(); 607 bool must_be_listening_for_commit) {
608 // For tabs with non-showing infobars, we should always be listening for both
609 // these notifications. For tabs with showing infobars, we may be listening
610 // for NOTIFICATION_NAV_ENTRY_COMMITTED if the user has performed a new search
611 // on this tab.
612 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
613 map_entry.navigation_controller_source)) {
614 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
615 map_entry.navigation_controller_source);
616 } else {
617 DCHECK(!must_be_listening_for_commit);
618 DCHECK(map_entry.infobar->showing());
619 }
620 const bool registered_for_tab_contents_destroyed =
621 registrar_.IsRegistered(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
622 map_entry.tab_contents_source);
623 DCHECK_NE(registered_for_tab_contents_destroyed,
624 map_entry.infobar->showing());
625 if (registered_for_tab_contents_destroyed) {
626 registrar_.Remove(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
627 map_entry.tab_contents_source);
628 }
518 } 629 }
OLDNEW
« no previous file with comments | « chrome/browser/google/google_url_tracker.h ('k') | chrome/browser/google/google_url_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698