Merge pull request #45 from jakemac53/disable-implicit-casts

turn on implicit casts, fix Page.reload
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 2477cd0..715751a 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,3 +1,5 @@
 analyzer:
   errors:
     deprecated_member_use_from_same_package: ignore
+  strong-mode:
+    implicit-casts: false
\ No newline at end of file
diff --git a/bin/multiplex.dart b/bin/multiplex.dart
index 69b87f5..2b512eb 100644
--- a/bin/multiplex.dart
+++ b/bin/multiplex.dart
@@ -23,7 +23,7 @@
 
   hierarchicalLoggingEnabled = true;
 
-  if (args['verbose']) {
+  if (args['verbose'] == true) {
     Logger.root.level = Level.ALL;
   } else {
     Logger.root.level = Level.WARNING;
@@ -33,7 +33,8 @@
     stderr.writeln('${rec.level.name}: ${rec.time}: ${rec.message}');
   });
 
-  var cr =
-      new ChromeConnection(args['chrome_host'], int.parse(args['chrome_port']));
-  new Server(int.parse(args['listen_port']), cr, modelDom: args['model_dom']);
+  var cr = new ChromeConnection(
+      args['chrome_host'] as String, int.parse(args['chrome_port'] as String));
+  new Server(int.parse(args['listen_port'] as String), cr,
+      modelDom: args['model_dom'] as bool);
 }
diff --git a/changelog.md b/changelog.md
index 3fffa01..32c3b99 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,9 @@
 # webkit_inspection_protocol.dart
 
+## 0.4.1
+- Fix `page.reload` method.
+- Disable implicit casts when developing this package.
+
 ## 0.4.0
 - Change the `RemoteObject.value` return type to `Object`.
 
diff --git a/lib/forwarder.dart b/lib/forwarder.dart
index 298d9b4..85f9f47 100644
--- a/lib/forwarder.dart
+++ b/lib/forwarder.dart
@@ -32,7 +32,7 @@
   final StreamController<Null> _closedController =
       new StreamController.broadcast();
 
-  factory WipForwarder(WipConnection debugger, Stream stream,
+  factory WipForwarder(WipConnection debugger, Stream<String> stream,
       {StreamSink sink, WipDom domModel}) {
     if (sink == null) {
       sink = stream as StreamSink;
@@ -52,8 +52,8 @@
     var response = {'id': json['id']};
     _log.info('Forwarding to debugger: $data');
     try {
-      String method = json['method'];
-      Map<String, dynamic> params = json['params'];
+      var method = json['method'] as String;
+      var params = json['params'] as Map<String, dynamic>;
       bool processed = false;
 
       if (method.contains('reakpoint')) {
@@ -68,7 +68,7 @@
             break;
           case 'DOM.getAttributes':
             var attributes = flattenAttributesMap(
-                await domModel.getAttributes(params['nodeId']));
+                await domModel.getAttributes(params['nodeId'] as int));
             response['result'] = {'attributes': attributes};
             processed = true;
             break;
diff --git a/lib/multiplex.dart b/lib/multiplex.dart
index 4a5d8a0..d877ded 100644
--- a/lib/multiplex.dart
+++ b/lib/multiplex.dart
@@ -11,6 +11,8 @@
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:shelf/shelf_io.dart' as io;
 import 'package:shelf_web_socket/shelf_web_socket.dart' as ws;
+import 'package:web_socket_channel/web_socket_channel.dart'
+    show WebSocketChannel;
 import 'package:webkit_inspection_protocol/dom_model.dart' show WipDomModel;
 import 'package:webkit_inspection_protocol/forwarder.dart' show WipForwarder;
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
@@ -124,19 +126,19 @@
     }
     _log.info('connecting to websocket: ${request.url}');
 
-    return ws.webSocketHandler((ws) async {
+    return ws.webSocketHandler((WebSocketChannel webSocket) async {
       var debugger = await _connections.putIfAbsent(path[2], () async {
         var tab = await chrome.getTab((tab) => tab.id == path[2]);
         return WipConnection.connect(tab.webSocketDebuggerUrl);
       });
-      var dom;
+      WipDomModel dom;
       if (modelDom) {
         dom = await _modelDoms.putIfAbsent(path[2], () {
           return new WipDomModel(debugger.dom);
         });
       }
-      var forwarder =
-          new WipForwarder(debugger, ws.stream, sink: ws.sink, domModel: dom);
+      var forwarder = new WipForwarder(debugger, webSocket.stream.cast(),
+          sink: webSocket.sink, domModel: dom);
       debugger.onClose.listen((_) {
         _connections.remove(path[2]);
         _modelDoms.remove(path[2]);
diff --git a/lib/src/console.dart b/lib/src/console.dart
index ec69683..e54f300 100644
--- a/lib/src/console.dart
+++ b/lib/src/console.dart
@@ -24,16 +24,16 @@
 class ConsoleMessageEvent extends WrappedWipEvent {
   ConsoleMessageEvent(WipEvent event) : super(event);
 
-  Map get _message => params['message'];
+  Map get _message => params['message'] as Map;
 
-  String get text => _message['text'];
-  String get level => _message['level'];
-  String get url => _message['url'];
+  String get text => _message['text'] as String;
+  String get level => _message['level'] as String;
+  String get url => _message['url'] as String;
 
   Iterable<WipConsoleCallFrame> getStackTrace() {
     if (_message.containsKey('stackTrace')) {
-      return params['stackTrace']
-          .map((frame) => new WipConsoleCallFrame.fromMap(frame));
+      return (params['stackTrace'] as List).map((frame) =>
+          new WipConsoleCallFrame.fromMap(frame as Map<String, dynamic>));
     } else {
       return [];
     }
@@ -51,9 +51,9 @@
 
   WipConsoleCallFrame.fromMap(this._map);
 
-  int get columnNumber => _map['columnNumber'];
-  String get functionName => _map['functionName'];
-  int get lineNumber => _map['lineNumber'];
-  String get scriptId => _map['scriptId'];
-  String get url => _map['url'];
+  int get columnNumber => _map['columnNumber'] as int;
+  String get functionName => _map['functionName'] as String;
+  int get lineNumber => _map['lineNumber'] as int;
+  String get scriptId => _map['scriptId'] as String;
+  String get url => _map['url'] as String;
 }
diff --git a/lib/src/debugger.dart b/lib/src/debugger.dart
index 980b500..5e48c6f 100644
--- a/lib/src/debugger.dart
+++ b/lib/src/debugger.dart
@@ -24,7 +24,7 @@
   Future<String> getScriptSource(String scriptId) async =>
       (await sendCommand('Debugger.getScriptSource',
               params: {'scriptId': scriptId}))
-          .result['scriptSource'];
+          .result['scriptSource'] as String;
 
   Future pause() => sendCommand('Debugger.pause');
   Future resume() => sendCommand('Debugger.resume');
@@ -85,11 +85,11 @@
 class DebuggerPausedEvent extends WrappedWipEvent {
   DebuggerPausedEvent(WipEvent event) : super(event);
 
-  String get reason => params['reason'];
+  String get reason => params['reason'] as String;
   Object get data => params['data'];
 
-  Iterable<WipCallFrame> getCallFrames() =>
-      params['callFrames'].map((frame) => new WipCallFrame(frame));
+  Iterable<WipCallFrame> getCallFrames() => (params['callFrames'] as List)
+      .map((frame) => new WipCallFrame(frame as Map<String, dynamic>));
 
   String toString() => 'paused: ${reason}';
 }
@@ -99,13 +99,15 @@
 
   WipCallFrame(this._map);
 
-  String get callFrameId => _map['callFrameId'];
-  String get functionName => _map['functionName'];
-  WipLocation get location => new WipLocation(_map['location']);
-  WipRemoteObject get thisObject => new WipRemoteObject(_map['this']);
+  String get callFrameId => _map['callFrameId'] as String;
+  String get functionName => _map['functionName'] as String;
+  WipLocation get location =>
+      new WipLocation(_map['location'] as Map<String, dynamic>);
+  WipRemoteObject get thisObject =>
+      new WipRemoteObject(_map['this'] as Map<String, dynamic>);
 
-  Iterable<WipScope> getScopeChain() =>
-      _map['scopeChain'].map((scope) => new WipScope(scope));
+  Iterable<WipScope> getScopeChain() => (_map['scopeChain'] as List)
+      .map((scope) => new WipScope(scope as Map<String, dynamic>));
 
   String toString() => '[${functionName}]';
 }
@@ -115,9 +117,9 @@
 
   WipLocation(this._map);
 
-  int get columnNumber => _map['columnNumber'];
-  int get lineNumber => _map['lineNumber'];
-  String get scriptId => _map['scriptId'];
+  int get columnNumber => _map['columnNumber'] as int;
+  int get lineNumber => _map['lineNumber'] as int;
+  String get scriptId => _map['scriptId'] as String;
 
   String toString() => '[${scriptId}:${lineNumber}:${columnNumber}]';
 }
@@ -127,11 +129,11 @@
 
   WipRemoteObject(this._map);
 
-  String get className => _map['className'];
-  String get description => _map['description'];
-  String get objectId => _map['objectId'];
-  String get subtype => _map['subtype'];
-  String get type => _map['type'];
+  String get className => _map['className'] as String;
+  String get description => _map['description'] as String;
+  String get objectId => _map['objectId'] as String;
+  String get subtype => _map['subtype'] as String;
+  String get type => _map['type'] as String;
   Object get value => _map['value'];
 }
 
@@ -140,14 +142,14 @@
 
   WipScript(this._map);
 
-  String get scriptId => _map['scriptId'];
-  String get url => _map['url'];
-  int get startLine => _map['startLine'];
-  int get startColumn => _map['startColumn'];
-  int get endLine => _map['endLine'];
-  int get endColumn => _map['endColumn'];
-  bool get isContentScript => _map['isContentScript'];
-  String get sourceMapURL => _map['sourceMapURL'];
+  String get scriptId => _map['scriptId'] as String;
+  String get url => _map['url'] as String;
+  int get startLine => _map['startLine'] as int;
+  int get startColumn => _map['startColumn'] as int;
+  int get endLine => _map['endLine'] as int;
+  int get endColumn => _map['endColumn'] as int;
+  bool get isContentScript => _map['isContentScript'] as bool;
+  String get sourceMapURL => _map['sourceMapURL'] as String;
 
   String toString() => '[script ${scriptId}: ${url}]';
 }
@@ -158,12 +160,13 @@
   WipScope(this._map);
 
   // "catch", "closure", "global", "local", "with"
-  String get scope => _map['scope'];
+  String get scope => _map['scope'] as String;
 
   /**
    * Object representing the scope. For global and with scopes it represents the
    * actual object; for the rest of the scopes, it is artificial transient
    * object enumerating scope variables as its properties.
    */
-  WipRemoteObject get object => new WipRemoteObject(_map['object']);
+  WipRemoteObject get object =>
+      new WipRemoteObject(_map['object'] as Map<String, dynamic>);
 }
diff --git a/lib/src/dom.dart b/lib/src/dom.dart
index f1c33b1..e8929ff 100644
--- a/lib/src/dom.dart
+++ b/lib/src/dom.dart
@@ -14,15 +14,16 @@
   Future<Map<String, String>> getAttributes(int nodeId) async {
     WipResponse resp =
         await sendCommand('DOM.getAttributes', params: {'nodeId': nodeId});
-    return _attributeListToMap(resp.result['attributes']);
+    return _attributeListToMap((resp.result['attributes'] as List).cast());
   }
 
   Future<Node> getDocument() async =>
-      new Node((await sendCommand('DOM.getDocument')).result['root']);
+      new Node((await sendCommand('DOM.getDocument')).result['root']
+          as Map<String, dynamic>);
 
   Future<String> getOuterHtml(int nodeId) async =>
       (await sendCommand('DOM.getOuterHTML', params: {'nodeId': nodeId}))
-          .result['root'];
+          .result['root'] as String;
 
   Future hideHighlight() => sendCommand('DOM.hideHighlight');
 
@@ -86,19 +87,19 @@
     }
 
     var resp = await sendCommand('DOM.moveTo', params: params);
-    return resp.result['nodeId'];
+    return resp.result['nodeId'] as int;
   }
 
   Future<int> querySelector(int nodeId, String selector) async {
     var resp = await sendCommand('DOM.querySelector',
         params: {'nodeId': nodeId, 'selector': selector});
-    return resp.result['nodeId'];
+    return resp.result['nodeId'] as int;
   }
 
   Future<List<int>> querySelectorAll(int nodeId, String selector) async {
     var resp = await sendCommand('DOM.querySelectorAll',
         params: {'nodeId': nodeId, 'selector': selector});
-    return resp.result['nodeIds'];
+    return (resp.result['nodeIds'] as List).cast();
   }
 
   Future removeAttribute(int nodeId, String name) =>
@@ -114,7 +115,7 @@
   Future<int> requestNode(String objectId) async {
     var resp =
         await sendCommand('DOM.requestNode', params: {'objectId': objectId});
-    return resp.result['nodeId'];
+    return resp.result['nodeId'] as int;
   }
 
   Future<WipRemoteObject> resolveNode(int nodeId, {String objectGroup}) async {
@@ -124,7 +125,7 @@
     }
 
     var resp = await sendCommand('DOM.resolveNode', params: params);
-    return new WipRemoteObject(resp.result['object']);
+    return new WipRemoteObject(resp.result['object'] as Map<String, dynamic>);
   }
 
   Future setAttributeValue(int nodeId, String name, String value) =>
@@ -142,7 +143,7 @@
   Future<int> setNodeName(int nodeId, String name) async {
     var resp = await sendCommand('DOM.setNodeName',
         params: {'nodeId': nodeId, 'name': name});
-    return resp.result['nodeId'];
+    return resp.result['nodeId'] as int;
   }
 
   Future setNodeValue(int nodeId, String value) =>
@@ -181,41 +182,41 @@
 class AttributeModifiedEvent extends WrappedWipEvent {
   AttributeModifiedEvent(WipEvent event) : super(event);
 
-  int get nodeId => params['nodeId'];
-  String get name => params['name'];
-  String get value => params['value'];
+  int get nodeId => params['nodeId'] as int;
+  String get name => params['name'] as String;
+  String get value => params['value'] as String;
 }
 
 class AttributeRemovedEvent extends WrappedWipEvent {
   AttributeRemovedEvent(WipEvent event) : super(event);
 
-  int get nodeId => params['nodeId'];
-  String get name => params['name'];
+  int get nodeId => params['nodeId'] as int;
+  String get name => params['name'] as String;
 }
 
 class CharacterDataModifiedEvent extends WrappedWipEvent {
   CharacterDataModifiedEvent(WipEvent event) : super(event);
 
-  int get nodeId => params['nodeId'];
-  String get characterData => params['characterData'];
+  int get nodeId => params['nodeId'] as int;
+  String get characterData => params['characterData'] as String;
 }
 
 class ChildNodeCountUpdatedEvent extends WrappedWipEvent {
   ChildNodeCountUpdatedEvent(WipEvent event) : super(event);
 
-  int get nodeId => params['nodeId'];
-  int get childNodeCount => params['childNodeCount'];
+  int get nodeId => params['nodeId'] as int;
+  int get childNodeCount => params['childNodeCount'] as int;
 }
 
 class ChildNodeInsertedEvent extends WrappedWipEvent {
   ChildNodeInsertedEvent(WipEvent event) : super(event);
 
-  int get parentNodeId => params['parentNodeId'];
-  int get previousNodeId => params['previousNodeId'];
+  int get parentNodeId => params['parentNodeId'] as int;
+  int get previousNodeId => params['previousNodeId'] as int;
   Node _node;
   Node get node {
     if (_node == null) {
-      _node = new Node(params['node']);
+      _node = new Node(params['node'] as Map<String, dynamic>);
     }
     return _node;
   }
@@ -224,8 +225,8 @@
 class ChildNodeRemovedEvent extends WrappedWipEvent {
   ChildNodeRemovedEvent(WipEvent event) : super(event);
 
-  int get parentNodeId => params['parentNodeId'];
-  int get nodeId => params['nodeId'];
+  int get parentNodeId => params['parentNodeId'] as int;
+  int get nodeId => params['nodeId'] as int;
 }
 
 class DocumentUpdatedEvent extends WrappedWipEvent {
@@ -235,10 +236,10 @@
 class SetChildNodesEvent extends WrappedWipEvent {
   SetChildNodesEvent(WipEvent event) : super(event);
 
-  int get nodeId => params['parentId'];
+  int get nodeId => params['parentId'] as int;
   Iterable<Node> get nodes sync* {
     for (Map node in params['nodes']) {
-      yield new Node(node);
+      yield new Node(node as Map<String, dynamic>);
     }
   }
 
@@ -253,55 +254,55 @@
 
   Node(this._map);
 
-  var _attributes;
+  Map<String, String> _attributes;
   Map<String, String> get attributes {
     if (_attributes == null && _map.containsKey('attributes')) {
-      _attributes = _attributeListToMap(_map['attributes']);
+      _attributes = _attributeListToMap((_map['attributes'] as List).cast());
     }
     return _attributes;
   }
 
-  int get childNodeCount => _map['childNodeCount'];
+  int get childNodeCount => _map['childNodeCount'] as int;
 
-  var _children;
+  List<Node> _children;
   List<Node> get children {
     if (_children == null && _map.containsKey('children')) {
-      _children =
-          new UnmodifiableListView(_map['children'].map((c) => new Node(c)));
+      _children = new UnmodifiableListView((_map['children'] as List)
+          .map((c) => new Node(c as Map<String, dynamic>)));
     }
     return _children;
   }
 
   Node get contentDocument {
     if (_map.containsKey('contentDocument')) {
-      return new Node(_map['contentDocument']);
+      return new Node(_map['contentDocument'] as Map<String, dynamic>);
     }
     return null;
   }
 
-  String get documentUrl => _map['documentURL'];
+  String get documentUrl => _map['documentURL'] as String;
 
-  String get internalSubset => _map['internalSubset'];
+  String get internalSubset => _map['internalSubset'] as String;
 
-  String get localName => _map['localName'];
+  String get localName => _map['localName'] as String;
 
-  String get name => _map['name'];
+  String get name => _map['name'] as String;
 
-  int get nodeId => _map['nodeId'];
+  int get nodeId => _map['nodeId'] as int;
 
-  String get nodeName => _map['nodeName'];
+  String get nodeName => _map['nodeName'] as String;
 
-  int get nodeType => _map['nodeType'];
+  int get nodeType => _map['nodeType'] as int;
 
-  String get nodeValue => _map['nodeValue'];
+  String get nodeValue => _map['nodeValue'] as String;
 
-  String get publicId => _map['publicId'];
+  String get publicId => _map['publicId'] as String;
 
-  String get systemId => _map['systemId'];
+  String get systemId => _map['systemId'] as String;
 
-  String get value => _map['value'];
+  String get value => _map['value'] as String;
 
-  String get xmlVersion => _map['xmlVersion'];
+  String get xmlVersion => _map['xmlVersion'] as String;
 
   String toString() => '$nodeName: $nodeId $attributes';
 }
@@ -324,7 +325,7 @@
 }
 
 Map<String, String> _attributeListToMap(List<String> attrList) {
-  var attributes = {};
+  var attributes = <String, String>{};
   for (int i = 0; i < attrList.length; i += 2) {
     attributes[attrList[i]] = attrList[i + 1];
   }
diff --git a/lib/src/log.dart b/lib/src/log.dart
index 595369d..eac0a42 100644
--- a/lib/src/log.dart
+++ b/lib/src/log.dart
@@ -18,25 +18,25 @@
 class LogEntry extends WrappedWipEvent {
   LogEntry(WipEvent event) : super(event);
 
-  Map<String, dynamic> get _entry => params['entry'];
+  Map<String, dynamic> get _entry => params['entry'] as Map<String, dynamic>;
 
   /// Log entry source. Allowed values: xml, javascript, network, storage,
   /// appcache, rendering, security, deprecation, worker, violation,
   /// intervention, other.
-  String get source => _entry['source'];
+  String get source => _entry['source'] as String;
 
   /// Log entry severity. Allowed values: verbose, info, warning, error.
-  String get level => _entry['level'];
+  String get level => _entry['level'] as String;
 
   /// Logged text.
-  String get text => _entry['text'];
+  String get text => _entry['text'] as String;
 
   /// URL of the resource if known.
   @optional
-  String get url => _entry['url'];
+  String get url => _entry['url'] as String;
 
   /// Timestamp when this entry was added.
-  num get timestamp => _entry['timestamp'];
+  num get timestamp => _entry['timestamp'] as num;
 
   String toString() => text;
 }
diff --git a/lib/src/page.dart b/lib/src/page.dart
index 8959a16..e7e03f9 100644
--- a/lib/src/page.dart
+++ b/lib/src/page.dart
@@ -15,7 +15,7 @@
       sendCommand('Page.navigate', params: {'url': url});
 
   Future reload({bool ignoreCache, String scriptToEvaluateOnLoad}) {
-    var params = {};
+    var params = <String, dynamic>{};
 
     if (ignoreCache != null) {
       params['ignoreCache'] = ignoreCache;
diff --git a/lib/src/runtime.dart b/lib/src/runtime.dart
index bc74da5..f223fb9 100644
--- a/lib/src/runtime.dart
+++ b/lib/src/runtime.dart
@@ -20,9 +20,11 @@
     });
 
     if (response.result.containsKey('exceptionDetails')) {
-      throw new ExceptionDetails(response.result['exceptionDetails']);
+      throw new ExceptionDetails(
+          response.result['exceptionDetails'] as Map<String, dynamic>);
     } else {
-      return new RemoteObject(response.result['result']);
+      return new RemoteObject(
+          response.result['result'] as Map<String, dynamic>);
     }
   }
 
@@ -57,9 +59,11 @@
         await sendCommand('Runtime.callFunctionOn', params: params);
 
     if (response.result.containsKey('exceptionDetails')) {
-      throw new ExceptionDetails(response.result['exceptionDetails']);
+      throw new ExceptionDetails(
+          response.result['exceptionDetails'] as Map<String, dynamic>);
     } else {
-      return new RemoteObject(response.result['result']);
+      return new RemoteObject(
+          response.result['result'] as Map<String, dynamic>);
     }
   }
 
@@ -78,14 +82,15 @@
   /// Type of the call. Allowed values: log, debug, info, error, warning, dir,
   /// dirxml, table, trace, clear, startGroup, startGroupCollapsed, endGroup,
   /// assert, profile, profileEnd.
-  String get type => params['type'];
+  String get type => params['type'] as String;
 
   // Call timestamp.
-  num get timestamp => params['timestamp'];
+  num get timestamp => params['timestamp'] as num;
 
   /// Call arguments.
-  List<RemoteObject> get args =>
-      (params['args'] as List).map((m) => new RemoteObject(m)).toList();
+  List<RemoteObject> get args => (params['args'] as List)
+      .map((m) => new RemoteObject(m as Map<String, dynamic>))
+      .toList();
 
 // TODO: stackTrace, StackTrace, Stack trace captured when the call was made.
 }
@@ -94,10 +99,10 @@
   ExceptionThrownEvent(WipEvent event) : super(event);
 
   /// Timestamp of the exception.
-  int get timestamp => params['timestamp'];
+  int get timestamp => params['timestamp'] as int;
 
   ExceptionDetails get exceptionDetails =>
-      new ExceptionDetails(params['exceptionDetails']);
+      new ExceptionDetails(params['exceptionDetails'] as Map<String, dynamic>);
 }
 
 class ExceptionDetails {
@@ -106,36 +111,38 @@
   ExceptionDetails(this._map);
 
   /// Exception id.
-  int get exceptionId => _map['exceptionId'];
+  int get exceptionId => _map['exceptionId'] as int;
 
   /// Exception text, which should be used together with exception object when
   /// available.
-  String get text => _map['text'];
+  String get text => _map['text'] as String;
 
   /// Line number of the exception location (0-based).
-  int get lineNumber => _map['lineNumber'];
+  int get lineNumber => _map['lineNumber'] as int;
 
   /// Column number of the exception location (0-based).
-  int get columnNumber => _map['columnNumber'];
+  int get columnNumber => _map['columnNumber'] as int;
 
   /// URL of the exception location, to be used when the script was not
   /// reported.
   @optional
-  String get url => _map['url'];
+  String get url => _map['url'] as String;
 
   /// Script ID of the exception location.
   @optional
-  String get scriptId => _map['scriptId'];
+  String get scriptId => _map['scriptId'] as String;
 
   /// JavaScript stack trace if available.
   @optional
-  StackTrace get stackTrace =>
-      _map['stackTrace'] == null ? null : new StackTrace(_map['stackTrace']);
+  StackTrace get stackTrace => _map['stackTrace'] == null
+      ? null
+      : new StackTrace(_map['stackTrace'] as Map<String, dynamic>);
 
   /// Exception object if available.
   @optional
-  RemoteObject get exception =>
-      _map['exception'] == null ? null : new RemoteObject(_map['exception']);
+  RemoteObject get exception => _map['exception'] == null
+      ? null
+      : new RemoteObject(_map['exception'] as Map<String, dynamic>);
 
   String toString() => '$text, $url, $scriptId, $lineNumber, $exception';
 }
@@ -148,10 +155,11 @@
   /// String label of this stack trace. For async traces this may be a name of
   /// the function that initiated the async call.
   @optional
-  String get description => _map['description'];
+  String get description => _map['description'] as String;
 
-  List<CallFrame> get callFrames =>
-      (_map['callFrames'] as List).map((m) => new CallFrame(m)).toList();
+  List<CallFrame> get callFrames => (_map['callFrames'] as List)
+      .map((m) => new CallFrame(m as Map<String, dynamic>))
+      .toList();
 
   // TODO: parent, StackTrace, Asynchronous JavaScript stack trace that preceded
   // this stack, if available.
@@ -178,19 +186,19 @@
   CallFrame(this._map);
 
   /// JavaScript function name.
-  String get functionName => _map['functionName'];
+  String get functionName => _map['functionName'] as String;
 
   /// JavaScript script id.
-  String get scriptId => _map['scriptId'];
+  String get scriptId => _map['scriptId'] as String;
 
   /// JavaScript script name or url.
-  String get url => _map['url'];
+  String get url => _map['url'] as String;
 
   /// JavaScript script line number (0-based).
-  int get lineNumber => _map['lineNumber'];
+  int get lineNumber => _map['lineNumber'] as int;
 
   /// JavaScript script column number (0-based).
-  int get columnNumber => _map['columnNumber'];
+  int get columnNumber => _map['columnNumber'] as int;
 
   String toString() => '$functionName() ($url $lineNumber:$columnNumber)';
 }
@@ -203,17 +211,17 @@
 
   /// Object type.object, function, undefined, string, number, boolean, symbol,
   /// bigint.
-  String get type => _map['type'];
+  String get type => _map['type'] as String;
 
   /// Remote object value in case of primitive values or JSON values (if it was
   /// requested). (optional)
   Object get value => _map['value'];
 
   /// String representation of the object. (optional)
-  String get description => _map['description'];
+  String get description => _map['description'] as String;
 
   /// Unique object identifier (for non-primitive values). (optional)
-  String get objectId => _map['objectId'];
+  String get objectId => _map['objectId'] as String;
 
   String toString() => '$type $value';
 }
diff --git a/lib/src/target.dart b/lib/src/target.dart
index 82b5cd7..7e1577d 100644
--- a/lib/src/target.dart
+++ b/lib/src/target.dart
@@ -16,7 +16,7 @@
   Future<String> createTarget(String url) async {
     WipResponse response =
         await sendCommand('Target.createTarget', params: {'url': url});
-    return response.result['targetId'];
+    return response.result['targetId'] as String;
   }
 
   /// Activates (focuses) the target.
@@ -29,7 +29,7 @@
   Future<bool> closeTarget(String targetId) async {
     WipResponse response =
         await sendCommand('Target.closeTarget', params: {'targetId': targetId});
-    return response.result['success'];
+    return response.result['success'] as bool;
   }
 
   /// Inject object to the target's main frame that provides a communication
diff --git a/lib/webkit_inspection_protocol.dart b/lib/webkit_inspection_protocol.dart
index 41688f8..aba2839 100644
--- a/lib/webkit_inspection_protocol.dart
+++ b/lib/webkit_inspection_protocol.dart
@@ -45,7 +45,7 @@
     var response = await getUrl('/json');
     var respBody = await utf8.decodeStream(response);
     return new List<ChromeTab>.from(
-        jsonDecode(respBody).map((m) => new ChromeTab(m)));
+        (jsonDecode(respBody) as List).map((m) => new ChromeTab(m as Map)));
   }
 
   Future<ChromeTab> getTab(bool accept(ChromeTab tab),
@@ -88,24 +88,24 @@
 
   ChromeTab(this._map);
 
-  String get description => _map['description'];
+  String get description => _map['description'] as String;
 
-  String get devtoolsFrontendUrl => _map['devtoolsFrontendUrl'];
+  String get devtoolsFrontendUrl => _map['devtoolsFrontendUrl'] as String;
 
-  String get faviconUrl => _map['faviconUrl'];
+  String get faviconUrl => _map['faviconUrl'] as String;
 
   /// Ex. `E1999E8A-EE27-0450-9900-5BFF4C69CA83`.
-  String get id => _map['id'];
+  String get id => _map['id'] as String;
 
-  String get title => _map['title'];
+  String get title => _map['title'] as String;
 
   /// Ex. `background_page`, `page`.
-  String get type => _map['type'];
+  String get type => _map['type'] as String;
 
-  String get url => _map['url'];
+  String get url => _map['url'] as String;
 
   /// Ex. `ws://localhost:1234/devtools/page/4F98236D-4EB0-7C6C-5DD1-AF9B6BE4BC71`.
-  String get webSocketDebuggerUrl => _map['webSocketDebuggerUrl'];
+  String get webSocketDebuggerUrl => _map['webSocketDebuggerUrl'] as String;
 
   bool get hasIcon => _map.containsKey('faviconUrl');
 
@@ -164,10 +164,8 @@
 
   final Map _completers = <int, Completer<WipResponse>>{};
 
-  final StreamController _closeController =
-      new StreamController<WipConnection>.broadcast();
-  final StreamController _notificationController =
-      new StreamController<WipEvent>.broadcast();
+  final _closeController = new StreamController<WipConnection>.broadcast();
+  final _notificationController = new StreamController<WipEvent>.broadcast();
 
   static Future<WipConnection> connect(String url) {
     return WebSocket.connect(url).then((socket) {
@@ -185,7 +183,7 @@
     _runtime = new WipRuntime(this);
 
     _ws.listen((data) {
-      var json = jsonDecode(data);
+      var json = jsonDecode(data as String) as Map<String, dynamic>;
 
       if (json.containsKey('id')) {
         _handleResponse(json);
@@ -245,8 +243,8 @@
   final Map<String, dynamic> params;
 
   WipEvent(Map<String, dynamic> map)
-      : method = map['method'],
-        params = map['params'];
+      : method = map['method'] as String,
+        params = map['params'] as Map<String, dynamic>;
 
   String toString() => 'WipEvent: $method($params)';
 }
@@ -256,7 +254,7 @@
   final dynamic error;
 
   WipError(Map<String, dynamic> json)
-      : id = json['id'],
+      : id = json['id'] as int,
         error = json['error'];
 
   String toString() => 'WipError $id: $error';
@@ -267,8 +265,8 @@
   final Map<String, dynamic> result;
 
   WipResponse(Map<String, dynamic> json)
-      : id = json['id'],
-        result = json['result'];
+      : id = json['id'] as int,
+        result = json['result'] as Map<String, dynamic>;
 
   String toString() => 'WipResponse $id: $result';
 }
@@ -282,28 +280,30 @@
   Map<String, Stream> _eventStreams = {};
 
   final WipConnection connection;
-  var _onClosed;
+  Stream<WipDomain> _onClosed;
 
   Stream<WipDomain> get onClosed => _onClosed;
 
   WipDomain(WipConnection connection) : this.connection = connection {
-    this._onClosed =
-        new StreamTransformer.fromHandlers(handleData: (event, EventSink sink) {
+    this._onClosed = new StreamTransformer.fromHandlers(
+        handleData: (event, EventSink<WipDomain> sink) {
       sink.add(this);
     }).bind(connection.onClose);
   }
 
   Stream<T> eventStream<T>(String method, WipEventTransformer<T> transformer) {
-    return _eventStreams.putIfAbsent(
-      method,
-      () => new StreamTransformer.fromHandlers(
-            handleData: (WipEvent event, EventSink<T> sink) {
-              if (event.method == method) {
-                sink.add(transformer(event));
-              }
-            },
-          ).bind(connection.onNotification),
-    );
+    return _eventStreams
+        .putIfAbsent(
+          method,
+          () => new StreamTransformer.fromHandlers(
+                handleData: (WipEvent event, EventSink<T> sink) {
+                  if (event.method == method) {
+                    sink.add(transformer(event));
+                  }
+                },
+              ).bind(connection.onNotification),
+        )
+        .cast();
   }
 
   Future<WipResponse> sendCommand(
diff --git a/pubspec.yaml b/pubspec.yaml
index 4e4c52f..9504478 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: webkit_inspection_protocol
-version: 0.4.0
+version: 0.4.1
 description: A client for the Webkit Inspection Protocol (WIP).
 
 homepage: https://github.com/google/webkit_inspection_protocol.dart
diff --git a/test/test_setup.dart b/test/test_setup.dart
index 9aeecb4..23b23ed 100644
--- a/test/test_setup.dart
+++ b/test/test_setup.dart
@@ -8,7 +8,7 @@
 import 'package:shelf_static/shelf_static.dart';
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
 
-var _wipConnection;
+Future<WipConnection> _wipConnection;
 
 /// Returns a (cached) debugger connection to the first regular tab of
 /// the browser with remote debugger running at 'localhost:9222',