1 // Copyright 2018 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 "third_party/blink/renderer/core/inspector/inspector_session_state.h"
6 
7 #include "third_party/inspector_protocol/crdtp/cbor.h"
8 
9 namespace blink {
10 namespace {
11 using crdtp::span;
12 using crdtp::SpanFrom;
13 using crdtp::cbor::CBORTokenizer;
14 using crdtp::cbor::CBORTokenTag;
15 using crdtp::cbor::EncodeDouble;
16 using crdtp::cbor::EncodeFalse;
17 using crdtp::cbor::EncodeFromLatin1;
18 using crdtp::cbor::EncodeFromUTF16;
19 using crdtp::cbor::EncodeInt32;
20 using crdtp::cbor::EncodeNull;
21 using crdtp::cbor::EncodeTrue;
22 }  // namespace
23 
24 //
25 // InspectorSessionState
26 //
InspectorSessionState(mojom::blink::DevToolsSessionStatePtr reattach)27 InspectorSessionState::InspectorSessionState(
28     mojom::blink::DevToolsSessionStatePtr reattach)
29     : reattach_state_(std::move(reattach)),
30       updates_(mojom::blink::DevToolsSessionState::New()) {}
31 
ReattachState() const32 const mojom::blink::DevToolsSessionState* InspectorSessionState::ReattachState()
33     const {
34   return reattach_state_.get();
35 }
36 
EnqueueUpdate(const WTF::String & key,const WebVector<uint8_t> * value)37 void InspectorSessionState::EnqueueUpdate(const WTF::String& key,
38                                           const WebVector<uint8_t>* value) {
39   base::Optional<WTF::Vector<uint8_t>> updated_value;
40   if (value) {
41     WTF::Vector<uint8_t> payload;
42     payload.AppendRange(value->begin(), value->end());
43     updated_value = std::move(payload);
44   }
45   updates_->entries.Set(key, std::move(updated_value));
46 }
47 
TakeUpdates()48 mojom::blink::DevToolsSessionStatePtr InspectorSessionState::TakeUpdates() {
49   auto updates = std::move(updates_);
50   updates_ = mojom::blink::DevToolsSessionState::New();
51   return updates;
52 }
53 
54 //
55 // Encoding / Decoding routines.
56 //
57 /*static*/
Serialize(bool v,WebVector<uint8_t> * out)58 void InspectorAgentState::Serialize(bool v, WebVector<uint8_t>* out) {
59   out->emplace_back(v ? EncodeTrue() : EncodeFalse());
60 }
61 
62 /*static*/
Deserialize(span<uint8_t> in,bool * v)63 bool InspectorAgentState::Deserialize(span<uint8_t> in, bool* v) {
64   CBORTokenizer tokenizer(in);
65   if (tokenizer.TokenTag() == CBORTokenTag::TRUE_VALUE) {
66     *v = true;
67     return true;
68   }
69   if (tokenizer.TokenTag() == CBORTokenTag::FALSE_VALUE) {
70     *v = false;
71     return true;
72   }
73   return false;
74 }
75 
76 /*static*/
Serialize(int32_t v,WebVector<uint8_t> * out)77 void InspectorAgentState::Serialize(int32_t v, WebVector<uint8_t>* out) {
78   auto encode = out->ReleaseVector();
79   EncodeInt32(v, &encode);
80   *out = std::move(encode);
81 }
82 
83 /*static*/
Deserialize(span<uint8_t> in,int32_t * v)84 bool InspectorAgentState::Deserialize(span<uint8_t> in, int32_t* v) {
85   CBORTokenizer tokenizer(in);
86   if (tokenizer.TokenTag() == CBORTokenTag::INT32) {
87     *v = tokenizer.GetInt32();
88     return true;
89   }
90   return false;
91 }
92 
93 /*static*/
Serialize(double v,WebVector<uint8_t> * out)94 void InspectorAgentState::Serialize(double v, WebVector<uint8_t>* out) {
95   auto encode = out->ReleaseVector();
96   EncodeDouble(v, &encode);
97   *out = std::move(encode);
98 }
99 
100 /*static*/
Deserialize(span<uint8_t> in,double * v)101 bool InspectorAgentState::Deserialize(span<uint8_t> in, double* v) {
102   CBORTokenizer tokenizer(in);
103   if (tokenizer.TokenTag() == CBORTokenTag::DOUBLE) {
104     *v = tokenizer.GetDouble();
105     return true;
106   }
107   return false;
108 }
109 
110 /*static*/
Serialize(const WTF::String & v,WebVector<uint8_t> * out)111 void InspectorAgentState::Serialize(const WTF::String& v,
112                                     WebVector<uint8_t>* out) {
113   auto encode = out->ReleaseVector();
114   if (v.Is8Bit()) {
115     auto span8 = v.Span8();
116     EncodeFromLatin1(span<uint8_t>(span8.data(), span8.size()), &encode);
117   } else {
118     auto span16 = v.Span16();
119     EncodeFromUTF16(
120         span<uint16_t>(reinterpret_cast<const uint16_t*>(span16.data()),
121                        span16.size()),
122         &encode);
123   }
124   *out = std::move(encode);
125 }
126 
127 /*static*/
Deserialize(span<uint8_t> in,WTF::String * v)128 bool InspectorAgentState::Deserialize(span<uint8_t> in, WTF::String* v) {
129   CBORTokenizer tokenizer(in);
130   if (tokenizer.TokenTag() == CBORTokenTag::STRING8) {
131     *v = WTF::String(
132         reinterpret_cast<const char*>(tokenizer.GetString8().data()),
133         static_cast<size_t>(tokenizer.GetString8().size()));
134     return true;
135   }
136   if (tokenizer.TokenTag() == CBORTokenTag::STRING16) {
137     *v = WTF::String(
138         reinterpret_cast<const UChar*>(tokenizer.GetString16WireRep().data()),
139         tokenizer.GetString16WireRep().size() / 2);
140     return true;
141   }
142   return false;
143 }
144 
145 /*static*/
Serialize(const std::vector<uint8_t> & v,WebVector<uint8_t> * out)146 void InspectorAgentState::Serialize(const std::vector<uint8_t>& v,
147                                     WebVector<uint8_t>* out) {
148   // We could CBOR encode this, but since we never look at the contents
149   // anyway (except for decoding just below), we just cheat and use the
150   // blob directly.
151   out->Assign(v.data(), v.size());
152 }
153 
154 /*static*/
Deserialize(span<uint8_t> in,std::vector<uint8_t> * v)155 bool InspectorAgentState::Deserialize(span<uint8_t> in,
156                                       std::vector<uint8_t>* v) {
157   v->insert(v->end(), in.begin(), in.end());
158   return true;
159 }
160 
161 //
162 // InspectorAgentState
163 //
InspectorAgentState(const WTF::String & domain_name)164 InspectorAgentState::InspectorAgentState(const WTF::String& domain_name)
165     : domain_name_(domain_name) {}
166 
RegisterField(Field * field)167 WTF::String InspectorAgentState::RegisterField(Field* field) {
168   WTF::String prefix_key =
169       domain_name_ + "." + WTF::String::Number(fields_.size()) + "/";
170   fields_.push_back(field);
171   return prefix_key;
172 }
173 
InitFrom(InspectorSessionState * session_state)174 void InspectorAgentState::InitFrom(InspectorSessionState* session_state) {
175   for (Field* f : fields_)
176     f->InitFrom(session_state);
177 }
178 
ClearAllFields()179 void InspectorAgentState::ClearAllFields() {
180   for (Field* f : fields_)
181     f->Clear();
182 }
183 
184 }  // namespace blink
185