Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Unified Diff: chrome/browser/google/google_url_tracker.cc

Issue 4880003: Fix a number of problems with the GoogleURLTracker (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/google/google_url_tracker.cc
===================================================================
--- chrome/browser/google/google_url_tracker.cc (revision 132905)
+++ chrome/browser/google/google_url_tracker.cc (working copy)
@@ -32,20 +32,15 @@
#include "net/url_request/url_request_status.h"
#include "ui/base/l10n/l10n_util.h"
-using content::NavigationController;
-using content::OpenURLParams;
-using content::Referrer;
-using content::WebContents;
-
namespace {
-InfoBarDelegate* CreateInfoBar(InfoBarTabHelper* infobar_helper,
- GoogleURLTracker* google_url_tracker,
- const GURL& new_google_url) {
- InfoBarDelegate* infobar = new GoogleURLTrackerInfoBarDelegate(infobar_helper,
+GoogleURLTrackerInfoBarDelegate* CreateInfoBar(
+ InfoBarTabHelper* infobar_helper,
+ const GURL& search_url,
+ GoogleURLTracker* google_url_tracker,
+ const GURL& new_google_url) {
+ return new GoogleURLTrackerInfoBarDelegate(infobar_helper, search_url,
google_url_tracker, new_google_url);
- infobar_helper->AddInfoBar(infobar);
- return infobar;
}
} // namespace
@@ -54,22 +49,25 @@
GoogleURLTrackerInfoBarDelegate::GoogleURLTrackerInfoBarDelegate(
InfoBarTabHelper* infobar_helper,
+ const GURL& search_url,
GoogleURLTracker* google_url_tracker,
const GURL& new_google_url)
: ConfirmInfoBarDelegate(infobar_helper),
+ map_key_(infobar_helper),
+ 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;
}
string16 GoogleURLTrackerInfoBarDelegate::GetLinkText() const {
@@ -78,18 +76,62 @@
bool GoogleURLTrackerInfoBarDelegate::LinkClicked(
WindowOpenDisposition disposition) {
- OpenURLParams params(
- google_util::AppendGoogleLocaleParam(GURL(
- "https://www.google.com/support/chrome/bin/answer.py?answer=1618699")),
- Referrer(),
+ content::OpenURLParams params(google_util::AppendGoogleLocaleParam(GURL(
+ "https://www.google.com/support/chrome/bin/answer.py?answer=1618699")),
+ content::Referrer(),
(disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
content::PAGE_TRANSITION_LINK, false);
owner()->web_contents()->OpenURL(params);
return false;
}
+void GoogleURLTrackerInfoBarDelegate::Show() {
+ owner()->AddInfoBar(this);
+ showing_ = true;
+}
+
+void GoogleURLTrackerInfoBarDelegate::Close(bool redo_search) {
+ if (!showing_) {
+ // We haven't been added to a tab, so just delete ourselves.
+ delete this;
+ return;
+ }
+
+ // 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(map_key_);
+ google_url_tracker_ = NULL;
+
+ // If we were showing in a background tab that was then closed, we could have
+ // been leaked, and subsequently reached here due to
+ // GoogleURLTracker::CloseAllInfoBars(). In this case our owner is now NULL
+ // so we should just do nothing.
+ // TODO(pkasting): This can go away once the InfoBar ownership model is fixed
+ // so that infobars in background tabs don't leak on tab closure.
Ilya Sherman 2012/04/24 00:30:47 nit: Is there a bug tracking this that we could li
+ if (!owner())
+ 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()) {
+ content::OpenURLParams params(new_search_url, content::Referrer(),
+ CURRENT_TAB, content::PAGE_TRANSITION_GENERATED, false);
+ owner()->web_contents()->OpenURL(params);
+ }
+ }
+
+ owner()->RemoveInfoBar(this);
+}
+
GoogleURLTrackerInfoBarDelegate::~GoogleURLTrackerInfoBarDelegate() {
- google_url_tracker_->InfoBarClosed();
+ if (google_url_tracker_)
Ilya Sherman 2012/04/24 00:30:47 nit: Should this also check the state of |showing_
Peter Kasting 2012/04/24 01:53:01 No. The infobar is present in the tracker's map r
+ google_url_tracker_->InfoBarClosed(map_key_);
}
string16 GoogleURLTrackerInfoBarDelegate::GetMessageText() const {
@@ -128,9 +170,7 @@
in_startup_sleep_(true),
already_fetched_(false),
need_to_fetch_(false),
- need_to_prompt_(false),
- controller_(NULL),
- infobar_(NULL) {
+ need_to_prompt_(false) {
net::NetworkChangeNotifier::AddIPAddressObserver(this);
// Because this function can be called during startup, when kicking off a URL
@@ -153,18 +193,20 @@
GoogleURLTracker::~GoogleURLTracker() {
net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
+ // We should only reach here after any tabs and their infobars have been torn
+ // down.
+ DCHECK(infobars_.empty());
}
// static
GURL GoogleURLTracker::GoogleURL() {
- const GoogleURLTracker* const tracker =
- g_browser_process->google_url_tracker();
+ const GoogleURLTracker* tracker = g_browser_process->google_url_tracker();
return tracker ? tracker->google_url_ : GURL(kDefaultGoogleHomepage);
}
// static
void GoogleURLTracker::RequestServerCheck() {
- GoogleURLTracker* const tracker = g_browser_process->google_url_tracker();
+ GoogleURLTracker* tracker = g_browser_process->google_url_tracker();
if (tracker)
tracker->SetNeedToFetch();
}
@@ -193,35 +235,22 @@
content::NotificationService::AllSources(),
content::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(const InfoBarTabHelper* infobar_helper) {
+ InfoBars::iterator i(infobars_.find(infobar_helper));
Ilya Sherman 2012/04/24 00:30:47 nit: Unless you're particularly attached to "i" he
+ DCHECK(i != infobars_.end());
+ 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()) {
- OpenURLParams params(new_search_url, Referrer(), CURRENT_TAB,
- content::PAGE_TRANSITION_GENERATED, false);
- controller_->GetWebContents()->OpenURL(params);
- }
-}
-
void GoogleURLTracker::SetNeedToFetch() {
need_to_fetch_ = true;
StartFetchIfDesirable();
@@ -291,7 +320,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
@@ -313,6 +341,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::Observe(int type,
@@ -320,22 +352,37 @@
const content::NotificationDetails& details) {
switch (type) {
case content::NOTIFICATION_NAV_ENTRY_PENDING: {
- NavigationController* controller =
- content::Source<NavigationController>(source).ptr();
- OnNavigationPending(source, controller->GetPendingEntry()->GetURL());
+ content::NavigationController* controller =
+ content::Source<content::NavigationController>(source).ptr();
+ content::WebContents* contents = controller->GetWebContents();
+ OnNavigationPending(source,
+ content::Source<content::WebContents>(contents),
+ TabContentsWrapper::GetCurrentWrapperForContents(contents)->
+ infobar_tab_helper(), controller->GetPendingEntry()->GetURL());
Ilya Sherman 2012/04/24 00:30:47 nit: Maybe move the last arg to a new line, since
break;
}
- case content::NOTIFICATION_NAV_ENTRY_COMMITTED:
- OnNavigationCommittedOrTabClosed(
- content::Source<NavigationController>(source).ptr()->
- GetWebContents(), type);
+ case content::NOTIFICATION_NAV_ENTRY_COMMITTED: {
+ content::WebContents* contents =
+ content::Source<content::NavigationController>(source)->
+ GetWebContents();
+ OnNavigationCommittedOrTabClosed(source,
+ content::Source<content::WebContents>(contents),
+ TabContentsWrapper::GetCurrentWrapperForContents(contents)->
+ infobar_tab_helper(), type);
break;
+ }
- case content::NOTIFICATION_WEB_CONTENTS_DESTROYED:
+ case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
+ content::WebContents* contents =
+ content::Source<content::WebContents>(source).ptr();
OnNavigationCommittedOrTabClosed(
- content::Source<content::WebContents>(source).ptr(), type);
+ content::Source<content::NavigationController>(&contents->
+ GetController()), source,
+ TabContentsWrapper::GetCurrentWrapperForContents(contents)->
+ infobar_tab_helper(), type);
break;
+ }
default:
NOTREACHED() << "Unknown notification received:" << type;
@@ -348,7 +395,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, content::NOTIFICATION_NAV_ENTRY_PENDING,
@@ -358,46 +405,58 @@
void GoogleURLTracker::OnNavigationPending(
const content::NotificationSource& source,
- const GURL& pending_url) {
- controller_ = content::Source<NavigationController>(source).ptr();
- search_url_ = pending_url;
+ const content::NotificationSource& contents_source,
+ InfoBarTabHelper* infobar_helper,
+ const GURL& search_url) {
registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
content::NotificationService::AllBrowserContextsAndSources());
- // 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, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
- content::Source<NavigationController>(controller_));
- registrar_.Add(
- this,
- content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<content::WebContents>(controller_->GetWebContents()));
+
+ if (registrar_.IsRegistered(this,
+ content::NOTIFICATION_WEB_CONTENTS_DESTROYED, contents_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(infobar_helper));
+ 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
+ // tab since this navigation will close it.
+ registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, source);
+ registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ contents_source);
+ }
+
+ infobars_[infobar_helper] = (*infobar_creator_)(infobar_helper, search_url,
+ this, fetched_google_url_);
}
void GoogleURLTracker::OnNavigationCommittedOrTabClosed(
- WebContents* web_contents,
+ const content::NotificationSource& source,
+ const content::NotificationSource& contents_source,
+ InfoBarTabHelper* infobar_helper,
int type) {
- registrar_.RemoveAll();
+ registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, source);
+ registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ contents_source);
- if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) {
- ShowGoogleURLInfoBarIfNecessary(web_contents);
- } else {
- controller_ = NULL;
- infobar_ = NULL;
- }
+ InfoBars::iterator i(infobars_.find(infobar_helper));
+ DCHECK(i != infobars_.end());
+ DCHECK(need_to_prompt_);
+ if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED)
+ i->second->Show();
+ else
+ i->second->Close(false); // Close manually since it's not added to a tab.
}
-void GoogleURLTracker::ShowGoogleURLInfoBarIfNecessary(
- WebContents* web_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);
- // |tab_contents| can be NULL during tests.
- InfoBarTabHelper* infobar_helper = NULL;
- if (web_contents) {
- TabContentsWrapper* wrapper =
- TabContentsWrapper::GetCurrentWrapperForContents(web_contents);
- infobar_helper = wrapper->infobar_tab_helper();
- }
- infobar_ = (*infobar_creator_)(infobar_helper, this, fetched_google_url_);
+ // Any registered listeners for NAV_ENTRY_COMMITTED and TAB_CLOSED are now
+ // irrelevant as the associated infobars are gone.
Ilya Sherman 2012/04/24 00:30:47 nit: You don't mention NAV_ENTRY_PENDING in this c
Peter Kasting 2012/04/24 01:53:01 The reason for that is that it's (supposed to be)
+ registrar_.RemoveAll();
}

Powered by Google App Engine
This is Rietveld 408576698