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

Unified 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, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « README.md ('k') | test/html_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/html.dart
diff --git a/lib/html.dart b/lib/html.dart
new file mode 100644
index 0000000000000000000000000000000000000000..9d0b070150753daf8246285bd6946beec7747107
--- /dev/null
+++ b/lib/html.dart
@@ -0,0 +1,146 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:async/async.dart';
+import 'package:stream_channel/stream_channel.dart';
+
+import 'src/channel.dart';
+import 'src/exception.dart';
+
+/// A [WebSocketChannel] that communicates using a `dart:html` [WebSocket].
+class HtmlWebSocketChannel extends StreamChannelMixin
+ implements WebSocketChannel {
+ /// The underlying `dart:html` [WebSocket].
+ final WebSocket _webSocket;
+
+ String get protocol => _webSocket.protocol;
+
+ int get closeCode => _closeCode;
+ int _closeCode;
+
+ String get closeReason => _closeReason;
+ String _closeReason;
+
+ /// The number of bytes of data that have been queued but not yet transmitted
+ /// to the network.
+ int get bufferedAmount => _webSocket.bufferedAmount;
+
+ /// The close code set by the local user.
+ ///
+ /// To ensure proper ordering, this is stored until we get a done event on
+ /// [_controller.local.stream].
+ int _localCloseCode;
+
+ /// The close reason set by the local user.
+ ///
+ /// To ensure proper ordering, this is stored until we get a done event on
+ /// [_controller.local.stream].
+ String _localCloseReason;
+
+ Stream get stream => _controller.foreign.stream;
+ final _controller = new StreamChannelController(
+ sync: true, allowForeignErrors: false);
+
+ WebSocketSink get sink => _sink;
+ WebSocketSink _sink;
+
+ /// Creates a new WebSocket connection.
+ ///
+ /// Connects to [url] using [new WebSocket] and returns a channel that can be
+ /// used to communicate over the resulting socket. The [url] may be either a
+ /// [String] or a [Uri]. The [protocols] parameter is the same as for
+ /// [new WebSocket].
+ ///
+ /// The [binaryType] parameter controls what type is used for binary messages
+ /// received by this socket. It defaults to [BinaryType.list], which causes
+ /// binary messages to be delivered as [Uint8List]s. If it's
+ /// [BinaryType.blob], they're delivered as [Blob]s instead.
+ HtmlWebSocketChannel.connect(url, {Iterable<String> protocols,
+ BinaryType binaryType})
+ : this(new WebSocket(url.toString(), protocols)
+ ..binaryType = (binaryType ?? BinaryType.list).value);
+
+ /// Creates a channel wrapping [webSocket].
+ HtmlWebSocketChannel(this._webSocket){
+ _sink = new _HtmlWebSocketSink(this);
+
+ if (_webSocket.readyState == WebSocket.OPEN) {
+ _listen();
+ } else {
+ // The socket API guarantees that only a single open event will be
+ // emitted.
+ _webSocket.onOpen.first.then((_) {
+ _listen();
+ });
+ }
+
+ // The socket API guarantees that only a single error event will be emitted,
+ // and that once it is no open or message events will be emitted.
+ _webSocket.onError.first.then((_) {
+ _controller.local.sink.addError(
+ new WebSocketChannelException("WebSocket connection failed."));
+ _controller.local.sink.close();
+ });
+
+ _webSocket.onMessage.listen((event) {
+ var data = event.data;
+ if (data is ByteBuffer) data = data.asUint8List();
+ _controller.local.sink.add(data);
+ });
+
+ // The socket API guarantees that only a single error event will be emitted,
+ // and that once it is no other events will be emitted.
+ _webSocket.onClose.first.then((event) {
+ _closeCode = event.code;
+ _closeReason = event.reason;
+ _controller.local.sink.close();
+ });
+ }
+
+ /// Pipes user events to [_webSocket].
+ void _listen() {
+ _controller.local.stream.listen((message) => _webSocket.send(message),
+ onDone: () => _webSocket.close(_localCloseCode, _localCloseReason));
+ }
+}
+
+/// A [WebSocketSink] that tracks the close code and reason passed to [close].
+class _HtmlWebSocketSink extends DelegatingStreamSink implements WebSocketSink {
+ /// The channel to which this sink belongs.
+ final HtmlWebSocketChannel _channel;
+
+ _HtmlWebSocketSink(HtmlWebSocketChannel channel)
+ : super(channel._controller.foreign.sink),
+ _channel = channel;
+
+ Future close([int closeCode, String closeReason]) {
+ _channel._localCloseCode = closeCode;
+ _channel._localCloseReason = closeReason;
+ return super.close();
+ }
+}
+
+/// An enum for choosing what type [HtmlWebSocketChannel] emits for binary
+/// messages.
+class BinaryType {
+ /// Tells the channel to emit binary messages as [Blob]s.
+ static const blob = const BinaryType._("blob", "blob");
+
+ /// Tells the channel to emit binary messages as [Uint8List]s.
+ static const list = const BinaryType._("list", "arraybuffer");
+
+ /// The name of the binary type, which matches its variable name.
+ final String name;
+
+ /// The value as understood by the underlying [WebSocket] API.
+ final String value;
+
+ const BinaryType._(this.name, this.value);
+
+ String toString() => name;
+}
« 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