Index: chrome/browser/google/google_url_tracker.cc |
=================================================================== |
--- chrome/browser/google/google_url_tracker.cc (revision 65992) |
+++ chrome/browser/google/google_url_tracker.cc (working copy) |
@@ -27,13 +27,13 @@ |
namespace { |
-InfoBarDelegate* CreateInfobar(TabContents* tab_contents, |
- GoogleURLTracker* google_url_tracker, |
- const GURL& new_google_url) { |
- InfoBarDelegate* infobar = new GoogleURLTrackerInfoBarDelegate(tab_contents, |
+GoogleURLTrackerInfoBarDelegate* CreateInfobar( |
+ TabContents* tab_contents, |
+ const GURL& search_url, |
+ GoogleURLTracker* google_url_tracker, |
+ const GURL& new_google_url) { |
+ return new GoogleURLTrackerInfoBarDelegate(tab_contents, search_url, |
google_url_tracker, new_google_url); |
- tab_contents->AddInfoBar(infobar); |
- return infobar; |
} |
} // namespace |
@@ -42,36 +42,77 @@ |
GoogleURLTrackerInfoBarDelegate::GoogleURLTrackerInfoBarDelegate( |
TabContents* tab_contents, |
+ const GURL& search_url, |
GoogleURLTracker* google_url_tracker, |
const GURL& new_google_url) |
: ConfirmInfoBarDelegate(tab_contents), |
+ tab_contents_(tab_contents), |
+ search_url_(search_url), |
google_url_tracker_(google_url_tracker), |
- new_google_url_(new_google_url) { |
+ new_google_url_(new_google_url), |
+ showing_(false) { |
} |
bool GoogleURLTrackerInfoBarDelegate::Accept() { |
google_url_tracker_->AcceptGoogleURL(new_google_url_); |
- google_url_tracker_->RedoSearch(); |
- return true; |
+ return false; |
} |
bool GoogleURLTrackerInfoBarDelegate::Cancel() { |
google_url_tracker_->CancelGoogleURL(new_google_url_); |
- return true; |
+ return false; |
} |
void GoogleURLTrackerInfoBarDelegate::InfoBarClosed() { |
- google_url_tracker_->InfoBarClosed(); |
+ if (google_url_tracker_) |
+ google_url_tracker_->InfoBarClosed(this, tab_contents_); |
delete this; |
} |
+void GoogleURLTrackerInfoBarDelegate::Show() { |
+ tab_contents_->AddInfoBar(this); |
+ showing_ = true; |
+} |
+ |
+void GoogleURLTrackerInfoBarDelegate::Close(bool redo_search) { |
+ if (!showing_) { |
+ // We haven't been added to a tab, so just delete ourselves. |
+ InfoBarClosed(); |
+ return; |
+ } |
+ |
+ if (redo_search) { |
+ // Re-do the user's search on the new domain. |
+ url_canon::Replacements<char> replacements; |
+ const std::string& host(new_google_url_.host()); |
+ replacements.SetHost(host.data(), url_parse::Component(0, host.length())); |
+ GURL new_search_url(search_url_.ReplaceComponents(replacements)); |
+ if (new_search_url.is_valid()) { |
+ tab_contents_->OpenURL(new_search_url, GURL(), CURRENT_TAB, |
+ PageTransition::GENERATED); |
+ } |
+ } |
+ |
+ // Synchronously remove ourselves from the URL tracker's list, because the |
+ // RemoveInfoBar() call below may result in either a synchronous or an |
+ // asynchronous call back to InfoBarClosed(), and it's easier to handle when |
+ // we just guarantee the removal is synchronous. |
+ google_url_tracker_->InfoBarClosed(this, tab_contents_); |
+ google_url_tracker_ = NULL; |
+ |
+ tab_contents_->RemoveInfoBar(this); |
+} |
+ |
GoogleURLTrackerInfoBarDelegate::~GoogleURLTrackerInfoBarDelegate() { |
} |
string16 GoogleURLTrackerInfoBarDelegate::GetMessageText() const { |
- // TODO(ukai): change new_google_url to google_base_domain? |
+ // Strip the "www." off the hostname since it's just noise. This should |
+ // always be present since we added it in OnURLFetchComplete(). |
+ std::string host(new_google_url_.host()); |
+ DCHECK(StartsWithASCII(host, "www.", true)); |
return l10n_util::GetStringFUTF16(IDS_GOOGLE_URL_TRACKER_INFOBAR_MESSAGE, |
- UTF8ToUTF16(new_google_url_.spec())); |
+ UTF8ToUTF16(host.substr(4))); |
} |
int GoogleURLTrackerInfoBarDelegate::GetButtons() const { |
@@ -104,11 +145,11 @@ |
already_fetched_(false), |
need_to_fetch_(false), |
request_context_available_(!!Profile::GetDefaultRequestContext()), |
- need_to_prompt_(false), |
- controller_(NULL), |
- infobar_(NULL) { |
- registrar_.Add(this, NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE, |
- NotificationService::AllSources()); |
+ need_to_prompt_(false) { |
+ if (!request_context_available_) { |
+ registrar_.Add(this, NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE, |
+ NotificationService::AllSources()); |
+ } |
net::NetworkChangeNotifier::AddObserver(this); |
@@ -127,6 +168,9 @@ |
GoogleURLTracker::~GoogleURLTracker() { |
runnable_method_factory_.RevokeAll(); |
net::NetworkChangeNotifier::RemoveObserver(this); |
+ // We should only reach here after any tabs and their infobars have been torn |
+ // down. |
+ DCHECK(infobars_.empty()); |
} |
// static |
@@ -241,7 +285,6 @@ |
GURL last_prompted_url( |
g_browser_process->local_state()->GetString( |
prefs::kLastPromptedGoogleURL)); |
- need_to_prompt_ = false; |
if (last_prompted_url.is_empty()) { |
// On the very first run of Chrome, when we've never looked up the URL at |
@@ -263,6 +306,10 @@ |
} |
need_to_prompt_ = true; |
+ |
+ // Any open infobars are pointing at the wrong Google URL. (This can happen |
+ // if an infobar has been sitting open and then our IP address changes.) |
+ CloseAllInfobars(false); |
} |
void GoogleURLTracker::AcceptGoogleURL(const GURL& new_google_url) { |
@@ -275,32 +322,23 @@ |
NotificationService::AllSources(), |
NotificationService::NoDetails()); |
need_to_prompt_ = false; |
+ CloseAllInfobars(true); |
} |
void GoogleURLTracker::CancelGoogleURL(const GURL& new_google_url) { |
g_browser_process->local_state()->SetString(prefs::kLastPromptedGoogleURL, |
new_google_url.spec()); |
+ need_to_prompt_ = false; |
+ CloseAllInfobars(false); |
} |
-void GoogleURLTracker::InfoBarClosed() { |
- registrar_.RemoveAll(); |
- controller_ = NULL; |
- infobar_ = NULL; |
- search_url_ = GURL(); |
+void GoogleURLTracker::InfoBarClosed(GoogleURLTrackerInfoBarDelegate* infobar, |
+ TabContents* tab_contents) { |
+ Infobars::iterator i(infobars_.find(tab_contents)); |
+ if ((i != infobars_.end()) && (i->second == infobar)) |
+ infobars_.erase(i); |
} |
-void GoogleURLTracker::RedoSearch() { |
- // Re-do the user's search on the new domain. |
- DCHECK(controller_); |
- url_canon::Replacements<char> replacements; |
- replacements.SetHost(google_url_.host().data(), |
- url_parse::Component(0, google_url_.host().length())); |
- GURL new_search_url(search_url_.ReplaceComponents(replacements)); |
- if (new_search_url.is_valid()) |
- controller_->tab_contents()->OpenURL(new_search_url, GURL(), CURRENT_TAB, |
- PageTransition::GENERATED); |
-} |
- |
void GoogleURLTracker::Observe(NotificationType type, |
const NotificationSource& source, |
const NotificationDetails& details) { |
@@ -313,13 +351,17 @@ |
StartFetchIfDesirable(); |
break; |
- case NotificationType::NAV_ENTRY_PENDING: |
- OnNavigationPending(source, controller_->pending_entry()->url()); |
+ case NotificationType::NAV_ENTRY_PENDING: { |
+ NavigationController* controller = |
+ Source<NavigationController>(source).ptr(); |
+ OnNavigationPending(source, controller->tab_contents(), |
+ controller->pending_entry()->url()); |
break; |
+ } |
case NotificationType::NAV_ENTRY_COMMITTED: |
case NotificationType::TAB_CLOSED: |
- OnNavigationCommittedOrTabClosed( |
+ OnNavigationCommittedOrTabClosed(source, |
Source<NavigationController>(source).ptr()->tab_contents(), |
type.value); |
break; |
@@ -335,7 +377,7 @@ |
} |
void GoogleURLTracker::SearchCommitted() { |
- if (registrar_.IsEmpty() && (need_to_prompt_ || fetcher_.get())) { |
+ if (need_to_prompt_) { |
// This notification will fire a bit later in the same call chain we're |
// currently in. |
registrar_.Add(this, NotificationType::NAV_ENTRY_PENDING, |
@@ -344,37 +386,57 @@ |
} |
void GoogleURLTracker::OnNavigationPending(const NotificationSource& source, |
+ TabContents* tab_contents, |
const GURL& pending_url) { |
- controller_ = Source<NavigationController>(source).ptr(); |
- search_url_ = pending_url; |
registrar_.Remove(this, NotificationType::NAV_ENTRY_PENDING, |
NotificationService::AllSources()); |
- // Start listening for the commit notification. We also need to listen for the |
- // tab close command since that means the load will never commit. |
- registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, |
- Source<NavigationController>(controller_)); |
- registrar_.Add(this, NotificationType::TAB_CLOSED, |
- Source<NavigationController>(controller_)); |
+ |
+ if (registrar_.IsRegistered(this, NotificationType::TAB_CLOSED, source)) { |
+ // If the previous load hasn't committed and the user triggers a new load, |
+ // we don't need to re-register our listeners; just kill the old, |
+ // never-shown infobar (to be replaced by a new one below). |
+ Infobars::iterator i(infobars_.find(tab_contents)); |
+ DCHECK(i != infobars_.end()); |
+ i->second->Close(false); |
+ } else { |
+ // Start listening for the commit notification. We also need to listen for |
+ // the tab close command since that means the load will never commit. Note |
+ // that in this case we don't need to close any previous infobar for this |
+ // TabContents since this navigation will close it. |
+ registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, source); |
+ registrar_.Add(this, NotificationType::TAB_CLOSED, source); |
+ } |
+ |
+ infobars_[tab_contents] = |
+ (*infobar_creator_)(tab_contents, pending_url, this, fetched_google_url_); |
} |
void GoogleURLTracker::OnNavigationCommittedOrTabClosed( |
+ const NotificationSource& source, |
TabContents* tab_contents, |
NotificationType::Type type) { |
- registrar_.RemoveAll(); |
+ registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED, source); |
+ registrar_.Remove(this, NotificationType::TAB_CLOSED, source); |
- if (type == NotificationType::NAV_ENTRY_COMMITTED) { |
- ShowGoogleURLInfoBarIfNecessary(tab_contents); |
- } else { |
- controller_ = NULL; |
- infobar_ = NULL; |
- } |
+ Infobars::iterator i(infobars_.find(tab_contents)); |
+ DCHECK(i != infobars_.end()); |
+ DCHECK(need_to_prompt_); |
Ilya Sherman
2010/11/16 00:17:47
Why does |need_to_prompt_| have to be true?
Suppo
Peter Kasting
2010/11/16 00:38:23
Talked over this in person to ensure both of us th
|
+ if (type == NotificationType::NAV_ENTRY_COMMITTED) |
+ i->second->Show(); |
+ else |
+ i->second->Close(false); // Close manually since it's not added to a tab. |
} |
-void GoogleURLTracker::ShowGoogleURLInfoBarIfNecessary( |
- TabContents* tab_contents) { |
- if (!need_to_prompt_) |
- return; |
- DCHECK(!fetched_google_url_.is_empty()); |
+void GoogleURLTracker::CloseAllInfobars(bool redo_searches) { |
+ // Close all infobars, whether they've been added to tabs or not. |
+ while (!infobars_.empty()) |
+ infobars_.begin()->second->Close(redo_searches); |
- infobar_ = (*infobar_creator_)(tab_contents, this, fetched_google_url_); |
+ // Any registered listeners for NAV_ENTRY_COMMITTED and TAB_CLOSED are now |
+ // irrelevant as the associated infobars are gone. |
+ registrar_.RemoveAll(); |
+ // We can't have had a listener for DEFAULT_REQUEST_CONTEXT_AVAILABLE, or we |
+ // could never have triggered the search domain check and thus couldn't have |
+ // reached here. |
+ DCHECK(request_context_available_); |
} |