OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 |
11 #include <algorithm> | 11 #include <algorithm> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/debug/trace_event.h" | 14 #include "base/debug/trace_event.h" |
15 #include "base/message_loop.h" | 15 #include "base/message_loop.h" |
16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
17 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
18 #include "chrome/browser/browser_process.h" | 18 #include "chrome/browser/browser_process.h" |
19 #include "chrome/browser/google/google_util.h" | 19 #include "chrome/browser/google/google_util.h" |
20 #include "chrome/browser/search_engines/template_url.h" | 20 #include "chrome/browser/search_engines/template_url.h" |
21 #include "chrome/browser/search_engines/template_url_service.h" | 21 #include "chrome/browser/search_engines/template_url_service.h" |
22 #include "chrome/browser/search_engines/template_url_service_factory.h" | 22 #include "chrome/browser/search_engines/template_url_service_factory.h" |
23 #include "chrome/common/chrome_notification_types.h" | 23 #include "chrome/common/chrome_notification_types.h" |
24 #include "content/public/browser/browser_thread.h" | 24 #include "content/public/browser/browser_thread.h" |
25 #include "content/public/browser/navigation_entry.h" | 25 #include "content/public/browser/navigation_entry.h" |
26 #include "content/public/browser/notification_service.h" | 26 #include "content/public/browser/notification_service.h" |
27 #include "net/http/http_util.h" | 27 #include "net/http/http_util.h" |
28 | 28 |
29 #if defined(OS_CHROMEOS) | |
30 #include "base/threading/sequenced_worker_pool.h" | |
31 #endif | |
32 | |
33 #if defined(OS_WIN) | 29 #if defined(OS_WIN) |
34 #include "chrome/installer/util/google_update_settings.h" | 30 #include "chrome/installer/util/google_update_settings.h" |
35 #else | 31 #else |
36 namespace GoogleUpdateSettings { | 32 namespace GoogleUpdateSettings { |
37 static bool GetLanguage(string16* language) { | 33 static bool GetLanguage(string16* language) { |
38 // TODO(thakis): Implement. | 34 // TODO(thakis): Implement. |
39 NOTIMPLEMENTED(); | 35 NOTIMPLEMENTED(); |
40 return false; | 36 return false; |
41 } | 37 } |
42 | 38 |
43 // The referral program is defunct and not used. No need to implement these | 39 // The referral program is defunct and not used. No need to implement these |
44 // functions on non-Win platforms. | 40 // functions on non-Win platforms. |
45 static bool GetReferral(string16* referral) { | 41 static bool GetReferral(string16* referral) { |
46 return true; | 42 return true; |
47 } | 43 } |
48 static bool ClearReferral() { | 44 static bool ClearReferral() { |
49 return true; | 45 return true; |
50 } | 46 } |
51 } // namespace GoogleUpdateSettings | 47 } // namespace GoogleUpdateSettings |
52 #endif | 48 #endif |
53 | 49 |
54 using content::BrowserThread; | 50 using content::BrowserThread; |
55 using content::NavigationEntry; | 51 using content::NavigationEntry; |
56 | 52 |
57 namespace { | 53 namespace { |
58 | 54 |
59 const char kRlzThreadName[] = "RLZ_thread"; | |
60 | |
61 bool IsBrandOrganic(const std::string& brand) { | 55 bool IsBrandOrganic(const std::string& brand) { |
62 return brand.empty() || google_util::IsOrganic(brand); | 56 return brand.empty() || google_util::IsOrganic(brand); |
63 } | 57 } |
64 | 58 |
65 void RecordProductEvents(bool first_run, | 59 void RecordProductEvents(bool first_run, |
66 bool is_google_default_search, | 60 bool is_google_default_search, |
67 bool is_google_homepage, | 61 bool is_google_homepage, |
68 bool is_google_in_startpages, | 62 bool is_google_in_startpages, |
69 bool already_ran, | 63 bool already_ran, |
70 bool omnibox_used, | 64 bool omnibox_used, |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 RLZTracker* RLZTracker::GetInstance() { | 164 RLZTracker* RLZTracker::GetInstance() { |
171 return tracker_ ? tracker_ : Singleton<RLZTracker>::get(); | 165 return tracker_ ? tracker_ : Singleton<RLZTracker>::get(); |
172 } | 166 } |
173 | 167 |
174 RLZTracker::RLZTracker() | 168 RLZTracker::RLZTracker() |
175 : first_run_(false), | 169 : first_run_(false), |
176 send_ping_immediately_(false), | 170 send_ping_immediately_(false), |
177 is_google_default_search_(false), | 171 is_google_default_search_(false), |
178 is_google_homepage_(false), | 172 is_google_homepage_(false), |
179 is_google_in_startpages_(false), | 173 is_google_in_startpages_(false), |
180 rlz_thread_(kRlzThreadName), | |
181 blocking_task_runner_(NULL), | |
182 url_request_context_(NULL), | |
183 already_ran_(false), | 174 already_ran_(false), |
184 omnibox_used_(false), | 175 omnibox_used_(false), |
185 homepage_used_(false) { | 176 homepage_used_(false) { |
186 } | 177 } |
187 | 178 |
188 RLZTracker::~RLZTracker() { | 179 RLZTracker::~RLZTracker() { |
189 } | 180 } |
190 | 181 |
191 // static | 182 // static |
192 bool RLZTracker::InitRlzDelayed(bool first_run, | 183 bool RLZTracker::InitRlzDelayed(bool first_run, |
193 int delay, | 184 int delay, |
194 bool is_google_default_search, | 185 bool is_google_default_search, |
195 bool is_google_homepage, | 186 bool is_google_homepage, |
196 bool is_google_in_startpages) { | 187 bool is_google_in_startpages) { |
197 return GetInstance()->Init(first_run, delay, is_google_default_search, | 188 return GetInstance()->Init(first_run, delay, is_google_default_search, |
198 is_google_homepage, is_google_in_startpages); | 189 is_google_homepage, is_google_in_startpages); |
199 } | 190 } |
200 | 191 |
201 bool RLZTracker::Init(bool first_run, | 192 bool RLZTracker::Init(bool first_run, |
202 int delay, | 193 int delay, |
203 bool is_google_default_search, | 194 bool is_google_default_search, |
204 bool is_google_homepage, | 195 bool is_google_homepage, |
205 bool is_google_in_startpages) { | 196 bool is_google_in_startpages) { |
206 first_run_ = first_run; | 197 first_run_ = first_run; |
207 is_google_default_search_ = is_google_default_search; | 198 is_google_default_search_ = is_google_default_search; |
208 is_google_homepage_ = is_google_homepage; | 199 is_google_homepage_ = is_google_homepage; |
209 is_google_in_startpages_ = is_google_in_startpages; | 200 is_google_in_startpages_ = is_google_in_startpages; |
210 | 201 |
211 if (!InitWorkers()) | |
212 return false; | |
213 | |
214 // A negative delay means that a financial ping should be sent immediately | 202 // A negative delay means that a financial ping should be sent immediately |
215 // after a first search is recorded, without waiting for the next restart | 203 // after a first search is recorded, without waiting for the next restart |
216 // of chrome. However, we only want this behaviour on first run. | 204 // of chrome. However, we only want this behaviour on first run. |
217 send_ping_immediately_ = false; | 205 send_ping_immediately_ = false; |
218 if (delay < 0) { | 206 if (delay < 0) { |
219 send_ping_immediately_ = true; | 207 send_ping_immediately_ = true; |
220 delay = -delay; | 208 delay = -delay; |
221 } | 209 } |
222 | 210 |
223 // Maximum and minimum delay we would allow to be set through master | 211 // Maximum and minimum delay we would allow to be set through master |
(...skipping 15 matching lines...) Expand all Loading... |
239 // typing in the omnibox (which triggers INSTANT_CONTROLLER_UPDATED). | 227 // typing in the omnibox (which triggers INSTANT_CONTROLLER_UPDATED). |
240 registrar_.Add(this, chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED, | 228 registrar_.Add(this, chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED, |
241 content::NotificationService::AllSources()); | 229 content::NotificationService::AllSources()); |
242 | 230 |
243 // Register for notifications from navigations, to see if the user has used | 231 // Register for notifications from navigations, to see if the user has used |
244 // the home page. | 232 // the home page. |
245 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING, | 233 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING, |
246 content::NotificationService::AllSources()); | 234 content::NotificationService::AllSources()); |
247 } | 235 } |
248 | 236 |
249 url_request_context_ = g_browser_process->system_request_context(); | 237 rlz_lib::SetURLRequestContext(g_browser_process->system_request_context()); |
250 ScheduleDelayedInit(delay); | 238 ScheduleDelayedInit(delay); |
251 | 239 |
252 return true; | 240 return true; |
253 } | 241 } |
254 | 242 |
255 void RLZTracker::ScheduleDelayedInit(int delay) { | 243 void RLZTracker::ScheduleDelayedInit(int delay) { |
256 // The RLZTracker is a singleton object that outlives any runnable tasks | 244 // The RLZTracker is a singleton object that outlives any runnable tasks |
257 // that will be queued up. | 245 // that will be queued up. |
258 blocking_task_runner_->PostDelayedTask( | 246 BrowserThread::GetBlockingPool()->PostDelayedTask( |
259 FROM_HERE, | 247 FROM_HERE, |
260 base::Bind(&RLZTracker::DelayedInit, base::Unretained(this)), | 248 base::Bind(&RLZTracker::DelayedInit, base::Unretained(this)), |
261 base::TimeDelta::FromMilliseconds(delay)); | 249 base::TimeDelta::FromMilliseconds(delay)); |
262 } | 250 } |
263 | 251 |
264 bool RLZTracker::InitWorkers() { | |
265 base::Thread::Options options; | |
266 options.message_loop_type = MessageLoop::TYPE_IO; | |
267 if (!rlz_thread_.StartWithOptions(options)) | |
268 return false; | |
269 blocking_task_runner_ = rlz_thread_.message_loop_proxy(); | |
270 | |
271 #if defined(OS_CHROMEOS) | |
272 base::SequencedWorkerPool* worker_pool = | |
273 content::BrowserThread::GetBlockingPool(); | |
274 if (!worker_pool) | |
275 return false; | |
276 rlz_lib::SetIOTaskRunner( | |
277 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( | |
278 worker_pool->GetSequenceToken(), | |
279 base::SequencedWorkerPool::BLOCK_SHUTDOWN)); | |
280 #endif | |
281 return true; | |
282 } | |
283 | |
284 void RLZTracker::DelayedInit() { | 252 void RLZTracker::DelayedInit() { |
285 if (!already_ran_) | 253 worker_pool_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken(); |
286 rlz_lib::SetURLRequestContext(url_request_context_); | |
287 | 254 |
288 bool schedule_ping = false; | 255 bool schedule_ping = false; |
289 | 256 |
290 // For organic brandcodes do not use rlz at all. Empty brandcode usually | 257 // For organic brandcodes do not use rlz at all. Empty brandcode usually |
291 // means a chromium install. This is ok. | 258 // means a chromium install. This is ok. |
292 std::string brand; | 259 std::string brand; |
293 if (google_util::GetBrand(&brand) && !IsBrandOrganic(brand)) { | 260 if (google_util::GetBrand(&brand) && !IsBrandOrganic(brand)) { |
294 RecordProductEvents(first_run_, is_google_default_search_, | 261 RecordProductEvents(first_run_, is_google_default_search_, |
295 is_google_homepage_, is_google_in_startpages_, | 262 is_google_homepage_, is_google_in_startpages_, |
296 already_ran_, omnibox_used_, homepage_used_); | 263 already_ran_, omnibox_used_, homepage_used_); |
(...skipping 12 matching lines...) Expand all Loading... |
309 schedule_ping = true; | 276 schedule_ping = true; |
310 } | 277 } |
311 | 278 |
312 already_ran_ = true; | 279 already_ran_ = true; |
313 | 280 |
314 if (schedule_ping) | 281 if (schedule_ping) |
315 ScheduleFinancialPing(); | 282 ScheduleFinancialPing(); |
316 } | 283 } |
317 | 284 |
318 void RLZTracker::ScheduleFinancialPing() { | 285 void RLZTracker::ScheduleFinancialPing() { |
319 blocking_task_runner_->PostTask( | 286 BrowserThread::GetBlockingPool()->PostSequencedWorkerTask( |
| 287 worker_pool_token_, |
320 FROM_HERE, | 288 FROM_HERE, |
321 base::Bind(&RLZTracker::PingNowImpl, base::Unretained(this))); | 289 base::Bind(&RLZTracker::PingNowImpl, base::Unretained(this))); |
322 } | 290 } |
323 | 291 |
324 void RLZTracker::PingNowImpl() { | 292 void RLZTracker::PingNowImpl() { |
325 TRACE_EVENT0("RLZ", "RLZTracker::PingNowImpl"); | 293 TRACE_EVENT0("RLZ", "RLZTracker::PingNowImpl"); |
326 string16 lang; | 294 string16 lang; |
327 GoogleUpdateSettings::GetLanguage(&lang); | 295 GoogleUpdateSettings::GetLanguage(&lang); |
328 if (lang.empty()) | 296 if (lang.empty()) |
329 lang = ASCIIToUTF16("en"); | 297 lang = ASCIIToUTF16("en"); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 } | 382 } |
415 | 383 |
416 return ret; | 384 return ret; |
417 } | 385 } |
418 | 386 |
419 bool RLZTracker::ScheduleRecordProductEvent(rlz_lib::Product product, | 387 bool RLZTracker::ScheduleRecordProductEvent(rlz_lib::Product product, |
420 rlz_lib::AccessPoint point, | 388 rlz_lib::AccessPoint point, |
421 rlz_lib::Event event_id) { | 389 rlz_lib::Event event_id) { |
422 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) | 390 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) |
423 return false; | 391 return false; |
424 if (!blocking_task_runner_) { | 392 if (!already_ran_) { |
425 LOG(ERROR) << "Attempted recording RLZ event before RLZ init."; | 393 LOG(ERROR) << "Attempted recording RLZ event before RLZ init."; |
426 return true; | 394 return true; |
427 } | 395 } |
428 | 396 |
429 blocking_task_runner_->PostTask( | 397 BrowserThread::GetBlockingPool()->PostSequencedWorkerTask( |
| 398 worker_pool_token_, |
430 FROM_HERE, | 399 FROM_HERE, |
431 base::Bind(base::IgnoreResult(&RLZTracker::RecordProductEvent), | 400 base::Bind(base::IgnoreResult(&RLZTracker::RecordProductEvent), |
432 product, point, event_id)); | 401 product, point, event_id)); |
433 | 402 |
434 return true; | 403 return true; |
435 } | 404 } |
436 | 405 |
437 void RLZTracker::RecordFirstSearch(rlz_lib::AccessPoint point) { | 406 void RLZTracker::RecordFirstSearch(rlz_lib::AccessPoint point) { |
438 // Make sure we don't access disk outside of the I/O thread. | 407 // Make sure we don't access disk outside of the I/O thread. |
439 // In such case we repost the task on the right thread and return error. | 408 // In such case we repost the task on the right thread and return error. |
440 if (ScheduleRecordFirstSearch(point)) | 409 if (ScheduleRecordFirstSearch(point)) |
441 return; | 410 return; |
442 | 411 |
443 bool* record_used = point == CHROME_OMNIBOX ? | 412 bool* record_used = point == CHROME_OMNIBOX ? |
444 &omnibox_used_ : &homepage_used_; | 413 &omnibox_used_ : &homepage_used_; |
445 | 414 |
446 // Try to record event now, else set the flag to try later when we | 415 // Try to record event now, else set the flag to try later when we |
447 // attempt the ping. | 416 // attempt the ping. |
448 if (!RecordProductEvent(rlz_lib::CHROME, point, rlz_lib::FIRST_SEARCH)) | 417 if (!RecordProductEvent(rlz_lib::CHROME, point, rlz_lib::FIRST_SEARCH)) |
449 *record_used = true; | 418 *record_used = true; |
450 else if (send_ping_immediately_ && point == CHROME_OMNIBOX) | 419 else if (send_ping_immediately_ && point == CHROME_OMNIBOX) |
451 ScheduleDelayedInit(0); | 420 ScheduleDelayedInit(0); |
452 } | 421 } |
453 | 422 |
454 bool RLZTracker::ScheduleRecordFirstSearch(rlz_lib::AccessPoint point) { | 423 bool RLZTracker::ScheduleRecordFirstSearch(rlz_lib::AccessPoint point) { |
455 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) | 424 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) |
456 return false; | 425 return false; |
457 blocking_task_runner_->PostTask( | 426 BrowserThread::GetBlockingPool()->PostSequencedWorkerTask( |
| 427 worker_pool_token_, |
458 FROM_HERE, | 428 FROM_HERE, |
459 base::Bind(&RLZTracker::RecordFirstSearch, | 429 base::Bind(&RLZTracker::RecordFirstSearch, |
460 base::Unretained(this), point)); | 430 base::Unretained(this), point)); |
461 return true; | 431 return true; |
462 } | 432 } |
463 | 433 |
464 // static | 434 // static |
465 std::string RLZTracker::GetAccessPointHttpHeader(rlz_lib::AccessPoint point) { | 435 std::string RLZTracker::GetAccessPointHttpHeader(rlz_lib::AccessPoint point) { |
466 TRACE_EVENT0("RLZ", "RLZTracker::GetAccessPointHttpHeader"); | 436 TRACE_EVENT0("RLZ", "RLZTracker::GetAccessPointHttpHeader"); |
467 std::string extra_headers; | 437 std::string extra_headers; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 base::AutoLock lock(cache_lock_); | 485 base::AutoLock lock(cache_lock_); |
516 rlz_cache_[point] = rlz_local; | 486 rlz_cache_[point] = rlz_local; |
517 return true; | 487 return true; |
518 } | 488 } |
519 | 489 |
520 bool RLZTracker::ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point) { | 490 bool RLZTracker::ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point) { |
521 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) | 491 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) |
522 return false; | 492 return false; |
523 | 493 |
524 string16* not_used = NULL; | 494 string16* not_used = NULL; |
525 blocking_task_runner_->PostTask( | 495 BrowserThread::GetBlockingPool()->PostSequencedWorkerTask( |
| 496 worker_pool_token_, |
526 FROM_HERE, | 497 FROM_HERE, |
527 base::Bind(base::IgnoreResult(&RLZTracker::GetAccessPointRlz), point, | 498 base::Bind(base::IgnoreResult(&RLZTracker::GetAccessPointRlz), point, |
528 not_used)); | 499 not_used)); |
529 return true; | 500 return true; |
530 } | 501 } |
531 | 502 |
532 // static | 503 // static |
533 void RLZTracker::CleanupRlz() { | 504 void RLZTracker::CleanupRlz() { |
534 GetInstance()->rlz_cache_.clear(); | 505 GetInstance()->rlz_cache_.clear(); |
535 GetInstance()->registrar_.RemoveAll(); | 506 GetInstance()->registrar_.RemoveAll(); |
536 } | 507 } |
OLD | NEW |