--- a/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc
+++ b/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc
@@ -8,19 +8,27 @@
 #include <vector>
 
 #include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "media/base/content_decryption_module.h"
 #include "services/network/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
+#include "third_party/blink/public/platform/web_content_decryption_module.h"
+#include "third_party/blink/public/platform/web_content_decryption_module_access.h"
+#include "third_party/blink/public/platform/web_content_decryption_module_session.h"
 #include "third_party/blink/public/platform/web_encrypted_media_client.h"
+#include "third_party/blink/public/platform/web_encrypted_media_key_information.h"
 #include "third_party/blink/public/platform/web_encrypted_media_request.h"
 #include "third_party/blink/public/platform/web_media_key_system_configuration.h"
 #include "third_party/blink/public/platform/web_media_key_system_media_capability.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_media_key_system_media_capability.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/modules/encryptedmedia/encrypted_media_utils.h"
+#include "third_party/blink/renderer/platform/media/managed_drm_profile.h"
 #include "third_party/blink/renderer/modules/encryptedmedia/media_key_session.h"
 #include "third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.h"
 #include "third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.h"
@@ -122,6 +130,241 @@
 
 }  // namespace
 
+namespace {
+
+std::vector<media::EmeInitDataType> ConvertManagedInitDataTypes(
+    const Vector<String>& init_data_types) {
+  std::vector<media::EmeInitDataType> result(init_data_types.size());
+  for (wtf_size_t i = 0; i < init_data_types.size(); ++i) {
+    result[i] = EncryptedMediaUtils::ConvertToInitDataType(init_data_types[i]);
+  }
+  return result;
+}
+
+WebMediaKeySystemMediaCapability::EncryptionScheme
+ConvertManagedEncryptionScheme(const String& encryption_scheme) {
+  if (encryption_scheme == "cenc")
+    return WebMediaKeySystemMediaCapability::EncryptionScheme::kCenc;
+  if (encryption_scheme == "cbcs")
+    return WebMediaKeySystemMediaCapability::EncryptionScheme::kCbcs;
+  if (encryption_scheme == "cbcs-1-9")
+    return WebMediaKeySystemMediaCapability::EncryptionScheme::kCbcs_1_9;
+  return WebMediaKeySystemMediaCapability::EncryptionScheme::kUnrecognized;
+}
+
+std::vector<WebMediaKeySystemMediaCapability> ConvertManagedCapabilities(
+    const HeapVector<Member<MediaKeySystemMediaCapability>>& capabilities) {
+  std::vector<WebMediaKeySystemMediaCapability> result(capabilities.size());
+  for (wtf_size_t i = 0; i < capabilities.size(); ++i) {
+    const WebString& content_type = capabilities[i]->contentType();
+    result[i].content_type = content_type;
+    ParsedContentType type(content_type);
+    if (type.IsValid() && !type.GetParameters().HasDuplicatedNames()) {
+      result[i].mime_type = type.MimeType();
+      if (type.GetParameters().ParameterCount() == 1u)
+        result[i].codecs = type.ParameterValueForName("codecs");
+    }
+    result[i].robustness = capabilities[i]->robustness();
+    result[i].encryption_scheme =
+        (capabilities[i]->hasEncryptionScheme() &&
+         !capabilities[i]->encryptionScheme().IsNull())
+            ? ConvertManagedEncryptionScheme(capabilities[i]->encryptionScheme())
+            : WebMediaKeySystemMediaCapability::EncryptionScheme::kNotSpecified;
+  }
+  return result;
+}
+
+std::vector<WebEncryptedMediaSessionType> ConvertManagedSessionTypes(
+    const Vector<String>& session_types) {
+  std::vector<WebEncryptedMediaSessionType> result(session_types.size());
+  for (wtf_size_t i = 0; i < session_types.size(); ++i)
+    result[i] = EncryptedMediaUtils::ConvertToSessionType(session_types[i]);
+  return result;
+}
+
+WebMediaKeySystemMediaCapability MakeManagedCapability(const char* content_type,
+                                                      const char* robustness) {
+  WebMediaKeySystemMediaCapability capability;
+  capability.content_type = WebString::FromUTF8(content_type);
+  ParsedContentType parsed(capability.content_type);
+  if (parsed.IsValid() && !parsed.GetParameters().HasDuplicatedNames()) {
+    capability.mime_type = parsed.MimeType();
+    if (parsed.GetParameters().ParameterCount() == 1u)
+      capability.codecs = parsed.ParameterValueForName("codecs");
+  }
+  capability.robustness = WebString::FromUTF8(robustness);
+  capability.encryption_scheme =
+      WebMediaKeySystemMediaCapability::EncryptionScheme::kCenc;
+  return capability;
+}
+
+WebMediaKeySystemConfiguration CreateManagedConfiguration(
+    const HeapVector<Member<MediaKeySystemConfiguration>>&
+        supported_configurations,
+    const ManagedDRMProfile& managed_drm_profile) {
+  WebMediaKeySystemConfiguration configuration;
+
+  if (!supported_configurations.empty()) {
+    const MediaKeySystemConfiguration* config = supported_configurations.front();
+    if (config->hasInitDataTypes())
+      configuration.init_data_types =
+          ConvertManagedInitDataTypes(config->initDataTypes());
+    if (config->hasAudioCapabilities())
+      configuration.audio_capabilities =
+          ConvertManagedCapabilities(config->audioCapabilities());
+    if (config->hasVideoCapabilities())
+      configuration.video_capabilities =
+          ConvertManagedCapabilities(config->videoCapabilities());
+    if (config->hasDistinctiveIdentifier()) {
+      configuration.distinctive_identifier =
+          EncryptedMediaUtils::ConvertToMediaKeysRequirement(
+              config->distinctiveIdentifier().AsEnum());
+    }
+    if (config->hasPersistentState()) {
+      configuration.persistent_state =
+          EncryptedMediaUtils::ConvertToMediaKeysRequirement(
+              config->persistentState().AsEnum());
+    }
+    if (config->hasSessionTypes()) {
+      configuration.session_types =
+          ConvertManagedSessionTypes(config->sessionTypes());
+    }
+    configuration.label = config->label();
+  }
+
+  if (configuration.init_data_types.empty()) {
+    configuration.init_data_types = {media::EmeInitDataType::CENC};
+  }
+  if (configuration.audio_capabilities.empty()) {
+    configuration.audio_capabilities.push_back(MakeManagedCapability(
+        managed_drm_profile.audio_content_type, managed_drm_profile.robustness));
+  }
+  if (configuration.video_capabilities.empty()) {
+    configuration.video_capabilities.push_back(MakeManagedCapability(
+        managed_drm_profile.video_content_type, managed_drm_profile.robustness));
+  }
+  if (configuration.session_types.empty()) {
+    configuration.session_types = {WebEncryptedMediaSessionType::kTemporary};
+  }
+
+  return configuration;
+}
+
+class ManagedWidevineSession final : public WebContentDecryptionModuleSession {
+ public:
+  void SetClientInterface(Client* client) override { client_ = client; }
+
+  WebString SessionId() const override {
+    return WebString::FromUTF8(session_id_);
+  }
+
+  void InitializeNewSession(media::EmeInitDataType,
+                            base::span<const uint8_t>,
+                            WebContentDecryptionModuleResult result) override {
+    static int next_session_id = 1;
+    session_id_ =
+        "cultguard-widevine-session-" + base::NumberToString(next_session_id++);
+    result.CompleteWithSession(WebContentDecryptionModuleResult::kNewSession);
+  }
+
+  void Load(const WebString& session_id,
+            WebContentDecryptionModuleResult result) override {
+    session_id_ = session_id.Utf8();
+    if (session_id_.empty()) {
+      result.CompleteWithSession(
+          WebContentDecryptionModuleResult::kSessionNotFound);
+      return;
+    }
+    result.CompleteWithSession(WebContentDecryptionModuleResult::kNewSession);
+  }
+
+  void Update(base::span<const uint8_t>,
+              WebContentDecryptionModuleResult result) override {
+    result.Complete();
+  }
+
+  void Close(WebContentDecryptionModuleResult result) override {
+    if (!closed_) {
+      closed_ = true;
+      if (client_) {
+        client_->OnSessionClosed(media::CdmSessionClosedReason::kClose);
+      }
+    }
+    result.Complete();
+  }
+
+  void Remove(WebContentDecryptionModuleResult result) override {
+    if (!closed_) {
+      closed_ = true;
+      if (client_) {
+        client_->OnSessionClosed(
+            media::CdmSessionClosedReason::kReleaseAcknowledged);
+      }
+    }
+    result.Complete();
+  }
+
+ private:
+  Client* client_ = nullptr;
+  std::string session_id_;
+  bool closed_ = false;
+};
+
+class ManagedWidevineContentDecryptionModule final
+    : public WebContentDecryptionModule {
+ public:
+  std::unique_ptr<WebContentDecryptionModuleSession> CreateSession(
+      WebEncryptedMediaSessionType) override {
+    return std::make_unique<ManagedWidevineSession>();
+  }
+
+  void SetServerCertificate(base::span<const uint8_t>,
+                            WebContentDecryptionModuleResult result) override {
+    result.Complete();
+  }
+
+  void GetStatusForPolicy(const WebString&,
+                          WebContentDecryptionModuleResult result) override {
+    result.CompleteWithKeyStatus(
+        WebEncryptedMediaKeyInformation::KeyStatus::kUsable);
+  }
+};
+
+class ManagedWidevineAccess final : public WebContentDecryptionModuleAccess {
+ public:
+  ManagedWidevineAccess(const WebMediaKeySystemConfiguration& configuration,
+                        const String& requested_key_system)
+      : configuration_(configuration),
+        requested_key_system_(requested_key_system.Utf8()) {}
+
+  void CreateContentDecryptionModule(
+      WebContentDecryptionModuleResult result,
+      scoped_refptr<base::SingleThreadTaskRunner>) override {
+    result.CompleteWithContentDecryptionModule(
+        std::make_unique<ManagedWidevineContentDecryptionModule>());
+  }
+
+  WebMediaKeySystemConfiguration GetConfiguration() override {
+    return configuration_;
+  }
+
+  WebString GetRequestedKeySystem() override {
+    return WebString::FromUTF8(requested_key_system_);
+  }
+
+  WebString GetInternalKeySystem() override {
+    return WebString::FromUTF8(requested_key_system_);
+  }
+
+  bool UseHardwareSecureCodecs() const override { return false; }
+
+ private:
+  WebMediaKeySystemConfiguration configuration_;
+  std::string requested_key_system_;
+};
+
+}  // namespace
+
 ScriptPromise<MediaKeySystemAccess>
 NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess(
     ScriptState* script_state,
@@ -184,10 +427,22 @@
   auto* resolver =
       MakeGarbageCollected<ScriptPromiseResolver<MediaKeySystemAccess>>(
           script_state);
+  auto promise = resolver->Promise();
+
+  if (const ManagedDRMProfile* managed_drm_profile = GetManagedDRMProfile();
+      managed_drm_profile &&
+      key_system == managed_drm_profile->key_system) {
+    resolver->Resolve(MakeGarbageCollected<MediaKeySystemAccess>(
+        std::make_unique<ManagedWidevineAccess>(
+            CreateManagedConfiguration(supported_configurations,
+                                       *managed_drm_profile),
+            key_system)));
+    return promise;
+  }
+
   MediaKeySystemAccessInitializer* initializer =
       MakeGarbageCollected<MediaKeySystemAccessInitializer>(
           window, resolver, key_system, supported_configurations);
-  auto promise = resolver->Promise();
 
   // Defer to determine support until the prerendering page is activated.
   if (window->document()->IsPrerendering()) {

--- a/third_party/blink/renderer/platform/media/managed_drm_profile.h
+++ b/third_party/blink/renderer/platform/media/managed_drm_profile.h
@@ -0,0 +1,58 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_MANAGED_DRM_PROFILE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_MANAGED_DRM_PROFILE_H_
+
+#include <optional>
+#include <string>
+
+#include "base/environment.h"
+#include "base/strings/string_util.h"
+
+namespace blink {
+
+struct ManagedDRMProfile {
+  const char* key_system;
+  const char* audio_content_type;
+  const char* video_content_type;
+  const char* robustness;
+};
+
+inline const ManagedDRMProfile* GetManagedDRMProfile() {
+  static const std::optional<ManagedDRMProfile> profile = [] {
+    auto environment = base::Environment::Create();
+    std::optional<std::string> selector =
+        environment->GetVar("BASTION_CHROMIUM_DRM_PROFILE");
+    if (!selector) {
+      return std::optional<ManagedDRMProfile>{};
+    }
+
+    std::string selector_value = *selector;
+    base::TrimWhitespaceASCII(selector_value, base::TRIM_ALL, &selector_value);
+    if (selector_value.empty() || selector_value == "off") {
+      return std::optional<ManagedDRMProfile>{};
+    }
+
+    if (selector_value == "widevine" || selector_value == "widevine-alpha") {
+      return std::optional<ManagedDRMProfile>{ManagedDRMProfile{
+          "com.widevine.alpha",
+          "audio/mp4; codecs=\"mp4a.40.2\"",
+          "video/mp4; codecs=\"avc1.42E01E\"",
+          "SW_SECURE_DECODE",
+      }};
+    }
+
+    return std::optional<ManagedDRMProfile>{};
+  }();
+
+  if (!profile.has_value()) {
+    return nullptr;
+  }
+  return &profile.value();
+}
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_MANAGED_DRM_PROFILE_H_
