Merge pull request #57 from google/0.6.0

add APIs to view WIP traffic
diff --git a/changelog.md b/changelog.md
index 87c826b..ec149a6 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,7 +1,12 @@
 # webkit_inspection_protocol.dart
 
+## 0.6.0
+- Add `onSend` and `onReceive` in `WipConnection` 
+- Expose `onExecutionContextCreated`, `onExecutionContextDestroyed`,
+  and `onExecutionContextsCleared` on WipRuntime
+
 ## 0.5.3
-- expose name in `WipScope`
+- expose `name` in `WipScope`
 
 ## 0.5.2
 - have `ExceptionDetails` and `WipError` implement `Exception`
diff --git a/lib/src/runtime.dart b/lib/src/runtime.dart
index 5fea55b..bd6d647 100644
--- a/lib/src/runtime.dart
+++ b/lib/src/runtime.dart
@@ -9,8 +9,12 @@
 class WipRuntime extends WipDomain {
   WipRuntime(WipConnection connection) : super(connection);
 
+  /// Enables reporting of execution contexts creation by means of
+  /// executionContextCreated event. When the reporting gets enabled the event
+  /// will be sent immediately for each existing execution context.
   Future<WipResponse> enable() => sendCommand('Runtime.enable');
 
+  /// Disables reporting of execution contexts creation.
   Future<WipResponse> disable() => sendCommand('Runtime.disable');
 
   /// Evaluates expression on global object.
@@ -107,6 +111,22 @@
   Stream<ExceptionThrownEvent> get onExceptionThrown => eventStream(
       'Runtime.exceptionThrown',
       (WipEvent event) => new ExceptionThrownEvent(event));
+
+  /// Issued when new execution context is created.
+  Stream<ExecutionContextDescription> get onExecutionContextCreated =>
+      eventStream(
+          'Runtime.executionContextCreated',
+          (WipEvent event) =>
+              new ExecutionContextDescription(event.params['context']));
+
+  /// Issued when execution context is destroyed.
+  Stream<String> get onExecutionContextDestroyed => eventStream(
+      'Runtime.executionContextDestroyed',
+      (WipEvent event) => event.params['executionContextId']);
+
+  /// Issued when all executionContexts were cleared in browser.
+  Stream get onExecutionContextsCleared => eventStream(
+      'Runtime.executionContextsCleared', (WipEvent event) => event);
 }
 
 class ConsoleAPIEvent extends WrappedWipEvent {
@@ -128,6 +148,23 @@
 // TODO: stackTrace, StackTrace, Stack trace captured when the call was made.
 }
 
+/// Description of an isolated world.
+class ExecutionContextDescription {
+  final Map<String, dynamic> map;
+
+  ExecutionContextDescription(this.map);
+
+  /// Unique id of the execution context. It can be used to specify in which
+  /// execution context script evaluation should be performed.
+  int get id => map['id'] as int;
+
+  /// Execution context origin.
+  String get origin => map['origin'];
+
+  /// Human readable name describing given context.
+  String get name => map['name'];
+}
+
 class ExceptionThrownEvent extends WrappedWipEvent {
   ExceptionThrownEvent(WipEvent event) : super(event);
 
diff --git a/lib/webkit_inspection_protocol.dart b/lib/webkit_inspection_protocol.dart
index 6c313f8..3618974 100644
--- a/lib/webkit_inspection_protocol.dart
+++ b/lib/webkit_inspection_protocol.dart
@@ -8,8 +8,6 @@
 import 'dart:convert';
 import 'dart:io' show HttpClient, HttpClientResponse, WebSocket;
 
-import 'package:logging/logging.dart' show Logger;
-
 import 'src/console.dart';
 import 'src/debugger.dart';
 import 'src/dom.dart';
@@ -119,8 +117,6 @@
 
 /// A Webkit Inspection Protocol (WIP) connection.
 class WipConnection {
-  static final _logger = new Logger('WipConnection');
-
   /// The WebSocket URL.
   final String url;
 
@@ -156,6 +152,11 @@
 
   WipRuntime get runtime => _runtime;
 
+  final StreamController<String> _onSend =
+      StreamController.broadcast(sync: true);
+  final StreamController<String> _onReceive =
+      StreamController.broadcast(sync: true);
+
   final Map _completers = <int, Completer<WipResponse>>{};
 
   final _closeController = new StreamController<WipConnection>.broadcast();
@@ -178,6 +179,7 @@
 
     _ws.listen((data) {
       var json = jsonDecode(data as String) as Map<String, dynamic>;
+      _onReceive.add(data);
 
       if (json.containsKey('id')) {
         _handleResponse(json);
@@ -197,19 +199,19 @@
 
   Future<WipResponse> sendCommand(String method,
       [Map<String, dynamic> params]) {
-    _logger.finest('Sending command: $method($params)');
     var completer = new Completer<WipResponse>();
     var json = {'id': _nextId++, 'method': method};
     if (params != null) {
       json['params'] = params;
     }
     _completers[json['id']] = completer;
-    _ws.add(jsonEncode(json));
+    String message = jsonEncode(json);
+    _ws.add(message);
+    _onSend.add(message);
     return completer.future;
   }
 
   void _handleNotification(Map<String, dynamic> json) {
-    _logger.finest('Received notification: $json');
     _notificationController.add(new WipEvent(json));
   }
 
@@ -217,10 +219,8 @@
     var completer = _completers.remove(event['id']);
 
     if (event.containsKey('error')) {
-      _logger.info('Received error: $event');
       completer.completeError(new WipError(event));
     } else {
-      _logger.finest('Received response: $event');
       completer.complete(new WipResponse(event));
     }
   }
@@ -230,6 +230,12 @@
     _closeController.close();
     _notificationController.close();
   }
+
+  /// Listen for all traffic sent on this WipConnection.
+  Stream<String> get onSend => _onSend.stream;
+
+  /// Listen for all traffic received by this WipConnection.
+  Stream<String> get onReceive => _onReceive.stream;
 }
 
 class WipEvent {
diff --git a/pubspec.yaml b/pubspec.yaml
index c1df8ee..76174a9 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: webkit_inspection_protocol
-version: 0.5.3
+version: 0.6.0
 description: A client for the Chrome DevTools Protocol (previously called the Webkit Inspection Protocol).
 homepage: https://github.com/google/webkit_inspection_protocol.dart