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 "mojo/services/html_viewer/websockethandle_impl.h"
10 #include "base/macros.h"
11 #include "base/memory/scoped_vector.h"
12 #include "mojo/services/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(bool fail
,
85 const String
& selected_subprotocol
,
86 const String
& extensions
,
87 mojo::ScopedDataPipeConsumerHandle receive_stream
) override
{
88 blink::WebSocketHandleClient
* client
= client_
;
89 WebSocketHandleImpl
* handle
= handle_
;
90 receive_stream_
= receive_stream
.Pass();
91 read_queue_
.reset(new WebSocketReadQueue(receive_stream_
.get()));
93 handle
->Disconnect(); // deletes |this|
94 client
->didConnect(handle
,
96 selected_subprotocol
.To
<WebString
>(),
97 extensions
.To
<WebString
>());
98 // |handle| can be deleted here.
101 void DidReceiveData(bool fin
,
102 WebSocket::MessageType type
,
103 uint32_t num_bytes
) override
{
104 read_queue_
->Read(num_bytes
,
105 base::Bind(&WebSocketClientImpl::DidReadFromReceiveStream
,
106 base::Unretained(this),
107 fin
, type
, num_bytes
));
110 void DidReceiveFlowControl(int64_t quota
) override
{
111 client_
->didReceiveFlowControl(handle_
, quota
);
112 // |handle| can be deleted here.
115 void DidFail(const String
& message
) override
{
116 blink::WebSocketHandleClient
* client
= client_
;
117 WebSocketHandleImpl
* handle
= handle_
;
118 handle
->Disconnect(); // deletes |this|
119 client
->didFail(handle
, message
.To
<WebString
>());
120 // |handle| can be deleted here.
123 void DidClose(bool was_clean
, uint16_t code
, const String
& reason
) override
{
124 blink::WebSocketHandleClient
* client
= client_
;
125 WebSocketHandleImpl
* handle
= handle_
;
126 handle
->Disconnect(); // deletes |this|
127 client
->didClose(handle
, was_clean
, code
, reason
.To
<WebString
>());
128 // |handle| can be deleted here.
131 void DidReadFromReceiveStream(bool fin
,
132 WebSocket::MessageType type
,
135 client_
->didReceiveData(handle_
,
137 ConvertTo
<WebSocketHandle::MessageType
>(type
),
140 // |handle_| can be deleted here.
143 // |handle_| owns this object, so it is guaranteed to outlive us.
144 WebSocketHandleImpl
* handle_
;
145 blink::WebSocketHandleClient
* client_
;
146 mojo::ScopedDataPipeConsumerHandle receive_stream_
;
147 scoped_ptr
<WebSocketReadQueue
> read_queue_
;
149 DISALLOW_COPY_AND_ASSIGN(WebSocketClientImpl
);
152 WebSocketHandleImpl::WebSocketHandleImpl(mojo::NetworkService
* network_service
)
153 : did_close_(false) {
154 network_service
->CreateWebSocket(GetProxy(&web_socket_
));
157 WebSocketHandleImpl::~WebSocketHandleImpl() {
159 // The connection is abruptly disconnected by the renderer without
160 // closing handshake.
161 web_socket_
->Close(WebSocket::kAbnormalCloseCode
, String());
165 void WebSocketHandleImpl::connect(const WebURL
& url
,
166 const WebVector
<WebString
>& protocols
,
167 const WebSerializedOrigin
& origin
,
168 WebSocketHandleClient
* client
) {
169 client_
.reset(new WebSocketClientImpl(this, client
));
170 mojo::WebSocketClientPtr client_ptr
;
171 // TODO(mpcomplete): Is this the right ownership model? Or should mojo own
173 WeakBindToProxy(client_
.get(), &client_ptr
);
175 mojo::DataPipe data_pipe
;
176 send_stream_
= data_pipe
.producer_handle
.Pass();
177 write_queue_
.reset(new mojo::WebSocketWriteQueue(send_stream_
.get()));
178 web_socket_
->Connect(url
.string().utf8(),
179 mojo::Array
<String
>::From(protocols
),
180 origin
.string().utf8(), data_pipe
.consumer_handle
.Pass(),
184 void WebSocketHandleImpl::send(bool fin
,
185 WebSocketHandle::MessageType type
,
191 uint32_t size32
= static_cast<uint32_t>(size
);
194 base::Bind(&WebSocketHandleImpl::DidWriteToSendStream
,
195 base::Unretained(this),
199 void WebSocketHandleImpl::flowControl(int64_t quota
) {
203 web_socket_
->FlowControl(quota
);
206 void WebSocketHandleImpl::close(unsigned short code
, const WebString
& reason
) {
207 web_socket_
->Close(code
, reason
.utf8());
210 void WebSocketHandleImpl::DidWriteToSendStream(
212 WebSocketHandle::MessageType type
,
215 web_socket_
->Send(fin
, ConvertTo
<WebSocket::MessageType
>(type
), num_bytes
);
218 void WebSocketHandleImpl::Disconnect() {
223 } // namespace html_viewer