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

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

Issue 10630022: More comprehensive handling of NOTIFICATION_NAV_ENTRY_PENDING for GoogleURLTracker. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 6 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 "grit/generated_resources.h" 30 #include "grit/generated_resources.h"
30 #include "net/base/load_flags.h" 31 #include "net/base/load_flags.h"
31 #include "net/base/net_util.h" 32 #include "net/base/net_util.h"
32 #include "net/url_request/url_fetcher.h" 33 #include "net/url_request/url_fetcher.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 GoogleURLTracker::MapEntry::MapEntry()
181 : infobar(NULL),
182 navigation_controller_source(
183 content::Source<content::NavigationController>(NULL)),
184 tab_contents_source(content::Source<TabContents>(NULL)) {
Ilya Sherman 2012/06/26 05:58:14 nit: Why bother with the initializer list if this
Peter Kasting 2012/06/26 17:38:31 I originally omitted this, but it wouldn't compile
185 NOTREACHED();
186 }
187
188 GoogleURLTracker::MapEntry::MapEntry(
189 GoogleURLTrackerInfoBarDelegate* infobar,
190 const content::NotificationSource& navigation_controller_source,
191 const content::NotificationSource& tab_contents_source)
192 : infobar(infobar),
193 navigation_controller_source(navigation_controller_source),
194 tab_contents_source(tab_contents_source) {
195 }
196
197 GoogleURLTracker::MapEntry::~MapEntry() {
198 }
199
200
163 // GoogleURLTracker ----------------------------------------------------------- 201 // GoogleURLTracker -----------------------------------------------------------
164 202
165 const char GoogleURLTracker::kDefaultGoogleHomepage[] = 203 const char GoogleURLTracker::kDefaultGoogleHomepage[] =
166 "http://www.google.com/"; 204 "http://www.google.com/";
167 const char GoogleURLTracker::kSearchDomainCheckURL[] = 205 const char GoogleURLTracker::kSearchDomainCheckURL[] =
168 "https://www.google.com/searchdomaincheck?format=url&type=chrome"; 206 "https://www.google.com/searchdomaincheck?format=url&type=chrome";
169 207
170 GoogleURLTracker::GoogleURLTracker(Profile* profile, Mode mode) 208 GoogleURLTracker::GoogleURLTracker(Profile* profile, Mode mode)
171 : profile_(profile), 209 : profile_(profile),
172 infobar_creator_(&CreateInfoBar), 210 infobar_creator_(&CreateInfoBar),
173 google_url_(mode == UNIT_TEST_MODE ? kDefaultGoogleHomepage : 211 google_url_(mode == UNIT_TEST_MODE ? kDefaultGoogleHomepage :
174 profile->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)), 212 profile->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)),
175 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), 213 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
176 fetcher_id_(0), 214 fetcher_id_(0),
177 in_startup_sleep_(true), 215 in_startup_sleep_(true),
178 already_fetched_(false), 216 already_fetched_(false),
179 need_to_fetch_(false), 217 need_to_fetch_(false),
180 need_to_prompt_(false) { 218 need_to_prompt_(false),
219 search_committed_(false) {
181 net::NetworkChangeNotifier::AddIPAddressObserver(this); 220 net::NetworkChangeNotifier::AddIPAddressObserver(this);
182 221
183 // Because this function can be called during startup, when kicking off a URL 222 // 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 223 // 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. 224 // 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 225 // 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 226 // browser is starting up, and if so, come back later", but there is currently
188 // no function to do this. 227 // no function to do this.
189 // 228 //
190 // In UNIT_TEST mode, where we want to explicitly control when the tracker 229 // 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 331 // 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 332 // new URL (for e.g. scheme changes). Otherwise we go ahead and close the
294 // existing infobars since their message is out-of-date. 333 // existing infobars since their message is out-of-date.
295 if (!url.is_valid()) // Note: |url| is the previous |fetched_google_url_|. 334 if (!url.is_valid()) // Note: |url| is the previous |fetched_google_url_|.
296 return; 335 return;
297 if (fetched_host != GetHost(url)) { 336 if (fetched_host != GetHost(url)) {
298 CloseAllInfoBars(false); 337 CloseAllInfoBars(false);
299 } else if (fetched_google_url_ != url) { 338 } else if (fetched_google_url_ != url) {
300 for (InfoBarMap::iterator i(infobar_map_.begin()); 339 for (InfoBarMap::iterator i(infobar_map_.begin());
301 i != infobar_map_.end(); ++i) 340 i != infobar_map_.end(); ++i)
302 i->second->SetGoogleURL(fetched_google_url_); 341 i->second.infobar->SetGoogleURL(fetched_google_url_);
303 } 342 }
304 } 343 }
305 } 344 }
306 345
307 void GoogleURLTracker::Observe(int type, 346 void GoogleURLTracker::Observe(int type,
308 const content::NotificationSource& source, 347 const content::NotificationSource& source,
309 const content::NotificationDetails& details) { 348 const content::NotificationDetails& details) {
310 switch (type) { 349 switch (type) {
311 case content::NOTIFICATION_NAV_ENTRY_PENDING: { 350 case content::NOTIFICATION_NAV_ENTRY_PENDING: {
312 content::NavigationController* controller = 351 content::NavigationController* controller =
313 content::Source<content::NavigationController>(source).ptr(); 352 content::Source<content::NavigationController>(source).ptr();
314 TabContents* tab_contents = 353 TabContents* tab_contents =
315 TabContents::FromWebContents(controller->GetWebContents()); 354 TabContents::FromWebContents(controller->GetWebContents());
316 OnNavigationPending(source, 355 OnNavigationPending(source, content::Source<TabContents>(tab_contents),
317 content::Source<TabContents>(tab_contents),
318 tab_contents->infobar_tab_helper(), 356 tab_contents->infobar_tab_helper(),
319 controller->GetPendingEntry()->GetURL()); 357 controller->GetPendingEntry()->GetUniqueID());
320 break; 358 break;
321 } 359 }
322 360
323 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { 361 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: {
324 TabContents* tab_contents = TabContents::FromWebContents( 362 content::NavigationController* controller =
325 content::Source<content::NavigationController>(source)-> 363 content::Source<content::NavigationController>(source).ptr();
326 GetWebContents()); 364 OnNavigationCommittedOrTabClosed(
327 OnNavigationCommittedOrTabClosed(source, 365 TabContents::FromWebContents(controller->GetWebContents())->
328 content::Source<TabContents>(tab_contents), 366 infobar_tab_helper(),
329 tab_contents->infobar_tab_helper(), true); 367 controller->GetActiveEntry()->GetURL());
330 break; 368 break;
331 } 369 }
332 370
333 case chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED: { 371 case chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED: {
334 TabContents* tab_contents = content::Source<TabContents>(source).ptr();
335 OnNavigationCommittedOrTabClosed( 372 OnNavigationCommittedOrTabClosed(
336 content::Source<content::NavigationController>( 373 content::Source<TabContents>(source)->infobar_tab_helper(), GURL());
337 &tab_contents->web_contents()->GetController()), source,
338 tab_contents->infobar_tab_helper(), false);
339 break; 374 break;
340 } 375 }
341 376
342 case chrome::NOTIFICATION_INSTANT_COMMITTED: { 377 case chrome::NOTIFICATION_INSTANT_COMMITTED: {
343 TabContents* tab_contents = content::Source<TabContents>(source).ptr(); 378 TabContents* tab_contents = content::Source<TabContents>(source).ptr();
344 content::WebContents* web_contents = tab_contents->web_contents(); 379 content::WebContents* web_contents = tab_contents->web_contents();
345 content::Source<content::NavigationController> source( 380 content::Source<content::NavigationController> source(
346 &web_contents->GetController()); 381 &web_contents->GetController());
347 content::Source<TabContents> tab_contents_source(tab_contents);
348 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper(); 382 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper();
349 OnNavigationPending(source, tab_contents_source, infobar_helper, 383 OnNavigationPending(source, content::Source<TabContents>(tab_contents),
350 web_contents->GetURL()); 384 infobar_helper, 0);
351 OnNavigationCommittedOrTabClosed(source, tab_contents_source, 385 OnNavigationCommittedOrTabClosed(infobar_helper, web_contents->GetURL());
352 infobar_helper, true);
353 break; 386 break;
354 } 387 }
355 388
356 default: 389 default:
357 NOTREACHED() << "Unknown notification received:" << type; 390 NOTREACHED() << "Unknown notification received:" << type;
358 } 391 }
359 } 392 }
360 393
361 void GoogleURLTracker::OnIPAddressChanged() { 394 void GoogleURLTracker::OnIPAddressChanged() {
362 already_fetched_ = false; 395 already_fetched_ = false;
(...skipping 23 matching lines...) Expand all
386 } 419 }
387 420
388 void GoogleURLTracker::CancelGoogleURL(const GURL& new_google_url) { 421 void GoogleURLTracker::CancelGoogleURL(const GURL& new_google_url) {
389 profile_->GetPrefs()->SetString(prefs::kLastPromptedGoogleURL, 422 profile_->GetPrefs()->SetString(prefs::kLastPromptedGoogleURL,
390 new_google_url.spec()); 423 new_google_url.spec());
391 need_to_prompt_ = false; 424 need_to_prompt_ = false;
392 CloseAllInfoBars(false); 425 CloseAllInfoBars(false);
393 } 426 }
394 427
395 void GoogleURLTracker::InfoBarClosed(const InfoBarTabHelper* infobar_helper) { 428 void GoogleURLTracker::InfoBarClosed(const InfoBarTabHelper* infobar_helper) {
429 DCHECK(!search_committed_);
396 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); 430 InfoBarMap::iterator i(infobar_map_.find(infobar_helper));
397 DCHECK(i != infobar_map_.end()); 431 DCHECK(i != infobar_map_.end());
432 const MapEntry& map_entry = i->second;
433
434 UnregisterForEntrySpecificNotifications(map_entry, false);
398 infobar_map_.erase(i); 435 infobar_map_.erase(i);
436
437 // Our global listeners for these other notifications should be in place iff
438 // we have any non-showing infobars.
439 for (InfoBarMap::const_iterator i(infobar_map_.begin());
440 i != infobar_map_.end(); ++i) {
441 if (!i->second.infobar->showing()) {
442 DCHECK(registrar_.IsRegistered(this,
443 content::NOTIFICATION_NAV_ENTRY_PENDING,
444 content::NotificationService::AllBrowserContextsAndSources()));
445 return;
446 }
447 }
448 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
449 content::NotificationService::AllBrowserContextsAndSources())) {
450 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
451 content::NotificationService::AllBrowserContextsAndSources());
452 registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
453 content::NotificationService::AllBrowserContextsAndSources());
454 }
399 } 455 }
400 456
401 void GoogleURLTracker::SetNeedToFetch() { 457 void GoogleURLTracker::SetNeedToFetch() {
402 need_to_fetch_ = true; 458 need_to_fetch_ = true;
403 StartFetchIfDesirable(); 459 StartFetchIfDesirable();
404 } 460 }
405 461
406 void GoogleURLTracker::FinishSleep() { 462 void GoogleURLTracker::FinishSleep() {
407 in_startup_sleep_ = false; 463 in_startup_sleep_ = false;
408 StartFetchIfDesirable(); 464 StartFetchIfDesirable();
(...skipping 30 matching lines...) Expand all
439 495
440 // Configure to max_retries at most kMaxRetries times for 5xx errors. 496 // Configure to max_retries at most kMaxRetries times for 5xx errors.
441 static const int kMaxRetries = 5; 497 static const int kMaxRetries = 5;
442 fetcher_->SetMaxRetries(kMaxRetries); 498 fetcher_->SetMaxRetries(kMaxRetries);
443 499
444 fetcher_->Start(); 500 fetcher_->Start();
445 } 501 }
446 502
447 void GoogleURLTracker::SearchCommitted() { 503 void GoogleURLTracker::SearchCommitted() {
448 if (need_to_prompt_) { 504 if (need_to_prompt_) {
449 // This notification will fire a bit later in the same call chain we're 505 search_committed_ = true;
506 // These notifications will fire a bit later in the same call chain we're
450 // currently in. 507 // currently in.
451 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING, 508 if (!registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
452 content::NotificationService::AllBrowserContextsAndSources()); 509 content::NotificationService::AllBrowserContextsAndSources())) {
453 registrar_.Add(this, chrome::NOTIFICATION_INSTANT_COMMITTED, 510 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
454 content::NotificationService::AllBrowserContextsAndSources()); 511 content::NotificationService::AllBrowserContextsAndSources());
512 registrar_.Add(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
513 content::NotificationService::AllBrowserContextsAndSources());
514 }
455 } 515 }
456 } 516 }
457 517
458 void GoogleURLTracker::OnNavigationPending( 518 void GoogleURLTracker::OnNavigationPending(
459 const content::NotificationSource& navigation_controller_source, 519 const content::NotificationSource& navigation_controller_source,
460 const content::NotificationSource& tab_contents_source, 520 const content::NotificationSource& tab_contents_source,
461 InfoBarTabHelper* infobar_helper, 521 InfoBarTabHelper* infobar_helper,
462 const GURL& search_url) { 522 int pending_id) {
463 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING, 523 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 524
468 if (registrar_.IsRegistered(this, 525 if (search_committed_) {
469 chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, tab_contents_source)) { 526 search_committed_ = false;
470 // If the previous load hasn't committed and the user triggers a new load, 527 // 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, 528 // 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). 529 // (We may already be registered for this if there is an existing infobar
473 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); 530 // that had a previous pending search that hasn't yet committed.)
474 DCHECK(i != infobar_map_.end()); 531 if (!registrar_.IsRegistered(this,
475 i->second->Close(false); 532 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
533 navigation_controller_source)) {
534 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
535 navigation_controller_source);
536 }
537 if (i == infobar_map_.end()) {
538 // This is a search on a tab that doesn't have one of our infobars, so add
539 // one. Note that we only listen for the tab's destruction on this path;
540 // if there was already an infobar, then either it's not yet showing and
541 // we're already registered for this, or it is showing and its owner will
542 // handle tearing it down when the tab is destroyed.
543 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
544 tab_contents_source);
545 infobar_map_.insert(std::make_pair(infobar_helper, MapEntry(
546 (*infobar_creator_)(infobar_helper, this, fetched_google_url_),
547 navigation_controller_source, tab_contents_source)));
548 } else {
549 // This is a new search on a tab where we already have an infobar (which
550 // may or may not be showing).
551 i->second.infobar->set_pending_id(pending_id);
552 }
553 } else if (i != infobar_map_.end()){
554 if (i->second.infobar->showing()) {
555 // This is a non-search navigation on a tab with a visible infobar. If
556 // there was a previous pending search on this tab, this means it won't
557 // commit, so undo anything we did in response to seeing that. Note that
558 // if there was no pending search on this tab, these statements are
559 // effectively a no-op.
560 //
561 // If this navigation actually commits, that will trigger the infobar's
562 // owner to expire the infobar if need be. If it doesn't commit, then
563 // simply leaving the infobar as-is will have been the right thing.
564 UnregisterForEntrySpecificNotifications(i->second, false);
565 i->second.infobar->set_pending_id(0);
566 } else {
567 // Non-search navigation on a tab with a not-yet-shown infobar. This
568 // means the original search won't commit, so close the infobar.
569 i->second.infobar->Close(false);
570 }
476 } else { 571 } else {
477 // Start listening for the commit notification. We also need to listen for 572 // 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 573 // 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 } 574 }
486
487 infobar_map_[infobar_helper] = (*infobar_creator_)(infobar_helper, search_url,
488 this, fetched_google_url_);
489 } 575 }
490 576
491 void GoogleURLTracker::OnNavigationCommittedOrTabClosed( 577 void GoogleURLTracker::OnNavigationCommittedOrTabClosed(
492 const content::NotificationSource& navigation_controller_source,
493 const content::NotificationSource& tab_contents_source,
494 const InfoBarTabHelper* infobar_helper, 578 const InfoBarTabHelper* infobar_helper,
495 bool navigated) { 579 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)); 580 InfoBarMap::iterator i(infobar_map_.find(infobar_helper));
502 DCHECK(i != infobar_map_.end()); 581 DCHECK(i != infobar_map_.end());
503 DCHECK(need_to_prompt_); 582 const MapEntry& map_entry = i->second;
504 if (navigated) 583
505 i->second->Show(); 584 if (!search_url.is_valid()) {
506 else 585 // 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. 586 // InfoBarClosed() will take care of unregistering the notifications for
587 // this tab.
588 map_entry.infobar->Close(false);
589 return;
590 }
591
592 // We're getting called because of a commit notification, so pass true for
593 // |must_be_listening_for_commit|.
594 UnregisterForEntrySpecificNotifications(map_entry, true);
595 map_entry.infobar->Show(search_url);
508 } 596 }
509 597
510 void GoogleURLTracker::CloseAllInfoBars(bool redo_searches) { 598 void GoogleURLTracker::CloseAllInfoBars(bool redo_searches) {
511 // Close all infobars, whether they've been added to tabs or not. 599 // Close all infobars, whether they've been added to tabs or not.
512 while (!infobar_map_.empty()) 600 while (!infobar_map_.empty())
513 infobar_map_.begin()->second->Close(redo_searches); 601 infobar_map_.begin()->second.infobar->Close(redo_searches);
602 }
514 603
515 // Any registered listeners for NAV_ENTRY_COMMITTED and TAB_CLOSED are now 604 void GoogleURLTracker::UnregisterForEntrySpecificNotifications(
516 // irrelevant as the associated infobars are gone. 605 const MapEntry& map_entry,
517 registrar_.RemoveAll(); 606 bool must_be_listening_for_commit) {
607 // For tabs with non-showing infobars, we should always be listening for both
608 // these notifications. For tabs with showing infobars, we may be listening
609 // for NOTIFICATION_NAV_ENTRY_COMMITTED if the user has performed a new search
610 // on this tab.
611 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
612 map_entry.navigation_controller_source)) {
613 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
614 map_entry.navigation_controller_source);
615 } else {
616 DCHECK(!must_be_listening_for_commit);
617 DCHECK(map_entry.infobar->showing());
618 }
619 const bool registered_for_tab_contents_destroyed =
620 registrar_.IsRegistered(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
621 map_entry.tab_contents_source);
622 DCHECK_NE(registered_for_tab_contents_destroyed,
623 map_entry.infobar->showing());
624 if (registered_for_tab_contents_destroyed) {
625 registrar_.Remove(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
626 map_entry.tab_contents_source);
627 }
518 } 628 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698