-
Notifications
You must be signed in to change notification settings - Fork 471
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
Shared installation support #3836
Comments
@magreenblatt Good news |
These are the proposed rules for CEF API design after Phase 2: Enums:
Structs:
Member methods:
Static methods & functions:
API versioning:
|
The API version number should be incremental (to work with logical operators) and might be based on the CEF version where it was first introduced. For example,
The CEF version number currently changes when the CEF C/C++ API changes, so this format would be easy to inspect ("Ah, the We can support this with a new tool that works as follows:
The CEF translator tool does not currently support #defines in CEF C++ headers. Since we'll need to add support for version #defines we might also add support for platform defines (OS_WIN, etc) at the same time. A few other related points:
|
Here are some concrete examples of API versioning. Original version
Method parameter changed in version 13201
Method parameter changed again in version 13301
Support removed for versions < 13201
|
I feel bit weird about examples above with ifdef magic: it should use at least ifelse or use opinionated define to hide deprecated methods (which you keep forever). But at same time - if this object sourced from CEF - i did not see any reason to be virtual at client side. Generally same rule for library side - there is no place for virtual method(s), because all such things dispatched at C ABI level. |
Thanks for the feedback. The above examples are intentionally verbose to make understanding easier. The #define usage in the C++ API can be whatever works best/clearest and is compiler supported. The #define usage in the C API can be whatever the translator tool can deduct/generate based on required member order. We will likely pass C API header files to |
As for platform specific calls: i'm like idea when if platform did not support method - it simply did not exist in headers/metadata (so it very hard to call invalid method). But from ABI perspective i like idea to keep their method slots reserved. This allows to keep ABI definitions universal, and CEF have not so many such stuff (however it definitely exist). Also if old method completely removed (not just deprecated and emulated) or call for method for unsupported platform is made - you should act, probably fail fast / crash. Some API in past has been completely removed, not really that happens really often, but can. Pinning to at least major version i guess is a must-have feature, because underlying chromium behavior changes over time, and things might easily become broken. It depends on cef features in-use or web-features in-use, but i expect at least about week lag before well maintained clients got real updates to major version change. Until this it is safer to use existing milestone engine, instead of break other apps in miriad ways. |
Agreed, for complex applications. Applications that are web-first (e.g. just a website in a container) might be fine with looser pinning since they need to keep working with older/newer Google Chrome versions in any case. In the future we might also define "API tiers" where we try to be more explicit about behavioral compatibility ranges and not just API compatibility ranges. |
CEF currently supports inheritance in the C API using nested structures like:
Each structure type has its own list of function pointers (see Proposal To facilitate multiple version usage in the library-side of the translation layer we might want to generate flat representations of each "object" struct at each supported version. Continuing the above example we would auto-generate structs like following:
And auto-generate helpers like the following to utilize the version-specific structs:
This would likely be the easiest way to guarantee that libcef and the client are using the same memory layout (and the same The library-side works with C structs in 2 ways currently:
With should be able to implement C++ wrapper objects for multiple versions of a C struct using a single C++ template implementation and C++20 concepts to check for and call individual struct members if they exist (like this). Alternatives An alternative implementation could be adding additional structure/members to the C structure to support the calculation of pointer offsets at different versions. For example, the new structure might be:
And the usage (at any version) might be:
This approach may generate less code and smaller binaries compared to the "Proposal" approach (due to less reliance on template specializations). However, it would be a breaking API change, more work for direct consumers of the C API to set up correctly, and (potentially) more error-prone. |
C struct member ordering rules will be as follows:
With this pseudo-code C++ example:
The resulting C API member ordering would be:
|
In the rare cases where we do add new API to stable branches, we can mark that API as experimental to avoid breaking existing fixed API versions. |
For example:
The |
Just wanted to mention that I'll be following your progress here for possible integration with tauri-apps/wry. 👋🏼 There are already some experimental Rust bindings to the C API in wusyong/cef-rs. The Tauri team is interested in using CEF as another rendering option for apps that need features in Chromium that are missing in the system web views currently in use, particularly on Linux and Mac. Figuring out how to redistribute/share the CEF runtime reliably is probably the biggest open question for how to take that forward. Thanks for tackling this! |
A first draft PR of API versioning changes now up at https://bitbucket.org/chromiumembedded/cef/pull-requests/852. |
Example of debugging API hash errors. (for background see ApiVersioning) 1. Start with an API change that isn't correctly versioned:
2. Run version_manager check (or cef_create_projects), see that it fails:
3. To analyze the failure run version_manager check both before and after the change with debugging enabled:
4. Compare API hash intermediate output (
5. Fix the API versioning:
6. Verify that the fix is correct:
|
Example of adding a new API version. (for background see ApiVersioning) 1. Make an API change using the
2. Run version_manager add, get notified of a problem:
3. Run again with
4. Manually inspect the changes:
5. Verify that no further updates are required:
|
Initial documentation for API versioning has been added at https://bitbucket.org/chromiumembedded/cef/wiki/ApiVersioning |
- Generated files are now created when running cef_create_projects or the new version_manager.py tool. These files are still created in the cef/ source tree (same location as before) but Git ignores them due to the generated .gitignore file. - API hashes are committed to Git as a new cef_api_versions.json file. This file is used for both code generation and CEF version calculation (replacing the previous usage of cef_api_hash.h for this purpose). It will be updated by the CEF admin before merging breaking API changes upstream. - As an added benefit to the above, contributor PRs will no longer contain generated code that is susceptible to frequent merge conflicts. - From a code generation perspective, the main difference is that we now use versioned structs (e.g. cef_browser_0_t instead of cef_browser_t) on the libcef (dll/framework) side. Most of the make_*.py tool changes are related to supporting this. - From the client perspective, you can now define CEF_API_VERSION in the project configuration (or get CEF_EXPERIMENTAL by default). This define will change the API exposed in CEF’s include/ and include/capi header files. All client-side targets including libcef_dll_wrapper will need be recompiled when changing this define. - Examples of the new API-related define usage are provided in cef_api_version_test.h, api_version_test_impl.cc and api_version_unittest.cc. To test: - Run `ceftests --gtest_filter=ApiVersionTest.*` - Add `cef_api_version=13300` to GN_DEFINES. Re-run configure, build and ceftests steps. - Repeat with 13301, 13302, 13303 (all supported test versions).
This file is passed to clang and will otherwise generate different API hashes on different platforms.
API versioning requires that enumerations end with a count value (`*_NUM_VALUES`) and structs begin with a size value (`size_t size`). Wrapper templates are updated to support structs with different size values indicating different versions. To test: Run `ceftests --gtest_filter=ApiVersionTest.StructVersion*`
Remaining work related to API versioning:
|
Overview
This issue tracks the implementation of shared installation support for CEF. Use of a shared installation will be optional and will likely come with restrictions on available APIs and/or installation behaviors. Embedders that require non-standard binaries (like proprietary codecs enabled or custom CEF/Chromium modifications) will continue using a bundled installation.
A shared installation will address these primary concerns:
WebView2 Evergreen, an alternative to CEF, supports the concept of a system installation shared by multiple application installations. WebView2 is unfortunately Windows-only and Microsoft has abandoned plans to support other platforms. We can, however, use WebView2 as a reference model for implementing this functionality in CEF.
This implementation will involve the following phases:
Phase 1: Shared runtime behavior
BACKGROUND: CEF/Chromium currently hard-codes some assumptions about usage in a single application.
GOAL: Run multiple CEF-based applications with CEF located in a separate/shared directory. Each application will run independently and be completely isolated from the others in memory and on disk.
RELATED PROBLEMS: The default "User Data" directory is not application-specific, each platform has it's own behavioral quirks related to path discovery (#3749), loading behavior of libcef is not consistent across platforms (related).
Phase 2: Back/forward ABI compatibility
BACKGROUND: The CEF library/framework exports a C API that isolates the user from the CEF runtime and code base. The libcef_dll_wrapper project, which is distributed in source code form as part of the binary release, wraps this exported C API in a C++ API that is then linked into the client application. The code for this C/C++ API translation layer is automatically generated by the translator tool.
GOAL: Ensure that a pre-compiled CEF-based application can successfully run against multiple different major/minor milestone versions of CEF/Chromium (both older and newer versions; WebView2 example).
RELATED PROBLEMS: CEF version (API hash) checking is too strict, C structs and enums are not consistently versioned, new API surface is not added in a backwards-compatible manner, cef_sandbox.lib linking introduces build dependencies on Windows/MacOS.
See additional details below.
Phase 3: Shared installers & guidelines
BACKGROUND: After completion of Phases 1 and 2 it will be technically feasible to install CEF in a shared location on a user's device and utilize that shared install from multiple CEF-based applications.
GOAL: Provide official CEF shared installers with associated documentation and guidelines on usage for each platform.
RELATED PROBLEMS: Installers and installation behavior will have platform-specific requirements, CEF embedders need testing/validation support to "guarantee" compatibility between milestone versions, some form of "version pinning" will likely be required.
Explicit Non-Goals
We do not anticipate significant changes to CEF/Chromium behaviors or CEF C++ APIs or as part of this effort. In that vein, we have defined some explicit project non-goals:
The text was updated successfully, but these errors were encountered: