libweave: Copy data_encoding.cc into libweave

It's reducing dependency on libchromeos.

BUG=brillo:1257
TEST=`FEATURES=test emerge-gizmo libweave buffet`

Change-Id: I8356302accb368e717777fd578caa2ba018a29dd
Reviewed-on: https://chromium-review.googlesource.com/293631
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
Trybot-Ready: Vitaly Buka <vitalybuka@chromium.org>
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/libweave/libweave.gyp b/libweave/libweave.gyp
index badd394..8903b28 100644
--- a/libweave/libweave.gyp
+++ b/libweave/libweave.gyp
@@ -17,10 +17,14 @@
     {
       'target_name': 'libweave_external',
       'type': 'static_library',
+      'include_dirs': [
+        '../libweave/third_party/modp_b64/modp_b64/',
+      ],
       'sources': [
         'external/crypto/p224.cc',
         'external/crypto/p224_spake.cc',
         'external/crypto/sha2.cc',
+        'third_party/modp_b64/modp_b64.cc',
       ],
     },
     {
@@ -43,6 +47,7 @@
         'src/commands/schema_constants.cc',
         'src/commands/schema_utils.cc',
         'src/commands/user_role.cc',
+        'src/data_encoding.cc',
         'src/device_manager.cc',
         'src/device_registration_info.cc',
         'src/http_constants.cc',
@@ -132,6 +137,7 @@
             'src/commands/command_queue_unittest.cc',
             'src/commands/object_schema_unittest.cc',
             'src/commands/schema_utils_unittest.cc',
+            'src/data_encoding_unittest.cc',
             'src/device_registration_info_unittest.cc',
             'src/notification/notification_parser_unittest.cc',
             'src/notification/xml_node_unittest.cc',
diff --git a/libweave/src/data_encoding.cc b/libweave/src/data_encoding.cc
new file mode 100644
index 0000000..817cbfc
--- /dev/null
+++ b/libweave/src/data_encoding.cc
@@ -0,0 +1,150 @@
+// Copyright 2014 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.
+
+#include "libweave/src/data_encoding.h"
+
+#include <memory>
+
+#include <base/logging.h>
+#include <base/strings/string_util.h>
+#include <base/strings/stringprintf.h>
+#include <chromeos/strings/string_utils.h>
+
+#include "libweave/third_party/modp_b64/modp_b64/modp_b64.h"
+
+namespace weave {
+
+namespace {
+
+inline int HexToDec(int hex) {
+  int dec = -1;
+  if (hex >= '0' && hex <= '9') {
+    dec = hex - '0';
+  } else if (hex >= 'A' && hex <= 'F') {
+    dec = hex - 'A' + 10;
+  } else if (hex >= 'a' && hex <= 'f') {
+    dec = hex - 'a' + 10;
+  }
+  return dec;
+}
+
+// Helper for Base64Encode() and Base64EncodeWrapLines().
+std::string Base64EncodeHelper(const void* data, size_t size) {
+  std::vector<char> buffer;
+  buffer.resize(modp_b64_encode_len(size));
+  size_t out_size =
+      modp_b64_encode(buffer.data(), static_cast<const char*>(data), size);
+  return std::string{buffer.begin(), buffer.begin() + out_size};
+}
+
+}  // namespace
+
+std::string UrlEncode(const char* data, bool encodeSpaceAsPlus) {
+  std::string result;
+
+  while (*data) {
+    char c = *data++;
+    // According to RFC3986 (http://www.faqs.org/rfcs/rfc3986.html),
+    // section 2.3. - Unreserved Characters
+    if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
+        (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' ||
+        c == '~') {
+      result += c;
+    } else if (c == ' ' && encodeSpaceAsPlus) {
+      // For historical reasons, some URLs have spaces encoded as '+',
+      // this also applies to form data encoded as
+      // 'application/x-www-form-urlencoded'
+      result += '+';
+    } else {
+      base::StringAppendF(&result, "%%%02X",
+                          static_cast<unsigned char>(c));  // Encode as %NN
+    }
+  }
+  return result;
+}
+
+std::string UrlDecode(const char* data) {
+  std::string result;
+  while (*data) {
+    char c = *data++;
+    int part1 = 0, part2 = 0;
+    // HexToDec would return -1 even for character 0 (end of string),
+    // so it is safe to access data[0] and data[1] without overrunning the buf.
+    if (c == '%' && (part1 = HexToDec(data[0])) >= 0 &&
+        (part2 = HexToDec(data[1])) >= 0) {
+      c = static_cast<char>((part1 << 4) | part2);
+      data += 2;
+    } else if (c == '+') {
+      c = ' ';
+    }
+    result += c;
+  }
+  return result;
+}
+
+std::string WebParamsEncode(const WebParamList& params,
+                            bool encodeSpaceAsPlus) {
+  std::vector<std::string> pairs;
+  pairs.reserve(params.size());
+  for (const auto& p : params) {
+    std::string key = UrlEncode(p.first.c_str(), encodeSpaceAsPlus);
+    std::string value = UrlEncode(p.second.c_str(), encodeSpaceAsPlus);
+    pairs.push_back(chromeos::string_utils::Join("=", key, value));
+  }
+
+  return chromeos::string_utils::Join("&", pairs);
+}
+
+WebParamList WebParamsDecode(const std::string& data) {
+  WebParamList result;
+  std::vector<std::string> params = chromeos::string_utils::Split(data, "&");
+  for (const auto& p : params) {
+    auto pair = chromeos::string_utils::SplitAtFirst(p, "=");
+    result.emplace_back(UrlDecode(pair.first.c_str()),
+                        UrlDecode(pair.second.c_str()));
+  }
+  return result;
+}
+
+std::string Base64Encode(const void* data, size_t size) {
+  return Base64EncodeHelper(data, size);
+}
+
+std::string Base64EncodeWrapLines(const void* data, size_t size) {
+  std::string unwrapped = Base64EncodeHelper(data, size);
+  std::string wrapped;
+
+  for (size_t i = 0; i < unwrapped.size(); i += 64) {
+    wrapped.append(unwrapped, i, 64);
+    wrapped.append("\n");
+  }
+  return wrapped;
+}
+
+bool Base64Decode(const std::string& input, chromeos::Blob* output) {
+  std::string temp_buffer;
+  const std::string* data = &input;
+  if (input.find_first_of("\r\n") != std::string::npos) {
+    base::ReplaceChars(input, "\n", "", &temp_buffer);
+    base::ReplaceChars(temp_buffer, "\r", "", &temp_buffer);
+    data = &temp_buffer;
+  }
+  // base64 decoded data has 25% fewer bytes than the original (since every
+  // 3 source octets are encoded as 4 characters in base64).
+  // modp_b64_decode_len provides an upper estimate of the size of the output
+  // data.
+  output->resize(modp_b64_decode_len(data->size()));
+
+  size_t size_read = modp_b64_decode(reinterpret_cast<char*>(output->data()),
+                                     data->data(), data->size());
+  if (size_read == MODP_B64_ERROR) {
+    output->resize(0);
+    return false;
+  }
+  output->resize(size_read);
+
+  return true;
+}
+
+}  // namespace weave
diff --git a/libweave/src/data_encoding.h b/libweave/src/data_encoding.h
new file mode 100644
index 0000000..ff6973d
--- /dev/null
+++ b/libweave/src/data_encoding.h
@@ -0,0 +1,78 @@
+// Copyright 2014 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 LIBWEAVE_SRC_DATA_ENCODING_H_
+#define LIBWEAVE_SRC_DATA_ENCODING_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <chromeos/secure_blob.h>
+
+namespace weave {
+
+using WebParamList = std::vector<std::pair<std::string, std::string>>;
+
+// Encode/escape string to be used in the query portion of a URL.
+// If |encodeSpaceAsPlus| is set to true, spaces are encoded as '+' instead
+// of "%20"
+std::string UrlEncode(const char* data, bool encodeSpaceAsPlus);
+
+inline std::string UrlEncode(const char* data) {
+  return UrlEncode(data, true);
+}
+
+// Decodes/unescapes a URL. Replaces all %XX sequences with actual characters.
+// Also replaces '+' with spaces.
+std::string UrlDecode(const char* data);
+
+// Converts a list of key-value pairs into a string compatible with
+// 'application/x-www-form-urlencoded' content encoding.
+std::string WebParamsEncode(const WebParamList& params, bool encodeSpaceAsPlus);
+
+inline std::string WebParamsEncode(const WebParamList& params) {
+  return WebParamsEncode(params, true);
+}
+
+// Parses a string of '&'-delimited key-value pairs (separated by '=') and
+// encoded in a way compatible with 'application/x-www-form-urlencoded'
+// content encoding.
+WebParamList WebParamsDecode(const std::string& data);
+
+// Encodes binary data using base64-encoding.
+std::string Base64Encode(const void* data, size_t size);
+
+// Encodes binary data using base64-encoding and wraps lines at 64 character
+// boundary using LF as required by PEM (RFC 1421) specification.
+std::string Base64EncodeWrapLines(const void* data, size_t size);
+
+// Decodes the input string from Base64.
+bool Base64Decode(const std::string& input, chromeos::Blob* output);
+
+// Helper wrappers to use std::string and chromeos::Blob as binary data
+// containers.
+inline std::string Base64Encode(const chromeos::Blob& input) {
+  return Base64Encode(input.data(), input.size());
+}
+inline std::string Base64EncodeWrapLines(const chromeos::Blob& input) {
+  return Base64EncodeWrapLines(input.data(), input.size());
+}
+inline std::string Base64Encode(const std::string& input) {
+  return Base64Encode(input.data(), input.size());
+}
+inline std::string Base64EncodeWrapLines(const std::string& input) {
+  return Base64EncodeWrapLines(input.data(), input.size());
+}
+inline bool Base64Decode(const std::string& input, std::string* output) {
+  chromeos::Blob blob;
+  if (!Base64Decode(input, &blob))
+    return false;
+  *output = std::string{blob.begin(), blob.end()};
+  return true;
+}
+
+}  // namespace weave
+
+#endif  // LIBWEAVE_SRC_DATA_ENCODING_H_
diff --git a/libweave/src/data_encoding_unittest.cc b/libweave/src/data_encoding_unittest.cc
new file mode 100644
index 0000000..28d6b85
--- /dev/null
+++ b/libweave/src/data_encoding_unittest.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2011 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.
+
+#include "libweave/src/data_encoding.h"
+
+#include <algorithm>
+#include <numeric>
+
+#include <gtest/gtest.h>
+
+namespace weave {
+
+TEST(data_encoding, UrlEncoding) {
+  std::string test = "\"http://sample/path/0014.html \"";
+  std::string encoded = UrlEncode(test.c_str());
+  EXPECT_EQ("%22http%3A%2F%2Fsample%2Fpath%2F0014.html+%22", encoded);
+  EXPECT_EQ(test, UrlDecode(encoded.c_str()));
+
+  test = "\"http://sample/path/0014.html \"";
+  encoded = UrlEncode(test.c_str(), false);
+  EXPECT_EQ("%22http%3A%2F%2Fsample%2Fpath%2F0014.html%20%22", encoded);
+  EXPECT_EQ(test, UrlDecode(encoded.c_str()));
+}
+
+TEST(data_encoding, WebParamsEncoding) {
+  std::string encoded =
+      WebParamsEncode({{"q", "test"}, {"path", "/usr/bin"}, {"#", "%"}});
+  EXPECT_EQ("q=test&path=%2Fusr%2Fbin&%23=%25", encoded);
+
+  auto params = WebParamsDecode(encoded);
+  EXPECT_EQ(3, params.size());
+  EXPECT_EQ("q", params[0].first);
+  EXPECT_EQ("test", params[0].second);
+  EXPECT_EQ("path", params[1].first);
+  EXPECT_EQ("/usr/bin", params[1].second);
+  EXPECT_EQ("#", params[2].first);
+  EXPECT_EQ("%", params[2].second);
+}
+
+TEST(data_encoding, Base64Encode) {
+  const std::string text1 = "hello world";
+  const std::string encoded1 = "aGVsbG8gd29ybGQ=";
+
+  const std::string text2 =
+      "Lorem ipsum dolor sit amet, facilisis erat nec aliquam, scelerisque "
+      "molestie commodo. Viverra tincidunt integer erat ipsum, integer "
+      "molestie, arcu in, sit mauris ac a sed sit etiam.";
+  const std::string encoded2 =
+      "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGZhY2lsaXNpcyBlcmF0IG5lYyBhbGlxdWF"
+      "tLCBzY2VsZXJpc3F1ZSBtb2xlc3RpZSBjb21tb2RvLiBWaXZlcnJhIHRpbmNpZHVudCBpbn"
+      "RlZ2VyIGVyYXQgaXBzdW0sIGludGVnZXIgbW9sZXN0aWUsIGFyY3UgaW4sIHNpdCBtYXVya"
+      "XMgYWMgYSBzZWQgc2l0IGV0aWFtLg==";
+
+  chromeos::Blob data3(256);
+  std::iota(data3.begin(), data3.end(), 0);  // Fills the buffer with 0x00-0xFF.
+  const std::string encoded3 =
+      "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ"
+      "1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaW"
+      "prbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en"
+      "6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU"
+      "1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==";
+
+  EXPECT_EQ(encoded1, Base64Encode(text1));
+  EXPECT_EQ(encoded2, Base64Encode(text2));
+  EXPECT_EQ(encoded3, Base64Encode(data3));
+}
+
+TEST(data_encoding, Base64EncodeWrapLines) {
+  const std::string text1 = "hello world";
+  const std::string encoded1 = "aGVsbG8gd29ybGQ=\n";
+
+  const std::string text2 =
+      "Lorem ipsum dolor sit amet, facilisis erat nec aliquam, scelerisque "
+      "molestie commodo. Viverra tincidunt integer erat ipsum, integer "
+      "molestie, arcu in, sit mauris ac a sed sit etiam.";
+  const std::string encoded2 =
+      "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGZhY2lsaXNpcyBlcmF0IG5lYyBh\n"
+      "bGlxdWFtLCBzY2VsZXJpc3F1ZSBtb2xlc3RpZSBjb21tb2RvLiBWaXZlcnJhIHRp\n"
+      "bmNpZHVudCBpbnRlZ2VyIGVyYXQgaXBzdW0sIGludGVnZXIgbW9sZXN0aWUsIGFy\n"
+      "Y3UgaW4sIHNpdCBtYXVyaXMgYWMgYSBzZWQgc2l0IGV0aWFtLg==\n";
+
+  chromeos::Blob data3(256);
+  std::iota(data3.begin(), data3.end(), 0);  // Fills the buffer with 0x00-0xFF.
+  const std::string encoded3 =
+      "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4v\n"
+      "MDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5f\n"
+      "YGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P\n"
+      "kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/\n"
+      "wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v\n"
+      "8PHy8/T19vf4+fr7/P3+/w==\n";
+
+  EXPECT_EQ(encoded1, Base64EncodeWrapLines(text1));
+  EXPECT_EQ(encoded2, Base64EncodeWrapLines(text2));
+  EXPECT_EQ(encoded3, Base64EncodeWrapLines(data3));
+}
+
+TEST(data_encoding, Base64Decode) {
+  const std::string encoded1 = "dGVzdCBzdHJpbmc=";
+
+  const std::string encoded2 =
+      "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGZhY2lsaXNpcyBlcmF0IG5lYyBh\n"
+      "bGlxdWFtLCBzY2VsZXJpc3F1ZSBtb2xlc3RpZSBjb21tb2RvLiBWaXZlcnJhIHRp\r\n"
+      "bmNpZHVudCBpbnRlZ2VyIGVyYXQgaXBzdW0sIGludGVnZXIgbW9sZXN0aWUsIGFy\r"
+      "Y3UgaW4sIHNpdCBtYXVyaXMgYWMgYSBzZWQgc2l0IGV0aWFt\n"
+      "Lg==\n\n\n";
+  const std::string decoded2 =
+      "Lorem ipsum dolor sit amet, facilisis erat nec aliquam, scelerisque "
+      "molestie commodo. Viverra tincidunt integer erat ipsum, integer "
+      "molestie, arcu in, sit mauris ac a sed sit etiam.";
+
+  const std::string encoded3 =
+      "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ"
+      "1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaW"
+      "prbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en"
+      "6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU"
+      "1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==";
+  chromeos::Blob decoded3(256);
+  std::iota(decoded3.begin(), decoded3.end(), 0);  // Fill with 0x00..0xFF.
+
+  std::string decoded;
+  EXPECT_TRUE(Base64Decode(encoded1, &decoded));
+  EXPECT_EQ("test string", decoded);
+
+  EXPECT_TRUE(Base64Decode(encoded2, &decoded));
+  EXPECT_EQ(decoded2, decoded);
+
+  chromeos::Blob decoded_blob;
+  EXPECT_TRUE(Base64Decode(encoded3, &decoded_blob));
+  EXPECT_EQ(decoded3, decoded_blob);
+
+  EXPECT_FALSE(Base64Decode("A", &decoded_blob));
+  EXPECT_TRUE(decoded_blob.empty());
+
+  EXPECT_TRUE(Base64Decode("/w==", &decoded_blob));
+  EXPECT_EQ((chromeos::Blob{0xFF}), decoded_blob);
+
+  EXPECT_TRUE(Base64Decode("//8=", &decoded_blob));
+  EXPECT_EQ((chromeos::Blob{0xFF, 0xFF}), decoded_blob);
+
+  EXPECT_FALSE(Base64Decode("AAECAwQFB,cI", &decoded_blob));
+  EXPECT_TRUE(decoded_blob.empty());
+}
+
+}  // namespace weave
diff --git a/libweave/src/device_registration_info.cc b/libweave/src/device_registration_info.cc
index 6696134..0b155a4 100644
--- a/libweave/src/device_registration_info.cc
+++ b/libweave/src/device_registration_info.cc
@@ -18,7 +18,6 @@
 #include <chromeos/bind_lambda.h>
 #include <chromeos/key_value_store.h>
 #include <chromeos/strings/string_utils.h>
-#include <chromeos/data_encoding.h>
 #include <weave/http_client.h>
 #include <weave/network.h>
 #include <weave/task_runner.h>
@@ -27,6 +26,7 @@
 #include "libweave/src/commands/command_definition.h"
 #include "libweave/src/commands/command_manager.h"
 #include "libweave/src/commands/schema_constants.h"
+#include "libweave/src/data_encoding.h"
 #include "libweave/src/http_constants.h"
 #include "libweave/src/json_error_codes.h"
 #include "libweave/src/notification/xmpp_channel.h"
@@ -75,18 +75,17 @@
   }
 }
 
-std::string AppendQueryParams(
-    const std::string& url,
-    const chromeos::data_encoding::WebParamList& params) {
+std::string AppendQueryParams(const std::string& url,
+                              const WebParamList& params) {
   CHECK_EQ(std::string::npos, url.find_first_of("?#"));
   if (params.empty())
     return url;
-  return url + '?' + chromeos::data_encoding::WebParamsEncode(params);
+  return url + '?' + WebParamsEncode(params);
 }
 
 std::string BuildURL(const std::string& url,
                      const std::string& subpath,
-                     const chromeos::data_encoding::WebParamList& params) {
+                     const WebParamList& params) {
   std::string result = url;
   if (!result.empty() && result.back() != '/' && !subpath.empty()) {
     CHECK_NE('/', subpath.front());
@@ -142,8 +141,7 @@
 
   void SetFormData(
       const std::vector<std::pair<std::string, std::string>>& data) {
-    SetData(chromeos::data_encoding::WebParamsEncode(data),
-            http::kWwwFormUrlEncoded);
+    SetData(WebParamsEncode(data), http::kWwwFormUrlEncoded);
   }
 
   void SetJsonData(const base::Value& json) {
@@ -256,13 +254,13 @@
 
 std::string DeviceRegistrationInfo::GetServiceURL(
     const std::string& subpath,
-    const chromeos::data_encoding::WebParamList& params) const {
+    const WebParamList& params) const {
   return BuildURL(config_->service_url(), subpath, params);
 }
 
 std::string DeviceRegistrationInfo::GetDeviceURL(
     const std::string& subpath,
-    const chromeos::data_encoding::WebParamList& params) const {
+    const WebParamList& params) const {
   CHECK(!config_->device_id().empty()) << "Must have a valid device ID";
   return BuildURL(config_->service_url(),
                   "devices/" + config_->device_id() + "/" + subpath, params);
@@ -270,7 +268,7 @@
 
 std::string DeviceRegistrationInfo::GetOAuthURL(
     const std::string& subpath,
-    const chromeos::data_encoding::WebParamList& params) const {
+    const WebParamList& params) const {
   return BuildURL(config_->oauth_url(), subpath, params);
 }
 
diff --git a/libweave/src/device_registration_info.h b/libweave/src/device_registration_info.h
index f162ee4..e0515a9 100644
--- a/libweave/src/device_registration_info.h
+++ b/libweave/src/device_registration_info.h
@@ -18,7 +18,6 @@
 #include <base/single_thread_task_runner.h>
 #include <base/time/time.h>
 #include <base/timer/timer.h>
-#include <chromeos/data_encoding.h>
 #include <chromeos/errors/error.h>
 #include <weave/cloud.h>
 #include <weave/config.h>
@@ -28,6 +27,7 @@
 #include "libweave/src/buffet_config.h"
 #include "libweave/src/commands/cloud_command_update_interface.h"
 #include "libweave/src/commands/command_manager.h"
+#include "libweave/src/data_encoding.h"
 #include "libweave/src/notification/notification_channel.h"
 #include "libweave/src/notification/notification_delegate.h"
 #include "libweave/src/notification/pull_channel.h"
@@ -102,28 +102,25 @@
   // appended to the base URL which is normally
   //    https://www.googleapis.com/clouddevices/v1/".
   // If |params| are specified, each key-value pair is formatted using
-  // chromeos::data_encoding::WebParamsEncode() and appended to URL as a query
+  // WebParamsEncode() and appended to URL as a query
   // string.
   // So, calling:
   //    GetServiceURL("ticket", {{"key","apiKey"}})
   // will return something like:
   //    https://www.googleapis.com/clouddevices/v1/ticket?key=apiKey
-  std::string GetServiceURL(
-      const std::string& subpath = {},
-      const chromeos::data_encoding::WebParamList& params = {}) const;
+  std::string GetServiceURL(const std::string& subpath = {},
+                            const WebParamList& params = {}) const;
 
   // Returns a service URL to access the registered device on GCD server.
   // The base URL used to construct the full URL looks like this:
   //    https://www.googleapis.com/clouddevices/v1/devices/<device_id>/
-  std::string GetDeviceURL(
-      const std::string& subpath = {},
-      const chromeos::data_encoding::WebParamList& params = {}) const;
+  std::string GetDeviceURL(const std::string& subpath = {},
+                           const WebParamList& params = {}) const;
 
   // Similar to GetServiceURL, GetOAuthURL() returns a URL of OAuth 2.0 server.
   // The base URL used is https://accounts.google.com/o/oauth2/.
-  std::string GetOAuthURL(
-      const std::string& subpath = {},
-      const chromeos::data_encoding::WebParamList& params = {}) const;
+  std::string GetOAuthURL(const std::string& subpath = {},
+                          const WebParamList& params = {}) const;
 
   // Starts GCD device if credentials available.
   void Start();
diff --git a/libweave/src/device_registration_info_unittest.cc b/libweave/src/device_registration_info_unittest.cc
index 711755d..5e368d3 100644
--- a/libweave/src/device_registration_info_unittest.cc
+++ b/libweave/src/device_registration_info_unittest.cc
@@ -75,7 +75,7 @@
 
 std::string GetFormField(const std::string& data, const std::string& name) {
   EXPECT_FALSE(data.empty());
-  for (const auto& i : chromeos::data_encoding::WebParamsDecode(data)) {
+  for (const auto& i : WebParamsDecode(data)) {
     if (i.first == name)
       return i.second;
   }
diff --git a/libweave/src/notification/xmpp_channel.cc b/libweave/src/notification/xmpp_channel.cc
index 13a3565..2715dd9 100644
--- a/libweave/src/notification/xmpp_channel.cc
+++ b/libweave/src/notification/xmpp_channel.cc
@@ -7,11 +7,11 @@
 #include <string>
 
 #include <base/bind.h>
-#include <chromeos/data_encoding.h>
 #include <weave/network.h>
 #include <weave/task_runner.h>
 
 #include "libweave/src/backoff_entry.h"
+#include "libweave/src/data_encoding.h"
 #include "libweave/src/notification/notification_delegate.h"
 #include "libweave/src/notification/notification_parser.h"
 #include "libweave/src/notification/xml_node.h"
@@ -40,7 +40,7 @@
       "auth:allow-non-google-login='true' "
       "auth:client-uses-full-bind-result='true' "
       "xmlns:auth='http://www.google.com/talk/protocol/auth'>" +
-      chromeos::data_encoding::Base64Encode(credentials) + "</auth>";
+      Base64Encode(credentials) + "</auth>";
   return msg;
 }
 
@@ -278,7 +278,7 @@
   }
   std::string data = node->text();
   std::string json_data;
-  if (!chromeos::data_encoding::Base64Decode(data, &json_data)) {
+  if (!Base64Decode(data, &json_data)) {
     LOG(WARNING) << "Failed to decode base64-encoded message payload: " << data;
     return;
   }
diff --git a/libweave/src/privet/security_manager.cc b/libweave/src/privet/security_manager.cc
index cc5f64a..5888b41 100644
--- a/libweave/src/privet/security_manager.cc
+++ b/libweave/src/privet/security_manager.cc
@@ -17,12 +17,12 @@
 #include <base/strings/string_number_conversions.h>
 #include <base/strings/stringprintf.h>
 #include <base/time/time.h>
-#include <chromeos/data_encoding.h>
 #include <chromeos/key_value_store.h>
 #include <chromeos/strings/string_utils.h>
 #include <weave/task_runner.h>
 
 #include "libweave/external/crypto/p224_spake.h"
+#include "libweave/src/data_encoding.h"
 #include "libweave/src/privet/constants.h"
 #include "libweave/src/privet/openssl_utils.h"
 
@@ -159,7 +159,7 @@
                                                const base::Time& time) {
   chromeos::SecureBlob data(CreateTokenData(user_info, time));
   chromeos::Blob hash(HmacSha256(secret_, data));
-  return chromeos::data_encoding::Base64Encode(chromeos::SecureBlob::Combine(
+  return Base64Encode(chromeos::SecureBlob::Combine(
       chromeos::SecureBlob(hash.begin(), hash.end()), data));
 }
 
@@ -167,8 +167,7 @@
 UserInfo SecurityManager::ParseAccessToken(const std::string& token,
                                            base::Time* time) const {
   chromeos::Blob decoded;
-  if (!chromeos::data_encoding::Base64Decode(token, &decoded) ||
-      decoded.size() <= kSha256OutputSize) {
+  if (!Base64Decode(token, &decoded) || decoded.size() <= kSha256OutputSize) {
     return UserInfo{};
   }
   chromeos::SecureBlob data(decoded.begin() + kSha256OutputSize, decoded.end());
@@ -193,7 +192,7 @@
   if (is_security_disabled_)
     return true;
   chromeos::Blob auth_decoded;
-  if (!chromeos::data_encoding::Base64Decode(auth_code, &auth_decoded))
+  if (!Base64Decode(auth_code, &auth_decoded))
     return false;
   for (const auto& session : confirmed_sessions_) {
     if (auth_decoded ==
@@ -292,7 +291,7 @@
       base::TimeDelta::FromMinutes(kPairingExpirationTimeMinutes));
 
   *session_id = session;
-  *device_commitment = chromeos::data_encoding::Base64Encode(commitment);
+  *device_commitment = Base64Encode(commitment);
   LOG(INFO) << "Pairing code for session " << *session_id << " is " << code;
   // TODO(vitalybuka): Handle case when device can't start multiple pairing
   // simultaneously and implement throttling to avoid brute force attack.
@@ -319,7 +318,7 @@
   CHECK(!certificate_fingerprint_.empty());
 
   chromeos::Blob commitment;
-  if (!chromeos::data_encoding::Base64Decode(client_commitment, &commitment)) {
+  if (!Base64Decode(client_commitment, &commitment)) {
     ClosePendingSession(session_id);
     chromeos::Error::AddToPrintf(
         error, FROM_HERE, errors::kDomain, errors::kInvalidFormat,
@@ -339,12 +338,11 @@
   std::string key = session->second->GetKey();
   VLOG(3) << "KEY " << base::HexEncode(key.data(), key.size());
 
-  *fingerprint =
-      chromeos::data_encoding::Base64Encode(certificate_fingerprint_);
+  *fingerprint = Base64Encode(certificate_fingerprint_);
   chromeos::Blob cert_hmac =
       HmacSha256(chromeos::SecureBlob(session->second->GetKey()),
                  certificate_fingerprint_);
-  *signature = chromeos::data_encoding::Base64Encode(cert_hmac);
+  *signature = Base64Encode(cert_hmac);
   confirmed_sessions_.emplace(session->first, std::move(session->second));
   task_runner_->PostDelayedTask(
       FROM_HERE,
diff --git a/libweave/src/privet/security_manager_unittest.cc b/libweave/src/privet/security_manager_unittest.cc
index c2024c2..44e01cf 100644
--- a/libweave/src/privet/security_manager_unittest.cc
+++ b/libweave/src/privet/security_manager_unittest.cc
@@ -18,7 +18,6 @@
 #include <base/rand_util.h>
 #include <base/strings/string_number_conversions.h>
 #include <base/strings/string_util.h>
-#include <chromeos/data_encoding.h>
 #include <chromeos/key_value_store.h>
 #include <chromeos/strings/string_utils.h>
 #include "libweave/external/crypto/p224_spake.h"
@@ -26,6 +25,7 @@
 #include <gtest/gtest.h>
 #include <weave/mock_task_runner.h>
 
+#include "libweave/src/data_encoding.h"
 #include "libweave/src/privet/openssl_utils.h"
 
 using testing::Eq;
@@ -92,8 +92,7 @@
     crypto::P224EncryptedKeyExchange spake{
         crypto::P224EncryptedKeyExchange::kPeerTypeClient, "1234"};
 
-    std::string client_commitment_base64{
-        chromeos::data_encoding::Base64Encode(spake.GetNextMessage())};
+    std::string client_commitment_base64{Base64Encode(spake.GetNextMessage())};
 
     EXPECT_TRUE(security_.ConfirmPairing(session_id, client_commitment_base64,
                                          fingerprint, signature, nullptr));
@@ -101,8 +100,7 @@
     EXPECT_TRUE(IsBase64(*signature));
 
     chromeos::Blob device_commitment;
-    ASSERT_TRUE(chromeos::data_encoding::Base64Decode(device_commitment_base64,
-                                                      &device_commitment));
+    ASSERT_TRUE(Base64Decode(device_commitment_base64, &device_commitment));
     spake.ProcessMessage(
         chromeos::string_utils::GetBytesAsString(device_commitment));
 
@@ -110,8 +108,7 @@
         HmacSha256(chromeos::SecureBlob{spake.GetUnverifiedKey()},
                    chromeos::SecureBlob{session_id})};
 
-    std::string auth_code_base64{
-        chromeos::data_encoding::Base64Encode(auth_code)};
+    std::string auth_code_base64{Base64Encode(auth_code)};
 
     EXPECT_TRUE(security_.IsValidPairingCode(auth_code_base64));
   }
@@ -223,8 +220,7 @@
     EXPECT_CALL(callbacks, OnPairingEnd(Eq(session_id)));
     crypto::P224EncryptedKeyExchange spake{
         crypto::P224EncryptedKeyExchange::kPeerTypeServer, "1234"};
-    std::string client_commitment =
-        chromeos::data_encoding::Base64Encode(spake.GetNextMessage());
+    std::string client_commitment = Base64Encode(spake.GetNextMessage());
     std::string fingerprint, signature;
     // Regardless of whether the commitment is valid or not, we should get a
     // callback indicating that the pairing session is gone.