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

chrome: Support creation of lightweight (Alloy-style) windows and browsers #3681

Open
magreenblatt opened this issue Apr 11, 2024 · 4 comments
Labels
chrome Related to the Chrome runtime enhancement Enhancement request

Comments

@magreenblatt
Copy link
Collaborator

magreenblatt commented Apr 11, 2024

Is your feature request related to a problem? Please describe.
Use of the Chrome or Alloy runtime must currently be configured at app startup and cannot be mixed in a single app instance. Each runtime has its own strengths and weaknesses. For example:

  • Chrome runtime supports the full Chrome UI and functionality (details).
  • Alloy runtime supports off-screen rendering, client-provided parent windows, and some callbacks that are missing with the Chrome runtime (issues).

Describe the solution you'd like
Start with the Chrome runtime. Add the ability to create lightweight (Alloy-style) windows and browsers that behave the same as existing Alloy windows/browsers. This would include support for the following:

Additional context
Chrome runtime bootstrap means that all global objects and CefRequestContext (Profile) will be Chrome objects. For Alloy-style we will create Widget and WebContents objects directly (like with current Alloy runtime) and modify the existing Alloy implementations to work with Chrome global objects. This can be done in stages:

  1. Use per-browser/window state instead of global IsChromeRuntimeEnabled/IsAlloyRuntimeEnabled functions.
  2. Add argument to CefBrowserHost/CefWindow creation to specify Chrome or Alloy style. Chrome style windows can contain Alloy style browsers, but not visa-versa. Some of this behavior may be implicit (for example, always create Alloy style with off-screen rendering or when a parent window handle is specified).
  3. Fix various issues with Alloy* implementations to make it all work nicely.
  4. Delete the Alloy runtime bootstrap and related unused classes. Chrome runtime bootstrap becomes the only option.
@magreenblatt magreenblatt added enhancement Enhancement request chrome Related to the Chrome runtime labels Apr 11, 2024
magreenblatt added a commit that referenced this issue Apr 22, 2024
Split the Alloy runtime into bootstrap and style components. Support
creation of Alloy style browsers and windows with the Chrome runtime.
Chrome runtime (`--enable-chrome-runtime`) + Alloy style
(`--use-alloy-style`) supports Views (`--use-views`), native parent
(`--use-native`) and windowless rendering
(`--off-screen-rendering-enabled`).

Print preview is supported in all cases except with windowless rendering
on all platforms and native parent on MacOS. It is disabled by default
with Alloy style for legacy compatibility. Where supported it can be
enabled or disabled globally using `--[enable|disable]-print-preview` or
configured on a per-RequestContext basis using the
`printing.print_preview_disabled` preference. It also behaves as
expected when triggered via the PDF viewer print button.

Chrome runtime + Alloy style behavior differs from Alloy runtime in the
following significant ways:

- Supports Chrome error pages by default.
- DevTools popups are Chrome style only (cannot be windowless).
- The Alloy extension API will not supported.

Chrome runtime + Alloy style passes all expected Alloy ceftests except
the following:

- `DisplayTest.AutoResize` (Alloy extension API not supported)
- `DownloadTest.*` (Download API not yet supported)
- `ExtensionTest.*` (Alloy extension API not supported)

This change also adds Chrome runtime support for
CefContextMenuHandler::RunContextMenu (see #3293).

This change also explicitly blocks (and doesn't retry) FrameAttached
requests from PDF viewer and print preview excluded frames (see #3664).

Known issues specific to Chrome runtime + Alloy style:
- DevTools popup with windowless rendering doesn't load successfully.
  Use windowed rendering or remote debugging as a workaround.
- Chrome style Window with Alloy style BrowserView (`--use-alloy-style
  --use-chrome-style-window`) does not show Chrome theme changes.

To test:
- Run `ceftests --enable-chrome-runtime --use-alloy-style
       [--use-chrome-style-window] [--use-views|--use-native]
       --gtest_filter=...`
- Run `cefclient --enable-chrome-runtime --use-alloy-style
       [--use-chrome-style-window]
       [--use-views|--use-native|--off-screen-rendering-enabled]`
- Run `cefsimple --enable-chrome-runtime --use-alloy-style [--use-views]`
@magreenblatt
Copy link
Collaborator Author

magreenblatt commented Apr 22, 2024

Remaining work:

  • Add support for CefDownloadHandler API. (DONE)
  • views: Add Chrome theme support for Alloy style BrowserView in Chrome style Window. (DONE)
  • views: Test multiple Alloy style BrowserViews in a single Window.
  • Add build configuration to disable Alloy bootstrap. (DONE)

@magreenblatt
Copy link
Collaborator Author

magreenblatt added a commit that referenced this issue Apr 28, 2024
Match the logic in Alloy's CefMimeHandlerViewGuestDelegate.
magreenblatt added a commit that referenced this issue Apr 28, 2024
This change adds minimal tabs API support for Alloy style browsers.
Clicking links in PDF documents now navigate as expected.
magreenblatt added a commit that referenced this issue Apr 28, 2024
Behaves the same as Alloy runtime except that CanDownload is not
called for invalid protocol schemes.
magreenblatt added a commit that referenced this issue May 1, 2024
Set enable_alloy_bootstrap=false to build with Alloy bootstrap code
removed. Extension API is documented as deprecated in comments but
not compiled out with this arg.
magreenblatt added a commit that referenced this issue May 1, 2024
Include cef_config.h from base/cef_build.h and fix detection of
args.gn changes so that defines are available everywhere by default.

Fix include configuration for chrome_elf_set and sandbox targets.
magreenblatt added a commit that referenced this issue May 2, 2024
To test:
- Run `cefclient --enable-chrome-runtime --use-alloy-style
                 --use-chrome-style-window [--background-color=green]`
- OS and Chrome theme changes behave as expected.
magreenblatt added a commit that referenced this issue May 3, 2024
Now that args.gn is an input to the make_config_header target we
don't want to invalidate the build unnecessarily by modifying the
file if the contents are unchanged.
magreenblatt added a commit that referenced this issue May 5, 2024
To test:
- Run `cefclient --enable-chrome-runtime --use-alloy-style
                 --use-chrome-style-window [--background-color=green]`
- OS and Chrome theme changes behave as expected.
@magreenblatt
Copy link
Collaborator Author

magreenblatt commented May 20, 2024

DevTools popups don't load successfully in combination with windowless rendering.

It appears that DevTools frontend #initializeTarget never completes (await runnableInstanceFunction().run() never returns when running the InspectorMainImpl), and consequently DevToolsUIBindings::ReadyForTest is never called. Adding console.log statements in InspectorMainImpl shows that waitForPrimaryPageTarget never resolves because targetManager.primaryPageTarget() returns null. It looks like the problem is parentTarget has type "browser" instead of the expected type "frame".
image
Here are the expected |targets| when not using OSR:
image

It looks like BuildTargetInfo is passing the wrong |type| value ("other" vs the expected "page") to AttachedToTarget.

With OSR:

+		m_targetId	0x00000237d0c06f30 "134E9E28B3E4D3F7DE74F1875541583F"	std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>
+		m_type	0x00000237d045d340 "other"	std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>
+		m_title	0x00000237d045d358 "Google"	std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>
+		m_url	0x00000237d0c07080 "https://www.google.com/"	std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>
		m_attached	true	bool
+		m_openerId	{is_just_=false value_=0x00000237d045d398 "" }	crdtp::detail::ValueMaybe<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>>
		m_canAccessOpener	false	bool
+		m_openerFrameId	{is_just_=false value_=0x00000237d045d3c0 "" }	crdtp::detail::ValueMaybe<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>>
+		m_browserContextId	{is_just_=true value_=0x00000237d0c06e50 "4B8CD36561F1E032B21AABA6461B51DD" }	crdtp::detail::ValueMaybe<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>>
+		m_subtype	{is_just_=false value_=0x00000237d045d400 "" }	crdtp::detail::ValueMaybe<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>>

Without OSR:

+		m_targetId	0x0000011aecb61280 "20E74CA864F5116161F41D82A6665643"	std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>
+		m_type	0x0000011aee9c6b30 "page"	std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>
+		m_title	0x0000011aee9c6b48 "Google"	std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>
+		m_url	0x0000011aed556940 "https://www.google.com/"	std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>
		m_attached	true	bool
+		m_openerId	{is_just_=false value_=0x0000011aee9c6b88 "" }	crdtp::detail::ValueMaybe<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>>
		m_canAccessOpener	false	bool
+		m_openerFrameId	{is_just_=false value_=0x0000011aee9c6bb0 "" }	crdtp::detail::ValueMaybe<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>>
+		m_browserContextId	{is_just_=true value_=0x0000011ae8f8b420 "7165BA42B823C82D06C6EA9BDF786D9E" }	crdtp::detail::ValueMaybe<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>>
+		m_subtype	{is_just_=false value_=0x0000011aee9c6bf0 "" }	crdtp::detail::ValueMaybe<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>>>

Call stack:

 	content.dll!content::protocol::`anonymous namespace'::BuildTargetInfo(content::DevToolsAgentHost * agent_host) Line 114	C++
>	content.dll!content::protocol::TargetHandler::Session::Attach(content::protocol::TargetHandler * handler, content::DevToolsAgentHost * agent_host, bool waiting_for_debugger, bool flatten_protocol) Line 437	C++
 	content.dll!content::protocol::TargetHandler::AutoAttach(content::protocol::TargetAutoAttacher * source, content::DevToolsAgentHost * host, bool waiting_for_debugger) Line 849	C++
 	content.dll!content::protocol::TargetHandler::SetAttachedTargetsOfType(content::protocol::TargetAutoAttacher * source, const base::internal::flat_tree<scoped_refptr<content::DevToolsAgentHost>,std::__Cr::identity,std::__Cr::less<void>,std::__Cr::vector<scoped_refptr<content::DevToolsAgentHost>,std::__Cr::allocator<scoped_refptr<content::DevToolsAgentHost>>>> & new_hosts, const std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>> & type) Line 887	C++
 	content.dll!content::protocol::TargetAutoAttacher::DispatchSetAttachedTargetsOfType(const base::internal::flat_tree<scoped_refptr<content::DevToolsAgentHost>,std::__Cr::identity,std::__Cr::less<void>,std::__Cr::vector<scoped_refptr<content::DevToolsAgentHost>,std::__Cr::allocator<scoped_refptr<content::DevToolsAgentHost>>>> & hosts, const std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>> & type) Line 140	C++
 	content.dll!content::WebContentsDevToolsAgentHost::AutoAttacher::UpdateAssociatedPages() Line 110	C++
 	content.dll!content::WebContentsDevToolsAgentHost::AutoAttacher::UpdateAutoAttach(base::OnceCallback<void ()> callback) Line 94	C++
 	content.dll!content::protocol::TargetAutoAttacher::AddClient(content::protocol::TargetAutoAttacher::Client * client, bool wait_for_debugger_on_start, base::OnceCallback<void ()> callback) Line 88	C++
 	content.dll!content::protocol::TargetHandler::SetAutoAttachInternal(bool auto_attach, bool wait_for_debugger_on_start, bool flatten, base::OnceCallback<void ()> callback) Line 816	C++
 	content.dll!content::protocol::TargetHandler::SetAutoAttach(bool auto_attach, bool wait_for_debugger_on_start, crdtp::detail::ValueMaybe<bool> flatten, crdtp::detail::PtrMaybe<std::__Cr::vector<std::__Cr::unique_ptr<content::protocol::Target::FilterEntry,std::__Cr::default_delete<content::protocol::Target::FilterEntry>>,std::__Cr::allocator<std::__Cr::unique_ptr<content::protocol::Target::FilterEntry,std::__Cr::default_delete<content::protocol::Target::FilterEntry>>>>> filter, std::__Cr::unique_ptr<content::protocol::Target::Backend::SetAutoAttachCallback,std::__Cr::default_delete<content::protocol::Target::Backend::SetAutoAttachCallback>> callback) Line 1028	C++
 	content.dll!content::protocol::Target::DomainDispatcherImpl::setAutoAttach(const crdtp::Dispatchable & dispatchable) Line 899	C++
 	content.dll!content::protocol::Target::DomainDispatcherImpl::Dispatch::<lambda_14>::operator()(const crdtp::Dispatchable & dispatchable) Line 288	C++
 	content.dll!std::__Cr::__invoke<`lambda at gen\content\browser\devtools\protocol\target.cc:286:10' &,const crdtp::Dispatchable &>(content::protocol::Target::DomainDispatcherImpl::Dispatch::<lambda_14> & __f, const crdtp::Dispatchable & __args) Line 150	C++
 	content.dll!std::__Cr::__invoke_void_return_wrapper<void,1>::__call<`lambda at gen\content\browser\devtools\protocol\target.cc:286:10' &,const crdtp::Dispatchable &>(content::protocol::Target::DomainDispatcherImpl::Dispatch::<lambda_14> & __args, const crdtp::Dispatchable & __args) Line 226	C++
 	content.dll!std::__Cr::__function::__default_alloc_func<`lambda at gen\content\browser\devtools\protocol\target.cc:286:10',void (const crdtp::Dispatchable &)>::operator()(const crdtp::Dispatchable & __arg) Line 208	C++
 	content.dll!std::__Cr::__function::__policy_invoker<void (const crdtp::Dispatchable &)>::__call_impl<std::__Cr::__function::__default_alloc_func<`lambda at gen\content\browser\devtools\protocol\target.cc:286:10',void (const crdtp::Dispatchable &)>>(const std::__Cr::__function::__policy_storage * __buf, const crdtp::Dispatchable & __args) Line 608	C++
 	third_party_inspector_protocol_crdtp.dll!std::__Cr::__function::__policy_func<void (const crdtp::Dispatchable &)>::operator()(const crdtp::Dispatchable & __args) Line 714	C++
 	third_party_inspector_protocol_crdtp.dll!std::__Cr::function<void (const crdtp::Dispatchable &)>::operator()(const crdtp::Dispatchable & __arg) Line 987	C++
 	third_party_inspector_protocol_crdtp.dll!crdtp::UberDispatcher::Dispatch::<lambda_0>::operator()() Line 545	C++
 	third_party_inspector_protocol_crdtp.dll!std::__Cr::__invoke<`lambda at ..\..\third_party\inspector_protocol\crdtp\dispatch.cc:543:19' &>(crdtp::UberDispatcher::Dispatch::<lambda_0> & __f) Line 150	C++
 	third_party_inspector_protocol_crdtp.dll!std::__Cr::__invoke_void_return_wrapper<void,1>::__call<`lambda at ..\..\third_party\inspector_protocol\crdtp\dispatch.cc:543:19' &>(crdtp::UberDispatcher::Dispatch::<lambda_0> & __args) Line 226	C++
 	third_party_inspector_protocol_crdtp.dll!std::__Cr::__function::__default_alloc_func<`lambda at ..\..\third_party\inspector_protocol\crdtp\dispatch.cc:543:19',void ()>::operator()() Line 208	C++
 	third_party_inspector_protocol_crdtp.dll!std::__Cr::__function::__policy_invoker<void ()>::__call_impl<std::__Cr::__function::__default_alloc_func<`lambda at ..\..\third_party\inspector_protocol\crdtp\dispatch.cc:543:19',void ()>>(const std::__Cr::__function::__policy_storage * __buf) Line 608	C++
 	third_party_inspector_protocol_crdtp.dll!std::__Cr::__function::__policy_func<void ()>::operator()() Line 714	C++
 	third_party_inspector_protocol_crdtp.dll!std::__Cr::function<void ()>::operator()() Line 987	C++
 	third_party_inspector_protocol_crdtp.dll!crdtp::UberDispatcher::DispatchResult::Run() Line 509	C++
 	content.dll!content::DevToolsSession::HandleCommandInternal(crdtp::Dispatchable dispatchable, base::span<const unsigned char,18446744073709551615,const unsigned char *> message) Line 380	C++
 	content.dll!content::DevToolsSession::HandleCommand(base::span<const unsigned char,18446744073709551615,const unsigned char *> message) Line 365	C++
 	content.dll!base::internal::DecayedFunctorTraits<void (content::DevToolsSession::*)(base::span<const unsigned char,18446744073709551615,const unsigned char *>),base::WeakPtr<content::DevToolsSession> &&>::Invoke<void (content::DevToolsSession::*)(base::span<const unsigned char,18446744073709551615,const unsigned char *>),const base::WeakPtr<content::DevToolsSession> &,base::span<const unsigned char,18446744073709551615,const unsigned char *>>(void(content::DevToolsSession::*)(base::span<const unsigned char,18446744073709551615,const unsigned char *>) method, const base::WeakPtr<content::DevToolsSession> & receiver_ptr, base::span<const unsigned char,18446744073709551615,const unsigned char *> && args) Line 738	C++
 	content.dll!base::internal::InvokeHelper<1,base::internal::FunctorTraits<void (content::DevToolsSession::*&&)(base::span<const unsigned char,18446744073709551615,const unsigned char *>),base::WeakPtr<content::DevToolsSession> &&>,void,0>::MakeItSo<void (content::DevToolsSession::*)(base::span<const unsigned char,18446744073709551615,const unsigned char *>),std::__Cr::tuple<base::WeakPtr<content::DevToolsSession>>,base::span<const unsigned char,18446744073709551615,const unsigned char *>>(void(content::DevToolsSession::*)(base::span<const unsigned char,18446744073709551615,const unsigned char *>) && functor, std::__Cr::tuple<base::WeakPtr<content::DevToolsSession>> && bound, base::span<const unsigned char,18446744073709551615,const unsigned char *> && args) Line 958	C++
 	content.dll!base::internal::Invoker<base::internal::FunctorTraits<void (content::DevToolsSession::*&&)(base::span<const unsigned char,18446744073709551615,const unsigned char *>),base::WeakPtr<content::DevToolsSession> &&>,base::internal::BindState<1,1,0,void (content::DevToolsSession::*)(base::span<const unsigned char,18446744073709551615,const unsigned char *>),base::WeakPtr<content::DevToolsSession>>,void (base::span<const unsigned char,18446744073709551615,const unsigned char *>)>::RunImpl<void (content::DevToolsSession::*)(base::span<const unsigned char,18446744073709551615,const unsigned char *>),std::__Cr::tuple<base::WeakPtr<content::DevToolsSession>>,0>(void(content::DevToolsSession::*)(base::span<const unsigned char,18446744073709551615,const unsigned char *>) && functor, std::__Cr::tuple<base::WeakPtr<content::DevToolsSession>> && bound, std::__Cr::integer_sequence<unsigned long long,0>, base::span<const unsigned char,18446744073709551615,const unsigned char *> && unbound_args) Line 1067	C++
 	content.dll!base::internal::Invoker<base::internal::FunctorTraits<void (content::DevToolsSession::*&&)(base::span<const unsigned char,18446744073709551615,const unsigned char *>),base::WeakPtr<content::DevToolsSession> &&>,base::internal::BindState<1,1,0,void (content::DevToolsSession::*)(base::span<const unsigned char,18446744073709551615,const unsigned char *>),base::WeakPtr<content::DevToolsSession>>,void (base::span<const unsigned char,18446744073709551615,const unsigned char *>)>::RunOnce(base::internal::BindStateBase * base, base::span<const unsigned char,18446744073709551615,const unsigned char *> && unbound_args) Line 980	C++
 	libcef.dll!base::OnceCallback<void (base::span<const unsigned char,18446744073709551615,const unsigned char *>)>::Run(base::span<const unsigned char,18446744073709551615,const unsigned char *> args) Line 157	C++
 	libcef.dll!ChromeDevToolsSession::HandleCommand(base::span<const unsigned char,18446744073709551615,const unsigned char *> message, base::OnceCallback<void (base::span<const unsigned char,18446744073709551615,const unsigned char *>)> callback) Line 141	C++
 	libcef.dll!ChromeDevToolsManagerDelegate::HandleCommand(content::DevToolsAgentHostClientChannel * channel, base::span<const unsigned char,18446744073709551615,const unsigned char *> message, base::OnceCallback<void (base::span<const unsigned char,18446744073709551615,const unsigned char *>)> callback) Line 232	C++
 	content.dll!content::DevToolsSession::DispatchProtocolMessageInternal(crdtp::Dispatchable dispatchable, base::span<const unsigned char,18446744073709551615,const unsigned char *> message) Line 356	C++
 	content.dll!content::DevToolsSession::DispatchProtocolMessage(base::span<const unsigned char,18446744073709551615,const unsigned char *> message) Line 315	C++
 	content.dll!content::DevToolsAgentHostImpl::DispatchProtocolMessage(content::DevToolsAgentHostClient * client, base::span<const unsigned char,18446744073709551615,const unsigned char *> message) Line 349	C++
 	libcef.dll!DevToolsUIBindings::DispatchProtocolMessageFromDevToolsFrontend(const std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char>> & message) Line 1532	C++

@magreenblatt
Copy link
Collaborator Author

DevTools popups don't load successfully in combination with windowless rendering.
It looks like BuildTargetInfo is passing the wrong |type| value ("other" vs the expected "page") to AttachedToTarget.

The problem is ChromeDevToolsManagerDelegate::GetTargetType. The AllTabContentses case catches Chrome style browsers and the WebView::IsWebViewContents case catches Alloy style windowed browsers, but there's no handling for OSR browsers.

magreenblatt added a commit that referenced this issue May 21, 2024
Chrome runtime only supports creation of a Views-hosted DevTools
popup in ChromeBrowserDelegate::CreateDevToolsBrowser if the parent
is also Views-hosted.

To test:
- Run `cefclient --use-native`
- Right click, select "Show DevTools"
- Close both windows and the app should exit
magreenblatt added a commit that referenced this issue May 21, 2024
Chrome runtime only supports creation of a Views-hosted DevTools
popup in ChromeBrowserDelegate::CreateDevToolsBrowser if the parent
is also Views-hosted.

To test:
- Run `cefclient --use-native`
- Right click, select "Show DevTools"
- Close both windows and the app should exit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chrome Related to the Chrome runtime enhancement Enhancement request
Projects
None yet
Development

No branches or pull requests

1 participant