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

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: Uploading any merged files after sync, no new changes 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
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,
311 187 NotificationService::AllSources());
312 // Schedule the delayed init items. 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());
192
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 non-interactive tests we don't do the rest of the initialization
212 // because sometimes the very act of loading the dll causes QEMU to crash.
213 if (::GetEnvironmentVariableW(ASCIIToWide(env_vars::kHeadless).c_str(),
214 NULL, 0)) {
215 return;
216 }
217
218 // For organic brandcodes do not use rlz at all. Empty brandcode usually
219 // means a chromium install. This is ok.
220 std::wstring brand;
221 if (!GoogleUpdateSettings::GetBrand(&brand) || brand.empty() ||
222 GoogleUpdateSettings::IsOrganic(brand))
223 return;
224
225 RecordProductEvents(first_run_, google_default_search_,
226 google_default_homepage_, already_ran_,
227 omnibox_used_, homepage_used_);
228
229 // If chrome has been reactivated, record the events for this brand
230 // as well.
231 std::wstring reactivation_brand;
232 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) {
233 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str());
234 RecordProductEvents(first_run_, google_default_search_,
235 google_default_homepage_, already_ran_,
236 omnibox_used_, homepage_used_);
237 }
238
239 already_ran_ = true;
240
241 ScheduleFinancialPing();
242 }
243
244 void RLZTracker::ScheduleFinancialPing() {
245 _beginthread(PingNow, 0, this);
246 }
247
248 // static
249 void _cdecl RLZTracker::PingNow(void* arg) {
250 RLZTracker* tracker = reinterpret_cast<RLZTracker*>(arg);
251 tracker->PingNowImpl();
252 }
253
254 void RLZTracker::PingNowImpl() {
255 // Needs to be evaluated. See http://crbug.com/62328.
256 base::ThreadRestrictions::ScopedAllowIO allow_io;
257
258 std::wstring lang;
259 GoogleUpdateSettings::GetLanguage(&lang);
260 if (lang.empty())
261 lang = L"en";
262 std::wstring brand;
263 GoogleUpdateSettings::GetBrand(&brand);
264 std::wstring referral;
265 GoogleUpdateSettings::GetReferral(&referral);
266 if (SendFinancialPing(brand, lang, referral, is_organic(brand))) {
267 GoogleUpdateSettings::ClearReferral();
268 base::AutoLock lock(cache_lock_);
269 rlz_cache_.clear();
270 }
271 }
272
273 bool RLZTracker::SendFinancialPing(const std::wstring& brand,
274 const std::wstring& lang,
275 const std::wstring& referral,
276 bool exclude_id) {
277 return ::SendFinancialPing(brand, lang, referral, exclude_id);
278 }
279
280 void RLZTracker::Observe(int type,
281 const NotificationSource& source,
282 const NotificationDetails& details) {
283 // Needs to be evaluated. See http://crbug.com/62328.
284 base::ThreadRestrictions::ScopedAllowIO allow_io;
285
286 rlz_lib::AccessPoint point;
287 bool* record_used = NULL;
288 bool call_record = false;
289
290 switch (type) {
291 case chrome::NOTIFICATION_OMNIBOX_OPENED_URL:
292 case chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED:
293 point = rlz_lib::CHROME_OMNIBOX;
294 record_used = &omnibox_used_;
295 call_record = true;
296
297 registrar_.Remove(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
298 NotificationService::AllSources());
299 registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
300 NotificationService::AllSources());
301 break;
302 case content::NOTIFICATION_NAV_ENTRY_PENDING: {
303 const NavigationEntry* entry = Details<NavigationEntry>(details).ptr();
304 if (entry != NULL &&
305 ((entry->transition_type() & RLZ_PAGETRANSITION_HOME_PAGE) != 0)) {
306 point = rlz_lib::CHROME_HOME_PAGE;
307 record_used = &homepage_used_;
308 call_record = true;
309
310 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
311 NotificationService::AllSources());
312 }
313 break;
314 }
315 default:
316 NOTREACHED();
317 break;
318 }
319
320 if (call_record) {
321 // Try to record event now, else set the flag to try later when we
322 // attempt the ping.
323 if (!RecordProductEvent(rlz_lib::CHROME, point, rlz_lib::FIRST_SEARCH))
324 *record_used = true;
325 else if (send_ping_immediately_ && point == rlz_lib::CHROME_OMNIBOX) {
326 ScheduleDelayedInit(0);
327 }
328 }
319 } 329 }
320 330
321 bool RLZTracker::RecordProductEvent(rlz_lib::Product product, 331 bool RLZTracker::RecordProductEvent(rlz_lib::Product product,
322 rlz_lib::AccessPoint point, 332 rlz_lib::AccessPoint point,
323 rlz_lib::Event event_id) { 333 rlz_lib::Event event_id) {
324 bool ret = rlz_lib::RecordProductEvent(product, point, event_id); 334 bool ret = rlz_lib::RecordProductEvent(product, point, event_id);
325 335
326 // If chrome has been reactivated, record the event for this brand as well. 336 // If chrome has been reactivated, record the event for this brand as well.
327 std::wstring reactivation_brand; 337 std::wstring reactivation_brand;
328 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) { 338 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) {
329 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); 339 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str());
330 ret &= rlz_lib::RecordProductEvent(product, point, event_id); 340 ret &= rlz_lib::RecordProductEvent(product, point, event_id);
331 } 341 }
332 342
333 return ret; 343 return ret;
334 } 344 }
335 345
336 // We implement caching of the answer of get_access_point() if the request 346 // 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 347 // a successful ping, then we update the cached value.
338 // cached value.
339
340 bool RLZTracker::GetAccessPointRlz(rlz_lib::AccessPoint point, 348 bool RLZTracker::GetAccessPointRlz(rlz_lib::AccessPoint point,
341 std::wstring* rlz) { 349 std::wstring* rlz) {
342 static std::wstring cached_ommibox_rlz; 350 return GetInstance()->GetAccessPointRlzImpl(point, rlz);
343 if (rlz_lib::CHROME_OMNIBOX == point) { 351 }
344 base::AutoLock lock(rlz_lock); 352
345 if (access_values_state == ACCESS_VALUES_FRESH) { 353 // GetAccessPointRlz() caches RLZ strings for all access points. If we had
346 *rlz = cached_ommibox_rlz; 354 // a successful ping, then we update the cached value.
355 bool RLZTracker::GetAccessPointRlzImpl(rlz_lib::AccessPoint point,
356 std::wstring* rlz) {
357 // If the RLZ string for the specified access point is already cached,
358 // simply return its value.
359 {
360 base::AutoLock lock(cache_lock_);
361 if (rlz_cache_.find(point) != rlz_cache_.end()) {
362 if (rlz)
363 *rlz = rlz_cache_[point];
347 return true; 364 return true;
348 } 365 }
349 } 366 }
350 367
351 // Make sure we don't access disk outside of the file context. 368 // 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. 369 // In such case we repost the task on the right thread and return error.
353 if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { 370 if (ScheduleGetAccessPointRlz(point))
354 // Caching of access points is now only implemented for the CHROME_OMNIBOX. 371 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 372
369 char str_rlz[rlz_lib::kMaxRlzLength + 1]; 373 char str_rlz[rlz_lib::kMaxRlzLength + 1];
370 if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength, NULL)) 374 if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength, NULL))
371 return false; 375 return false;
372 *rlz = ASCIIToWide(std::string(str_rlz)); 376
373 if (rlz_lib::CHROME_OMNIBOX == point) { 377 std::wstring rlz_local(ASCIIToWide(std::string(str_rlz)));
374 base::AutoLock lock(rlz_lock); 378 if (rlz)
375 cached_ommibox_rlz.assign(*rlz); 379 *rlz = rlz_local;
376 access_values_state = ACCESS_VALUES_FRESH; 380
377 } 381 base::AutoLock lock(cache_lock_);
382 rlz_cache_[point] = rlz_local;
383 return true;
384 }
385
386 bool RLZTracker::ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point) {
387 if (BrowserThread::CurrentlyOn(BrowserThread::FILE))
388 return false;
389
390 std::wstring* not_used = NULL;
391 BrowserThread::PostTask(
392 BrowserThread::FILE, FROM_HERE,
393 NewRunnableFunction(&RLZTracker::GetAccessPointRlz, point, not_used));
378 return true; 394 return true;
379 } 395 }
380 396
381 // static 397 // static
382 void RLZTracker::CleanupRlz() { 398 void RLZTracker::CleanupRlz() {
383 OmniBoxUsageObserver::DeleteInstance(); 399 GetInstance()->rlz_cache_.clear();
400 GetInstance()->registrar_.RemoveAll();
384 } 401 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698