sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h" |
| 6 | |
Sebastien Marchand | f1349f5 | 2019-01-25 03:16:41 | [diff] [blame] | 7 | #include "base/bind.h" |
Hans Wennborg | 1790e6b | 2020-04-24 19:10:33 | [diff] [blame] | 8 | #include "base/check.h" |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 9 | #include "base/command_line.h" |
Hans Wennborg | 1790e6b | 2020-04-24 19:10:33 | [diff] [blame] | 10 | #include "base/notreached.h" |
avi | b896c71 | 2015-12-26 02:10:43 | [diff] [blame] | 11 | #include "build/build_config.h" |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 12 | #include "chrome/browser/browser_process.h" |
| 13 | #include "chrome/browser/chrome_notification_types.h" |
| 14 | #include "chrome/browser/google/google_brand.h" |
sdefresne | bd4c75c | 2015-07-22 09:06:18 | [diff] [blame] | 15 | #include "chrome/browser/prefs/session_startup_pref.h" |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 16 | #include "chrome/browser/profiles/profile.h" |
| 17 | #include "chrome/browser/search_engines/template_url_service_factory.h" |
sdefresne | bd4c75c | 2015-07-22 09:06:18 | [diff] [blame] | 18 | #include "chrome/browser/ui/startup/startup_browser_creator.h" |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 19 | #include "chrome/common/chrome_switches.h" |
| 20 | #include "chrome/common/pref_names.h" |
John Abd-El-Malek | 9cf3d7f0 | 2018-07-27 02:40:39 | [diff] [blame] | 21 | #include "components/google/core/common/google_util.h" |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 22 | #include "components/omnibox/browser/omnibox_log.h" |
gab | 3ca4a49 | 2017-03-02 00:19:41 | [diff] [blame] | 23 | #include "components/pref_registry/pref_registry_syncable.h" |
brettw | b1fc1b8 | 2016-02-02 00:19:08 | [diff] [blame] | 24 | #include "components/prefs/pref_service.h" |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 25 | #include "components/search_engines/template_url.h" |
| 26 | #include "components/search_engines/template_url_service.h" |
| 27 | #include "content/public/browser/browser_thread.h" |
| 28 | #include "content/public/browser/navigation_controller.h" |
| 29 | #include "content/public/browser/navigation_details.h" |
| 30 | #include "content/public/browser/navigation_entry.h" |
| 31 | #include "content/public/browser/notification_details.h" |
| 32 | #include "content/public/browser/notification_service.h" |
| 33 | #include "content/public/browser/notification_source.h" |
brettw | 90e9260 | 2015-10-10 00:12:40 | [diff] [blame] | 34 | #include "content/public/common/content_switches.h" |
Scott Violet | a5f7ba1 | 2018-04-02 22:03:40 | [diff] [blame] | 35 | #include "rlz/buildflags/buildflags.h" |
Antonio Gomes | a739bf46 | 2018-08-13 20:50:30 | [diff] [blame] | 36 | #include "services/network/public/cpp/shared_url_loader_factory.h" |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 37 | |
| 38 | #if defined(OS_WIN) |
| 39 | #include "chrome/installer/util/google_update_settings.h" |
| 40 | #endif |
| 41 | |
Wenzhao Zang | 8825a77 | 2018-04-04 01:56:22 | [diff] [blame] | 42 | #if defined(OS_CHROMEOS) |
| 43 | #include "base/command_line.h" |
Steven Bennetts | 38e9bde2 | 2019-01-03 17:31:10 | [diff] [blame] | 44 | #include "chromeos/constants/chromeos_switches.h" |
Wenzhao Zang | 8825a77 | 2018-04-04 01:56:22 | [diff] [blame] | 45 | #endif |
| 46 | |
rogerta | c4a9c77 | 2017-08-01 16:40:30 | [diff] [blame] | 47 | ChromeRLZTrackerDelegate::ChromeRLZTrackerDelegate() {} |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 48 | |
rogerta | c4a9c77 | 2017-08-01 16:40:30 | [diff] [blame] | 49 | ChromeRLZTrackerDelegate::~ChromeRLZTrackerDelegate() {} |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 50 | |
| 51 | // static |
gab | 3ca4a49 | 2017-03-02 00:19:41 | [diff] [blame] | 52 | void ChromeRLZTrackerDelegate::RegisterProfilePrefs( |
| 53 | user_prefs::PrefRegistrySyncable* registry) { |
| 54 | #if BUILDFLAG(ENABLE_RLZ) |
Wenzhao Zang | 8825a77 | 2018-04-04 01:56:22 | [diff] [blame] | 55 | int rlz_ping_delay_seconds = 90; |
Roger Tawa | c5d56c3c | 2018-03-15 14:21:23 | [diff] [blame] | 56 | #if defined(OS_CHROMEOS) |
Wenzhao Zang | 8825a77 | 2018-04-04 01:56:22 | [diff] [blame] | 57 | if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 58 | chromeos::switches::kRlzPingDelay)) { |
| 59 | // Use a switch for overwriting the default delay because it doesn't seem |
| 60 | // possible to manually override the Preferences file on Chrome OS: the file |
| 61 | // is already loaded into memory by the time you modify it and any changes |
| 62 | // made get overwritten by Chrome. |
| 63 | rlz_ping_delay_seconds = |
| 64 | std::stoi(base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 65 | chromeos::switches::kRlzPingDelay)); |
| 66 | } else { |
| 67 | rlz_ping_delay_seconds = 24 * 3600; |
| 68 | } |
gab | 3ca4a49 | 2017-03-02 00:19:41 | [diff] [blame] | 69 | #endif |
Wenzhao Zang | 8825a77 | 2018-04-04 01:56:22 | [diff] [blame] | 70 | registry->RegisterIntegerPref(prefs::kRlzPingDelaySeconds, |
| 71 | rlz_ping_delay_seconds); |
Roger Tawa | c5d56c3c | 2018-03-15 14:21:23 | [diff] [blame] | 72 | #endif |
gab | 3ca4a49 | 2017-03-02 00:19:41 | [diff] [blame] | 73 | } |
| 74 | |
| 75 | // static |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 76 | bool ChromeRLZTrackerDelegate::IsGoogleDefaultSearch(Profile* profile) { |
| 77 | bool is_google_default_search = false; |
| 78 | TemplateURLService* template_url_service = |
| 79 | TemplateURLServiceFactory::GetForProfile(profile); |
| 80 | if (template_url_service) { |
| 81 | const TemplateURL* url_template = |
| 82 | template_url_service->GetDefaultSearchProvider(); |
| 83 | is_google_default_search = url_template && |
| 84 | url_template->url_ref().HasGoogleBaseURLs( |
| 85 | template_url_service->search_terms_data()); |
| 86 | } |
| 87 | return is_google_default_search; |
| 88 | } |
| 89 | |
| 90 | // static |
| 91 | bool ChromeRLZTrackerDelegate::IsGoogleHomepage(Profile* profile) { |
| 92 | return google_util::IsGoogleHomePageUrl( |
| 93 | GURL(profile->GetPrefs()->GetString(prefs::kHomePage))); |
| 94 | } |
| 95 | |
| 96 | // static |
| 97 | bool ChromeRLZTrackerDelegate::IsGoogleInStartpages(Profile* profile) { |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 98 | bool is_google_in_startpages = false; |
| 99 | SessionStartupPref session_startup_prefs = |
| 100 | StartupBrowserCreator::GetSessionStartupPref( |
| 101 | *base::CommandLine::ForCurrentProcess(), profile); |
| 102 | if (session_startup_prefs.type == SessionStartupPref::URLS) { |
| 103 | is_google_in_startpages = |
| 104 | std::count_if(session_startup_prefs.urls.begin(), |
| 105 | session_startup_prefs.urls.end(), |
| 106 | google_util::IsGoogleHomePageUrl) > 0; |
| 107 | } |
| 108 | return is_google_in_startpages; |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 109 | } |
| 110 | |
| 111 | void ChromeRLZTrackerDelegate::Cleanup() { |
| 112 | registrar_.RemoveAll(); |
| 113 | on_omnibox_search_callback_.Reset(); |
| 114 | on_homepage_search_callback_.Reset(); |
| 115 | } |
| 116 | |
| 117 | bool ChromeRLZTrackerDelegate::IsOnUIThread() { |
| 118 | return content::BrowserThread::CurrentlyOn(content::BrowserThread::UI); |
| 119 | } |
| 120 | |
Antonio Gomes | a739bf46 | 2018-08-13 20:50:30 | [diff] [blame] | 121 | scoped_refptr<network::SharedURLLoaderFactory> |
| 122 | ChromeRLZTrackerDelegate::GetURLLoaderFactory() { |
| 123 | return g_browser_process->shared_url_loader_factory(); |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | bool ChromeRLZTrackerDelegate::GetBrand(std::string* brand) { |
Wenzhao Zang | 2015379 | 2018-09-29 00:37:10 | [diff] [blame] | 127 | return google_brand::GetRlzBrand(brand); |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 128 | } |
| 129 | |
| 130 | bool ChromeRLZTrackerDelegate::IsBrandOrganic(const std::string& brand) { |
Joshua Pawlicki | bc5533ae | 2019-03-25 16:32:43 | [diff] [blame] | 131 | return google_brand::IsOrganic(brand); |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 132 | } |
| 133 | |
| 134 | bool ChromeRLZTrackerDelegate::GetReactivationBrand(std::string* brand) { |
| 135 | return google_brand::GetReactivationBrand(brand); |
| 136 | } |
| 137 | |
| 138 | bool ChromeRLZTrackerDelegate::ShouldEnableZeroDelayForTesting() { |
| 139 | return base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 140 | ::switches::kTestType); |
| 141 | } |
| 142 | |
| 143 | bool ChromeRLZTrackerDelegate::GetLanguage(base::string16* language) { |
| 144 | #if defined(OS_WIN) |
| 145 | return GoogleUpdateSettings::GetLanguage(language); |
| 146 | #else |
xdai | ae4bf62a | 2016-04-06 18:15:59 | [diff] [blame] | 147 | // On other systems, we don't know the install language of promotions. That's |
| 148 | // OK, for now all promotions on non-Windows systems will be reported as "en". |
| 149 | // If non-Windows promotions end up requiring language code reporting, that |
| 150 | // code will need to go here. |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 151 | return false; |
| 152 | #endif |
| 153 | } |
| 154 | |
| 155 | bool ChromeRLZTrackerDelegate::GetReferral(base::string16* referral) { |
| 156 | #if defined(OS_WIN) |
| 157 | return GoogleUpdateSettings::GetReferral(referral); |
| 158 | #else |
| 159 | // The referral program is defunct and not used. No need to implement this |
| 160 | // function on non-Win platforms. |
| 161 | return true; |
| 162 | #endif |
| 163 | } |
| 164 | |
| 165 | bool ChromeRLZTrackerDelegate::ClearReferral() { |
| 166 | #if defined(OS_WIN) |
| 167 | return GoogleUpdateSettings::ClearReferral(); |
| 168 | #else |
| 169 | // The referral program is defunct and not used. No need to implement this |
| 170 | // function on non-Win platforms. |
| 171 | return true; |
| 172 | #endif |
| 173 | } |
| 174 | |
| 175 | void ChromeRLZTrackerDelegate::SetOmniboxSearchCallback( |
Ayu Ishii | ebdc85f | 2020-02-07 17:50:43 | [diff] [blame] | 176 | base::OnceClosure callback) { |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 177 | DCHECK(!callback.is_null()); |
blundell | 8130800 | 2015-08-18 15:06:09 | [diff] [blame] | 178 | omnibox_url_opened_subscription_ = |
| 179 | OmniboxEventGlobalTracker::GetInstance()->RegisterCallback( |
| 180 | base::Bind(&ChromeRLZTrackerDelegate::OnURLOpenedFromOmnibox, |
| 181 | base::Unretained(this))); |
Ayu Ishii | ebdc85f | 2020-02-07 17:50:43 | [diff] [blame] | 182 | on_omnibox_search_callback_ = std::move(callback); |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 183 | } |
| 184 | |
| 185 | void ChromeRLZTrackerDelegate::SetHomepageSearchCallback( |
Ayu Ishii | ebdc85f | 2020-02-07 17:50:43 | [diff] [blame] | 186 | base::OnceClosure callback) { |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 187 | DCHECK(!callback.is_null()); |
| 188 | registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 189 | content::NotificationService::AllSources()); |
Ayu Ishii | ebdc85f | 2020-02-07 17:50:43 | [diff] [blame] | 190 | on_homepage_search_callback_ = std::move(callback); |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 191 | } |
| 192 | |
Jérôme Lebel | 0d2a5a8 | 2018-12-06 10:13:37 | [diff] [blame] | 193 | bool ChromeRLZTrackerDelegate::ShouldUpdateExistingAccessPointRlz() { |
| 194 | return true; |
| 195 | } |
| 196 | |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 197 | void ChromeRLZTrackerDelegate::Observe( |
| 198 | int type, |
| 199 | const content::NotificationSource& source, |
| 200 | const content::NotificationDetails& details) { |
Ayu Ishii | ebdc85f | 2020-02-07 17:50:43 | [diff] [blame] | 201 | base::OnceClosure callback_to_run; |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 202 | switch (type) { |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 203 | case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { |
| 204 | // Firstly check if it is a Google search. |
| 205 | content::LoadCommittedDetails* load_details = |
| 206 | content::Details<content::LoadCommittedDetails>(details).ptr(); |
| 207 | if (load_details == nullptr) |
| 208 | break; |
| 209 | |
| 210 | content::NavigationEntry* entry = load_details->entry; |
| 211 | if (entry == nullptr) |
| 212 | break; |
| 213 | |
| 214 | if (google_util::IsGoogleSearchUrl(entry->GetURL())) { |
| 215 | // If it is a Google search, check if it originates from HOMEPAGE by |
| 216 | // getting the previous NavigationEntry. |
| 217 | content::NavigationController* controller = |
| 218 | content::Source<content::NavigationController>(source).ptr(); |
| 219 | if (controller == nullptr) |
| 220 | break; |
| 221 | |
| 222 | int entry_index = controller->GetLastCommittedEntryIndex(); |
| 223 | if (entry_index < 1) |
| 224 | break; |
| 225 | |
Lucas Furukawa Gadani | 5553a15 | 2019-01-08 18:55:57 | [diff] [blame] | 226 | content::NavigationEntry* previous_entry = |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 227 | controller->GetEntryAtIndex(entry_index - 1); |
| 228 | |
| 229 | if (previous_entry == nullptr) |
| 230 | break; |
| 231 | |
| 232 | // Make sure it is a Google web page originated from HOMEPAGE. |
| 233 | if (google_util::IsGoogleHomePageUrl(previous_entry->GetURL()) && |
| 234 | ((previous_entry->GetTransitionType() & |
| 235 | ui::PAGE_TRANSITION_HOME_PAGE) != 0)) { |
| 236 | registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 237 | content::NotificationService::AllSources()); |
Ayu Ishii | ebdc85f | 2020-02-07 17:50:43 | [diff] [blame] | 238 | callback_to_run = std::move(on_homepage_search_callback_); |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 239 | } |
| 240 | } |
| 241 | break; |
| 242 | } |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 243 | |
| 244 | default: |
| 245 | NOTREACHED(); |
| 246 | break; |
| 247 | } |
| 248 | |
| 249 | if (!callback_to_run.is_null()) |
Ayu Ishii | ebdc85f | 2020-02-07 17:50:43 | [diff] [blame] | 250 | std::move(callback_to_run).Run(); |
sdefresne | d967d55 | 2015-07-16 08:34:35 | [diff] [blame] | 251 | } |
blundell | 8130800 | 2015-08-18 15:06:09 | [diff] [blame] | 252 | |
| 253 | void ChromeRLZTrackerDelegate::OnURLOpenedFromOmnibox(OmniboxLog* log) { |
blundell | 8130800 | 2015-08-18 15:06:09 | [diff] [blame] | 254 | |
| 255 | // In M-36, we made NOTIFICATION_OMNIBOX_OPENED_URL fire more often than |
| 256 | // it did previously. The RLZ folks want RLZ's "first search" detection |
| 257 | // to remain as unaffected as possible by this change. This test is |
| 258 | // there to keep the old behavior. |
| 259 | if (!log->is_popup_open) |
| 260 | return; |
| 261 | |
Peter Kasting | 7ba9440c | 2020-11-22 01:49:02 | [diff] [blame] | 262 | omnibox_url_opened_subscription_ = {}; |
Ayu Ishii | ebdc85f | 2020-02-07 17:50:43 | [diff] [blame] | 263 | std::move(on_omnibox_search_callback_).Run(); |
blundell | 8130800 | 2015-08-18 15:06:09 | [diff] [blame] | 264 | } |