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

Side by Side Diff: content/renderer/presentation/presentation_dispatcher.cc

Issue 1259073004: [Presentation API] Change ListenForSessionMessages API to client-style. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Compile fix Created 5 years, 4 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/presentation/presentation_dispatcher.h" 5 #include "content/renderer/presentation/presentation_dispatcher.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 case presentation::PRESENTATION_SESSION_STATE_CONNECTED: 43 case presentation::PRESENTATION_SESSION_STATE_CONNECTED:
44 return blink::WebPresentationSessionState::Connected; 44 return blink::WebPresentationSessionState::Connected;
45 case presentation::PRESENTATION_SESSION_STATE_DISCONNECTED: 45 case presentation::PRESENTATION_SESSION_STATE_DISCONNECTED:
46 return blink::WebPresentationSessionState::Disconnected; 46 return blink::WebPresentationSessionState::Disconnected;
47 } 47 }
48 48
49 NOTREACHED(); 49 NOTREACHED();
50 return blink::WebPresentationSessionState::Disconnected; 50 return blink::WebPresentationSessionState::Disconnected;
51 } 51 }
52 52
53 presentation::SessionMessage* GetMojoSessionMessage(
54 const blink::WebString& presentationUrl,
55 const blink::WebString& presentationId,
56 presentation::PresentationMessageType type,
57 const uint8* data,
58 size_t length) {
59 presentation::SessionMessage* session_message =
60 new presentation::SessionMessage();
61 session_message->presentation_url = presentationUrl.utf8();
62 session_message->presentation_id = presentationId.utf8();
63 session_message->type = type;
64 const std::vector<uint8> vector(data, data + length);
65 session_message->data = mojo::Array<uint8>::From(vector);
66 return session_message;
67 }
68
69 } // namespace 53 } // namespace
70 54
71 namespace content { 55 namespace content {
72 56
73 PresentationDispatcher::PresentationDispatcher(RenderFrame* render_frame) 57 PresentationDispatcher::PresentationDispatcher(RenderFrame* render_frame)
74 : RenderFrameObserver(render_frame), 58 : RenderFrameObserver(render_frame),
75 controller_(nullptr), 59 controller_(nullptr),
76 binding_(this), 60 binding_(this),
77 listening_state_(ListeningState::Inactive), 61 listening_state_(ListeningState::Inactive),
78 last_known_availability_(false), 62 last_known_availability_(false) {}
79 listening_for_messages_(false) {
80 }
81 63
82 PresentationDispatcher::~PresentationDispatcher() { 64 PresentationDispatcher::~PresentationDispatcher() {
83 // Controller should be destroyed before the dispatcher when frame is 65 // Controller should be destroyed before the dispatcher when frame is
84 // destroyed. 66 // destroyed.
85 DCHECK(!controller_); 67 DCHECK(!controller_);
86 } 68 }
87 69
88 void PresentationDispatcher::setController( 70 void PresentationDispatcher::setController(
89 blink::WebPresentationController* controller) { 71 blink::WebPresentationController* controller) {
90 // There shouldn't be any swapping from one non-null controller to another. 72 // There shouldn't be any swapping from one non-null controller to another.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 const blink::WebString& presentationId, 124 const blink::WebString& presentationId,
143 const blink::WebString& message) { 125 const blink::WebString& message) {
144 if (message.utf8().size() > kMaxPresentationSessionMessageSize) { 126 if (message.utf8().size() > kMaxPresentationSessionMessageSize) {
145 // TODO(crbug.com/459008): Limit the size of individual messages to 64k 127 // TODO(crbug.com/459008): Limit the size of individual messages to 64k
146 // for now. Consider throwing DOMException or splitting bigger messages 128 // for now. Consider throwing DOMException or splitting bigger messages
147 // into smaller chunks later. 129 // into smaller chunks later.
148 LOG(WARNING) << "message size exceeded limit!"; 130 LOG(WARNING) << "message size exceeded limit!";
149 return; 131 return;
150 } 132 }
151 133
152 presentation::SessionMessage* session_message = 134 message_request_queue_.push(make_linked_ptr(
153 new presentation::SessionMessage(); 135 GetSendStringMessageRequest(presentationUrl, presentationId, message)));
154 session_message->presentation_url = presentationUrl.utf8();
155 session_message->presentation_id = presentationId.utf8();
156 session_message->type = presentation::PresentationMessageType::
157 PRESENTATION_MESSAGE_TYPE_TEXT;
158 session_message->message = message.utf8();
159
160 message_request_queue_.push(make_linked_ptr(session_message));
161 // Start processing request if only one in the queue. 136 // Start processing request if only one in the queue.
162 if (message_request_queue_.size() == 1) { 137 if (message_request_queue_.size() == 1) {
163 const linked_ptr<presentation::SessionMessage>& request = 138 const linked_ptr<SendMessageRequest>& request =
164 message_request_queue_.front(); 139 message_request_queue_.front();
165 DoSendMessage(*request); 140 DoSendMessage(*request);
166 } 141 }
167 } 142 }
168 143
169 void PresentationDispatcher::sendArrayBuffer( 144 void PresentationDispatcher::sendArrayBuffer(
170 const blink::WebString& presentationUrl, 145 const blink::WebString& presentationUrl,
171 const blink::WebString& presentationId, 146 const blink::WebString& presentationId,
172 const uint8* data, 147 const uint8* data,
173 size_t length) { 148 size_t length) {
174 DCHECK(data); 149 DCHECK(data);
175 if (length > kMaxPresentationSessionMessageSize) { 150 if (length > kMaxPresentationSessionMessageSize) {
176 // TODO(crbug.com/459008): Same as in sendString(). 151 // TODO(crbug.com/459008): Same as in sendString().
177 LOG(WARNING) << "data size exceeded limit!"; 152 LOG(WARNING) << "data size exceeded limit!";
178 return; 153 return;
179 } 154 }
180 155
181 presentation::SessionMessage* session_message = 156 message_request_queue_.push(make_linked_ptr(
182 GetMojoSessionMessage(presentationUrl, presentationId, 157 GetSendDataMessageRequest(presentationUrl, presentationId,
183 presentation::PresentationMessageType:: 158 presentation::PresentationMessageType::
184 PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER, 159 PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER,
185 data, length); 160 data, length)));
186 message_request_queue_.push(make_linked_ptr(session_message));
187 // Start processing request if only one in the queue. 161 // Start processing request if only one in the queue.
188 if (message_request_queue_.size() == 1) { 162 if (message_request_queue_.size() == 1) {
189 const linked_ptr<presentation::SessionMessage>& request = 163 const linked_ptr<SendMessageRequest>& request =
190 message_request_queue_.front(); 164 message_request_queue_.front();
191 DoSendMessage(*request); 165 DoSendMessage(*request);
192 } 166 }
193 } 167 }
194 168
195 void PresentationDispatcher::sendBlobData( 169 void PresentationDispatcher::sendBlobData(
196 const blink::WebString& presentationUrl, 170 const blink::WebString& presentationUrl,
197 const blink::WebString& presentationId, 171 const blink::WebString& presentationId,
198 const uint8* data, 172 const uint8* data,
199 size_t length) { 173 size_t length) {
200 DCHECK(data); 174 DCHECK(data);
201 if (length > kMaxPresentationSessionMessageSize) { 175 if (length > kMaxPresentationSessionMessageSize) {
202 // TODO(crbug.com/459008): Same as in sendString(). 176 // TODO(crbug.com/459008): Same as in sendString().
203 LOG(WARNING) << "data size exceeded limit!"; 177 LOG(WARNING) << "data size exceeded limit!";
204 return; 178 return;
205 } 179 }
206 180
207 presentation::SessionMessage* session_message = GetMojoSessionMessage( 181 message_request_queue_.push(make_linked_ptr(GetSendDataMessageRequest(
208 presentationUrl, presentationId, 182 presentationUrl, presentationId,
209 presentation::PresentationMessageType::PRESENTATION_MESSAGE_TYPE_BLOB, 183 presentation::PresentationMessageType::PRESENTATION_MESSAGE_TYPE_BLOB,
210 data, length); 184 data, length)));
211 message_request_queue_.push(make_linked_ptr(session_message));
212 if (message_request_queue_.size() == 1) { 185 if (message_request_queue_.size() == 1) {
213 const linked_ptr<presentation::SessionMessage>& request = 186 const linked_ptr<SendMessageRequest>& request =
214 message_request_queue_.front(); 187 message_request_queue_.front();
215 DoSendMessage(*request); 188 DoSendMessage(*request);
216 } 189 }
217 } 190 }
218 191
219 void PresentationDispatcher::DoSendMessage( 192 void PresentationDispatcher::DoSendMessage(const SendMessageRequest& request) {
220 const presentation::SessionMessage& session_message) {
221 ConnectToPresentationServiceIfNeeded(); 193 ConnectToPresentationServiceIfNeeded();
222 presentation::SessionMessagePtr message_request(
223 presentation::SessionMessage::New());
224 message_request->presentation_url = session_message.presentation_url;
225 message_request->presentation_id = session_message.presentation_id;
226 message_request->type = session_message.type;
227 switch (session_message.type) {
228 case presentation::PresentationMessageType::
229 PRESENTATION_MESSAGE_TYPE_TEXT: {
230 message_request->message = session_message.message;
231 break;
232 }
233 case presentation::PresentationMessageType::
234 PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER:
235 case presentation::PresentationMessageType::
236 PRESENTATION_MESSAGE_TYPE_BLOB: {
237 message_request->data =
238 mojo::Array<uint8>::From(session_message.data.storage());
239 break;
240 }
241 default: {
242 NOTREACHED() << "Invalid presentation message type "
243 << session_message.type;
244 break;
245 }
246 }
247 194
248 presentation_service_->SendSessionMessage( 195 presentation_service_->SendSessionMessage(
249 message_request.Pass(), 196 request.session_info.Clone(), request.message.Clone(),
haibinlu 2015/07/30 23:16:30 why clone the potentially large message? move is b
imcheng 2015/08/03 18:56:33 Yes, it should be safe to use Pass() here. The |me
250 base::Bind(&PresentationDispatcher::HandleSendMessageRequests, 197 base::Bind(&PresentationDispatcher::HandleSendMessageRequests,
251 base::Unretained(this))); 198 base::Unretained(this)));
252 } 199 }
253 200
254 void PresentationDispatcher::HandleSendMessageRequests(bool success) { 201 void PresentationDispatcher::HandleSendMessageRequests(bool success) {
255 // In normal cases, message_request_queue_ should not be empty at this point 202 // In normal cases, message_request_queue_ should not be empty at this point
256 // of time, but when DidCommitProvisionalLoad() is invoked before receiving 203 // of time, but when DidCommitProvisionalLoad() is invoked before receiving
257 // the callback for previous send mojo call, queue would have been emptied. 204 // the callback for previous send mojo call, queue would have been emptied.
258 if (message_request_queue_.empty()) 205 if (message_request_queue_.empty())
259 return; 206 return;
260 207
261 if (!success) { 208 if (!success) {
262 // PresentationServiceImpl is informing that Frame has been detached or 209 // PresentationServiceImpl is informing that Frame has been detached or
263 // navigated away. Invalidate all pending requests. 210 // navigated away. Invalidate all pending requests.
264 MessageRequestQueue empty; 211 MessageRequestQueue empty;
265 std::swap(message_request_queue_, empty); 212 std::swap(message_request_queue_, empty);
266 return; 213 return;
267 } 214 }
268 215
269 message_request_queue_.pop(); 216 message_request_queue_.pop();
270 if (!message_request_queue_.empty()) { 217 if (!message_request_queue_.empty()) {
271 const linked_ptr<presentation::SessionMessage>& request = 218 const linked_ptr<SendMessageRequest>& request =
272 message_request_queue_.front(); 219 message_request_queue_.front();
273 DoSendMessage(*request); 220 DoSendMessage(*request);
274 } 221 }
275 } 222 }
276 223
277 void PresentationDispatcher::closeSession( 224 void PresentationDispatcher::closeSession(
278 const blink::WebString& presentationUrl, 225 const blink::WebString& presentationUrl,
279 const blink::WebString& presentationId) { 226 const blink::WebString& presentationId) {
280 ConnectToPresentationServiceIfNeeded(); 227 ConnectToPresentationServiceIfNeeded();
281 228
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 bool is_new_navigation, 267 bool is_new_navigation,
321 bool is_same_page_navigation) { 268 bool is_same_page_navigation) {
322 blink::WebFrame* frame = render_frame()->GetWebFrame(); 269 blink::WebFrame* frame = render_frame()->GetWebFrame();
323 // If not top-level navigation. 270 // If not top-level navigation.
324 if (frame->parent() || is_same_page_navigation) 271 if (frame->parent() || is_same_page_navigation)
325 return; 272 return;
326 273
327 // Remove all pending send message requests. 274 // Remove all pending send message requests.
328 MessageRequestQueue empty; 275 MessageRequestQueue empty;
329 std::swap(message_request_queue_, empty); 276 std::swap(message_request_queue_, empty);
330
331 listening_for_messages_ = false;
332 } 277 }
333 278
334 void PresentationDispatcher::OnScreenAvailabilityUpdated(bool available) { 279 void PresentationDispatcher::OnScreenAvailabilityUpdated(bool available) {
335 last_known_availability_ = available; 280 last_known_availability_ = available;
336 281
337 if (listening_state_ == ListeningState::Waiting) 282 if (listening_state_ == ListeningState::Waiting)
338 listening_state_ = ListeningState::Active; 283 listening_state_ = ListeningState::Active;
339 284
340 for (auto observer : availability_observers_) 285 for (auto observer : availability_observers_)
341 observer->availabilityChanged(available); 286 observer->availabilityChanged(available);
(...skipping 29 matching lines...) Expand all
371 if (!controller_) 316 if (!controller_)
372 return; 317 return;
373 318
374 // Reset the callback to get the next event. 319 // Reset the callback to get the next event.
375 presentation_service_->ListenForDefaultSessionStart(base::Bind( 320 presentation_service_->ListenForDefaultSessionStart(base::Bind(
376 &PresentationDispatcher::OnDefaultSessionStarted, 321 &PresentationDispatcher::OnDefaultSessionStarted,
377 base::Unretained(this))); 322 base::Unretained(this)));
378 323
379 if (!session_info.is_null()) { 324 if (!session_info.is_null()) {
380 controller_->didStartDefaultSession( 325 controller_->didStartDefaultSession(
381 new PresentationSessionClient(session_info.Pass())); 326 new PresentationSessionClient(session_info.Clone()));
382 StartListenForMessages(); 327 presentation_service_->ListenForSessionMessages(session_info.Pass());
383 } 328 }
384 } 329 }
385 330
386 void PresentationDispatcher::OnSessionCreated( 331 void PresentationDispatcher::OnSessionCreated(
387 blink::WebPresentationSessionClientCallbacks* callback, 332 blink::WebPresentationSessionClientCallbacks* callback,
388 presentation::PresentationSessionInfoPtr session_info, 333 presentation::PresentationSessionInfoPtr session_info,
389 presentation::PresentationErrorPtr error) { 334 presentation::PresentationErrorPtr error) {
390 DCHECK(callback); 335 DCHECK(callback);
391 if (!error.is_null()) { 336 if (!error.is_null()) {
392 DCHECK(session_info.is_null()); 337 DCHECK(session_info.is_null());
393 callback->onError(new blink::WebPresentationError( 338 callback->onError(new blink::WebPresentationError(
394 GetWebPresentationErrorTypeFromMojo(error->error_type), 339 GetWebPresentationErrorTypeFromMojo(error->error_type),
395 blink::WebString::fromUTF8(error->message))); 340 blink::WebString::fromUTF8(error->message)));
396 return; 341 return;
397 } 342 }
398 343
399 DCHECK(!session_info.is_null()); 344 DCHECK(!session_info.is_null());
400 callback->onSuccess(new PresentationSessionClient(session_info.Pass())); 345 callback->onSuccess(new PresentationSessionClient(session_info.Clone()));
401 StartListenForMessages(); 346 presentation_service_->ListenForSessionMessages(session_info.Pass());
402 }
403
404 void PresentationDispatcher::StartListenForMessages() {
405 if (listening_for_messages_)
406 return;
407
408 listening_for_messages_ = true;
409 presentation_service_->ListenForSessionMessages(
410 base::Bind(&PresentationDispatcher::OnSessionMessagesReceived,
411 base::Unretained(this)));
412 } 347 }
413 348
414 void PresentationDispatcher::OnSessionStateChanged( 349 void PresentationDispatcher::OnSessionStateChanged(
415 presentation::PresentationSessionInfoPtr session_info, 350 presentation::PresentationSessionInfoPtr session_info,
416 presentation::PresentationSessionState session_state) { 351 presentation::PresentationSessionState session_state) {
417 if (!controller_) 352 if (!controller_)
418 return; 353 return;
419 354
420 DCHECK(!session_info.is_null()); 355 DCHECK(!session_info.is_null());
421 controller_->didChangeSessionState( 356 controller_->didChangeSessionState(
422 new PresentationSessionClient(session_info.Pass()), 357 new PresentationSessionClient(session_info.Pass()),
423 GetWebPresentationSessionStateFromMojo(session_state)); 358 GetWebPresentationSessionStateFromMojo(session_state));
424 } 359 }
425 360
426 void PresentationDispatcher::OnSessionMessagesReceived( 361 void PresentationDispatcher::OnSessionMessagesReceived(
362 presentation::PresentationSessionInfoPtr session_info,
427 mojo::Array<presentation::SessionMessagePtr> messages) { 363 mojo::Array<presentation::SessionMessagePtr> messages) {
428 if (!listening_for_messages_) 364 if (!controller_)
429 return; // messages may come after the frame navigated.
430
431 // When messages is null, there is an error at presentation service side.
432 if (!controller_ || messages.is_null()) {
433 listening_for_messages_ = false;
434 return; 365 return;
435 }
436 366
437 for (size_t i = 0; i < messages.size(); ++i) { 367 for (size_t i = 0; i < messages.size(); ++i) {
438 // Note: Passing batches of messages to the Blink layer would be more 368 // Note: Passing batches of messages to the Blink layer would be more
439 // efficient. 369 // efficient.
440 scoped_ptr<PresentationSessionClient> session_client( 370 scoped_ptr<PresentationSessionClient> session_client(
441 new PresentationSessionClient(messages[i]->presentation_url, 371 new PresentationSessionClient(session_info->url, session_info->id));
442 messages[i]->presentation_id));
443 switch (messages[i]->type) { 372 switch (messages[i]->type) {
444 case presentation::PresentationMessageType:: 373 case presentation::PresentationMessageType::
445 PRESENTATION_MESSAGE_TYPE_TEXT: { 374 PRESENTATION_MESSAGE_TYPE_TEXT: {
446 controller_->didReceiveSessionTextMessage( 375 controller_->didReceiveSessionTextMessage(
447 session_client.release(), 376 session_client.release(),
448 blink::WebString::fromUTF8(messages[i]->message)); 377 blink::WebString::fromUTF8(messages[i]->message));
449 break; 378 break;
450 } 379 }
451 case presentation::PresentationMessageType:: 380 case presentation::PresentationMessageType::
452 PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER: 381 PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER:
453 case presentation::PresentationMessageType:: 382 case presentation::PresentationMessageType::
454 PRESENTATION_MESSAGE_TYPE_BLOB: { 383 PRESENTATION_MESSAGE_TYPE_BLOB: {
455 controller_->didReceiveSessionBinaryMessage( 384 controller_->didReceiveSessionBinaryMessage(
456 session_client.release(), &(messages[i]->data.front()), 385 session_client.release(), &(messages[i]->data.front()),
457 messages[i]->data.size()); 386 messages[i]->data.size());
458 break; 387 break;
459 } 388 }
460 default: { 389 default: {
461 NOTREACHED(); 390 NOTREACHED();
462 break; 391 break;
463 } 392 }
464 } 393 }
465 } 394 }
466
467 presentation_service_->ListenForSessionMessages(
468 base::Bind(&PresentationDispatcher::OnSessionMessagesReceived,
469 base::Unretained(this)));
470 } 395 }
471 396
472 void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() { 397 void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() {
473 if (presentation_service_.get()) 398 if (presentation_service_.get())
474 return; 399 return;
475 400
476 render_frame()->GetServiceRegistry()->ConnectToRemoteService( 401 render_frame()->GetServiceRegistry()->ConnectToRemoteService(
477 mojo::GetProxy(&presentation_service_)); 402 mojo::GetProxy(&presentation_service_));
478 presentation::PresentationServiceClientPtr client_ptr; 403 presentation::PresentationServiceClientPtr client_ptr;
479 binding_.Bind(GetProxy(&client_ptr)); 404 binding_.Bind(GetProxy(&client_ptr));
(...skipping 16 matching lines...) Expand all
496 ConnectToPresentationServiceIfNeeded(); 421 ConnectToPresentationServiceIfNeeded();
497 if (should_listen) { 422 if (should_listen) {
498 listening_state_ = ListeningState::Waiting; 423 listening_state_ = ListeningState::Waiting;
499 presentation_service_->ListenForScreenAvailability(); 424 presentation_service_->ListenForScreenAvailability();
500 } else { 425 } else {
501 listening_state_ = ListeningState::Inactive; 426 listening_state_ = ListeningState::Inactive;
502 presentation_service_->StopListeningForScreenAvailability(); 427 presentation_service_->StopListeningForScreenAvailability();
503 } 428 }
504 } 429 }
505 430
431 PresentationDispatcher::SendMessageRequest::SendMessageRequest(
432 presentation::PresentationSessionInfoPtr session_info,
433 presentation::SessionMessagePtr message)
434 : session_info(session_info.Pass()), message(message.Pass()) {}
435
436 PresentationDispatcher::SendMessageRequest::~SendMessageRequest() {}
437
438 // static
439 PresentationDispatcher::SendMessageRequest*
440 PresentationDispatcher::GetSendStringMessageRequest(
441 const blink::WebString& presentationUrl,
442 const blink::WebString& presentationId,
443 const blink::WebString& message) {
444 presentation::PresentationSessionInfoPtr session_info =
445 presentation::PresentationSessionInfo::New();
446 session_info->url = presentationUrl.utf8();
447 session_info->id = presentationId.utf8();
448
449 presentation::SessionMessagePtr session_message =
450 presentation::SessionMessage::New();
451 session_message->type =
452 presentation::PresentationMessageType::PRESENTATION_MESSAGE_TYPE_TEXT;
453 session_message->message = message.utf8();
454 return new SendMessageRequest(session_info.Pass(), session_message.Pass());
455 }
456
457 // static
458 PresentationDispatcher::SendMessageRequest*
459 PresentationDispatcher::GetSendDataMessageRequest(
460 const blink::WebString& presentationUrl,
461 const blink::WebString& presentationId,
462 presentation::PresentationMessageType type,
463 const uint8* data,
464 size_t length) {
465 presentation::PresentationSessionInfoPtr session_info =
466 presentation::PresentationSessionInfo::New();
467 session_info->url = presentationUrl.utf8();
468 session_info->id = presentationId.utf8();
469
470 presentation::SessionMessagePtr session_message =
471 presentation::SessionMessage::New();
472 session_message->type = type;
473 std::vector<uint8> tmp_data_vector(data, data + length);
474 session_message->data.Swap(&tmp_data_vector);
475 return new SendMessageRequest(session_info.Pass(), session_message.Pass());
476 }
477
506 } // namespace content 478 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698