Bug 1636539 - Part 4: Use Rust remote settings client to fetch remote kill switch. r?agashlin,bytesized draft
authorNick Alexander <nalexander@mozilla.com>
Tue, 23 Jun 2020 13:20:33 -0700
changeset 2999947 6a84a323332b1588c49e8293406b36335a3d0028
parent 2999946 6306f8b70aab00ccafc5bc7f5097c461e33ba289
child 2999948 dcbad051581a79971415d22d0419ec7046610552
push id558587
push usernalexander@mozilla.com
push dateTue, 23 Jun 2020 23:30:09 +0000
treeherdertry@dcbad051581a [default view] [failures only]
reviewersagashlin, bytesized
bugs1636539
milestone79.0a1
Bug 1636539 - Part 4: Use Rust remote settings client to fetch remote kill switch. r?agashlin,bytesized
toolkit/mozapps/defaultagent/RemoteSettings.cpp
toolkit/mozapps/defaultagent/RemoteSettings.h
toolkit/mozapps/defaultagent/main.cpp
toolkit/mozapps/defaultagent/moz.build
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/defaultagent/RemoteSettings.cpp
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "RemoteSettings.h"
+
+#include <iostream>
+#include <windows.h>
+#include <shlwapi.h>
+
+#include "common.h"
+#include "Registry.h"
+
+#include "mozilla/Maybe.h"
+#include "mozilla/Result.h"
+#include "mozilla/Unused.h"
+
+// All strings cross the C/C++ <-> Rust FFI boundary as
+// null-terminated UTF-8.
+extern "C" {
+int IsAgentRemoteDisabledRust(const char* szUrl, DWORD* lpdwDisabled);
+}
+
+#define PROD_ENDPOINT "https://firefox.settings.services.mozilla.com/v2"
+#define PROD_CID "windows-default-browser-agent"
+#define PROD_GUID "ffffffff-0c5f-49a0-bb48-11f17173ffff"
+
+#define PROD_URL \
+  PROD_ENDPOINT "/buckets/main/collections/" PROD_CID "/records/" PROD_GUID
+
+using BoolResult = mozilla::WindowsErrorResult<bool>;
+
+// Use Rust library to query remote service endpoint to determine if
+// WDBA is disabled.
+//
+// Pass through errors.
+static BoolResult IsAgentRemoteDisabledInternal() {
+  // Fetch remote service disabled state URL from registry.
+  auto urlResult =
+      RegistryGetValueString(L"ServicesSettingsServer");  // XXX: FULL URL.
+
+  // Unconfigured?  Fallback to production.
+  std::string url = urlResult.unwrapOr(mozilla::Some(std::string(PROD_URL)))
+                        .valueOr(std::string(PROD_URL));
+
+  std::cerr << "default-browser-agent: Remote service disabled state URL: '"
+            << url << "'" << std::endl;
+
+  // Invoke Rust to query remote settings.
+  DWORD isRemoteDisabled;
+  LSTATUS ls = IsAgentRemoteDisabledRust(url.c_str(), &isRemoteDisabled);
+
+  std::cerr << "default-browser-agent: Error code: 0x" << std::hex << ls
+            << std::endl;
+
+  if (ls == ERROR_SUCCESS) {
+    return (0 != isRemoteDisabled);
+  }
+
+  HRESULT hr = HRESULT_FROM_WIN32(ls);
+  LOG_ERROR(hr);
+  return mozilla::Err(mozilla::WindowsError::FromHResult(hr));
+}
+
+// Query remote service endpoint to determine if WDBA is disabled.
+//
+// Handle errors, failing to the last state witnessed without error.
+bool IsAgentRemoteDisabled() {
+  // Fetch last witnessed state from registry.  If we can't get the last
+  // state, or there is no last state, assume we're not disabled.
+  bool lastRemoteDisabled =
+      RegistryGetValueBool(L"DefaultAgentLastRemoteDisabled")
+          .unwrapOr(mozilla::Some(false))
+          .valueOr(false);
+
+  std::cerr << "default-browser-agent: Last remote disabled: "
+            << lastRemoteDisabled << std::endl;
+
+  auto remoteDisabledResult = IsAgentRemoteDisabledInternal();
+  if (remoteDisabledResult.isErr()) {
+    // Fail to the last state witnessed without error.
+    return lastRemoteDisabled;
+  }
+
+  bool remoteDisabled = remoteDisabledResult.unwrap();
+
+  std::cerr << "default-browser-agent: Next remote disabled: " << remoteDisabled
+            << std::endl;
+
+  // Update last witnessed state in registry.
+  mozilla::Unused << RegistrySetValueBool(L"DefaultAgentLastRemoteDisabled",
+                                          remoteDisabled);
+
+  return remoteDisabled;
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/defaultagent/RemoteSettings.h
@@ -0,0 +1,14 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __DEFAULT_BROWSER_AGENT_REMOTE_SETTINGS_H__
+#define __DEFAULT_BROWSER_AGENT_REMOTE_SETTINGS_H__
+
+#include <windows.h>
+
+bool IsAgentRemoteDisabled();
+
+#endif  // __DEFAULT_BROWSER_AGENT_REMOTE_SETTINGS_H__
--- a/toolkit/mozapps/defaultagent/main.cpp
+++ b/toolkit/mozapps/defaultagent/main.cpp
@@ -8,16 +8,17 @@
 #include <shlwapi.h>
 #include <objbase.h>
 #include <string.h>
 
 #include "nsAutoRef.h"
 #include "nsWindowsHelpers.h"
 #include "mozilla/WinHeaderOnlyUtils.h"
 
+#include "RemoteSettings.h"
 #include "ScheduledTask.h"
 #include "Policy.h"
 #include "Telemetry.h"
 
 static void RemoveAllRegistryEntries() {
   mozilla::UniquePtr<wchar_t[]> installPath = mozilla::GetFullBinaryPath();
   if (!PathRemoveFileSpecW(installPath.get())) {
     return;
@@ -147,16 +148,24 @@ int wmain(int argc, wchar_t** argv) {
     }
     return RegisterTask(argv[2]);
   } else if (!wcscmp(argv[1], L"update-task")) {
     if (argc < 3 || !argv[2]) {
       return E_INVALIDARG;
     }
     return UpdateTask(argv[2]);
   } else if (!wcscmp(argv[1], L"do-task")) {
+    // Check for remote disable and (re-)enable.
+    if (IsAgentRemoteDisabled()) {
+      return S_OK;
+    }
     if (!IsTelemetryDisabled()) {
       return SendDefaultBrowserPing();
     }
     return S_OK;
+  } else if (!wcscmp(argv[1], L"debug-remote-disabled")) {
+    int disabled = IsAgentRemoteDisabled();
+    std::wcerr << "IsAgentRemoteDisabled: " << disabled << std::endl;
+    return S_OK;
   } else {
     return E_INVALIDARG;
   }
 }
--- a/toolkit/mozapps/defaultagent/moz.build
+++ b/toolkit/mozapps/defaultagent/moz.build
@@ -11,16 +11,17 @@ SPHINX_TREES['default-browser-agent'] = 
 DIRS += ['rust']
 
 UNIFIED_SOURCES += [
     "/mfbt/Poison.cpp",
     "EventLog.cpp",
     "main.cpp",
     "Policy.cpp",
     "Registry.cpp",
+    "RemoteSettings.cpp",
     "ScheduledTask.cpp",
     "Telemetry.cpp",
 ]
 
 USE_LIBS += [
     "defaultagent-static",
     "jsoncpp",
 ]