summaryrefslogtreecommitdiffstats
path: root/chrome/browser/rlz/rlz.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/rlz/rlz.cc
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/rlz/rlz.cc')
-rw-r--r--chrome/browser/rlz/rlz.cc279
1 files changed, 279 insertions, 0 deletions
diff --git a/chrome/browser/rlz/rlz.cc b/chrome/browser/rlz/rlz.cc
new file mode 100644
index 0000000..00cee6d
--- /dev/null
+++ b/chrome/browser/rlz/rlz.cc
@@ -0,0 +1,279 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// This code glues the RLZ library DLL with Chrome. It allows Chrome to work
+// with or without the DLL being present. If the DLL is not present the
+// functions do nothing and just return false.
+
+#include "chrome/browser/rlz/rlz.h"
+
+#include <windows.h>
+#include <process.h>
+
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/task.h"
+#include "base/thread.h"
+#include "chrome/app/google_update_settings.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/profile_manager.h"
+#include "chrome/browser/template_url_model.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/env_vars.h"
+//#include "chrome/common/pref_names.h"
+//#include "chrome/common/pref_service.h"
+
+namespace {
+
+// The maximum length of an access points RLZ in wide chars.
+const DWORD kMaxRlzLength = 64;
+
+// The RLZ is a DLL that might not be present in the system. We load it
+// as needed but never unload it.
+volatile HMODULE rlz_dll = NULL;
+
+
+enum {
+ ACCESS_VALUES_STALE, // Possibly new values available.
+ ACCESS_VALUES_FRESH // The cached values are current.
+};
+
+// Tracks if we have tried and succeeded sending the ping. This helps us
+// decide if we need to refresh the some cached strings.
+volatile int access_values_state = ACCESS_VALUES_STALE;
+
+extern "C" {
+typedef bool (*RecordProductEventFn)(RLZTracker::Product product,
+ RLZTracker::AccessPoint point,
+ RLZTracker::Event event_id,
+ void* reserved);
+
+typedef bool (*GetAccessPointRlzFn)(RLZTracker::AccessPoint point,
+ wchar_t* rlz,
+ DWORD rlz_size,
+ void* reserved);
+
+typedef bool (*ClearAllProductEventsFn)(RLZTracker::Product product,
+ void* reserved);
+
+typedef bool (*SendFinancialPingFn)(RLZTracker::Product product,
+ RLZTracker::AccessPoint* access_points,
+ const WCHAR* product_signature,
+ const WCHAR* product_brand,
+ const WCHAR* product_id,
+ const WCHAR* product_lang,
+ void* reserved);
+} // extern "C"
+
+RecordProductEventFn record_event = NULL;
+GetAccessPointRlzFn get_access_point = NULL;
+ClearAllProductEventsFn clear_all_events = NULL;
+SendFinancialPingFn send_ping = NULL;
+
+template <typename FuncT>
+FuncT WireExport(HMODULE module, const char* export_name) {
+ void* entry_point = ::GetProcAddress(module, export_name);
+ return (module)? reinterpret_cast<FuncT>(entry_point) : NULL;
+}
+
+HMODULE LoadRLZLibraryInternal(int directory_key) {
+ std::wstring rlz_path;
+ if (!PathService::Get(directory_key, &rlz_path))
+ return NULL;
+ file_util::AppendToPath(&rlz_path, L"rlz.dll");
+ return ::LoadLibraryW(rlz_path.c_str());
+}
+
+bool LoadRLZLibrary(int directory_key) {
+ rlz_dll = LoadRLZLibraryInternal(directory_key);
+ if (!rlz_dll) {
+ // As a last resort we can try the EXE directory.
+ if (directory_key != base::DIR_EXE)
+ rlz_dll = LoadRLZLibraryInternal(base::DIR_EXE);
+ }
+ if (rlz_dll) {
+ record_event =
+ WireExport<RecordProductEventFn>(rlz_dll, "RecordProductEvent");
+ get_access_point =
+ WireExport<GetAccessPointRlzFn>(rlz_dll, "GetAccessPointRlz");
+ clear_all_events =
+ WireExport<ClearAllProductEventsFn>(rlz_dll, "ClearAllProductEvents");
+ send_ping =
+ WireExport<SendFinancialPingFn>(rlz_dll, "SendFinancialPing");
+ return true;
+ }
+ return false;
+}
+
+class DailyPingTask : public Task {
+ public:
+ virtual ~DailyPingTask() {
+ }
+ virtual void Run() {
+ // We use a transient thread because we have no guarantees about
+ // how long the RLZ lib can block us.
+ _beginthread(PingNow, 0, NULL);
+ }
+
+ private:
+ // Causes a ping to the server using WinInet. There is logic inside RLZ dll
+ // that throttles it to a maximum of one ping per day.
+ static void _cdecl PingNow(void*) {
+ std::wstring lang;
+ GoogleUpdateSettings::GetLanguage(&lang);
+ if (lang.empty())
+ lang = L"en";
+ std::wstring brand;
+ GoogleUpdateSettings::GetBrand(&brand);
+ if (brand.empty())
+ brand = L"GGLD";
+ if (RLZTracker::SendFinancialPing(RLZTracker::CHROME, L"chrome",
+ brand.c_str(), NULL, lang.c_str())) {
+ access_values_state = ACCESS_VALUES_STALE;
+ }
+ }
+};
+
+// Performs late RLZ initialization and RLZ event recording for chrome.
+// This task needs to run on the UI thread.
+class DelayedInitTask : public Task {
+ public:
+ explicit DelayedInitTask(int directory_key, bool first_run)
+ : directory_key_(directory_key), first_run_(first_run) {
+ }
+ virtual ~DelayedInitTask() {
+ }
+ virtual void Run() {
+ if (!LoadRLZLibrary(directory_key_))
+ return;
+ // For non-interactive tests we don't do the rest of the initialization.
+ if (::GetEnvironmentVariableW(env_vars::kHeadless, NULL, 0))
+ return;
+ if (first_run_) {
+ // Record the installation of chrome.
+ RLZTracker::RecordProductEvent(RLZTracker::CHROME,
+ RLZTracker::CHROME_OMNIBOX,
+ RLZTracker::INSTALL);
+ RLZTracker::RecordProductEvent(RLZTracker::CHROME,
+ RLZTracker::CHROME_HOME_PAGE,
+ RLZTracker::INSTALL);
+ // Record if google is the initial search provider.
+ if (IsGoogleDefaultSearch()) {
+ RLZTracker::RecordProductEvent(RLZTracker::CHROME,
+ RLZTracker::CHROME_OMNIBOX,
+ RLZTracker::SET_TO_GOOGLE);
+ }
+ }
+ // Schedule the daily RLZ ping.
+ Thread* thread = g_browser_process->file_thread();
+ if (thread)
+ thread->message_loop()->PostTask(FROM_HERE, new DailyPingTask());
+ }
+
+ private:
+ bool IsGoogleDefaultSearch() {
+ if (!g_browser_process)
+ return false;
+ std::wstring user_data_dir;
+ if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
+ return false;
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
+ if (!profile)
+ return false;
+ const TemplateURL* url_template =
+ profile->GetTemplateURLModel()->GetDefaultSearchProvider();
+ if (!url_template)
+ return false;
+ return url_template->url()->HasGoogleBaseURLs();
+ }
+
+ int directory_key_;
+ bool first_run_;
+ DISALLOW_IMPLICIT_CONSTRUCTORS(DelayedInitTask);
+};
+
+} // namespace
+
+bool RLZTracker::InitRlz(int directory_key) {
+ return LoadRLZLibrary(directory_key);
+}
+
+bool RLZTracker::InitRlzDelayed(int directory_key, bool first_run) {
+ // Schedule the delayed init items.
+ const int kOneHundredSeconds = 100000;
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ new DelayedInitTask(directory_key, first_run), kOneHundredSeconds);
+ return true;
+}
+
+bool RLZTracker::RecordProductEvent(Product product, AccessPoint point,
+ Event event) {
+ return (record_event) ? record_event(product, point, event, NULL) : false;
+}
+
+bool RLZTracker::ClearAllProductEvents(Product product) {
+ return (clear_all_events) ? clear_all_events(product, NULL) : false;
+}
+
+// We implement caching of the answer of get_access_point() if the request
+// is for CHROME_OMNIBOX. If we had a successful ping, then we update the
+// cached value.
+
+bool RLZTracker::GetAccessPointRlz(AccessPoint point, std::wstring* rlz) {
+ static std::wstring cached_ommibox_rlz;
+ if (!get_access_point)
+ return false;
+ if ((CHROME_OMNIBOX == point) &&
+ (access_values_state == ACCESS_VALUES_FRESH)) {
+ *rlz = cached_ommibox_rlz;
+ return true;
+ }
+ wchar_t str_rlz[kMaxRlzLength];
+ if (!get_access_point(point, str_rlz, kMaxRlzLength, NULL))
+ return false;
+ if (CHROME_OMNIBOX == point) {
+ access_values_state = ACCESS_VALUES_FRESH;
+ cached_ommibox_rlz.assign(str_rlz);
+ }
+ *rlz = str_rlz;
+ return true;
+}
+
+bool RLZTracker::SendFinancialPing(Product product,
+ const wchar_t* product_signature,
+ const wchar_t* product_brand,
+ const wchar_t* product_id,
+ const wchar_t* product_lang) {
+ AccessPoint points[] = {CHROME_OMNIBOX, CHROME_HOME_PAGE, NO_ACCESS_POINT};
+ return (send_ping) ? send_ping(product, points, product_signature,
+ product_brand, product_id, product_lang, NULL) : false;
+}