diagnostics: add network_health_adapter

The network_health_adapter is a wrapper around the Chrome mojo service,
NetworkHealth. The remote from NetworkHealth will be sent when Chrome
starts up and bootstraps the mojo connection to cros_healthd. This
service will eventually be used to gather network telemetry.

BUG=chromium:1057739
TEST=FEATURES=test emerge-sarien diagnostics;
cros deploy dut diagnostics

Cq-Depend: chromium:2333268
Change-Id: If698dd7fc1ad02902712183711cb7c2ad85b9f8c
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2315388
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Reviewed-by: Paul Moy <pmoy@chromium.org>
Tested-by: Trent Begin <tbegin@chromium.org>
Commit-Queue: Trent Begin <tbegin@chromium.org>
diff --git a/diagnostics/BUILD.gn b/diagnostics/BUILD.gn
index eb660d9..bcba6eb 100644
--- a/diagnostics/BUILD.gn
+++ b/diagnostics/BUILD.gn
@@ -20,6 +20,7 @@
       "//diagnostics/cros_healthd:cros_healthd_test",
       "//diagnostics/cros_healthd/events:libcros_healthd_events_test",
       "//diagnostics/cros_healthd/fetchers:libcros_healthd_fetchers_test",
+      "//diagnostics/cros_healthd/network:network_test",
       "//diagnostics/cros_healthd/routines:routine_test",
       "//diagnostics/cros_healthd/system:system_config_test",
       "//diagnostics/cros_healthd/utils:libcros_healthd_utils_test",
diff --git a/diagnostics/cros_healthd/cros_healthd.cc b/diagnostics/cros_healthd/cros_healthd.cc
index 91f6b7d..bf301cc 100644
--- a/diagnostics/cros_healthd/cros_healthd.cc
+++ b/diagnostics/cros_healthd/cros_healthd.cc
@@ -172,6 +172,12 @@
   mojo_service_->AddEventBinding(std::move(service));
 }
 
+void CrosHealthd::SendNetworkHealthService(
+    mojo::PendingRemote<chromeos::network_health::mojom::NetworkHealthService>
+        remote) {
+  context_->network_health_adapter()->SetServiceRemote(std::move(remote));
+}
+
 void CrosHealthd::ShutDownDueToMojoError(const std::string& debug_reason) {
   // Our daemon has to be restarted to be prepared for future Mojo connection
   // bootstraps. We can't do this without a restart since Mojo EDK gives no
diff --git a/diagnostics/cros_healthd/cros_healthd.h b/diagnostics/cros_healthd/cros_healthd.h
index 05ab9f1..cff7b28 100644
--- a/diagnostics/cros_healthd/cros_healthd.h
+++ b/diagnostics/cros_healthd/cros_healthd.h
@@ -52,6 +52,9 @@
   void GetEventService(
       chromeos::cros_healthd::mojom::CrosHealthdEventServiceRequest service)
       override;
+  void SendNetworkHealthService(
+      mojo::PendingRemote<chromeos::network_health::mojom::NetworkHealthService>
+          remote) override;
 
   // Implementation of the "org.chromium.CrosHealthdInterface" D-Bus interface
   // exposed by the cros_healthd daemon (see constants for the API methods at
diff --git a/diagnostics/cros_healthd/network/BUILD.gn b/diagnostics/cros_healthd/network/BUILD.gn
new file mode 100644
index 0000000..a56b062
--- /dev/null
+++ b/diagnostics/cros_healthd/network/BUILD.gn
@@ -0,0 +1,43 @@
+# Copyright 2020 The Chromium OS 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("//common-mk/pkg_config.gni")
+
+pkg_config("libnetwork_health_pkg_deps") {
+  pkg_deps = [
+    "libchrome-${libbase_ver}",
+    "libchrome-test-${libbase_ver}",
+    "libmojo-${libbase_ver}",
+  ]
+}
+
+source_set("libnetwork_health_adapter") {
+  configs += [ ":libnetwork_health_pkg_deps" ]
+  deps = [ "//diagnostics/mojo:network_health_mojo_bindings" ]
+  sources = [ "network_health_adapter_impl.cc" ]
+}
+
+if (use.test) {
+  executable("network_test") {
+    configs += [
+      ":libnetwork_health_pkg_deps",
+      "//common-mk:test",
+    ]
+    deps = [
+      ":libnetwork_health_adapter",
+      "//common-mk/testrunner:testrunner",
+      "//diagnostics/mojo:network_health_mojo_bindings",
+    ]
+    sources = [ "network_health_adapter_impl_test.cc" ]
+  }
+
+  source_set("libnetwork_health_adapter_test_utils") {
+    configs += [ ":libnetwork_health_pkg_deps" ]
+    deps = [
+      ":libnetwork_health_adapter",
+      "//diagnostics/mojo:cros_healthd_mojo_bindings",
+    ]
+    sources = [ "fake_network_health_adapter.cc" ]
+  }
+}
diff --git a/diagnostics/cros_healthd/network/fake_network_health_adapter.cc b/diagnostics/cros_healthd/network/fake_network_health_adapter.cc
new file mode 100644
index 0000000..96fb8bb
--- /dev/null
+++ b/diagnostics/cros_healthd/network/fake_network_health_adapter.cc
@@ -0,0 +1,43 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "diagnostics/cros_healthd/network/fake_network_health_adapter.h"
+
+#include <utility>
+
+#include <base/optional.h>
+
+#include "mojo/network_health.mojom.h"
+
+namespace {
+
+using chromeos::network_health::mojom::NetworkHealthStatePtr;
+
+}  // namespace
+
+namespace diagnostics {
+
+FakeNetworkHealthAdapter::FakeNetworkHealthAdapter() = default;
+FakeNetworkHealthAdapter::~FakeNetworkHealthAdapter() = default;
+
+void FakeNetworkHealthAdapter::GetNetworkHealthState(
+    FetchNetworkStateCallback callback) {
+  if (!bound_) {
+    std::move(callback).Run(base::nullopt);
+    return;
+  }
+
+  std::move(callback).Run(network_health_state_.Clone());
+}
+
+void FakeNetworkHealthAdapter::SetRemoteBound(bool bound) {
+  bound_ = bound;
+}
+
+void FakeNetworkHealthAdapter::SetNetworkHealthStateResponse(
+    NetworkHealthStatePtr network_health_state) {
+  network_health_state_ = std::move(network_health_state);
+}
+
+}  // namespace diagnostics
diff --git a/diagnostics/cros_healthd/network/fake_network_health_adapter.h b/diagnostics/cros_healthd/network/fake_network_health_adapter.h
new file mode 100644
index 0000000..9d65d64
--- /dev/null
+++ b/diagnostics/cros_healthd/network/fake_network_health_adapter.h
@@ -0,0 +1,44 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DIAGNOSTICS_CROS_HEALTHD_NETWORK_FAKE_NETWORK_HEALTH_ADAPTER_H_
+#define DIAGNOSTICS_CROS_HEALTHD_NETWORK_FAKE_NETWORK_HEALTH_ADAPTER_H_
+
+#include "diagnostics/cros_healthd/network/network_health_adapter.h"
+#include "mojo/network_health.mojom-forward.h"
+
+namespace diagnostics {
+
+// Fake implementation of the NetworkHealthAdapter interface used for testing.
+class FakeNetworkHealthAdapter final : public NetworkHealthAdapter {
+ public:
+  FakeNetworkHealthAdapter();
+  FakeNetworkHealthAdapter(const FakeNetworkHealthAdapter&) = delete;
+  FakeNetworkHealthAdapter& operator=(const FakeNetworkHealthAdapter&) = delete;
+  ~FakeNetworkHealthAdapter() override;
+
+  // NetworkHealthAdapterInterface overrides:
+  void GetNetworkHealthState(FetchNetworkStateCallback callback) override;
+  // Unimplemented. The fake implementation is not going to use the service
+  // remote, so nothing needs to be done.
+  void SetServiceRemote(
+      mojo::PendingRemote<chromeos::network_health::mojom::NetworkHealthService>
+          remote) override {}
+
+  // Method to provide the canned response for the GetNetworkHealthState
+  // request.
+  void SetNetworkHealthStateResponse(
+      chromeos::network_health::mojom::NetworkHealthStatePtr response);
+
+  // Method to set if the internal NetworkHealthService remote is bound.
+  void SetRemoteBound(bool bound);
+
+ private:
+  bool bound_;
+  chromeos::network_health::mojom::NetworkHealthStatePtr network_health_state_;
+};
+
+}  // namespace diagnostics
+
+#endif  // DIAGNOSTICS_CROS_HEALTHD_NETWORK_FAKE_NETWORK_HEALTH_ADAPTER_H_
diff --git a/diagnostics/cros_healthd/network/network_health_adapter.h b/diagnostics/cros_healthd/network/network_health_adapter.h
new file mode 100644
index 0000000..9d7d1af
--- /dev/null
+++ b/diagnostics/cros_healthd/network/network_health_adapter.h
@@ -0,0 +1,36 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DIAGNOSTICS_CROS_HEALTHD_NETWORK_NETWORK_HEALTH_ADAPTER_H_
+#define DIAGNOSTICS_CROS_HEALTHD_NETWORK_NETWORK_HEALTH_ADAPTER_H_
+
+#include <base/callback_forward.h>
+#include <base/optional.h>
+#include <mojo/public/cpp/bindings/pending_remote.h>
+
+#include "mojo/network_health.mojom-forward.h"
+
+namespace diagnostics {
+
+// Interface for interacting with the NetworkHealthService in Chrome.
+class NetworkHealthAdapter {
+ public:
+  using FetchNetworkStateCallback = base::OnceCallback<void(
+      base::Optional<chromeos::network_health::mojom::NetworkHealthStatePtr>)>;
+  virtual ~NetworkHealthAdapter() = default;
+
+  // Request to get the NetworkHealthState snapshot. Will return the
+  // NetworkHealthState if the remote is bound, or base::nullopt if the remote
+  // is not bound through the callback.
+  virtual void GetNetworkHealthState(FetchNetworkStateCallback callback) = 0;
+
+  // Method that sets the internal NetworkHealthService remote.
+  virtual void SetServiceRemote(
+      mojo::PendingRemote<chromeos::network_health::mojom::NetworkHealthService>
+          remote) = 0;
+};
+
+}  // namespace diagnostics
+
+#endif  // DIAGNOSTICS_CROS_HEALTHD_NETWORK_NETWORK_HEALTH_ADAPTER_H_
diff --git a/diagnostics/cros_healthd/network/network_health_adapter_impl.cc b/diagnostics/cros_healthd/network/network_health_adapter_impl.cc
new file mode 100644
index 0000000..a8e084c
--- /dev/null
+++ b/diagnostics/cros_healthd/network/network_health_adapter_impl.cc
@@ -0,0 +1,51 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "diagnostics/cros_healthd/network/network_health_adapter_impl.h"
+
+#include <utility>
+
+#include <base/callback.h>
+#include <base/optional.h>
+
+#include "mojo/network_health.mojom.h"
+
+namespace diagnostics {
+
+namespace {
+
+namespace network_health_ipc = chromeos::network_health::mojom;
+
+// Forwards the response from the network health remote to |callback|.
+void OnNetworkHealthStateReceived(
+    base::OnceCallback<void(
+        base::Optional<network_health_ipc::NetworkHealthStatePtr>)> callback,
+    network_health_ipc::NetworkHealthStatePtr response) {
+  std::move(callback).Run(std::move(response));
+}
+
+}  // namespace
+
+NetworkHealthAdapterImpl::NetworkHealthAdapterImpl() = default;
+NetworkHealthAdapterImpl::~NetworkHealthAdapterImpl() = default;
+
+void NetworkHealthAdapterImpl::GetNetworkHealthState(
+    FetchNetworkStateCallback callback) {
+  if (!network_health_remote_.is_bound()) {
+    std::move(callback).Run(base::nullopt);
+    return;
+  }
+
+  network_health_remote_->GetHealthSnapshot(
+      base::BindOnce(&OnNetworkHealthStateReceived, std::move(callback)));
+}
+
+void NetworkHealthAdapterImpl::SetServiceRemote(
+    mojo::PendingRemote<network_health_ipc::NetworkHealthService> remote) {
+  if (network_health_remote_.is_bound())
+    network_health_remote_.reset();
+  network_health_remote_.Bind(std::move(remote));
+}
+
+}  // namespace diagnostics
diff --git a/diagnostics/cros_healthd/network/network_health_adapter_impl.h b/diagnostics/cros_healthd/network/network_health_adapter_impl.h
new file mode 100644
index 0000000..e38c61a
--- /dev/null
+++ b/diagnostics/cros_healthd/network/network_health_adapter_impl.h
@@ -0,0 +1,41 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DIAGNOSTICS_CROS_HEALTHD_NETWORK_NETWORK_HEALTH_ADAPTER_IMPL_H_
+#define DIAGNOSTICS_CROS_HEALTHD_NETWORK_NETWORK_HEALTH_ADAPTER_IMPL_H_
+
+#include <base/memory/weak_ptr.h>
+#include <mojo/public/cpp/bindings/pending_remote.h>
+#include <mojo/public/cpp/bindings/remote.h>
+
+#include "diagnostics/cros_healthd/network/network_health_adapter.h"
+#include "mojo/network_health.mojom.h"
+
+namespace diagnostics {
+
+// Production implementation of the NetworkHealthAdapter.
+class NetworkHealthAdapterImpl final : public NetworkHealthAdapter {
+ public:
+  NetworkHealthAdapterImpl();
+  NetworkHealthAdapterImpl(const NetworkHealthAdapterImpl&) = delete;
+  NetworkHealthAdapterImpl& operator=(const NetworkHealthAdapterImpl&) = delete;
+  ~NetworkHealthAdapterImpl() override;
+
+  // NetworkHealthAdapterInterface overrides:
+  void GetNetworkHealthState(FetchNetworkStateCallback callback) override;
+  void SetServiceRemote(
+      mojo::PendingRemote<chromeos::network_health::mojom::NetworkHealthService>
+          remote) override;
+
+ private:
+  mojo::Remote<chromeos::network_health::mojom::NetworkHealthService>
+      network_health_remote_;
+
+  // Must be the last member of the class.
+  base::WeakPtrFactory<NetworkHealthAdapterImpl> weak_factory_{this};
+};
+
+}  // namespace diagnostics
+
+#endif  // DIAGNOSTICS_CROS_HEALTHD_NETWORK_NETWORK_HEALTH_ADAPTER_IMPL_H_
diff --git a/diagnostics/cros_healthd/network/network_health_adapter_impl_test.cc b/diagnostics/cros_healthd/network/network_health_adapter_impl_test.cc
new file mode 100644
index 0000000..3fcc38d
--- /dev/null
+++ b/diagnostics/cros_healthd/network/network_health_adapter_impl_test.cc
@@ -0,0 +1,101 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utility>
+
+#include <base/callback.h>
+#include <base/message_loop/message_loop.h>
+#include <base/optional.h>
+#include <base/run_loop.h>
+#include <base/test/bind_test_util.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <mojo/core/embedder/embedder.h>
+
+#include "diagnostics/cros_healthd/network/network_health_adapter_impl.h"
+#include "mojo/network_health.mojom.h"
+
+namespace diagnostics {
+
+namespace {
+
+namespace network_health_ipc = chromeos::network_health::mojom;
+
+class MockNetworkHealthService
+    : public network_health_ipc::NetworkHealthService {
+ public:
+  MockNetworkHealthService() : receiver_{this} {}
+  MockNetworkHealthService(const MockNetworkHealthService&) = delete;
+  MockNetworkHealthService& operator=(const MockNetworkHealthService&) = delete;
+
+  MOCK_METHOD(void,
+              GetNetworkList,
+              (NetworkHealthService::GetNetworkListCallback),
+              (override));
+  MOCK_METHOD(void,
+              GetHealthSnapshot,
+              (NetworkHealthService::GetHealthSnapshotCallback),
+              (override));
+
+  mojo::PendingRemote<network_health_ipc::NetworkHealthService>
+  pending_remote() {
+    return receiver_.BindNewPipeAndPassRemote();
+  }
+
+ private:
+  mojo::Receiver<NetworkHealthService> receiver_;
+};
+
+}  // namespace
+
+class NetworkHealthAdapterImplTest : public testing::Test {
+ protected:
+  NetworkHealthAdapterImplTest() { mojo::core::Init(); }
+
+  NetworkHealthAdapterImpl* network_health_adapter() {
+    return &network_health_adapter_;
+  }
+
+ private:
+  base::MessageLoop message_loop_;
+  NetworkHealthAdapterImpl network_health_adapter_;
+};
+
+// Test that the NetworkHealthAdapterImpl can set the NetworkHealthService
+// remote and request the NetworkHealthState.
+TEST_F(NetworkHealthAdapterImplTest, RequestNetworkHealthState) {
+  MockNetworkHealthService service;
+  network_health_adapter()->SetServiceRemote(service.pending_remote());
+
+  base::RunLoop run_loop;
+  auto canned_response = network_health_ipc::NetworkHealthState::New();
+  EXPECT_CALL(service, GetHealthSnapshot(testing::_))
+      .WillOnce(testing::Invoke([&](network_health_ipc::NetworkHealthService::
+                                        GetHealthSnapshotCallback callback) {
+        std::move(callback).Run(canned_response.Clone());
+      }));
+
+  network_health_adapter()->GetNetworkHealthState(base::BindLambdaForTesting(
+      [&](base::Optional<network_health_ipc::NetworkHealthStatePtr> response) {
+        ASSERT_TRUE(response.has_value());
+        EXPECT_EQ(canned_response, response);
+        run_loop.Quit();
+      }));
+
+  run_loop.Run();
+}
+
+// Test a base::nullopt is returned if no remote is bound;
+TEST_F(NetworkHealthAdapterImplTest, NoRemote) {
+  base::RunLoop run_loop;
+  network_health_adapter()->GetNetworkHealthState(base::BindLambdaForTesting(
+      [&](base::Optional<network_health_ipc::NetworkHealthStatePtr> response) {
+        EXPECT_FALSE(response.has_value());
+        run_loop.Quit();
+      }));
+
+  run_loop.Run();
+}
+
+}  // namespace diagnostics
diff --git a/diagnostics/cros_healthd/system/BUILD.gn b/diagnostics/cros_healthd/system/BUILD.gn
index 1c47dc2..2c2bab3 100644
--- a/diagnostics/cros_healthd/system/BUILD.gn
+++ b/diagnostics/cros_healthd/system/BUILD.gn
@@ -22,6 +22,7 @@
   deps = [
     "//diagnostics/common:libcommon",
     "//diagnostics/cros_healthd/executor:libcros_healthd_executor",
+    "//diagnostics/cros_healthd/network:libnetwork_health_adapter",
   ]
   sources = [
     "context.cc",
@@ -55,6 +56,7 @@
       ":libcros_healthd_system",
       "//diagnostics/common:libcommon_test_utils",
       "//diagnostics/cros_healthd/executor:libcros_healthd_executor_test_utils",
+      "//diagnostics/cros_healthd/network:libnetwork_health_adapter_test_utils",
     ]
     sources = [
       "fake_system_config.cc",
diff --git a/diagnostics/cros_healthd/system/context.cc b/diagnostics/cros_healthd/system/context.cc
index 6219415..f3c6275 100644
--- a/diagnostics/cros_healthd/system/context.cc
+++ b/diagnostics/cros_healthd/system/context.cc
@@ -15,6 +15,7 @@
 #include "diagnostics/common/system/debugd_adapter_impl.h"
 #include "diagnostics/common/system/powerd_adapter_impl.h"
 #include "diagnostics/cros_healthd/executor/executor_adapter_impl.h"
+#include "diagnostics/cros_healthd/network/network_health_adapter_impl.h"
 #include "diagnostics/cros_healthd/system/system_config.h"
 #include "diagnostics/cros_healthd/system/system_utilities_impl.h"
 
@@ -40,6 +41,8 @@
   debugd_proxy_ = std::make_unique<org::chromium::debugdProxy>(dbus_bus_);
   debugd_adapter_ = std::make_unique<DebugdAdapterImpl>(
       std::make_unique<org::chromium::debugdProxy>(dbus_bus_));
+  // Create the NetworkHealthAdapter.
+  network_health_adapter_ = std::make_unique<NetworkHealthAdapterImpl>();
   // TODO(crbug/1074476): Remove |power_manager_proxy_| once |powerd_adapter_|
   // supports all the methods we call on |power_manager_proxy_|.
   power_manager_proxy_ = dbus_bus_->GetObjectProxy(
@@ -77,6 +80,10 @@
   return debugd_adapter_.get();
 }
 
+NetworkHealthAdapter* Context::network_health_adapter() const {
+  return network_health_adapter_.get();
+}
+
 dbus::ObjectProxy* Context::power_manager_proxy() const {
   return power_manager_proxy_;
 }
diff --git a/diagnostics/cros_healthd/system/context.h b/diagnostics/cros_healthd/system/context.h
index cf093f0..2181612 100644
--- a/diagnostics/cros_healthd/system/context.h
+++ b/diagnostics/cros_healthd/system/context.h
@@ -18,6 +18,7 @@
 #include "diagnostics/common/system/debugd_adapter.h"
 #include "diagnostics/common/system/powerd_adapter.h"
 #include "diagnostics/cros_healthd/executor/executor_adapter.h"
+#include "diagnostics/cros_healthd/network/network_health_adapter.h"
 #include "diagnostics/cros_healthd/system/system_config_interface.h"
 #include "diagnostics/cros_healthd/system/system_utilities.h"
 
@@ -61,6 +62,10 @@
   // Example: cros_healthd calls out to debugd with async callbacks when it
   // needs to trigger nvme self-test or collect data like progress info.
   DebugdAdapter* debugd_adapter() const;
+  // Use the object returned by network_health_adapter() to make requests to the
+  // NetworkHealthService. Example: cros_healthd calls out to the
+  // NetworkHealthService to get network telemetry data.
+  NetworkHealthAdapter* network_health_adapter() const;
   // Use the object returned by power_manager_proxy() to make calls to
   // power_manager. Example: cros_healthd calls out to power_manager when it
   // needs to collect battery metrics like cycle count.
@@ -98,6 +103,7 @@
   std::unique_ptr<BluetoothClient> bluetooth_client_;
   std::unique_ptr<org::chromium::debugdProxyInterface> debugd_proxy_;
   std::unique_ptr<DebugdAdapter> debugd_adapter_;
+  std::unique_ptr<NetworkHealthAdapter> network_health_adapter_;
   // Owned by |dbus_bus_|.
   dbus::ObjectProxy* power_manager_proxy_;
   std::unique_ptr<PowerdAdapter> powerd_adapter_;
diff --git a/diagnostics/cros_healthd/system/mock_context.cc b/diagnostics/cros_healthd/system/mock_context.cc
index 2650ca5..1de2420 100644
--- a/diagnostics/cros_healthd/system/mock_context.cc
+++ b/diagnostics/cros_healthd/system/mock_context.cc
@@ -28,6 +28,7 @@
   debugd_proxy_ =
       std::make_unique<testing::StrictMock<org::chromium::debugdProxyMock>>();
   debugd_adapter_ = std::make_unique<testing::StrictMock<MockDebugdAdapter>>();
+  network_health_adapter_ = std::make_unique<FakeNetworkHealthAdapter>();
   power_manager_proxy_ = mock_power_manager_proxy_.get();
   powerd_adapter_ = std::make_unique<FakePowerdAdapter>();
   system_config_ = std::make_unique<FakeSystemConfig>();
@@ -51,6 +52,10 @@
       debugd_adapter_.get());
 }
 
+FakeNetworkHealthAdapter* MockContext::fake_network_health_adapter() const {
+  return static_cast<FakeNetworkHealthAdapter*>(network_health_adapter_.get());
+}
+
 dbus::MockObjectProxy* MockContext::mock_power_manager_proxy() const {
   return mock_power_manager_proxy_.get();
 }
diff --git a/diagnostics/cros_healthd/system/mock_context.h b/diagnostics/cros_healthd/system/mock_context.h
index 8ea806c..e6dad04 100644
--- a/diagnostics/cros_healthd/system/mock_context.h
+++ b/diagnostics/cros_healthd/system/mock_context.h
@@ -14,6 +14,7 @@
 #include "diagnostics/common/system/fake_powerd_adapter.h"
 #include "diagnostics/common/system/mock_debugd_adapter.h"
 #include "diagnostics/cros_healthd/executor/mock_executor_adapter.h"
+#include "diagnostics/cros_healthd/network/fake_network_health_adapter.h"
 #include "diagnostics/cros_healthd/system/context.h"
 #include "diagnostics/cros_healthd/system/fake_system_config.h"
 #include "diagnostics/cros_healthd/system/fake_system_utilities.h"
@@ -42,6 +43,7 @@
   org::chromium::debugdProxyMock* mock_debugd_proxy() const;
   MockDebugdAdapter* mock_debugd_adapter() const;
   dbus::MockObjectProxy* mock_power_manager_proxy() const;
+  FakeNetworkHealthAdapter* fake_network_health_adapter() const;
   FakePowerdAdapter* fake_powerd_adapter() const;
   FakeSystemConfig* fake_system_config() const;
   FakeSystemUtilities* fake_system_utils() const;
diff --git a/diagnostics/mojo/BUILD.gn b/diagnostics/mojo/BUILD.gn
index 0f9c03f..c8b9507 100644
--- a/diagnostics/mojo/BUILD.gn
+++ b/diagnostics/mojo/BUILD.gn
@@ -7,6 +7,7 @@
 
 generate_mojom_bindings("cros_healthd_mojo_bindings") {
   mojo_root = "//diagnostics"
+  deps = [ ":network_health_mojo_bindings" ]
   sources = [
     "cros_healthd.mojom",
     "cros_healthd_diagnostics.mojom",
@@ -15,6 +16,14 @@
   ]
 }
 
+generate_mojom_bindings("network_health_mojo_bindings") {
+  mojo_root = "//diagnostics"
+  sources = [
+    "network_health.mojom",
+    "network_types.mojom",
+  ]
+}
+
 generate_mojom_bindings("wilco_dtc_supportd_mojo_bindings") {
   mojo_root = "//diagnostics"
   sources = [ "wilco_dtc_supportd.mojom" ]
diff --git a/diagnostics/mojo/cros_healthd.mojom b/diagnostics/mojo/cros_healthd.mojom
index 4abe2bf..b4175bb 100644
--- a/diagnostics/mojo/cros_healthd.mojom
+++ b/diagnostics/mojo/cros_healthd.mojom
@@ -13,9 +13,11 @@
 import "cros_healthd_diagnostics.mojom";
 import "cros_healthd_events.mojom";
 import "cros_healthd_probe.mojom";
+import "network_health.mojom";
 
 // Factory interface which allows remote ends to request implementations of the
-// probe or diagnostics services.
+// probe or diagnostics services or to receive network services sent from
+// Chrome.
 interface CrosHealthdServiceFactory {
   // Returns a bound interface to the diagnostics service.
   GetDiagnosticsService(CrosHealthdDiagnosticsService& service);
@@ -23,6 +25,10 @@
   GetEventService(CrosHealthdEventService& service);
   // Returns a bound interface to the probe service.
   GetProbeService(CrosHealthdProbeService& service);
+  // Sends a bound interface to the Network Health service in Chrome.
+  SendNetworkHealthService(
+      pending_remote<
+          chromeos.network_health.mojom.NetworkHealthService> remote);
 };
 
 // Diagnostics interface exposed by the cros_healthd daemon.
diff --git a/diagnostics/mojo/network_health.mojom b/diagnostics/mojo/network_health.mojom
new file mode 100644
index 0000000..ee81065
--- /dev/null
+++ b/diagnostics/mojo/network_health.mojom
@@ -0,0 +1,68 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// API intended for retrieving a snapshot of the network health state. Returns
+// properties of any available network technologies and any connected or
+// connecting network when available.
+
+// NOTE: This mojom should kept in sync with the copy in Chromium's repo in
+// src/chromeos/services/network_health/public/mojom/network_health.mojom.
+
+module chromeos.network_health.mojom;
+
+import "network_types.mojom";
+
+enum NetworkState {
+  // The network type is available but not yet initialized.
+  kUninitialized,
+  // The network type is available but disabled or disabling.
+  kDisabled,
+  // The network type is prohibited by policy.
+  kProhibited,
+  // The network type is available and enabled or enabling, but no network
+  // connection has been established.
+  kNotConnected,
+  // The network type is available and enabled, and a network connection is
+  // in progress.
+  kConnecting,
+  // The network is in a portal state.
+  kPortal,
+  // The network is in a connected state, but connectivity is limited.
+  kConnected,
+  // The network is connected and online.
+  kOnline,
+};
+
+// Contains information for a single network connection and underlying
+// network technology e.g WiFi.
+struct Network {
+  chromeos.network_config.mojom.NetworkType type;
+  NetworkState state;
+  // The unique identifier for the network when a network service exists.
+  string? guid;
+  // The user facing name of the network if available.
+  string? name;
+  // Optional string for the network devices's mac_address. This field is not
+  // intended to be parsed and is only for informational purposes.
+  string? mac_address;
+};
+
+// Aggregate structure for all of the network health state.
+struct NetworkHealthState {
+  // Networks will be sorted with active connections listed first.
+  array<Network> networks;
+};
+
+// Interface for retrieving aggregated information about the current network
+// state and health.
+interface NetworkHealthService {
+  // Returns a list of all the networks. Networks will be sorted with active
+  // connections listed first.
+  GetNetworkList() => (array<Network> networks);
+
+  // Returns the current network health state.
+  // This is currently the same information provided by GetNetworkList. More
+  // information will be added over time.
+  GetHealthSnapshot() => (NetworkHealthState state);
+};
diff --git a/diagnostics/mojo/network_types.mojom b/diagnostics/mojo/network_types.mojom
new file mode 100644
index 0000000..cb5224b
--- /dev/null
+++ b/diagnostics/mojo/network_types.mojom
@@ -0,0 +1,78 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// These are shared enums used by cros_network_config.
+
+// NOTE: This mojom should kept in sync with the copy in Chromium's repo in
+// src/chromeos/services/network_config/public/mojom/network_config.mojom.
+
+module chromeos.network_config.mojom;
+
+// Connection state of visible networks.
+enum ConnectionStateType {
+  kOnline,
+  kConnected,
+  kPortal,
+  kConnecting,
+  kNotConnected,
+};
+
+// Device / Technology state for devices.
+enum DeviceStateType {
+  kUninitialized,
+  kDisabled,
+  kDisabling,
+  kEnabling,
+  kEnabled,
+  kProhibited,
+  // Not used in DeviceStateProperties, but useful when querying by type.
+  kUnavailable,
+};
+
+// The network technology type. NOTE: 'All' and 'Wireless' are only used by
+// FilterType for requesting groups of networks.
+enum NetworkType {
+  kAll,
+  kCellular,
+  kEthernet,
+  // Mobile includes Cellular, and Tether.
+  kMobile,
+  kTether,
+  kVPN,
+  // Wireles includes Cellular, Tether, and WiFi.
+  kWireless,
+  kWiFi,
+};
+
+// The ONC source for the network configuration, i.e. whether it is stored in
+// the User or Device profile and whether it was configured by policy.
+enum OncSource {
+  // The network is not remembered, or the property is not configurable.
+  kNone,
+  // The configuration is saved in the user profile.
+  kUser,
+  // The configuration is saved in the device profile.
+  kDevice,
+  // The configuration came from a user policy and is saved in the user profile.
+  kUserPolicy,
+  // The configuration came from a device policy and is saved in the device
+  // profile.
+  kDevicePolicy,
+};
+
+// The policy source for property values managed by policy.
+enum PolicySource {
+  // The property is not controlled by policy.
+  kNone,
+  // The property value came from a user policy and is enforced.
+  kUserPolicyEnforced,
+  // The property value came from a device policy and is enforced.
+  kDevicePolicyEnforced,
+  // The property value came from a user policy and is recommended.
+  kUserPolicyRecommended,
+  // The property value came from a device policy and is recommended.
+  kDevicePolicyRecommended,
+  // The property value came from an extension.
+  kActiveExtension,
+};