172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This code glues the RLZ library DLL with Chrome. It allows Chrome to work 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// with or without the DLL being present. If the DLL is not present the 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// functions do nothing and just return false. 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/rlz/rlz.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <process.h> 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <windows.h> 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm> 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/path_service.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/synchronization/lock.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/task.h" 223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h" 233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread_restrictions.h" 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h" 2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile_manager.h" 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/search_engines/template_url.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/search_engines/template_url_model.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_paths.h" 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/env_vars.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/installer/util/google_update_settings.h" 33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_registrar.h" 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The maximum length of an access points RLZ in wide chars. 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst DWORD kMaxRlzLength = 64; 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum { 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ACCESS_VALUES_STALE, // Possibly new values available. 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ACCESS_VALUES_FRESH // The cached values are current. 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tracks if we have tried and succeeded sending the ping. This helps us 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// decide if we need to refresh the some cached strings. 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvolatile int access_values_state = ACCESS_VALUES_STALE; 5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbase::Lock rlz_lock; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SendFinancialPing(const std::wstring& brand, const std::wstring& lang, 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::wstring& referral, bool exclude_id) { 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX, 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::CHROME_HOME_PAGE, 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::NO_ACCESS_POINT}; 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string brand_ascii(WideToASCII(brand)); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string lang_ascii(WideToASCII(lang)); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string referral_ascii(WideToASCII(referral)); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rlz_lib::SendFinancialPing(rlz_lib::CHROME, points, "chrome", 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch brand_ascii.c_str(), referral_ascii.c_str(), 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lang_ascii.c_str(), exclude_id, NULL, true); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class leverages the AutocompleteEditModel notification to know when 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the user first interacted with the omnibox and set a global accordingly. 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass OmniBoxUsageObserver : public NotificationObserver { 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OmniBoxUsageObserver(bool first_run, bool send_ping_immediately) 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : first_run_(first_run), 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen send_ping_immediately_(send_ping_immediately) { 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::OMNIBOX_OPENED_URL, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If instant is enabled we'll start searching as soon as the user starts 76731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // typing in the omnibox (which triggers INSTANT_CONTROLLER_UPDATED). 77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick registrar_.Add(this, NotificationType::INSTANT_CONTROLLER_UPDATED, 78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NotificationService::AllSources()); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch omnibox_used_ = false; 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!instance_); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch instance_ = this; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Observe(NotificationType type, 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const NotificationDetails& details); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static bool used() { 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return omnibox_used_; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Deletes the single instance of OmniBoxUsageObserver. 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static void DeleteInstance() { 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete instance_; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Dtor is private so the object cannot be created on the stack. 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~OmniBoxUsageObserver() { 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch instance_ = NULL; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static bool omnibox_used_; 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // There should only be one instance created at a time, and instance_ points 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to that instance. 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: this is only non-null for the amount of time it is needed. Once the 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // instance_ is no longer needed (or Chrome is exiting), this is null. 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static OmniBoxUsageObserver* instance_; 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationRegistrar registrar_; 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool first_run_; 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool send_ping_immediately_; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool OmniBoxUsageObserver::omnibox_used_ = false; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochOmniBoxUsageObserver* OmniBoxUsageObserver::instance_ = NULL; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This task is run in the file thread, so to not block it for a long time 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// we use a throwaway thread to do the blocking url request. 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass DailyPingTask : public Task { 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~DailyPingTask() { 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Run() { 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We use a transient thread because we have no guarantees about 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // how long the RLZ lib can block us. 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _beginthread(PingNow, 0, NULL); 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Causes a ping to the server using WinInet. 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static void _cdecl PingNow(void*) { 1344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Needs to be evaluated. See http://crbug.com/62328. 1354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::ThreadRestrictions::ScopedAllowIO allow_io; 1364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring lang; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GoogleUpdateSettings::GetLanguage(&lang); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (lang.empty()) 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lang = L"en"; 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring brand; 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GoogleUpdateSettings::GetBrand(&brand); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring referral; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GoogleUpdateSettings::GetReferral(&referral); 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (SendFinancialPing(brand, lang, referral, is_organic(brand))) { 14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock lock(rlz_lock); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch access_values_state = ACCESS_VALUES_STALE; 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GoogleUpdateSettings::ClearReferral(); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Organic brands all start with GG, such as GGCM. 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static bool is_organic(const std::wstring& brand) { 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (brand.size() < 2) ? false : (brand.substr(0, 2) == L"GG"); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Performs late RLZ initialization and RLZ event recording for chrome. 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This task needs to run on the UI thread. 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass DelayedInitTask : public Task { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit DelayedInitTask(bool first_run) 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : first_run_(first_run) { 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~DelayedInitTask() { 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Run() { 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For non-interactive tests we don't do the rest of the initialization 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // because sometimes the very act of loading the dll causes QEMU to crash. 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (::GetEnvironmentVariableW(ASCIIToWide(env_vars::kHeadless).c_str(), 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, 0)) { 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For organic brandcodes do not use rlz at all. Empty brandcode usually 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // means a chromium install. This is ok. 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring brand; 1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!GoogleUpdateSettings::GetBrand(&brand) || brand.empty() || 1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GoogleUpdateSettings::IsOrganic(brand)) 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Do the initial event recording if is the first run or if we have an 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // empty rlz which means we haven't got a chance to do it. 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring omnibox_rlz; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &omnibox_rlz); 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if ((first_run_ || omnibox_rlz.empty()) && !already_ran_) { 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen already_ran_ = true; 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Record the installation of chrome. 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RLZTracker::RecordProductEvent(rlz_lib::CHROME, 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::CHROME_OMNIBOX, 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::INSTALL); 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RLZTracker::RecordProductEvent(rlz_lib::CHROME, 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::CHROME_HOME_PAGE, 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::INSTALL); 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Record if google is the initial search provider. 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsGoogleDefaultSearch()) { 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RLZTracker::RecordProductEvent(rlz_lib::CHROME, 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::CHROME_OMNIBOX, 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::SET_TO_GOOGLE); 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Record first user interaction with the omnibox. We call this all the 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // time but the rlz lib should ingore all but the first one. 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (OmniBoxUsageObserver::used()) { 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RLZTracker::RecordProductEvent(rlz_lib::CHROME, 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::CHROME_OMNIBOX, 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::FIRST_SEARCH); 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Schedule the daily RLZ ping. 21172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen MessageLoop::current()->PostTask(FROM_HERE, new DailyPingTask()); 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool IsGoogleDefaultSearch() { 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!g_browser_process) 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath user_data_dir; 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProfileManager* profile_manager = g_browser_process->profile_manager(); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile = profile_manager->GetDefaultProfile(user_data_dir); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!profile) 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TemplateURL* url_template = 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile->GetTemplateURLModel()->GetDefaultSearchProvider(); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url_template) 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TemplateURLRef* urlref = url_template->url(); 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!urlref) 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return urlref->HasGoogleBaseURLs(); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Flag that remembers if the delayed task already ran or not. This is 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // needed only in the first_run case, since we don't want to record the 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // set-to-google event more than once. We need to worry about this event 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // (and not the others) because it is not a stateful RLZ event. 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static bool already_ran_; 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool first_run_; 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_IMPLICIT_CONSTRUCTORS(DelayedInitTask); 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DelayedInitTask::already_ran_ = false; 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid OmniBoxUsageObserver::Observe(NotificationType type, 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const NotificationSource& source, 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const NotificationDetails& details) { 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Needs to be evaluated. See http://crbug.com/62328. 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::ThreadRestrictions::ScopedAllowIO allow_io; 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Try to record event now, else set the flag to try later when we 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // attempt the ping. 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!RLZTracker::RecordProductEvent(rlz_lib::CHROME, 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen rlz_lib::CHROME_OMNIBOX, 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen rlz_lib::FIRST_SEARCH)) 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen omnibox_used_ = true; 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else if (send_ping_immediately_) { 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::PostTask( 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::FILE, FROM_HERE, new DelayedInitTask(first_run_)); 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delete this; 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RLZTracker::InitRlzDelayed(bool first_run, int delay) { 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // A negative delay means that a financial ping should be sent immediately 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // after a first search is recorded, without waiting for the next restart 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // of chrome. However, we only want this behaviour on first run. 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool send_ping_immediately = false; 274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (delay < 0) { 275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen send_ping_immediately = true; 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delay = -delay; 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Maximum and minimum delay we would allow to be set through master 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // preferences. Somewhat arbitrary, may need to be adjusted in future. 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int kMaxDelay = 200 * 1000; 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int kMinDelay = 20 * 1000; 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delay *= 1000; 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delay = (delay < kMinDelay) ? kMinDelay : delay; 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delay = (delay > kMaxDelay) ? kMaxDelay : delay; 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!OmniBoxUsageObserver::used()) 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new OmniBoxUsageObserver(first_run, send_ping_immediately); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Schedule the delayed init items. 29272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BrowserThread::PostDelayedTask( 29372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BrowserThread::FILE, FROM_HERE, new DelayedInitTask(first_run), delay); 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RLZTracker::RecordProductEvent(rlz_lib::Product product, 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::AccessPoint point, 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rlz_lib::Event event_id) { 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rlz_lib::RecordProductEvent(product, point, event_id); 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RLZTracker::ClearAllProductEvents(rlz_lib::Product product) { 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rlz_lib::ClearAllProductEvents(product); 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We implement caching of the answer of get_access_point() if the request 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is for CHROME_OMNIBOX. If we had a successful ping, then we update the 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// cached value. 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RLZTracker::GetAccessPointRlz(rlz_lib::AccessPoint point, 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring* rlz) { 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static std::wstring cached_ommibox_rlz; 31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rlz_lib::CHROME_OMNIBOX == point) { 31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock lock(rlz_lock); 31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (access_values_state == ACCESS_VALUES_FRESH) { 31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *rlz = cached_ommibox_rlz; 31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 31972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 32272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Make sure we don't access disk outside of the file context. 32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // In such case we repost the task on the right thread and return error. 32472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { 32572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Caching of access points is now only implemented for the CHROME_OMNIBOX. 32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Thus it is not possible to call this function on another thread for 32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // other access points until proper caching for these has been implemented 32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // and the code that calls this function can handle synchronous fetching 32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // of the access point. 33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_EQ(rlz_lib::CHROME_OMNIBOX, point); 33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BrowserThread::PostTask( 33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BrowserThread::FILE, FROM_HERE, 33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NewRunnableFunction(&RLZTracker::GetAccessPointRlz, 33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen point, &cached_ommibox_rlz)); 33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rlz->erase(); 33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char str_rlz[kMaxRlzLength + 1]; 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength, NULL)) 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *rlz = ASCIIToWide(std::string(str_rlz)); 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rlz_lib::CHROME_OMNIBOX == point) { 34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock lock(rlz_lock); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cached_ommibox_rlz.assign(*rlz); 34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen access_values_state = ACCESS_VALUES_FRESH; 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid RLZTracker::CleanupRlz() { 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OmniBoxUsageObserver::DeleteInstance(); 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 356