Index: chrome/browser/google/google_url_tracker.cc |
diff --git a/chrome/browser/google/google_url_tracker.cc b/chrome/browser/google/google_url_tracker.cc |
deleted file mode 100644 |
index 77cdaad3af8360893909dde58c606742edda7d83..0000000000000000000000000000000000000000 |
--- a/chrome/browser/google/google_url_tracker.cc |
+++ /dev/null |
@@ -1,407 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/google/google_url_tracker.h" |
- |
-#include "base/bind.h" |
-#include "base/command_line.h" |
-#include "base/prefs/pref_service.h" |
-#include "base/strings/string_util.h" |
-#include "chrome/browser/chrome_notification_types.h" |
-#include "chrome/browser/google/google_url_tracker_factory.h" |
-#include "chrome/browser/google/google_url_tracker_infobar_delegate.h" |
-#include "chrome/browser/google/google_url_tracker_navigation_helper.h" |
-#include "chrome/browser/google/google_util.h" |
-#include "chrome/common/pref_names.h" |
-#include "components/google/core/browser/google_pref_names.h" |
-#include "components/google/core/browser/google_switches.h" |
-#include "components/google/core/browser/google_url_tracker_client.h" |
-#include "components/infobars/core/infobar.h" |
-#include "components/infobars/core/infobar_manager.h" |
-#include "content/public/browser/notification_service.h" |
-#include "net/base/load_flags.h" |
-#include "net/base/net_util.h" |
-#include "net/url_request/url_fetcher.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=url&type=chrome"; |
- |
-GoogleURLTracker::GoogleURLTracker(scoped_ptr<GoogleURLTrackerClient> client, |
- Mode mode) |
- : client_(client.Pass()), |
- google_url_(mode == UNIT_TEST_MODE ? |
- kDefaultGoogleHomepage : |
- client_->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)), |
- fetcher_id_(0), |
- in_startup_sleep_(true), |
- already_fetched_(false), |
- need_to_fetch_(false), |
- need_to_prompt_(false), |
- search_committed_(false), |
- weak_ptr_factory_(this) { |
- net::NetworkChangeNotifier::AddIPAddressObserver(this); |
- client_->set_google_url_tracker(this); |
- |
- // 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. |
- // Ideally, instead of this timer, we'd do something like "check if the |
- // browser is starting up, and if so, come back later", but there is currently |
- // no function to do this. |
- // |
- // In UNIT_TEST mode, where we want to explicitly control when the tracker |
- // "wakes up", we do nothing at all. |
- if (mode == NORMAL_MODE) { |
- static const int kStartFetchDelayMS = 5000; |
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE, |
- base::Bind(&GoogleURLTracker::FinishSleep, |
- weak_ptr_factory_.GetWeakPtr()), |
- base::TimeDelta::FromMilliseconds(kStartFetchDelayMS)); |
- } |
-} |
- |
-GoogleURLTracker::~GoogleURLTracker() { |
- // We should only reach here after any tabs and their infobars have been torn |
- // down. |
- DCHECK(entry_map_.empty()); |
-} |
- |
-void GoogleURLTracker::RequestServerCheck(bool force) { |
- // If this instance already has a fetcher, SetNeedToFetch() is unnecessary, |
- // and changing |already_fetched_| is wrong. |
- if (!fetcher_) { |
- if (force) |
- already_fetched_ = false; |
- SetNeedToFetch(); |
- } |
-} |
- |
-void GoogleURLTracker::SearchCommitted() { |
- if (need_to_prompt_) { |
- search_committed_ = true; |
- // These notifications will fire a bit later in the same call chain we're |
- // currently in. |
- if (!client_->IsListeningForNavigationStart()) |
- client_->SetListeningForNavigationStart(true); |
- } |
-} |
- |
-void GoogleURLTracker::AcceptGoogleURL(bool redo_searches) { |
- GURL old_google_url = google_url_; |
- google_url_ = fetched_google_url_; |
- PrefService* prefs = client_->GetPrefs(); |
- prefs->SetString(prefs::kLastKnownGoogleURL, google_url_.spec()); |
- prefs->SetString(prefs::kLastPromptedGoogleURL, google_url_.spec()); |
- NotifyGoogleURLUpdated(old_google_url, google_url_); |
- |
- need_to_prompt_ = false; |
- CloseAllEntries(redo_searches); |
-} |
- |
-void GoogleURLTracker::CancelGoogleURL() { |
- client_->GetPrefs()->SetString(prefs::kLastPromptedGoogleURL, |
- fetched_google_url_.spec()); |
- need_to_prompt_ = false; |
- CloseAllEntries(false); |
-} |
- |
-void GoogleURLTracker::OnURLFetchComplete(const net::URLFetcher* source) { |
- // Delete the fetcher on this function's exit. |
- scoped_ptr<net::URLFetcher> clean_up_fetcher(fetcher_.release()); |
- |
- // Don't update the URL if the request didn't succeed. |
- if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200)) { |
- already_fetched_ = false; |
- return; |
- } |
- |
- // See if the response data was valid. It should be |
- // "<scheme>://[www.]google.<TLD>/". |
- std::string url_str; |
- source->GetResponseAsString(&url_str); |
- base::TrimWhitespace(url_str, base::TRIM_ALL, &url_str); |
- GURL url(url_str); |
- if (!url.is_valid() || (url.path().length() > 1) || url.has_query() || |
- url.has_ref() || |
- !google_util::IsGoogleDomainUrl(url, google_util::DISALLOW_SUBDOMAIN, |
- google_util::DISALLOW_NON_STANDARD_PORTS)) |
- return; |
- |
- std::swap(url, fetched_google_url_); |
- GURL last_prompted_url( |
- client_->GetPrefs()->GetString(prefs::kLastPromptedGoogleURL)); |
- |
- if (last_prompted_url.is_empty()) { |
- // 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. |
- AcceptGoogleURL(true); // Arg is irrelevant. |
- return; |
- } |
- |
- base::string16 fetched_host(net::StripWWWFromHost(fetched_google_url_)); |
- if (fetched_google_url_ == google_url_) { |
- // Either the user has continually been on this URL, or we prompted for a |
- // different URL but have now changed back before they responded to any of |
- // the prompts. In this latter case we want to close any infobars and stop |
- // prompting. |
- CancelGoogleURL(); |
- } else if (fetched_host == net::StripWWWFromHost(google_url_)) { |
- // Similar to the above case, but this time the new URL differs from the |
- // existing one, probably due to switching between HTTP and HTTPS searching. |
- // Like before we want to close any infobars and stop prompting; we also |
- // want to silently accept the change in scheme. We don't redo open |
- // searches so as to avoid suddenly changing a page the user might be |
- // interacting with; it's enough to simply get future searches right. |
- AcceptGoogleURL(false); |
- } else if (fetched_host == net::StripWWWFromHost(last_prompted_url)) { |
- // We've re-fetched a TLD the user previously turned down. Although the new |
- // URL might have a different scheme than the old, we want to preserve the |
- // user's decision. Note that it's possible that, like in the above two |
- // cases, we fetched yet another different URL in the meantime, which we |
- // have infobars prompting about; in this case, as in those above, we want |
- // to go ahead and close the infobars and stop prompting, since we've |
- // switched back away from that URL. |
- CancelGoogleURL(); |
- } else { |
- // We've fetched a URL with a different TLD than the user is currently using |
- // or was previously prompted about. This means we need to prompt again. |
- need_to_prompt_ = true; |
- |
- // As in all the above cases, there could be infobars prompting about some |
- // URL. If these URLs have the same TLD (e.g. for scheme changes), we can |
- // simply leave the existing infobars open as their messages will still be |
- // accurate. Otherwise we go ahead and close them because we need to |
- // display a new message. |
- // Note: |url| is the previous |fetched_google_url_|. |
- if (url.is_valid() && (fetched_host != net::StripWWWFromHost(url))) |
- CloseAllEntries(false); |
- } |
-} |
- |
-void GoogleURLTracker::OnIPAddressChanged() { |
- already_fetched_ = false; |
- StartFetchIfDesirable(); |
-} |
- |
-void GoogleURLTracker::Shutdown() { |
- client_.reset(); |
- fetcher_.reset(); |
- weak_ptr_factory_.InvalidateWeakPtrs(); |
- net::NetworkChangeNotifier::RemoveIPAddressObserver(this); |
-} |
- |
-void GoogleURLTracker::DeleteMapEntryForManager( |
- const infobars::InfoBarManager* infobar_manager) { |
- // WARNING: |infobar_manager| may point to a deleted object. Do not |
- // dereference it! See OnTabClosed(). |
- EntryMap::iterator i(entry_map_.find(infobar_manager)); |
- DCHECK(i != entry_map_.end()); |
- GoogleURLTrackerMapEntry* map_entry = i->second; |
- |
- UnregisterForEntrySpecificNotifications(map_entry, false); |
- entry_map_.erase(i); |
- delete map_entry; |
-} |
- |
-void GoogleURLTracker::SetNeedToFetch() { |
- need_to_fetch_ = true; |
- StartFetchIfDesirable(); |
-} |
- |
-void GoogleURLTracker::FinishSleep() { |
- in_startup_sleep_ = false; |
- StartFetchIfDesirable(); |
-} |
- |
-void GoogleURLTracker::StartFetchIfDesirable() { |
- // Bail if a fetch isn't appropriate right now. This function will be called |
- // again each time one of the preconditions changes, so we'll fetch |
- // immediately once all of them are met. |
- // |
- // See comments in header on the class, on RequestServerCheck(), and on the |
- // various members here for more detail on exactly what the conditions are. |
- if (in_startup_sleep_ || already_fetched_ || !need_to_fetch_) |
- return; |
- |
- // Some switches should disable the Google URL tracker entirely. If we can't |
- // do background networking, we can't do the necessary fetch, and if the user |
- // specified a Google base URL manually, we shouldn't bother to look up any |
- // alternatives or offer to switch to them. |
- if (!client_->IsBackgroundNetworkingEnabled() || |
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kGoogleBaseURL)) |
- return; |
- |
- already_fetched_ = true; |
- fetcher_.reset(net::URLFetcher::Create( |
- fetcher_id_, GURL(kSearchDomainCheckURL), net::URLFetcher::GET, this)); |
- ++fetcher_id_; |
- // We don't want this fetch to set new entries in the cache or cookies, lest |
- // we alarm the user. |
- fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE | |
- net::LOAD_DO_NOT_SAVE_COOKIES); |
- fetcher_->SetRequestContext(client_->GetRequestContext()); |
- |
- // Configure to max_retries at most kMaxRetries times for 5xx errors. |
- static const int kMaxRetries = 5; |
- fetcher_->SetMaxRetriesOn5xx(kMaxRetries); |
- |
- fetcher_->Start(); |
-} |
- |
-void GoogleURLTracker::OnNavigationPending( |
- scoped_ptr<GoogleURLTrackerNavigationHelper> nav_helper, |
- infobars::InfoBarManager* infobar_manager, |
- int pending_id) { |
- GoogleURLTrackerMapEntry* map_entry = NULL; |
- |
- EntryMap::iterator i(entry_map_.find(infobar_manager)); |
- if (i != entry_map_.end()) |
- map_entry = i->second; |
- |
- if (search_committed_) { |
- search_committed_ = false; |
- if (!map_entry) { |
- // This is a search on a tab that doesn't have one of our infobars, so |
- // prepare to add one. Note that we only listen for the tab's destruction |
- // on this path; if there was already a map entry, then either it doesn't |
- // yet have an infobar and we're already registered for this, or it has an |
- // infobar and the infobar's owner will handle tearing it down when the |
- // tab is destroyed. |
- map_entry = new GoogleURLTrackerMapEntry( |
- this, infobar_manager, nav_helper.Pass()); |
- map_entry->navigation_helper()->SetListeningForTabDestruction(true); |
- entry_map_.insert(std::make_pair(infobar_manager, map_entry)); |
- } else if (map_entry->infobar_delegate()) { |
- // This is a new search on a tab where we already have an infobar. |
- map_entry->infobar_delegate()->set_pending_id(pending_id); |
- } |
- |
- // Whether there's an existing infobar or not, we need to listen for the |
- // load to commit, so we can show and/or update the infobar when it does. |
- // (We may already be registered for this if there is an existing infobar |
- // that had a previous pending search that hasn't yet committed.) |
- if (!map_entry->navigation_helper()->IsListeningForNavigationCommit()) |
- map_entry->navigation_helper()->SetListeningForNavigationCommit(true); |
- } else if (map_entry) { |
- if (map_entry->has_infobar_delegate()) { |
- // This is a non-search navigation on a tab with an infobar. If there was |
- // a previous pending search on this tab, this means it won't commit, so |
- // undo anything we did in response to seeing that. Note that if there |
- // was no pending search on this tab, these statements are effectively a |
- // no-op. |
- // |
- // If this navigation actually commits, that will trigger the infobar's |
- // owner to expire the infobar if need be. If it doesn't commit, then |
- // simply leaving the infobar as-is will have been the right thing. |
- UnregisterForEntrySpecificNotifications(map_entry, false); |
- map_entry->infobar_delegate()->set_pending_id(0); |
- } else { |
- // Non-search navigation on a tab with an entry that has not yet created |
- // an infobar. This means the original search won't commit, so delete the |
- // entry. |
- map_entry->Close(false); |
- } |
- } else { |
- // Non-search navigation on a tab without an infobars. This is irrelevant |
- // to us. |
- } |
-} |
- |
-void GoogleURLTracker::OnNavigationCommitted( |
- infobars::InfoBarManager* infobar_manager, |
- const GURL& search_url) { |
- EntryMap::iterator i(entry_map_.find(infobar_manager)); |
- DCHECK(i != entry_map_.end()); |
- GoogleURLTrackerMapEntry* map_entry = i->second; |
- DCHECK(search_url.is_valid()); |
- |
- UnregisterForEntrySpecificNotifications(map_entry, true); |
- if (map_entry->has_infobar_delegate()) { |
- map_entry->infobar_delegate()->Update(search_url); |
- } else { |
- infobars::InfoBar* infobar = GoogleURLTrackerInfoBarDelegate::Create( |
- infobar_manager, this, search_url); |
- if (infobar) { |
- map_entry->SetInfoBarDelegate( |
- static_cast<GoogleURLTrackerInfoBarDelegate*>(infobar->delegate())); |
- } else { |
- map_entry->Close(false); |
- } |
- } |
-} |
- |
-void GoogleURLTracker::OnTabClosed( |
- GoogleURLTrackerNavigationHelper* nav_helper) { |
- // Because InfoBarManager tears itself down on tab destruction, it's possible |
- // to get a non-NULL InfoBarManager pointer here, depending on which order |
- // notifications fired in. Likewise, the pointer in |entry_map_| (and in its |
- // associated MapEntry) may point to deleted memory. Therefore, if we were |
- // to access the InfoBarManager* we have for this tab, we'd need to ensure we |
- // just looked at the raw pointer value, and never dereferenced it. This |
- // function doesn't need to do even that, but others in the call chain from |
- // here might (and have comments pointing back here). |
- for (EntryMap::iterator i(entry_map_.begin()); i != entry_map_.end(); ++i) { |
- if (i->second->navigation_helper() == nav_helper) { |
- i->second->Close(false); |
- return; |
- } |
- } |
- NOTREACHED(); |
-} |
- |
-scoped_ptr<GoogleURLTracker::Subscription> GoogleURLTracker::RegisterCallback( |
- const OnGoogleURLUpdatedCallback& cb) { |
- return callback_list_.Add(cb); |
-} |
- |
-void GoogleURLTracker::CloseAllEntries(bool redo_searches) { |
- // Delete all entries, whether they have infobars or not. |
- while (!entry_map_.empty()) |
- entry_map_.begin()->second->Close(redo_searches); |
-} |
- |
-void GoogleURLTracker::UnregisterForEntrySpecificNotifications( |
- GoogleURLTrackerMapEntry* map_entry, |
- bool must_be_listening_for_commit) { |
- // For tabs with map entries but no infobars, we should always be listening |
- // for both these notifications. For tabs with infobars, we may be listening |
- // for navigation commits if the user has performed a new search on this tab. |
- if (map_entry->navigation_helper()->IsListeningForNavigationCommit()) { |
- map_entry->navigation_helper()->SetListeningForNavigationCommit(false); |
- } else { |
- DCHECK(!must_be_listening_for_commit); |
- DCHECK(map_entry->has_infobar_delegate()); |
- } |
- const bool registered_for_tab_destruction = |
- map_entry->navigation_helper()->IsListeningForTabDestruction(); |
- DCHECK_NE(registered_for_tab_destruction, map_entry->has_infobar_delegate()); |
- if (registered_for_tab_destruction) { |
- map_entry->navigation_helper()->SetListeningForTabDestruction(false); |
- } |
- |
- // Our global listeners for these other notifications should be in place iff |
- // we have any tabs still listening for commits. These tabs either have no |
- // infobars or have received new pending searches atop existing infobars; in |
- // either case we want to catch subsequent pending non-search navigations. |
- // See the various cases inside OnNavigationPending(). |
- for (EntryMap::const_iterator i(entry_map_.begin()); i != entry_map_.end(); |
- ++i) { |
- if (i->second->navigation_helper()->IsListeningForNavigationCommit()) { |
- DCHECK(client_->IsListeningForNavigationStart()); |
- return; |
- } |
- } |
- if (client_->IsListeningForNavigationStart()) { |
- DCHECK(!search_committed_); |
- client_->SetListeningForNavigationStart(false); |
- } |
-} |
- |
-void GoogleURLTracker::NotifyGoogleURLUpdated(GURL old_url, GURL new_url) { |
- callback_list_.Notify(old_url, new_url); |
-} |