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

Unified Diff: chrome/browser/google_url_tracker.cc

Issue 3171019: Reland r56483 - Monitor network change in GoogleURLTracker (Closed)
Patch Set: check Chrome Frame Created 10 years, 4 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
« no previous file with comments | « chrome/browser/google_url_tracker.h ('k') | chrome/browser/google_url_tracker_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/google_url_tracker.cc
diff --git a/chrome/browser/google_url_tracker.cc b/chrome/browser/google_url_tracker.cc
index b7033930c60d3cc9b6715fbc11cb51fead659bf7..b6f111e1edf0321190fb5d546d773f33eb295143 100644
--- a/chrome/browser/google_url_tracker.cc
+++ b/chrome/browser/google_url_tracker.cc
@@ -6,31 +6,116 @@
#include <vector>
+#include "app/l10n_util.h"
#include "base/compiler_specific.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/net/url_fetcher_protect.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request_status.h"
const char GoogleURLTracker::kDefaultGoogleHomepage[] =
"http://www.google.com/";
+const char GoogleURLTracker::kSearchDomainCheckURL[] =
+ "https://www.google.com/searchdomaincheck?format=domain&type=chrome";
+
+namespace {
+
+class GoogleURLTrackerInfoBarDelegate : public ConfirmInfoBarDelegate {
+ public:
+ GoogleURLTrackerInfoBarDelegate(TabContents* tab_contents,
+ GoogleURLTracker* google_url_tracker,
+ const GURL& new_google_url)
+ : ConfirmInfoBarDelegate(tab_contents),
+ google_url_tracker_(google_url_tracker),
+ new_google_url_(new_google_url) {}
+
+ // ConfirmInfoBarDelegate
+ virtual string16 GetMessageText() const {
+ // TODO(ukai): change new_google_url to google_base_domain?
+ return l10n_util::GetStringFUTF16(IDS_GOOGLE_URL_TRACKER_INFOBAR_MESSAGE,
+ UTF8ToUTF16(new_google_url_.spec()));
+ }
+
+ virtual int GetButtons() const {
+ return BUTTON_OK | BUTTON_CANCEL;
+ }
+
+ virtual string16 GetButtonLabel(InfoBarButton button) const {
+ return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
+ IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL :
+ IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL);
+ }
+
+ virtual bool Accept() {
+ google_url_tracker_->AcceptGoogleURL(new_google_url_);
+ google_url_tracker_->RedoSearch();
+ return true;
+ }
+
+ virtual void InfoBarClosed() {
+ google_url_tracker_->InfoBarClosed();
+ delete this;
+ }
+
+ private:
+ virtual ~GoogleURLTrackerInfoBarDelegate() {}
+
+ GoogleURLTracker* google_url_tracker_;
+ const GURL new_google_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(GoogleURLTrackerInfoBarDelegate);
+};
+
+} // anonymous namespace
+
+InfoBarDelegate* GoogleURLTracker::InfoBarDelegateFactory::CreateInfoBar(
+ TabContents* tab_contents,
+ GoogleURLTracker* google_url_tracker,
+ const GURL& new_google_url) {
+ InfoBarDelegate* infobar =
+ new GoogleURLTrackerInfoBarDelegate(tab_contents,
+ google_url_tracker,
+ new_google_url);
+ tab_contents->AddInfoBar(infobar);
+ return infobar;
+}
GoogleURLTracker::GoogleURLTracker()
: google_url_(g_browser_process->local_state()->GetString(
prefs::kLastKnownGoogleURL)),
- ALLOW_THIS_IN_INITIALIZER_LIST(fetcher_factory_(this)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(runnable_method_factory_(this)),
+ fetcher_id_(0),
in_startup_sleep_(true),
already_fetched_(false),
need_to_fetch_(false),
- request_context_available_(!!Profile::GetDefaultRequestContext()) {
+ request_context_available_(!!Profile::GetDefaultRequestContext()),
+ need_to_prompt_(false),
+ controller_(NULL),
+ infobar_factory_(new InfoBarDelegateFactory),
+ infobar_(NULL) {
registrar_.Add(this, NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE,
NotificationService::AllSources());
+ net::NetworkChangeNotifier::AddObserver(this);
+
+ // Configure to max_retries at most kMaxRetries times for 5xx errors.
+ URLFetcherProtectEntry* protect =
+ URLFetcherProtectManager::GetInstance()->Register(
+ GURL(kSearchDomainCheckURL).host());
+ static const int kMaxRetries = 5;
+ protect->SetMaxRetries(kMaxRetries);
+
// Because this function can be called during startup, when kicking off a URL
// fetch can eat up 20 ms of time, we delay five seconds, which is hopefully
// long enough to be after startup, but still get results back quickly.
@@ -39,11 +124,14 @@ GoogleURLTracker::GoogleURLTracker()
// no function to do this.
static const int kStartFetchDelayMS = 5000;
MessageLoop::current()->PostDelayedTask(FROM_HERE,
- fetcher_factory_.NewRunnableMethod(&GoogleURLTracker::FinishSleep),
+ runnable_method_factory_.NewRunnableMethod(
+ &GoogleURLTracker::FinishSleep),
kStartFetchDelayMS);
}
GoogleURLTracker::~GoogleURLTracker() {
+ runnable_method_factory_.RevokeAll();
+ net::NetworkChangeNotifier::RemoveObserver(this);
}
// static
@@ -64,42 +152,14 @@ void GoogleURLTracker::RequestServerCheck() {
void GoogleURLTracker::RegisterPrefs(PrefService* prefs) {
prefs->RegisterStringPref(prefs::kLastKnownGoogleURL,
kDefaultGoogleHomepage);
+ prefs->RegisterStringPref(prefs::kLastPromptedGoogleURL, std::string());
}
// static
-bool GoogleURLTracker::CheckAndConvertToGoogleBaseURL(const GURL& url,
- GURL* base_url) {
- // Only allow updates if the new URL appears to be on google.xx, google.co.xx,
- // or google.com.xx. Cases other than this are either malicious, or doorway
- // pages for hotel WiFi connections and the like.
- // NOTE: Obviously the above is not as secure as whitelisting all known Google
- // frontpage domains, but for now we're trying to prevent login pages etc.
- // from ruining the user experience, rather than preventing hijacking.
- std::vector<std::string> host_components;
- SplitStringDontTrim(url.host(), '.', &host_components);
- if (host_components.size() < 2)
- return false;
- size_t google_component = host_components.size() - 2;
- const std::string& component = host_components[google_component];
- if (component != "google") {
- if ((host_components.size() < 3) ||
- ((component != "co") && (component != "com")))
- return false;
- google_component = host_components.size() - 3;
- if (host_components[google_component] != "google")
- return false;
- }
- // For Google employees only: If the URL appears to be on
- // [*.]corp.google.com, it's likely a doorway (e.g.
- // wifi.corp.google.com), so ignore it.
- if ((google_component > 0) &&
- (host_components[google_component - 1] == "corp"))
- return false;
-
- // If the url's path does not begin "/intl/", reset it to "/". Other paths
- // represent services such as iGoogle that are irrelevant to the baseURL.
- *base_url = url.path().compare(0, 6, "/intl/") ? url.GetWithEmptyPath() : url;
- return true;
+void GoogleURLTracker::GoogleURLSearchCommitted() {
+ GoogleURLTracker* tracker = g_browser_process->google_url_tracker();
+ if (tracker)
+ tracker->SearchCommitted();
}
void GoogleURLTracker::SetNeedToFetch() {
@@ -123,12 +183,10 @@ void GoogleURLTracker::StartFetchIfDesirable() {
!request_context_available_)
return;
- need_to_fetch_ = false;
- already_fetched_ = true; // If fetching fails, we don't bother to reset this
- // flag; we just live with an outdated URL for this
- // run of the browser.
- fetcher_.reset(new URLFetcher(GURL(kDefaultGoogleHomepage), URLFetcher::HEAD,
- this));
+ already_fetched_ = true;
+ fetcher_.reset(URLFetcher::Create(fetcher_id_, GURL(kSearchDomainCheckURL),
+ URLFetcher::GET, this));
+ ++fetcher_id_;
// We don't want this fetch to affect existing state in the profile. For
// example, if a user has no Google cookies, this automatic check should not
// cause one to be set, lest we alarm the user.
@@ -148,32 +206,148 @@ void GoogleURLTracker::OnURLFetchComplete(const URLFetcher* source,
scoped_ptr<URLFetcher> clean_up_fetcher(fetcher_.release());
// Don't update the URL if the request didn't succeed.
- if (!status.is_success() || (response_code != 200))
+ if (!status.is_success() || (response_code != 200)) {
+ already_fetched_ = false;
return;
+ }
- // See if the response URL was one we want to use, and if so, convert to the
+ // See if the response data was one we want to use, and if so, convert to the
// appropriate Google base URL.
- GURL base_url;
- if (!CheckAndConvertToGoogleBaseURL(url, &base_url))
+ std::string url_str;
+ TrimWhitespace(data, TRIM_ALL, &url_str);
+
+ if (!StartsWithASCII(url_str, ".google.", false))
return;
- // Update the saved base URL if it has changed.
- const std::string base_url_str(base_url.spec());
- if (g_browser_process->local_state()->GetString(prefs::kLastKnownGoogleURL) !=
- base_url_str) {
- g_browser_process->local_state()->SetString(prefs::kLastKnownGoogleURL,
- base_url_str);
- google_url_ = base_url;
- NotificationService::current()->Notify(NotificationType::GOOGLE_URL_UPDATED,
- NotificationService::AllSources(),
- NotificationService::NoDetails());
+ fetched_google_url_ = GURL("http://www" + url_str);
+ GURL last_prompted_url(
+ g_browser_process->local_state()->GetString(
+ prefs::kLastPromptedGoogleURL));
+ need_to_prompt_ = false;
+ // On the very first run of Chrome, when we've never looked up the URL at all,
+ // we should just silently switch over to whatever we get immediately.
+ if (last_prompted_url.is_empty()) {
+ AcceptGoogleURL(fetched_google_url_);
+ // Set fetched_google_url_ as an initial value of last prompted URL.
+ g_browser_process->local_state()->SetString(prefs::kLastPromptedGoogleURL,
+ fetched_google_url_.spec());
+ return;
}
+
+ if (fetched_google_url_ == last_prompted_url)
+ return;
+ if (fetched_google_url_ == google_url_) {
+ // The user came back to their original location after having temporarily
+ // moved. Reset the prompted URL so we'll prompt again if they move again.
+ g_browser_process->local_state()->SetString(prefs::kLastPromptedGoogleURL,
+ fetched_google_url_.spec());
+ return;
+ }
+
+ need_to_prompt_ = true;
+}
+
+void GoogleURLTracker::AcceptGoogleURL(const GURL& new_google_url) {
+ google_url_ = new_google_url;
+ g_browser_process->local_state()->SetString(prefs::kLastKnownGoogleURL,
+ google_url_.spec());
+ NotificationService::current()->Notify(NotificationType::GOOGLE_URL_UPDATED,
+ NotificationService::AllSources(),
+ NotificationService::NoDetails());
+ need_to_prompt_ = false;
+}
+
+void GoogleURLTracker::InfoBarClosed() {
+ registrar_.RemoveAll();
+ controller_ = NULL;
+ infobar_ = NULL;
+ search_url_ = GURL();
+}
+
+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()));
+ search_url_ = search_url_.ReplaceComponents(replacements);
+ if (search_url_.is_valid())
+ controller_->tab_contents()->OpenURL(search_url_, GURL(), CURRENT_TAB,
+ PageTransition::GENERATED);
}
void GoogleURLTracker::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
- DCHECK_EQ(NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE, type.value);
- request_context_available_ = true;
+ switch (type.value) {
+ case NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE:
+ request_context_available_ = true;
+ StartFetchIfDesirable();
+ break;
+
+ case NotificationType::NAV_ENTRY_PENDING:
+ // If we've already received a notification for the same controller, we
+ // should reset infobar as that indicates that the page is being
+ // re-loaded
+ if (!infobar_ &&
+ controller_ == Source<NavigationController>(source).ptr()) {
+ infobar_ = NULL;
+ } else if (!controller_) {
+ controller_ = Source<NavigationController>(source).ptr();
+ NavigationEntry* entry = controller_->pending_entry();
+ DCHECK(entry);
+ search_url_ = entry->url();
+
+ // 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_));
+ }
+ break;
+
+ case NotificationType::NAV_ENTRY_COMMITTED:
+ DCHECK(controller_);
+ registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED,
+ Source<NavigationController>(controller_));
+ ShowGoogleURLInfoBarIfNecessary(controller_->tab_contents());
+ break;
+
+ case NotificationType::TAB_CLOSED:
+ registrar_.RemoveAll();
+ controller_ = NULL;
+ infobar_ = NULL;
+ break;
+
+ default:
+ NOTREACHED() << "Unknown notification received:" << type.value;
+ }
+}
+
+void GoogleURLTracker::OnIPAddressChanged() {
+ already_fetched_ = false;
StartFetchIfDesirable();
}
+
+void GoogleURLTracker::SearchCommitted() {
+ registrar_.Add(this, NotificationType::NAV_ENTRY_PENDING,
+ NotificationService::AllSources());
+}
+
+void GoogleURLTracker::ShowGoogleURLInfoBarIfNecessary(
+ TabContents* tab_contents) {
+ if (!need_to_prompt_)
+ return;
+ if (infobar_)
+ return;
+ DCHECK(!fetched_google_url_.is_empty());
+ DCHECK(infobar_factory_.get());
+
+ infobar_ = infobar_factory_->CreateInfoBar(tab_contents,
+ this,
+ fetched_google_url_);
+ g_browser_process->local_state()->SetString(prefs::kLastPromptedGoogleURL,
+ fetched_google_url_.spec());
+}
« no previous file with comments | « chrome/browser/google_url_tracker.h ('k') | chrome/browser/google_url_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698