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

Side by Side Diff: content/browser/android/string_message_codec.cc

Issue 2422793002: HTML MessagePort as mojo::MessagePipeHandle (Closed)
Patch Set: Add missing ScopedAsyncTaskScheduler instance for the new unit tests; required by a recent change t… 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/android/string_message_codec.h"
6
7 #include <vector>
8
9 #include "base/logging.h"
10
11 namespace content {
12 namespace {
13
14 const uint32_t kVarIntShift = 7;
15 const uint32_t kVarIntMask = (1 << kVarIntShift) - 1;
16
17 const uint8_t kVersionTag = 0xFF;
18 const uint8_t kPaddingTag = '\0';
19 const uint8_t kOneByteStringTag = '"';
20 const uint8_t kTwoByteStringTag = 'c';
21
22 const uint32_t kVersion = 10;
23
24 static size_t BytesNeededForUint32(uint32_t value) {
25 size_t result = 0;
26 do {
27 result++;
28 value >>= kVarIntShift;
29 } while (value);
30 return result;
31 }
32
33 void WriteUint8(uint8_t value, std::vector<uint8_t>* buffer) {
34 buffer->push_back(value);
35 }
36
37 void WriteUint32(uint32_t value, std::vector<uint8_t>* buffer) {
38 for (;;) {
39 uint8_t b = (value & kVarIntMask);
40 value >>= kVarIntShift;
41 if (!value) {
42 WriteUint8(b, buffer);
43 break;
44 }
45 WriteUint8(b | (1 << kVarIntShift), buffer);
46 }
47 }
48
49 void WriteBytes(const char* bytes, size_t num_bytes,
50 std::vector<uint8_t>* buffer) {
51 buffer->insert(buffer->end(), bytes, bytes + num_bytes);
52 }
53
54 bool ReadUint8(const uint8_t** ptr, const uint8_t* end, uint8_t* value) {
55 if (*ptr >= end)
56 return false;
57 *value = *(*ptr)++;
58 return true;
59 }
60
61 bool ReadUint32(const uint8_t** ptr, const uint8_t* end, uint32_t* value) {
62 *value = 0;
63 uint8_t current_byte;
64 int shift = 0;
65 do {
66 if (*ptr >= end)
67 return false;
68 current_byte = *(*ptr)++;
69 *value |= (static_cast<uint32_t>(current_byte & kVarIntMask) << shift);
70 shift += kVarIntShift;
71 } while (current_byte & (1 << kVarIntShift));
72 return true;
73 }
74
75 bool ContainsOnlyLatin1(const base::string16& data) {
76 base::char16 x = 0;
77 for (base::char16 c : data)
78 x |= c;
79 return !(x & 0xFF00);
80 }
81
82 } // namespace
83
84 base::string16 EncodeStringMessage(const base::string16& data) {
85 std::vector<uint8_t> buffer;
86 WriteUint8(kVersionTag, &buffer);
87 WriteUint32(kVersion, &buffer);
88
89 if (ContainsOnlyLatin1(data)) {
90 std::string data_latin1(data.begin(), data.end());
91 WriteUint8(kOneByteStringTag, &buffer);
92 WriteUint32(data_latin1.size(), &buffer);
93 WriteBytes(data_latin1.c_str(), data_latin1.size(), &buffer);
94 } else {
95 size_t num_bytes = data.size() * sizeof(base::char16);
96 if ((buffer.size() + 1 + BytesNeededForUint32(num_bytes)) & 1)
97 WriteUint8(kPaddingTag, &buffer);
98 WriteUint8(kTwoByteStringTag, &buffer);
99 WriteUint32(num_bytes, &buffer);
100 WriteBytes(reinterpret_cast<const char*>(data.data()), num_bytes, &buffer);
101 }
102
103 base::string16 result;
104 size_t result_num_bytes = (buffer.size() + 1) & ~1;
105 result.resize(result_num_bytes / 2);
106 uint8_t* destination = reinterpret_cast<uint8_t*>(&result[0]);
107 memcpy(destination, &buffer[0], buffer.size());
108 return result;
109 }
110
111 bool DecodeStringMessage(const base::string16& encoded_data,
112 base::string16* result) {
113 size_t num_bytes = encoded_data.size() * 2;
114
115 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(&encoded_data[0]);
116 const uint8_t* end = ptr + num_bytes;
117
118 uint8_t tag;
119 if (!ReadUint8(&ptr, end, &tag) || tag != kVersionTag)
120 return false;
121
122 uint32_t version;
123 if (!ReadUint32(&ptr, end, &version))
124 return false;
125
126 do {
127 if (!ReadUint8(&ptr, end, &tag))
128 return false;
129 } while (tag == kPaddingTag);
130
131 switch (tag) {
132 case kOneByteStringTag: {
133 uint32_t num_bytes;
134 if (!ReadUint32(&ptr, end, &num_bytes))
135 return false;
136 result->assign(reinterpret_cast<const char*>(ptr),
137 reinterpret_cast<const char*>(ptr) + num_bytes);
138 return true;
139 }
140 case kTwoByteStringTag: {
141 uint32_t num_bytes;
142 if (!ReadUint32(&ptr, end, &num_bytes))
143 return false;
144 result->assign(reinterpret_cast<const base::char16*>(ptr), num_bytes / 2);
145 return true;
146 }
147 }
148
149 DLOG(WARNING) << "Unexpected tag: " << tag;
150 return false;
151 }
152
153 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/android/string_message_codec.h ('k') | content/browser/android/string_message_codec_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698