OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/google/google_url_tracker.h" | 5 #include "chrome/browser/google/google_url_tracker.h" |
6 | 6 |
7 #include <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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |