This source file includes following definitions.
- weak_ptr_factory_
- RequestServerCheck
- GoogleURLSearchCommitted
- AcceptGoogleURL
- CancelGoogleURL
- OnURLFetchComplete
- OnIPAddressChanged
- Shutdown
- DeleteMapEntryForService
- SetNeedToFetch
- FinishSleep
- StartFetchIfDesirable
- SearchCommitted
- OnNavigationPending
- OnNavigationCommitted
- OnTabClosed
- CloseAllEntries
- UnregisterForEntrySpecificNotifications
#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/browser/infobars/infobar.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.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(
Profile* profile,
scoped_ptr<GoogleURLTrackerNavigationHelper> nav_helper,
Mode mode)
: profile_(profile),
nav_helper_(nav_helper.Pass()),
infobar_creator_(base::Bind(&GoogleURLTrackerInfoBarDelegate::Create)),
google_url_(mode == UNIT_TEST_MODE ? kDefaultGoogleHomepage :
profile->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);
nav_helper_->SetGoogleURLTracker(this);
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() {
DCHECK(entry_map_.empty());
}
GURL GoogleURLTracker::GoogleURL(Profile* profile) {
const GoogleURLTracker* tracker =
GoogleURLTrackerFactory::GetForProfile(profile);
return tracker ? tracker->google_url_ : GURL(kDefaultGoogleHomepage);
}
void GoogleURLTracker::RequestServerCheck(Profile* profile, bool force) {
GoogleURLTracker* tracker = GoogleURLTrackerFactory::GetForProfile(profile);
if (tracker && !tracker->fetcher_) {
if (force)
tracker->already_fetched_ = false;
tracker->SetNeedToFetch();
}
}
void GoogleURLTracker::GoogleURLSearchCommitted(Profile* profile) {
GoogleURLTracker* tracker = GoogleURLTrackerFactory::GetForProfile(profile);
if (tracker)
tracker->SearchCommitted();
}
void GoogleURLTracker::AcceptGoogleURL(bool redo_searches) {
UpdatedDetails urls(google_url_, fetched_google_url_);
google_url_ = fetched_google_url_;
PrefService* prefs = profile_->GetPrefs();
prefs->SetString(prefs::kLastKnownGoogleURL, google_url_.spec());
prefs->SetString(prefs::kLastPromptedGoogleURL, google_url_.spec());
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_GOOGLE_URL_UPDATED,
content::Source<Profile>(profile_),
content::Details<UpdatedDetails>(&urls));
need_to_prompt_ = false;
CloseAllEntries(redo_searches);
}
void GoogleURLTracker::CancelGoogleURL() {
profile_->GetPrefs()->SetString(prefs::kLastPromptedGoogleURL,
fetched_google_url_.spec());
need_to_prompt_ = false;
CloseAllEntries(false);
}
void GoogleURLTracker::OnURLFetchComplete(const net::URLFetcher* source) {
scoped_ptr<net::URLFetcher> clean_up_fetcher(fetcher_.release());
if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200)) {
already_fetched_ = false;
return;
}
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(
profile_->GetPrefs()->GetString(prefs::kLastPromptedGoogleURL));
if (last_prompted_url.is_empty()) {
AcceptGoogleURL(true);
return;
}
base::string16 fetched_host(net::StripWWWFromHost(fetched_google_url_));
if (fetched_google_url_ == google_url_) {
CancelGoogleURL();
} else if (fetched_host == net::StripWWWFromHost(google_url_)) {
AcceptGoogleURL(false);
} else if (fetched_host == net::StripWWWFromHost(last_prompted_url)) {
CancelGoogleURL();
} else {
need_to_prompt_ = true;
if (url.is_valid() && (fetched_host != net::StripWWWFromHost(url)))
CloseAllEntries(false);
}
}
void GoogleURLTracker::OnIPAddressChanged() {
already_fetched_ = false;
StartFetchIfDesirable();
}
void GoogleURLTracker::Shutdown() {
nav_helper_.reset();
fetcher_.reset();
weak_ptr_factory_.InvalidateWeakPtrs();
net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
}
void GoogleURLTracker::DeleteMapEntryForService(
const InfoBarService* infobar_service) {
EntryMap::iterator i(entry_map_.find(infobar_service));
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() {
if (in_startup_sleep_ || already_fetched_ || !need_to_fetch_)
return;
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableBackgroundNetworking) ||
CommandLine::ForCurrentProcess()->HasSwitch(switches::kGoogleBaseURL))
return;
already_fetched_ = true;
fetcher_.reset(net::URLFetcher::Create(
fetcher_id_, GURL(kSearchDomainCheckURL), net::URLFetcher::GET, this));
++fetcher_id_;
fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE |
net::LOAD_DO_NOT_SAVE_COOKIES);
fetcher_->SetRequestContext(profile_->GetRequestContext());
static const int kMaxRetries = 5;
fetcher_->SetMaxRetriesOn5xx(kMaxRetries);
fetcher_->Start();
}
void GoogleURLTracker::SearchCommitted() {
if (need_to_prompt_) {
search_committed_ = true;
if (!nav_helper_->IsListeningForNavigationStart())
nav_helper_->SetListeningForNavigationStart(true);
}
}
void GoogleURLTracker::OnNavigationPending(
content::NavigationController* navigation_controller,
InfoBarService* infobar_service,
int pending_id) {
EntryMap::iterator i(entry_map_.find(infobar_service));
if (search_committed_) {
search_committed_ = false;
if (!nav_helper_->IsListeningForNavigationCommit(navigation_controller)) {
nav_helper_->SetListeningForNavigationCommit(navigation_controller,
true);
}
if (i == entry_map_.end()) {
nav_helper_->SetListeningForTabDestruction(navigation_controller, true);
entry_map_.insert(std::make_pair(
infobar_service,
new GoogleURLTrackerMapEntry(this, infobar_service,
navigation_controller)));
} else if (i->second->has_infobar_delegate()) {
i->second->infobar_delegate()->set_pending_id(pending_id);
}
} else if (i != entry_map_.end()){
if (i->second->has_infobar_delegate()) {
UnregisterForEntrySpecificNotifications(*i->second, false);
i->second->infobar_delegate()->set_pending_id(0);
} else {
i->second->Close(false);
}
} else {
}
}
void GoogleURLTracker::OnNavigationCommitted(InfoBarService* infobar_service,
const GURL& search_url) {
EntryMap::iterator i(entry_map_.find(infobar_service));
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 {
InfoBar* infobar = infobar_creator_.Run(infobar_service, this, search_url);
if (infobar) {
map_entry->SetInfoBarDelegate(
static_cast<GoogleURLTrackerInfoBarDelegate*>(infobar->delegate()));
} else {
map_entry->Close(false);
}
}
}
void GoogleURLTracker::OnTabClosed(
content::NavigationController* navigation_controller) {
for (EntryMap::iterator i(entry_map_.begin()); i != entry_map_.end(); ++i) {
if (i->second->navigation_controller() == navigation_controller) {
i->second->Close(false);
return;
}
}
NOTREACHED();
}
void GoogleURLTracker::CloseAllEntries(bool redo_searches) {
while (!entry_map_.empty())
entry_map_.begin()->second->Close(redo_searches);
}
void GoogleURLTracker::UnregisterForEntrySpecificNotifications(
const GoogleURLTrackerMapEntry& map_entry,
bool must_be_listening_for_commit) {
if (nav_helper_->IsListeningForNavigationCommit(
map_entry.navigation_controller())) {
nav_helper_->SetListeningForNavigationCommit(
map_entry.navigation_controller(), false);
} else {
DCHECK(!must_be_listening_for_commit);
DCHECK(map_entry.has_infobar_delegate());
}
const bool registered_for_tab_destruction =
nav_helper_->IsListeningForTabDestruction(
map_entry.navigation_controller());
DCHECK_NE(registered_for_tab_destruction, map_entry.has_infobar_delegate());
if (registered_for_tab_destruction) {
nav_helper_->SetListeningForTabDestruction(
map_entry.navigation_controller(), false);
}
for (EntryMap::const_iterator i(entry_map_.begin()); i != entry_map_.end();
++i) {
if (nav_helper_->IsListeningForNavigationCommit(
i->second->navigation_controller())) {
DCHECK(nav_helper_->IsListeningForNavigationStart());
return;
}
}
if (nav_helper_->IsListeningForNavigationStart()) {
DCHECK(!search_committed_);
nav_helper_->SetListeningForNavigationStart(false);
}
}