syncslides: Integrating the new back button event with the app.

Closes: https://github.com/vanadium/syncslides/issues/2
Change-Id: I5cd3fc6f5a1d9fc836160b8de7157da5241886a5
diff --git a/dart/lib/main.dart b/dart/lib/main.dart
index 85e2522..6ef619e 100644
--- a/dart/lib/main.dart
+++ b/dart/lib/main.dart
@@ -7,14 +7,25 @@
 
 import 'styles/common.dart' as style;
 import 'components/deckgrid.dart';
+import 'utils/back_button.dart' as backButtonUtil;
+
+NavigatorState _navigator;
 
 void main() {
   _initLogging();
+  _initBackButtonHandler();
 
   runApp(new MaterialApp(
       theme: style.theme,
       title: 'SyncSlides',
-      routes: {'/': (RouteArguments args) => new DeckGridPage()}));
+      routes: {'/': (RouteArguments args) => new LandingPage()}));
+}
+
+class LandingPage extends StatelessComponent {
+  Widget build(BuildContext context) {
+    _navigator = Navigator.of(context);
+    return new DeckGridPage();
+  }
 }
 
 void _initLogging() {
@@ -23,3 +34,15 @@
     print('\nSyncSlides: ${rec.time}: ${rec.message}');
   });
 }
+
+void _initBackButtonHandler() {
+  backButtonUtil.onBackButton(() {
+    if (_navigator != null && _navigator.hasPreviousRoute) {
+      _navigator.pop();
+      return true;
+    }
+
+    // Tell the app to exit.
+    return false;
+  });
+}
diff --git a/dart/lib/utils/back_button.dart b/dart/lib/utils/back_button.dart
new file mode 100644
index 0000000..9df68c2
--- /dev/null
+++ b/dart/lib/utils/back_button.dart
@@ -0,0 +1,40 @@
+// Copyright 2015 The Vanadium 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:flutter/services.dart' show shell;
+import 'package:mojo_services/input/input.mojom.dart';
+
+String _inputMojoUrl = 'mojo:input';
+
+typedef bool BackButtonHandler();
+
+BackButtonHandler _handler;
+// Registers a handler for the back button.
+// Handler should return false when it no longer wants to control
+// the behaviour of the back button, in which case the app will exit.
+void onBackButton(BackButtonHandler handler) {
+  if (_handler != null) {
+    throw new ArgumentError("Only one back button handler can exist per app.");
+  }
+
+  InputServiceProxy inputService = new InputServiceProxy.unbound();
+  shell.connectToService(_inputMojoUrl, inputService);
+
+  InputClientStub intputClientStub = new InputClientStub.unbound();
+  intputClientStub.impl = new _InputHandler();
+
+  inputService.ptr.setClient(intputClientStub);
+  _handler = handler;
+}
+
+class _InputHandler extends InputClient {
+  dynamic onBackButton([Function responseFactory]) {
+    bool exit = !_handler();
+    if (exit) {
+      return null;
+    } else {
+      return responseFactory();
+    }
+  }
+}
diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml
index 45a372b..86d198c 100644
--- a/dart/pubspec.yaml
+++ b/dart/pubspec.yaml
@@ -4,6 +4,7 @@
   flutter:
     path: "../../../../../flutter/packages/flutter"
   logging: ">=0.11.2 <0.12.0"
+  mojo_services: ">=0.4.5 <0.5.0"
   syncbase: ">=0.0.9 <0.1.0"
   v23discovery: ">=0.0.4 < 0.1.0"
   uuid: ">=0.5.0 <0.6.0"