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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
10 #include "chrome/browser/google/google_url_tracker_factory.h" | 10 #include "chrome/browser/google/google_url_tracker_factory.h" |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 78 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
79 base::Bind(&GoogleURLTracker::FinishSleep, | 79 base::Bind(&GoogleURLTracker::FinishSleep, |
80 weak_ptr_factory_.GetWeakPtr()), | 80 weak_ptr_factory_.GetWeakPtr()), |
81 base::TimeDelta::FromMilliseconds(kStartFetchDelayMS)); | 81 base::TimeDelta::FromMilliseconds(kStartFetchDelayMS)); |
82 } | 82 } |
83 } | 83 } |
84 | 84 |
85 GoogleURLTracker::~GoogleURLTracker() { | 85 GoogleURLTracker::~GoogleURLTracker() { |
86 // We should only reach here after any tabs and their infobars have been torn | 86 // We should only reach here after any tabs and their infobars have been torn |
87 // down. | 87 // down. |
88 DCHECK(infobar_map_.empty()); | 88 DCHECK(entry_map_.empty()); |
89 } | 89 } |
90 | 90 |
91 // static | 91 // static |
92 GURL GoogleURLTracker::GoogleURL(Profile* profile) { | 92 GURL GoogleURLTracker::GoogleURL(Profile* profile) { |
93 const GoogleURLTracker* tracker = | 93 const GoogleURLTracker* tracker = |
94 GoogleURLTrackerFactory::GetForProfile(profile); | 94 GoogleURLTrackerFactory::GetForProfile(profile); |
95 return tracker ? tracker->google_url_ : GURL(kDefaultGoogleHomepage); | 95 return tracker ? tracker->google_url_ : GURL(kDefaultGoogleHomepage); |
96 } | 96 } |
97 | 97 |
98 // static | 98 // static |
(...skipping 14 matching lines...) Expand all Loading... |
113 UpdatedDetails urls(google_url_, fetched_google_url_); | 113 UpdatedDetails urls(google_url_, fetched_google_url_); |
114 google_url_ = fetched_google_url_; | 114 google_url_ = fetched_google_url_; |
115 PrefService* prefs = profile_->GetPrefs(); | 115 PrefService* prefs = profile_->GetPrefs(); |
116 prefs->SetString(prefs::kLastKnownGoogleURL, google_url_.spec()); | 116 prefs->SetString(prefs::kLastKnownGoogleURL, google_url_.spec()); |
117 prefs->SetString(prefs::kLastPromptedGoogleURL, google_url_.spec()); | 117 prefs->SetString(prefs::kLastPromptedGoogleURL, google_url_.spec()); |
118 content::NotificationService::current()->Notify( | 118 content::NotificationService::current()->Notify( |
119 chrome::NOTIFICATION_GOOGLE_URL_UPDATED, | 119 chrome::NOTIFICATION_GOOGLE_URL_UPDATED, |
120 content::Source<Profile>(profile_), | 120 content::Source<Profile>(profile_), |
121 content::Details<UpdatedDetails>(&urls)); | 121 content::Details<UpdatedDetails>(&urls)); |
122 need_to_prompt_ = false; | 122 need_to_prompt_ = false; |
123 CloseAllInfoBars(redo_searches); | 123 CloseAllEntries(redo_searches); |
124 } | 124 } |
125 | 125 |
126 void GoogleURLTracker::CancelGoogleURL() { | 126 void GoogleURLTracker::CancelGoogleURL() { |
127 profile_->GetPrefs()->SetString(prefs::kLastPromptedGoogleURL, | 127 profile_->GetPrefs()->SetString(prefs::kLastPromptedGoogleURL, |
128 fetched_google_url_.spec()); | 128 fetched_google_url_.spec()); |
129 need_to_prompt_ = false; | 129 need_to_prompt_ = false; |
130 CloseAllInfoBars(false); | 130 CloseAllEntries(false); |
131 } | 131 } |
132 | 132 |
133 void GoogleURLTracker::OnURLFetchComplete(const net::URLFetcher* source) { | 133 void GoogleURLTracker::OnURLFetchComplete(const net::URLFetcher* source) { |
134 // Delete the fetcher on this function's exit. | 134 // Delete the fetcher on this function's exit. |
135 scoped_ptr<net::URLFetcher> clean_up_fetcher(fetcher_.release()); | 135 scoped_ptr<net::URLFetcher> clean_up_fetcher(fetcher_.release()); |
136 | 136 |
137 // Don't update the URL if the request didn't succeed. | 137 // Don't update the URL if the request didn't succeed. |
138 if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200)) { | 138 if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200)) { |
139 already_fetched_ = false; | 139 already_fetched_ = false; |
140 return; | 140 return; |
(...skipping 20 matching lines...) Expand all Loading... |
161 // On the very first run of Chrome, when we've never looked up the URL at | 161 // On the very first run of Chrome, when we've never looked up the URL at |
162 // all, we should just silently switch over to whatever we get immediately. | 162 // all, we should just silently switch over to whatever we get immediately. |
163 AcceptGoogleURL(true); // Arg is irrelevant. | 163 AcceptGoogleURL(true); // Arg is irrelevant. |
164 return; | 164 return; |
165 } | 165 } |
166 | 166 |
167 string16 fetched_host(net::StripWWWFromHost(fetched_google_url_)); | 167 string16 fetched_host(net::StripWWWFromHost(fetched_google_url_)); |
168 if (fetched_google_url_ == google_url_) { | 168 if (fetched_google_url_ == google_url_) { |
169 // Either the user has continually been on this URL, or we prompted for a | 169 // Either the user has continually been on this URL, or we prompted for a |
170 // different URL but have now changed back before they responded to any of | 170 // different URL but have now changed back before they responded to any of |
171 // the prompts. In this latter case we want to close any open infobars and | 171 // the prompts. In this latter case we want to close any infobars and stop |
172 // stop prompting. | 172 // prompting. |
173 CancelGoogleURL(); | 173 CancelGoogleURL(); |
174 } else if (fetched_host == net::StripWWWFromHost(google_url_)) { | 174 } else if (fetched_host == net::StripWWWFromHost(google_url_)) { |
175 // Similar to the above case, but this time the new URL differs from the | 175 // Similar to the above case, but this time the new URL differs from the |
176 // existing one, probably due to switching between HTTP and HTTPS searching. | 176 // existing one, probably due to switching between HTTP and HTTPS searching. |
177 // Like before we want to close any open infobars and stop prompting; we | 177 // Like before we want to close any infobars and stop prompting; we also |
178 // also want to silently accept the change in scheme. We don't redo open | 178 // want to silently accept the change in scheme. We don't redo open |
179 // searches so as to avoid suddenly changing a page the user might be | 179 // searches so as to avoid suddenly changing a page the user might be |
180 // interacting with; it's enough to simply get future searches right. | 180 // interacting with; it's enough to simply get future searches right. |
181 AcceptGoogleURL(false); | 181 AcceptGoogleURL(false); |
182 } else if (fetched_host == net::StripWWWFromHost(last_prompted_url)) { | 182 } else if (fetched_host == net::StripWWWFromHost(last_prompted_url)) { |
183 // We've re-fetched a TLD the user previously turned down. Although the new | 183 // We've re-fetched a TLD the user previously turned down. Although the new |
184 // URL might have a different scheme than the old, we want to preserve the | 184 // URL might have a different scheme than the old, we want to preserve the |
185 // user's decision. Note that it's possible that, like in the above two | 185 // user's decision. Note that it's possible that, like in the above two |
186 // cases, we fetched yet another different URL in the meantime, which we | 186 // cases, we fetched yet another different URL in the meantime, which we |
187 // have open infobars prompting about; in this case, as in those above, we | 187 // have infobars prompting about; in this case, as in those above, we want |
188 // want to go ahead and close the infobars and stop prompting, since we've | 188 // to go ahead and close the infobars and stop prompting, since we've |
189 // switched back away from that URL. | 189 // switched back away from that URL. |
190 CancelGoogleURL(); | 190 CancelGoogleURL(); |
191 } else { | 191 } else { |
192 // We've fetched a URL with a different TLD than the user is currently using | 192 // We've fetched a URL with a different TLD than the user is currently using |
193 // or was previously prompted about. This means we need to prompt again. | 193 // or was previously prompted about. This means we need to prompt again. |
194 need_to_prompt_ = true; | 194 need_to_prompt_ = true; |
195 | 195 |
196 // As in all the above cases, there could be open infobars prompting about | 196 // As in all the above cases, there could be infobars prompting about some |
197 // some URL. If these URLs have the same TLD (e.g. for scheme changes), we | 197 // URL. If these URLs have the same TLD (e.g. for scheme changes), we can |
198 // can simply leave the existing infobars open as their messages will still | 198 // simply leave the existing infobars open as their messages will still be |
199 // be accurate. Otherwise we go ahead and close them because we need to | 199 // accurate. Otherwise we go ahead and close them because we need to |
200 // display a new message. | 200 // display a new message. |
201 // Note: |url| is the previous |fetched_google_url_|. | 201 // Note: |url| is the previous |fetched_google_url_|. |
202 if (url.is_valid() && (fetched_host != net::StripWWWFromHost(url))) | 202 if (url.is_valid() && (fetched_host != net::StripWWWFromHost(url))) |
203 CloseAllInfoBars(false); | 203 CloseAllEntries(false); |
204 } | 204 } |
205 } | 205 } |
206 | 206 |
207 void GoogleURLTracker::Observe(int type, | 207 void GoogleURLTracker::Observe(int type, |
208 const content::NotificationSource& source, | 208 const content::NotificationSource& source, |
209 const content::NotificationDetails& details) { | 209 const content::NotificationDetails& details) { |
210 switch (type) { | 210 switch (type) { |
211 case content::NOTIFICATION_NAV_ENTRY_PENDING: { | 211 case content::NOTIFICATION_NAV_ENTRY_PENDING: { |
212 content::NavigationController* controller = | 212 content::NavigationController* controller = |
213 content::Source<content::NavigationController>(source).ptr(); | 213 content::Source<content::NavigationController>(source).ptr(); |
214 content::WebContents* web_contents = controller->GetWebContents(); | 214 content::WebContents* web_contents = controller->GetWebContents(); |
215 InfoBarTabHelper* infobar_tab_helper = | 215 InfoBarTabHelper* infobar_tab_helper = |
216 InfoBarTabHelper::FromWebContents(web_contents); | 216 InfoBarTabHelper::FromWebContents(web_contents); |
217 // Because we're listening to all sources, there may be no | 217 // Because we're listening to all sources, there may be no |
218 // InfoBarTabHelper for some notifications, e.g. navigations in | 218 // InfoBarTabHelper for some notifications, e.g. navigations in |
219 // bubbles/balloons etc. | 219 // bubbles/balloons etc. |
220 if (infobar_tab_helper) { | 220 if (infobar_tab_helper) { |
221 OnNavigationPending( | 221 OnNavigationPending( |
222 source, content::Source<content::WebContents>(web_contents), | 222 source, content::Source<content::WebContents>(web_contents), |
223 infobar_tab_helper, controller->GetPendingEntry()->GetUniqueID()); | 223 infobar_tab_helper, controller->GetPendingEntry()->GetUniqueID()); |
224 } | 224 } |
225 break; | 225 break; |
226 } | 226 } |
227 | 227 |
228 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { | 228 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { |
229 content::NavigationController* controller = | 229 content::NavigationController* controller = |
230 content::Source<content::NavigationController>(source).ptr(); | 230 content::Source<content::NavigationController>(source).ptr(); |
231 // Here we're only listening to notifications where we already know | 231 // Here we're only listening to notifications where we already know |
232 // there's an associated InfoBarTabHelper. | 232 // there's an associated InfoBarTabHelper. |
| 233 content::WebContents* web_contents = controller->GetWebContents(); |
233 InfoBarTabHelper* infobar_tab_helper = | 234 InfoBarTabHelper* infobar_tab_helper = |
234 InfoBarTabHelper::FromWebContents(controller->GetWebContents()); | 235 InfoBarTabHelper::FromWebContents(web_contents); |
235 DCHECK(infobar_tab_helper); | 236 DCHECK(infobar_tab_helper); |
236 OnNavigationCommittedOrTabClosed(infobar_tab_helper, | 237 const GURL& search_url = controller->GetActiveEntry()->GetURL(); |
237 controller->GetActiveEntry()->GetURL()); | 238 if (!search_url.is_valid()) // Not clear if this can happen. |
| 239 OnTabClosed(content::Source<content::WebContents>(web_contents)); |
| 240 OnNavigationCommitted(infobar_tab_helper, search_url); |
238 break; | 241 break; |
239 } | 242 } |
240 | 243 |
241 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: | 244 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: |
242 OnNavigationCommittedOrTabClosed( | 245 OnTabClosed(source); |
243 InfoBarTabHelper::FromWebContents( | |
244 content::Source<content::WebContents>(source).ptr()), GURL()); | |
245 break; | 246 break; |
246 | 247 |
247 case chrome::NOTIFICATION_INSTANT_COMMITTED: { | 248 case chrome::NOTIFICATION_INSTANT_COMMITTED: { |
248 content::WebContents* web_contents = | 249 content::WebContents* web_contents = |
249 content::Source<content::WebContents>(source).ptr(); | 250 content::Source<content::WebContents>(source).ptr(); |
250 OnInstantCommitted(content::Source<content::NavigationController>( | 251 const GURL& search_url = web_contents->GetURL(); |
251 &web_contents->GetController()), | 252 if (!search_url.is_valid()) // Not clear if this can happen. |
252 source, | 253 OnTabClosed(source); |
253 InfoBarTabHelper::FromWebContents(web_contents), | 254 OnInstantCommitted( |
254 web_contents->GetURL()); | 255 content::Source<content::NavigationController>( |
| 256 &web_contents->GetController()), |
| 257 source, InfoBarTabHelper::FromWebContents(web_contents), search_url); |
255 break; | 258 break; |
256 } | 259 } |
257 | 260 |
258 default: | 261 default: |
259 NOTREACHED() << "Unknown notification received:" << type; | 262 NOTREACHED() << "Unknown notification received:" << type; |
260 } | 263 } |
261 } | 264 } |
262 | 265 |
263 void GoogleURLTracker::OnIPAddressChanged() { | 266 void GoogleURLTracker::OnIPAddressChanged() { |
264 already_fetched_ = false; | 267 already_fetched_ = false; |
265 StartFetchIfDesirable(); | 268 StartFetchIfDesirable(); |
266 } | 269 } |
267 | 270 |
268 void GoogleURLTracker::Shutdown() { | 271 void GoogleURLTracker::Shutdown() { |
269 registrar_.RemoveAll(); | 272 registrar_.RemoveAll(); |
270 weak_ptr_factory_.InvalidateWeakPtrs(); | 273 weak_ptr_factory_.InvalidateWeakPtrs(); |
271 fetcher_.reset(); | 274 fetcher_.reset(); |
272 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); | 275 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); |
273 } | 276 } |
274 | 277 |
275 void GoogleURLTracker::DeleteMapEntryForHelper( | 278 void GoogleURLTracker::DeleteMapEntryForHelper( |
276 const InfoBarTabHelper* infobar_helper) { | 279 const InfoBarTabHelper* infobar_helper) { |
277 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); | 280 // WARNING: |infobar_helper| may point to a deleted object. Do not |
278 DCHECK(i != infobar_map_.end()); | 281 // dereference it! See OnTabClosed(). |
| 282 EntryMap::iterator i(entry_map_.find(infobar_helper)); |
| 283 DCHECK(i != entry_map_.end()); |
279 GoogleURLTrackerMapEntry* map_entry = i->second; | 284 GoogleURLTrackerMapEntry* map_entry = i->second; |
280 | 285 |
281 UnregisterForEntrySpecificNotifications(*map_entry, false); | 286 UnregisterForEntrySpecificNotifications(*map_entry, false); |
282 infobar_map_.erase(i); | 287 entry_map_.erase(i); |
283 delete map_entry; | 288 delete map_entry; |
284 } | 289 } |
285 | 290 |
286 void GoogleURLTracker::SetNeedToFetch() { | 291 void GoogleURLTracker::SetNeedToFetch() { |
287 need_to_fetch_ = true; | 292 need_to_fetch_ = true; |
288 StartFetchIfDesirable(); | 293 StartFetchIfDesirable(); |
289 } | 294 } |
290 | 295 |
291 void GoogleURLTracker::FinishSleep() { | 296 void GoogleURLTracker::FinishSleep() { |
292 in_startup_sleep_ = false; | 297 in_startup_sleep_ = false; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 content::NotificationService::AllBrowserContextsAndSources()); | 347 content::NotificationService::AllBrowserContextsAndSources()); |
343 } | 348 } |
344 } | 349 } |
345 } | 350 } |
346 | 351 |
347 void GoogleURLTracker::OnNavigationPending( | 352 void GoogleURLTracker::OnNavigationPending( |
348 const content::NotificationSource& navigation_controller_source, | 353 const content::NotificationSource& navigation_controller_source, |
349 const content::NotificationSource& web_contents_source, | 354 const content::NotificationSource& web_contents_source, |
350 InfoBarTabHelper* infobar_helper, | 355 InfoBarTabHelper* infobar_helper, |
351 int pending_id) { | 356 int pending_id) { |
352 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); | 357 EntryMap::iterator i(entry_map_.find(infobar_helper)); |
353 | 358 |
354 if (search_committed_) { | 359 if (search_committed_) { |
355 search_committed_ = false; | 360 search_committed_ = false; |
356 // Whether there's an existing infobar or not, we need to listen for the | 361 // Whether there's an existing infobar or not, we need to listen for the |
357 // load to commit, so we can show and/or update the infobar when it does. | 362 // load to commit, so we can show and/or update the infobar when it does. |
358 // (We may already be registered for this if there is an existing infobar | 363 // (We may already be registered for this if there is an existing infobar |
359 // that had a previous pending search that hasn't yet committed.) | 364 // that had a previous pending search that hasn't yet committed.) |
360 if (!registrar_.IsRegistered(this, | 365 if (!registrar_.IsRegistered(this, |
361 content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 366 content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
362 navigation_controller_source)) { | 367 navigation_controller_source)) { |
363 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 368 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
364 navigation_controller_source); | 369 navigation_controller_source); |
365 } | 370 } |
366 if (i == infobar_map_.end()) { | 371 if (i == entry_map_.end()) { |
367 // This is a search on a tab that doesn't have one of our infobars, so | 372 // This is a search on a tab that doesn't have one of our infobars, so |
368 // prepare to add one. Note that we only listen for the tab's destruction | 373 // prepare to add one. Note that we only listen for the tab's destruction |
369 // on this path; if there was already a map entry, then either it doesn't | 374 // on this path; if there was already a map entry, then either it doesn't |
370 // yet have an infobar and we're already registered for this, or it has an | 375 // yet have an infobar and we're already registered for this, or it has an |
371 // infobar and the infobar's owner will handle tearing it down when the | 376 // infobar and the infobar's owner will handle tearing it down when the |
372 // tab is destroyed. | 377 // tab is destroyed. |
373 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 378 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
374 web_contents_source); | 379 web_contents_source); |
375 infobar_map_.insert(std::make_pair( | 380 entry_map_.insert(std::make_pair( |
376 infobar_helper, | 381 infobar_helper, |
377 new GoogleURLTrackerMapEntry(this, infobar_helper, | 382 new GoogleURLTrackerMapEntry(this, infobar_helper, |
378 navigation_controller_source, | 383 navigation_controller_source, |
379 web_contents_source))); | 384 web_contents_source))); |
380 } else if (i->second->has_infobar()) { | 385 } else if (i->second->has_infobar()) { |
381 // This is a new search on a tab where we already have a visible infobar. | 386 // This is a new search on a tab where we already have an infobar. |
382 i->second->infobar()->set_pending_id(pending_id); | 387 i->second->infobar()->set_pending_id(pending_id); |
383 } | 388 } |
384 } else if (i != infobar_map_.end()){ | 389 } else if (i != entry_map_.end()){ |
385 if (i->second->has_infobar()) { | 390 if (i->second->has_infobar()) { |
386 // This is a non-search navigation on a tab with a visible infobar. If | 391 // This is a non-search navigation on a tab with an infobar. If there was |
387 // there was a previous pending search on this tab, this means it won't | 392 // a previous pending search on this tab, this means it won't commit, so |
388 // commit, so undo anything we did in response to seeing that. Note that | 393 // undo anything we did in response to seeing that. Note that if there |
389 // if there was no pending search on this tab, these statements are | 394 // was no pending search on this tab, these statements are effectively a |
390 // effectively a no-op. | 395 // no-op. |
391 // | 396 // |
392 // If this navigation actually commits, that will trigger the infobar's | 397 // If this navigation actually commits, that will trigger the infobar's |
393 // owner to expire the infobar if need be. If it doesn't commit, then | 398 // owner to expire the infobar if need be. If it doesn't commit, then |
394 // simply leaving the infobar as-is will have been the right thing. | 399 // simply leaving the infobar as-is will have been the right thing. |
395 UnregisterForEntrySpecificNotifications(*i->second, false); | 400 UnregisterForEntrySpecificNotifications(*i->second, false); |
396 i->second->infobar()->set_pending_id(0); | 401 i->second->infobar()->set_pending_id(0); |
397 } else { | 402 } else { |
398 // Non-search navigation on a tab with an entry that has not yet created | 403 // Non-search navigation on a tab with an entry that has not yet created |
399 // an infobar. This means the original search won't commit, so delete the | 404 // an infobar. This means the original search won't commit, so delete the |
400 // entry. | 405 // entry. |
401 i->second->Close(false); | 406 i->second->Close(false); |
402 } | 407 } |
403 } else { | 408 } else { |
404 // Non-search navigation on a tab without one of our infobars. This is | 409 // Non-search navigation on a tab without an infobars. This is irrelevant |
405 // irrelevant to us. | 410 // to us. |
406 } | 411 } |
407 } | 412 } |
408 | 413 |
409 void GoogleURLTracker::OnNavigationCommittedOrTabClosed( | 414 void GoogleURLTracker::OnNavigationCommitted(InfoBarTabHelper* infobar_helper, |
410 InfoBarTabHelper* infobar_helper, | 415 const GURL& search_url) { |
411 const GURL& search_url) { | 416 EntryMap::iterator i(entry_map_.find(infobar_helper)); |
412 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); | 417 DCHECK(i != entry_map_.end()); |
413 DCHECK(i != infobar_map_.end()); | |
414 GoogleURLTrackerMapEntry* map_entry = i->second; | 418 GoogleURLTrackerMapEntry* map_entry = i->second; |
| 419 DCHECK(search_url.is_valid()); |
415 | 420 |
416 if (!search_url.is_valid()) { | |
417 // Tab closed, or we somehow tried to navigate to an invalid URL (?!). | |
418 // DeleteMapEntryForHelper() will take care of unregistering the | |
419 // notifications for this tab. | |
420 map_entry->Close(false); | |
421 return; | |
422 } | |
423 | |
424 // We're getting called because of a commit notification, so pass true for | |
425 // |must_be_listening_for_commit|. | |
426 UnregisterForEntrySpecificNotifications(*map_entry, true); | 421 UnregisterForEntrySpecificNotifications(*map_entry, true); |
427 if (map_entry->has_infobar()) { | 422 if (map_entry->has_infobar()) { |
428 map_entry->infobar()->Update(search_url); | 423 map_entry->infobar()->Update(search_url); |
429 } else { | 424 } else { |
430 GoogleURLTrackerInfoBarDelegate* infobar_delegate = | 425 GoogleURLTrackerInfoBarDelegate* infobar_delegate = |
431 infobar_creator_.Run(infobar_helper, this, search_url); | 426 infobar_creator_.Run(infobar_helper, this, search_url); |
432 if (infobar_delegate) | 427 if (infobar_delegate) |
433 map_entry->SetInfoBar(infobar_delegate); | 428 map_entry->SetInfoBar(infobar_delegate); |
434 else | 429 else |
435 map_entry->Close(false); | 430 map_entry->Close(false); |
436 } | 431 } |
437 } | 432 } |
438 | 433 |
| 434 void GoogleURLTracker::OnTabClosed( |
| 435 const content::NotificationSource& web_contents_source) { |
| 436 // Because InfoBarTabHelper tears itself down in response to |
| 437 // NOTIFICATION_WEB_CONTENTS_DESTROYED, it may or may not be possible to |
| 438 // get a non-NULL pointer back from InfoBarTabHelper::FromWebContents() here, |
| 439 // depending on which order notifications fired in. Likewise, the pointer in |
| 440 // |entry_map_| (and in its associated MapEntry) may point to deleted memory. |
| 441 // Therefore, if we were to access to the InfoBarTabHelper* we have for this |
| 442 // tab, we'd need to ensure we just looked at the raw pointer value, and never |
| 443 // dereferenced it. This function doesn't need to do even that, but others in |
| 444 // the call chain from here might (and have comments pointing back here). |
| 445 for (EntryMap::iterator i(entry_map_.begin()); i != entry_map_.end(); ++i) { |
| 446 if (i->second->web_contents_source() == web_contents_source) { |
| 447 i->second->Close(false); |
| 448 return; |
| 449 } |
| 450 } |
| 451 NOTREACHED(); |
| 452 } |
| 453 |
439 void GoogleURLTracker::OnInstantCommitted( | 454 void GoogleURLTracker::OnInstantCommitted( |
440 const content::NotificationSource& navigation_controller_source, | 455 const content::NotificationSource& navigation_controller_source, |
441 const content::NotificationSource& web_contents_source, | 456 const content::NotificationSource& web_contents_source, |
442 InfoBarTabHelper* infobar_helper, | 457 InfoBarTabHelper* infobar_helper, |
443 const GURL& search_url) { | 458 const GURL& search_url) { |
444 // If this was the search we were listening for, OnNavigationPending() should | 459 // If this was the search we were listening for, OnNavigationPending() should |
445 // ensure we're registered for NAV_ENTRY_COMMITTED, and we should call | 460 // ensure we're registered for NAV_ENTRY_COMMITTED, and we should call |
446 // OnNavigationCommittedOrTabClosed() to simulate that firing. Otherwise, | 461 // OnNavigationCommitted() to simulate that firing. Otherwise, this is some |
447 // this is some sort of non-search navigation, so while we should still call | 462 // sort of non-search navigation, so while we should still call |
448 // OnNavigationPending(), that function should then ensure that we're not | 463 // OnNavigationPending(), that function should then ensure that we're not |
449 // listening for NAV_ENTRY_COMMITTED on this tab, and we should not call | 464 // listening for NAV_ENTRY_COMMITTED on this tab, and we should not call |
450 // OnNavigationCommittedOrTabClosed() afterwards. Note that we need to save | 465 // OnNavigationCommitted() afterwards. Note that we need to save off |
451 // off |search_committed_| here because OnNavigationPending() will reset it. | 466 // |search_committed_| here because OnNavigationPending() will reset it. |
452 bool was_search_committed = search_committed_; | 467 bool was_search_committed = search_committed_; |
453 OnNavigationPending(navigation_controller_source, web_contents_source, | 468 OnNavigationPending(navigation_controller_source, web_contents_source, |
454 infobar_helper, 0); | 469 infobar_helper, 0); |
455 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); | 470 EntryMap::iterator i(entry_map_.find(infobar_helper)); |
456 DCHECK_EQ(was_search_committed, (i != infobar_map_.end()) && | 471 DCHECK_EQ(was_search_committed, (i != entry_map_.end()) && |
457 registrar_.IsRegistered(this, | 472 registrar_.IsRegistered(this, |
458 content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 473 content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
459 i->second->navigation_controller_source())); | 474 i->second->navigation_controller_source())); |
460 if (was_search_committed) | 475 if (was_search_committed) |
461 OnNavigationCommittedOrTabClosed(infobar_helper, search_url); | 476 OnNavigationCommitted(infobar_helper, search_url); |
462 } | 477 } |
463 | 478 |
464 void GoogleURLTracker::CloseAllInfoBars(bool redo_searches) { | 479 void GoogleURLTracker::CloseAllEntries(bool redo_searches) { |
465 // Delete all entries, whether they have infobars or not. | 480 // Delete all entries, whether they have infobars or not. |
466 while (!infobar_map_.empty()) | 481 while (!entry_map_.empty()) |
467 infobar_map_.begin()->second->Close(redo_searches); | 482 entry_map_.begin()->second->Close(redo_searches); |
468 } | 483 } |
469 | 484 |
470 void GoogleURLTracker::UnregisterForEntrySpecificNotifications( | 485 void GoogleURLTracker::UnregisterForEntrySpecificNotifications( |
471 const GoogleURLTrackerMapEntry& map_entry, | 486 const GoogleURLTrackerMapEntry& map_entry, |
472 bool must_be_listening_for_commit) { | 487 bool must_be_listening_for_commit) { |
473 // For tabs with non-showing infobars, we should always be listening for both | 488 // For tabs with map entries but no infobars, we should always be listening |
474 // these notifications. For tabs with showing infobars, we may be listening | 489 // for both these notifications. For tabs with infobars, we may be listening |
475 // for NOTIFICATION_NAV_ENTRY_COMMITTED if the user has performed a new search | 490 // for NOTIFICATION_NAV_ENTRY_COMMITTED if the user has performed a new search |
476 // on this tab. | 491 // on this tab. |
477 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 492 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
478 map_entry.navigation_controller_source())) { | 493 map_entry.navigation_controller_source())) { |
479 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 494 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
480 map_entry.navigation_controller_source()); | 495 map_entry.navigation_controller_source()); |
481 } else { | 496 } else { |
482 DCHECK(!must_be_listening_for_commit); | 497 DCHECK(!must_be_listening_for_commit); |
483 DCHECK(map_entry.has_infobar()); | 498 DCHECK(map_entry.has_infobar()); |
484 } | 499 } |
485 const bool registered_for_web_contents_destroyed = registrar_.IsRegistered( | 500 const bool registered_for_web_contents_destroyed = registrar_.IsRegistered( |
486 this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 501 this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
487 map_entry.web_contents_source()); | 502 map_entry.web_contents_source()); |
488 DCHECK_NE(registered_for_web_contents_destroyed, map_entry.has_infobar()); | 503 DCHECK_NE(registered_for_web_contents_destroyed, map_entry.has_infobar()); |
489 if (registered_for_web_contents_destroyed) { | 504 if (registered_for_web_contents_destroyed) { |
490 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 505 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
491 map_entry.web_contents_source()); | 506 map_entry.web_contents_source()); |
492 } | 507 } |
493 | 508 |
494 // Our global listeners for these other notifications should be in place iff | 509 // Our global listeners for these other notifications should be in place iff |
495 // we have any infobars still listening for commits. These infobars are | 510 // we have any tabs still listening for commits. These tabs either have no |
496 // either not yet shown or have received a new pending search atop an existing | 511 // infobars or have received new pending searches atop existing infobars; in |
497 // infobar; in either case we want to catch subsequent pending non-search | 512 // either case we want to catch subsequent pending non-search navigations. |
498 // navigations. See the various cases inside OnNavigationPending(). | 513 // See the various cases inside OnNavigationPending(). |
499 for (InfoBarMap::const_iterator i(infobar_map_.begin()); | 514 for (EntryMap::const_iterator i(entry_map_.begin()); i != entry_map_.end(); |
500 i != infobar_map_.end(); ++i) { | 515 ++i) { |
501 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 516 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
502 i->second->navigation_controller_source())) { | 517 i->second->navigation_controller_source())) { |
503 DCHECK(registrar_.IsRegistered(this, | 518 DCHECK(registrar_.IsRegistered(this, |
504 content::NOTIFICATION_NAV_ENTRY_PENDING, | 519 content::NOTIFICATION_NAV_ENTRY_PENDING, |
505 content::NotificationService::AllBrowserContextsAndSources())); | 520 content::NotificationService::AllBrowserContextsAndSources())); |
506 return; | 521 return; |
507 } | 522 } |
508 } | 523 } |
509 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_PENDING, | 524 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_PENDING, |
510 content::NotificationService::AllBrowserContextsAndSources())) { | 525 content::NotificationService::AllBrowserContextsAndSources())) { |
511 DCHECK(!search_committed_); | 526 DCHECK(!search_committed_); |
512 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING, | 527 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING, |
513 content::NotificationService::AllBrowserContextsAndSources()); | 528 content::NotificationService::AllBrowserContextsAndSources()); |
514 registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_COMMITTED, | 529 registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_COMMITTED, |
515 content::NotificationService::AllBrowserContextsAndSources()); | 530 content::NotificationService::AllBrowserContextsAndSources()); |
516 } | 531 } |
517 } | 532 } |
OLD | NEW |