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

Side by Side Diff: lib/html.dart

Issue 1747113003: Add an HTML implementation of WebSocketChannel. (Closed) Base URL: git@github.com:dart-lang/web_socket_channel.git@master
Patch Set: Code review changes Created 4 years, 9 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
« no previous file with comments | « README.md ('k') | test/html_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 import 'dart:async';
6 import 'dart:html';
7 import 'dart:typed_data';
8
9 import 'package:async/async.dart';
10 import 'package:stream_channel/stream_channel.dart';
11
12 import 'src/channel.dart';
13 import 'src/exception.dart';
14
15 /// A [WebSocketChannel] that communicates using a `dart:html` [WebSocket].
16 class HtmlWebSocketChannel extends StreamChannelMixin
17 implements WebSocketChannel {
18 /// The underlying `dart:html` [WebSocket].
19 final WebSocket _webSocket;
20
21 String get protocol => _webSocket.protocol;
22
23 int get closeCode => _closeCode;
24 int _closeCode;
25
26 String get closeReason => _closeReason;
27 String _closeReason;
28
29 /// The number of bytes of data that have been queued but not yet transmitted
30 /// to the network.
31 int get bufferedAmount => _webSocket.bufferedAmount;
32
33 /// The close code set by the local user.
34 ///
35 /// To ensure proper ordering, this is stored until we get a done event on
36 /// [_controller.local.stream].
37 int _localCloseCode;
38
39 /// The close reason set by the local user.
40 ///
41 /// To ensure proper ordering, this is stored until we get a done event on
42 /// [_controller.local.stream].
43 String _localCloseReason;
44
45 Stream get stream => _controller.foreign.stream;
46 final _controller = new StreamChannelController(
47 sync: true, allowForeignErrors: false);
48
49 WebSocketSink get sink => _sink;
50 WebSocketSink _sink;
51
52 /// Creates a new WebSocket connection.
53 ///
54 /// Connects to [url] using [new WebSocket] and returns a channel that can be
55 /// used to communicate over the resulting socket. The [url] may be either a
56 /// [String] or a [Uri]. The [protocols] parameter is the same as for
57 /// [new WebSocket].
58 ///
59 /// The [binaryType] parameter controls what type is used for binary messages
60 /// received by this socket. It defaults to [BinaryType.list], which causes
61 /// binary messages to be delivered as [Uint8List]s. If it's
62 /// [BinaryType.blob], they're delivered as [Blob]s instead.
63 HtmlWebSocketChannel.connect(url, {Iterable<String> protocols,
64 BinaryType binaryType})
65 : this(new WebSocket(url.toString(), protocols)
66 ..binaryType = (binaryType ?? BinaryType.list).value);
67
68 /// Creates a channel wrapping [webSocket].
69 HtmlWebSocketChannel(this._webSocket){
70 _sink = new _HtmlWebSocketSink(this);
71
72 if (_webSocket.readyState == WebSocket.OPEN) {
73 _listen();
74 } else {
75 // The socket API guarantees that only a single open event will be
76 // emitted.
77 _webSocket.onOpen.first.then((_) {
78 _listen();
79 });
80 }
81
82 // The socket API guarantees that only a single error event will be emitted,
83 // and that once it is no open or message events will be emitted.
84 _webSocket.onError.first.then((_) {
85 _controller.local.sink.addError(
86 new WebSocketChannelException("WebSocket connection failed."));
87 _controller.local.sink.close();
88 });
89
90 _webSocket.onMessage.listen((event) {
91 var data = event.data;
92 if (data is ByteBuffer) data = data.asUint8List();
93 _controller.local.sink.add(data);
94 });
95
96 // The socket API guarantees that only a single error event will be emitted,
97 // and that once it is no other events will be emitted.
98 _webSocket.onClose.first.then((event) {
99 _closeCode = event.code;
100 _closeReason = event.reason;
101 _controller.local.sink.close();
102 });
103 }
104
105 /// Pipes user events to [_webSocket].
106 void _listen() {
107 _controller.local.stream.listen((message) => _webSocket.send(message),
108 onDone: () => _webSocket.close(_localCloseCode, _localCloseReason));
109 }
110 }
111
112 /// A [WebSocketSink] that tracks the close code and reason passed to [close].
113 class _HtmlWebSocketSink extends DelegatingStreamSink implements WebSocketSink {
114 /// The channel to which this sink belongs.
115 final HtmlWebSocketChannel _channel;
116
117 _HtmlWebSocketSink(HtmlWebSocketChannel channel)
118 : super(channel._controller.foreign.sink),
119 _channel = channel;
120
121 Future close([int closeCode, String closeReason]) {
122 _channel._localCloseCode = closeCode;
123 _channel._localCloseReason = closeReason;
124 return super.close();
125 }
126 }
127
128 /// An enum for choosing what type [HtmlWebSocketChannel] emits for binary
129 /// messages.
130 class BinaryType {
131 /// Tells the channel to emit binary messages as [Blob]s.
132 static const blob = const BinaryType._("blob", "blob");
133
134 /// Tells the channel to emit binary messages as [Uint8List]s.
135 static const list = const BinaryType._("list", "arraybuffer");
136
137 /// The name of the binary type, which matches its variable name.
138 final String name;
139
140 /// The value as understood by the underlying [WebSocket] API.
141 final String value;
142
143 const BinaryType._(this.name, this.value);
144
145 String toString() => name;
146 }
OLDNEW
« no previous file with comments | « README.md ('k') | test/html_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698