| 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" |
| 11 #include "chrome/browser/google/google_url_tracker_infobar_delegate.h" | 11 #include "chrome/browser/google/google_url_tracker_infobar_delegate.h" |
| 12 #include "chrome/browser/google/google_util.h" | 12 #include "chrome/browser/google/google_util.h" |
| 13 #include "chrome/browser/infobars/infobar_tab_helper.h" | 13 #include "chrome/browser/infobars/infobar_tab_helper.h" |
| 14 #include "chrome/browser/prefs/pref_service.h" | 14 #include "chrome/browser/prefs/pref_service.h" |
| 15 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 16 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| 17 #include "chrome/common/chrome_notification_types.h" | 17 #include "chrome/common/chrome_notification_types.h" |
| 18 #include "chrome/common/chrome_switches.h" | 18 #include "chrome/common/chrome_switches.h" |
| 19 #include "chrome/common/pref_names.h" | 19 #include "chrome/common/pref_names.h" |
| 20 #include "content/public/browser/navigation_controller.h" | 20 #include "content/public/browser/navigation_controller.h" |
| 21 #include "content/public/browser/navigation_entry.h" | 21 #include "content/public/browser/navigation_entry.h" |
| 22 #include "content/public/browser/notification_service.h" | 22 #include "content/public/browser/notification_service.h" |
| 23 #include "content/public/browser/web_contents.h" | 23 #include "content/public/browser/web_contents.h" |
| 24 #include "net/base/load_flags.h" | 24 #include "net/base/load_flags.h" |
| 25 #include "net/base/net_util.h" | 25 #include "net/base/net_util.h" |
| 26 #include "net/url_request/url_fetcher.h" | 26 #include "net/url_request/url_fetcher.h" |
| 27 #include "net/url_request/url_request_status.h" | 27 #include "net/url_request/url_request_status.h" |
| 28 | 28 |
| 29 |
| 29 namespace { | 30 namespace { |
| 30 | 31 |
| 31 GoogleURLTrackerInfoBarDelegate* CreateInfoBar( | 32 GoogleURLTrackerInfoBarDelegate* CreateInfoBar( |
| 32 InfoBarTabHelper* infobar_helper, | 33 InfoBarTabHelper* infobar_helper, |
| 33 GoogleURLTracker* google_url_tracker, | 34 GoogleURLTracker* google_url_tracker, |
| 34 const GURL& new_google_url) { | 35 const GURL& search_url) { |
| 35 return new GoogleURLTrackerInfoBarDelegate(infobar_helper, google_url_tracker, | 36 GoogleURLTrackerInfoBarDelegate* infobar = |
| 36 new_google_url); | 37 new GoogleURLTrackerInfoBarDelegate(infobar_helper, google_url_tracker, |
| 38 search_url); |
| 39 // AddInfoBar() takes ownership; it will delete |infobar| if it fails. |
| 40 return infobar_helper->AddInfoBar(infobar) ? infobar : NULL; |
| 37 } | 41 } |
| 38 | 42 |
| 39 } // namespace | 43 } // namespace |
| 40 | 44 |
| 41 | 45 |
| 42 // GoogleURLTracker::MapEntry ------------------------------------------------- | |
| 43 | |
| 44 // Note that we have to initialize at least the NotificationSources explicitly | |
| 45 // lest this not compile, because NotificationSource has no null constructor. | |
| 46 GoogleURLTracker::MapEntry::MapEntry() | |
| 47 : infobar(NULL), | |
| 48 navigation_controller_source( | |
| 49 content::Source<content::NavigationController>(NULL)), | |
| 50 web_contents_source(content::Source<content::WebContents>(NULL)) { | |
| 51 NOTREACHED(); | |
| 52 } | |
| 53 | |
| 54 GoogleURLTracker::MapEntry::MapEntry( | |
| 55 GoogleURLTrackerInfoBarDelegate* infobar, | |
| 56 const content::NotificationSource& navigation_controller_source, | |
| 57 const content::NotificationSource& web_contents_source) | |
| 58 : infobar(infobar), | |
| 59 navigation_controller_source(navigation_controller_source), | |
| 60 web_contents_source(web_contents_source) { | |
| 61 } | |
| 62 | |
| 63 GoogleURLTracker::MapEntry::~MapEntry() { | |
| 64 } | |
| 65 | |
| 66 | |
| 67 // GoogleURLTracker ----------------------------------------------------------- | 46 // GoogleURLTracker ----------------------------------------------------------- |
| 68 | 47 |
| 69 const char GoogleURLTracker::kDefaultGoogleHomepage[] = | 48 const char GoogleURLTracker::kDefaultGoogleHomepage[] = |
| 70 "http://www.google.com/"; | 49 "http://www.google.com/"; |
| 71 const char GoogleURLTracker::kSearchDomainCheckURL[] = | 50 const char GoogleURLTracker::kSearchDomainCheckURL[] = |
| 72 "https://www.google.com/searchdomaincheck?format=url&type=chrome"; | 51 "https://www.google.com/searchdomaincheck?format=url&type=chrome"; |
| 73 | 52 |
| 74 GoogleURLTracker::GoogleURLTracker(Profile* profile, Mode mode) | 53 GoogleURLTracker::GoogleURLTracker(Profile* profile, Mode mode) |
| 75 : profile_(profile), | 54 : profile_(profile), |
| 76 infobar_creator_(&CreateInfoBar), | 55 infobar_creator_(base::Bind(&CreateInfoBar)), |
| 77 google_url_(mode == UNIT_TEST_MODE ? kDefaultGoogleHomepage : | 56 google_url_(mode == UNIT_TEST_MODE ? kDefaultGoogleHomepage : |
| 78 profile->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)), | 57 profile->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)), |
| 79 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | 58 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
| 80 fetcher_id_(0), | 59 fetcher_id_(0), |
| 81 in_startup_sleep_(true), | 60 in_startup_sleep_(true), |
| 82 already_fetched_(false), | 61 already_fetched_(false), |
| 83 need_to_fetch_(false), | 62 need_to_fetch_(false), |
| 84 need_to_prompt_(false), | 63 need_to_prompt_(false), |
| 85 search_committed_(false) { | 64 search_committed_(false) { |
| 86 net::NetworkChangeNotifier::AddIPAddressObserver(this); | 65 net::NetworkChangeNotifier::AddIPAddressObserver(this); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 tracker->SetNeedToFetch(); | 102 tracker->SetNeedToFetch(); |
| 124 } | 103 } |
| 125 | 104 |
| 126 // static | 105 // static |
| 127 void GoogleURLTracker::GoogleURLSearchCommitted(Profile* profile) { | 106 void GoogleURLTracker::GoogleURLSearchCommitted(Profile* profile) { |
| 128 GoogleURLTracker* tracker = GoogleURLTrackerFactory::GetForProfile(profile); | 107 GoogleURLTracker* tracker = GoogleURLTrackerFactory::GetForProfile(profile); |
| 129 if (tracker) | 108 if (tracker) |
| 130 tracker->SearchCommitted(); | 109 tracker->SearchCommitted(); |
| 131 } | 110 } |
| 132 | 111 |
| 112 void GoogleURLTracker::AcceptGoogleURL(bool redo_searches) { |
| 113 UpdatedDetails urls(google_url_, fetched_google_url_); |
| 114 google_url_ = fetched_google_url_; |
| 115 PrefService* prefs = profile_->GetPrefs(); |
| 116 prefs->SetString(prefs::kLastKnownGoogleURL, google_url_.spec()); |
| 117 prefs->SetString(prefs::kLastPromptedGoogleURL, google_url_.spec()); |
| 118 content::NotificationService::current()->Notify( |
| 119 chrome::NOTIFICATION_GOOGLE_URL_UPDATED, |
| 120 content::Source<Profile>(profile_), |
| 121 content::Details<UpdatedDetails>(&urls)); |
| 122 need_to_prompt_ = false; |
| 123 CloseAllInfoBars(redo_searches); |
| 124 } |
| 125 |
| 126 void GoogleURLTracker::CancelGoogleURL() { |
| 127 profile_->GetPrefs()->SetString(prefs::kLastPromptedGoogleURL, |
| 128 fetched_google_url_.spec()); |
| 129 need_to_prompt_ = false; |
| 130 CloseAllInfoBars(false); |
| 131 } |
| 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; |
| 141 } | 141 } |
| 142 | 142 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 153 google_util::DISALLOW_NON_STANDARD_PORTS)) | 153 google_util::DISALLOW_NON_STANDARD_PORTS)) |
| 154 return; | 154 return; |
| 155 | 155 |
| 156 std::swap(url, fetched_google_url_); | 156 std::swap(url, fetched_google_url_); |
| 157 GURL last_prompted_url( | 157 GURL last_prompted_url( |
| 158 profile_->GetPrefs()->GetString(prefs::kLastPromptedGoogleURL)); | 158 profile_->GetPrefs()->GetString(prefs::kLastPromptedGoogleURL)); |
| 159 | 159 |
| 160 if (last_prompted_url.is_empty()) { | 160 if (last_prompted_url.is_empty()) { |
| 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(fetched_google_url_, true); // Second 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 open infobars and |
| 172 // stop prompting. | 172 // stop prompting. |
| 173 CancelGoogleURL(fetched_google_url_); | 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 open infobars and stop prompting; we |
| 178 // also want to silently accept the change in scheme. We don't redo open | 178 // also 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(fetched_google_url_, 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 open infobars prompting about; in this case, as in those above, we |
| 188 // want to go ahead and close the infobars and stop prompting, since we've | 188 // want 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(fetched_google_url_); | 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 open infobars prompting about |
| 197 // some URL. If these URLs have the same TLD, we can simply leave the | 197 // some URL. If these URLs have the same TLD (e.g. for scheme changes), we |
| 198 // existing infobars open and quietly point their "new Google URL"s at the | 198 // can simply leave the existing infobars open as their messages will still |
| 199 // new URL (for e.g. scheme changes). Otherwise we go ahead and close the | 199 // be accurate. Otherwise we go ahead and close them because we need to |
| 200 // existing infobars since their message is out-of-date. | 200 // display a new message. |
| 201 if (!url.is_valid()) // Note: |url| is the previous |fetched_google_url_|. | 201 // Note: |url| is the previous |fetched_google_url_|. |
| 202 return; | 202 if (url.is_valid() && (fetched_host != net::StripWWWFromHost(url))) |
| 203 if (fetched_host != net::StripWWWFromHost(url)) { | |
| 204 CloseAllInfoBars(false); | 203 CloseAllInfoBars(false); |
| 205 } else if (fetched_google_url_ != url) { | |
| 206 for (InfoBarMap::iterator i(infobar_map_.begin()); | |
| 207 i != infobar_map_.end(); ++i) | |
| 208 i->second.infobar->SetGoogleURL(fetched_google_url_); | |
| 209 } | |
| 210 } | 204 } |
| 211 } | 205 } |
| 212 | 206 |
| 213 void GoogleURLTracker::Observe(int type, | 207 void GoogleURLTracker::Observe(int type, |
| 214 const content::NotificationSource& source, | 208 const content::NotificationSource& source, |
| 215 const content::NotificationDetails& details) { | 209 const content::NotificationDetails& details) { |
| 216 switch (type) { | 210 switch (type) { |
| 217 case content::NOTIFICATION_NAV_ENTRY_PENDING: { | 211 case content::NOTIFICATION_NAV_ENTRY_PENDING: { |
| 218 content::NavigationController* controller = | 212 content::NavigationController* controller = |
| 219 content::Source<content::NavigationController>(source).ptr(); | 213 content::Source<content::NavigationController>(source).ptr(); |
| 220 content::WebContents* web_contents = controller->GetWebContents(); | 214 content::WebContents* web_contents = controller->GetWebContents(); |
| 221 InfoBarTabHelper* infobar_tab_helper = | 215 InfoBarTabHelper* infobar_tab_helper = |
| 222 InfoBarTabHelper::FromWebContents(web_contents); | 216 InfoBarTabHelper::FromWebContents(web_contents); |
| 223 // Because we're listening to all sources, there may be no | 217 // Because we're listening to all sources, there may be no |
| 224 // InfoBarTabHelper for some notifications, e.g. navigations in | 218 // InfoBarTabHelper for some notifications, e.g. navigations in |
| 225 // bubbles/balloons etc. | 219 // bubbles/balloons etc. |
| 226 if (infobar_tab_helper) { | 220 if (infobar_tab_helper) { |
| 227 OnNavigationPending(source, | 221 OnNavigationPending( |
| 228 content::Source<content::WebContents>(web_contents), | 222 source, content::Source<content::WebContents>(web_contents), |
| 229 infobar_tab_helper, | 223 infobar_tab_helper, controller->GetPendingEntry()->GetUniqueID()); |
| 230 controller->GetPendingEntry()->GetUniqueID()); | |
| 231 } | 224 } |
| 232 break; | 225 break; |
| 233 } | 226 } |
| 234 | 227 |
| 235 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { | 228 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { |
| 236 content::NavigationController* controller = | 229 content::NavigationController* controller = |
| 237 content::Source<content::NavigationController>(source).ptr(); | 230 content::Source<content::NavigationController>(source).ptr(); |
| 238 // Here we're only listening to notifications where we already know | 231 // Here we're only listening to notifications where we already know |
| 239 // there's an associated InfoBarTabHelper. | 232 // there's an associated InfoBarTabHelper. |
| 240 InfoBarTabHelper* infobar_tab_helper = | 233 InfoBarTabHelper* infobar_tab_helper = |
| 241 InfoBarTabHelper::FromWebContents(controller->GetWebContents()); | 234 InfoBarTabHelper::FromWebContents(controller->GetWebContents()); |
| 242 DCHECK(infobar_tab_helper); | 235 DCHECK(infobar_tab_helper); |
| 243 OnNavigationCommittedOrTabClosed(infobar_tab_helper, | 236 OnNavigationCommittedOrTabClosed(infobar_tab_helper, |
| 244 controller->GetActiveEntry()->GetURL()); | 237 controller->GetActiveEntry()->GetURL()); |
| 245 break; | 238 break; |
| 246 } | 239 } |
| 247 | 240 |
| 248 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { | 241 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: |
| 249 InfoBarTabHelper* infobar_tab_helper = InfoBarTabHelper::FromWebContents( | 242 OnNavigationCommittedOrTabClosed( |
| 250 content::Source<content::WebContents>(source).ptr()); | 243 InfoBarTabHelper::FromWebContents( |
| 251 OnNavigationCommittedOrTabClosed(infobar_tab_helper, GURL()); | 244 content::Source<content::WebContents>(source).ptr()), GURL()); |
| 252 break; | 245 break; |
| 253 } | |
| 254 | 246 |
| 255 case chrome::NOTIFICATION_INSTANT_COMMITTED: { | 247 case chrome::NOTIFICATION_INSTANT_COMMITTED: { |
| 256 content::WebContents* web_contents = | 248 content::WebContents* web_contents = |
| 257 content::Source<content::WebContents>(source).ptr(); | 249 content::Source<content::WebContents>(source).ptr(); |
| 258 OnInstantCommitted(content::Source<content::NavigationController>( | 250 OnInstantCommitted(content::Source<content::NavigationController>( |
| 259 &web_contents->GetController()), | 251 &web_contents->GetController()), |
| 260 source, | 252 source, |
| 261 InfoBarTabHelper::FromWebContents(web_contents), | 253 InfoBarTabHelper::FromWebContents(web_contents), |
| 262 web_contents->GetURL()); | 254 web_contents->GetURL()); |
| 263 break; | 255 break; |
| 264 } | 256 } |
| 265 | 257 |
| 266 default: | 258 default: |
| 267 NOTREACHED() << "Unknown notification received:" << type; | 259 NOTREACHED() << "Unknown notification received:" << type; |
| 268 } | 260 } |
| 269 } | 261 } |
| 270 | 262 |
| 271 void GoogleURLTracker::OnIPAddressChanged() { | 263 void GoogleURLTracker::OnIPAddressChanged() { |
| 272 already_fetched_ = false; | 264 already_fetched_ = false; |
| 273 StartFetchIfDesirable(); | 265 StartFetchIfDesirable(); |
| 274 } | 266 } |
| 275 | 267 |
| 276 void GoogleURLTracker::Shutdown() { | 268 void GoogleURLTracker::Shutdown() { |
| 277 registrar_.RemoveAll(); | 269 registrar_.RemoveAll(); |
| 278 weak_ptr_factory_.InvalidateWeakPtrs(); | 270 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 279 fetcher_.reset(); | 271 fetcher_.reset(); |
| 280 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); | 272 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); |
| 281 } | 273 } |
| 282 | 274 |
| 283 void GoogleURLTracker::AcceptGoogleURL(const GURL& new_google_url, | 275 void GoogleURLTracker::DeleteMapEntryForHelper( |
| 284 bool redo_searches) { | 276 const InfoBarTabHelper* infobar_helper) { |
| 285 UpdatedDetails urls(google_url_, new_google_url); | |
| 286 google_url_ = new_google_url; | |
| 287 PrefService* prefs = profile_->GetPrefs(); | |
| 288 prefs->SetString(prefs::kLastKnownGoogleURL, google_url_.spec()); | |
| 289 prefs->SetString(prefs::kLastPromptedGoogleURL, google_url_.spec()); | |
| 290 content::NotificationService::current()->Notify( | |
| 291 chrome::NOTIFICATION_GOOGLE_URL_UPDATED, | |
| 292 content::Source<Profile>(profile_), | |
| 293 content::Details<UpdatedDetails>(&urls)); | |
| 294 need_to_prompt_ = false; | |
| 295 CloseAllInfoBars(redo_searches); | |
| 296 } | |
| 297 | |
| 298 void GoogleURLTracker::CancelGoogleURL(const GURL& new_google_url) { | |
| 299 profile_->GetPrefs()->SetString(prefs::kLastPromptedGoogleURL, | |
| 300 new_google_url.spec()); | |
| 301 need_to_prompt_ = false; | |
| 302 CloseAllInfoBars(false); | |
| 303 } | |
| 304 | |
| 305 void GoogleURLTracker::InfoBarClosed(const InfoBarTabHelper* infobar_helper) { | |
| 306 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); | 277 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); |
| 307 DCHECK(i != infobar_map_.end()); | 278 DCHECK(i != infobar_map_.end()); |
| 279 GoogleURLTrackerMapEntry* map_entry = i->second; |
| 308 | 280 |
| 309 UnregisterForEntrySpecificNotifications(i->second, false); | 281 UnregisterForEntrySpecificNotifications(*map_entry, false); |
| 310 infobar_map_.erase(i); | 282 infobar_map_.erase(i); |
| 283 delete map_entry; |
| 311 } | 284 } |
| 312 | 285 |
| 313 void GoogleURLTracker::SetNeedToFetch() { | 286 void GoogleURLTracker::SetNeedToFetch() { |
| 314 need_to_fetch_ = true; | 287 need_to_fetch_ = true; |
| 315 StartFetchIfDesirable(); | 288 StartFetchIfDesirable(); |
| 316 } | 289 } |
| 317 | 290 |
| 318 void GoogleURLTracker::FinishSleep() { | 291 void GoogleURLTracker::FinishSleep() { |
| 319 in_startup_sleep_ = false; | 292 in_startup_sleep_ = false; |
| 320 StartFetchIfDesirable(); | 293 StartFetchIfDesirable(); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 // load to commit, so we can show and/or update the infobar when it does. | 357 // load to commit, so we can show and/or update the infobar when it does. |
| 385 // (We may already be registered for this if there is an existing infobar | 358 // (We may already be registered for this if there is an existing infobar |
| 386 // that had a previous pending search that hasn't yet committed.) | 359 // that had a previous pending search that hasn't yet committed.) |
| 387 if (!registrar_.IsRegistered(this, | 360 if (!registrar_.IsRegistered(this, |
| 388 content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 361 content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 389 navigation_controller_source)) { | 362 navigation_controller_source)) { |
| 390 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 363 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 391 navigation_controller_source); | 364 navigation_controller_source); |
| 392 } | 365 } |
| 393 if (i == infobar_map_.end()) { | 366 if (i == infobar_map_.end()) { |
| 394 // This is a search on a tab that doesn't have one of our infobars, so add | 367 // This is a search on a tab that doesn't have one of our infobars, so |
| 395 // one. Note that we only listen for the tab's destruction on this path; | 368 // prepare to add one. Note that we only listen for the tab's destruction |
| 396 // if there was already an infobar, then either it's not yet showing and | 369 // on this path; if there was already a map entry, then either it doesn't |
| 397 // we're already registered for this, or it is showing and its owner will | 370 // yet have an infobar and we're already registered for this, or it has an |
| 398 // handle tearing it down when the tab is destroyed. | 371 // infobar and the infobar's owner will handle tearing it down when the |
| 372 // tab is destroyed. |
| 399 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 373 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 400 web_contents_source); | 374 web_contents_source); |
| 401 infobar_map_.insert(std::make_pair(infobar_helper, MapEntry( | 375 infobar_map_.insert(std::make_pair( |
| 402 (*infobar_creator_)(infobar_helper, this, fetched_google_url_), | 376 infobar_helper, |
| 403 navigation_controller_source, web_contents_source))); | 377 new GoogleURLTrackerMapEntry(this, infobar_helper, |
| 404 } else { | 378 navigation_controller_source, |
| 405 // This is a new search on a tab where we already have an infobar (which | 379 web_contents_source))); |
| 406 // may or may not be showing). | 380 } else if (i->second->has_infobar()) { |
| 407 i->second.infobar->set_pending_id(pending_id); | 381 // This is a new search on a tab where we already have a visible infobar. |
| 382 i->second->infobar()->set_pending_id(pending_id); |
| 408 } | 383 } |
| 409 } else if (i != infobar_map_.end()){ | 384 } else if (i != infobar_map_.end()){ |
| 410 if (i->second.infobar->showing()) { | 385 if (i->second->has_infobar()) { |
| 411 // This is a non-search navigation on a tab with a visible infobar. If | 386 // This is a non-search navigation on a tab with a visible infobar. If |
| 412 // there was a previous pending search on this tab, this means it won't | 387 // there was a previous pending search on this tab, this means it won't |
| 413 // commit, so undo anything we did in response to seeing that. Note that | 388 // commit, so undo anything we did in response to seeing that. Note that |
| 414 // if there was no pending search on this tab, these statements are | 389 // if there was no pending search on this tab, these statements are |
| 415 // effectively a no-op. | 390 // effectively a no-op. |
| 416 // | 391 // |
| 417 // If this navigation actually commits, that will trigger the infobar's | 392 // If this navigation actually commits, that will trigger the infobar's |
| 418 // owner to expire the infobar if need be. If it doesn't commit, then | 393 // owner to expire the infobar if need be. If it doesn't commit, then |
| 419 // simply leaving the infobar as-is will have been the right thing. | 394 // simply leaving the infobar as-is will have been the right thing. |
| 420 UnregisterForEntrySpecificNotifications(i->second, false); | 395 UnregisterForEntrySpecificNotifications(*i->second, false); |
| 421 i->second.infobar->set_pending_id(0); | 396 i->second->infobar()->set_pending_id(0); |
| 422 } else { | 397 } else { |
| 423 // Non-search navigation on a tab with a not-yet-shown infobar. This | 398 // Non-search navigation on a tab with an entry that has not yet created |
| 424 // means the original search won't commit, so close the infobar. | 399 // an infobar. This means the original search won't commit, so delete the |
| 425 i->second.infobar->Close(false); | 400 // entry. |
| 401 i->second->Close(false); |
| 426 } | 402 } |
| 427 } else { | 403 } else { |
| 428 // Non-search navigation on a tab without one of our infobars. This is | 404 // Non-search navigation on a tab without one of our infobars. This is |
| 429 // irrelevant to us. | 405 // irrelevant to us. |
| 430 } | 406 } |
| 431 } | 407 } |
| 432 | 408 |
| 433 void GoogleURLTracker::OnNavigationCommittedOrTabClosed( | 409 void GoogleURLTracker::OnNavigationCommittedOrTabClosed( |
| 434 const InfoBarTabHelper* infobar_helper, | 410 InfoBarTabHelper* infobar_helper, |
| 435 const GURL& search_url) { | 411 const GURL& search_url) { |
| 436 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); | 412 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); |
| 437 DCHECK(i != infobar_map_.end()); | 413 DCHECK(i != infobar_map_.end()); |
| 438 const MapEntry& map_entry = i->second; | 414 GoogleURLTrackerMapEntry* map_entry = i->second; |
| 439 | 415 |
| 440 if (!search_url.is_valid()) { | 416 if (!search_url.is_valid()) { |
| 441 // Tab closed, or we somehow tried to navigate to an invalid URL (?!). | 417 // Tab closed, or we somehow tried to navigate to an invalid URL (?!). |
| 442 // InfoBarClosed() will take care of unregistering the notifications for | 418 // DeleteMapEntryForHelper() will take care of unregistering the |
| 443 // this tab. | 419 // notifications for this tab. |
| 444 map_entry.infobar->Close(false); | 420 map_entry->Close(false); |
| 445 return; | 421 return; |
| 446 } | 422 } |
| 447 | 423 |
| 448 // We're getting called because of a commit notification, so pass true for | 424 // We're getting called because of a commit notification, so pass true for |
| 449 // |must_be_listening_for_commit|. | 425 // |must_be_listening_for_commit|. |
| 450 UnregisterForEntrySpecificNotifications(map_entry, true); | 426 UnregisterForEntrySpecificNotifications(*map_entry, true); |
| 451 map_entry.infobar->Show(search_url); | 427 if (map_entry->has_infobar()) { |
| 428 map_entry->infobar()->Update(search_url); |
| 429 } else { |
| 430 GoogleURLTrackerInfoBarDelegate* infobar_delegate = |
| 431 infobar_creator_.Run(infobar_helper, this, search_url); |
| 432 if (infobar_delegate) |
| 433 map_entry->SetInfoBar(infobar_delegate); |
| 434 else |
| 435 map_entry->Close(false); |
| 436 } |
| 452 } | 437 } |
| 453 | 438 |
| 454 void GoogleURLTracker::OnInstantCommitted( | 439 void GoogleURLTracker::OnInstantCommitted( |
| 455 const content::NotificationSource& navigation_controller_source, | 440 const content::NotificationSource& navigation_controller_source, |
| 456 const content::NotificationSource& web_contents_source, | 441 const content::NotificationSource& web_contents_source, |
| 457 InfoBarTabHelper* infobar_helper, | 442 InfoBarTabHelper* infobar_helper, |
| 458 const GURL& search_url) { | 443 const GURL& search_url) { |
| 459 // If this was the search we were listening for, OnNavigationPending() should | 444 // If this was the search we were listening for, OnNavigationPending() should |
| 460 // ensure we're registered for NAV_ENTRY_COMMITTED, and we should call | 445 // ensure we're registered for NAV_ENTRY_COMMITTED, and we should call |
| 461 // OnNavigationCommittedOrTabClosed() to simulate that firing. Otherwise, | 446 // OnNavigationCommittedOrTabClosed() to simulate that firing. Otherwise, |
| 462 // this is some sort of non-search navigation, so while we should still call | 447 // this is some sort of non-search navigation, so while we should still call |
| 463 // OnNavigationPending(), that function should then ensure that we're not | 448 // OnNavigationPending(), that function should then ensure that we're not |
| 464 // listening for NAV_ENTRY_COMMITTED on this tab, and we should not call | 449 // listening for NAV_ENTRY_COMMITTED on this tab, and we should not call |
| 465 // OnNavigationCommittedOrTabClosed() afterwards. Note that we need to save | 450 // OnNavigationCommittedOrTabClosed() afterwards. Note that we need to save |
| 466 // off |search_committed_| here because OnNavigationPending() will reset it. | 451 // off |search_committed_| here because OnNavigationPending() will reset it. |
| 467 bool was_search_committed = search_committed_; | 452 bool was_search_committed = search_committed_; |
| 468 OnNavigationPending(navigation_controller_source, web_contents_source, | 453 OnNavigationPending(navigation_controller_source, web_contents_source, |
| 469 infobar_helper, 0); | 454 infobar_helper, 0); |
| 470 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); | 455 InfoBarMap::iterator i(infobar_map_.find(infobar_helper)); |
| 471 DCHECK_EQ(was_search_committed, (i != infobar_map_.end()) && | 456 DCHECK_EQ(was_search_committed, (i != infobar_map_.end()) && |
| 472 registrar_.IsRegistered(this, | 457 registrar_.IsRegistered(this, |
| 473 content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 458 content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 474 i->second.navigation_controller_source)); | 459 i->second->navigation_controller_source())); |
| 475 if (was_search_committed) | 460 if (was_search_committed) |
| 476 OnNavigationCommittedOrTabClosed(infobar_helper, search_url); | 461 OnNavigationCommittedOrTabClosed(infobar_helper, search_url); |
| 477 } | 462 } |
| 478 | 463 |
| 479 void GoogleURLTracker::CloseAllInfoBars(bool redo_searches) { | 464 void GoogleURLTracker::CloseAllInfoBars(bool redo_searches) { |
| 480 // Close all infobars, whether they've been added to tabs or not. | 465 // Delete all entries, whether they have infobars or not. |
| 481 while (!infobar_map_.empty()) | 466 while (!infobar_map_.empty()) |
| 482 infobar_map_.begin()->second.infobar->Close(redo_searches); | 467 infobar_map_.begin()->second->Close(redo_searches); |
| 483 } | 468 } |
| 484 | 469 |
| 485 void GoogleURLTracker::UnregisterForEntrySpecificNotifications( | 470 void GoogleURLTracker::UnregisterForEntrySpecificNotifications( |
| 486 const MapEntry& map_entry, | 471 const GoogleURLTrackerMapEntry& map_entry, |
| 487 bool must_be_listening_for_commit) { | 472 bool must_be_listening_for_commit) { |
| 488 // For tabs with non-showing infobars, we should always be listening for both | 473 // For tabs with non-showing infobars, we should always be listening for both |
| 489 // these notifications. For tabs with showing infobars, we may be listening | 474 // these notifications. For tabs with showing infobars, we may be listening |
| 490 // for NOTIFICATION_NAV_ENTRY_COMMITTED if the user has performed a new search | 475 // for NOTIFICATION_NAV_ENTRY_COMMITTED if the user has performed a new search |
| 491 // on this tab. | 476 // on this tab. |
| 492 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 477 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 493 map_entry.navigation_controller_source)) { | 478 map_entry.navigation_controller_source())) { |
| 494 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 479 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 495 map_entry.navigation_controller_source); | 480 map_entry.navigation_controller_source()); |
| 496 } else { | 481 } else { |
| 497 DCHECK(!must_be_listening_for_commit); | 482 DCHECK(!must_be_listening_for_commit); |
| 498 DCHECK(map_entry.infobar->showing()); | 483 DCHECK(map_entry.has_infobar()); |
| 499 } | 484 } |
| 500 const bool registered_for_web_contents_destroyed = | 485 const bool registered_for_web_contents_destroyed = registrar_.IsRegistered( |
| 501 registrar_.IsRegistered(this, | 486 this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 502 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 487 map_entry.web_contents_source()); |
| 503 map_entry.web_contents_source); | 488 DCHECK_NE(registered_for_web_contents_destroyed, map_entry.has_infobar()); |
| 504 DCHECK_NE(registered_for_web_contents_destroyed, | |
| 505 map_entry.infobar->showing()); | |
| 506 if (registered_for_web_contents_destroyed) { | 489 if (registered_for_web_contents_destroyed) { |
| 507 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 490 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 508 map_entry.web_contents_source); | 491 map_entry.web_contents_source()); |
| 509 } | 492 } |
| 510 | 493 |
| 511 // Our global listeners for these other notifications should be in place iff | 494 // Our global listeners for these other notifications should be in place iff |
| 512 // we have any infobars still listening for commits. These infobars are | 495 // we have any infobars still listening for commits. These infobars are |
| 513 // either not yet shown or have received a new pending search atop an existing | 496 // either not yet shown or have received a new pending search atop an existing |
| 514 // infobar; in either case we want to catch subsequent pending non-search | 497 // infobar; in either case we want to catch subsequent pending non-search |
| 515 // navigations. See the various cases inside OnNavigationPending(). | 498 // navigations. See the various cases inside OnNavigationPending(). |
| 516 for (InfoBarMap::const_iterator i(infobar_map_.begin()); | 499 for (InfoBarMap::const_iterator i(infobar_map_.begin()); |
| 517 i != infobar_map_.end(); ++i) { | 500 i != infobar_map_.end(); ++i) { |
| 518 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 501 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 519 i->second.navigation_controller_source)) { | 502 i->second->navigation_controller_source())) { |
| 520 DCHECK(registrar_.IsRegistered(this, | 503 DCHECK(registrar_.IsRegistered(this, |
| 521 content::NOTIFICATION_NAV_ENTRY_PENDING, | 504 content::NOTIFICATION_NAV_ENTRY_PENDING, |
| 522 content::NotificationService::AllBrowserContextsAndSources())); | 505 content::NotificationService::AllBrowserContextsAndSources())); |
| 523 return; | 506 return; |
| 524 } | 507 } |
| 525 } | 508 } |
| 526 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_PENDING, | 509 if (registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_PENDING, |
| 527 content::NotificationService::AllBrowserContextsAndSources())) { | 510 content::NotificationService::AllBrowserContextsAndSources())) { |
| 528 DCHECK(!search_committed_); | 511 DCHECK(!search_committed_); |
| 529 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING, | 512 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING, |
| 530 content::NotificationService::AllBrowserContextsAndSources()); | 513 content::NotificationService::AllBrowserContextsAndSources()); |
| 531 registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_COMMITTED, | 514 registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_COMMITTED, |
| 532 content::NotificationService::AllBrowserContextsAndSources()); | 515 content::NotificationService::AllBrowserContextsAndSources()); |
| 533 } | 516 } |
| 534 } | 517 } |
| OLD | NEW |