Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RCefWebDisplayHandle.cxx
Go to the documentation of this file.
1// Author: Sergey Linev <S.Linev@gsi.de>
2// Date: 2020-08-21
3// Warning: This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
4
5/*************************************************************************
6 * Copyright (C) 1995-2023, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13
14#if !defined(_MSC_VER)
15#pragma GCC diagnostic ignored "-Wunused-parameter"
16#pragma GCC diagnostic ignored "-Wshadow"
17#endif
18
19
21
22#include "TTimer.h"
23#include "TROOT.h"
24#include "TSystem.h"
25#include "TEnv.h"
26#include "TApplication.h"
27
28#include "include/base/cef_build.h"
29
30#include <ROOT/RLogger.hxx>
31
32#include <memory>
33
34
35class TCefTimer : public TTimer {
36public:
38 void Timeout() override
39 {
40 // just let run loop
42 }
43};
44
45
47
49
50public:
51
53
54 ~FrameSourceVisitor() override = default;
55
56 void Visit(const CefString &str) override
57 {
58 if (fHandle && fHandle->IsValid())
59 fHandle->SetContent(str.ToString());
60 }
61
62private:
63 // Include the default reference counting implementation.
66};
67
68
70 bool *fFlag{nullptr};
71public:
73 ~HeadlessPrintCallback() override = default;
74
75 void OnPdfPrintFinished(const CefString&, bool ok) override
76 {
77 if (fFlag) *fFlag = true;
78 }
79private:
80 // Include the default reference counting implementation.
83};
84
85std::unique_ptr<ROOT::RWebDisplayHandle> RCefWebDisplayHandle::CefCreator::Display(const ROOT::RWebDisplayArgs &args)
86{
87
88 auto handle = std::make_unique<RCefWebDisplayHandle>(args.GetFullUrl());
89 if (!args.IsStandalone())
90 handle->fCloseBrowser = false;
91
92 Int_t wait_tmout = args.IsHeadless() ? gEnv->GetValue("WebGui.CefHeadlessTimeout", 30) : -1;
93
94 if (fCefApp) {
95 fCefApp->SetNextHandle(handle.get(), args.IsHeadless());
96
97 CefRect rect((args.GetX() > 0) ? args.GetX() : 0, (args.GetY() > 0) ? args.GetY() : 0,
98 (args.GetWidth() > 0) ? args.GetWidth() : 800, (args.GetHeight() > 0) ? args.GetHeight() : 600);
99
100 fCefApp->StartWindow(args.GetHttpServer(), args.GetFullUrl(), args.GetPageContent(), rect, args.IsHeadless());
101
102 if (args.IsHeadless())
103 handle->WaitForContent(wait_tmout, args.GetExtraArgs());
104
105 return handle;
106 }
107
109 bool use_views = true;
110
111 TString env_use_views = gEnv->GetValue("WebGui.CefUseViews", "");
112 if ((env_use_views == "yes") || (env_use_views == "1"))
113 use_views = true;
114 else if ((env_use_views == "no") || (env_use_views == "0"))
115 use_views = false;
116
117 // Specify CEF global settings here.
119
120 TString ceflog = gEnv->GetValue("WebGui.CefLogSeveriry", "fatal");
121 if (ceflog == "fatal")
122 settings.log_severity = LOGSEVERITY_FATAL;
123 else if (ceflog == "verbose")
124 settings.log_severity = LOGSEVERITY_VERBOSE;
125 else if (ceflog == "info")
126 settings.log_severity = LOGSEVERITY_INFO;
127 else if (ceflog == "warning")
128 settings.log_severity = LOGSEVERITY_WARNING;
129 else if (ceflog == "error")
130 settings.log_severity = LOGSEVERITY_ERROR;
131 else if (ceflog == "disable")
132 settings.log_severity = LOGSEVERITY_DISABLE;
133 else
134 settings.log_severity = LOGSEVERITY_FATAL;
135
136 bool supress_log = (settings.log_severity == LOGSEVERITY_DISABLE) ||
137 (settings.log_severity == LOGSEVERITY_FATAL);
138
139
140#ifdef OS_WIN
141
142 // CefMainArgs main_args(args.IsHeadless() ? (HINSTANCE) 0 : GetModuleHandle(nullptr));
143
145
146#else
147
148 TApplication *root_app = gROOT->GetApplication();
149
150 std::vector<const char *> cef_argv = { root_app->Argv(0) };
151
152 if (supress_log) {
153 cef_argv.emplace_back("--disable-logging");
154 cef_argv.emplace_back("--enable-logging=none");
155 cef_argv.emplace_back("--v=-1");
156 }
157
158 cef_argv.emplace_back(nullptr);
159
160 CefMainArgs main_args(cef_argv.size() - 1, (char **) cef_argv.data());
161
162#endif
163
164 // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
165 // that share the same executable. This function checks the command-line and,
166 // if this is a sub-process, executes the appropriate logic.
167
168 /* int exit_code = CefExecuteProcess(main_args, nullptr, nullptr);
169 if (exit_code >= 0) {
170 // The sub-process has completed so return here.
171 return exit_code;
172 }
173 */
174
175 // Install xlib error handlers so that the application won't be terminated
176 // on non-fatal errors.
177 // XSetErrorHandler(XErrorHandlerImpl);
178 // XSetIOErrorHandler(XIOErrorHandlerImpl);
179
180
181 TString cef_main = TROOT::GetBinDir() + "/cef_main";
182 cef_string_ascii_to_utf16(cef_main.Data(), cef_main.Length(), &settings.browser_subprocess_path);
183
184#ifdef OS_MACOSX
185 // on mac there is framework directory, where resources and libs are combined together
186 TString path = TROOT::GetDataDir() + "/Frameworks/Chromium Embedded Framework.framework";
187 cef_string_ascii_to_utf16(path.Data(), path.Length(), &settings.framework_dir_path);
188
189 // add CEF libraries to DYLD library path
190 TString dypath = gSystem->Getenv("DYLD_LIBRARY_PATH");
191 if (dypath.Length() > 0)
192 dypath.Append(":");
193 dypath.Append(path + "/Libraries/");
194 gSystem->Setenv("DYLD_LIBRARY_PATH", dypath);
195#endif
196
197#ifdef OS_WIN
199 cef_string_ascii_to_utf16(resource_dir.Data(), resource_dir.Length(), &settings.resources_dir_path);
200 TString locales_dir = TROOT::GetDataDir() + "/Frameworks/cef/locales";
201 cef_string_ascii_to_utf16(locales_dir.Data(), locales_dir.Length(), &settings.locales_dir_path);
202#endif
203
204#ifdef OS_LINUX
206 cef_string_ascii_to_utf16(resource_dir.Data(), resource_dir.Length(), &settings.resources_dir_path);
207 TString locales_dir = TROOT::GetDataDir() + "/Frameworks/cef/locales";
208 cef_string_ascii_to_utf16(locales_dir.Data(), locales_dir.Length(), &settings.locales_dir_path);
209#endif
210
211 settings.no_sandbox = true;
212 // if (gROOT->IsWebDisplayBatch()) settings.single_process = true;
213
214 if (args.IsHeadless())
215 settings.windowless_rendering_enabled = true;
216
217 // settings.external_message_pump = true;
218 // settings.multi_threaded_message_loop = false;
219
220 std::string plog = "cef.log";
221 cef_string_ascii_to_utf16(plog.c_str(), plog.length(), &settings.log_file);
222
223 // settings.uncaught_exception_stack_size = 100;
224 // settings.ignore_certificate_errors = true;
225
226 // settings.remote_debugging_port = 7890;
227
228 // SimpleApp implements application-level callbacks for the browser process.
229 // It will create the first browser instance in OnContextInitialized() after
230 // CEF has initialized.
232 args.GetHttpServer(), args.GetFullUrl(), args.GetPageContent(),
233 args.GetWidth() > 0 ? args.GetWidth() : 800,
234 args.GetHeight() > 0 ? args.GetHeight() : 600,
235 args.IsHeadless());
236
237 fCefApp->SetNextHandle(handle.get(), args.IsHeadless());
238
239 // Initialize CEF for the browser process.
240 CefInitialize(main_args, settings, fCefApp.get(), nullptr);
241
242 if (args.IsHeadless()) {
243 handle->WaitForContent(wait_tmout, args.GetExtraArgs());
244 } else {
245 // Create timer to let run CEF message loop together with ROOT event loop
246 Int_t interval = gEnv->GetValue("WebGui.CefTimer", 10);
247 TCefTimer *timer = new TCefTimer((interval > 0) ? interval : 10, kTRUE);
248 timer->TurnOn();
249 }
250
251 // window not yet exists here
252 return handle;
253}
254
255///////////////////////////////////////////////////////////////////////////////////////////////////
256/// Destructor
257/// Closes browser window if any
258
265
266///////////////////////////////////////////////////////////////////////////////////////////////////
267/// Closes associated browser window
268
270{
271 if (fBrowser && fCloseBrowser) {
272 auto host = fBrowser->GetHost();
273 if (host) host->CloseBrowser(true);
274 fBrowser = nullptr;
275 }
276}
277
278///////////////////////////////////////////////////////////////////////////////////////////////////
279/// Process system events until browser content is available
280/// Used in headless mode for batch production like chrome --dump-dom is doing
281
283{
284 int expired = tmout_sec * 100;
285 bool did_try = false, print_finished = false;
286 std::string pdffile;
287 if (!extra_args.empty() && (extra_args.find("--print-to-pdf=")==0))
288 pdffile = extra_args.substr(15);
289
290 while ((--expired > 0) && GetContent().empty() && !print_finished) {
291
292 if (gSystem->ProcessEvents()) break; // interrupted, has to return
293
295
296 if (fBrowser && !did_try && fBrowser->HasDocument() && !fBrowser->IsLoading() && fBrowser->GetMainFrame()) {
297 did_try = true;
298 if (pdffile.empty()) {
299 fBrowser->GetMainFrame()->GetSource(new FrameSourceVisitor(this));
300 } else {
302 fBrowser->GetHost()->PrintToPDF(pdffile, settings, new HeadlessPrintCallback(&print_finished));
303 }
304 }
305
306 gSystem->Sleep(10); // only 10 ms sleep
307 }
308
309 CloseBrowser();
310
311 // call it once here to complete browser window closing, timer is not installed in batch mode
313
314 return !GetContent().empty();
315}
316
317///////////////////////////////////////////////////////////////////////////////////////////////////
318/// Resize browser window
319
321{
322 if (!fBrowser)
323 return false;
325}
326
327///////////////////////////////////////////////////////////////////////////////////////////////////
328/// Add CEF creator
329
331{
332 auto &entry = FindCreator("cef");
333 if (!entry)
334 GetMap().emplace("cef", std::make_unique<CefCreator>());
335}
336
337///////////////////////////////////////////////////////////////////////////////////////////////////
338/// Helper struct to add creator
339
343
struct RCefCreatorReg newRCefCreatorReg
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:126
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t rect
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t height
#define gROOT
Definition TROOT.h:417
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
DISALLOW_COPY_AND_ASSIGN(FrameSourceVisitor)
void Visit(const CefString &str) override
FrameSourceVisitor(RCefWebDisplayHandle *handle)
IMPLEMENT_REFCOUNTING(FrameSourceVisitor)
RCefWebDisplayHandle * fHandle
~FrameSourceVisitor() override=default
static bool PlatformResize(CefRefPtr< CefBrowser > browser, int width, int height)
static void PlatformInit()
void OnPdfPrintFinished(const CefString &, bool ok) override
~HeadlessPrintCallback() override=default
IMPLEMENT_REFCOUNTING(HeadlessPrintCallback)
DISALLOW_COPY_AND_ASSIGN(HeadlessPrintCallback)
std::unique_ptr< ROOT::RWebDisplayHandle > Display(const ROOT::RWebDisplayArgs &args) override
CefRefPtr< CefBrowser > fBrowser
associated browser
void CloseBrowser()
Closes associated browser window.
static void AddCreator()
Add CEF creator.
bool WaitForContent(int tmout_sec, const std::string &extra_args)
Process system events until browser content is available Used in headless mode for batch production l...
unsigned fValid
used to verify if instance valid or not
~RCefWebDisplayHandle() override
Destructor Closes browser window if any.
bool Resize(int, int) override
Resize browser window.
Holds different arguments for starting browser with RWebDisplayHandle::Display() method.
THttpServer * GetHttpServer() const
returns http server instance, used for window display
int GetWidth() const
returns preferable web window width
int GetY() const
set preferable web window y position
std::string GetFullUrl() const
returns window url with append options
bool IsStandalone() const
Return true if browser should runs in standalone mode.
int GetHeight() const
returns preferable web window height
bool IsHeadless() const
returns headless mode
const std::string & GetExtraArgs() const
get extra command line arguments for starting web browser command
int GetX() const
set preferable web window x position
const std::string & GetPageContent() const
returns window url
const std::string & GetContent() const
get content
static std::map< std::string, std::unique_ptr< Creator > > & GetMap()
Static holder of registered creators of web displays.
void SetContent(const std::string &cont)
set content
static std::unique_ptr< Creator > & FindCreator(const std::string &name, const std::string &libname="")
Search for specific browser creator If not found, try to add one.
This class creates the ROOT Application Environment that interfaces to the windowing system eventloop...
void Timeout() override
TCefTimer(Long_t milliSec, Bool_t mode)
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:511
static const TString & GetBinDir()
Get the binary directory in the installation. Static utility function.
Definition TROOT.cxx:3150
static const TString & GetLibDir()
Get the library directory in the installation.
Definition TROOT.cxx:3178
static const TString & GetDataDir()
Get the data directory in the installation. Static utility function.
Definition TROOT.cxx:3391
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:427
const char * Data() const
Definition TString.h:386
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1680
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:439
virtual void Setenv(const char *name, const char *value)
Set environment variable.
Definition TSystem.cxx:1664
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:418
Handles synchronous and a-synchronous timer events.
Definition TTimer.h:51
Helper struct to add creator.