// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h"
#include "base/check.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/google/google_brand.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/ui/startup/startup_browser_creator.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/google/core/common/google_util.h"
#include "components/omnibox/browser/omnibox_log.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "rlz/buildflags/buildflags.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#if BUILDFLAG(IS_WIN)
#include "chrome/installer/util/google_update_settings.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/constants/ash_switches.h"
#endif
ChromeRLZTrackerDelegate::ChromeRLZTrackerDelegate() {}
ChromeRLZTrackerDelegate::~ChromeRLZTrackerDelegate() {}
// static
void ChromeRLZTrackerDelegate::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
#if BUILDFLAG(ENABLE_RLZ)
int rlz_ping_delay_seconds = 90;
#if BUILDFLAG(IS_CHROMEOS_ASH)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
ash::switches::kRlzPingDelay)) {
// Use a switch for overwriting the default delay because it doesn't seem
// possible to manually override the Preferences file on Chrome OS: the file
// is already loaded into memory by the time you modify it and any changes
// made get overwritten by Chrome.
int parsed_delay_from_switch = 0;
if (base::StringToInt(
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
ash::switches::kRlzPingDelay),
&parsed_delay_from_switch)) {
rlz_ping_delay_seconds = parsed_delay_from_switch;
}
} else {
rlz_ping_delay_seconds = 24 * 3600;
}
#endif
registry->RegisterIntegerPref(prefs::kRlzPingDelaySeconds,
rlz_ping_delay_seconds);
#endif
}
// static
bool ChromeRLZTrackerDelegate::IsGoogleDefaultSearch(Profile* profile) {
bool is_google_default_search = false;
TemplateURLService* template_url_service =
TemplateURLServiceFactory::GetForProfile(profile);
if (template_url_service) {
const TemplateURL* url_template =
template_url_service->GetDefaultSearchProvider();
is_google_default_search = url_template &&
url_template->url_ref().HasGoogleBaseURLs(
template_url_service->search_terms_data());
}
return is_google_default_search;
}
// static
bool ChromeRLZTrackerDelegate::IsGoogleHomepage(Profile* profile) {
return google_util::IsGoogleHomePageUrl(
GURL(profile->GetPrefs()->GetString(prefs::kHomePage)));
}
// static
bool ChromeRLZTrackerDelegate::IsGoogleInStartpages(Profile* profile) {
bool is_google_in_startpages = false;
SessionStartupPref session_startup_prefs =
StartupBrowserCreator::GetSessionStartupPref(
*base::CommandLine::ForCurrentProcess(), profile);
if (session_startup_prefs.type == SessionStartupPref::URLS) {
is_google_in_startpages = base::Contains(session_startup_prefs.urls, true,
google_util::IsGoogleHomePageUrl);
}
return is_google_in_startpages;
}
void ChromeRLZTrackerDelegate::Cleanup() {
on_omnibox_search_callback_.Reset();
on_homepage_search_callback_.Reset();
}
bool ChromeRLZTrackerDelegate::IsOnUIThread() {
return content::BrowserThread::CurrentlyOn(content::BrowserThread::UI);
}
scoped_refptr<network::SharedURLLoaderFactory>
ChromeRLZTrackerDelegate::GetURLLoaderFactory() {
return g_browser_process->shared_url_loader_factory();
}
bool ChromeRLZTrackerDelegate::GetBrand(std::string* brand) {
return google_brand::GetRlzBrand(brand);
}
bool ChromeRLZTrackerDelegate::IsBrandOrganic(const std::string& brand) {
return google_brand::IsOrganic(brand);
}
bool ChromeRLZTrackerDelegate::GetReactivationBrand(std::string* brand) {
return google_brand::GetReactivationBrand(brand);
}
bool ChromeRLZTrackerDelegate::ShouldEnableZeroDelayForTesting() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kTestType);
}
bool ChromeRLZTrackerDelegate::GetLanguage(std::u16string* language) {
#if BUILDFLAG(IS_WIN)
std::wstring wide_language;
bool result = GoogleUpdateSettings::GetLanguage(&wide_language);
*language = base::AsString16(wide_language);
return result;
#else
// On other systems, we don't know the install language of promotions. That's
// OK, for now all promotions on non-Windows systems will be reported as "en".
// If non-Windows promotions end up requiring language code reporting, that
// code will need to go here.
return false;
#endif
}
bool ChromeRLZTrackerDelegate::GetReferral(std::u16string* referral) {
#if BUILDFLAG(IS_WIN)
std::wstring wide_referral;
bool result = GoogleUpdateSettings::GetReferral(&wide_referral);
*referral = base::AsString16(wide_referral);
return result;
#else
// The referral program is defunct and not used. No need to implement this
// function on non-Win platforms.
return true;
#endif
}
bool ChromeRLZTrackerDelegate::ClearReferral() {
#if BUILDFLAG(IS_WIN)
return GoogleUpdateSettings::ClearReferral();
#else
// The referral program is defunct and not used. No need to implement this
// function on non-Win platforms.
return true;
#endif
}
void ChromeRLZTrackerDelegate::SetOmniboxSearchCallback(
base::OnceClosure callback) {
DCHECK(!callback.is_null());
omnibox_url_opened_subscription_ =
OmniboxEventGlobalTracker::GetInstance()->RegisterCallback(
base::BindRepeating(&ChromeRLZTrackerDelegate::OnURLOpenedFromOmnibox,
base::Unretained(this)));
on_omnibox_search_callback_ = std::move(callback);
}
void ChromeRLZTrackerDelegate::SetHomepageSearchCallback(
base::OnceClosure callback) {
DCHECK(!callback.is_null());
on_homepage_search_callback_ = std::move(callback);
}
void ChromeRLZTrackerDelegate::RunHomepageSearchCallback() {
if (!on_homepage_search_callback_.is_null()) {
std::move(on_homepage_search_callback_).Run();
}
}
bool ChromeRLZTrackerDelegate::ShouldUpdateExistingAccessPointRlz() {
return true;
}
void ChromeRLZTrackerDelegate::OnURLOpenedFromOmnibox(OmniboxLog* log) {
// In M-36, we made NOTIFICATION_OMNIBOX_OPENED_URL fire more often than
// it did previously. The RLZ folks want RLZ's "first search" detection
// to remain as unaffected as possible by this change. This test is
// there to keep the old behavior.
if (!log->is_popup_open)
return;
omnibox_url_opened_subscription_ = {};
std::move(on_omnibox_search_callback_).Run();
}