Move GCMDecryptionResult to its own file

It's used in places beyond the GCMEncryptionProvider now, and might be
exposed to GCM app handlers in the future, so let's factor it out.

BUG=678347

Change-Id: I2301c05b403a4ec52d04e45616988ff40f270fde
Reviewed-on: https://chromium-review.googlesource.com/550155
Commit-Queue: Peter Beverloo <[email protected]>
Reviewed-by: Anita Woodruff <[email protected]>
Cr-Commit-Position: refs/heads/master@{#482657}
diff --git a/components/gcm_driver/crypto/BUILD.gn b/components/gcm_driver/crypto/BUILD.gn
index 20d24ee..5ee3c7d 100644
--- a/components/gcm_driver/crypto/BUILD.gn
+++ b/components/gcm_driver/crypto/BUILD.gn
@@ -8,6 +8,8 @@
   sources = [
     "encryption_header_parsers.cc",
     "encryption_header_parsers.h",
+    "gcm_decryption_result.cc",
+    "gcm_decryption_result.h",
     "gcm_encryption_provider.cc",
     "gcm_encryption_provider.h",
     "gcm_key_store.cc",
diff --git a/components/gcm_driver/crypto/gcm_decryption_result.cc b/components/gcm_driver/crypto/gcm_decryption_result.cc
new file mode 100644
index 0000000..099e7f5
--- /dev/null
+++ b/components/gcm_driver/crypto/gcm_decryption_result.cc
@@ -0,0 +1,39 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/gcm_driver/crypto/gcm_decryption_result.h"
+
+#include "base/logging.h"
+
+namespace gcm {
+
+std::string ToGCMDecryptionResultDetailsString(GCMDecryptionResult result) {
+  switch (result) {
+    case GCMDecryptionResult::UNENCRYPTED:
+      return "Message was not encrypted";
+    case GCMDecryptionResult::DECRYPTED_DRAFT_03:
+      return "Message decrypted (draft 03)";
+    case GCMDecryptionResult::DECRYPTED_DRAFT_08:
+      return "Message decrypted (draft 08)";
+    case GCMDecryptionResult::INVALID_ENCRYPTION_HEADER:
+      return "Invalid format for the Encryption header";
+    case GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER:
+      return "Invalid format for the Crypto-Key header";
+    case GCMDecryptionResult::NO_KEYS:
+      return "There are no associated keys with the subscription";
+    case GCMDecryptionResult::INVALID_SHARED_SECRET:
+      return "The shared secret cannot be derived from the keying material";
+    case GCMDecryptionResult::INVALID_PAYLOAD:
+      return "AES-GCM decryption failed";
+    case GCMDecryptionResult::INVALID_BINARY_HEADER:
+      return "The message's binary header could not be parsed.";
+    case GCMDecryptionResult::ENUM_SIZE:
+      break;  // deliberate fall-through
+  }
+
+  NOTREACHED();
+  return "(invalid result)";
+}
+
+}  // namespace gcm
diff --git a/components/gcm_driver/crypto/gcm_decryption_result.h b/components/gcm_driver/crypto/gcm_decryption_result.h
new file mode 100644
index 0000000..0126a5a6
--- /dev/null
+++ b/components/gcm_driver/crypto/gcm_decryption_result.h
@@ -0,0 +1,58 @@
+// Copyright 2017 The Chromium 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 COMPONENTS_GCM_DRIVER_CRYPTO_GCM_DECRYPTION_RESULT_H_
+#define COMPONENTS_GCM_DRIVER_CRYPTO_GCM_DECRYPTION_RESULT_H_
+
+#include <string>
+
+namespace gcm {
+
+// Result of decrypting an incoming message. The values of these reasons must
+// not be changed as they are being recorded using UMA. When adding a value,
+// please update GCMDecryptionResult in //tools/metrics/histograms/enums.xml.
+enum class GCMDecryptionResult {
+  // The message had not been encrypted by the sender.
+  UNENCRYPTED = 0,
+
+  // The message had been encrypted by the sender, and could successfully be
+  // decrypted for the registration it has been received for. The encryption
+  // scheme used for the message was draft-ietf-webpush-encryption-03.
+  DECRYPTED_DRAFT_03 = 1,
+
+  // The contents of the Encryption HTTP header could not be parsed.
+  INVALID_ENCRYPTION_HEADER = 2,
+
+  // The contents of the Crypto-Key HTTP header could not be parsed.
+  INVALID_CRYPTO_KEY_HEADER = 3,
+
+  // No public/private key-pair was associated with the app_id.
+  NO_KEYS = 4,
+
+  // The shared secret cannot be derived from the keying material.
+  INVALID_SHARED_SECRET = 5,
+
+  // The payload could not be decrypted as AES-128-GCM.
+  INVALID_PAYLOAD = 6,
+
+  // The binary header leading the ciphertext could not be parsed. Only
+  // applicable to messages encrypted per draft-ietf-webpush-encryption-08.
+  INVALID_BINARY_HEADER = 7,
+
+  // The message had been encrypted by the sender, and could successfully be
+  // decrypted for the registration it has been received for. The encryption
+  // scheme used for the message was draft-ietf-webpush-encryption-08.
+  DECRYPTED_DRAFT_08 = 8,
+
+  // Should be one more than the otherwise highest value in this enumeration.
+  ENUM_SIZE = DECRYPTED_DRAFT_08 + 1
+};
+
+// Converts the GCMDecryptionResult value to a string that can be used to
+// explain the issue on chrome://gcm-internals/.
+std::string ToGCMDecryptionResultDetailsString(GCMDecryptionResult result);
+
+}  // namespace gcm
+
+#endif  // COMPONENTS_GCM_DRIVER_CRYPTO_GCM_DECRYPTION_RESULT_H_
diff --git a/components/gcm_driver/crypto/gcm_encryption_provider.cc b/components/gcm_driver/crypto/gcm_encryption_provider.cc
index 6a4bdc5f..20f6d8e4 100644
--- a/components/gcm_driver/crypto/gcm_encryption_provider.cc
+++ b/components/gcm_driver/crypto/gcm_encryption_provider.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "components/gcm_driver/common/gcm_messages.h"
 #include "components/gcm_driver/crypto/encryption_header_parsers.h"
+#include "components/gcm_driver/crypto/gcm_decryption_result.h"
 #include "components/gcm_driver/crypto/gcm_key_store.h"
 #include "components/gcm_driver/crypto/gcm_message_cryptographer.h"
 #include "components/gcm_driver/crypto/message_payload_parser.h"
@@ -34,33 +35,6 @@
 
 }  // namespace
 
-std::string GCMEncryptionProvider::ToDecryptionResultDetailsString(
-    DecryptionResult result) {
-  switch (result) {
-    case DECRYPTION_RESULT_UNENCRYPTED:
-      return "Message was not encrypted";
-    case DECRYPTION_RESULT_DECRYPTED_DRAFT_03:
-      return "Message decrypted (draft 03)";
-    case DECRYPTION_RESULT_DECRYPTED_DRAFT_08:
-      return "Message decrypted (draft 08)";
-    case DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER:
-      return "Invalid format for the Encryption header";
-    case DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER:
-      return "Invalid format for the Crypto-Key header";
-    case DECRYPTION_RESULT_NO_KEYS:
-      return "There are no associated keys with the subscription";
-    case DECRYPTION_RESULT_INVALID_SHARED_SECRET:
-      return "The shared secret cannot be derived from the keying material";
-    case DECRYPTION_RESULT_INVALID_PAYLOAD:
-      return "AES-GCM decryption failed";
-    case DECRYPTION_RESULT_INVALID_BINARY_HEADER:
-      return "The message's binary header could not be parsed.";
-  }
-
-  NOTREACHED();
-  return "(invalid result)";
-}
-
 GCMEncryptionProvider::GCMEncryptionProvider()
     : weak_ptr_factory_(this) {
 }
@@ -129,7 +103,7 @@
     const MessageCallback& callback) {
   DCHECK(key_store_);
   if (!IsEncryptedMessage(message)) {
-    callback.Run(DECRYPTION_RESULT_UNENCRYPTED, message);
+    callback.Run(GCMDecryptionResult::UNENCRYPTED, message);
     return;
   }
 
@@ -146,7 +120,8 @@
     MessagePayloadParser parser(message.raw_data);
     if (!parser.IsValid()) {
       DLOG(ERROR) << "Unable to parse the message's binary header";
-      callback.Run(DECRYPTION_RESULT_INVALID_BINARY_HEADER, IncomingMessage());
+      callback.Run(GCMDecryptionResult::INVALID_BINARY_HEADER,
+                   IncomingMessage());
       return;
     }
 
@@ -170,7 +145,7 @@
         encryption_header->second.begin(), encryption_header->second.end());
     if (!encryption_header_iterator.GetNext()) {
       DLOG(ERROR) << "Unable to parse the value of the Encryption header";
-      callback.Run(DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER,
+      callback.Run(GCMDecryptionResult::INVALID_ENCRYPTION_HEADER,
                    IncomingMessage());
       return;
     }
@@ -178,7 +153,7 @@
     if (encryption_header_iterator.salt().size() !=
         GCMMessageCryptographer::kSaltSize) {
       DLOG(ERROR) << "Invalid values supplied in the Encryption header";
-      callback.Run(DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER,
+      callback.Run(GCMDecryptionResult::INVALID_ENCRYPTION_HEADER,
                    IncomingMessage());
       return;
     }
@@ -190,7 +165,7 @@
         crypto_key_header->second.begin(), crypto_key_header->second.end());
     if (!crypto_key_header_iterator.GetNext()) {
       DLOG(ERROR) << "Unable to parse the value of the Crypto-Key header";
-      callback.Run(DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER,
+      callback.Run(GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER,
                    IncomingMessage());
       return;
     }
@@ -219,7 +194,7 @@
 
     if (!valid_crypto_key_header) {
       DLOG(ERROR) << "Invalid values supplied in the Crypto-Key header";
-      callback.Run(DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER,
+      callback.Run(GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER,
                    IncomingMessage());
       return;
     }
@@ -284,7 +259,7 @@
     const std::string& auth_secret) {
   if (!pair.IsInitialized()) {
     DLOG(ERROR) << "Unable to retrieve the keys for the incoming message.";
-    callback.Run(DECRYPTION_RESULT_NO_KEYS, IncomingMessage());
+    callback.Run(GCMDecryptionResult::NO_KEYS, IncomingMessage());
     return;
   }
 
@@ -294,7 +269,7 @@
   if (!ComputeSharedP256Secret(pair.private_key(), pair.public_key_x509(),
                                public_key, &shared_secret)) {
     DLOG(ERROR) << "Unable to calculate the shared secret.";
-    callback.Run(DECRYPTION_RESULT_INVALID_SHARED_SECRET, IncomingMessage());
+    callback.Run(GCMDecryptionResult::INVALID_SHARED_SECRET, IncomingMessage());
     return;
   }
 
@@ -306,7 +281,7 @@
                              auth_secret, salt, ciphertext, record_size,
                              &plaintext)) {
     DLOG(ERROR) << "Unable to decrypt the incoming data.";
-    callback.Run(DECRYPTION_RESULT_INVALID_PAYLOAD, IncomingMessage());
+    callback.Run(GCMDecryptionResult::INVALID_PAYLOAD, IncomingMessage());
     return;
   }
 
@@ -321,8 +296,8 @@
   DCHECK_EQ(0u, decrypted_message.data.size());
 
   callback.Run(version == GCMMessageCryptographer::Version::DRAFT_03
-                   ? DECRYPTION_RESULT_DECRYPTED_DRAFT_03
-                   : DECRYPTION_RESULT_DECRYPTED_DRAFT_08,
+                   ? GCMDecryptionResult::DECRYPTED_DRAFT_03
+                   : GCMDecryptionResult::DECRYPTED_DRAFT_08,
                decrypted_message);
 }
 
diff --git a/components/gcm_driver/crypto/gcm_encryption_provider.h b/components/gcm_driver/crypto/gcm_encryption_provider.h
index 65c1c9cc..7d65b17e0 100644
--- a/components/gcm_driver/crypto/gcm_encryption_provider.h
+++ b/components/gcm_driver/crypto/gcm_encryption_provider.h
@@ -23,6 +23,7 @@
 
 namespace gcm {
 
+enum class GCMDecryptionResult;
 class GCMKeyStore;
 struct IncomingMessage;
 class KeyPair;
@@ -31,44 +32,6 @@
 // and decryption of incoming messages.
 class GCMEncryptionProvider {
  public:
-  // Result of decrypting an incoming message. The values of these reasons must
-  // not be changed, because they are being recorded using UMA.
-  enum DecryptionResult {
-    // The message had not been encrypted by the sender.
-    DECRYPTION_RESULT_UNENCRYPTED = 0,
-
-    // The message had been encrypted by the sender, and could successfully be
-    // decrypted for the registration it has been received for. The encryption
-    // scheme used for the message was draft-ietf-webpush-encryption-03.
-    DECRYPTION_RESULT_DECRYPTED_DRAFT_03 = 1,
-
-    // The contents of the Encryption HTTP header could not be parsed.
-    DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER = 2,
-
-    // The contents of the Crypto-Key HTTP header could not be parsed.
-    DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER = 3,
-
-    // No public/private key-pair was associated with the app_id.
-    DECRYPTION_RESULT_NO_KEYS = 4,
-
-    // The shared secret cannot be derived from the keying material.
-    DECRYPTION_RESULT_INVALID_SHARED_SECRET = 5,
-
-    // The payload could not be decrypted as AES-128-GCM.
-    DECRYPTION_RESULT_INVALID_PAYLOAD = 6,
-
-    // The binary header leading the ciphertext could not be parsed. Only
-    // applicable to messages encrypted per draft-ietf-webpush-encryption-08.
-    DECRYPTION_RESULT_INVALID_BINARY_HEADER = 7,
-
-    // The message had been encrypted by the sender, and could successfully be
-    // decrypted for the registration it has been received for. The encryption
-    // scheme used for the message was draft-ietf-webpush-encryption-08.
-    DECRYPTION_RESULT_DECRYPTED_DRAFT_08 = 8,
-
-    DECRYPTION_RESULT_LAST = DECRYPTION_RESULT_DECRYPTED_DRAFT_08
-  };
-
   // Callback to be invoked when the public key and auth secret are available.
   using EncryptionInfoCallback =
       base::Callback<void(const std::string& p256dh,
@@ -77,12 +40,9 @@
   // Callback to be invoked when a message may have been decrypted, as indicated
   // by the |result|. The |message| contains the dispatchable message in success
   // cases, or will be initialized to an empty, default state for failure.
-  using MessageCallback = base::Callback<void(DecryptionResult result,
+  using MessageCallback = base::Callback<void(GCMDecryptionResult result,
                                               const IncomingMessage& message)>;
 
-  // Converts |result| to a string describing the details of said result.
-  static std::string ToDecryptionResultDetailsString(DecryptionResult result);
-
   GCMEncryptionProvider();
   ~GCMEncryptionProvider();
 
diff --git a/components/gcm_driver/crypto/gcm_encryption_provider_unittest.cc b/components/gcm_driver/crypto/gcm_encryption_provider_unittest.cc
index 0f0fc0c4..3d18c61f 100644
--- a/components/gcm_driver/crypto/gcm_encryption_provider_unittest.cc
+++ b/components/gcm_driver/crypto/gcm_encryption_provider_unittest.cc
@@ -21,6 +21,7 @@
 #include "base/strings/string_util.h"
 #include "base/test/histogram_tester.h"
 #include "components/gcm_driver/common/gcm_messages.h"
+#include "components/gcm_driver/crypto/gcm_decryption_result.h"
 #include "components/gcm_driver/crypto/gcm_key_store.h"
 #include "components/gcm_driver/crypto/gcm_message_cryptographer.h"
 #include "components/gcm_driver/crypto/p256_key_util.h"
@@ -128,9 +129,7 @@
   }
 
   // Returns the result of the previous decryption operation.
-  GCMEncryptionProvider::DecryptionResult decryption_result() {
-    return decryption_result_;
-  }
+  GCMDecryptionResult decryption_result() { return decryption_result_; }
 
   // Returns the message resulting from the previous decryption operation.
   const IncomingMessage& decrypted_message() { return decrypted_message_; }
@@ -146,7 +145,7 @@
                                GCMMessageCryptographer::Version version);
 
  private:
-  void DidDecryptMessage(GCMEncryptionProvider::DecryptionResult result,
+  void DidDecryptMessage(GCMDecryptionResult result,
                          const IncomingMessage& message) {
     decryption_result_ = result;
     decrypted_message_ = message;
@@ -158,8 +157,7 @@
 
   std::unique_ptr<GCMEncryptionProvider> encryption_provider_;
 
-  GCMEncryptionProvider::DecryptionResult decryption_result_ =
-      GCMEncryptionProvider::DECRYPTION_RESULT_UNENCRYPTED;
+  GCMDecryptionResult decryption_result_ = GCMDecryptionResult::UNENCRYPTED;
 
   IncomingMessage decrypted_message_;
 };
@@ -205,7 +203,7 @@
   invalid_message.raw_data = "foo";
 
   ASSERT_NO_FATAL_FAILURE(Decrypt(invalid_message));
-  EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER,
+  EXPECT_EQ(GCMDecryptionResult::INVALID_ENCRYPTION_HEADER,
             decryption_result());
 
   IncomingMessage valid_message;
@@ -214,7 +212,7 @@
   valid_message.raw_data = "foo";
 
   ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message));
-  EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER,
+  EXPECT_NE(GCMDecryptionResult::INVALID_ENCRYPTION_HEADER,
             decryption_result());
 }
 
@@ -228,7 +226,7 @@
   invalid_message.raw_data = "foo";
 
   ASSERT_NO_FATAL_FAILURE(Decrypt(invalid_message));
-  EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER,
+  EXPECT_EQ(GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER,
             decryption_result());
 
   IncomingMessage valid_message;
@@ -237,7 +235,7 @@
   valid_message.raw_data = "foo";
 
   ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message));
-  EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER,
+  EXPECT_NE(GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER,
             decryption_result());
 }
 
@@ -251,7 +249,7 @@
   valid_message.raw_data = "foo";
 
   ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message));
-  EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER,
+  EXPECT_NE(GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER,
             decryption_result());
 }
 
@@ -265,7 +263,7 @@
   valid_message.raw_data = "foo";
 
   ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message));
-  EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER,
+  EXPECT_EQ(GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER,
             decryption_result());
 }
 
@@ -279,8 +277,7 @@
   message.raw_data = "foo";
 
   ASSERT_NO_FATAL_FAILURE(Decrypt(message));
-  EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_NO_KEYS,
-            decryption_result());
+  EXPECT_EQ(GCMDecryptionResult::NO_KEYS, decryption_result());
 
   std::string public_key, auth_secret;
   encryption_provider()->GetEncryptionInfo(
@@ -295,8 +292,7 @@
   ASSERT_GT(auth_secret.size(), 0u);
 
   ASSERT_NO_FATAL_FAILURE(Decrypt(message));
-  EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_NO_KEYS,
-            decryption_result());
+  EXPECT_NE(GCMDecryptionResult::NO_KEYS, decryption_result());
 }
 
 TEST_F(GCMEncryptionProviderTest, VerifiesKeyRemovalGCMRegistration) {
@@ -566,8 +562,8 @@
   // Decrypt the message, and expect everything to go wonderfully well.
   ASSERT_NO_FATAL_FAILURE(Decrypt(message));
   ASSERT_EQ(version == GCMMessageCryptographer::Version::DRAFT_03
-                ? GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED_DRAFT_03
-                : GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED_DRAFT_08,
+                ? GCMDecryptionResult::DECRYPTED_DRAFT_03
+                : GCMDecryptionResult::DECRYPTED_DRAFT_08,
             decryption_result());
 
   EXPECT_TRUE(decrypted_message().decrypted);
diff --git a/components/gcm_driver/fake_gcm_client.cc b/components/gcm_driver/fake_gcm_client.cc
index 2f992c52..38a1688c97 100644
--- a/components/gcm_driver/fake_gcm_client.cc
+++ b/components/gcm_driver/fake_gcm_client.cc
@@ -166,9 +166,8 @@
                             weak_ptr_factory_.GetWeakPtr(), app_id, message));
 }
 
-void FakeGCMClient::RecordDecryptionFailure(
-    const std::string& app_id,
-    GCMEncryptionProvider::DecryptionResult result) {
+void FakeGCMClient::RecordDecryptionFailure(const std::string& app_id,
+                                            GCMDecryptionResult result) {
   recorder_.RecordDecryptionFailure(app_id, result);
 }
 
diff --git a/components/gcm_driver/fake_gcm_client.h b/components/gcm_driver/fake_gcm_client.h
index 0199b3ab7..9abb5f8 100644
--- a/components/gcm_driver/fake_gcm_client.h
+++ b/components/gcm_driver/fake_gcm_client.h
@@ -62,8 +62,7 @@
             const std::string& receiver_id,
             const OutgoingMessage& message) override;
   void RecordDecryptionFailure(const std::string& app_id,
-                               GCMEncryptionProvider::DecryptionResult result)
-      override;
+                               GCMDecryptionResult result) override;
   void SetRecording(bool recording) override;
   void ClearActivityLogs() override;
   GCMStatistics GetStatistics() const override;
diff --git a/components/gcm_driver/fake_gcm_driver.cc b/components/gcm_driver/fake_gcm_driver.cc
index 9974f92bf..89ceea45 100644
--- a/components/gcm_driver/fake_gcm_driver.cc
+++ b/components/gcm_driver/fake_gcm_driver.cc
@@ -86,10 +86,8 @@
                              const OutgoingMessage& message) {
 }
 
-void FakeGCMDriver::RecordDecryptionFailure(
-    const std::string& app_id,
-    GCMEncryptionProvider::DecryptionResult result) {
-}
+void FakeGCMDriver::RecordDecryptionFailure(const std::string& app_id,
+                                            GCMDecryptionResult result) {}
 
 void FakeGCMDriver::SetAccountTokens(
     const std::vector<GCMClient::AccountTokenInfo>& account_tokens) {
diff --git a/components/gcm_driver/fake_gcm_driver.h b/components/gcm_driver/fake_gcm_driver.h
index 131802e2..ba1664ec 100644
--- a/components/gcm_driver/fake_gcm_driver.h
+++ b/components/gcm_driver/fake_gcm_driver.h
@@ -65,8 +65,7 @@
                 const std::string& receiver_id,
                 const OutgoingMessage& message) override;
   void RecordDecryptionFailure(const std::string& app_id,
-                               GCMEncryptionProvider::DecryptionResult result)
-      override;
+                               GCMDecryptionResult result) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(FakeGCMDriver);
diff --git a/components/gcm_driver/gcm_client.h b/components/gcm_driver/gcm_client.h
index 921c414..64cbd56 100644
--- a/components/gcm_driver/gcm_client.h
+++ b/components/gcm_driver/gcm_client.h
@@ -14,7 +14,6 @@
 
 #include "base/memory/linked_ptr.h"
 #include "components/gcm_driver/common/gcm_messages.h"
-#include "components/gcm_driver/crypto/gcm_encryption_provider.h"
 #include "components/gcm_driver/gcm_activity.h"
 #include "components/gcm_driver/registration_info.h"
 
@@ -33,8 +32,9 @@
 
 namespace gcm {
 
-class Encryptor;
 struct AccountMapping;
+class Encryptor;
+enum class GCMDecryptionResult;
 
 // Interface that encapsulates the network communications with the Google Cloud
 // Messaging server. This interface is not supposed to be thread-safe.
@@ -288,9 +288,8 @@
                     const OutgoingMessage& message) = 0;
 
   // Records a decryption failure due to |result| for the |app_id|.
-  virtual void RecordDecryptionFailure(
-      const std::string& app_id,
-      GCMEncryptionProvider::DecryptionResult result) = 0;
+  virtual void RecordDecryptionFailure(const std::string& app_id,
+                                       GCMDecryptionResult result) = 0;
 
   // Enables or disables internal activity recording.
   virtual void SetRecording(bool recording) = 0;
diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gcm_client_impl.cc
index 8754ba2..9cd3eb9 100644
--- a/components/gcm_driver/gcm_client_impl.cc
+++ b/components/gcm_driver/gcm_client_impl.cc
@@ -24,6 +24,7 @@
 #include "base/time/default_clock.h"
 #include "base/timer/timer.h"
 #include "components/crx_file/id_util.h"
+#include "components/gcm_driver/crypto/gcm_decryption_result.h"
 #include "components/gcm_driver/gcm_account_mapper.h"
 #include "components/gcm_driver/gcm_backoff_policy.h"
 #include "google_apis/gcm/base/encryptor.h"
@@ -1217,9 +1218,8 @@
   return std::string();
 }
 
-void GCMClientImpl::RecordDecryptionFailure(
-    const std::string& app_id,
-    GCMEncryptionProvider::DecryptionResult result) {
+void GCMClientImpl::RecordDecryptionFailure(const std::string& app_id,
+                                            GCMDecryptionResult result) {
   recorder_.RecordDecryptionFailure(app_id, result);
 }
 
diff --git a/components/gcm_driver/gcm_client_impl.h b/components/gcm_driver/gcm_client_impl.h
index 62c4d3b..68c9e2e4 100644
--- a/components/gcm_driver/gcm_client_impl.h
+++ b/components/gcm_driver/gcm_client_impl.h
@@ -125,8 +125,7 @@
             const std::string& receiver_id,
             const OutgoingMessage& message) override;
   void RecordDecryptionFailure(const std::string& app_id,
-                               GCMEncryptionProvider::DecryptionResult result)
-      override;
+                               GCMDecryptionResult result) override;
   void SetRecording(bool recording) override;
   void ClearActivityLogs() override;
   GCMStatistics GetStatistics() const override;
diff --git a/components/gcm_driver/gcm_driver.cc b/components/gcm_driver/gcm_driver.cc
index 0f797f7..c13ae9e 100644
--- a/components/gcm_driver/gcm_driver.cc
+++ b/components/gcm_driver/gcm_driver.cc
@@ -12,6 +12,7 @@
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "components/gcm_driver/crypto/gcm_decryption_result.h"
 #include "components/gcm_driver/gcm_app_handler.h"
 
 namespace gcm {
@@ -279,17 +280,16 @@
                                   weak_ptr_factory_.GetWeakPtr(), app_id));
 }
 
-void GCMDriver::DispatchMessageInternal(
-    const std::string& app_id,
-    GCMEncryptionProvider::DecryptionResult result,
-    const IncomingMessage& message) {
+void GCMDriver::DispatchMessageInternal(const std::string& app_id,
+                                        GCMDecryptionResult result,
+                                        const IncomingMessage& message) {
   UMA_HISTOGRAM_ENUMERATION("GCM.Crypto.DecryptMessageResult", result,
-                            GCMEncryptionProvider::DECRYPTION_RESULT_LAST + 1);
+                            GCMDecryptionResult::ENUM_SIZE);
 
   switch (result) {
-    case GCMEncryptionProvider::DECRYPTION_RESULT_UNENCRYPTED:
-    case GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED_DRAFT_03:
-    case GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED_DRAFT_08: {
+    case GCMDecryptionResult::UNENCRYPTED:
+    case GCMDecryptionResult::DECRYPTED_DRAFT_03:
+    case GCMDecryptionResult::DECRYPTED_DRAFT_08: {
       GCMAppHandler* handler = GetAppHandler(app_id);
       if (handler)
         handler->OnMessage(app_id, message);
@@ -298,14 +298,16 @@
       // chrome://gcm-internals and send a delivery receipt.
       return;
     }
-    case GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER:
-    case GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER:
-    case GCMEncryptionProvider::DECRYPTION_RESULT_NO_KEYS:
-    case GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_SHARED_SECRET:
-    case GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_PAYLOAD:
-    case GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_BINARY_HEADER:
+    case GCMDecryptionResult::INVALID_ENCRYPTION_HEADER:
+    case GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER:
+    case GCMDecryptionResult::NO_KEYS:
+    case GCMDecryptionResult::INVALID_SHARED_SECRET:
+    case GCMDecryptionResult::INVALID_PAYLOAD:
+    case GCMDecryptionResult::INVALID_BINARY_HEADER:
       RecordDecryptionFailure(app_id, result);
       return;
+    case GCMDecryptionResult::ENUM_SIZE:
+      break;  // deliberate fall-through
   }
 
   NOTREACHED();
diff --git a/components/gcm_driver/gcm_driver.h b/components/gcm_driver/gcm_driver.h
index 8d671b7d..0bdb150 100644
--- a/components/gcm_driver/gcm_driver.h
+++ b/components/gcm_driver/gcm_driver.h
@@ -27,6 +27,7 @@
 
 class GCMAppHandler;
 class GCMConnectionObserver;
+enum class GCMDecryptionResult;
 struct AccountMapping;
 
 // Provides the InstanceID support via GCMDriver.
@@ -279,9 +280,8 @@
                         const OutgoingMessage& message) = 0;
 
   // Platform-specific implementation of recording message decryption failures.
-  virtual void RecordDecryptionFailure(
-      const std::string& app_id,
-      GCMEncryptionProvider::DecryptionResult result) = 0;
+  virtual void RecordDecryptionFailure(const std::string& app_id,
+                                       GCMDecryptionResult result) = 0;
 
   // Runs the Register callback.
   void RegisterFinished(const std::string& app_id,
@@ -323,7 +323,7 @@
   // if |result| indicates that it is safe to do so, or will report a decryption
   // failure for the |app_id| otherwise.
   void DispatchMessageInternal(const std::string& app_id,
-                               GCMEncryptionProvider::DecryptionResult result,
+                               GCMDecryptionResult result,
                                const IncomingMessage& message);
 
   // Called after unregistration completes in order to trigger the pending
diff --git a/components/gcm_driver/gcm_driver_android.cc b/components/gcm_driver/gcm_driver_android.cc
index b7230f2..702ac28 100644
--- a/components/gcm_driver/gcm_driver_android.cc
+++ b/components/gcm_driver/gcm_driver_android.cc
@@ -267,9 +267,8 @@
   NOTIMPLEMENTED();
 }
 
-void GCMDriverAndroid::RecordDecryptionFailure(
-    const std::string& app_id,
-    GCMEncryptionProvider::DecryptionResult result) {
+void GCMDriverAndroid::RecordDecryptionFailure(const std::string& app_id,
+                                               GCMDecryptionResult result) {
   recorder_.RecordDecryptionFailure(app_id, result);
 }
 
diff --git a/components/gcm_driver/gcm_driver_android.h b/components/gcm_driver/gcm_driver_android.h
index fb37f754..7cfcd63 100644
--- a/components/gcm_driver/gcm_driver_android.h
+++ b/components/gcm_driver/gcm_driver_android.h
@@ -99,8 +99,7 @@
                 const std::string& receiver_id,
                 const OutgoingMessage& message) override;
   void RecordDecryptionFailure(const std::string& app_id,
-                               GCMEncryptionProvider::DecryptionResult result)
-      override;
+                               GCMDecryptionResult result) override;
 
  private:
   base::android::ScopedJavaGlobalRef<jobject> java_ref_;
diff --git a/components/gcm_driver/gcm_driver_desktop.cc b/components/gcm_driver/gcm_driver_desktop.cc
index 9c3fa552..67867c3 100644
--- a/components/gcm_driver/gcm_driver_desktop.cc
+++ b/components/gcm_driver/gcm_driver_desktop.cc
@@ -114,7 +114,7 @@
                    const std::string& scope);
 
   void RecordDecryptionFailure(const std::string& app_id,
-                               GCMEncryptionProvider::DecryptionResult result);
+                               GCMDecryptionResult result);
 
   // For testing purpose. Can be called from UI thread. Use with care.
   GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); }
@@ -518,7 +518,7 @@
 
 void GCMDriverDesktop::IOWorker::RecordDecryptionFailure(
     const std::string& app_id,
-    GCMEncryptionProvider::DecryptionResult result) {
+    GCMDecryptionResult result) {
   DCHECK(io_thread_->RunsTasksInCurrentSequence());
   gcm_client_->RecordDecryptionFailure(app_id, result);
 }
@@ -798,9 +798,8 @@
                  message));
 }
 
-void GCMDriverDesktop::RecordDecryptionFailure(
-    const std::string& app_id,
-    GCMEncryptionProvider::DecryptionResult result) {
+void GCMDriverDesktop::RecordDecryptionFailure(const std::string& app_id,
+                                               GCMDecryptionResult result) {
   DCHECK(ui_thread_->RunsTasksInCurrentSequence());
   io_thread_->PostTask(
       FROM_HERE,
diff --git a/components/gcm_driver/gcm_driver_desktop.h b/components/gcm_driver/gcm_driver_desktop.h
index c7568035..90e5d1c 100644
--- a/components/gcm_driver/gcm_driver_desktop.h
+++ b/components/gcm_driver/gcm_driver_desktop.h
@@ -17,6 +17,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/tuple.h"
+#include "components/gcm_driver/crypto/gcm_decryption_result.h"
 #include "components/gcm_driver/gcm_channel_status_syncer.h"
 #include "components/gcm_driver/gcm_client.h"
 #include "components/gcm_driver/gcm_connection_observer.h"
@@ -38,6 +39,7 @@
 class GCMAccountMapper;
 class GCMAppHandler;
 class GCMClientFactory;
+enum class GCMDecryptionResult;
 class GCMDelayedTaskController;
 
 // GCMDriver implementation for desktop and Chrome OS, using GCMClient.
@@ -107,8 +109,7 @@
                 const std::string& receiver_id,
                 const OutgoingMessage& message) override;
   void RecordDecryptionFailure(const std::string& app_id,
-                               GCMEncryptionProvider::DecryptionResult result)
-      override;
+                               GCMDecryptionResult result) override;
 
   // InstanceIDHandler implementation:
   void GetToken(const std::string& app_id,
diff --git a/components/gcm_driver/gcm_stats_recorder_android.cc b/components/gcm_driver/gcm_stats_recorder_android.cc
index fedd7ba..dc3137be 100644
--- a/components/gcm_driver/gcm_stats_recorder_android.cc
+++ b/components/gcm_driver/gcm_stats_recorder_android.cc
@@ -4,6 +4,7 @@
 
 #include <stddef.h>
 
+#include "components/gcm_driver/crypto/gcm_decryption_result.h"
 #include "components/gcm_driver/gcm_stats_recorder_android.h"
 
 namespace gcm {
@@ -125,19 +126,16 @@
 
 void GCMStatsRecorderAndroid::RecordDecryptionFailure(
     const std::string& app_id,
-    GCMEncryptionProvider::DecryptionResult result) {
-  DCHECK_NE(result, GCMEncryptionProvider::DECRYPTION_RESULT_UNENCRYPTED);
-  DCHECK_NE(result,
-            GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED_DRAFT_03);
-  DCHECK_NE(result,
-            GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED_DRAFT_08);
+    GCMDecryptionResult result) {
+  DCHECK_NE(result, GCMDecryptionResult::UNENCRYPTED);
+  DCHECK_NE(result, GCMDecryptionResult::DECRYPTED_DRAFT_03);
+  DCHECK_NE(result, GCMDecryptionResult::DECRYPTED_DRAFT_08);
   if (!is_recording_)
     return;
 
   DecryptionFailureActivity activity;
   activity.app_id = app_id;
-  activity.details =
-      GCMEncryptionProvider::ToDecryptionResultDetailsString(result);
+  activity.details = ToGCMDecryptionResultDetailsString(result);
 
   decryption_failure_activities_.push_front(activity);
   if (decryption_failure_activities_.size() > MAX_LOGGED_ACTIVITY_COUNT)
diff --git a/components/gcm_driver/gcm_stats_recorder_android.h b/components/gcm_driver/gcm_stats_recorder_android.h
index 64d0575..6a0c79a 100644
--- a/components/gcm_driver/gcm_stats_recorder_android.h
+++ b/components/gcm_driver/gcm_stats_recorder_android.h
@@ -9,11 +9,12 @@
 #include <string>
 
 #include "base/macros.h"
-#include "components/gcm_driver/crypto/gcm_encryption_provider.h"
 #include "components/gcm_driver/gcm_activity.h"
 
 namespace gcm {
 
+enum class GCMDecryptionResult;
+
 // Stats recorder for Android, used for recording stats and activities on the
 // GCM Driver level for debugging purposes. Based on the GCMStatsRecorder, as
 // defined in the GCM Engine, which does not exist on Android.
@@ -62,7 +63,7 @@
 
   // Records a message decryption failure caused by |result| for |app_id|.
   void RecordDecryptionFailure(const std::string& app_id,
-                               GCMEncryptionProvider::DecryptionResult result);
+                               GCMDecryptionResult result);
 
   bool is_recording() const { return is_recording_; }
   void set_is_recording(bool recording) { is_recording_ = recording; }
diff --git a/components/gcm_driver/gcm_stats_recorder_android_unittest.cc b/components/gcm_driver/gcm_stats_recorder_android_unittest.cc
index e7b3267..d789e769 100644
--- a/components/gcm_driver/gcm_stats_recorder_android_unittest.cc
+++ b/components/gcm_driver/gcm_stats_recorder_android_unittest.cc
@@ -6,7 +6,7 @@
 
 #include <stddef.h>
 
-#include "components/gcm_driver/crypto/gcm_encryption_provider.h"
+#include "components/gcm_driver/crypto/gcm_decryption_result.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace gcm {
@@ -58,8 +58,8 @@
                                      42 /* message_byte_size */);
   EXPECT_EQ(5u, activity_recorded_calls());
 
-  recorder.RecordDecryptionFailure(
-      kTestAppId, GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_PAYLOAD);
+  recorder.RecordDecryptionFailure(kTestAppId,
+                                   GCMDecryptionResult::INVALID_PAYLOAD);
   EXPECT_EQ(6u, activity_recorded_calls());
 
   RecordedActivities activities;
diff --git a/components/gcm_driver/gcm_stats_recorder_impl.cc b/components/gcm_driver/gcm_stats_recorder_impl.cc
index 14544a9..cf511d8 100644
--- a/components/gcm_driver/gcm_stats_recorder_impl.cc
+++ b/components/gcm_driver/gcm_stats_recorder_impl.cc
@@ -12,6 +12,8 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "components/gcm_driver/crypto/gcm_decryption_result.h"
+#include "components/gcm_driver/crypto/gcm_encryption_provider.h"
 
 namespace gcm {
 
@@ -187,14 +189,11 @@
     delegate_->OnActivityRecorded();
 }
 
-void GCMStatsRecorderImpl::RecordDecryptionFailure(
-    const std::string& app_id,
-    GCMEncryptionProvider::DecryptionResult result) {
-  DCHECK_NE(result, GCMEncryptionProvider::DECRYPTION_RESULT_UNENCRYPTED);
-  DCHECK_NE(result,
-            GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED_DRAFT_03);
-  DCHECK_NE(result,
-            GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED_DRAFT_08);
+void GCMStatsRecorderImpl::RecordDecryptionFailure(const std::string& app_id,
+                                                   GCMDecryptionResult result) {
+  DCHECK_NE(result, GCMDecryptionResult::UNENCRYPTED);
+  DCHECK_NE(result, GCMDecryptionResult::DECRYPTED_DRAFT_03);
+  DCHECK_NE(result, GCMDecryptionResult::DECRYPTED_DRAFT_08);
   if (!is_recording_)
     return;
 
@@ -202,8 +201,7 @@
   DecryptionFailureActivity* inserted_data = InsertCircularBuffer(
       &decryption_failure_activities_, data);
   inserted_data->app_id = app_id;
-  inserted_data->details =
-      GCMEncryptionProvider::ToDecryptionResultDetailsString(result);
+  inserted_data->details = ToGCMDecryptionResultDetailsString(result);
 
   NotifyActivityRecorded();
 }
diff --git a/components/gcm_driver/gcm_stats_recorder_impl.h b/components/gcm_driver/gcm_stats_recorder_impl.h
index a2c46d1f..77af2970 100644
--- a/components/gcm_driver/gcm_stats_recorder_impl.h
+++ b/components/gcm_driver/gcm_stats_recorder_impl.h
@@ -13,7 +13,6 @@
 
 #include "base/macros.h"
 #include "base/time/time.h"
-#include "components/gcm_driver/crypto/gcm_encryption_provider.h"
 #include "components/gcm_driver/gcm_activity.h"
 #include "google_apis/gcm/engine/connection_factory.h"
 #include "google_apis/gcm/engine/mcs_client.h"
@@ -23,6 +22,8 @@
 
 namespace gcm {
 
+enum class GCMDecryptionResult;
+
 // Records GCM internal stats and activities for debugging purpose. Recording
 // can be turned on/off by calling set_is_recording(...) function. It is turned
 // off by default.
@@ -41,7 +42,7 @@
 
   // Records a message decryption failure caused by |result| for |app_id|.
   void RecordDecryptionFailure(const std::string& app_id,
-                               GCMEncryptionProvider::DecryptionResult result);
+                               GCMDecryptionResult result);
 
   // GCMStatsRecorder implementation:
   void RecordCheckinInitiated(uint64_t android_id) override;
diff --git a/components/gcm_driver/gcm_stats_recorder_impl_unittest.cc b/components/gcm_driver/gcm_stats_recorder_impl_unittest.cc
index eae8909..a73a78b 100644
--- a/components/gcm_driver/gcm_stats_recorder_impl_unittest.cc
+++ b/components/gcm_driver/gcm_stats_recorder_impl_unittest.cc
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include "components/gcm_driver/crypto/gcm_decryption_result.h"
 #include "components/gcm_driver/crypto/gcm_encryption_provider.h"
 #include "google_apis/gcm/engine/mcs_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -99,8 +100,8 @@
 static const char kIncomingSendErrorEvent[] = "Received 'send error' msg";
 static const char kIncomingSendErrorDetails[] = "";
 
-static const GCMEncryptionProvider::DecryptionResult kDecryptionResultFailure =
-    GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_PAYLOAD;
+static const GCMDecryptionResult kDecryptionResultFailure =
+    GCMDecryptionResult::INVALID_PAYLOAD;
 
 }  // namespace
 
@@ -301,10 +302,9 @@
     const auto& queue = recorder_.decryption_failure_activities();
 
     EXPECT_EQ(kAppId, queue.front().app_id) << remark;
-    EXPECT_EQ(
-        GCMEncryptionProvider::ToDecryptionResultDetailsString(
-            kDecryptionResultFailure),
-        queue.front().details) << remark;
+    EXPECT_EQ(ToGCMDecryptionResultDetailsString(kDecryptionResultFailure),
+              queue.front().details)
+        << remark;
   }
 
  protected: