Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alloy: Add component updater support for Widevine #3149

Closed
magreenblatt opened this issue Jun 17, 2021 · 14 comments
Closed

alloy: Add component updater support for Widevine #3149

magreenblatt opened this issue Jun 17, 2021 · 14 comments
Labels
alloy Related to the Alloy runtime enhancement Enhancement request Framework Related to framework code or APIs

Comments

@magreenblatt
Copy link
Collaborator

Original report by me.


Applications using the Alloy runtime must currently download Widevine binaries from a Google CDN and register them using the CefRegisterWidevineCdm function as documented here. Chrome, on the other hand, uses the component updater to update the binaries at runtime when necessary.

Manual download and registration of Widevine with the Alloy runtime has proven problematic for the following reasons:

  1. CEF code must be kept in sync with Chrome code, which is an error-prone process (see issue widevine: Breaking manifest change (VP9 version string) with v4.10.2209.0 #3138 as a recent example).
  2. Communications from the Widevine team must be carefully monitored to know what CDM version to download for a particular platform and Chromium version combination.
  3. Failure by the client to download and register the correct CDM version will cause playback errors.
  4. The Chrome runtime currently uses the component updater (same code as Chrome), and we don’t want to require separate approaches for the Chrome and Alloy runtimes.

The original Widevine implementation in CEF used the component updater (see issue #1631). That implementation was subsequently replaced by the CefRegisterWidevineCdm approach currently in use (see issue #2009). The stated reasons for dropping component updater support at that time (mid-2016) were:

  1. There may be a delay of arbitrary length before the CDM binaries are downloaded;
  2. The remote service controls the specific CDM version that is downloaded;
  3. The downloaded CDM version may not work with the Chromium version in use by the client application -- the newest available CDM version is always downloaded and Google only tests that CDM version with the current Google Chrome stable version.

Recent communications with Google (mid-2021) provide the following responses:

  • Re # 1: “The CDM is normally bundled with a new Chrome installation process. On upgrade, the CDM component will auto-download after X time, I believe the default is either 600s or 900s. If the user attempts DRM playback before the CDM exists, there will be a delay until the CDM retrieval is dynamically executed and completed.”
  • Re # 2: “We have cleaned up the CDM rollout process to be more stable. The CDM rollout process/schedule looks like this:
    [T0] Available on Chrome beta channel for upcoming Chrome release
    [T1] Available on Chrome stable channel (and Component Updater) for current Chrome release (this means CDM is available on latest Chrome, not previous Chrome releases yet)
    [T1 + 2 weeks] CDM is available via Component Updater for all compatible Chrome releases (right now, it's M68 or later)
    [T1 + 2 weeks] Direct HTTP download links are updated and current.txt is updated with latest CDM version”
  • Re # 3: “Minimal testing is conducted on previous versions of Chrome - usually 1-2 versions back but this is not always guaranteed. We expect the CDM to work as long as the CDM interface is unchanged (currently at 10), which goes back as far as M68.”

Based on the above, we have decided to restore component updater usage with the Alloy runtime. The existing CefRegisterWidevineCdm approach will be removed.

@magreenblatt
Copy link
Collaborator Author

This work is currently scheduled for M93 which will reach stable at the end of August 2021.

@magreenblatt
Copy link
Collaborator Author

Note that Google currently bundles Widevine binaries with the Chrome installer. It is expected that Widevine will load from disk if you create the correct directory structure before initializing CEF (e.g. you might still choose to download Widevine using client code, and have it available after the next client restart). However, going forward, update of the CDM during runtime will only be supported via the Component Updater.

@magreenblatt
Copy link
Collaborator Author

The quick test for Widevine support is to visit https://shaka-player-demo.appspot.com/support.html and notice that "com.widevine.alpha" is non-null under "drm". The CDM files will be downloaded under CefSettings.user_data_path (e.g. default of “C:\Users\[User]\AppData\Local\CEF\User Data\WidevineCdm” on Windows, “/Application Support/CEF/User Data/WidevineCdm“ on MacOS and "/.config/cef_user_data/WidevineCdm" on Linux).

The longer test is to play a video with the Widevine DRM (WV) symbol at https://shaka-player-demo.appspot.com/demo/. Note that proprietary codecs like MP4 are not supported by default CEF builds. This video is a good test example.

You can also try executing a JavaScript snippet from the DevTools console, like:

await navigator.requestMediaKeySystemAccess('com.widevine.alpha', [{
  sessionTypes: ['temporary'],
  videoCapabilities: [{
    contentType: 'video/webm; codecs="vp09.00.10.08"',
    robustness: 'SW_SECURE_DECODE'
  }]
}])

The component updater can be disabled by passing the --disable-component-update command-line flag, in which case Widevine will not be downloaded or initialized.

Faster execution of the component updater after application start can be triggered by passing the --component-updater=fast-update command-line flag. Other supported values for that flag are listed here.

Windows and MacOS support loading of the Widevine CDM after component updater download without first requiring a client restart. A restart is required on Linux because the CDM must be loaded into the zygote at startup (see description here).

@magreenblatt
Copy link
Collaborator Author

Important breakpoints (in order) for debugging Widevine component updater behavior:

Breakpoints for debugging CDM behavior from the renderer:

  • IsKeySystemSupported (renderer) calls CdmRegistryImpl::GetCdmInfo (browser) to retrieve the info that was populated by RegisterWidevineCdmWithChrome.

    ChromeKeySystemsProvider is responsible in the renderer process for refreshing the key system status after Widevine is installed as a component update.

  • Example IsKeySystemSupported call stack in the renderer triggered by a call to navigator.requestMediaKeySystemAccess from JavaScript code:

    ```

    content.dll!content::IsKeySystemSupported(const std::__1::basic_string<char,std::__1::char_traits,std::__1::allocator> & key_system, mojo::StructPtrmedia::mojom::KeySystemCapability * key_system_capability) Line 26 C++ libcef.dll!anonymous namespace'::AddWidevine(std::__1::vector<std::__1::unique_ptr<media::KeySystemProperties,std::__1::default_delete<media::KeySystemProperties>>,std::__1::allocator<std::__1::unique_ptr<media::KeySystemProperties,std::__1::default_delete<media::KeySystemProperties>>>> * concrete_key_systems) Line 314 C++ libcef.dll!AddChromeKeySystems(std::__1::vector<std::__1::unique_ptr<media::KeySystemProperties,std::__1::default_delete<media::KeySystemProperties>>,std::__1::allocator<std::__1::unique_ptr<media::KeySystemProperties,std::__1::default_delete<media::KeySystemProperties>>>> * key_systems_properties) Line 410 C++ libcef.dll!AlloyContentRendererClient::AddSupportedKeySystems(std::__1::vector<std::__1::unique_ptr<media::KeySystemProperties,std::__1::default_delete<media::KeySystemProperties>>,std::__1::allocator<std::__1::unique_ptr<media::KeySystemProperties,std::__1::default_delete<media::KeySystemProperties>>>> * key_systems) Line 416 C++ content.dll!content::RenderMediaClient::AddSupportedKeySystems(std::__1::vector<std::__1::unique_ptr<media::KeySystemProperties,std::__1::default_delete<media::KeySystemProperties>>,std::__1::allocator<std::__1::unique_ptr<media::KeySystemProperties,std::__1::default_delete<media::KeySystemProperties>>>> * key_systems) Line 31 C++ media.dll!media::KeySystemsImpl::UpdateSupportedKeySystems() Line 423 C++ media.dll!media::KeySystemsImpl::KeySystemsImpl() Line 351 C++ media.dll!base::NoDestructor<media::KeySystemsImpl,nullptr_t>::NoDestructor<>() Line 71 C++ media.dll!media::KeySystemsImpl::GetInstance() Line 334 C++ media.dll!media::KeySystems::GetInstance() Line 766 C++ blink_platform_media.dll!blink::WebEncryptedMediaClientImpl::WebEncryptedMediaClientImpl(media::CdmFactory * cdm_factory, media::MediaPermission * media_permission, std::__1::unique_ptr<blink::KeySystemConfigSelector::WebLocalFrameDelegate,std::__1::default_delete<blink::KeySystemConfigSelector::WebLocalFrameDelegate>> web_frame_delegate) Line 105 C++ content.dll!std::__1::make_unique<blink::WebEncryptedMediaClientImpl,media::CdmFactory *,media::MediaPermission *,std::unique_ptr<blink::KeySystemConfigSelector::WebLocalFrameDelegate>>(media::CdmFactory * && __args, media::MediaPermission * && __args, std::__1::unique_ptr<blink::KeySystemConfigSelector::WebLocalFrameDelegate,std::__1::default_delete<blink::KeySystemConfigSelector::WebLocalFrameDelegate>> && __args) Line 725 C++ content.dll!content::MediaFactory::EncryptedMediaClient() Line 585 C++ content.dll!content::RenderFrameImpl::EncryptedMediaClient() Line 4445 C++ blink_modules.dll!blink::MediaKeysController::EncryptedMediaClient(blink::ExecutionContext * context) Line 23 C++ blink_modules.dll!blink::NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess(blink::ScriptState * script_state, blink::Navigator & navigator, const WTF::String & key_system, const blink::HeapVector<blink::Member<blink::MediaKeySystemConfiguration>,0> & supported_configurations, blink::ExceptionState & exception_state) Line 196 C++ blink_modules.dll!blink::anonymous namespace'::v8_navigator::RequestMediaKeySystemAccessOperationCallback(const v8::FunctionCallbackInfov8::Value & info) Line 1763 C++ v8.dll!v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo handler) Line 155 C++```

@magreenblatt
Copy link
Collaborator Author

widevine: Use component updater with the Alloy runtime (fixes issue #3149)

Widevine CDM binaries will be downloaded on supported platforms shortly after
application startup. Widevine support will then become available within a few
seconds after successful installation on Windows or after the next application
restart on other platforms. The CDM files will be downloaded to a "WidevineCdm"
directory inside the CefSettings.user_data_path directory.

Pass the --disable-component-update command-line flag to disable Widevine
download and installation. Pass the --component-updater=fast-update command-
line flag to force Widevine download immediately after application startup.

See the related issue for additional usage details.

→ <<cset 240b869db5cc (bb)>>

@magreenblatt
Copy link
Collaborator Author

  • changed state from "new" to "resolved"

@magreenblatt
Copy link
Collaborator Author

widevine: Use component updater with the Alloy runtime (fixes issue #3149)

Widevine CDM binaries will be downloaded on supported platforms shortly after
application startup. Widevine support will then become available within a few
seconds after successful installation on Windows or after the next application
restart on other platforms. The CDM files will be downloaded to a "WidevineCdm"
directory inside the CefSettings.user_data_path directory.

Pass the --disable-component-update command-line flag to disable Widevine
download and installation. Pass the --component-updater=fast-update command-
line flag to force Widevine download immediately after application startup.

See the related issue for additional usage details.

→ <<cset 5a0b3ea93778 (bb)>>

@magreenblatt
Copy link
Collaborator Author

widevine: Fix ARM compile error due to unused variable (see issue #3149)

alloy_browser_main.cc:223:17: error: unused variable 'cus' [-Werror,-Wunused-variable]
auto* const cus = g_browser_process->component_updater();

→ <<cset 17d2d13030cb (bb)>>

@magreenblatt
Copy link
Collaborator Author

widevine: Fix ARM compile error due to unused variable (see issue #3149)

alloy_browser_main.cc:223:17: error: unused variable 'cus' [-Werror,-Wunused-variable]
auto* const cus = g_browser_process->component_updater();

→ <<cset 6a52098b6251 (bb)>>

@magreenblatt
Copy link
Collaborator Author

Linux: Update user data path docs (see issue #3149)

→ <<cset f435c3af9efe (bb)>>

@magreenblatt
Copy link
Collaborator Author

Linux: Update user data path docs (see issue #3149)

→ <<cset b4cf6e54ded0 (bb)>>

@magreenblatt
Copy link
Collaborator Author

alloy: Fix ComponentUpdateService shutdown crash with multi-threaded message loop (see issue #3149)

→ <<cset 0d1bea3a789e (bb)>>

@magreenblatt
Copy link
Collaborator Author

alloy: Fix ComponentUpdateService shutdown crash with multi-threaded message loop (see issue #3149)

→ <<cset c4d96f07faf1 (bb)>>

@magreenblatt
Copy link
Collaborator Author

alloy: Fix ComponentUpdateService shutdown crash with multi-threaded message loop (see issue #3149)

→ <<cset 4dd314dec308 (bb)>>

robincarlisle pushed a commit to robincarlisle/cef that referenced this issue Apr 28, 2023
…hromiumembedded#3149)

Widevine CDM binaries will be downloaded on supported platforms shortly after
application startup. Widevine support will then become available within a few
seconds after successful installation on Windows or after the next application
restart on other platforms. The CDM files will be downloaded to a "WidevineCdm"
directory inside the `CefSettings.user_data_path` directory.

Pass the `--disable-component-update` command-line flag to disable Widevine
download and installation. Pass the `--component-updater=fast-update` command-
line flag to force Widevine download immediately after application startup.

See the related issue for additional usage details.
robincarlisle pushed a commit to robincarlisle/cef that referenced this issue Apr 28, 2023
…omiumembedded#3149)

alloy_browser_main.cc:223:17: error: unused variable 'cus' [-Werror,-Wunused-variable]
    auto* const cus = g_browser_process->component_updater();
robincarlisle pushed a commit to robincarlisle/cef that referenced this issue Apr 28, 2023
filipnavara pushed a commit to emclient/cef that referenced this issue Dec 26, 2023
…hromiumembedded#3149)

Widevine CDM binaries will be downloaded on supported platforms shortly after
application startup. Widevine support will then become available within a few
seconds after successful installation on Windows or after the next application
restart on other platforms. The CDM files will be downloaded to a "WidevineCdm"
directory inside the `CefSettings.user_data_path` directory.

Pass the `--disable-component-update` command-line flag to disable Widevine
download and installation. Pass the `--component-updater=fast-update` command-
line flag to force Widevine download immediately after application startup.

See the related issue for additional usage details.
filipnavara pushed a commit to emclient/cef that referenced this issue Dec 26, 2023
…omiumembedded#3149)

alloy_browser_main.cc:223:17: error: unused variable 'cus' [-Werror,-Wunused-variable]
    auto* const cus = g_browser_process->component_updater();
filipnavara pushed a commit to emclient/cef that referenced this issue Dec 26, 2023
filipnavara pushed a commit to emclient/cef that referenced this issue Dec 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
alloy Related to the Alloy runtime enhancement Enhancement request Framework Related to framework code or APIs
Projects
None yet
Development

No branches or pull requests

1 participant