implement the getMemoryUsage API call (#1022)

diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md
index 0c07bf0..b9a730e 100644
--- a/dwds/CHANGELOG.md
+++ b/dwds/CHANGELOG.md
@@ -11,6 +11,7 @@
   that are not handled.
 - Prompt users to install the Dart Debug Extension if local debugging does not work.
 - Allow for the injected client to run with CSP enforced.
+- Implement the `getMemoryUsage()` call.
 
 ## 3.1.1
 
diff --git a/dwds/lib/src/debugging/inspector.dart b/dwds/lib/src/debugging/inspector.dart
index d34fd37..08ccc5b 100644
--- a/dwds/lib/src/debugging/inspector.dart
+++ b/dwds/lib/src/debugging/inspector.dart
@@ -343,6 +343,19 @@
       ..source = source;
   }
 
+  Future<MemoryUsage> getMemoryUsage(String isolateId) async {
+    checkIsolate('getMemoryUsage', isolateId);
+
+    final response = await remoteDebugger.sendCommand('Runtime.getHeapUsage');
+
+    final jsUsage = HeapUsage(response.result);
+    return MemoryUsage.parse({
+      'heapUsage': jsUsage.usedSize,
+      'heapCapacity': jsUsage.totalSize,
+      'externalUsage': 0,
+    });
+  }
+
   /// Returns the [ScriptRef] for the provided Dart server path [uri].
   Future<ScriptRef> scriptRefFor(String uri) async {
     if (_serverPathToScriptRef.isEmpty) {
diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart
index 3397832..be48765 100644
--- a/dwds/lib/src/services/chrome_proxy_service.dart
+++ b/dwds/lib/src/services/chrome_proxy_service.dart
@@ -424,8 +424,8 @@
   Future<Isolate> getIsolate(String isolateId) async => _getIsolate(isolateId);
 
   @override
-  Future<MemoryUsage> getMemoryUsage(String isolateId) async {
-    throw UnimplementedError();
+  Future<MemoryUsage> getMemoryUsage(String isolateId) {
+    return _inspector.getMemoryUsage(isolateId);
   }
 
   @override
diff --git a/dwds/test/chrome_proxy_service_test.dart b/dwds/test/chrome_proxy_service_test.dart
index 83b558d..2048850 100644
--- a/dwds/test/chrome_proxy_service_test.dart
+++ b/dwds/test/chrome_proxy_service_test.dart
@@ -187,16 +187,39 @@
       });
     });
 
-    test('clearVMTimeline', () {
-      expect(() => service.clearVMTimeline(), throwsUnimplementedError);
+    group('VMTimeline', () {
+      test('clearVMTimeline', () {
+        expect(() => service.clearVMTimeline(), throwsUnimplementedError);
+      });
+
+      test('getVMTimelineMicros', () {
+        expect(() => service.getVMTimelineMicros(), throwsUnimplementedError);
+      });
+
+      test('getVMTimeline', () {
+        expect(() => service.getVMTimeline(), throwsUnimplementedError);
+      });
+
+      test('getVMTimelineFlags', () {
+        expect(() => service.getVMTimelineFlags(), throwsUnimplementedError);
+      });
+
+      test('setVMTimelineFlags', () {
+        expect(
+            () => service.setVMTimelineFlags(null), throwsUnimplementedError);
+      });
     });
 
-    test('clearVMTimeline', () {
-      expect(() => service.clearVMTimeline(), throwsUnimplementedError);
-    });
+    test('getMemoryUsage', () async {
+      var vm = await service.getVM();
+      var isolate = await service.getIsolate(vm.isolates.first.id);
 
-    test('clearVMTimeline', () {
-      expect(() => service.clearVMTimeline(), throwsUnimplementedError);
+      var memoryUsage = await service.getMemoryUsage(isolate.id);
+
+      expect(memoryUsage.heapUsage, isNotNull);
+      expect(memoryUsage.heapUsage, greaterThan(0));
+      expect(memoryUsage.heapCapacity, greaterThan(0));
+      expect(memoryUsage.externalUsage, equals(0));
     });
 
     group('evaluate', () {
@@ -604,10 +627,6 @@
           contains('package:intl/src/intl/date_format_helpers.dart'));
     });
 
-    test('clearVMTimeline', () {
-      expect(() => service.clearVMTimeline(), throwsUnimplementedError);
-    });
-
     group('getSourceReport', () {
       test('Coverage report', () async {
         var vm = await service.getVM();
@@ -1032,10 +1051,6 @@
       expect(vm.name, 'foo');
     });
 
-    test('setVMTimelineFlags', () {
-      expect(() => service.setVMTimelineFlags(null), throwsUnimplementedError);
-    });
-
     test('streamCancel', () {
       expect(() => service.streamCancel(null), throwsUnimplementedError);
     });