| 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 |