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

Side by Side Diff: chrome/browser/rlz/rlz.cc

Issue 7736001: Adding unit tests to RLZ code. Refactoring RLZ code to make it more testable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Removing all references to headless envvar Created 9 years, 3 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/rlz/rlz.h ('k') | chrome/browser/rlz/rlz_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This code glues the RLZ library DLL with Chrome. It allows Chrome to work 5 // This code glues the RLZ library DLL with Chrome. It allows Chrome to work
6 // with or without the DLL being present. If the DLL is not present the 6 // with or without the DLL being present. If the DLL is not present the
7 // functions do nothing and just return false. 7 // functions do nothing and just return false.
8 8
9 #include "chrome/browser/rlz/rlz.h" 9 #include "chrome/browser/rlz/rlz.h"
10 10
(...skipping 13 matching lines...) Expand all
24 #include "base/utf_string_conversions.h" 24 #include "base/utf_string_conversions.h"
25 #include "chrome/browser/browser_process.h" 25 #include "chrome/browser/browser_process.h"
26 #include "chrome/browser/search_engines/template_url.h" 26 #include "chrome/browser/search_engines/template_url.h"
27 #include "chrome/browser/search_engines/template_url_service.h" 27 #include "chrome/browser/search_engines/template_url_service.h"
28 #include "chrome/browser/search_engines/template_url_service_factory.h" 28 #include "chrome/browser/search_engines/template_url_service_factory.h"
29 #include "chrome/common/chrome_notification_types.h" 29 #include "chrome/common/chrome_notification_types.h"
30 #include "chrome/common/chrome_paths.h" 30 #include "chrome/common/chrome_paths.h"
31 #include "chrome/common/env_vars.h" 31 #include "chrome/common/env_vars.h"
32 #include "chrome/installer/util/google_update_settings.h" 32 #include "chrome/installer/util/google_update_settings.h"
33 #include "content/browser/browser_thread.h" 33 #include "content/browser/browser_thread.h"
34 #include "content/common/notification_registrar.h" 34 #include "content/browser/tab_contents/navigation_entry.h"
35 #include "content/common/notification_service.h" 35 #include "content/common/notification_service.h"
36 36
37 namespace { 37 namespace {
38 38
39 enum { 39 // Organic brands all start with GG, such as GGCM.
40 ACCESS_VALUES_STALE, // Possibly new values available. 40 static bool is_organic(const std::wstring& brand) {
41 ACCESS_VALUES_FRESH // The cached values are current. 41 return (brand.size() < 2) ? false : (brand.substr(0, 2) == L"GG");
42 }; 42 }
43 43
44 // Tracks if we have tried and succeeded sending the ping. This helps us 44 void RecordProductEvents(bool first_run, bool google_default_search,
45 // decide if we need to refresh the cached RLZ string. 45 bool google_default_homepage, bool already_ran,
46 volatile int access_values_state = ACCESS_VALUES_STALE; 46 bool omnibox_used, bool homepage_used) {
47 base::Lock rlz_lock; 47 // Record the installation of chrome. We call this all the time but the rlz
48 // lib should ingore all but the first one.
49 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
50 rlz_lib::CHROME_OMNIBOX,
51 rlz_lib::INSTALL);
52 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
53 rlz_lib::CHROME_HOME_PAGE,
54 rlz_lib::INSTALL);
48 55
49 bool SendFinancialPing(const std::wstring& brand, const std::wstring& lang, 56 if (!already_ran) {
50 const std::wstring& referral, bool exclude_id) { 57 // Do the initial event recording if is the first run or if we have an
58 // empty rlz which means we haven't got a chance to do it.
59 char omnibox_rlz[rlz_lib::kMaxRlzLength + 1];
60 if (!rlz_lib::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, omnibox_rlz,
61 rlz_lib::kMaxRlzLength, NULL)) {
62 omnibox_rlz[0] = 0;
63 }
64
65 // Record if google is the initial search provider and/or home page.
66 if ((first_run || omnibox_rlz[0] == 0) && google_default_search) {
67 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
68 rlz_lib::CHROME_OMNIBOX,
69 rlz_lib::SET_TO_GOOGLE);
70 }
71
72 char homepage_rlz[rlz_lib::kMaxRlzLength + 1];
73 if (!rlz_lib::GetAccessPointRlz(rlz_lib::CHROME_HOME_PAGE, homepage_rlz,
74 rlz_lib::kMaxRlzLength, NULL)) {
75 homepage_rlz[0] = 0;
76 }
77
78 if ((first_run || homepage_rlz[0] == 0) && google_default_homepage) {
79 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
80 rlz_lib::CHROME_HOME_PAGE,
81 rlz_lib::SET_TO_GOOGLE);
82 }
83 }
84
85 // Record first user interaction with the omnibox. We call this all the
86 // time but the rlz lib should ingore all but the first one.
87 if (omnibox_used) {
88 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
89 rlz_lib::CHROME_OMNIBOX,
90 rlz_lib::FIRST_SEARCH);
91 }
92
93 // Record first user interaction with the home page. We call this all the
94 // time but the rlz lib should ingore all but the first one.
95 if (homepage_used) {
96 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
97 rlz_lib::CHROME_HOME_PAGE,
98 rlz_lib::FIRST_SEARCH);
99 }
100 }
101
102 bool SendFinancialPing(const std::wstring& brand,
103 const std::wstring& lang,
104 const std::wstring& referral,
105 bool exclude_id) {
51 rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX, 106 rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX,
52 rlz_lib::CHROME_HOME_PAGE, 107 rlz_lib::CHROME_HOME_PAGE,
53 rlz_lib::NO_ACCESS_POINT}; 108 rlz_lib::NO_ACCESS_POINT};
54 std::string brand_ascii(WideToASCII(brand)); 109 std::string brand_ascii(WideToASCII(brand));
55 std::string lang_ascii(WideToASCII(lang)); 110 std::string lang_ascii(WideToASCII(lang));
56 std::string referral_ascii(WideToASCII(referral)); 111 std::string referral_ascii(WideToASCII(referral));
57 112
58 // If chrome has been reactivated, send a ping for this brand as well. 113 // If chrome has been reactivated, send a ping for this brand as well.
59 // We ignore the return value of SendFinancialPing() since we'll try again 114 // We ignore the return value of SendFinancialPing() since we'll try again
60 // later anyway. Callers of this function are only interested in whether 115 // later anyway. Callers of this function are only interested in whether
61 // the ping for the main brand succeeded or not. 116 // the ping for the main brand succeeded or not.
62 std::wstring reactivation_brand; 117 std::wstring reactivation_brand;
63 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) { 118 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) {
64 std::string reactivation_brand_ascii(WideToASCII(reactivation_brand)); 119 std::string reactivation_brand_ascii(WideToASCII(reactivation_brand));
65 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); 120 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str());
66 rlz_lib::SendFinancialPing(rlz_lib::CHROME, points, "chrome", 121 rlz_lib::SendFinancialPing(rlz_lib::CHROME, points, "chrome",
67 reactivation_brand_ascii.c_str(), 122 reactivation_brand_ascii.c_str(),
68 referral_ascii.c_str(), lang_ascii.c_str(), 123 referral_ascii.c_str(), lang_ascii.c_str(),
69 exclude_id, NULL, true); 124 exclude_id, NULL, true);
70 } 125 }
71 126
72 return rlz_lib::SendFinancialPing(rlz_lib::CHROME, points, "chrome", 127 return rlz_lib::SendFinancialPing(rlz_lib::CHROME, points, "chrome",
73 brand_ascii.c_str(), referral_ascii.c_str(), 128 brand_ascii.c_str(), referral_ascii.c_str(),
74 lang_ascii.c_str(), exclude_id, NULL, true); 129 lang_ascii.c_str(), exclude_id, NULL, true);
75 } 130 }
76 131
77 // This class leverages the AutocompleteEditModel notification to know when
78 // the user first interacted with the omnibox and set a global accordingly.
79 class OmniBoxUsageObserver : public NotificationObserver {
80 public:
81 OmniBoxUsageObserver(bool first_run, bool send_ping_immediately,
82 bool google_default_search)
83 : first_run_(first_run),
84 send_ping_immediately_(send_ping_immediately),
85 google_default_search_(google_default_search) {
86 registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
87 NotificationService::AllSources());
88 // If instant is enabled we'll start searching as soon as the user starts
89 // typing in the omnibox (which triggers INSTANT_CONTROLLER_UPDATED).
90 registrar_.Add(this, chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
91 NotificationService::AllSources());
92 omnibox_used_ = false;
93 DCHECK(!instance_);
94 instance_ = this;
95 }
96
97 virtual void Observe(int type,
98 const NotificationSource& source,
99 const NotificationDetails& details);
100
101 static bool used() {
102 return omnibox_used_;
103 }
104
105 // Deletes the single instance of OmniBoxUsageObserver.
106 static void DeleteInstance() {
107 delete instance_;
108 }
109
110 private:
111 // Dtor is private so the object cannot be created on the stack.
112 ~OmniBoxUsageObserver() {
113 instance_ = NULL;
114 }
115
116 static bool omnibox_used_;
117
118 // There should only be one instance created at a time, and instance_ points
119 // to that instance.
120 // NOTE: this is only non-null for the amount of time it is needed. Once the
121 // instance_ is no longer needed (or Chrome is exiting), this is null.
122 static OmniBoxUsageObserver* instance_;
123
124 NotificationRegistrar registrar_;
125 bool first_run_;
126 bool send_ping_immediately_;
127 bool google_default_search_;
128 };
129
130 bool OmniBoxUsageObserver::omnibox_used_ = false;
131 OmniBoxUsageObserver* OmniBoxUsageObserver::instance_ = NULL;
132
133 // This task is run in the file thread, so to not block it for a long time
134 // we use a throwaway thread to do the blocking url request.
135 class DailyPingTask : public Task {
136 public:
137 virtual ~DailyPingTask() {
138 }
139 virtual void Run() {
140 // We use a transient thread because we have no guarantees about
141 // how long the RLZ lib can block us.
142 _beginthread(PingNow, 0, NULL);
143 }
144
145 private:
146 // Causes a ping to the server using WinInet.
147 static void _cdecl PingNow(void*) {
148 // Needs to be evaluated. See http://crbug.com/62328.
149 base::ThreadRestrictions::ScopedAllowIO allow_io;
150
151 std::wstring lang;
152 GoogleUpdateSettings::GetLanguage(&lang);
153 if (lang.empty())
154 lang = L"en";
155 std::wstring brand;
156 GoogleUpdateSettings::GetBrand(&brand);
157 std::wstring referral;
158 GoogleUpdateSettings::GetReferral(&referral);
159 if (SendFinancialPing(brand, lang, referral, is_organic(brand))) {
160 base::AutoLock lock(rlz_lock);
161 access_values_state = ACCESS_VALUES_STALE;
162 GoogleUpdateSettings::ClearReferral();
163 }
164 }
165
166 // Organic brands all start with GG, such as GGCM.
167 static bool is_organic(const std::wstring& brand) {
168 return (brand.size() < 2) ? false : (brand.substr(0, 2) == L"GG");
169 }
170 };
171
172 // Performs late RLZ initialization and RLZ event recording for chrome.
173 // This task needs to run on the UI thread.
174 class DelayedInitTask : public Task {
175 public:
176 DelayedInitTask(bool first_run, bool google_default_search)
177 : first_run_(first_run),
178 google_default_search_(google_default_search) {
179 }
180 virtual ~DelayedInitTask() {
181 }
182 virtual void Run() {
183 // For non-interactive tests we don't do the rest of the initialization
184 // because sometimes the very act of loading the dll causes QEMU to crash.
185 if (::GetEnvironmentVariableW(ASCIIToWide(env_vars::kHeadless).c_str(),
186 NULL, 0)) {
187 return;
188 }
189 // For organic brandcodes do not use rlz at all. Empty brandcode usually
190 // means a chromium install. This is ok.
191 std::wstring brand;
192 if (!GoogleUpdateSettings::GetBrand(&brand) || brand.empty() ||
193 GoogleUpdateSettings::IsOrganic(brand))
194 return;
195
196 RecordProductEvents(first_run_, google_default_search_, already_ran_);
197
198 // If chrome has been reactivated, record the events for this brand
199 // as well.
200 std::wstring reactivation_brand;
201 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) {
202 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str());
203 RecordProductEvents(first_run_, google_default_search_, already_ran_);
204 }
205
206 already_ran_ = true;
207
208 // Schedule the daily RLZ ping.
209 MessageLoop::current()->PostTask(FROM_HERE, new DailyPingTask());
210 }
211
212 private:
213 static void RecordProductEvents(bool first_run, bool google_default_search,
214 bool already_ran) {
215 // Record the installation of chrome. We call this all the time but the rlz
216 // lib should ingore all but the first one.
217 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
218 rlz_lib::CHROME_OMNIBOX,
219 rlz_lib::INSTALL);
220 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
221 rlz_lib::CHROME_HOME_PAGE,
222 rlz_lib::INSTALL);
223
224 // Do the initial event recording if is the first run or if we have an
225 // empty rlz which means we haven't got a chance to do it.
226 char omnibox_rlz[rlz_lib::kMaxRlzLength + 1];
227 if (!rlz_lib::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, omnibox_rlz,
228 rlz_lib::kMaxRlzLength, NULL)) {
229 omnibox_rlz[0] = 0;
230 }
231
232 // Record if google is the initial search provider.
233 if ((first_run || omnibox_rlz[0] == 0) && google_default_search &&
234 !already_ran) {
235 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
236 rlz_lib::CHROME_OMNIBOX,
237 rlz_lib::SET_TO_GOOGLE);
238 }
239
240 // Record first user interaction with the omnibox. We call this all the
241 // time but the rlz lib should ingore all but the first one.
242 if (OmniBoxUsageObserver::used()) {
243 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
244 rlz_lib::CHROME_OMNIBOX,
245 rlz_lib::FIRST_SEARCH);
246 }
247 }
248
249 // Flag that remembers if the delayed task already ran or not. This is
250 // needed only in the first_run case, since we don't want to record the
251 // set-to-google event more than once. We need to worry about this event
252 // (and not the others) because it is not a stateful RLZ event.
253 static bool already_ran_;
254
255 bool first_run_;
256
257 // True if Google is the default search engine for the first profile starting
258 // in a browser during first run.
259 bool google_default_search_;
260
261 };
262
263 bool DelayedInitTask::already_ran_ = false;
264
265 void OmniBoxUsageObserver::Observe(int type,
266 const NotificationSource& source,
267 const NotificationDetails& details) {
268 // Needs to be evaluated. See http://crbug.com/62328.
269 base::ThreadRestrictions::ScopedAllowIO allow_io;
270
271 // Try to record event now, else set the flag to try later when we
272 // attempt the ping.
273 if (!RLZTracker::RecordProductEvent(rlz_lib::CHROME,
274 rlz_lib::CHROME_OMNIBOX,
275 rlz_lib::FIRST_SEARCH))
276 omnibox_used_ = true;
277 else if (send_ping_immediately_) {
278 BrowserThread::PostTask(
279 BrowserThread::FILE, FROM_HERE, new DelayedInitTask(first_run_,
280 google_default_search_));
281 }
282
283 delete this;
284 }
285
286 } // namespace 132 } // namespace
287 133
134 RLZTracker* RLZTracker::tracker_ = NULL;
135
136 // static
137 RLZTracker* RLZTracker::GetInstance() {
138 return tracker_ ? tracker_ : Singleton<RLZTracker>::get();
139 }
140
141 RLZTracker::RLZTracker()
142 : first_run_(false),
143 send_ping_immediately_(false),
144 google_default_search_(false),
145 already_ran_(false),
146 omnibox_used_(false),
147 homepage_used_(false) {
148 }
149
150 RLZTracker::~RLZTracker() {
151 }
152
288 bool RLZTracker::InitRlzDelayed(bool first_run, int delay, 153 bool RLZTracker::InitRlzDelayed(bool first_run, int delay,
289 bool google_default_search) { 154 bool google_default_search,
155 bool google_default_homepage) {
156 return GetInstance()->Init(first_run, delay, google_default_search,
157 google_default_homepage);
158 }
159
160 bool RLZTracker::Init(bool first_run, int delay, bool google_default_search,
161 bool google_default_homepage) {
162 first_run_ = first_run;
163 google_default_search_ = google_default_search;
164 google_default_homepage_ = google_default_homepage;
165
290 // A negative delay means that a financial ping should be sent immediately 166 // A negative delay means that a financial ping should be sent immediately
291 // after a first search is recorded, without waiting for the next restart 167 // after a first search is recorded, without waiting for the next restart
292 // of chrome. However, we only want this behaviour on first run. 168 // of chrome. However, we only want this behaviour on first run.
293 bool send_ping_immediately = false; 169 send_ping_immediately_ = false;
294 if (delay < 0) { 170 if (delay < 0) {
295 send_ping_immediately = true; 171 send_ping_immediately_ = true;
296 delay = -delay; 172 delay = -delay;
297 } 173 }
298 174
299 // Maximum and minimum delay we would allow to be set through master 175 // Maximum and minimum delay we would allow to be set through master
300 // preferences. Somewhat arbitrary, may need to be adjusted in future. 176 // preferences. Somewhat arbitrary, may need to be adjusted in future.
301 const int kMaxDelay = 200 * 1000; 177 const int kMaxDelay = 200 * 1000;
302 const int kMinDelay = 20 * 1000; 178 const int kMinDelay = 20 * 1000;
303 179
304 delay *= 1000; 180 delay *= 1000;
305 delay = (delay < kMinDelay) ? kMinDelay : delay; 181 delay = (delay < kMinDelay) ? kMinDelay : delay;
306 delay = (delay > kMaxDelay) ? kMaxDelay : delay; 182 delay = (delay > kMaxDelay) ? kMaxDelay : delay;
307 183
308 if (!OmniBoxUsageObserver::used()) 184 // Register for notifications from the omnibox so that we can record when
309 new OmniBoxUsageObserver(first_run, send_ping_immediately, 185 // the user performs a first search.
310 google_default_search); 186 registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
187 NotificationService::AllSources());
188 // If instant is enabled we'll start searching as soon as the user starts
189 // typing in the omnibox (which triggers INSTANT_CONTROLLER_UPDATED).
190 registrar_.Add(this, chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
191 NotificationService::AllSources());
311 192
312 // Schedule the delayed init items. 193 // Register for notifications from navigations, to see if the user has used
194 // the home page.
195 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
196 NotificationService::AllSources());
197
198 ScheduleDelayedInit(delay);
199 return true;
200 }
201
202 void RLZTracker::ScheduleDelayedInit(int delay) {
313 BrowserThread::PostDelayedTask( 203 BrowserThread::PostDelayedTask(
314 BrowserThread::FILE, 204 BrowserThread::FILE,
315 FROM_HERE, 205 FROM_HERE,
316 new DelayedInitTask(first_run, google_default_search), 206 NewRunnableMethod(this, &RLZTracker::DelayedInit),
317 delay); 207 delay);
318 return true; 208 }
209
210 void RLZTracker::DelayedInit() {
211 // For organic brandcodes do not use rlz at all. Empty brandcode usually
212 // means a chromium install. This is ok.
213 std::wstring brand;
214 if (!GoogleUpdateSettings::GetBrand(&brand) || brand.empty() ||
215 GoogleUpdateSettings::IsOrganic(brand))
216 return;
217
218 RecordProductEvents(first_run_, google_default_search_,
219 google_default_homepage_, already_ran_,
220 omnibox_used_, homepage_used_);
221
222 // If chrome has been reactivated, record the events for this brand
223 // as well.
224 std::wstring reactivation_brand;
225 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) {
226 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str());
227 RecordProductEvents(first_run_, google_default_search_,
228 google_default_homepage_, already_ran_,
229 omnibox_used_, homepage_used_);
230 }
231
232 already_ran_ = true;
233
234 ScheduleFinancialPing();
235 }
236
237 void RLZTracker::ScheduleFinancialPing() {
238 _beginthread(PingNow, 0, this);
239 }
240
241 // static
242 void _cdecl RLZTracker::PingNow(void* arg) {
243 RLZTracker* tracker = reinterpret_cast<RLZTracker*>(arg);
244 tracker->PingNowImpl();
245 }
246
247 void RLZTracker::PingNowImpl() {
248 // Needs to be evaluated. See http://crbug.com/62328.
249 base::ThreadRestrictions::ScopedAllowIO allow_io;
250
251 std::wstring lang;
252 GoogleUpdateSettings::GetLanguage(&lang);
253 if (lang.empty())
254 lang = L"en";
255 std::wstring brand;
256 GoogleUpdateSettings::GetBrand(&brand);
257 std::wstring referral;
258 GoogleUpdateSettings::GetReferral(&referral);
259 if (SendFinancialPing(brand, lang, referral, is_organic(brand))) {
260 GoogleUpdateSettings::ClearReferral();
261 base::AutoLock lock(cache_lock_);
262 rlz_cache_.clear();
263 }
264 }
265
266 bool RLZTracker::SendFinancialPing(const std::wstring& brand,
267 const std::wstring& lang,
268 const std::wstring& referral,
269 bool exclude_id) {
270 return ::SendFinancialPing(brand, lang, referral, exclude_id);
271 }
272
273 void RLZTracker::Observe(int type,
274 const NotificationSource& source,
275 const NotificationDetails& details) {
276 // Needs to be evaluated. See http://crbug.com/62328.
277 base::ThreadRestrictions::ScopedAllowIO allow_io;
278
279 rlz_lib::AccessPoint point;
280 bool* record_used = NULL;
281 bool call_record = false;
282
283 switch (type) {
284 case chrome::NOTIFICATION_OMNIBOX_OPENED_URL:
285 case chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED:
286 point = rlz_lib::CHROME_OMNIBOX;
287 record_used = &omnibox_used_;
288 call_record = true;
289
290 registrar_.Remove(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
291 NotificationService::AllSources());
292 registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
293 NotificationService::AllSources());
294 break;
295 case content::NOTIFICATION_NAV_ENTRY_PENDING: {
296 const NavigationEntry* entry = Details<NavigationEntry>(details).ptr();
297 if (entry != NULL &&
298 ((entry->transition_type() & RLZ_PAGETRANSITION_HOME_PAGE) != 0)) {
299 point = rlz_lib::CHROME_HOME_PAGE;
300 record_used = &homepage_used_;
301 call_record = true;
302
303 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
304 NotificationService::AllSources());
305 }
306 break;
307 }
308 default:
309 NOTREACHED();
310 break;
311 }
312
313 if (call_record) {
314 // Try to record event now, else set the flag to try later when we
315 // attempt the ping.
316 if (!RecordProductEvent(rlz_lib::CHROME, point, rlz_lib::FIRST_SEARCH))
317 *record_used = true;
318 else if (send_ping_immediately_ && point == rlz_lib::CHROME_OMNIBOX) {
319 ScheduleDelayedInit(0);
320 }
321 }
319 } 322 }
320 323
321 bool RLZTracker::RecordProductEvent(rlz_lib::Product product, 324 bool RLZTracker::RecordProductEvent(rlz_lib::Product product,
322 rlz_lib::AccessPoint point, 325 rlz_lib::AccessPoint point,
323 rlz_lib::Event event_id) { 326 rlz_lib::Event event_id) {
324 bool ret = rlz_lib::RecordProductEvent(product, point, event_id); 327 bool ret = rlz_lib::RecordProductEvent(product, point, event_id);
325 328
326 // If chrome has been reactivated, record the event for this brand as well. 329 // If chrome has been reactivated, record the event for this brand as well.
327 std::wstring reactivation_brand; 330 std::wstring reactivation_brand;
328 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) { 331 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) {
329 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); 332 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str());
330 ret &= rlz_lib::RecordProductEvent(product, point, event_id); 333 ret &= rlz_lib::RecordProductEvent(product, point, event_id);
331 } 334 }
332 335
333 return ret; 336 return ret;
334 } 337 }
335 338
336 // We implement caching of the answer of get_access_point() if the request 339 // GetAccessPointRlz() caches RLZ strings for all access points. If we had
337 // is for CHROME_OMNIBOX. If we had a successful ping, then we update the 340 // a successful ping, then we update the cached value.
338 // cached value.
339
340 bool RLZTracker::GetAccessPointRlz(rlz_lib::AccessPoint point, 341 bool RLZTracker::GetAccessPointRlz(rlz_lib::AccessPoint point,
341 std::wstring* rlz) { 342 std::wstring* rlz) {
342 static std::wstring cached_ommibox_rlz; 343 return GetInstance()->GetAccessPointRlzImpl(point, rlz);
343 if (rlz_lib::CHROME_OMNIBOX == point) { 344 }
344 base::AutoLock lock(rlz_lock); 345
345 if (access_values_state == ACCESS_VALUES_FRESH) { 346 // GetAccessPointRlz() caches RLZ strings for all access points. If we had
346 *rlz = cached_ommibox_rlz; 347 // a successful ping, then we update the cached value.
348 bool RLZTracker::GetAccessPointRlzImpl(rlz_lib::AccessPoint point,
349 std::wstring* rlz) {
350 // If the RLZ string for the specified access point is already cached,
351 // simply return its value.
352 {
353 base::AutoLock lock(cache_lock_);
354 if (rlz_cache_.find(point) != rlz_cache_.end()) {
355 if (rlz)
356 *rlz = rlz_cache_[point];
347 return true; 357 return true;
348 } 358 }
349 } 359 }
350 360
351 // Make sure we don't access disk outside of the file context. 361 // Make sure we don't access disk outside of the I/O thread.
352 // In such case we repost the task on the right thread and return error. 362 // In such case we repost the task on the right thread and return error.
353 if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { 363 if (ScheduleGetAccessPointRlz(point))
354 // Caching of access points is now only implemented for the CHROME_OMNIBOX. 364 return false;
355 // Thus it is not possible to call this function on another thread for
356 // other access points until proper caching for these has been implemented
357 // and the code that calls this function can handle synchronous fetching
358 // of the access point.
359 DCHECK_EQ(rlz_lib::CHROME_OMNIBOX, point);
360
361 BrowserThread::PostTask(
362 BrowserThread::FILE, FROM_HERE,
363 NewRunnableFunction(&RLZTracker::GetAccessPointRlz,
364 point, &cached_ommibox_rlz));
365 rlz->erase();
366 return false;
367 }
368 365
369 char str_rlz[rlz_lib::kMaxRlzLength + 1]; 366 char str_rlz[rlz_lib::kMaxRlzLength + 1];
370 if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength, NULL)) 367 if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength, NULL))
371 return false; 368 return false;
372 *rlz = ASCIIToWide(std::string(str_rlz)); 369
373 if (rlz_lib::CHROME_OMNIBOX == point) { 370 std::wstring rlz_local(ASCIIToWide(std::string(str_rlz)));
374 base::AutoLock lock(rlz_lock); 371 if (rlz)
375 cached_ommibox_rlz.assign(*rlz); 372 *rlz = rlz_local;
376 access_values_state = ACCESS_VALUES_FRESH; 373
377 } 374 base::AutoLock lock(cache_lock_);
375 rlz_cache_[point] = rlz_local;
376 return true;
377 }
378
379 bool RLZTracker::ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point) {
380 if (BrowserThread::CurrentlyOn(BrowserThread::FILE))
381 return false;
382
383 std::wstring* not_used = NULL;
384 BrowserThread::PostTask(
385 BrowserThread::FILE, FROM_HERE,
386 NewRunnableFunction(&RLZTracker::GetAccessPointRlz, point, not_used));
378 return true; 387 return true;
379 } 388 }
380 389
381 // static 390 // static
382 void RLZTracker::CleanupRlz() { 391 void RLZTracker::CleanupRlz() {
383 OmniBoxUsageObserver::DeleteInstance(); 392 GetInstance()->rlz_cache_.clear();
393 GetInstance()->registrar_.RemoveAll();
384 } 394 }
OLDNEW
« no previous file with comments | « chrome/browser/rlz/rlz.h ('k') | chrome/browser/rlz/rlz_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698