Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Unified Diff: content/browser/android/string_message_codec.cc

Issue 2422793002: HTML MessagePort as mojo::MessagePipeHandle (Closed)
Patch Set: Eliminate unnecessary PostTask Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/android/string_message_codec.cc
diff --git a/content/browser/android/string_message_codec.cc b/content/browser/android/string_message_codec.cc
new file mode 100644
index 0000000000000000000000000000000000000000..aa258875ef539ec64df030c2bb84a4a9943c0865
--- /dev/null
+++ b/content/browser/android/string_message_codec.cc
@@ -0,0 +1,153 @@
+// 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 "content/browser/android/string_message_codec.h"
+
+#include <vector>
+
+#include "base/logging.h"
+
+namespace content {
+namespace {
+
+const uint32_t kVarIntShift = 7;
+const uint32_t kVarIntMask = (1 << kVarIntShift) - 1;
+
+const uint8_t kVersionTag = 0xFF;
+const uint8_t kPaddingTag = '\0';
+const uint8_t kOneByteStringTag = '"';
+const uint8_t kTwoByteStringTag = 'c';
+
+const uint32_t kVersion = 10;
+
+static size_t BytesNeededForUint32(uint32_t value) {
+ size_t result = 0;
+ do {
+ result++;
+ value >>= kVarIntShift;
+ } while (value);
+ return result;
+}
+
+void WriteUint8(uint8_t value, std::vector<uint8_t>* buffer) {
+ buffer->push_back(value);
+}
+
+void WriteUint32(uint32_t value, std::vector<uint8_t>* buffer) {
+ for (;;) {
+ uint8_t b = (value & kVarIntMask);
+ value >>= kVarIntShift;
+ if (!value) {
+ WriteUint8(b, buffer);
+ break;
+ }
+ WriteUint8(b | (1 << kVarIntShift), buffer);
+ }
+}
+
+void WriteBytes(const char* bytes, size_t num_bytes,
+ std::vector<uint8_t>* buffer) {
+ buffer->insert(buffer->end(), bytes, bytes + num_bytes);
+}
+
+bool ReadUint8(const uint8_t** ptr, const uint8_t* end, uint8_t* value) {
+ if (*ptr >= end)
+ return false;
+ *value = *(*ptr)++;
+ return true;
+}
+
+bool ReadUint32(const uint8_t** ptr, const uint8_t* end, uint32_t* value) {
+ *value = 0;
+ uint8_t current_byte;
+ int shift = 0;
+ do {
+ if (*ptr >= end)
+ return false;
+ current_byte = *(*ptr)++;
+ *value |= (static_cast<uint32_t>(current_byte & kVarIntMask) << shift);
+ shift += kVarIntShift;
+ } while (current_byte & (1 << kVarIntShift));
+ return true;
+}
+
+bool ContainsOnlyLatin1(const base::string16& data) {
+ base::char16 x = 0;
+ for (base::char16 c : data)
+ x |= c;
+ return !(x & 0xFF00);
+}
+
+} // namespace
+
+base::string16 EncodeStringMessage(const base::string16& data) {
+ std::vector<uint8_t> buffer;
+ WriteUint8(kVersionTag, &buffer);
+ WriteUint32(kVersion, &buffer);
+
+ if (ContainsOnlyLatin1(data)) {
+ std::string data_latin1(data.begin(), data.end());
+ WriteUint8(kOneByteStringTag, &buffer);
+ WriteUint32(data_latin1.size(), &buffer);
+ WriteBytes(data_latin1.c_str(), data_latin1.size(), &buffer);
+ } else {
+ size_t num_bytes = data.size() * sizeof(base::char16);
+ if ((buffer.size() + 1 + BytesNeededForUint32(num_bytes)) & 1)
+ WriteUint8(kPaddingTag, &buffer);
+ WriteUint8(kTwoByteStringTag, &buffer);
+ WriteUint32(num_bytes, &buffer);
+ WriteBytes(reinterpret_cast<const char*>(data.data()), num_bytes, &buffer);
+ }
+
+ base::string16 result;
+ size_t result_num_bytes = (buffer.size() + 1) & ~1;
+ result.resize(result_num_bytes / 2);
+ uint8_t* destination = reinterpret_cast<uint8_t*>(&result[0]);
+ memcpy(destination, &buffer[0], buffer.size());
+ return result;
+}
+
+bool DecodeStringMessage(const base::string16& encoded_data,
+ base::string16* result) {
+ size_t num_bytes = encoded_data.size() * 2;
+
+ const uint8_t* ptr = reinterpret_cast<const uint8_t*>(&encoded_data[0]);
+ const uint8_t* end = ptr + num_bytes;
+
+ uint8_t tag;
+ if (!ReadUint8(&ptr, end, &tag) || tag != kVersionTag)
+ return false;
+
+ uint32_t version;
+ if (!ReadUint32(&ptr, end, &version))
+ return false;
+
+ do {
+ if (!ReadUint8(&ptr, end, &tag))
+ return false;
+ } while (tag == kPaddingTag);
+
+ switch (tag) {
+ case kOneByteStringTag: {
+ uint32_t num_bytes;
+ if (!ReadUint32(&ptr, end, &num_bytes))
+ return false;
+ result->assign(reinterpret_cast<const char*>(ptr),
+ reinterpret_cast<const char*>(ptr) + num_bytes);
+ return true;
+ }
+ case kTwoByteStringTag: {
+ uint32_t num_bytes;
+ if (!ReadUint32(&ptr, end, &num_bytes))
+ return false;
+ result->assign(reinterpret_cast<const base::char16*>(ptr), num_bytes / 2);
+ return true;
+ }
+ }
+
+ DLOG(WARNING) << "Unexpected tag: " << tag;
+ return false;
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698