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.
5 #include "components/html_viewer/web_socket_handle_impl.h"
10 #include "base/macros.h"
11 #include "base/memory/scoped_vector.h"
12 #include "components/html_viewer/blink_basic_type_converters.h"
13 #include "mojo/services/network/public/cpp/web_socket_read_queue.h"
14 #include "mojo/services/network/public/cpp/web_socket_write_queue.h"
15 #include "mojo/services/network/public/interfaces/network_service.mojom.h"
16 #include "third_party/WebKit/public/platform/WebSerializedOrigin.h"
17 #include "third_party/WebKit/public/platform/WebSocketHandleClient.h"
18 #include "third_party/WebKit/public/platform/WebString.h"
19 #include "third_party/WebKit/public/platform/WebURL.h"
20 #include "third_party/WebKit/public/platform/WebVector.h"
22 using blink::WebSerializedOrigin
;
23 using blink::WebSocketHandle
;
24 using blink::WebSocketHandleClient
;
25 using blink::WebString
;
27 using blink::WebVector
;
29 using mojo::ConvertTo
;
31 using mojo::WebSocket
;
32 using mojo::WebSocketReadQueue
;
37 struct TypeConverter
<WebSocket::MessageType
, WebSocketHandle::MessageType
> {
38 static WebSocket::MessageType
Convert(WebSocketHandle::MessageType type
) {
39 DCHECK(type
== WebSocketHandle::MessageTypeContinuation
||
40 type
== WebSocketHandle::MessageTypeText
||
41 type
== WebSocketHandle::MessageTypeBinary
);
42 typedef WebSocket::MessageType MessageType
;
44 static_cast<MessageType
>(WebSocketHandle::MessageTypeContinuation
) ==
45 WebSocket::MESSAGE_TYPE_CONTINUATION
,
46 enum_values_must_match_for_message_type
);
48 static_cast<MessageType
>(WebSocketHandle::MessageTypeText
) ==
49 WebSocket::MESSAGE_TYPE_TEXT
,
50 enum_values_must_match_for_message_type
);
52 static_cast<MessageType
>(WebSocketHandle::MessageTypeBinary
) ==
53 WebSocket::MESSAGE_TYPE_BINARY
,
54 enum_values_must_match_for_message_type
);
55 return static_cast<WebSocket::MessageType
>(type
);
60 struct TypeConverter
<WebSocketHandle::MessageType
, WebSocket::MessageType
> {
61 static WebSocketHandle::MessageType
Convert(WebSocket::MessageType type
) {
62 DCHECK(type
== WebSocket::MESSAGE_TYPE_CONTINUATION
||
63 type
== WebSocket::MESSAGE_TYPE_TEXT
||
64 type
== WebSocket::MESSAGE_TYPE_BINARY
);
65 return static_cast<WebSocketHandle::MessageType
>(type
);
71 namespace html_viewer
{
73 // This class forms a bridge from the mojo WebSocketClient interface and the
74 // Blink WebSocketHandleClient interface.
75 class WebSocketClientImpl
: public mojo::InterfaceImpl
<mojo::WebSocketClient
> {
77 explicit WebSocketClientImpl(WebSocketHandleImpl
* handle
,
78 blink::WebSocketHandleClient
* client
)
79 : handle_(handle
), client_(client
) {}
80 ~WebSocketClientImpl() override
{}
83 // WebSocketClient methods:
84 void DidConnect(const String
& selected_subprotocol
,
85 const String
& extensions
,
86 mojo::ScopedDataPipeConsumerHandle receive_stream
) override
{
87 blink::WebSocketHandleClient
* client
= client_
;
88 WebSocketHandleImpl
* handle
= handle_
;
89 receive_stream_
= receive_stream
.Pass();
90 read_queue_
.reset(new WebSocketReadQueue(receive_stream_
.get()));
91 client
->didConnect(handle
,
92 selected_subprotocol
.To
<WebString
>(),
93 extensions
.To
<WebString
>());
94 // |handle| can be deleted here.
97 void DidReceiveData(bool fin
,
98 WebSocket::MessageType type
,
99 uint32_t num_bytes
) override
{
100 read_queue_
->Read(num_bytes
,
101 base::Bind(&WebSocketClientImpl::DidReadFromReceiveStream
,
102 base::Unretained(this),
103 fin
, type
, num_bytes
));
106 void DidReceiveFlowControl(int64_t quota
) override
{
107 client_
->didReceiveFlowControl(handle_
, quota
);
108 // |handle| can be deleted here.
111 void DidFail(const String
& message
) override
{
112 blink::WebSocketHandleClient
* client
= client_
;
113 WebSocketHandleImpl
* handle
= handle_
;
114 handle
->Disconnect(); // deletes |this|
115 client
->didFail(handle
, message
.To
<WebString
>());
116 // |handle| can be deleted here.
119 void DidClose(bool was_clean
, uint16_t code
, const String
& reason
) override
{
120 blink::WebSocketHandleClient
* client
= client_
;
121 WebSocketHandleImpl
* handle
= handle_
;
122 handle
->Disconnect(); // deletes |this|
123 client
->didClose(handle
, was_clean
, code
, reason
.To
<WebString
>());
124 // |handle| can be deleted here.
127 void DidReadFromReceiveStream(bool fin
,
128 WebSocket::MessageType type
,
131 client_
->didReceiveData(handle_
,
133 ConvertTo
<WebSocketHandle::MessageType
>(type
),
136 // |handle_| can be deleted here.
139 // |handle_| owns this object, so it is guaranteed to outlive us.
140 WebSocketHandleImpl
* handle_
;
141 blink::WebSocketHandleClient
* client_
;
142 mojo::ScopedDataPipeConsumerHandle receive_stream_
;
143 scoped_ptr
<WebSocketReadQueue
> read_queue_
;
145 DISALLOW_COPY_AND_ASSIGN(WebSocketClientImpl
);
148 WebSocketHandleImpl::WebSocketHandleImpl(mojo::NetworkService
* network_service
)
149 : did_close_(false) {
150 network_service
->CreateWebSocket(GetProxy(&web_socket_
));
153 WebSocketHandleImpl::~WebSocketHandleImpl() {
155 // The connection is abruptly disconnected by the renderer without
156 // closing handshake.
157 web_socket_
->Close(WebSocket::kAbnormalCloseCode
, String());
161 void WebSocketHandleImpl::connect(const WebURL
& url
,
162 const WebVector
<WebString
>& protocols
,
163 const WebSerializedOrigin
& origin
,
164 WebSocketHandleClient
* client
) {
165 client_
.reset(new WebSocketClientImpl(this, client
));
166 mojo::WebSocketClientPtr client_ptr
;
167 // TODO(mpcomplete): Is this the right ownership model? Or should mojo own
169 WeakBindToProxy(client_
.get(), &client_ptr
);
171 mojo::DataPipe data_pipe
;
172 send_stream_
= data_pipe
.producer_handle
.Pass();
173 write_queue_
.reset(new mojo::WebSocketWriteQueue(send_stream_
.get()));
174 web_socket_
->Connect(url
.string().utf8(),
175 mojo::Array
<String
>::From(protocols
),
176 origin
.string().utf8(), data_pipe
.consumer_handle
.Pass(),
180 void WebSocketHandleImpl::send(bool fin
,
181 WebSocketHandle::MessageType type
,
187 uint32_t size32
= static_cast<uint32_t>(size
);
190 base::Bind(&WebSocketHandleImpl::DidWriteToSendStream
,
191 base::Unretained(this),
195 void WebSocketHandleImpl::flowControl(int64_t quota
) {
199 web_socket_
->FlowControl(quota
);
202 void WebSocketHandleImpl::close(unsigned short code
, const WebString
& reason
) {
203 web_socket_
->Close(code
, reason
.utf8());
206 void WebSocketHandleImpl::DidWriteToSendStream(
208 WebSocketHandle::MessageType type
,
211 web_socket_
->Send(fin
, ConvertTo
<WebSocket::MessageType
>(type
), num_bytes
);
214 void WebSocketHandleImpl::Disconnect() {
219 } // namespace html_viewer