AU: Skip all automatic update checks if OOBE is not complete.
Right before an automatic update check is initiated, check if OOBE is
complete. If it is, go ahead with the check. Otherwise, skip the check
and schedule a new one as if it is the first one.
BUG=5377
TEST=unit tests, gmerged on device and tried with/without .oobe_completed.
Change-Id: I713e156a176b58a4dd04a01bca340b88277b0361
Review URL: http://codereview.chromium.org/3398018
diff --git a/update_check_scheduler.cc b/update_check_scheduler.cc
index 3d00ff3..7319ec4 100644
--- a/update_check_scheduler.cc
+++ b/update_check_scheduler.cc
@@ -50,6 +50,10 @@
return utils::IsRemovableDevice(utils::RootDevice(utils::BootDevice()));
}
+bool UpdateCheckScheduler::IsOOBEComplete() {
+ return utils::IsOOBEComplete();
+}
+
bool UpdateCheckScheduler::IsOfficialBuild() {
return utils::IsOfficialBuild();
}
@@ -77,7 +81,14 @@
UpdateCheckScheduler* me = reinterpret_cast<UpdateCheckScheduler*>(scheduler);
CHECK(me->scheduled_);
me->scheduled_ = false;
- me->update_attempter_->Update("", "");
+ if (me->IsOOBEComplete()) {
+ me->update_attempter_->Update("", "");
+ } else {
+ // Skips all automatic update checks if the OOBE process is not complete and
+ // schedules a new check as if it is the first one.
+ LOG(WARNING) << "Skipping update check because OOBE is not complete.";
+ me->ScheduleCheck(kTimeoutOnce, kTimeoutRegularFuzz);
+ }
// This check ensures that future update checks will be or are already
// scheduled. The check should never fail. A check failure means that there's
// a bug that will most likely prevent further automatic update checks. It
diff --git a/update_check_scheduler.h b/update_check_scheduler.h
index e3158ed..2ba5253 100644
--- a/update_check_scheduler.h
+++ b/update_check_scheduler.h
@@ -60,6 +60,7 @@
FRIEND_TEST(UpdateCheckSchedulerTest, ComputeNextIntervalAndFuzzTest);
FRIEND_TEST(UpdateCheckSchedulerTest, GTimeoutAddSecondsTest);
FRIEND_TEST(UpdateCheckSchedulerTest, IsBootDeviceRemovableTest);
+ FRIEND_TEST(UpdateCheckSchedulerTest, IsOOBECompleteTest);
FRIEND_TEST(UpdateCheckSchedulerTest, IsOfficialBuildTest);
FRIEND_TEST(UpdateCheckSchedulerTest, RunBootDeviceRemovableTest);
FRIEND_TEST(UpdateCheckSchedulerTest, RunNonOfficialBuildTest);
@@ -72,13 +73,15 @@
FRIEND_TEST(UpdateCheckSchedulerTest, SetUpdateStatusIdleDisabledTest);
FRIEND_TEST(UpdateCheckSchedulerTest, SetUpdateStatusIdleEnabledTest);
FRIEND_TEST(UpdateCheckSchedulerTest, SetUpdateStatusNonIdleTest);
- FRIEND_TEST(UpdateCheckSchedulerTest, StaticCheckTest);
+ FRIEND_TEST(UpdateCheckSchedulerTest, StaticCheckOOBECompleteTest);
+ FRIEND_TEST(UpdateCheckSchedulerTest, StaticCheckOOBENotCompleteTest);
// Wraps GLib's g_timeout_add_seconds so that it can be mocked in tests.
virtual guint GTimeoutAddSeconds(guint interval, GSourceFunc function);
// Wrappers for utils functions so that they can be mocked in tests.
virtual bool IsBootDeviceRemovable();
+ virtual bool IsOOBEComplete();
virtual bool IsOfficialBuild();
// Returns true if an update check can be scheduled. An update check should
diff --git a/update_check_scheduler_unittest.cc b/update_check_scheduler_unittest.cc
index 3aea760..2d2e81d 100644
--- a/update_check_scheduler_unittest.cc
+++ b/update_check_scheduler_unittest.cc
@@ -10,6 +10,7 @@
using std::string;
using testing::_;
using testing::AllOf;
+using testing::Assign;
using testing::Ge;
using testing::Le;
using testing::MockFunction;
@@ -34,6 +35,7 @@
MOCK_METHOD2(GTimeoutAddSeconds, guint(guint seconds, GSourceFunc function));
MOCK_METHOD0(IsBootDeviceRemovable, bool());
MOCK_METHOD0(IsOfficialBuild, bool());
+ MOCK_METHOD0(IsOOBEComplete, bool());
};
class UpdateCheckSchedulerTest : public ::testing::Test {
@@ -148,6 +150,11 @@
EXPECT_FALSE(scheduler_.UpdateCheckScheduler::IsBootDeviceRemovable());
}
+TEST_F(UpdateCheckSchedulerTest, IsOOBECompleteTest) {
+ // Invokes the actual utils wrapper method rather than the subclass mock.
+ EXPECT_FALSE(scheduler_.UpdateCheckScheduler::IsOOBEComplete());
+}
+
TEST_F(UpdateCheckSchedulerTest, IsOfficialBuildTest) {
// Invokes the actual utils wrapper method rather than the subclass mock.
EXPECT_TRUE(scheduler_.UpdateCheckScheduler::IsOfficialBuild());
@@ -260,9 +267,30 @@
scheduler_.SetUpdateStatus(UPDATE_STATUS_DOWNLOADING);
}
-TEST_F(UpdateCheckSchedulerTest, StaticCheckTest) {
+TEST_F(UpdateCheckSchedulerTest, StaticCheckOOBECompleteTest) {
scheduler_.scheduled_ = true;
- EXPECT_CALL(attempter_, Update("", "")).Times(1);
+ EXPECT_CALL(scheduler_, IsOOBEComplete()).Times(1).WillOnce(Return(true));
+ EXPECT_CALL(attempter_, Update("", ""))
+ .Times(1)
+ .WillOnce(Assign(&scheduler_.scheduled_, true));
+ scheduler_.enabled_ = true;
+ EXPECT_CALL(scheduler_, GTimeoutAddSeconds(_, _)).Times(0);
+ UpdateCheckSchedulerUnderTest::StaticCheck(&scheduler_);
+}
+
+TEST_F(UpdateCheckSchedulerTest, StaticCheckOOBENotCompleteTest) {
+ scheduler_.scheduled_ = true;
+ EXPECT_CALL(scheduler_, IsOOBEComplete()).Times(1).WillOnce(Return(false));
+ EXPECT_CALL(attempter_, Update("", "")).Times(0);
+ int interval_min, interval_max;
+ FuzzRange(UpdateCheckScheduler::kTimeoutOnce,
+ UpdateCheckScheduler::kTimeoutRegularFuzz,
+ &interval_min,
+ &interval_max);
+ scheduler_.enabled_ = true;
+ EXPECT_CALL(scheduler_,
+ GTimeoutAddSeconds(AllOf(Ge(interval_min), Le(interval_max)),
+ scheduler_.StaticCheck)).Times(1);
UpdateCheckSchedulerUnderTest::StaticCheck(&scheduler_);
}
diff --git a/utils.cc b/utils.cc
index 6ebffd0..6006eb8 100644
--- a/utils.cc
+++ b/utils.cc
@@ -37,6 +37,8 @@
namespace utils {
+static const char kOOBECompletedMarker[] = "/home/chronos/.oobe_completed";
+
bool IsOfficialBuild() {
OmahaRequestDeviceParams params;
if (!params.Init("", "")) {
@@ -46,6 +48,10 @@
params.app_track != "developer-build";
}
+bool IsOOBEComplete() {
+ return file_util::PathExists(FilePath(kOOBECompletedMarker));
+}
+
bool WriteFile(const char* path, const char* data, int data_len) {
DirectFileWriter writer;
TEST_AND_RETURN_FALSE_ERRNO(0 == writer.Open(path,
diff --git a/utils.h b/utils.h
index 8b070ed..a46ffef 100644
--- a/utils.h
+++ b/utils.h
@@ -27,6 +27,10 @@
// assumes the build is official.
bool IsOfficialBuild();
+// Returns true if the OOBE process has been completed and EULA accepted, false
+// otherwise.
+bool IsOOBEComplete();
+
// Writes the data passed to path. The file at path will be overwritten if it
// exists. Returns true on success, false otherwise.
bool WriteFile(const char* path, const char* data, int data_len);