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

Side by Side Diff: extensions/browser/api/copresence_endpoints/copresence_endpoints_api.cc

Issue 895783002: Remove the Copresence Endpoints API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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 2014 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 "extensions/browser/api/copresence_endpoints/copresence_endpoints_api.h "
6
7 #include "base/base64.h"
8 #include "base/json/json_reader.h"
9 #include "base/json/json_writer.h"
10 #include "base/lazy_instance.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_piece.h"
13 #include "base/strings/string_util.h"
14 #include "components/copresence_endpoints/public/copresence_endpoint.h"
15 #include "content/public/browser/browser_context.h"
16 #include "extensions/browser/api/copresence_endpoints/copresence_endpoint_resour ce.h"
17 #include "extensions/browser/event_router.h"
18 #include "extensions/common/api/copresence_endpoints.h"
19 #include "net/base/io_buffer.h"
20
21 using copresence_endpoints::CopresenceEndpoint;
22
23 namespace extensions {
24
25 namespace {
26
27 const size_t kSizeBytes = 2;
28 const char kToField[] = "to";
29 const char kDataField[] = "data";
30 const char kReplyToField[] = "replyTo";
31
32 bool Base64DecodeWithoutPadding(const std::string& data, std::string* out) {
33 std::string ret = data;
34 while (ret.size() % 4)
35 ret.push_back('=');
36
37 if (!base::Base64Decode(ret, &ret))
38 return false;
39
40 out->swap(ret);
41 return true;
42 }
43
44 std::string Base64EncodeWithoutPadding(const std::string& data) {
45 std::string ret = data;
46 base::Base64Encode(ret, &ret);
47 while (*(ret.end() - 1) == '=')
48 ret.erase(ret.end() - 1);
49 return ret;
50 }
51
52 // Create a message to send to another endpoint.
53 std::string CreateMessage(const std::vector<char>& data,
54 const std::string& local_endpoint_locator,
55 int remote_endpoint_id) {
56 base::DictionaryValue dict;
57 dict.SetString(kToField, base::IntToString(remote_endpoint_id));
58 dict.SetString(kDataField, Base64EncodeWithoutPadding(
59 std::string(data.begin(), data.end())));
60 dict.SetString(kReplyToField,
61 Base64EncodeWithoutPadding(local_endpoint_locator));
62
63 std::string json;
64 base::JSONWriter::Write(&dict, &json);
65
66 std::string message;
67 message.push_back(static_cast<unsigned char>(json.size() & 0xff));
68 message.push_back(static_cast<unsigned char>(json.size() >> 8));
69
70 message.append(json);
71 return message;
72 }
73
74 bool IsMessageComplete(const std::string& message, size_t* length) {
75 if (message.size() < kSizeBytes)
76 return false;
77
78 // message[1] = upper order 8 bits.
79 // message[0] = lower order 8 bits.
80 size_t message_length = (static_cast<size_t>(message[1]) << 8) |
81 (static_cast<size_t>(message[0]) & 0xff);
82
83 if (message.size() >= kSizeBytes + message_length) {
84 *length = message_length;
85 return true;
86 }
87
88 return false;
89 }
90
91 bool ExtractEndpointId(const std::string& endpoint_locator, int* id) {
92 std::vector<std::string> tokens;
93 if (Tokenize(endpoint_locator, ".", &tokens) <= 1)
94 return false;
95
96 if (!base::StringToInt(tokens[0], id))
97 return false;
98
99 return true;
100 }
101
102 // Parse a message received from another endpoint.
103 bool ParseReceivedMessage(const std::string& message,
104 std::string* data,
105 int* remote_endpoint_id) {
106 scoped_ptr<base::Value> value(base::JSONReader::Read(message));
107
108 // Check to see that we have a valid dictionary.
109 base::DictionaryValue* dict = nullptr;
110 if (!value || !value->GetAsDictionary(&dict) || !dict->HasKey(kDataField)) {
111 LOG(WARNING) << "Invalid message: " << message;
112 return false;
113 }
114
115 // The fields in the json string are,
116 // to: Endpoint Id this message is meant for (unused atm, we only support one
117 // local endpoint). TODO(rkc): Fix this to support multiple endpoints.
118 // data: Data content of the message.
119 // replyTo: Sender of this message (in the locator data format). We only need
120 // the endpoint id that we have to reply to, but currently we get
121 // the full locator. TODO(rkc): Fix this once other platforms change
122 // over to only sending us the ID.
123 if (!dict->GetStringASCII(kDataField, data))
124 return false;
125 if (!Base64DecodeWithoutPadding(*data, data))
126 return false;
127
128 std::string endpoint_locator;
129 if (!dict->GetStringASCII(kReplyToField, &endpoint_locator))
130 return false;
131 if (!Base64DecodeWithoutPadding(endpoint_locator, &endpoint_locator))
132 return false;
133
134 if (!ExtractEndpointId(endpoint_locator, remote_endpoint_id))
135 return false;
136
137 VLOG(3) << "Valid message parsed.";
138 return true;
139 }
140
141 } // namespace
142
143 // CopresenceEndpointFunction public methods:
144
145 CopresenceEndpointFunction::CopresenceEndpointFunction()
146 : endpoints_manager_(nullptr) {
147 }
148
149 void CopresenceEndpointFunction::DispatchOnConnectedEvent(int endpoint_id) {
150 // Send the messages to the client app.
151 scoped_ptr<Event> event(new Event(
152 core_api::copresence_endpoints::OnConnected::kEventName,
153 core_api::copresence_endpoints::OnConnected::Create(endpoint_id),
154 browser_context()));
155 EventRouter::Get(browser_context())
156 ->DispatchEventToExtension(extension_id(), event.Pass());
157 VLOG(2) << "Dispatched OnConnected event: endpointId = " << endpoint_id;
158 }
159
160 // CopresenceEndpointFunction protected methods:
161
162 int CopresenceEndpointFunction::AddEndpoint(
163 CopresenceEndpointResource* endpoint) {
164 return endpoints_manager_->Add(endpoint);
165 }
166
167 void CopresenceEndpointFunction::ReplaceEndpoint(
168 const std::string& extension_id,
169 int endpoint_id,
170 CopresenceEndpointResource* endpoint) {
171 endpoints_manager_->Replace(extension_id, endpoint_id, endpoint);
172 }
173
174 CopresenceEndpointResource* CopresenceEndpointFunction::GetEndpoint(
175 int endpoint_id) {
176 return endpoints_manager_->Get(extension_id(), endpoint_id);
177 }
178
179 void CopresenceEndpointFunction::RemoveEndpoint(int endpoint_id) {
180 endpoints_manager_->Remove(extension_id(), endpoint_id);
181 }
182
183 ExtensionFunction::ResponseAction CopresenceEndpointFunction::Run() {
184 Initialize();
185 return Execute();
186 }
187
188 // CopresenceEndpointFunction private methods:
189
190 CopresenceEndpointFunction::~CopresenceEndpointFunction() {
191 }
192
193 void CopresenceEndpointFunction::Initialize() {
194 endpoints_manager_ =
195 ApiResourceManager<CopresenceEndpointResource>::Get(browser_context());
196 }
197
198 void CopresenceEndpointFunction::OnDataReceived(
199 int local_endpoint_id,
200 const scoped_refptr<net::IOBuffer>& buffer,
201 int size) {
202 CopresenceEndpointResource* local_endpoint = GetEndpoint(local_endpoint_id);
203 if (!local_endpoint) {
204 VLOG(2) << "Receiving endpoint not found. ID = " << local_endpoint_id;
205 return;
206 }
207
208 std::string& packet = local_endpoint->packet();
209 packet.append(std::string(buffer->data(), size));
210 size_t message_length;
211 if (IsMessageComplete(packet, &message_length)) {
212 std::string message_data;
213 int remote_endpoint_id;
214 if (ParseReceivedMessage(packet.substr(kSizeBytes, message_length),
215 &message_data, &remote_endpoint_id)) {
216 DispatchOnReceiveEvent(local_endpoint_id, remote_endpoint_id,
217 message_data);
218 } else {
219 LOG(WARNING) << "Invalid message received: "
220 << packet.substr(kSizeBytes, message_length)
221 << " of length: " << message_length;
222 }
223
224 if (packet.size() > message_length + kSizeBytes) {
225 packet = packet.substr(message_length + kSizeBytes);
226 } else {
227 packet.clear();
228 }
229 }
230 }
231
232 void CopresenceEndpointFunction::DispatchOnReceiveEvent(
233 int local_endpoint_id,
234 int remote_endpoint_id,
235 const std::string& data) {
236 core_api::copresence_endpoints::ReceiveInfo info;
237 info.local_endpoint_id = local_endpoint_id;
238 info.remote_endpoint_id = remote_endpoint_id;
239 info.data.assign(data.begin(), data.end());
240 // Send the data to the client app.
241 scoped_ptr<Event> event(
242 new Event(core_api::copresence_endpoints::OnReceive::kEventName,
243 core_api::copresence_endpoints::OnReceive::Create(info),
244 browser_context()));
245 EventRouter::Get(browser_context())
246 ->DispatchEventToExtension(extension_id(), event.Pass());
247 VLOG(2) << "Dispatched OnReceive event: localEndpointId = "
248 << local_endpoint_id << ", remoteEndpointId = " << remote_endpoint_id
249 << " and data = " << data;
250 }
251
252 // CopresenceEndpointsCreateLocalEndpointFunction implementation:
253 ExtensionFunction::ResponseAction
254 CopresenceEndpointsCreateLocalEndpointFunction::Execute() {
255 // Add an empty endpoint to create a placeholder endpoint_id. We will need to
256 // bind
257 // this id to the OnConnected event dispatcher, so we need it before we
258 // create the actual endpoint. Once we have the endpoint created, we'll
259 // replace the
260 // placeholder with the actual endpoint object.
261 int endpoint_id =
262 AddEndpoint(new CopresenceEndpointResource(extension_id(), nullptr));
263
264 scoped_ptr<CopresenceEndpoint> endpoint =
265 make_scoped_ptr(new CopresenceEndpoint(
266 endpoint_id,
267 base::Bind(&CopresenceEndpointsCreateLocalEndpointFunction::OnCreated,
268 this, endpoint_id),
269 base::Bind(&CopresenceEndpointFunction::DispatchOnConnectedEvent,
270 this, endpoint_id),
271 base::Bind(&CopresenceEndpointFunction::OnDataReceived, this,
272 endpoint_id)));
273
274 ReplaceEndpoint(
275 extension_id(), endpoint_id,
276 new CopresenceEndpointResource(extension_id(), endpoint.Pass()));
277
278 return RespondLater();
279 }
280
281 void CopresenceEndpointsCreateLocalEndpointFunction::OnCreated(
282 int endpoint_id,
283 const std::string& locator) {
284 core_api::copresence_endpoints::EndpointInfo endpoint_info;
285 endpoint_info.endpoint_id = endpoint_id;
286 endpoint_info.locator = locator;
287 Respond(ArgumentList(
288 core_api::copresence_endpoints::CreateLocalEndpoint::Results::Create(
289 endpoint_info)));
290 }
291
292 // CopresenceEndpointsDestroyEndpointFunction implementation:
293 ExtensionFunction::ResponseAction
294 CopresenceEndpointsDestroyEndpointFunction::Execute() {
295 scoped_ptr<core_api::copresence_endpoints::DestroyEndpoint::Params> params(
296 core_api::copresence_endpoints::DestroyEndpoint::Params::Create(*args_));
297 EXTENSION_FUNCTION_VALIDATE(params.get());
298
299 RemoveEndpoint(params->endpoint_id);
300 return RespondNow(NoArguments());
301 }
302
303 // CopresenceEndpointsSendFunction implementation:
304 ExtensionFunction::ResponseAction CopresenceEndpointsSendFunction::Execute() {
305 scoped_ptr<core_api::copresence_endpoints::Send::Params> params(
306 core_api::copresence_endpoints::Send::Params::Create(*args_));
307 EXTENSION_FUNCTION_VALIDATE(params.get());
308
309 CopresenceEndpointResource* endpoint = GetEndpoint(params->local_endpoint_id);
310 if (!endpoint) {
311 VLOG(1) << "Endpoint not found. ID = " << params->local_endpoint_id;
312 return RespondNow(
313 ArgumentList(core_api::copresence_endpoints::Send::Results::Create(
314 core_api::copresence_endpoints::
315 ENDPOINT_STATUS_INVALID_LOCAL_ENDPOINT)));
316 }
317 DCHECK(endpoint->endpoint());
318
319 const std::string& message =
320 CreateMessage(params->data, endpoint->endpoint()->GetLocator(),
321 params->remote_endpoint_id);
322 VLOG(3) << "Sending message to remote_endpoint_id = "
323 << params->remote_endpoint_id
324 << " from local_endpoint_id = " << params->local_endpoint_id
325 << " with data[0] = " << static_cast<int>(message[0])
326 << ", data[1] = " << static_cast<int>(message[1]) << ", data[2:] = "
327 << std::string((message.c_str() + 2), message.size() - 2);
328
329 endpoint->endpoint()->Send(new net::StringIOBuffer(message), message.size());
330
331 return RespondNow(
332 ArgumentList(core_api::copresence_endpoints::Send::Results::Create(
333 core_api::copresence_endpoints::ENDPOINT_STATUS_NO_ERROR)));
334 }
335
336 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698