shill: wimax: Connect to a specific WiMAX network with EAP credentials.

BUG=chrome-os-partner:9830
TEST=Build and run unit tests.

Change-Id: I429aff11a610bff93f7debc3f9bdc156fe83a15a
Reviewed-on: https://gerrit.chromium.org/gerrit/23096
Tested-by: Ben Chan <benchan@chromium.org>
Reviewed-by: Darin Petkov <petkov@chromium.org>
Commit-Ready: Ben Chan <benchan@chromium.org>
diff --git a/mock_wimax_device_proxy.h b/mock_wimax_device_proxy.h
index 307b268..3ff2c0b 100644
--- a/mock_wimax_device_proxy.h
+++ b/mock_wimax_device_proxy.h
@@ -26,7 +26,9 @@
   MOCK_METHOD3(ScanNetworks, void(Error *error,
                                   const ResultCallback &callback,
                                   int timeout));
-  MOCK_METHOD3(Connect, void(Error *error,
+  MOCK_METHOD5(Connect, void(const DBus::Path &network,
+                             const DBusPropertiesMap &parameters,
+                             Error *error,
                              const ResultCallback &callback,
                              int timeout));
   MOCK_METHOD3(Disconnect, void(Error *error,
diff --git a/mock_wimax_network_proxy.h b/mock_wimax_network_proxy.h
index 807be18..e54a065 100644
--- a/mock_wimax_network_proxy.h
+++ b/mock_wimax_network_proxy.h
@@ -16,11 +16,12 @@
   MockWiMaxNetworkProxy();
   virtual ~MockWiMaxNetworkProxy();
 
+  MOCK_CONST_METHOD0(proxy_object_path, DBus::Path());
   MOCK_METHOD1(Identifier, uint32(Error *error));
   MOCK_METHOD1(Name, std::string(Error *error));
   MOCK_METHOD1(Type, int(Error *error));
   MOCK_METHOD1(CINR, int(Error *error));
-  MOCK_METHOD1(RSSI, int (Error *error));
+  MOCK_METHOD1(RSSI, int(Error *error));
 
   DISALLOW_COPY_AND_ASSIGN(MockWiMaxNetworkProxy);
 };
diff --git a/wimax.cc b/wimax.cc
index 63bb83d..f96d6b2 100644
--- a/wimax.cc
+++ b/wimax.cc
@@ -92,9 +92,11 @@
   }
   service->SetState(Service::kStateAssociating);
   pending_service_ = service;
-  // TODO(petkov): Need to update this to connect to a specific service,
-  // however, there's no support for this in WiMaxManager yet.
+
+  DBusPropertiesMap parameters;
+  service->GetConnectParameters(&parameters);
   proxy_->Connect(
+      service->GetNetworkObjectPath(), parameters,
       error, Bind(&WiMax::OnConnectComplete, this), kTimeoutDefault);
   if (error->IsFailure()) {
     OnConnectComplete(*error);
diff --git a/wimax_device_proxy.cc b/wimax_device_proxy.cc
index f5e0ef4..a776184 100644
--- a/wimax_device_proxy.cc
+++ b/wimax_device_proxy.cc
@@ -52,12 +52,15 @@
          error, callback, timeout);
 }
 
-void WiMaxDeviceProxy::Connect(Error *error,
+void WiMaxDeviceProxy::Connect(const DBus::Path &network,
+                               const DBusPropertiesMap &parameters,
+                               Error *error,
                                const ResultCallback &callback,
                                int timeout) {
   SLOG(DBus, 2) << __func__ << "(" << timeout << ")";
-  Invoke(Bind((void (Proxy::*)(void *, int))&Proxy::Connect,
-              Unretained(&proxy_)),
+  Invoke(Bind((void (Proxy::*)(const DBus::Path &, const DBusPropertiesMap &,
+                               void *, int))&Proxy::Connect,
+              Unretained(&proxy_), network, parameters),
          error, callback, timeout);
 }
 
diff --git a/wimax_device_proxy.h b/wimax_device_proxy.h
index 8977ee0..d829227 100644
--- a/wimax_device_proxy.h
+++ b/wimax_device_proxy.h
@@ -29,7 +29,9 @@
   virtual void ScanNetworks(Error *error,
                             const ResultCallback &callback,
                             int timeout);
-  virtual void Connect(Error *error,
+  virtual void Connect(const DBus::Path &network,
+                       const DBusPropertiesMap &parameters,
+                       Error *error,
                        const ResultCallback &callback,
                        int timeout);
   virtual void Disconnect(Error *error,
diff --git a/wimax_device_proxy_interface.h b/wimax_device_proxy_interface.h
index 89a4971..b83a69f 100644
--- a/wimax_device_proxy_interface.h
+++ b/wimax_device_proxy_interface.h
@@ -10,6 +10,7 @@
 #include <base/basictypes.h>
 
 #include "shill/callbacks.h"
+#include "shill/dbus_properties.h"
 
 namespace shill {
 
@@ -32,7 +33,9 @@
   virtual void ScanNetworks(Error *error,
                             const ResultCallback &callback,
                             int timeout) = 0;
-  virtual void Connect(Error *error,
+  virtual void Connect(const DBus::Path &network,
+                       const DBusPropertiesMap &parameters,
+                       Error *error,
                        const ResultCallback &callback,
                        int timeout) = 0;
   virtual void Disconnect(Error *error,
diff --git a/wimax_network_proxy.cc b/wimax_network_proxy.cc
index ed2dc73..9859d67 100644
--- a/wimax_network_proxy.cc
+++ b/wimax_network_proxy.cc
@@ -20,6 +20,10 @@
 
 WiMaxNetworkProxy::~WiMaxNetworkProxy() {}
 
+DBus::Path WiMaxNetworkProxy::proxy_object_path() const {
+  return proxy_.path();
+}
+
 uint32 WiMaxNetworkProxy::Identifier(Error *error) {
   SLOG(DBus, 2) << __func__;
   try {
diff --git a/wimax_network_proxy.h b/wimax_network_proxy.h
index b66a551..3902af4 100644
--- a/wimax_network_proxy.h
+++ b/wimax_network_proxy.h
@@ -18,6 +18,7 @@
   virtual ~WiMaxNetworkProxy();
 
   // Inherited from WiMaxNetwokProxyInterface.
+  virtual DBus::Path proxy_object_path() const;
   virtual uint32 Identifier(Error *error);
   virtual std::string Name(Error *error);
   virtual int Type(Error *error);
diff --git a/wimax_network_proxy_interface.h b/wimax_network_proxy_interface.h
index 530acb2..4c82e61 100644
--- a/wimax_network_proxy_interface.h
+++ b/wimax_network_proxy_interface.h
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SHILL_WIMAX_NETWORK_PROXY_INTERFACE_
-#define SHILL_WIMAX_NETWORK_PROXY_INTERFACE_
+#ifndef SHILL_WIMAX_NETWORK_PROXY_INTERFACE_H_
+#define SHILL_WIMAX_NETWORK_PROXY_INTERFACE_H_
 
 #include <string>
 
 #include <base/basictypes.h>
+#include <dbus-c++/dbus.h>
 
 namespace shill {
 
@@ -19,6 +20,8 @@
  public:
   virtual ~WiMaxNetworkProxyInterface() {}
 
+  virtual DBus::Path proxy_object_path() const = 0;
+
   // Properties.
   virtual uint32 Identifier(Error *error) = 0;
   virtual std::string Name(Error *error) = 0;
diff --git a/wimax_service.cc b/wimax_service.cc
index 741c3f2..b34b5bc 100644
--- a/wimax_service.cc
+++ b/wimax_service.cc
@@ -27,10 +27,32 @@
                            const WiMaxRefPtr &wimax)
     : Service(control, dispatcher, metrics, manager, Technology::kWiMax),
       wimax_(wimax),
-      network_identifier_(0) {}
+      network_identifier_(0),
+      need_passphrase_(true) {
+  PropertyStore *store = this->mutable_store();
+  // TODO(benchan): Support networks that require no user credentials or
+  // implicitly defined credentials.
+  store->RegisterBool(flimflam::kPassphraseRequiredProperty, &need_passphrase_);
+}
 
 WiMaxService::~WiMaxService() {}
 
+void WiMaxService::GetConnectParameters(DBusPropertiesMap *parameters) const {
+  CHECK(parameters);
+
+  (*parameters)[wimax_manager::kEAPAnonymousIdentity].writer()
+      .append_string(eap().anonymous_identity.c_str());
+  (*parameters)[wimax_manager::kEAPUserIdentity].writer()
+      .append_string(eap().identity.c_str());
+  (*parameters)[wimax_manager::kEAPUserPassword].writer()
+      .append_string(eap().password.c_str());
+}
+
+DBus::Path WiMaxService::GetNetworkObjectPath() const {
+  CHECK(proxy_.get());
+  return proxy_->proxy_object_path();
+}
+
 bool WiMaxService::Start(WiMaxNetworkProxyInterface *proxy) {
   SLOG(WiMax, 2) << __func__;
   proxy_.reset(proxy);
diff --git a/wimax_service.h b/wimax_service.h
index 410c04c..98e4cc2 100644
--- a/wimax_service.h
+++ b/wimax_service.h
@@ -23,6 +23,15 @@
                const WiMaxRefPtr &wimax);
   virtual ~WiMaxService();
 
+  // Returns the parameters to be passed to WiMaxManager.Device.Connect() when
+  // connecting to the network associated with this service.
+  void GetConnectParameters(DBusPropertiesMap *parameters) const;
+
+  // Returns the DBus object path for the WiMaxManager.Network object
+  // associated with this service. Must only be called after |proxy_| is set
+  // by Start().
+  DBus::Path GetNetworkObjectPath() const;
+
   // Returns true on success, false otherwise. Takes ownership of proxy,
   // regardless of the result of the operation.
   bool Start(WiMaxNetworkProxyInterface *proxy);
@@ -47,6 +56,7 @@
 
   uint32 network_identifier_;
   std::string network_name_;
+  bool need_passphrase_;
 
   DISALLOW_COPY_AND_ASSIGN(WiMaxService);
 };
diff --git a/wimax_service_unittest.cc b/wimax_service_unittest.cc
index 5162098..f0fa69a 100644
--- a/wimax_service_unittest.cc
+++ b/wimax_service_unittest.cc
@@ -19,6 +19,9 @@
 using testing::_;
 using testing::NiceMock;
 using testing::Return;
+using wimax_manager::kEAPAnonymousIdentity;
+using wimax_manager::kEAPUserIdentity;
+using wimax_manager::kEAPUserPassword;
 
 namespace shill {
 
@@ -51,6 +54,42 @@
   WiMaxServiceRefPtr service_;
 };
 
+TEST_F(WiMaxServiceTest, GetConnectParameters) {
+  {
+    DBusPropertiesMap parameters;
+    service_->GetConnectParameters(&parameters);
+
+    EXPECT_TRUE(ContainsKey(parameters, kEAPAnonymousIdentity));
+    EXPECT_STREQ("", parameters[kEAPAnonymousIdentity].reader().get_string());
+
+    EXPECT_TRUE(ContainsKey(parameters, kEAPUserIdentity));
+    EXPECT_STREQ("", parameters[kEAPUserIdentity].reader().get_string());
+
+    EXPECT_TRUE(ContainsKey(parameters, kEAPUserPassword));
+    EXPECT_STREQ("", parameters[kEAPUserPassword].reader().get_string());
+  }
+  {
+    Service::EapCredentials eap;
+    eap.anonymous_identity = "TestAnonymousIdentity";
+    eap.identity = "TestUserIdentity";
+    eap.password = "TestPassword";
+    service_->set_eap(eap);
+
+    DBusPropertiesMap parameters;
+    service_->GetConnectParameters(&parameters);
+
+    EXPECT_TRUE(ContainsKey(parameters, kEAPAnonymousIdentity));
+    EXPECT_EQ(eap.anonymous_identity,
+              parameters[kEAPAnonymousIdentity].reader().get_string());
+
+    EXPECT_TRUE(ContainsKey(parameters, kEAPUserIdentity));
+    EXPECT_EQ(eap.identity, parameters[kEAPUserIdentity].reader().get_string());
+
+    EXPECT_TRUE(ContainsKey(parameters, kEAPUserPassword));
+    EXPECT_EQ(eap.password, parameters[kEAPUserPassword].reader().get_string());
+  }
+}
+
 TEST_F(WiMaxServiceTest, TechnologyIs) {
   EXPECT_TRUE(service_->TechnologyIs(Technology::kWiMax));
   EXPECT_FALSE(service_->TechnologyIs(Technology::kEthernet));