u2fd: Start WebAuthn handler on policy status change

This should have been part of http://crrev/c/2572025. Since we now
initialize WebAuthn handler only if policy is ready, there's a case
(typically OOBE) where the device policy takes time to load, and u2fd
decides not to initialize WebAuthn since device policy is not ready.
This causes WebAuthn to not work right after OOBE.

The U2fHid service actually has a callback registered with Session
Manager that retries starting service on device policy state change.
So the right thing to do is to also try starting WebAuthn in that
callback.

BUG=b:175228002
TEST=Unenroll and go through OOBE, WebAuthn works.
TEST=Enable U2F and try the U2F API registration/auth on
     https://securitykeys.info/qa.html

Change-Id: I6d733d40f33dc3ed32f508c1e44a7d37bba74c6e
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2583130
Tested-by: Yicheng Li <yichengli@chromium.org>
Reviewed-by: Andrey Pronin <apronin@chromium.org>
Commit-Queue: Yicheng Li <yichengli@chromium.org>
(cherry picked from commit 53b0c73c9f16cff4e23deb39bc4e09d01030d7e3)
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2590488
Reviewed-by: Yicheng Li <yichengli@chromium.org>
diff --git a/u2fd/u2f_daemon.cc b/u2fd/u2f_daemon.cc
index 93b0a44..ae298a8 100644
--- a/u2fd/u2f_daemon.cc
+++ b/u2fd/u2f_daemon.cc
@@ -159,19 +159,13 @@
       sm_proxy_.get(), legacy_kh_fallback_ ? kLegacyKhCounterMin : 0);
 
   sm_proxy_->RegisterPropertyChangeCompleteSignalHandler(
-      base::Bind(&U2fDaemon::TryStartU2fHidService, base::Unretained(this)),
+      base::Bind(&U2fDaemon::TryStartService, base::Unretained(this)),
       base::Bind(&OnPolicySignalConnected));
 
   bool policy_ready = U2fPolicyReady();
 
   if (policy_ready) {
-    int status = StartU2fHidService();
-
-    U2fMode u2f_mode = GetU2fMode(force_u2f_, force_g2f_);
-    if (u2f_mode != U2fMode::kU2f && u2f_mode != U2fMode::kU2fExtended) {
-      LOG(INFO) << "Initializing WebAuthn handler.";
-      InitializeWebAuthnHandler();
-    }
+    int status = StartService();
 
     // If U2F is not currently enabled, we'll wait for policy updates
     // that may enable it. We don't ever disable U2F on policy updates.
@@ -189,16 +183,37 @@
   return EX_OK;
 }
 
-void U2fDaemon::TryStartU2fHidService(
+void U2fDaemon::TryStartService(
     const std::string& /* unused dbus signal status */) {
-  if (!u2fhid_ && U2fPolicyReady()) {
-    int status = StartU2fHidService();
-    if (status != EX_OK && status != EX_CONFIG) {
-      exit(status);
-    }
+  // If there's u2fhid_ then we have already started service.
+  if (u2fhid_)
+    return;
+
+  if (!U2fPolicyReady())
+    return;
+
+  int status = StartService();
+
+  if (status != EX_OK && status != EX_CONFIG) {
+    // Something went wrong.
+    exit(status);
   }
 }
 
+int U2fDaemon::StartService() {
+  // Start U2fHid service before WebAuthn because WebAuthn initialization can
+  // be slow.
+  int status = StartU2fHidService();
+
+  U2fMode u2f_mode = GetU2fMode(force_u2f_, force_g2f_);
+  if (u2f_mode != U2fMode::kU2f && u2f_mode != U2fMode::kU2fExtended) {
+    LOG(INFO) << "Initializing WebAuthn handler.";
+    InitializeWebAuthnHandler();
+  }
+
+  return status;
+}
+
 int U2fDaemon::StartU2fHidService() {
   if (u2fhid_) {
     // Any failures in previous calls to this function would have caused the
diff --git a/u2fd/u2f_daemon.h b/u2fd/u2f_daemon.h
index 5d454c5..af1cb84 100644
--- a/u2fd/u2f_daemon.h
+++ b/u2fd/u2f_daemon.h
@@ -48,10 +48,12 @@
       brillo::dbus_utils::AsyncEventSequencer* sequencer) override;
 
  private:
-  // Checks if the device policy is available, and if so, starts the U2F
-  // service.
-  void TryStartU2fHidService(
-      const std::string& /* unused dbus signal status */);
+  // Callback for device policy status change. Checks if the device policy is
+  // available, and if so, starts the U2F service and the WebAuthn handler.
+  void TryStartService(const std::string& /* unused dbus signal status */);
+
+  // Starts the U2F service and the WebAuthn handler.
+  int StartService();
 
   // Starts the U2F service, and creates the virtual USB HID device. Calling
   // after the service is started is a no-op. Returns: