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

Side by Side Diff: mojo/services/network/web_socket_impl.cc

Issue 515923003: Mojo: Add a WebSocket/Client interface and hook it up to the HTML viewer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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 "mojo/services/network/web_socket_impl.h"
6
7 #include "base/logging.h"
8 #include "mojo/services/network/network_context.h"
9 #include "net/websockets/websocket_channel.h"
10 #include "net/websockets/websocket_errors.h"
11 #include "net/websockets/websocket_event_interface.h"
12 #include "net/websockets/websocket_frame.h" // for WebSocketFrameHeader::OpCode
13 #include "net/websockets/websocket_handshake_request_info.h"
14 #include "net/websockets/websocket_handshake_response_info.h"
15 #include "url/origin.h"
16
17 namespace mojo {
18
19 template <>
20 class TypeConverter<net::WebSocketFrameHeader::OpCode, WebSocket::MessageType> {
21 public:
22 static net::WebSocketFrameHeader::OpCode ConvertFrom(
23 WebSocket::MessageType type) {
24 DCHECK(type == WebSocket::MESSAGE_TYPE_CONTINUATION ||
25 type == WebSocket::MESSAGE_TYPE_TEXT ||
26 type == WebSocket::MESSAGE_TYPE_BINARY);
27 typedef net::WebSocketFrameHeader::OpCode OpCode;
28 // These compile asserts verify that the same underlying values are used for
29 // both types, so we can simply cast between them.
30 COMPILE_ASSERT(static_cast<OpCode>(WebSocket::MESSAGE_TYPE_CONTINUATION) ==
31 net::WebSocketFrameHeader::kOpCodeContinuation,
32 enum_values_must_match_for_opcode_continuation);
33 COMPILE_ASSERT(static_cast<OpCode>(WebSocket::MESSAGE_TYPE_TEXT) ==
34 net::WebSocketFrameHeader::kOpCodeText,
35 enum_values_must_match_for_opcode_text);
36 COMPILE_ASSERT(static_cast<OpCode>(WebSocket::MESSAGE_TYPE_BINARY) ==
37 net::WebSocketFrameHeader::kOpCodeBinary,
38 enum_values_must_match_for_opcode_binary);
39 return static_cast<OpCode>(type);
40 }
41 };
42
43 template <>
44 class TypeConverter<WebSocket::MessageType, net::WebSocketFrameHeader::OpCode> {
45 public:
46 static WebSocket::MessageType ConvertFrom(
47 net::WebSocketFrameHeader::OpCode type) {
48 DCHECK(type == net::WebSocketFrameHeader::kOpCodeContinuation ||
49 type == net::WebSocketFrameHeader::kOpCodeText ||
50 type == net::WebSocketFrameHeader::kOpCodeBinary);
51 return static_cast<WebSocket::MessageType>(type);
52 }
53 };
54
55 // TODO(mpcomplete): remove this.
56 template <typename T, typename U>
57 inline T ConvertTo(const U& obj) {
58 return TypeConverter<T, U>::ConvertFrom(obj);
59 }
60
61 namespace {
62
63 typedef net::WebSocketEventInterface::ChannelState ChannelState;
64
65 class WebSocketEventHandler : public net::WebSocketEventInterface {
66 public:
67 WebSocketEventHandler(WebSocketClientPtr client)
68 : client_(client.Pass()) {
69 }
70 virtual ~WebSocketEventHandler() {}
71
72 private:
73 // net::WebSocketEventInterface methods:
74 virtual ChannelState OnAddChannelResponse(
75 bool fail,
76 const std::string& selected_subprotocol,
77 const std::string& extensions) OVERRIDE;
78 virtual ChannelState OnDataFrame(bool fin,
79 WebSocketMessageType type,
80 const std::vector<char>& data) OVERRIDE;
81 virtual ChannelState OnClosingHandshake() OVERRIDE;
82 virtual ChannelState OnFlowControl(int64 quota) OVERRIDE;
83 virtual ChannelState OnDropChannel(bool was_clean,
84 uint16 code,
85 const std::string& reason) OVERRIDE;
86 virtual ChannelState OnFailChannel(const std::string& message) OVERRIDE;
87 virtual ChannelState OnStartOpeningHandshake(
88 scoped_ptr<net::WebSocketHandshakeRequestInfo> request) OVERRIDE;
89 virtual ChannelState OnFinishOpeningHandshake(
90 scoped_ptr<net::WebSocketHandshakeResponseInfo> response) OVERRIDE;
91 virtual ChannelState OnSSLCertificateError(
92 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
93 const GURL& url,
94 const net::SSLInfo& ssl_info,
95 bool fatal) OVERRIDE;
96
97 WebSocketClientPtr client_;
98
99 DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
100 };
101
102 ChannelState WebSocketEventHandler::OnAddChannelResponse(
103 bool fail,
104 const std::string& selected_protocol,
105 const std::string& extensions) {
106 client_->DidConnect(fail, selected_protocol, extensions);
107 return WebSocketEventInterface::CHANNEL_ALIVE;
108 }
109
110 ChannelState WebSocketEventHandler::OnDataFrame(
111 bool fin,
112 net::WebSocketFrameHeader::OpCode type,
113 const std::vector<char>& data) {
114 // TODO(mpcomplete): reuse the data pipe for subsequent frames.
115 uint32_t num_bytes = static_cast<uint32_t>(data.size());
116 MojoCreateDataPipeOptions options;
117 options.struct_size = sizeof(MojoCreateDataPipeOptions);
118 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
119 options.element_num_bytes = 1;
120 options.capacity_num_bytes = num_bytes;
121 DataPipe data_pipe(options);
122 WriteDataRaw(data_pipe.producer_handle.get(),
123 &data[0],
124 &num_bytes,
125 MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
126 client_->DidReceiveData(fin, ConvertTo<WebSocket::MessageType>(type),
127 data_pipe.consumer_handle.Pass());
128 return WebSocketEventInterface::CHANNEL_ALIVE;
129 }
130
131 ChannelState WebSocketEventHandler::OnClosingHandshake() {
132 return WebSocketEventInterface::CHANNEL_ALIVE;
133 }
134
135 ChannelState WebSocketEventHandler::OnFlowControl(int64 quota) {
136 client_->DidReceiveFlowControl(quota);
137 return WebSocketEventInterface::CHANNEL_ALIVE;
138 }
139
140 ChannelState WebSocketEventHandler::OnDropChannel(bool was_clean,
141 uint16 code,
142 const std::string& reason) {
143 return WebSocketEventInterface::CHANNEL_ALIVE;
144 }
145
146 ChannelState WebSocketEventHandler::OnFailChannel(const std::string& message) {
147 return WebSocketEventInterface::CHANNEL_ALIVE;
148 }
149
150 ChannelState WebSocketEventHandler::OnStartOpeningHandshake(
151 scoped_ptr<net::WebSocketHandshakeRequestInfo> request) {
152 return WebSocketEventInterface::CHANNEL_ALIVE;
153 }
154
155 ChannelState WebSocketEventHandler::OnFinishOpeningHandshake(
156 scoped_ptr<net::WebSocketHandshakeResponseInfo> response) {
157 return WebSocketEventInterface::CHANNEL_ALIVE;
158 }
159
160 ChannelState WebSocketEventHandler::OnSSLCertificateError(
161 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
162 const GURL& url,
163 const net::SSLInfo& ssl_info,
164 bool fatal) {
165 // The above method is always asynchronous.
166 return WebSocketEventInterface::CHANNEL_ALIVE;
167 }
168
169 } // namespace mojo
170
171 WebSocketImpl::WebSocketImpl(NetworkContext* context) : context_(context) {
172 }
173
174 WebSocketImpl::~WebSocketImpl() {
175 }
176
177 void WebSocketImpl::Connect(const String& url,
178 Array<String> protocols,
179 const String& origin,
180 WebSocketClientPtr client) {
181 DCHECK(!channel_);
182 scoped_ptr<net::WebSocketEventInterface> event_interface(
183 new WebSocketEventHandler(client.Pass()));
184 channel_.reset(new net::WebSocketChannel(event_interface.Pass(),
185 context_->url_request_context()));
186 channel_->SendAddChannelRequest(GURL(url.get()),
187 protocols.To<std::vector<std::string> >(),
188 url::Origin(origin.get()));
189 }
190
191 void WebSocketImpl::Send(bool fin,
192 WebSocket::MessageType type,
193 ScopedDataPipeConsumerHandle data_pipe) {
194 DCHECK(channel_);
195 uint32_t num_bytes;
196 ReadDataRaw(data_pipe.get(), NULL, &num_bytes, MOJO_READ_DATA_FLAG_QUERY);
197 std::vector<char> data(num_bytes);
198 ReadDataRaw(data_pipe.get(), &data[0], &num_bytes, MOJO_READ_DATA_FLAG_NONE);
199 channel_->SendFrame(
200 fin, ConvertTo<net::WebSocketFrameHeader::OpCode>(type), data);
201 }
202
203 void WebSocketImpl::FlowControl(int64_t quota) {
204 DCHECK(channel_);
205 channel_->SendFlowControl(quota);
206 }
207
208 void WebSocketImpl::Close(int16_t code, const String& reason) {
209 DCHECK(channel_);
210 channel_->StartClosingHandshake(code, reason);
211 }
212
213
214 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698