Enable test mode updates.
* Uses the GPIO module to deduce whether a current update session needs
to be treated as a controlled test, which allows a few relaxations.
* LibcurlHttpFetcher is extended to relax some of its security lock down
provisions.
* Fix: a test mode flag remains persistent throughout an update attempt,
so that it can be delegated to the various HttpFetcher instances used
in the same attempt.
BUG=chromium-os:25397
TEST=Builds and unittests; automated test script works w/ servo
connected Alex
Change-Id: I8a29d1a21a0632912c10f01f69a26d9c659472fd
Reviewed-on: https://gerrit.chromium.org/gerrit/25128
Reviewed-by: Gilad Arnold <garnold@chromium.org>
Tested-by: Gilad Arnold <garnold@chromium.org>
Commit-Ready: Gilad Arnold <garnold@chromium.org>
diff --git a/http_fetcher_unittest.cc b/http_fetcher_unittest.cc
index a46ad2c..9750067 100644
--- a/http_fetcher_unittest.cc
+++ b/http_fetcher_unittest.cc
@@ -238,7 +238,7 @@
proxy_resolver_.set_num_proxies(num_proxies);
LibcurlHttpFetcher *ret = new
LibcurlHttpFetcher(reinterpret_cast<ProxyResolver*>(&proxy_resolver_),
- &mock_system_state_);
+ &mock_system_state_, false);
// Speed up test execution.
ret->set_idle_seconds(1);
ret->set_retry_seconds(1);
@@ -285,8 +285,9 @@
proxy_resolver_.set_num_proxies(num_proxies);
ProxyResolver* resolver =
reinterpret_cast<ProxyResolver*>(&proxy_resolver_);
- MultiRangeHttpFetcher *ret = new MultiRangeHttpFetcher(
- new LibcurlHttpFetcher(resolver, &mock_system_state_));
+ MultiRangeHttpFetcher *ret =
+ new MultiRangeHttpFetcher(
+ new LibcurlHttpFetcher(resolver, &mock_system_state_, false));
ret->ClearRanges();
ret->AddRange(0);
// Speed up test execution.
diff --git a/libcurl_http_fetcher.cc b/libcurl_http_fetcher.cc
index 6153f4c..7c40cba 100644
--- a/libcurl_http_fetcher.cc
+++ b/libcurl_http_fetcher.cc
@@ -171,7 +171,7 @@
// Security lock-down in official builds: makes sure that peer certificate
// verification is enabled, restricts the set of trusted certificates,
// restricts protocols to HTTPS, restricts ciphers to HIGH.
- if (IsOfficialBuild()) {
+ if (!is_test_mode_ && IsOfficialBuild()) {
CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_SSL_VERIFYPEER, 1),
CURLE_OK);
CHECK_EQ(curl_easy_setopt(curl_handle_,
diff --git a/libcurl_http_fetcher.h b/libcurl_http_fetcher.h
index e317819..981d096 100644
--- a/libcurl_http_fetcher.h
+++ b/libcurl_http_fetcher.h
@@ -31,7 +31,8 @@
static const int kMaxRetryCountOobeNotComplete;
LibcurlHttpFetcher(ProxyResolver* proxy_resolver,
- SystemState* system_state)
+ SystemState* system_state,
+ bool is_test_mode)
: HttpFetcher(proxy_resolver, system_state),
curl_multi_handle_(NULL),
curl_handle_(NULL),
@@ -53,7 +54,8 @@
in_write_callback_(false),
sent_byte_(false),
terminate_requested_(false),
- check_certificate_(CertificateChecker::kNone) {}
+ check_certificate_(CertificateChecker::kNone),
+ is_test_mode_(is_test_mode) {}
// Cleans up all internal state. Does not notify delegate
~LibcurlHttpFetcher();
@@ -258,6 +260,9 @@
// this should be kNone.
CertificateChecker::ServerToCheck check_certificate_;
+ // If true, utilizes a relaxed test mode fetch logic. False by default.
+ bool is_test_mode_;
+
DISALLOW_COPY_AND_ASSIGN(LibcurlHttpFetcher);
};
diff --git a/main.cc b/main.cc
index 84b6c11..596b04d 100644
--- a/main.cc
+++ b/main.cc
@@ -21,6 +21,7 @@
#include "update_engine/dbus_constants.h"
#include "update_engine/dbus_interface.h"
#include "update_engine/dbus_service.h"
+#include "update_engine/gpio_handler.h"
#include "update_engine/prefs.h"
#include "update_engine/subprocess.h"
#include "update_engine/terminator.h"
@@ -181,13 +182,22 @@
chromeos_update_engine::CertificateChecker::set_openssl_wrapper(
&openssl_wrapper);
+ // Initialize a GPIO handler. Defer GPIO discovery to ensure the udev has
+ // ample time to export the devices. Also require that test mode is physically
+ // queries at most once and the result cached, for a more consistent update
+ // behavior.
+ chromeos_update_engine::StandardUdevInterface udev_iface;
+ chromeos_update_engine::EintrSafeFileDescriptor file_descriptor;
+ chromeos_update_engine::StandardGpioHandler
+ gpio_handler(&udev_iface, &file_descriptor, true, true);
+
// Create the update attempter:
chromeos_update_engine::ConcreteDbusGlib dbus;
chromeos_update_engine::RealSystemState real_system_state;
chromeos_update_engine::UpdateAttempter update_attempter(&prefs,
&metrics_lib,
&dbus,
- NULL,
+ &gpio_handler,
&real_system_state);
// Create the dbus service object:
@@ -201,7 +211,7 @@
// Schedule periodic update checks.
chromeos_update_engine::UpdateCheckScheduler scheduler(&update_attempter,
- NULL,
+ &gpio_handler,
&real_system_state);
scheduler.Run();
diff --git a/update_attempter.cc b/update_attempter.cc
index 7e3f362..93c3c1f 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -134,6 +134,7 @@
start_action_processor_(false),
policy_provider_(NULL),
is_using_test_url_(false),
+ is_test_mode_(false),
is_test_update_attempted_(false),
gpio_handler_(gpio_handler),
init_waiting_period_from_prefs_(true),
@@ -150,7 +151,7 @@
const string& omaha_url,
bool obey_proxies,
bool interactive,
- bool is_test,
+ bool is_test_mode,
bool is_user_initiated) {
chrome_proxy_resolver_.Init();
fake_update_success_ = false;
@@ -171,7 +172,7 @@
omaha_url,
obey_proxies,
interactive,
- is_test,
+ is_test_mode,
is_user_initiated)) {
return;
}
@@ -191,10 +192,13 @@
const string& omaha_url,
bool obey_proxies,
bool interactive,
- bool is_test,
+ bool is_test_mode,
bool is_user_initiated) {
http_response_code_ = 0;
+ // Set the test mode flag for the current update attempt.
+ is_test_mode_ = is_test_mode;
+
// Lazy initialize the policy provider, or reload the latest policy data.
if (!policy_provider_.get()) {
policy_provider_.reset(new policy::PolicyProvider());
@@ -305,7 +309,7 @@
// Determine whether an alternative test address should be used.
string omaha_url_to_use = omaha_url;
- if ((is_using_test_url_ = (omaha_url_to_use.empty() && is_test))) {
+ if ((is_using_test_url_ = (omaha_url_to_use.empty() && is_test_mode_))) {
omaha_url_to_use = kTestUpdateUrl;
LOG(INFO) << "using alternative server address: " << omaha_url_to_use;
}
@@ -359,7 +363,7 @@
// Actions:
LibcurlHttpFetcher* update_check_fetcher =
- new LibcurlHttpFetcher(GetProxyResolver(), system_state_);
+ new LibcurlHttpFetcher(GetProxyResolver(), system_state_, is_test_mode_);
// Try harder to connect to the network, esp when not interactive.
// See comment in libcurl_http_fetcher.cc.
update_check_fetcher->set_no_network_max_retries(interactive ? 1 : 3);
@@ -382,10 +386,11 @@
new OmahaEvent(
OmahaEvent::kTypeUpdateDownloadStarted),
new LibcurlHttpFetcher(GetProxyResolver(),
- system_state_),
+ system_state_,
+ is_test_mode_),
false));
LibcurlHttpFetcher* download_fetcher =
- new LibcurlHttpFetcher(GetProxyResolver(), system_state_);
+ new LibcurlHttpFetcher(GetProxyResolver(), system_state_, is_test_mode_);
download_fetcher->set_check_certificate(CertificateChecker::kDownload);
shared_ptr<DownloadAction> download_action(
new DownloadAction(prefs_,
@@ -397,7 +402,8 @@
new OmahaEvent(
OmahaEvent::kTypeUpdateDownloadFinished),
new LibcurlHttpFetcher(GetProxyResolver(),
- system_state_),
+ system_state_,
+ is_test_mode_),
false));
shared_ptr<FilesystemCopierAction> filesystem_verifier_action(
new FilesystemCopierAction(false, true, 0));
@@ -410,7 +416,8 @@
&omaha_request_params_,
new OmahaEvent(OmahaEvent::kTypeUpdateComplete),
new LibcurlHttpFetcher(GetProxyResolver(),
- system_state_),
+ system_state_,
+ is_test_mode_),
false));
download_action->set_delegate(this);
@@ -469,16 +476,16 @@
// Read GPIO signals and determine whether this is an automated test scenario.
// For safety, we only allow a test update to be performed once; subsequent
// update requests will be carried out normally.
- bool is_test = (!is_test_update_attempted_ && gpio_handler_ &&
- gpio_handler_->IsTestModeSignaled());
- if (is_test) {
- LOG(INFO) << "test mode signaled";
+ bool is_test_mode = (!is_test_update_attempted_ && gpio_handler_ &&
+ gpio_handler_->IsTestModeSignaled());
+ if (is_test_mode) {
+ LOG(WARNING) << "this is a test mode update attempt!";
is_test_update_attempted_ = true;
}
// Passing true for is_user_initiated to indicate that this
// is not a scheduled update check.
- Update(app_version, omaha_url, true, true, is_test, is_user_initiated);
+ Update(app_version, omaha_url, true, true, is_test_mode, is_user_initiated);
}
bool UpdateAttempter::RebootIfNeeded() {
@@ -798,7 +805,8 @@
&omaha_request_params_,
error_event_.release(), // Pass ownership.
new LibcurlHttpFetcher(GetProxyResolver(),
- system_state_),
+ system_state_,
+ is_test_mode_),
false));
actions_.push_back(shared_ptr<AbstractAction>(error_event_action));
processor_->EnqueueAction(error_event_action.get());
@@ -913,7 +921,8 @@
&omaha_request_params_,
NULL,
new LibcurlHttpFetcher(GetProxyResolver(),
- system_state_),
+ system_state_,
+ is_test_mode_),
true));
actions_.push_back(shared_ptr<OmahaRequestAction>(ping_action));
processor_->set_delegate(NULL);
diff --git a/update_attempter.h b/update_attempter.h
index 77af499..1ab8352 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -80,7 +80,7 @@
const std::string& omaha_url,
bool obey_proxies,
bool interactive,
- bool is_test,
+ bool is_test_mode,
bool is_user_initiated);
// ActionProcessorDelegate methods:
@@ -335,6 +335,9 @@
// A flag for indicating whether we are using a test server URL.
bool is_using_test_url_;
+ // If true, will induce a test mode update attempt.
+ bool is_test_mode_;
+
// A flag indicating whether a test update cycle was already attempted.
bool is_test_update_attempted_;
diff --git a/update_check_scheduler.cc b/update_check_scheduler.cc
index be599ab..074cb4a 100644
--- a/update_check_scheduler.cc
+++ b/update_check_scheduler.cc
@@ -90,12 +90,12 @@
CHECK(me->scheduled_);
me->scheduled_ = false;
- bool is_test = false;
+ bool is_test_mode = false;
if (me->system_state_->IsOOBEComplete() ||
- (is_test = (!me->is_test_update_attempted_ &&
- me->gpio_handler_ &&
- me->gpio_handler_->IsTestModeSignaled()))) {
- if (is_test) {
+ (is_test_mode = (!me->is_test_update_attempted_ &&
+ me->gpio_handler_ &&
+ me->gpio_handler_->IsTestModeSignaled()))) {
+ if (is_test_mode) {
LOG(WARNING)
<< "test mode signaled, allowing update check prior to OOBE complete";
me->is_test_update_attempted_ = true;
@@ -103,7 +103,7 @@
// Before updating, we flush any previously generated UMA reports.
CertificateChecker::FlushReport();
- me->update_attempter_->Update("", "", false, false, is_test, false);
+ me->update_attempter_->Update("", "", false, false, is_test_mode, false);
} 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.