[Telemetry] Add the MAC address field

This CL adds the MAC address field to the NetworkInfo type.
This field is guarded by a permission that is checked at runtime.

Bug: b/249246037, b/188897824
Test: browser_tests --gtest_filter="*TelemetryExtension*"
Change-Id: Icc73c313c3826aff161d2972cef22c85ade1ec4d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3934361
Commit-Queue: Bastian Kersting <bkersting@google.com>
Reviewed-by: Oleh Lamzin <lamzin@google.com>
Cr-Commit-Position: refs/heads/main@{#1071548}
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc
index 8d52a0f..f34983c 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc
@@ -19,6 +19,7 @@
 #include "chrome/common/chromeos/extensions/api/telemetry.h"
 #include "chromeos/crosapi/mojom/probe_service.mojom.h"
 #include "extensions/common/permissions/permissions_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromeos {
 
@@ -175,15 +176,23 @@
   }
   auto& network_info = ptr->network_result->get_network_health();
 
-  // TODO(b/249246037): This is not part of the converter since we will need to
-  // check permissions here for additional fields like MAC address that we want
-  // to add soon. Add the permission here as soon as it is available.
   api::os_telemetry::InternetConnectivityInfo result;
   for (auto& network : network_info->networks) {
+    absl::optional<std::string> mac_address;
+    if (extension()->permissions_data()->HasAPIPermission(
+            extensions::mojom::APIPermissionID::
+                kChromeOSTelemetryNetworkInformation)) {
+      mac_address = std::move(network->mac_address);
+    }
+
     auto converted_network =
         converters::ConvertPtr<api::os_telemetry::NetworkInfo>(
             std::move(network));
 
+    if (mac_address && !mac_address->empty()) {
+      converted_network.mac_address = std::move(mac_address);
+    }
+
     // Don't include networks with an undefined type.
     if (converted_network.type !=
         api::os_telemetry::NetworkType::NETWORK_TYPE_NONE) {
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc
index 1f59250..d9c6482 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc
@@ -719,6 +719,7 @@
       auto network = chromeos::network_health::mojom::Network::New();
       network->type = chromeos::network_config::mojom::NetworkType::kWiFi;
       network->state = chromeos::network_health::mojom::NetworkState::kOnline;
+      network->mac_address = "00:00:5e:00:53:af";
       network->ipv4_address = "1.1.1.1";
       network->ipv6_addresses = {"FE80:CD00:0000:0CDE:1257:0000:211E:729C"};
       network->signal_strength =
@@ -731,6 +732,7 @@
           chromeos::network_config::mojom::NetworkType::kAll;
       invalid_network->state =
           chromeos::network_health::mojom::NetworkState::kOnline;
+      invalid_network->mac_address = "00:00:5e:00:53:fu";
       invalid_network->ipv4_address = "2.2.2.2";
       invalid_network->ipv6_addresses = {
           "FE80:0000:CD00:729C:0CDE:1257:0000:211E"};
@@ -764,6 +766,7 @@
         const network_result = result.networks[0];
         chrome.test.assertEq('wifi', network_result.type);
         chrome.test.assertEq('online', network_result.state);
+        chrome.test.assertEq('00:00:5e:00:53:af', network_result.macAddress);
         chrome.test.assertEq('1.1.1.1', network_result.ipv4Address);
         chrome.test.assertEq(['FE80:CD00:0000:0CDE:1257:0000:211E:729C'],
           network_result.ipv6Addresses);
@@ -1207,17 +1210,19 @@
   )");
 }
 
-class TelemetryExtensionTelemetryApiWithoutSerialNumberBrowserTest
+class TelemetryExtensionTelemetryApiWithoutAdditionalPermissionsBrowserTest
     : public TelemetryExtensionTelemetryApiBrowserTest {
  public:
-  TelemetryExtensionTelemetryApiWithoutSerialNumberBrowserTest() = default;
-  ~TelemetryExtensionTelemetryApiWithoutSerialNumberBrowserTest() override =
+  TelemetryExtensionTelemetryApiWithoutAdditionalPermissionsBrowserTest() =
       default;
+  ~TelemetryExtensionTelemetryApiWithoutAdditionalPermissionsBrowserTest()
+      override = default;
 
-  TelemetryExtensionTelemetryApiWithoutSerialNumberBrowserTest(
+  TelemetryExtensionTelemetryApiWithoutAdditionalPermissionsBrowserTest(
       const BaseTelemetryExtensionBrowserTest&) = delete;
-  TelemetryExtensionTelemetryApiWithoutSerialNumberBrowserTest& operator=(
-      const TelemetryExtensionTelemetryApiWithoutSerialNumberBrowserTest&) =
+  TelemetryExtensionTelemetryApiWithoutAdditionalPermissionsBrowserTest&
+  operator=(
+      const TelemetryExtensionTelemetryApiWithoutAdditionalPermissionsBrowserTest&) =
       delete;
 
  protected:
@@ -1246,7 +1251,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(
-    TelemetryExtensionTelemetryApiWithoutSerialNumberBrowserTest,
+    TelemetryExtensionTelemetryApiWithoutAdditionalPermissionsBrowserTest,
     GetBatteryInfoWithoutSerialNumberPermission) {
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // If Probe interface is not available on this version of ash-chrome, this
@@ -1327,7 +1332,69 @@
 }
 
 IN_PROC_BROWSER_TEST_F(
-    TelemetryExtensionTelemetryApiWithoutSerialNumberBrowserTest,
+    TelemetryExtensionTelemetryApiWithoutAdditionalPermissionsBrowserTest,
+    GetOemInternetConnectivityWithoutPermission) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  // If Probe interface is not available on this version of ash-chrome, this
+  // test suite will no-op.
+  if (!IsServiceAvailable()) {
+    return;
+  }
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
+  // Configure FakeProbeService.
+  {
+    auto telemetry_info = crosapi::mojom::ProbeTelemetryInfo::New();
+
+    {
+      auto network = chromeos::network_health::mojom::Network::New();
+      network->type = chromeos::network_config::mojom::NetworkType::kWiFi;
+      network->state = chromeos::network_health::mojom::NetworkState::kOnline;
+      network->mac_address = "00:00:5e:00:53:af";
+      network->ipv4_address = "1.1.1.1";
+      network->ipv6_addresses = {"FE80:CD00:0000:0CDE:1257:0000:211E:729C"};
+      network->signal_strength =
+          chromeos::network_health::mojom::UInt32Value::New(100);
+
+      auto network_info =
+          chromeos::network_health::mojom::NetworkHealthState::New();
+      network_info->networks.push_back(std::move(network));
+
+      telemetry_info->network_result =
+          crosapi::mojom::ProbeNetworkResult::NewNetworkHealth(
+              std::move(network_info));
+    }
+
+    auto fake_service_impl = std::make_unique<FakeProbeService>();
+    fake_service_impl->SetProbeTelemetryInfoResponse(std::move(telemetry_info));
+    fake_service_impl->SetExpectedLastRequestedCategories(
+        {crosapi::mojom::ProbeCategoryEnum::kNetwork});
+
+    SetServiceForTesting(std::move(fake_service_impl));
+  }
+
+  CreateExtensionAndRunServiceWorker(R"(
+    chrome.test.runTests([
+      async function getInternetConnectivityInfo() {
+        const result = await chrome.os.telemetry.getInternetConnectivityInfo();
+        chrome.test.assertEq(1, result.networks.length);
+
+        const network_result = result.networks[0];
+        chrome.test.assertEq('wifi', network_result.type);
+        chrome.test.assertEq('online', network_result.state);
+        chrome.test.assertEq('1.1.1.1', network_result.ipv4Address);
+        chrome.test.assertEq(null, network_result.macAddress);
+        chrome.test.assertEq(['FE80:CD00:0000:0CDE:1257:0000:211E:729C'],
+          network_result.ipv6Addresses);
+        chrome.test.assertEq(100, network_result.signalStrength);
+        chrome.test.succeed();
+      }
+    ]);
+  )");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TelemetryExtensionTelemetryApiWithoutAdditionalPermissionsBrowserTest,
     GetOemDataWithoutSerialNumberPermission) {
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // If Probe interface is not available on this version of ash-chrome, this
@@ -1358,7 +1425,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(
-    TelemetryExtensionTelemetryApiWithoutSerialNumberBrowserTest,
+    TelemetryExtensionTelemetryApiWithoutAdditionalPermissionsBrowserTest,
     GetVpdInfoWithoutSerialNumberPermission) {
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // If Probe interface is not available on this version of ash-chrome, this
diff --git a/chrome/common/chromeos/extensions/api/telemetry.idl b/chrome/common/chromeos/extensions/api/telemetry.idl
index ce42bd224..bf531ab0 100644
--- a/chrome/common/chromeos/extensions/api/telemetry.idl
+++ b/chrome/common/chromeos/extensions/api/telemetry.idl
@@ -117,6 +117,7 @@
   dictionary NetworkInfo {
     NetworkType? type;
     NetworkState? state;
+    DOMString? macAddress;
     DOMString? ipv4Address;
     DOMString[] ipv6Addresses;
     double? signalStrength;