Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RWebWindowsManager.cxx
Go to the documentation of this file.
1// Author: Sergey Linev <s.linev@gsi.de>
2// Date: 2017-10-16
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-2019, 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
14
15#include <ROOT/RLogger.hxx>
18
20
21#include "THttpServer.h"
22
23#include "TSystem.h"
24#include "TRandom.h"
25#include "TString.h"
26#include "TApplication.h"
27#include "TTimer.h"
28#include "TROOT.h"
29#include "TEnv.h"
30#include "TExec.h"
31
32#include <thread>
33#include <chrono>
34#include <iostream>
35
36using namespace ROOT::Experimental;
37
38///////////////////////////////////////////////////////////////
39/// Parse boolean gEnv variable which should be "yes" or "no"
40/// Returns 1 for true or 0 for false
41/// Returns \param dflt if result is not defined
42
43int RWebWindowWSHandler::GetBoolEnv(const std::string &name, int dflt)
44{
45 const char *undef = "<undefined>";
46 const char *value = gEnv->GetValue(name.c_str(), undef);
47 if (!value) return dflt;
48 std::string svalue = value;
49 if (svalue == undef) return dflt;
50
51 if (svalue == "yes") return 1;
52 if (svalue == "no") return 0;
53
54 R__LOG_ERROR(WebGUILog()) << name << " has to be yes or no";
55 return dflt;
56}
57
58
59/** \class ROOT::Experimental::RWebWindowsManager
60\ingroup webdisplay
61
62Central instance to create and show web-based windows like Canvas or FitPanel.
63
64Manager responsible to creating THttpServer instance, which is used for RWebWindow's
65communication with clients.
66
67Method RWebWindowsManager::Show() used to show window in specified location.
68*/
69
70//////////////////////////////////////////////////////////////////////////////////////////
71/// Returns default window manager
72/// Used to display all standard ROOT elements like TCanvas or TFitPanel
73
74std::shared_ptr<RWebWindowsManager> &RWebWindowsManager::Instance()
75{
76 static std::shared_ptr<RWebWindowsManager> sInstance = std::make_shared<RWebWindowsManager>();
77 return sInstance;
78}
79
80//////////////////////////////////////////////////////////////////
81/// This thread id used to identify main application thread, where ROOT event processing runs
82/// To inject code in that thread, one should use TTimer (like THttpServer does)
83/// In other threads special run methods have to be invoked like RWebWindow::Run()
84///
85/// TODO: probably detection of main thread should be delivered by central ROOT instances like gApplication or gROOT
86/// Main thread can only make sense if special processing runs there and one can inject own functionality there
87
88static std::thread::id gWebWinMainThrd = std::this_thread::get_id();
89static bool gWebWinMainThrdSet = true;
90
91//////////////////////////////////////////////////////////////////////////////////////////
92/// Returns true when called from main process
93/// Main process recognized at the moment when library is loaded
94/// It supposed to be a thread where gApplication->Run() will be called
95/// If application runs in separate thread, one have to use AssignMainThrd() method
96/// to let RWebWindowsManager correctly recognize such situation
97
99{
100 return gWebWinMainThrdSet && (std::this_thread::get_id() == gWebWinMainThrd);
101}
102
103//////////////////////////////////////////////////////////////////////////////////////////
104/// Re-assigns main thread id
105/// Normally main thread id recognized at the moment when library is loaded
106/// It supposed to be a thread where gApplication->Run() will be called
107/// If application runs in separate thread, one have to call this method
108/// to let RWebWindowsManager correctly recognize such situation
109
111{
112 gWebWinMainThrdSet = true;
113 gWebWinMainThrd = std::this_thread::get_id();
114}
115
116//////////////////////////////////////////////////////////////////////////////////////////
117/// window manager constructor
118/// Required here for correct usage of unique_ptr<THttpServer>
119
121{
122 fExternalProcessEvents = RWebWindowWSHandler::GetBoolEnv("WebGui.ExternalProcessEvents") == 1;
124 gWebWinMainThrdSet = false;
125 fAssgnExec = std::make_unique<TExec>("init_threadid", "ROOT::Experimental::RWebWindowsManager::AssignMainThrd();");
126 TTimer::SingleShot(0, "TExec", fAssgnExec.get(), "Exec()");
127 }
128}
129
130//////////////////////////////////////////////////////////////////////////////////////////
131/// window manager destructor
132/// Required here for correct usage of unique_ptr<THttpServer>
133
135{
136 if (gApplication && fServer && !fServer->IsTerminated()) {
137 gApplication->Disconnect("Terminate(Int_t)", fServer.get(), "SetTerminate()");
138 fServer->SetTerminate();
139 }
140}
141
142//////////////////////////////////////////////////////////////////////////////////////////
143/// Assign thread id for window
144/// Required in case of external process events
145
147{
149 win.fUseServerThreads = false;
150 win.fProcessMT = false;
151 win.fCallbacksThrdIdSet = true;
153 }
154}
155
156//////////////////////////////////////////////////////////////////////////////////////////
157/// Creates http server, if required - with real http engine (civetweb)
158/// One could configure concrete HTTP port, which should be used for the server,
159/// provide following entry in rootrc file:
160///
161/// WebGui.HttpPort: 8088
162///
163/// or specify range of http ports, which can be used:
164///
165/// WebGui.HttpPortMin: 8800
166/// WebGui.HttpPortMax: 9800
167///
168/// By default range [8800..9800] is used
169///
170/// One also can bind HTTP server socket to loopback address,
171/// In that case only connection from localhost will be available:
172///
173/// WebGui.HttpLoopback: yes
174///
175/// Or one could specify hostname which should be used for binding of server socket
176///
177/// WebGui.HttpBind: hostname | ipaddress
178///
179/// To use secured protocol, following parameter should be specified
180///
181/// WebGui.UseHttps: yes
182/// WebGui.ServerCert: sertificate_filename.pem
183///
184/// All incoming requests processed in THttpServer in timer handler with 10 ms timeout.
185/// One may decrease value to improve latency or increase value to minimize CPU load
186///
187/// WebGui.HttpTimer: 10
188///
189/// To processing incoming http requests and websockets, THttpServer allocate 10 threads
190/// One have to increase this number if more simultaneous connections are expected:
191///
192/// WebGui.HttpThrds: 10
193///
194/// One also can configure usage of special thread of processing of http server requests
195///
196/// WebGui.HttpThrd: no
197///
198/// Extra threads can be used to send data to different clients via websocket (default no)
199///
200/// WebGui.SenderThrds: no
201///
202/// If required, one could change websocket timeouts (default is 10000 ms)
203///
204/// WebGui.HttpWSTmout: 10000
205///
206/// By default, THttpServer created in restricted mode which only allows websocket handlers
207/// and processes only very few other related http requests. For security reasons such mode
208/// should be always enabled. Only if it is really necessary to process all other kinds
209/// of HTTP requests, one could specify no for following parameter (default yes):
210///
211/// WebGui.WSOnly: yes
212///
213/// In some applications one may need to force longpoll websocket emulations from the beginning,
214/// for instance when clients connected via proxys. Although JSROOT should automatically fallback
215/// to longpoll engine, one can configure this directly (default no)
216///
217/// WebGui.WSLongpoll: no
218///
219/// Following parameter controls browser max-age caching parameter for files (default 3600)
220/// When 0 is specified, browser cache will be disabled
221///
222/// WebGui.HttpMaxAge: 3600
223///
224/// One also can configure usage of FastCGI server for web windows:
225///
226/// WebGui.FastCgiPort: 4000
227/// WebGui.FastCgiThreads: 10
228///
229/// To be able start web browser for such windows, one can provide real URL of the
230/// web server which will connect with that FastCGI instance:
231///
232/// WebGui.FastCgiServer: https://your_apache_server.com/root_cgi_path
233///
234
236{
237 if (gROOT->GetWebDisplay() == "off")
238 return false;
239
240 // explicitly protect server creation
241 std::lock_guard<std::recursive_mutex> grd(fMutex);
242
243 if (!fServer) {
244
245 fServer = std::make_unique<THttpServer>("basic_sniffer");
246
248 fUseHttpThrd = false;
249 } else {
250 auto serv_thrd = RWebWindowWSHandler::GetBoolEnv("WebGui.HttpThrd");
251 if (serv_thrd != -1)
252 fUseHttpThrd = serv_thrd != 0;
253 }
254
255 auto send_thrds = RWebWindowWSHandler::GetBoolEnv("WebGui.SenderThrds");
256 if (send_thrds != -1)
257 fUseSenderThreads = send_thrds != 0;
258
259 if (IsUseHttpThread())
260 fServer->CreateServerThread();
261
262 if (gApplication)
263 gApplication->Connect("Terminate(Int_t)", "THttpServer", fServer.get(), "SetTerminate()");
264
265 fServer->SetWSOnly(RWebWindowWSHandler::GetBoolEnv("WebGui.WSOnly", 1) != 0);
266
267 // this is location where all ROOT UI5 sources are collected
268 // normally it is $ROOTSYS/ui5 or <prefix>/ui5 location
269 TString ui5dir = gSystem->Getenv("ROOTUI5SYS");
270 if (ui5dir.Length() == 0)
271 ui5dir = gEnv->GetValue("WebGui.RootUi5Path","");
272
273 if (ui5dir.Length() == 0)
274 ui5dir.Form("%s/ui5", TROOT::GetDataDir().Data());
275
276 if (gSystem->ExpandPathName(ui5dir)) {
277 R__LOG_ERROR(WebGUILog()) << "Path to ROOT ui5 sources " << ui5dir << " not found, set ROOTUI5SYS correctly";
278 ui5dir = ".";
279 }
280
281 fServer->AddLocation("rootui5sys/", ui5dir.Data());
282 }
283
284 if (!with_http || fServer->IsAnyEngine())
285 return true;
286
287 int http_port = gEnv->GetValue("WebGui.HttpPort", 0);
288 int http_min = gEnv->GetValue("WebGui.HttpPortMin", 8800);
289 int http_max = gEnv->GetValue("WebGui.HttpPortMax", 9800);
290 int http_timer = gEnv->GetValue("WebGui.HttpTimer", 10);
291 int http_thrds = gEnv->GetValue("WebGui.HttpThreads", 10);
292 int http_wstmout = gEnv->GetValue("WebGui.HttpWSTmout", 10000);
293 int http_maxage = gEnv->GetValue("WebGui.HttpMaxAge", -1);
294 int fcgi_port = gEnv->GetValue("WebGui.FastCgiPort", 0);
295 int fcgi_thrds = gEnv->GetValue("WebGui.FastCgiThreads", 10);
296 const char *fcgi_serv = gEnv->GetValue("WebGui.FastCgiServer", "");
297 fLaunchTmout = gEnv->GetValue("WebGui.LaunchTmout", 30.);
298 bool assign_loopback = RWebWindowWSHandler::GetBoolEnv("WebGui.HttpLoopback", 1) == 1;
299 const char *http_bind = gEnv->GetValue("WebGui.HttpBind", "");
300 bool use_secure = RWebWindowWSHandler::GetBoolEnv("WebGui.UseHttps", 0) == 1;
301 const char *ssl_cert = gEnv->GetValue("WebGui.ServerCert", "rootserver.pem");
302
303 int ntry = 100;
304
305 if ((http_port < 0) && (fcgi_port <= 0)) {
306 R__LOG_ERROR(WebGUILog()) << "Not allowed to create HTTP server, check WebGui.HttpPort variable";
307 return false;
308 }
309
310 if ((http_timer > 0) && !IsUseHttpThread())
311 fServer->SetTimer(http_timer);
312
313 if (http_port < 0) {
314 ntry = 0;
315 } else {
316
317 if (http_port == 0)
318 gRandom->SetSeed(0);
319
320 if (http_max - http_min < ntry)
321 ntry = http_max - http_min;
322 }
323
324 if (fcgi_port > 0)
325 ntry++;
326
327 while (ntry-- >= 0) {
328 if ((http_port == 0) && (fcgi_port <= 0)) {
329 if ((http_min <= 0) || (http_max <= http_min)) {
330 R__LOG_ERROR(WebGUILog()) << "Wrong HTTP range configuration, check WebGui.HttpPortMin/Max variables";
331 return false;
332 }
333
334 http_port = (int)(http_min + (http_max - http_min) * gRandom->Rndm(1));
335 }
336
337 TString engine, url;
338
339 if (fcgi_port > 0) {
340 engine.Form("fastcgi:%d?thrds=%d", fcgi_port, fcgi_thrds);
341 if (!fServer->CreateEngine(engine)) return false;
342 if (fcgi_serv && (strlen(fcgi_serv) > 0)) fAddr = fcgi_serv;
343 if (http_port < 0) return true;
344 fcgi_port = 0;
345 } else if (http_port > 0) {
346 url = use_secure ? "https://" : "http://";
347 engine.Form("%s:%d?thrds=%d&websocket_timeout=%d", (use_secure ? "https" : "http"), http_port, http_thrds, http_wstmout);
348 if (assign_loopback) {
349 engine.Append("&loopback");
350 url.Append("localhost");
351 } else if (http_bind && (strlen(http_bind) > 0)) {
352 engine.Append("&bind=");
353 engine.Append(http_bind);
354 url.Append(http_bind);
355 } else {
356 url.Append("localhost");
357 }
358
359 if (http_maxage >= 0)
360 engine.Append(TString::Format("&max_age=%d", http_maxage));
361
362 if (use_secure) {
363 engine.Append("&ssl_cert=");
364 engine.Append(ssl_cert);
365 }
366
367 if (fServer->CreateEngine(engine)) {
368 fAddr = url.Data();
369 fAddr.append(":");
370 fAddr.append(std::to_string(http_port));
371 return true;
372 }
373 http_port = 0;
374 }
375 }
376
377 return false;
378}
379
380//////////////////////////////////////////////////////////////////////////////////////////
381/// Creates new window
382/// To show window, RWebWindow::Show() have to be called
383
384std::shared_ptr<RWebWindow> RWebWindowsManager::CreateWindow()
385{
386 // we book manager mutex for a longer operation, locked again in server creation
387 std::lock_guard<std::recursive_mutex> grd(fMutex);
388
389 if (!CreateServer()) {
390 R__LOG_ERROR(WebGUILog()) << "Cannot create server when creating window";
391 return nullptr;
392 }
393
394 std::shared_ptr<RWebWindow> win = std::make_shared<RWebWindow>();
395
396 if (!win) {
397 R__LOG_ERROR(WebGUILog()) << "Fail to create RWebWindow instance";
398 return nullptr;
399 }
400
401 double dflt_tmout = gEnv->GetValue("WebGui.OperationTmout", 50.);
402
403 auto wshandler = win->CreateWSHandler(Instance(), ++fIdCnt, dflt_tmout);
404
405 if (gEnv->GetValue("WebGui.RecordData", 0) > 0) {
406 std::string fname, prefix;
407 if (fIdCnt > 1) {
408 prefix = std::string("f") + std::to_string(fIdCnt) + "_";
409 fname = std::string("protcol") + std::to_string(fIdCnt) + ".json";
410 } else {
411 fname = "protocol.json";
412 }
413 win->RecordData(fname, prefix);
414 }
415
418 AssignWindowThreadId(*win.get());
419 else
420 win->UseServerThreads(); // let run window until thread is obtained
421 } else if (IsUseHttpThread())
422 win->UseServerThreads();
423
424 const char *token = gEnv->GetValue("WebGui.ConnToken", "");
425 if (token && *token)
426 win->SetConnToken(token);
427
428 fServer->RegisterWS(wshandler);
429
430 return win;
431}
432
433//////////////////////////////////////////////////////////////////////////////////////////
434/// Release all references to specified window
435/// Called from RWebWindow destructor
436
438{
439 if (win.fWSHandler)
440 fServer->UnregisterWS(win.fWSHandler);
441}
442
443//////////////////////////////////////////////////////////////////////////
444/// Provide URL address to access specified window from inside or from remote
445
446std::string RWebWindowsManager::GetUrl(const RWebWindow &win, bool remote)
447{
448 if (!fServer) {
449 R__LOG_ERROR(WebGUILog()) << "Server instance not exists when requesting window URL";
450 return "";
451 }
452
453 std::string addr = "/";
454
455 addr.append(win.fWSHandler->GetName());
456
457 addr.append("/");
458
459 if (remote) {
460 if (!CreateServer(true)) {
461 R__LOG_ERROR(WebGUILog()) << "Fail to start real HTTP server when requesting URL";
462 return "";
463 }
464
465 addr = fAddr + addr;
466 }
467
468 return addr;
469}
470
471///////////////////////////////////////////////////////////////////////////////////////////////////
472/// Show web window in specified location.
473///
474/// \param user_args specifies where and how display web window
475///
476/// As display args one can use string like "firefox" or "chrome" - these are two main supported web browsers.
477/// See RWebDisplayArgs::SetBrowserKind() for all available options. Default value for the browser can be configured
478/// when starting root with --web argument like: "root --web=chrome". When root started in web server mode "root --web=server",
479/// no any web browser will be started - just URL will be printout, which can be entered in any running web browser
480///
481/// If allowed, same window can be displayed several times (like for RCanvas or TCanvas)
482///
483/// Following parameters can be configured in rootrc file:
484///
485/// WebGui.Chrome: full path to Google Chrome executable
486/// WebGui.ChromeBatch: command to start chrome in batch, used for image production, like "$prog --headless --disable-gpu $geometry $url"
487/// WebGui.ChromeHeadless: command to start chrome in headless mode, like "fork: --headless --disable-gpu $geometry $url"
488/// WebGui.ChromeInteractive: command to start chrome in interactive mode, like "$prog $geometry --app=\'$url\' &"
489/// WebGui.Firefox: full path to Mozilla Firefox executable
490/// WebGui.FirefoxHeadless: command to start Firefox in headless mode, like "fork:--headless --private-window --no-remote $profile $url"
491/// WebGui.FirefoxInteractive: command to start Firefox in interactive mode, like "$prog --private-window \'$url\' &"
492/// WebGui.FirefoxProfile: name of Firefox profile to use
493/// WebGui.FirefoxProfilePath: file path to Firefox profile
494/// WebGui.FirefoxRandomProfile: usage of random Firefox profile -1 never, 0 - only for headless mode (dflt), 1 - always
495/// WebGui.LaunchTmout: time required to start process in seconds (default 30 s)
496/// WebGui.OperationTmout: time required to perform WebWindow operation like execute command or update drawings
497/// WebGui.RecordData: if specified enables data recording for each web window 0 - off, 1 - on
498/// WebGui.JsonComp: compression factor for JSON conversion, if not specified - each widget uses own default values
499/// WebGui.ForceHttp: 0 - off (default), 1 - always create real http server to run web window
500/// WebGui.Console: -1 - output only console.error(), 0 - add console.warn(), 1 - add console.log() output
501/// WebGui.ConnCredits: 10 - number of packets which can be send by server or client without acknowledge from receiving side
502/// WebGui.openui5src: alternative location for openui5 like https://openui5.hana.ondemand.com/
503/// WebGui.openui5libs: list of pre-loaded ui5 libs like sap.m, sap.ui.layout, sap.ui.unified
504/// WebGui.openui5theme: openui5 theme like sap_belize (default) or sap_fiori_3
505///
506/// THttpServer-related parameters documented in \ref CreateServer method
507
509{
510 // silently ignore regular Show() calls in batch mode
511 if (!user_args.IsHeadless() && gROOT->IsWebDisplayBatch())
512 return 0;
513
514 // for embedded window no any browser need to be started
515 // also when off is specified, no browser should be started
516 if ((user_args.GetBrowserKind() == RWebDisplayArgs::kEmbedded) || (user_args.GetBrowserKind() == RWebDisplayArgs::kOff))
517 return 0;
518
519 // catch window showing, used by the RBrowser to embed some of ROOT widgets
520 if (fShowCallback)
521 if (fShowCallback(win, user_args))
522 return 0;
523
524 // place here while involves conn mutex
525 auto token = win.GetConnToken();
526
527 // we book manager mutex for a longer operation,
528 std::lock_guard<std::recursive_mutex> grd(fMutex);
529
530 if (!fServer) {
531 R__LOG_ERROR(WebGUILog()) << "Server instance not exists to show window";
532 return 0;
533 }
534
535 std::string key;
536 int ntry = 100000;
537
538 do {
539 key = std::to_string(gRandom->Integer(0x100000));
540 } while ((--ntry > 0) && win.HasKey(key));
541 if (ntry == 0) {
542 R__LOG_ERROR(WebGUILog()) << "Fail to create unique key for the window";
543 return 0;
544 }
545
546 RWebDisplayArgs args(user_args);
547
548 if (args.IsHeadless() && !args.IsSupportHeadless()) {
549 R__LOG_ERROR(WebGUILog()) << "Cannot use batch mode with " << args.GetBrowserName();
550 return 0;
551 }
552
553 if (args.GetWidth() <= 0) args.SetWidth(win.GetWidth());
554 if (args.GetHeight() <= 0) args.SetHeight(win.GetHeight());
555
556 bool normal_http = !args.IsLocalDisplay();
557 if (!normal_http && (gEnv->GetValue("WebGui.ForceHttp",0) == 1))
558 normal_http = true;
559
560 std::string url = GetUrl(win, normal_http);
561 if (url.empty()) {
562 R__LOG_ERROR(WebGUILog()) << "Cannot create URL for the window";
563 return 0;
564 }
565 if (normal_http && fAddr.empty()) {
566 R__LOG_WARNING(WebGUILog()) << "Full URL cannot be produced for window " << url << " to start web browser";
567 return 0;
568 }
569
570 args.SetUrl(url);
571
572 args.AppendUrlOpt(std::string("key=") + key);
573 if (args.IsHeadless()) args.AppendUrlOpt("headless"); // used to create holder request
574 if (!token.empty())
575 args.AppendUrlOpt(std::string("token=") + token);
576
577 if (!args.IsHeadless() && (gROOT->GetWebDisplay() == "server")) {
578 std::cout << "New web window: " << args.GetUrl() << std::endl;
579 return 0;
580 }
581
582 if (!normal_http)
583 args.SetHttpServer(GetServer());
584
585 auto handle = RWebDisplayHandle::Display(args);
586
587 if (!handle) {
588 R__LOG_ERROR(WebGUILog()) << "Cannot display window in " << args.GetBrowserName();
589 return 0;
590 }
591
592 return win.AddDisplayHandle(args.IsHeadless(), key, handle);
593}
594
595//////////////////////////////////////////////////////////////////////////
596/// Waits until provided check function or lambdas returns non-zero value
597/// Regularly calls WebWindow::Sync() method to let run event loop
598/// If call from the main thread, runs system events processing
599/// Check function has following signature: int func(double spent_tm)
600/// Parameter spent_tm is time in seconds, which already spent inside function
601/// Waiting will be continued, if function returns zero.
602/// First non-zero value breaks waiting loop and result is returned (or 0 if time is expired).
603/// If parameter timed is true, timelimit (in seconds) defines how long to wait
604
605int RWebWindowsManager::WaitFor(RWebWindow &win, WebWindowWaitFunc_t check, bool timed, double timelimit)
606{
607 int res = 0, cnt = 0;
608 double spent = 0.;
609
610 auto start = std::chrono::high_resolution_clock::now();
611
612 win.Sync(); // in any case call sync once to ensure
613
614 auto is_main_thread = IsMainThrd();
615
616 while ((res = check(spent)) == 0) {
617
618 if (is_main_thread)
620
621 win.Sync();
622
623 // only when first 1000 events processed, invoke sleep
624 if (++cnt > 1000)
625 std::this_thread::sleep_for(std::chrono::milliseconds(cnt > 5000 ? 10 : 1));
626
627 std::chrono::duration<double, std::milli> elapsed = std::chrono::high_resolution_clock::now() - start;
628
629 spent = elapsed.count() * 1e-3; // use ms precision
630
631 if (timed && (spent > timelimit))
632 return -3;
633 }
634
635 return res;
636}
637
638//////////////////////////////////////////////////////////////////////////
639/// Terminate http server and ROOT application
640
642{
643 if (fServer)
644 fServer->SetTerminate();
645
646 if (gApplication)
647 TTimer::SingleShot(100, "TApplication", gApplication, "Terminate()");
648}
#define R__LOG_WARNING(...)
Definition RLogger.hxx:363
#define R__LOG_ERROR(...)
Definition RLogger.hxx:362
#define e(i)
Definition RSha256.hxx:103
static bool gWebWinMainThrdSet
static std::thread::id gWebWinMainThrd
This thread id used to identify main application thread, where ROOT event processing runs To inject c...
R__EXTERN TApplication * gApplication
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
char name[80]
Definition TGX11.cxx:110
#define gROOT
Definition TROOT.h:404
R__EXTERN TRandom * gRandom
Definition TRandom.h:62
R__EXTERN TSystem * gSystem
Definition TSystem.h:559
Holds different arguments for starting browser with RWebDisplayHandle::Display() method.
std::string GetBrowserName() const
Returns configured browser name.
bool IsSupportHeadless() const
returns true if browser supports headless mode
bool IsHeadless() const
returns headless mode
RWebDisplayArgs & SetUrl(const std::string &url)
set window url
int GetHeight() const
returns preferable web window height
void SetHttpServer(THttpServer *serv)
set http server instance, used for window display
EBrowserKind GetBrowserKind() const
returns configured browser kind, see EBrowserKind for supported values
void AppendUrlOpt(const std::string &opt)
append extra url options, add "&" as separator if required
bool IsLocalDisplay() const
returns true if local display like CEF or Qt5 QWebEngine should be used
@ kEmbedded
window will be embedded into other, no extra browser need to be started
@ kOff
disable web display, do not start any browser
RWebDisplayArgs & SetHeight(int h=0)
set preferable web window height
const std::string & GetUrl() const
returns window url
int GetWidth() const
returns preferable web window width
RWebDisplayArgs & SetWidth(int w=0)
set preferable web window width
static std::unique_ptr< RWebDisplayHandle > Display(const RWebDisplayArgs &args)
Create web display.
static int GetBoolEnv(const std::string &name, int dfl=-1)
Parse boolean gEnv variable which should be "yes" or "no" Returns 1 for true or 0 for false Returns.
Represents web window, which can be shown in web browser or any other supported environment.
void Sync()
Special method to process all internal activity when window runs in separate thread.
bool fCallbacksThrdIdSet
! flag indicating that thread id is assigned
unsigned AddDisplayHandle(bool headless_mode, const std::string &key, std::unique_ptr< RWebDisplayHandle > &handle)
Add display handle and associated key Key is random number generated when starting new window When cl...
std::thread::id fCallbacksThrdId
! thread id where callbacks should be invoked
std::string GetConnToken() const
Returns configured connection token.
unsigned GetHeight() const
returns configured window height (0 - default)
bool HasKey(const std::string &key) const
Returns true if provided key value already exists (in processes map or in existing connections)
unsigned GetWidth() const
returns configured window width (0 - default) actual window width can be different
std::shared_ptr< RWebWindowWSHandler > fWSHandler
! specialize websocket handler for all incoming connections
bool fUseServerThreads
! indicates that server thread is using, no special window thread
bool fProcessMT
! if window event processing performed in dedicated thread
void AssignWindowThreadId(RWebWindow &win)
Assign thread id for window Required in case of external process events.
std::unique_ptr< THttpServer > fServer
! central communication with the all used displays
std::string GetUrl(const RWebWindow &win, bool remote=false)
Provide URL address to access specified window from inside or from remote.
bool CreateServer(bool with_http=false)
Creates http server, if required - with real http engine (civetweb) One could configure concrete HTTP...
RWebWindowsManager()
window manager constructor Required here for correct usage of unique_ptr<THttpServer>
int WaitFor(RWebWindow &win, WebWindowWaitFunc_t check, bool timed=false, double tm=-1)
Waits until provided check function or lambdas returns non-zero value Regularly calls WebWindow::Sync...
std::recursive_mutex fMutex
! main mutex, used for window creations
unsigned fIdCnt
! counter for identifiers
unsigned ShowWindow(RWebWindow &win, const RWebDisplayArgs &args)
Show window in specified location, see Show() method for more details.
std::string fAddr
! HTTP address of the server
bool fUseSenderThreads
! use extra threads for sending data from RWebWindow to clients
void Terminate()
Terminate http server and ROOT application.
~RWebWindowsManager()
window manager destructor Required here for correct usage of unique_ptr<THttpServer>
THttpServer * GetServer() const
Returns THttpServer instance.
WebWindowShowCallback_t fShowCallback
! function called for each RWebWindow::Show call
static void AssignMainThrd()
Re-assigns main thread id Normally main thread id recognized at the moment when library is loaded It ...
std::unique_ptr< TExec > fAssgnExec
! special exec to assign thread id via ProcessEvents
bool IsUseHttpThread() const
Returns true if http server use special thread for requests processing (default off)
static bool IsMainThrd()
Returns true when called from main process Main process recognized at the moment when library is load...
static std::shared_ptr< RWebWindowsManager > & Instance()
Returns default window manager Used to display all standard ROOT elements like TCanvas or TFitPanel.
bool fUseHttpThrd
! use special thread for THttpServer
void Unregister(RWebWindow &win)
Release all references to specified window Called from RWebWindow destructor.
float fLaunchTmout
! timeout in seconds to start browser process, default 30s
bool fExternalProcessEvents
! indicate that there are external process events engine
std::shared_ptr< RWebWindow > CreateWindow()
Creates new window To show window, RWebWindow::Show() have to be called.
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
Bool_t Connect(const char *signal, const char *receiver_class, void *receiver, const char *slot)
Non-static method is used to connect from the signal of this object to the receiver slot.
Definition TQObject.cxx:869
Bool_t Disconnect(const char *signal=0, void *receiver=0, const char *slot=0)
Disconnects signal of this object from slot of receiver.
static const TString & GetDataDir()
Get the data directory in the installation. Static utility function.
Definition TROOT.cxx:2979
virtual void SetSeed(ULong_t seed=0)
Set the random generator seed.
Definition TRandom.cxx:608
virtual Double_t Rndm()
Machine independent random number generator.
Definition TRandom.cxx:552
virtual UInt_t Integer(UInt_t imax)
Returns a random integer uniformly distributed on the interval [ 0, imax-1 ].
Definition TRandom.cxx:360
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
const char * Data() const
Definition TString.h:369
TString & Append(const char *cs)
Definition TString.h:564
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2336
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2314
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1274
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1663
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:419
static void SingleShot(Int_t milliSec, const char *receiver_class, void *receiver, const char *method)
This static function calls a slot after a given time interval.
Definition TTimer.cxx:256
RLogChannel & WebGUILog()
Log channel for WebGUI diagnostics.
std::function< int(double)> WebWindowWaitFunc_t
function signature for waiting call-backs Such callback used when calling thread need to waits for so...