[Agent] Add getTokenManager api

Test:
fx run-host-tests fuchsia_modular_package_unittests

Change-Id: Ife638d93c7fc74a5dd6160bb3faa9a13582f955a
diff --git a/public/dart/fuchsia_modular/lib/src/agent/agent.dart b/public/dart/fuchsia_modular/lib/src/agent/agent.dart
index 9e63d24..b125907 100644
--- a/public/dart/fuchsia_modular/lib/src/agent/agent.dart
+++ b/public/dart/fuchsia_modular/lib/src/agent/agent.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:fidl/fidl.dart';
+import 'package:fidl_fuchsia_auth/fidl_async.dart' as fidl_auth;
 
 import 'internal/_agent_impl.dart';
 
@@ -59,7 +60,11 @@
   /// ```
   /// typedef ServiceProvider<T> = FutureOr<T> Function();
   /// ```
-  /// Where [T] represents the service type. 
+  /// Where [T] represents the service type.
   void exposeServiceProvider<T>(
       ServiceProvider<T> serviceProvider, ServiceData<T> serviceData);
+
+  /// Returns the auth token manager this Agent may use for accessing external
+  /// services.
+  fidl_auth.TokenManagerProxy getTokenManager();
 }
diff --git a/public/dart/fuchsia_modular/lib/src/agent/internal/_agent_context.dart b/public/dart/fuchsia_modular/lib/src/agent/internal/_agent_context.dart
new file mode 100644
index 0000000..562f4e5
--- /dev/null
+++ b/public/dart/fuchsia_modular/lib/src/agent/internal/_agent_context.dart
@@ -0,0 +1,18 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:fidl_fuchsia_modular/fidl_async.dart' as fidl;
+import 'package:fuchsia_services/services.dart';
+
+final fidl.AgentContext _agentContext = () {
+  final proxy = fidl.AgentContextProxy();
+  connectToEnvironmentService(proxy);
+  return proxy;
+}();
+
+/// Method to return the singleton, connected [fidl.AgentContext].
+///
+/// Multiple calls to this method will result in the same context being
+/// returned.
+fidl.AgentContext getAgentContext() => _agentContext;
diff --git a/public/dart/fuchsia_modular/lib/src/agent/internal/_agent_impl.dart b/public/dart/fuchsia_modular/lib/src/agent/internal/_agent_impl.dart
index 48367f7..af18361 100644
--- a/public/dart/fuchsia_modular/lib/src/agent/internal/_agent_impl.dart
+++ b/public/dart/fuchsia_modular/lib/src/agent/internal/_agent_impl.dart
@@ -5,12 +5,14 @@
 import 'dart:async';
 
 import 'package:fidl/fidl.dart';
-import 'package:fuchsia_services/services.dart';
+import 'package:fidl_fuchsia_auth/fidl_async.dart' as fidl_auth;
 import 'package:fidl_fuchsia_modular/fidl_async.dart' as fidl;
 import 'package:fidl_fuchsia_sys/fidl_async.dart' as fidl_sys;
 import 'package:fuchsia_modular/lifecycle.dart';
+import 'package:fuchsia_services/services.dart';
 
 import '../agent.dart';
+import '_agent_context.dart';
 
 /// A concrete implementation of the [Agent] interface.
 ///
@@ -32,12 +34,25 @@
   final List<AsyncBinding<Object>> _outgoingServicesBindings =
       <AsyncBinding<Object>>[];
 
+  /// Returns the [fidl.AgentContext] for the running module. This variable
+  /// should not be used directly, use the [getContext()] method instead.
+  fidl.AgentContext _agentContext;
+
+  /// Returns a [fidl_auth.TokenManagerProxy]. It's abstracted to aid with
+  /// testing and this variable should not be used directly, use the
+  /// [getTokenManager()] method instead.
+  fidl_auth.TokenManagerProxy _tokenManagerProxy;
+
   /// The default constructor for this instance.
-  AgentImpl(
-      {Lifecycle lifecycle,
-      StartupContext startupContext,
-      ServiceProviderImpl serviceProviderImpl})
-      : _serviceProvider = serviceProviderImpl ?? ServiceProviderImpl() {
+  AgentImpl({
+    Lifecycle lifecycle,
+    StartupContext startupContext,
+    fidl.AgentContext agentContext,
+    ServiceProviderImpl serviceProviderImpl,
+    fidl_auth.TokenManagerProxy tokenManagerProxy,
+  })  : _agentContext = agentContext,
+        _tokenManagerProxy = tokenManagerProxy,
+        _serviceProvider = serviceProviderImpl ?? ServiceProviderImpl() {
     (lifecycle ??= Lifecycle()).addTerminateListener(_terminate);
     startupContext ??= StartupContext.fromStartupInfo();
 
@@ -93,6 +108,13 @@
   }
 
   @override
+  fidl_auth.TokenManagerProxy getTokenManager() {
+    final tokenManagerProxy = _getTokenManager();
+    _getContext().getTokenManager(tokenManagerProxy.ctrl.request());
+    return tokenManagerProxy;
+  }
+
+  @override
   Future<void> runTask(String taskId) {
     if (taskId == null) {
       throw ArgumentError.notNull('taskId');
@@ -116,6 +138,12 @@
     );
   }
 
+  fidl.AgentContext _getContext() => _agentContext ??= getAgentContext();
+
+  fidl_auth.TokenManagerProxy _getTokenManager() {
+    return _tokenManagerProxy ??= fidl_auth.TokenManagerProxy();
+  }
+
   // Any necessary cleanup should be done here.
   Future<void> _terminate() async {
     _agentBinding.close();
diff --git a/public/dart/fuchsia_modular/test/agent/internal/agent_impl_test.dart b/public/dart/fuchsia_modular/test/agent/internal/agent_impl_test.dart
index 1064753..69a25f8 100644
--- a/public/dart/fuchsia_modular/test/agent/internal/agent_impl_test.dart
+++ b/public/dart/fuchsia_modular/test/agent/internal/agent_impl_test.dart
@@ -4,26 +4,36 @@
 
 // ignore_for_file: implementation_imports
 
-import 'package:fidl/fidl.dart' show AsyncBinding;
+import 'package:fidl/fidl.dart' show AsyncBinding, AsyncProxyController;
 import 'package:fidl/src/interface.dart';
+import 'package:fidl_fuchsia_auth/fidl_async.dart' as fidl_auth;
+import 'package:fidl_fuchsia_modular/fidl_async.dart' as fidl;
 import 'package:fidl_fuchsia_sys/fidl_async.dart';
 import 'package:fuchsia_modular/lifecycle.dart';
-import 'package:mockito/mockito.dart';
-import 'package:fuchsia_services/services.dart';
-import 'package:test/test.dart';
-import 'package:fidl_fuchsia_modular/fidl_async.dart' as fidl;
-
 import 'package:fuchsia_modular/src/agent/internal/_agent_impl.dart';
+import 'package:fuchsia_services/services.dart';
+import 'package:mockito/mockito.dart';
+import 'package:test/test.dart';
 
 // Mock classes
 class MockLifecycle extends Mock implements Lifecycle {}
 
 class MockStartupContext extends Mock implements StartupContext {}
 
+class MockAgentContext extends Mock implements fidl.AgentContext {}
+
 class MockServiceProviderImpl extends Mock implements ServiceProviderImpl {}
 
 class MockAsyncBinding extends Mock implements AsyncBinding {}
 
+class MockAsyncProxyController<T> extends Mock
+    implements AsyncProxyController<T> {}
+
+class MockInterfaceRequest<T> extends Mock implements InterfaceRequest<T> {}
+
+class MockTokenManagerProxy extends Mock
+    implements fidl_auth.TokenManagerProxy {}
+
 void main() {
   test('startupContext ', () {
     final mockStartupContext = MockStartupContext();
@@ -144,6 +154,22 @@
       await untilCalled(mockServiceBindings.bind(service, any));
     });
   });
+
+  test('verify getTokenManager should call context.getTokenManager', () {
+    final mockAgentContext = MockAgentContext();
+    final mockTokenManagerProxy = MockTokenManagerProxy();
+    final mockedCtrl = MockAsyncProxyController<fidl_auth.TokenManager>();
+
+    when(mockTokenManagerProxy.ctrl).thenReturn(mockedCtrl);
+    when(mockedCtrl.request()).thenReturn(MockInterfaceRequest());
+
+    AgentImpl(
+      agentContext: mockAgentContext,
+      tokenManagerProxy: mockTokenManagerProxy,
+    ).getTokenManager();
+
+    verify(mockAgentContext.getTokenManager(any));
+  });
 }
 
 /// This is a dummyService used for testing.