Classify errors and advance URL index according to the error code.

In CL https://gerrit.chromium.org/gerrit/39638, we always incremented
the URL index irrespective of the error code. That would cause the first
URL to be given up too quickly in favor of the second one even for
transient errors such as when user closes a lid and reopens after some
time.

The right behavior in this case is to just count those failures towards
the URL and only after repeated failures with no progress should we
advance the URL index.

This CL implements this logic and completes the multiple URL-related
work items outlined in the design doc.

BUG=chromium-os:37206
TEST=Tested all uses cases on my ZGB. Added and updated unit tests.

Change-Id: Ida0cfbfeb9bfab732144049d1b27e3b8958bc252
Reviewed-on: https://gerrit.chromium.org/gerrit/39885
Commit-Queue: Jay Srinivasan <jaysri@chromium.org>
Reviewed-by: Jay Srinivasan <jaysri@chromium.org>
Tested-by: Jay Srinivasan <jaysri@chromium.org>
diff --git a/payload_state_interface.h b/payload_state_interface.h
new file mode 100644
index 0000000..031fbec
--- /dev/null
+++ b/payload_state_interface.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_PAYLOAD_STATE_INTERFACE_H__
+#define CHROMEOS_PLATFORM_UPDATE_ENGINE_PAYLOAD_STATE_INTERFACE_H__
+
+#include <string>
+
+#include "update_engine/action_processor.h"
+
+namespace chromeos_update_engine {
+
+// Forward declaration here because we get a circular dependency if
+// we include omaha_request_action.h directly.
+struct OmahaResponse;
+
+// Describes the methods that need to be implemented by the PayloadState class.
+// This interface has been carved out to support mocking of the PayloadState
+// object.
+class PayloadStateInterface {
+ public:
+  // Sets the internal payload state based on the given Omaha response. This
+  // response could be the same or different from the one for which we've stored
+  // the internal state. If it's different, then this method resets all the
+  // internal state corresponding to the old response. Since the Omaha response
+  // has a lot of fields that are not related to payload state, it uses only
+  // a subset of the fields in the Omaha response to compare equality.
+  virtual void SetResponse(const OmahaResponse& response) = 0;
+
+  // This method should be called whenever we have completed downloading all
+  // the bytes of a payload and have verified that its size and hash match the
+  // expected values. We use this notificaiton to increment the payload attempt
+  // number so that the throttle the next attempt to download the same payload
+  // (in case there's an error in subsequent steps such as post-install)
+  // appropriately.
+  virtual void DownloadComplete() = 0;
+
+  // This method should be called whenever we receive new bytes from the
+  // network for the current payload. We use this notification to reset the
+  // failure count for a given URL since receipt of some bytes means we are
+  // able to make forward progress with the current URL.
+  virtual void DownloadProgress(size_t count) = 0;
+
+  // This method should be called whenever an update attempt fails with the
+  // given error code. We use this notification to update the payload state
+  // depending on the type of the error that happened.
+  virtual void UpdateFailed(ActionExitCode error) = 0;
+
+  // Returns the currently stored response.
+  virtual std::string GetResponse() = 0;
+
+  // Returns the payload attempt number.
+  virtual uint32_t GetPayloadAttemptNumber() = 0;
+
+  // Returns the current URL index.
+  virtual uint32_t GetUrlIndex() = 0;
+
+  // Returns the current URL's failure count.
+  virtual uint32_t GetUrlFailureCount() = 0;
+ };
+
+}  // namespace chromeos_update_engine
+
+#endif  // CHROMEOS_PLATFORM_UPDATE_ENGINE_PAYLOAD_STATE_INTERFACE_H__