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