Remove usage of legacy VideoCapture API on Ash

Instead of exposing video_capture::mojom::DeviceFactory, the VC Service
now exposes crosapi::mojom::VideoCaptureDeviceFactory.

crosapi service directly binds the device factory to what is exposed by
the Video Capture service instead of holding an adapter.

Bug: 1344751
Change-Id: Ic60814d8633c67ea14c1a80207dc4e7580cd10b0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4110806
Commit-Queue: Ilya Nikolaevskiy <ilnik@chromium.org>
Reviewed-by: Wei Lee <wtlee@chromium.org>
Reviewed-by: Camille Lamy <clamy@chromium.org>
Reviewed-by: Markus Handell <handellm@google.com>
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Reviewed-by: Erik Chen <erikchen@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1091824}
diff --git a/chrome/browser/ash/camera_presence_notifier_unittest.cc b/chrome/browser/ash/camera_presence_notifier_unittest.cc
index 12181dbc..ce7ccdde 100644
--- a/chrome/browser/ash/camera_presence_notifier_unittest.cc
+++ b/chrome/browser/ash/camera_presence_notifier_unittest.cc
@@ -56,8 +56,8 @@
       mojo::PendingReceiver<cros::mojom::CameraAppDeviceBridge> receiver)
       override {}
 
-  void ConnectToDeviceFactory(
-      mojo::PendingReceiver<video_capture::mojom::DeviceFactory> receiver)
+  void BindVideoCaptureDeviceFactory(
+      mojo::PendingReceiver<crosapi::mojom::VideoCaptureDeviceFactory> receiver)
       override {}
 
   void ConnectToVideoSourceProvider(
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn
index c398f70..3e64ee1 100644
--- a/chrome/browser/ash/crosapi/BUILD.gn
+++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -218,12 +218,6 @@
     "translate_proxy_config_to_crosapi.cc",
     "url_handler_ash.cc",
     "url_handler_ash.h",
-    "video_capture_device_ash.cc",
-    "video_capture_device_ash.h",
-    "video_capture_device_factory_ash.cc",
-    "video_capture_device_factory_ash.h",
-    "video_frame_handler_ash.cc",
-    "video_frame_handler_ash.h",
     "virtual_keyboard_ash.cc",
     "virtual_keyboard_ash.h",
     "volume_manager_ash.cc",
@@ -342,8 +336,6 @@
     "//remoting/host/chromeos:remoting_service",
     "//services/data_decoder/public/cpp:cpp",
     "//services/device/wake_lock/power_save_blocker",
-    "//services/video_capture/public/cpp:cpp",
-    "//services/video_capture/public/mojom",
     "//ui/base",
     "//ui/message_center",
     "//ui/message_center/public/cpp",
@@ -366,6 +358,7 @@
     ":browser_util",
     "//media/gpu:buildflags",
     "//printing",
+    "//services/video_capture:video_capture_ash",
   ]
 }
 
diff --git a/chrome/browser/ash/crosapi/DEPS b/chrome/browser/ash/crosapi/DEPS
index 7762da1..b7a068e 100644
--- a/chrome/browser/ash/crosapi/DEPS
+++ b/chrome/browser/ash/crosapi/DEPS
@@ -1,4 +1,7 @@
 specific_include_rules = {
+  "crosapi_ash\.cc": [
+    "+services/video_capture/ash",
+  ],
   "crosapi_ash\.h": [
     "+media/gpu/buildflags.h",
   ],
@@ -16,6 +19,9 @@
     # For remote support functionality.
     "+remoting/host/chromeos",
   ],
+  "screen_manager_ash\.cc": [
+    "+services/video_capture/ash",
+  ],
   "select_file_ash\.cc": [
     # For Chrome OS-specific file manager parameters.
     "+chrome/browser/ui/views/select_file_dialog_extension.h",
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.cc b/chrome/browser/ash/crosapi/crosapi_ash.cc
index a3ffcfc..2022169 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.cc
+++ b/chrome/browser/ash/crosapi/crosapi_ash.cc
@@ -91,7 +91,6 @@
 #include "chrome/browser/ash/crosapi/task_manager_ash.h"
 #include "chrome/browser/ash/crosapi/time_zone_service_ash.h"
 #include "chrome/browser/ash/crosapi/url_handler_ash.h"
-#include "chrome/browser/ash/crosapi/video_capture_device_factory_ash.h"
 #include "chrome/browser/ash/crosapi/virtual_keyboard_ash.h"
 #include "chrome/browser/ash/crosapi/volume_manager_ash.h"
 #include "chrome/browser/ash/crosapi/vpn_extension_observer_ash.h"
@@ -136,8 +135,11 @@
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/device_service.h"
 #include "content/public/browser/media_session_service.h"
+#include "content/public/browser/video_capture_service.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "printing/buildflags/buildflags.h"
+#include "services/video_capture/ash/video_capture_device_factory_ash.h"
+#include "services/video_capture/public/mojom/video_capture_service.mojom.h"
 
 #if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
 #include "content/public/browser/stable_video_decoder_factory.h"
@@ -261,8 +263,6 @@
       time_zone_service_ash_(std::make_unique<TimeZoneServiceAsh>()),
       tts_ash_(std::make_unique<TtsAsh>(g_browser_process->profile_manager())),
       url_handler_ash_(std::make_unique<UrlHandlerAsh>()),
-      video_capture_device_factory_ash_(
-          std::make_unique<VideoCaptureDeviceFactoryAsh>()),
       video_conference_manager_ash_(
           std::make_unique<ash::VideoConferenceManagerAsh>()),
       virtual_keyboard_ash_(std::make_unique<VirtualKeyboardAsh>()),
@@ -816,7 +816,8 @@
 
 void CrosapiAsh::BindVideoCaptureDeviceFactory(
     mojo::PendingReceiver<mojom::VideoCaptureDeviceFactory> receiver) {
-  video_capture_device_factory_ash_->BindReceiver(std::move(receiver));
+  content::GetVideoCaptureService().BindVideoCaptureDeviceFactory(
+      std::move(receiver));
 }
 
 void CrosapiAsh::BindVideoConferenceManager(
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.h b/chrome/browser/ash/crosapi/crosapi_ash.h
index 148b0b7..aca9f6f 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.h
+++ b/chrome/browser/ash/crosapi/crosapi_ash.h
@@ -111,7 +111,6 @@
 class WebAppServiceAsh;
 class WebPageInfoFactoryAsh;
 class UrlHandlerAsh;
-class VideoCaptureDeviceFactoryAsh;
 class VirtualKeyboardAsh;
 class VolumeManagerAsh;
 class VpnExtensionObserverAsh;
@@ -570,8 +569,6 @@
   std::unique_ptr<TimeZoneServiceAsh> time_zone_service_ash_;
   std::unique_ptr<TtsAsh> tts_ash_;
   std::unique_ptr<UrlHandlerAsh> url_handler_ash_;
-  std::unique_ptr<VideoCaptureDeviceFactoryAsh>
-      video_capture_device_factory_ash_;
   std::unique_ptr<ash::VideoConferenceManagerAsh> video_conference_manager_ash_;
   std::unique_ptr<VirtualKeyboardAsh> virtual_keyboard_ash_;
   std::unique_ptr<VolumeManagerAsh> volume_manager_ash_;
diff --git a/chrome/browser/ash/crosapi/screen_manager_ash.cc b/chrome/browser/ash/crosapi/screen_manager_ash.cc
index efdc6d4..19b80480 100644
--- a/chrome/browser/ash/crosapi/screen_manager_ash.cc
+++ b/chrome/browser/ash/crosapi/screen_manager_ash.cc
@@ -16,12 +16,12 @@
 #include "base/functional/bind.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
-#include "chrome/browser/ash/crosapi/video_capture_device_ash.h"
 #include "components/exo/shell_surface_util.h"
 #include "content/public/browser/desktop_capture.h"
 #include "content/public/browser/desktop_media_id.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "services/video_capture/ash/video_capture_device_ash.h"
 #include "ui/aura/window_observer.h"
 #include "ui/snapshot/snapshot.h"
 
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn
index 534dea32..a3c749c 100644
--- a/chromeos/crosapi/mojom/BUILD.gn
+++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -96,7 +96,6 @@
     "tts.mojom",
     "ui_constants.mojom",
     "url_handler.mojom",
-    "video_capture.mojom",
     "video_conference.mojom",
     "virtual_keyboard.mojom",
     "volume_manager.mojom",
@@ -111,6 +110,7 @@
   cpp_only = true
 
   public_deps = [
+    ":video_capture",
     "//chromeos/components/remote_apps/mojom",
     "//chromeos/components/sensors/mojom",
     "//chromeos/services/machine_learning/public/mojom",
@@ -118,8 +118,6 @@
     "//components/digital_goods/mojom:mojom",
     "//components/metrics/structured/mojom",
     "//components/tab_groups/public/mojom:mojo_bindings",
-    "//media/capture/mojom:image_capture",
-    "//media/capture/mojom:video_capture_types",
     "//media/mojo/mojom:speech_recognition",
     "//mojo/public/mojom/base",
     "//printing/backend/mojom",
@@ -305,6 +303,20 @@
   ]
 }
 
+# This needs a separate target, because this is also used
+# by the Video Capture Service in Ash and blink bindings
+# are needed.
+mojom("video_capture") {
+  sources = [ "video_capture.mojom" ]
+  public_deps = [
+    "//media/capture/mojom:image_capture",
+    "//media/capture/mojom:video_capture_types",
+    "//mojo/public/mojom/base",
+    "//ui/gfx/geometry/mojom",
+    "//ui/gfx/mojom",
+  ]
+}
+
 source_set("unit_tests") {
   testonly = true
   sources = [
diff --git a/services/video_capture/BUILD.gn b/services/video_capture/BUILD.gn
index 48c1156..89b2644d0 100644
--- a/services/video_capture/BUILD.gn
+++ b/services/video_capture/BUILD.gn
@@ -37,6 +37,7 @@
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
   public_deps = [
+    ":video_capture_ash",
     "//base",
     "//media",
     "//media/capture:capture",
@@ -79,6 +80,25 @@
   }
 }
 
+source_set("video_capture_ash") {
+  if (is_chromeos_ash) {
+    sources = [
+      "ash/video_capture_device_ash.cc",
+      "ash/video_capture_device_ash.h",
+      "ash/video_capture_device_factory_ash.cc",
+      "ash/video_capture_device_factory_ash.h",
+      "ash/video_frame_handler_ash.cc",
+      "ash/video_frame_handler_ash.h",
+    ]
+
+    public_deps = [
+      "//base",
+      "//services/video_capture/public/cpp:cpp",
+      "//services/video_capture/public/mojom",
+    ]
+  }
+}
+
 source_set("tests") {
   testonly = true
 
diff --git a/chrome/browser/ash/crosapi/video_capture_device_ash.cc b/services/video_capture/ash/video_capture_device_ash.cc
similarity index 94%
rename from chrome/browser/ash/crosapi/video_capture_device_ash.cc
rename to services/video_capture/ash/video_capture_device_ash.cc
index 98c5b5c..12de446 100644
--- a/chrome/browser/ash/crosapi/video_capture_device_ash.cc
+++ b/services/video_capture/ash/video_capture_device_ash.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/crosapi/video_capture_device_ash.h"
+#include "services/video_capture/ash/video_capture_device_ash.h"
 
 #include <memory>
 #include <utility>
 
-#include "chrome/browser/ash/crosapi/video_frame_handler_ash.h"
 #include "media/capture/mojom/image_capture.mojom.h"
+#include "services/video_capture/ash/video_frame_handler_ash.h"
 
 namespace crosapi {
 
diff --git a/chrome/browser/ash/crosapi/video_capture_device_ash.h b/services/video_capture/ash/video_capture_device_ash.h
similarity index 91%
rename from chrome/browser/ash/crosapi/video_capture_device_ash.h
rename to services/video_capture/ash/video_capture_device_ash.h
index 369097e..c05908d3 100644
--- a/chrome/browser/ash/crosapi/video_capture_device_ash.h
+++ b/services/video_capture/ash/video_capture_device_ash.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_CROSAPI_VIDEO_CAPTURE_DEVICE_ASH_H_
-#define CHROME_BROWSER_ASH_CROSAPI_VIDEO_CAPTURE_DEVICE_ASH_H_
+#ifndef SERVICES_VIDEO_CAPTURE_ASH_VIDEO_CAPTURE_DEVICE_ASH_H_
+#define SERVICES_VIDEO_CAPTURE_ASH_VIDEO_CAPTURE_DEVICE_ASH_H_
 
 #include "base/functional/callback_forward.h"
 #include "chromeos/crosapi/mojom/video_capture.mojom.h"
@@ -57,4 +57,4 @@
 
 }  // namespace crosapi
 
-#endif  // CHROME_BROWSER_ASH_CROSAPI_VIDEO_CAPTURE_DEVICE_ASH_H_
+#endif  // SERVICES_VIDEO_CAPTURE_ASH_VIDEO_CAPTURE_DEVICE_ASH_H_
diff --git a/chrome/browser/ash/crosapi/video_capture_device_factory_ash.cc b/services/video_capture/ash/video_capture_device_factory_ash.cc
similarity index 78%
rename from chrome/browser/ash/crosapi/video_capture_device_factory_ash.cc
rename to services/video_capture/ash/video_capture_device_factory_ash.cc
index 82d6bfe..14d84dc 100644
--- a/chrome/browser/ash/crosapi/video_capture_device_factory_ash.cc
+++ b/services/video_capture/ash/video_capture_device_factory_ash.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/crosapi/video_capture_device_factory_ash.h"
+#include "services/video_capture/ash/video_capture_device_factory_ash.h"
 
 #include <memory>
 #include <string>
@@ -10,24 +10,17 @@
 
 #include "base/functional/bind.h"
 #include "base/notreached.h"
-#include "chrome/browser/ash/crosapi/video_capture_device_ash.h"
-#include "content/public/browser/video_capture_service.h"
-#include "services/video_capture/public/mojom/video_capture_service.mojom.h"
+#include "services/video_capture/ash/video_capture_device_ash.h"
+#include "services/video_capture/device_factory.h"
 
 namespace crosapi {
 
-VideoCaptureDeviceFactoryAsh::VideoCaptureDeviceFactoryAsh() {
-  content::GetVideoCaptureService().ConnectToDeviceFactory(
-      device_factory_.BindNewPipeAndPassReceiver());
-}
+VideoCaptureDeviceFactoryAsh::VideoCaptureDeviceFactoryAsh(
+    raw_ptr<video_capture::DeviceFactory> device_factory)
+    : device_factory_(device_factory) {}
 
 VideoCaptureDeviceFactoryAsh::~VideoCaptureDeviceFactoryAsh() = default;
 
-void VideoCaptureDeviceFactoryAsh::BindReceiver(
-    mojo::PendingReceiver<crosapi::mojom::VideoCaptureDeviceFactory> receiver) {
-  receivers_.Add(this, std::move(receiver));
-}
-
 void VideoCaptureDeviceFactoryAsh::GetDeviceInfos(
     GetDeviceInfosCallback callback) {
   device_factory_->GetDeviceInfos(std::move(callback));
diff --git a/chrome/browser/ash/crosapi/video_capture_device_factory_ash.h b/services/video_capture/ash/video_capture_device_factory_ash.h
similarity index 77%
rename from chrome/browser/ash/crosapi/video_capture_device_factory_ash.h
rename to services/video_capture/ash/video_capture_device_factory_ash.h
index 127d2bb..87fe4cd 100644
--- a/chrome/browser/ash/crosapi/video_capture_device_factory_ash.h
+++ b/services/video_capture/ash/video_capture_device_factory_ash.h
@@ -2,41 +2,43 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_CROSAPI_VIDEO_CAPTURE_DEVICE_FACTORY_ASH_H_
-#define CHROME_BROWSER_ASH_CROSAPI_VIDEO_CAPTURE_DEVICE_FACTORY_ASH_H_
+#ifndef SERVICES_VIDEO_CAPTURE_ASH_VIDEO_CAPTURE_DEVICE_FACTORY_ASH_H_
+#define SERVICES_VIDEO_CAPTURE_ASH_VIDEO_CAPTURE_DEVICE_FACTORY_ASH_H_
 
 #include <string>
 
 #include "base/containers/flat_map.h"
+#include "base/memory/raw_ptr.h"
 #include "chromeos/crosapi/mojom/video_capture.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote.h"
-#include "services/video_capture/public/mojom/device_factory.mojom.h"
+
+namespace video_capture {
+class DeviceFactory;
+}  // namespace video_capture
 
 namespace crosapi {
 
 class VideoCaptureDeviceAsh;
 
 // This class is the ash-chrome implementation of the VideoCaptureDeviceFactory
-// interface. This class must only be used from the main thread.
+// interface.
 // It is used as a proxy between Lacros-Chrome and actual
 // video_capture::DeviceFactory in Ash-Chrome and also responsible for
 // translating structures between crosapi and other components.
 // (e.g. gfx, media, video_capture)
+// It must be destroyed before the passed video_capture::DeviceFactory.
 class VideoCaptureDeviceFactoryAsh
     : public crosapi::mojom::VideoCaptureDeviceFactory {
  public:
-  VideoCaptureDeviceFactoryAsh();
+  explicit VideoCaptureDeviceFactoryAsh(
+      raw_ptr<video_capture::DeviceFactory> device_factory);
   VideoCaptureDeviceFactoryAsh(const VideoCaptureDeviceFactoryAsh&) = delete;
   VideoCaptureDeviceFactoryAsh& operator=(const VideoCaptureDeviceFactoryAsh&) =
       delete;
   ~VideoCaptureDeviceFactoryAsh() override;
 
-  void BindReceiver(
-      mojo::PendingReceiver<crosapi::mojom::VideoCaptureDeviceFactory>
-          receiver);
-
   // crosapi::mojom::VideoCaptureDeviceFactory:
   void GetDeviceInfos(GetDeviceInfosCallback callback) override;
   void CreateDevice(
@@ -49,7 +51,7 @@
   // video_capture::mojom::Device in Lacros-Chrome is dropped.
   void OnClientConnectionErrorOrClose(const std::string& device_id);
 
-  mojo::Remote<video_capture::mojom::DeviceFactory> device_factory_;
+  raw_ptr<video_capture::DeviceFactory> device_factory_;
 
   // The key is the device id used in blink::MediaStreamDevice.
   base::flat_map<std::string, std::unique_ptr<VideoCaptureDeviceAsh>> devices_;
@@ -59,4 +61,4 @@
 
 }  // namespace crosapi
 
-#endif  // CHROME_BROWSER_ASH_CROSAPI_VIDEO_CAPTURE_DEVICE_FACTORY_ASH_H_
+#endif  // SERVICES_VIDEO_CAPTURE_ASH_VIDEO_CAPTURE_DEVICE_FACTORY_ASH_H_
diff --git a/chrome/browser/ash/crosapi/video_frame_handler_ash.cc b/services/video_capture/ash/video_frame_handler_ash.cc
similarity index 97%
rename from chrome/browser/ash/crosapi/video_frame_handler_ash.cc
rename to services/video_capture/ash/video_frame_handler_ash.cc
index 1102423..ebbe30d 100644
--- a/chrome/browser/ash/crosapi/video_frame_handler_ash.cc
+++ b/services/video_capture/ash/video_frame_handler_ash.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/crosapi/video_frame_handler_ash.h"
+#include "services/video_capture/ash/video_frame_handler_ash.h"
 
 #include <memory>
 #include <string>
@@ -62,8 +62,9 @@
     }
     crosapi_buffer_info->rotation = crosapi_rotation;
   }
-  if (buffer_info->metadata.reference_time.has_value())
+  if (buffer_info->metadata.reference_time.has_value()) {
     crosapi_buffer_info->reference_time = *buffer_info->metadata.reference_time;
+  }
 
   crosapi_buffer->frame_info = std::move(crosapi_buffer_info);
   return crosapi_buffer;
diff --git a/chrome/browser/ash/crosapi/video_frame_handler_ash.h b/services/video_capture/ash/video_frame_handler_ash.h
similarity index 94%
rename from chrome/browser/ash/crosapi/video_frame_handler_ash.h
rename to services/video_capture/ash/video_frame_handler_ash.h
index da19696..2f6edf6 100644
--- a/chrome/browser/ash/crosapi/video_frame_handler_ash.h
+++ b/services/video_capture/ash/video_frame_handler_ash.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_CROSAPI_VIDEO_FRAME_HANDLER_ASH_H_
-#define CHROME_BROWSER_ASH_CROSAPI_VIDEO_FRAME_HANDLER_ASH_H_
+#ifndef SERVICES_VIDEO_CAPTURE_ASH_VIDEO_FRAME_HANDLER_ASH_H_
+#define SERVICES_VIDEO_CAPTURE_ASH_VIDEO_FRAME_HANDLER_ASH_H_
 
 #include <vector>
 
@@ -87,4 +87,4 @@
 
 }  // namespace crosapi
 
-#endif  // CHROME_BROWSER_ASH_CROSAPI_VIDEO_FRAME_HANDLER_ASH_H_
+#endif  // SERVICES_VIDEO_CAPTURE_ASH_VIDEO_FRAME_HANDLER_ASH_H_
diff --git a/services/video_capture/public/cpp/mock_video_capture_service.cc b/services/video_capture/public/cpp/mock_video_capture_service.cc
index 734ec74..3373e95 100644
--- a/services/video_capture/public/cpp/mock_video_capture_service.cc
+++ b/services/video_capture/public/cpp/mock_video_capture_service.cc
@@ -25,9 +25,9 @@
   DoInjectGpuDependencies(std::move(accelerator_factory));
 }
 
-void MockVideoCaptureService::ConnectToDeviceFactory(
-    mojo::PendingReceiver<video_capture::mojom::DeviceFactory> receiver) {
-  DoConnectToDeviceFactory(std::move(receiver));
+void MockVideoCaptureService::BindVideoCaptureDeviceFactory(
+    mojo::PendingReceiver<crosapi::mojom::VideoCaptureDeviceFactory> receiver) {
+  DoBindVideoCaptureDeviceFactory(std::move(receiver));
 }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
diff --git a/services/video_capture/public/cpp/mock_video_capture_service.h b/services/video_capture/public/cpp/mock_video_capture_service.h
index fbbd0b9..6bdab44f 100644
--- a/services/video_capture/public/cpp/mock_video_capture_service.h
+++ b/services/video_capture/public/cpp/mock_video_capture_service.h
@@ -28,8 +28,8 @@
       mojo::PendingRemote<video_capture::mojom::AcceleratorFactory>
           accelerator_factory) override;
 
-  void ConnectToDeviceFactory(
-      mojo::PendingReceiver<video_capture::mojom::DeviceFactory> receiver)
+  void BindVideoCaptureDeviceFactory(
+      mojo::PendingReceiver<crosapi::mojom::VideoCaptureDeviceFactory> receiver)
       override;
 
   MOCK_METHOD1(
@@ -37,9 +37,9 @@
       void(mojo::PendingRemote<video_capture::mojom::AcceleratorFactory>
                accelerator_factory));
 
-  MOCK_METHOD1(DoConnectToDeviceFactory,
-               void(mojo::PendingReceiver<video_capture::mojom::DeviceFactory>
-                        receiver));
+  MOCK_METHOD1(DoBindVideoCaptureDeviceFactory,
+               void(mojo::PendingReceiver<
+                    crosapi::mojom::VideoCaptureDeviceFactory> receiver));
 
   void ConnectToCameraAppDeviceBridge(
       mojo::PendingReceiver<cros::mojom::CameraAppDeviceBridge>) override {}
diff --git a/services/video_capture/public/mojom/BUILD.gn b/services/video_capture/public/mojom/BUILD.gn
index fbcc823..563e9ec 100644
--- a/services/video_capture/public/mojom/BUILD.gn
+++ b/services/video_capture/public/mojom/BUILD.gn
@@ -31,6 +31,7 @@
 
   if (is_chromeos_ash) {
     deps += [
+      "//chromeos/crosapi/mojom:video_capture",
       "//components/chromeos_camera/common",
       "//media/capture/video/chromeos/mojom:cros_camera",
     ]
diff --git a/services/video_capture/public/mojom/video_capture_service.mojom b/services/video_capture/public/mojom/video_capture_service.mojom
index e6fb6bb..79e482b 100644
--- a/services/video_capture/public/mojom/video_capture_service.mojom
+++ b/services/video_capture/public/mojom/video_capture_service.mojom
@@ -13,6 +13,8 @@
 import "components/chromeos_camera/common/mjpeg_decode_accelerator.mojom";
 [EnableIf=is_chromeos_ash]
 import "media/capture/video/chromeos/mojom/camera_app.mojom";
+[EnableIf=is_chromeos_ash]
+import "chromeos/crosapi/mojom/video_capture.mojom";
 
 [EnableIf=is_win]
 import "gpu/ipc/common/luid.mojom";
@@ -52,9 +54,11 @@
   ConnectToCameraAppDeviceBridge(
       pending_receiver<cros.mojom.CameraAppDeviceBridge> receiver);
 
-  // Legacy API. Supports one client per device.
+  // Interface to expose the internal DeviceFactory to be passed from ash
+  // to lacros.
   [EnableIf=is_chromeos_ash]
-  ConnectToDeviceFactory(pending_receiver<DeviceFactory> receiver);
+  BindVideoCaptureDeviceFactory(
+      pending_receiver<crosapi.mojom.VideoCaptureDeviceFactory> receiver);
 
   // Current API. Supports multiple clients per source.
   ConnectToVideoSourceProvider(pending_receiver<VideoSourceProvider> receiver);
diff --git a/services/video_capture/video_capture_service_impl.cc b/services/video_capture/video_capture_service_impl.cc
index bcea0e5..779a21b 100644
--- a/services/video_capture/video_capture_service_impl.cc
+++ b/services/video_capture/video_capture_service_impl.cc
@@ -112,7 +112,8 @@
 
 VideoCaptureServiceImpl::~VideoCaptureServiceImpl() {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  factory_receivers_.Clear();
+  factory_receivers_ash_.Clear();
+  device_factory_ash_adapter_.reset();
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   device_factory_.reset();
 
@@ -139,10 +140,11 @@
       std::move(receiver));
 }
 
-void VideoCaptureServiceImpl::ConnectToDeviceFactory(
-    mojo::PendingReceiver<mojom::DeviceFactory> receiver) {
+void VideoCaptureServiceImpl::BindVideoCaptureDeviceFactory(
+    mojo::PendingReceiver<crosapi::mojom::VideoCaptureDeviceFactory> receiver) {
   LazyInitializeDeviceFactory();
-  factory_receivers_.Add(device_factory_.get(), std::move(receiver));
+  factory_receivers_ash_.Add(device_factory_ash_adapter_.get(),
+                             std::move(receiver));
 }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
@@ -193,6 +195,9 @@
               &GpuDependenciesContext::CreateJpegDecodeAccelerator,
               gpu_dependencies_context_->GetWeakPtr()),
           gpu_dependencies_context_->GetTaskRunner()));
+  device_factory_ash_adapter_ =
+      std::make_unique<crosapi::VideoCaptureDeviceFactoryAsh>(
+          device_factory_.get());
 #elif BUILDFLAG(IS_CHROMEOS_LACROS)
   // LacrosService might be null in unit tests.
   auto* lacros_service = chromeos::LacrosService::Get();
diff --git a/services/video_capture/video_capture_service_impl.h b/services/video_capture/video_capture_service_impl.h
index 2af926db..bfeaa24 100644
--- a/services/video_capture/video_capture_service_impl.h
+++ b/services/video_capture/video_capture_service_impl.h
@@ -20,7 +20,9 @@
 #include "services/video_capture/public/mojom/video_capture_service.mojom.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "chromeos/crosapi/mojom/video_capture.mojom.h"
 #include "media/capture/video/chromeos/mojom/camera_app.mojom.h"
+#include "services/video_capture/ash/video_capture_device_factory_ash.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace video_capture {
@@ -46,8 +48,9 @@
   void ConnectToCameraAppDeviceBridge(
       mojo::PendingReceiver<cros::mojom::CameraAppDeviceBridge> receiver)
       override;
-  void ConnectToDeviceFactory(
-      mojo::PendingReceiver<mojom::DeviceFactory> receiver) override;
+  void BindVideoCaptureDeviceFactory(
+      mojo::PendingReceiver<crosapi::mojom::VideoCaptureDeviceFactory> receiver)
+      override;
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   void ConnectToVideoSourceProvider(
       mojo::PendingReceiver<mojom::VideoSourceProvider> receiver) override;
@@ -65,15 +68,20 @@
   void LazyInitializeVideoSourceProvider();
   void OnLastSourceProviderClientDisconnected();
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  mojo::ReceiverSet<mojom::DeviceFactory> factory_receivers_;
-#endif
-
   mojo::Receiver<mojom::VideoCaptureService> receiver_;
   std::unique_ptr<VirtualDeviceEnabledDeviceFactory> device_factory_;
   std::unique_ptr<VideoSourceProviderImpl> video_source_provider_;
   std::unique_ptr<GpuDependenciesContext> gpu_dependencies_context_;
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // Must be destroyed before |device_factory_|.
+  std::unique_ptr<crosapi::VideoCaptureDeviceFactoryAsh>
+      device_factory_ash_adapter_;
+  // Must be destroyed before |device_factory_ash_adapter_|.
+  mojo::ReceiverSet<crosapi::mojom::VideoCaptureDeviceFactory>
+      factory_receivers_ash_;
+#endif
+
   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
 };