Commit 8242fb62 authored by Wenzhao Zang's avatar Wenzhao Zang Committed by Commit Bot

cros: Add check for |should_send_rlz_ping| in RW_VPD

Reading from VPD is supported by StatisticsProvider so IMO we can reuse
the code. There will be a follow-up Chrome OS CL to deal with writing
to VPD specifically.

Bug: 820783
Change-Id: I57de7212ca3b5366731789f0836ab5c6fcca294f
Reviewed-on: https://chromium-review.googlesource.com/969942
Commit-Queue: Wenzhao (Colin) Zang <wzang@chromium.org>
Reviewed-by: default avatarAlexander Alekseev <alemate@chromium.org>
Reviewed-by: default avatarRoger Tawa <rogerta@chromium.org>
Cr-Commit-Position: refs/heads/master@{#545659}
parent 5e5875bd
......@@ -174,6 +174,10 @@ bool GetInitialLocaleFromRegionalData(const base::DictionaryValue* region_dict,
// Key values for GetMachineStatistic()/GetMachineFlag() calls.
const char kActivateDateKey[] = "ActivateDate";
const char kCheckEnrollmentKey[] = "check_enrollment";
const char kShouldSendRlzPingKey[] = "should_send_rlz_ping";
const char kShouldSendRlzPingValueFalse[] = "0";
const char kShouldSendRlzPingValueTrue[] = "1";
const char kRlzEmbargoEndDateKey[] = "rlz_embargo_end_date";
const char kCustomizationIdKey[] = "customization_id";
const char kDevSwitchBootKey[] = "devsw_boot";
const char kDevSwitchBootValueDev[] = "1";
......
......@@ -19,6 +19,15 @@ CHROMEOS_EXPORT extern const char kActivateDateKey[];
// The key that will be present in VPD if the device ever was enrolled.
CHROMEOS_EXPORT extern const char kCheckEnrollmentKey[];
// The key and values present in VPD to indicate if RLZ ping should be sent.
CHROMEOS_EXPORT extern const char kShouldSendRlzPingKey[];
CHROMEOS_EXPORT extern const char kShouldSendRlzPingValueFalse[];
CHROMEOS_EXPORT extern const char kShouldSendRlzPingValueTrue[];
// The key present in VPD that indicates the date after which the RLZ ping is
// allowed to be sent. It is in the format of "yyyy-mm-dd".
CHROMEOS_EXPORT extern const char kRlzEmbargoEndDateKey[];
// Customization ID key.
CHROMEOS_EXPORT extern const char kCustomizationIdKey[];
......
......@@ -37,4 +37,8 @@ source_set("unit_tests") {
"//rlz:test_support",
"//ui/base",
]
if (is_chromeos) {
deps += [ "//chromeos" ]
}
}
include_rules = [
"+chromeos/system",
"+components/google",
"+net",
"+rlz",
......
......@@ -24,6 +24,10 @@
#include "ui/base/device_form_factor.h"
#endif
#if defined(OS_CHROMEOS)
#include "chromeos/system/fake_statistics_provider.h"
#endif
using testing::AssertionResult;
using testing::AssertionSuccess;
using testing::AssertionFailure;
......@@ -255,6 +259,11 @@ class RlzLibTest : public testing::Test {
TestRLZTrackerDelegate* delegate_;
std::unique_ptr<TestRLZTracker> tracker_;
RlzLibTestNoMachineStateHelper m_rlz_test_helper_;
#if defined(OS_CHROMEOS)
std::unique_ptr<chromeos::system::FakeStatisticsProvider>
statistics_provider_;
#endif
};
void RlzLibTest::SetUp() {
......@@ -269,6 +278,13 @@ void RlzLibTest::SetUp() {
// is pretty much a no-op.
SetMainBrand("TEST");
SetReactivationBrand("");
#if defined(OS_CHROMEOS)
statistics_provider_ =
std::make_unique<chromeos::system::FakeStatisticsProvider>();
chromeos::system::StatisticsProvider::SetTestProvider(
statistics_provider_.get());
#endif // defined(OS_CHROMEOS)
}
void RlzLibTest::TearDown() {
......@@ -276,6 +292,10 @@ void RlzLibTest::TearDown() {
tracker_.reset();
testing::Test::TearDown();
m_rlz_test_helper_.TearDown();
#if defined(OS_CHROMEOS)
chromeos::system::StatisticsProvider::SetTestProvider(nullptr);
#endif // defined(OS_CHROMEOS)
}
void RlzLibTest::SetMainBrand(const char* brand) {
......
......@@ -85,6 +85,10 @@ if (!is_android) {
"//url",
]
if (is_chromeos) {
deps += [ "//chromeos" ]
}
if (is_mac) {
libs = [
"Foundation.framework",
......@@ -115,6 +119,9 @@ if (!is_android) {
"//base/test:test_support",
"//testing/gtest",
]
if (is_chromeos) {
deps += [ "//chromeos" ]
}
}
test("rlz_unittests") {
......
......@@ -56,6 +56,7 @@ deps = {
include_rules = [
"+build",
"+chromeos/system",
"+net", # This is only used when force_rlz_use_chrome_net=1 is passed to gyp.
"+third_party/zlib",
]
......
......@@ -16,6 +16,8 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "chromeos/system/statistics_provider.h"
#include "rlz/lib/financial_ping.h"
#include "rlz/lib/lib_values.h"
#include "rlz/lib/recursive_cross_process_lock_posix.h"
#include "rlz/lib/rlz_lib.h"
......@@ -46,9 +48,6 @@ base::LazyInstance<base::FilePath>::Leaky g_testing_rlz_store_path =
LAZY_INSTANCE_INITIALIZER;
base::FilePath GetRlzStorePathCommon() {
// TODO(wzang): Replace base::DIR_HOME with something that is shared by all
// profiles on the device. This location must be somewhere that is wiped
// when the device is factory reset or powerwashed.
base::FilePath homedir;
PathService::Get(base::DIR_HOME, &homedir);
return g_testing_rlz_store_path.Get().empty()
......@@ -82,8 +81,43 @@ std::string GetKeyName(const std::string& key, Product product) {
return key + "." + GetProductName(product) + "." + brand;
}
// Returns true if the |rlz_embargo_end_date| present in VPD has passed
// compared to the current time.
bool HasRlzEmbargoEndDatePassed() {
chromeos::system::StatisticsProvider* stats =
chromeos::system::StatisticsProvider::GetInstance();
std::string rlz_embargo_end_date;
if (!stats->GetMachineStatistic(chromeos::system::kRlzEmbargoEndDateKey,
&rlz_embargo_end_date)) {
// |rlz_embargo_end_date| only exists on new devices that have not yet
// launched. When the field doesn't exist, returns true so it's a no-op.
return true;
}
base::Time parsed_time;
if (!base::Time::FromUTCString(rlz_embargo_end_date.c_str(), &parsed_time)) {
LOG(ERROR) << "|rlz_embargo_end_date| exists but cannot be parsed.";
return true;
}
if (parsed_time - base::Time::Now() >=
base::TimeDelta::FromDays(
RlzValueStoreChromeOS::kRlzEmbargoEndDateGarbageDateThresholdDays)) {
// If |rlz_embargo_end_date| is more than this many days in the future,
// ignore it. Because it indicates that the device is not connected to an
// ntp server in the factory, and its internal clock could be off when the
// date is written.
return true;
}
return base::Time::Now() > parsed_time;
}
} // namespace
const int RlzValueStoreChromeOS::kRlzEmbargoEndDateGarbageDateThresholdDays =
14;
RlzValueStoreChromeOS::RlzValueStoreChromeOS(const base::FilePath& store_path)
: rlz_store_(new base::DictionaryValue),
store_path_(store_path),
......@@ -111,12 +145,12 @@ bool RlzValueStoreChromeOS::WritePingTime(Product product, int64_t time) {
bool RlzValueStoreChromeOS::ReadPingTime(Product product, int64_t* time) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
#if defined(OS_CHROMEOS)
// TODO(wzang): make sure time is correct (check that npupdate has updated
// successfully).
// TODO(wzang): if the current time is within 7 days of the
// factory_production_date value in the RW_VPD, then return the current time.
#endif
if (!HasRlzEmbargoEndDatePassed()) {
*time = FinancialPing::GetSystemTimeAsInt64();
return true;
}
std::string ping_time;
return rlz_store_->GetString(GetKeyName(kPingTimeKey, product), &ping_time) &&
......@@ -131,7 +165,6 @@ bool RlzValueStoreChromeOS::ClearPingTime(Product product) {
bool RlzValueStoreChromeOS::WriteAccessPointRlz(AccessPoint access_point,
const char* new_rlz) {
#if defined(OS_CHROMEOS)
// If an access point already exists, don't overwrite it. This is to prevent
// writing cohort data for first search which is not needed in Chrome OS.
//
......@@ -147,7 +180,6 @@ bool RlzValueStoreChromeOS::WriteAccessPointRlz(AccessPoint access_point,
dummy[0] != 0) {
return true;
}
#endif
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
rlz_store_->SetString(
......@@ -217,12 +249,9 @@ bool RlzValueStoreChromeOS::AddStatefulEvent(Product product,
const char* event_rlz) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
#if defined(OS_CHROMEOS)
if (strcmp(event_rlz, "CAF") == 0) {
// TODO(wzang): Set rlz_first_use_ping_not_sent to 0 in RW_VPD.
}
#endif
return AddValueToList(GetKeyName(kStatefulEventKey, product),
std::make_unique<base::Value>(event_rlz));
}
......@@ -231,24 +260,36 @@ bool RlzValueStoreChromeOS::IsStatefulEvent(Product product,
const char* event_rlz) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
#if defined(OS_CHROMEOS)
if (strcmp(event_rlz, "CAF") == 0) {
// TODO(wzang): If rlz_first_use_ping_not_sent exists in RW_VPD with
// value 0, then return true.
// TODO(wzang): if the current time is within 7 days of the
// factory_production_date value in the RW_VPD, then return true.
// TODO(wzang): if rlz_first_use_ping_not_sent exists in RW_VPD with
// value 1 but below the code finds |event_value| in the list, try to
// set rlz_first_use_ping_not_sent to zero in the RW_VPD. This is to try
// and fix the RW_VPD if there was an error writing to it earlier.
}
#endif
base::Value event_value(event_rlz);
base::ListValue* events_list = NULL;
return rlz_store_->GetList(GetKeyName(kStatefulEventKey, product),
&events_list) &&
const bool event_exists =
rlz_store_->GetList(GetKeyName(kStatefulEventKey, product),
&events_list) &&
events_list->Find(event_value) != events_list->end();
if (strcmp(event_rlz, "CAF") == 0) {
chromeos::system::StatisticsProvider* stats =
chromeos::system::StatisticsProvider::GetInstance();
std::string should_send_rlz_ping_value;
if (stats->GetMachineStatistic(chromeos::system::kShouldSendRlzPingKey,
&should_send_rlz_ping_value)) {
if (should_send_rlz_ping_value ==
chromeos::system::kShouldSendRlzPingValueFalse) {
return true;
}
if (!HasRlzEmbargoEndDatePassed())
return true;
DCHECK_EQ(should_send_rlz_ping_value,
chromeos::system::kShouldSendRlzPingValueTrue);
if (event_exists) {
// TODO(wzang): If we reach here, it means there was an error writing to
// RW_VPD earlier. We should log the error and try writing to RW_VPD
// again. Also, capture UMA stat on persistent failure to write VPD.
}
}
}
return event_exists;
}
bool RlzValueStoreChromeOS::ClearAllStatefulEvents(Product product) {
......
......@@ -25,6 +25,10 @@ namespace rlz_lib {
// An implementation of RlzValueStore for ChromeOS.
class RlzValueStoreChromeOS : public RlzValueStore {
public:
// Ignore |kRlzEmbargoEndDateKey| if it's more than this many days in the
// future.
static const int kRlzEmbargoEndDateGarbageDateThresholdDays;
// Creates new instance and synchronously reads data from file.
explicit RlzValueStoreChromeOS(const base::FilePath& store_path);
~RlzValueStoreChromeOS() override;
......
......@@ -70,31 +70,6 @@ class InternetHandle {
#endif
namespace {
// Returns the time relative to a fixed point in the past in multiples of
// 100 ns stepts. The point in the past is arbitrary but can't change, as the
// result of this value is stored on disk.
int64_t GetSystemTimeAsInt64() {
#if defined(OS_WIN)
FILETIME now_as_file_time;
// Relative to Jan 1, 1601 (UTC).
GetSystemTimeAsFileTime(&now_as_file_time);
LARGE_INTEGER integer;
integer.HighPart = now_as_file_time.dwHighDateTime;
integer.LowPart = now_as_file_time.dwLowDateTime;
return integer.QuadPart;
#else
// Seconds since epoch (Jan 1, 1970).
double now_seconds = base::Time::Now().ToDoubleT();
return static_cast<int64_t>(now_seconds * 1000 * 1000 * 10);
#endif
}
} // namespace
namespace rlz_lib {
using base::subtle::AtomicWord;
......@@ -503,6 +478,23 @@ bool FinancialPing::ClearLastPingTime(Product product) {
return store->ClearPingTime(product);
}
int64_t FinancialPing::GetSystemTimeAsInt64() {
#if defined(OS_WIN)
FILETIME now_as_file_time;
// Relative to Jan 1, 1601 (UTC).
GetSystemTimeAsFileTime(&now_as_file_time);
LARGE_INTEGER integer;
integer.HighPart = now_as_file_time.dwHighDateTime;
integer.LowPart = now_as_file_time.dwLowDateTime;
return integer.QuadPart;
#else
// Seconds since epoch (Jan 1, 1970).
double now_seconds = base::Time::Now().ToDoubleT();
return static_cast<int64_t>(now_seconds * 1000 * 1000 * 10);
#endif
}
#if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
namespace test {
......
......@@ -49,6 +49,11 @@ class FinancialPing {
// Ping the financial server with request. Writes to RlzValueStore.
static bool PingServer(const char* request, std::string* response);
// Returns the time relative to a fixed point in the past in multiples of
// 100 ns stepts. The point in the past is arbitrary but can't change, as the
// result of this value is stored on disk.
static int64_t GetSystemTimeAsInt64();
#if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
static bool SetURLRequestContext(net::URLRequestContextGetter* context);
#endif
......
......@@ -38,22 +38,11 @@
#include "base/time/time.h"
#endif
namespace {
// Must match the implementation in file_time.cc.
int64_t GetSystemTimeAsInt64() {
#if defined(OS_WIN)
FILETIME now_as_file_time;
GetSystemTimeAsFileTime(&now_as_file_time);
LARGE_INTEGER integer;
integer.HighPart = now_as_file_time.dwHighDateTime;
integer.LowPart = now_as_file_time.dwLowDateTime;
return integer.QuadPart;
#else
double now_seconds = base::Time::Now().ToDoubleT();
return static_cast<int64_t>(now_seconds * 1000 * 1000 * 10);
#if defined(OS_CHROMEOS)
#include "rlz/chromeos/lib/rlz_value_store_chromeos.h"
#endif
}
namespace {
#if defined(OS_CHROMEOS)
void RemoveMachineIdFromUrl(std::string* url) {
......@@ -61,6 +50,22 @@ void RemoveMachineIdFromUrl(std::string* url) {
EXPECT_NE(std::string::npos, id_offset);
url->resize(id_offset);
}
// Utility function to convert a |base::Time::Exploded| to "yyyy-mm-dd" format.
std::string ConvertExplodedToRlzEmbargoDate(
const base::Time::Exploded& exploded) {
std::string rlz_embargo_date = std::to_string(exploded.year);
rlz_embargo_date += '-';
if (exploded.month < 10)
rlz_embargo_date += '0';
rlz_embargo_date += std::to_string(exploded.month);
rlz_embargo_date += '-';
if (exploded.day_of_month < 10)
rlz_embargo_date += '0';
rlz_embargo_date += std::to_string(exploded.day_of_month);
return rlz_embargo_date;
}
#endif
// Ping times in 100-nanosecond intervals.
......@@ -218,7 +223,7 @@ static void SetLastPingTime(int64_t time, rlz_lib::Product product) {
}
TEST_F(FinancialPingTest, IsPingTime) {
int64_t now = GetSystemTimeAsInt64();
int64_t now = rlz_lib::FinancialPing::GetSystemTimeAsInt64();
int64_t last_ping = now - rlz_lib::kEventsPingInterval - k1MinuteInterval;
SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
......@@ -270,7 +275,7 @@ TEST_F(FinancialPingTest, BrandingIsPingTime) {
if (!rlz_lib::SupplementaryBranding::GetBrand().empty())
return;
int64_t now = GetSystemTimeAsInt64();
int64_t now = rlz_lib::FinancialPing::GetSystemTimeAsInt64();
int64_t last_ping = now - rlz_lib::kEventsPingInterval - k1MinuteInterval;
SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
......@@ -305,7 +310,7 @@ TEST_F(FinancialPingTest, BrandingIsPingTime) {
}
TEST_F(FinancialPingTest, ClearLastPingTime) {
int64_t now = GetSystemTimeAsInt64();
int64_t now = rlz_lib::FinancialPing::GetSystemTimeAsInt64();
int64_t last_ping = now - rlz_lib::kEventsPingInterval + k1MinuteInterval;
SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
......@@ -321,3 +326,58 @@ TEST_F(FinancialPingTest, ClearLastPingTime) {
EXPECT_TRUE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
false));
}
#if defined(OS_CHROMEOS)
TEST_F(FinancialPingTest, RlzEmbargoEndDate) {
// Do not set last ping time, verify that |IsPingTime| returns true.
EXPECT_TRUE(
rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER, false));
// Simulate writing a past embargo date to VPD, verify that |IsPingTime|
// returns true when the embargo date has already passed.
base::Time::Exploded exploded;
base::Time past_rlz_embargo_date =
base::Time::NowFromSystemTime() - base::TimeDelta::FromDays(1);
past_rlz_embargo_date.LocalExplode(&exploded);
std::string past_rlz_embargo_date_value =
ConvertExplodedToRlzEmbargoDate(exploded);
statistics_provider_->SetMachineStatistic(
chromeos::system::kRlzEmbargoEndDateKey, past_rlz_embargo_date_value);
EXPECT_TRUE(
rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER, false));
// Simulate writing a future embargo date (less than
// |kRlzEmbargoEndDateGarbageDateThresholdDays|) to VPD, verify that
// |IsPingTime| is false.
base::Time future_rlz_embargo_date =
base::Time::NowFromSystemTime() +
base::TimeDelta::FromDays(rlz_lib::RlzValueStoreChromeOS::
kRlzEmbargoEndDateGarbageDateThresholdDays -
1);
future_rlz_embargo_date.LocalExplode(&exploded);
std::string future_rlz_embargo_date_value =
ConvertExplodedToRlzEmbargoDate(exploded);
statistics_provider_->SetMachineStatistic(
chromeos::system::kRlzEmbargoEndDateKey, future_rlz_embargo_date_value);
EXPECT_FALSE(
rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER, false));
// Simulate writing a future embargo date (more than
// |kRlzEmbargoEndDateGarbageDateThresholdDays|) to VPD, verify that
// |IsPingTime| is true.
future_rlz_embargo_date =
base::Time::NowFromSystemTime() +
base::TimeDelta::FromDays(rlz_lib::RlzValueStoreChromeOS::
kRlzEmbargoEndDateGarbageDateThresholdDays +
1);
future_rlz_embargo_date.LocalExplode(&exploded);
future_rlz_embargo_date_value = ConvertExplodedToRlzEmbargoDate(exploded);
statistics_provider_->SetMachineStatistic(
chromeos::system::kRlzEmbargoEndDateKey, future_rlz_embargo_date_value);
EXPECT_TRUE(
rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER, false));
}
#endif
......@@ -162,6 +162,10 @@ void RlzLibTestNoMachineState::TearDown() {
m_rlz_test_helper_.TearDown();
}
RlzLibTestBase::RlzLibTestBase() = default;
RlzLibTestBase::~RlzLibTestBase() = default;
void RlzLibTestBase::SetUp() {
RlzLibTestNoMachineState::SetUp();
#if defined(OS_WIN)
......@@ -173,5 +177,18 @@ void RlzLibTestBase::SetUp() {
// out not set, since on Chrome OS RLZ string can only be set once.
EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, ""));
EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IE_HOME_PAGE, ""));
#endif // defined(OS_POSIX)
#if defined(OS_CHROMEOS)
statistics_provider_ =
std::make_unique<chromeos::system::FakeStatisticsProvider>();
chromeos::system::StatisticsProvider::SetTestProvider(
statistics_provider_.get());
#endif // defined(OS_CHROMEOS)
}
void RlzLibTestBase::TearDown() {
#if defined(OS_CHROMEOS)
chromeos::system::StatisticsProvider::SetTestProvider(nullptr);
#endif // defined(OS_CHROMEOS)
}
......@@ -19,6 +19,10 @@
#include "base/test/test_reg_util_win.h"
#endif
#if defined(OS_CHROMEOS)
#include "chromeos/system/fake_statistics_provider.h"
#endif
// A test helper class that constructs and destructs platform dependent machine
// state. It's used by src/components/rlz/rlz_tracker_unittest.cc and
// src/rlz/lib/rlz_lib_test.cc
......@@ -46,8 +50,18 @@ class RlzLibTestNoMachineState : public ::testing::Test {
};
class RlzLibTestBase : public RlzLibTestNoMachineState {
public:
RlzLibTestBase();
~RlzLibTestBase() override;
protected:
void SetUp() override;
void TearDown() override;
#if defined(OS_CHROMEOS)
std::unique_ptr<chromeos::system::FakeStatisticsProvider>
statistics_provider_;
#endif
};
#endif // RLZ_TEST_RLZ_TEST_HELPERS_H
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment