17#include "RConfigure.h"
45using namespace std::string_literals;
61 static std::map<std::string, std::unique_ptr<RWebDisplayHandle::Creator>> sMap;
74 auto search =
m.find(
name);
75 if (search ==
m.end()) {
77 if (libname ==
"ChromeCreator") {
78 m.emplace(
name, std::make_unique<ChromeCreator>(
name ==
"edge"));
79 }
else if (libname ==
"FirefoxCreator") {
80 m.emplace(
name, std::make_unique<FirefoxCreator>());
81 }
else if (libname ==
"BrowserCreator") {
82 m.emplace(
name, std::make_unique<BrowserCreator>(
false));
83 }
else if (!libname.empty()) {
87 search =
m.find(
name);
90 if (search !=
m.end())
91 return search->second;
93 static std::unique_ptr<RWebDisplayHandle::Creator> dummy;
116 RWebBrowserHandle(
const std::string &url,
const std::string &tmpdir,
const std::string &tmpfile,
const std::string &dump) :
131 gSystem->Exec((
"taskkill /F /PID "s + std::to_string(
fPid) +
" >NUL 2>NUL").c_str());
132 std::string rmdir =
"rmdir /S /Q ", rmfile =
"del /F ";
136 std::string rmdir =
"rm -rf ", rmfile =
"rm -f ";
156 if (exec.find(
"$url") == std::string::npos) {
159 fExec = exec +
" $url";
161 fExec = exec +
" $url &";
165 auto pos = exec.find(
" ");
166 if (pos != std::string::npos)
167 fProg = exec.substr(0, pos);
169 }
else if (
gSystem->InheritsFrom(
"TMacOSXSystem")) {
170 fExec =
"open \'$url\'";
171 }
else if (
gSystem->InheritsFrom(
"TWinNTSystem")) {
172 fExec =
"start $url";
174 fExec =
"xdg-open \'$url\' &";
183 if (nexttry.empty() || !
fProg.empty())
188 fProg = std::regex_replace(nexttry, std::regex(
"%20"),
" ");
195 if (!check_std_paths)
199 std::string ProgramFiles =
gSystem->Getenv(
"ProgramFiles");
200 auto pos = ProgramFiles.find(
" (x86)");
201 if (pos != std::string::npos)
202 ProgramFiles.erase(pos, 6);
203 std::string ProgramFilesx86 =
gSystem->Getenv(
"ProgramFiles(x86)");
205 if (!ProgramFiles.empty())
206 TestProg(ProgramFiles + nexttry,
false);
207 if (!ProgramFilesx86.empty())
208 TestProg(ProgramFilesx86 + nexttry,
false);
215std::unique_ptr<RWebDisplayHandle>
223 std::cout <<
"New web window: " << url << std::endl;
224 return std::make_unique<RWebBrowserHandle>(url,
"",
"",
"");
235 exec =
"$prog $url &";
240 std::string swidth = std::to_string(args.
GetWidth() > 0 ? args.
GetWidth() : 800),
242 sposx = std::to_string(args.
GetX() >= 0 ? args.
GetX() : 0),
243 sposy = std::to_string(args.
GetY() >= 0 ? args.
GetY() : 0);
252 if (((url.find(
"token=") != std::string::npos) || (url.find(
"key=") != std::string::npos)) && !args.
IsBatchMode() && !args.
IsHeadless()) {
253 TString filebase =
"root_start_";
255 auto f =
gSystem->TempFileName(filebase,
nullptr,
".html");
262 std::string content = std::regex_replace(
264 "<html lang=\"en\">\n"
266 " <meta charset=\"utf-8\">\n"
267 " <meta http-equiv=\"refresh\" content=\"0;url=$url\"/>\n"
268 " <title>Opening ROOT widget</title>\n"
272 " This page should redirect you to a ROOT widget. If it doesn't,\n"
273 " <a href=\"$url\">click here to go to ROOT</a>.\n"
276 "</html>\n", std::regex(
"\\$url"), url);
278 if (fwrite(content.c_str(), 1, content.length(),
f) != content.length())
284 tmpfile = filebase.
Data();
286 url =
"file://"s + tmpfile;
290 if (!tmpfile.empty())
291 gSystem->Unlink(tmpfile.c_str());
297 exec = std::regex_replace(exec, std::regex(
"\\$rootetcdir"),
TROOT::GetEtcDir().Data());
298 exec = std::regex_replace(exec, std::regex(
"\\$url"), url);
299 exec = std::regex_replace(exec, std::regex(
"\\$width"), swidth);
300 exec = std::regex_replace(exec, std::regex(
"\\$height"), sheight);
301 exec = std::regex_replace(exec, std::regex(
"\\$posx"), sposx);
302 exec = std::regex_replace(exec, std::regex(
"\\$posy"), sposy);
304 if (exec.compare(0,5,
"fork:") == 0) {
306 if (!tmpfile.empty())
307 gSystem->Unlink(tmpfile.c_str());
317 if (!fargs || (fargs->GetLast()<=0)) {
318 if (!tmpfile.empty())
319 gSystem->Unlink(tmpfile.c_str());
324 std::vector<char *> argv;
325 argv.push_back((
char *)
fProg.c_str());
326 for (
Int_t n = 0;
n <= fargs->GetLast(); ++
n)
327 argv.push_back((
char *)fargs->At(
n)->GetName());
328 argv.push_back(
nullptr);
333 int status = posix_spawn(&pid, argv[0],
nullptr,
nullptr, argv.data(),
nullptr);
335 if (!tmpfile.empty())
336 gSystem->Unlink(tmpfile.c_str());
343 return std::make_unique<RWebBrowserHandle>(url, rmdir, tmpfile, pid);
348 if (!tmpfile.empty())
349 gSystem->Unlink(tmpfile.c_str());
355 exec =
"wmic process call create '"s +
gSystem->UnixPathName(
fProg.c_str()) + exec +
"' | find \"ProcessId\" "s;
356 std::string process_id =
gSystem->GetFromPipe(exec.c_str()).Data();
357 std::stringstream ss(process_id);
361 ss >> tmp >>
c >> pid;
364 if (!tmpfile.empty())
365 gSystem->Unlink(tmpfile.c_str());
371 return std::make_unique<RWebBrowserHandle>(url, rmdir, tmpfile, pid);
377 if (exec.rfind(
"&") == exec.length() - 1) {
380 exec.resize(exec.length() - 1);
382 std::vector<char *> argv;
383 std::string firstarg =
fProg;
384 auto slashpos = firstarg.find_last_of(
"/\\");
385 if (slashpos != std::string::npos)
386 firstarg.erase(0, slashpos + 1);
387 argv.push_back((
char *)firstarg.c_str());
390 for (
Int_t n = 1;
n <= fargs->GetLast(); ++
n)
391 argv.push_back((
char *)fargs->At(
n)->GetName());
392 argv.push_back(
nullptr);
396 _spawnv(_P_NOWAIT,
gSystem->UnixPathName(
fProg.c_str()), argv.data());
398 return std::make_unique<RWebBrowserHandle>(url, rmdir, tmpfile,
""s);
401 std::string prog =
"\""s +
gSystem->UnixPathName(
fProg.c_str()) +
"\""s;
406 std::string prog = std::regex_replace(
fProg, std::regex(
" "),
"\\ ");
408 std::string prog =
fProg;
413 exec = std::regex_replace(exec, std::regex(
"\\$prog"), prog);
417 if (!redirect.empty()) {
418 auto p = exec.length();
419 if (exec.rfind(
"&") == p-1) --p;
420 exec.insert(p,
" >"s + redirect +
" "s);
428 if (!redirect.empty()) {
431 gSystem->Unlink(redirect.c_str());
434 return std::make_unique<RWebBrowserHandle>(url, rmdir, tmpfile, dump_content);
453 TestProg(
"\\Microsoft\\Edge\\Application\\msedge.exe",
true);
455 TestProg(
"\\Google\\Chrome\\Application\\chrome.exe",
true);
458 TestProg(
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome");
462 TestProg(
"/usr/bin/chromium-browser");
463 TestProg(
"/usr/bin/chrome-browser");
464 TestProg(
"/usr/bin/google-chrome-stable");
470 fHeadlessExec =
gEnv->GetValue((
fEnvPrefix +
"Headless").c_str(),
"$prog --headless --disable-gpu $geometry \"$url\" --dump-dom &");
471 fExec =
gEnv->GetValue((
fEnvPrefix +
"Interactive").c_str(),
"$prog $geometry --new-window --app=$url &");
474 bool use_normal =
true;
480 fBatchExec =
gEnv->GetValue((
fEnvPrefix +
"Batch").c_str(),
"$prog --headless --no-sandbox --no-zygote --disable-extensions --disable-gpu --disable-audio-output $geometry $url");
481 fHeadlessExec =
gEnv->GetValue((
fEnvPrefix +
"Headless").c_str(),
"$prog --headless --no-sandbox --no-zygote --disable-extensions --disable-gpu --disable-audio-output $geometry \'$url\' --dump-dom >/dev/null &");
484 fBatchExec =
gEnv->GetValue((
fEnvPrefix +
"Batch").c_str(),
"$prog --headless=new --no-sandbox --no-zygote --disable-extensions --disable-gpu --disable-audio-output $geometry $url");
485 fHeadlessExec =
gEnv->GetValue((
fEnvPrefix +
"Headless").c_str(),
"$prog --headless=new --no-sandbox --no-zygote --disable-extensions --disable-gpu --disable-audio-output $geometry \'$url\' &");
487 fExec =
gEnv->GetValue((
fEnvPrefix +
"Interactive").c_str(),
"$prog $geometry --new-window --app=\'$url\' >/dev/null 2>/dev/null &");
506 geometry.append(
"--window-position="s + std::to_string(args.
GetX() >= 0 ? args.
GetX() : 0) +
","s +
507 std::to_string(args.
GetY() >= 0 ? args.
GetY() : 0));
515 exec = std::regex_replace(exec, std::regex(
"\\$geometry"),
geometry);
524 std::string rmdir, profile_arg;
526 if (exec.find(
"$profile") == std::string::npos)
529 const char *chrome_profile =
gEnv->GetValue((
fEnvPrefix +
"Profile").c_str(),
"");
530 if (chrome_profile && *chrome_profile) {
531 profile_arg = chrome_profile;
534 profile_arg =
gSystem->TempDirectory();
540 if (!profile_arg.empty() && (profile_arg[profile_arg.length()-1] !=
slash))
541 profile_arg +=
slash;
542 profile_arg +=
"root_chrome_profile_"s + std::to_string(
gRandom->Integer(0x100000));
547 exec = std::regex_replace(exec, std::regex(
"\\$profile"), profile_arg);
561 TestProg(
"\\Mozilla Firefox\\firefox.exe",
true);
564 TestProg(
"/Applications/Firefox.app/Contents/MacOS/firefox");
574 fBatchExec =
gEnv->GetValue(
"WebGui.FirefoxBatch",
"$prog -headless -no-remote $profile $url");
575 fHeadlessExec =
gEnv->GetValue(
"WebGui.FirefoxHeadless",
"$prog -headless -no-remote $profile $url &");
576 fExec =
gEnv->GetValue(
"WebGui.FirefoxInteractive",
"$prog -no-remote $profile $geometry $url &");
578 fBatchExec =
gEnv->GetValue(
"WebGui.FirefoxBatch",
"$prog --headless --private-window -no-remote $profile $url");
579 fHeadlessExec =
gEnv->GetValue(
"WebGui.FirefoxHeadless",
"fork:--headless --private-window -no-remote $profile $url");
580 fExec =
gEnv->GetValue(
"WebGui.FirefoxInteractive",
"$rootetcdir/runfirefox.sh $cleanup_profile $prog -no-remote $profile $geometry -url \'$url\' &");
593 exec = std::regex_replace(exec, std::regex(
"\\$geometry"),
geometry);
601 std::string rmdir, profile_arg;
603 if (exec.find(
"$profile") == std::string::npos)
606 const char *ff_profile =
gEnv->GetValue(
"WebGui.FirefoxProfile",
"");
607 const char *ff_profilepath =
gEnv->GetValue(
"WebGui.FirefoxProfilePath",
"");
608 Int_t ff_randomprofile =
gEnv->GetValue(
"WebGui.FirefoxRandomProfile", (
Int_t) 1);
609 if (ff_profile && *ff_profile) {
610 profile_arg =
"-P "s + ff_profile;
611 }
else if (ff_profilepath && *ff_profilepath) {
612 profile_arg =
"-profile "s + ff_profilepath;
613 }
else if (ff_randomprofile > 0) {
616 std::string profile_dir =
gSystem->TempDirectory();
623 if (!profile_dir.empty() && (profile_dir[profile_dir.length()-1] !=
slash))
624 profile_dir +=
slash;
625 profile_dir +=
"root_ff_profile_"s + std::to_string(
gRandom->Integer(0x100000));
627 profile_arg =
"-profile "s + profile_dir;
629 if (
gSystem->mkdir(profile_dir.c_str()) == 0) {
632 std::ofstream user_js(profile_dir +
"/user.js", std::ios::trunc);
635 user_js <<
"user_pref(\"datareporting.policy.dataSubmissionPolicyAcceptedVersion\", 2);" << std::endl;
636 user_js <<
"user_pref(\"datareporting.policy.dataSubmissionPolicyNotifiedTime\", \"1635760572813\");" << std::endl;
639 user_js <<
"user_pref(\"browser.tabs.closeWindowWithLastTab\", true);" << std::endl;
640 user_js <<
"user_pref(\"dom.allow_scripts_to_close_windows\", true);" << std::endl;
641 user_js <<
"user_pref(\"browser.sessionstore.resume_from_crash\", false);" << std::endl;
645 user_js <<
"user_pref(\"browser.dom.window.dump.enabled\", true);" << std::endl;
648 user_js <<
"user_pref(\"datareporting.policy.firstRunURL\", \"\");" << std::endl;
650 user_js <<
"user_pref(\"toolkit.legacyUserProfileCustomizations.stylesheets\", true);" << std::endl;
652 user_js <<
"user_pref(\"browser.tabs.inTitlebar\", 0);" << std::endl;
654 std::ofstream times_json(profile_dir +
"/times.json", std::ios::trunc);
655 times_json <<
"{" << std::endl;
656 times_json <<
" \"created\": 1699968480952," << std::endl;
657 times_json <<
" \"firstUse\": null" << std::endl;
658 times_json <<
"}" << std::endl;
659 if (
gSystem->mkdir((profile_dir +
"/chrome").c_str()) == 0) {
660 std::ofstream
style(profile_dir +
"/chrome/userChrome.css", std::ios::trunc);
662 style <<
"#TabsToolbar { visibility: collapse; }" << std::endl;
664 style <<
"#nav-bar, #urlbar-container, #searchbar { visibility: collapse !important; }" << std::endl;
673 exec = std::regex_replace(exec, std::regex(
"\\$profile"), profile_arg);
675 if (exec.find(
"$cleanup_profile") != std::string::npos) {
676 if (rmdir.empty()) rmdir =
"<dummy>";
677 exec = std::regex_replace(exec, std::regex(
"\\$cleanup_profile"), rmdir);
698 auto &qt6 =
FindCreator(
"qt6",
"libROOTQt6WebDisplay");
699 if (qt6 && qt6->IsActive())
703 auto &qt5 =
FindCreator(
"qt5",
"libROOTQt5WebDisplay");
704 if (qt5 && qt5->IsActive())
708 auto &cef =
FindCreator(
"cef",
"libROOTCefDisplay");
709 if (cef && cef->IsActive())
726 std::unique_ptr<RWebDisplayHandle> handle;
731 auto try_creator = [&](std::unique_ptr<Creator> &creator) {
732 if (!creator || !creator->IsActive())
734 handle = creator->Display(args);
735 return handle ?
true :
false;
740 has_qt5web =
false, has_qt6web =
false, has_cefweb =
false;
755 if (try_creator(
FindCreator(
"qt6",
"libROOTQt6WebDisplay")))
760 if (try_creator(
FindCreator(
"qt5",
"libROOTQt5WebDisplay")))
765 if (try_creator(
FindCreator(
"cef",
"libROOTCefDisplay")))
774 bool handleAsNative =
779 if (try_creator(
FindCreator(
"edge",
"ChromeCreator")))
785 if (try_creator(
FindCreator(
"chrome",
"ChromeCreator")))
790 if (try_creator(
FindCreator(
"firefox",
"FirefoxCreator")))
801 std::unique_ptr<Creator> creator = std::make_unique<BrowserCreator>(
false, args.
GetCustomExec());
802 try_creator(creator);
804 try_creator(
FindCreator(
"browser",
"BrowserCreator"));
842 bool detected =
false;
845 if (
h1 &&
h1->IsActive()) {
851 auto &h2 =
FindCreator(
"firefox",
"FirefoxCreator");
852 if (h2 && h2->IsActive()) {
861 if (h3 && h3->IsActive()) {
872 return h1 &&
h1->IsActive();
876 auto &h2 =
FindCreator(
"firefox",
"FirefoxCreator");
877 return h2 && h2->IsActive();
883 return h3 && h3->IsActive();
912bool RWebDisplayHandle::ProduceImages(
const std::string &fname,
const std::vector<std::string> &jsons,
const std::vector<int> &widths,
const std::vector<int> &heights,
const char *batch_file)
917 auto EndsWith = [&fname](
const std::string &suffix) {
918 std::string _fname = fname;
919 std::transform(_fname.begin(), _fname.end(), _fname.begin(), ::tolower);
920 return (_fname.length() > suffix.length()) ? (0 == _fname.compare(_fname.length() - suffix.length(), suffix.length(), suffix)) :
false;
923 std::vector<std::string> fnames;
925 if (!EndsWith(
".pdf")) {
926 std::string farg = fname;
928 bool has_quialifier = farg.find(
"%") != std::string::npos;
930 if (!has_quialifier && (jsons.size() > 1)) {
931 farg.insert(farg.rfind(
"."),
"%d");
932 has_quialifier =
true;
935 for (
unsigned n = 0;
n < jsons.size();
n++) {
936 if (has_quialifier) {
938 fnames.emplace_back(expand_name.Data());
940 fnames.emplace_back(farg);
945 if (EndsWith(
".json")) {
946 for (
unsigned n = 0;
n < jsons.size(); ++
n) {
947 std::ofstream ofs(fnames[
n]);
953 const char *jsrootsys =
gSystem->Getenv(
"JSROOTSYS");
957 if (
gSystem->ExpandPathName(jsrootsysdflt)) {
961 jsrootsys = jsrootsysdflt.
Data();
973 std::string draw_kind;
975 if (EndsWith(
".pdf"))
977 else if (EndsWith(
"shot.png") && (jsons.size() == 1))
978 draw_kind = isChromeBased ?
"draw" :
"png";
979 else if (EndsWith(
".svg"))
981 else if (EndsWith(
".png"))
983 else if (EndsWith(
".jpg") || EndsWith(
".jpeg"))
985 else if (EndsWith(
".webp"))
990 if (!batch_file || !*batch_file)
991 batch_file =
"/js/files/canv_batch.htm";
994 if (
gSystem->ExpandPathName(origin)) {
1000 if (filecont.empty()) {
1005 int max_width = 0, max_height = 0, page_margin = 10;
1006 for (
auto &
w : widths)
1009 for (
auto &
h : heights)
1017 for (
auto &json : jsons) {
1018 mains.append(mains.empty() ?
"[" :
", ");
1023 if (strstr(jsrootsys,
"http://") || strstr(jsrootsys,
"https://") || strstr(jsrootsys,
"file://"))
1024 filecont = std::regex_replace(filecont, std::regex(
"\\$jsrootsys"), jsrootsys);
1026 filecont = std::regex_replace(filecont, std::regex(
"\\$jsrootsys"),
"file://"s + jsrootsys);
1028 filecont = std::regex_replace(filecont, std::regex(
"\\$page_margin"), std::to_string(page_margin) +
"px");
1029 filecont = std::regex_replace(filecont, std::regex(
"\\$page_width"), std::to_string(max_width + 2*page_margin) +
"px");
1030 filecont = std::regex_replace(filecont, std::regex(
"\\$page_height"), std::to_string(max_height + 2*page_margin) +
"px");
1032 filecont = std::regex_replace(filecont, std::regex(
"\\$draw_kind"), draw_kind);
1033 filecont = std::regex_replace(filecont, std::regex(
"\\$draw_widths"), jsonw.Data());
1034 filecont = std::regex_replace(filecont, std::regex(
"\\$draw_heights"), jsonh.Data());
1035 filecont = std::regex_replace(filecont, std::regex(
"\\$draw_objects"), mains);
1038 if (draw_kind ==
"draw") {
1039 if (!isChromeBased) {
1043 }
else if (isChromeBased || isFirefox) {
1044 dump_name =
"canvasdump";
1045 FILE *df =
gSystem->TempFileName(dump_name);
1050 fputs(
"placeholder", df);
1056 static bool chrome_tmp_workaround =
false;
1069 R__LOG_DEBUG(0,
WebGUILog()) <<
"Using file content_len " << filecont.length() <<
" to produce batch images " << fname;
1072 tmp_name =
"canvasbody";
1073 FILE *hf =
gSystem->TempFileName(tmp_name);
1078 fputs(filecont.c_str(), hf);
1081 html_name = tmp_name +
".html";
1083 if (chrome_tmp_workaround) {
1084 std::string homedir =
gSystem->GetHomeDirectory();
1085 auto pos = html_name.
Last(
'/');
1089 html_name.
Remove(0, pos);
1090 html_name = homedir + html_name.
Data();
1094 std::ofstream ofs(html_name.
Data(), std::ofstream::out);
1107 R__LOG_DEBUG(0,
WebGUILog()) <<
"Using " << html_name <<
" content_len " << filecont.length() <<
" to produce batch images " << fname;
1115 args.
SetSize(widths[0], heights[0]);
1117 if (draw_kind ==
"draw") {
1119 TString tgtfilename = fname.c_str();
1120 if (!
gSystem->IsAbsoluteFileName(tgtfilename.
Data()))
1121 gSystem->PrependPathName(
gSystem->WorkingDirectory(), tgtfilename);
1123 wait_file_name = tgtfilename;
1125 if (EndsWith(
".pdf"))
1133 }
else if (isFirefox) {
1137 }
else if (isChromeBased) {
1155 if (html_name.
Length() > 0)
1158 if (!wait_file_name.
IsNull() &&
gSystem->AccessPathName(wait_file_name.
Data())) {
1163 if (draw_kind !=
"draw") {
1165 auto dumpcont = handle->GetContent();
1167 if ((dumpcont.length() > 20) && (dumpcont.length() < 60) && !chrome_tmp_workaround && isChromeBased) {
1170 chrome_tmp_workaround =
true;
1174 if (dumpcont.length() < 100) {
1179 if (draw_kind ==
"svg") {
1181 std::string::size_type p = 0;
1183 for (
auto & fn : fnames) {
1184 auto p1 = dumpcont.find(
"<svg", p);
1185 auto p2 = dumpcont.find(
"</svg></div>", p1 + 4);
1187 std::ofstream ofs(fn);
1188 if ((p1 != std::string::npos) && (p2 != std::string::npos) && (p1 < p2)) {
1189 ofs << dumpcont.substr(p1, p2-p1+6);
1190 ::Info(
"ProduceImage",
"SVG file %s size %d bytes has been created", fn.c_str(), (
int) (p2-p1+6));
1193 ofs <<
"Failure!!!\n" << dumpcont;
1199 std::string::size_type p = 0;
1201 for (
auto &fn : fnames) {
1203 auto p1 = dumpcont.find(
";base64,", p);
1204 auto p2 = dumpcont.find(
"></div>", p1 + 4);
1207 if ((p1 != std::string::npos) && (p2 != std::string::npos) && (p1 < p2)) {
1209 auto base64 = dumpcont.substr(p1+8, p2-p1-9);
1212 std::ofstream ofs(fn, std::ios::binary);
1213 ofs.write(binary.Data(), binary.Length());
1215 ::Info(
"ProduceImage",
"Image file %s size %d bytes has been created", fn.c_str(), (
int) binary.Length());
1223 }
else if (EndsWith(
".pdf")) {
1224 ::Info(
"ProduceImage",
"PDF file %s with %d pages has been created", fname.c_str(), (
int) jsons.size());
1227 if (fnames.size() == 1)
true
Register systematic variations for multiple existing columns using auto-generated tags.
#define R__LOG_ERROR(...)
#define R__LOG_DEBUG(DEBUGLEVEL,...)
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void w
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t height
R__EXTERN TRandom * gRandom
R__EXTERN TSystem * gSystem
RWebBrowserHandle(const std::string &url, const std::string &tmpdir, const std::string &tmpfile, browser_process_id pid)
std::string fTmpDir
temporary directory to delete at the end
RWebBrowserHandle(const std::string &url, const std::string &tmpdir, const std::string &tmpfile, const std::string &dump)
std::string fTmpFile
temporary file to remove
~RWebBrowserHandle() override
Holds different arguments for starting browser with RWebDisplayHandle::Display() method.
std::string GetBrowserName() const
Returns configured browser name.
EBrowserKind GetBrowserKind() const
returns configured browser kind, see EBrowserKind for supported values
const std::string & GetRedirectOutput() const
get file name to which web browser output should be redirected
void SetStandalone(bool on=true)
Set standalone mode for running browser, default on When disabled, normal browser window (or just tab...
void SetBatchMode(bool on=true)
set batch mode
RWebDisplayArgs & SetSize(int w, int h)
set preferable web window width and height
RWebDisplayArgs & SetUrl(const std::string &url)
set window url
int GetWidth() const
returns preferable web window width
RWebDisplayArgs & SetPageContent(const std::string &cont)
set window url
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
RWebDisplayArgs & SetBrowserKind(const std::string &kind)
Set browser kind as string argument.
std::string GetCustomExec() const
returns custom executable to start web browser
void SetExtraArgs(const std::string &args)
set extra command line arguments for starting web browser command
bool IsBatchMode() const
returns batch mode
bool IsHeadless() const
returns headless mode
@ kOn
web display enable, first try use embed displays like Qt or CEF, then native browsers and at the end ...
@ kFirefox
Mozilla Firefox browser.
@ kNative
either Chrome or Firefox - both support major functionality
@ kLocal
either CEF or Qt5 - both runs on local display without real http server
@ kServer
indicates that ROOT runs as server and just printouts window URL, browser should be started by the us...
@ kOff
disable web display, do not start any browser
@ kCEF
Chromium Embedded Framework - local display with CEF libs.
@ kQt5
Qt5 QWebEngine libraries - Chromium code packed in qt5.
@ kQt6
Qt6 QWebEngine libraries - Chromium code packed in qt6.
@ kCustom
custom web browser, execution string should be provided
@ kChrome
Google Chrome browser.
@ kEdge
Microsoft Edge browser (Windows only)
void SetRedirectOutput(const std::string &fname="")
specify file name to which web browser output should be redirected
void SetHeadless(bool on=true)
set 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
bool IsLocalDisplay() const
returns true if local display like CEF or Qt5 QWebEngine should be used
std::string fProg
browser executable
std::string fBatchExec
batch execute line
std::string fHeadlessExec
headless execute line
std::unique_ptr< RWebDisplayHandle > Display(const RWebDisplayArgs &args) override
Display given URL in web browser.
virtual void ProcessGeometry(std::string &, const RWebDisplayArgs &)
std::string fExec
standard execute line
void TestProg(const std::string &nexttry, bool check_std_paths=false)
Check if browser executable exists and can be used.
BrowserCreator(bool custom=true, const std::string &exec="")
Class to handle starting of web-browsers like Chrome or Firefox.
virtual std::string MakeProfile(std::string &, bool)
ChromeCreator(bool is_edge=false)
Constructor.
void ProcessGeometry(std::string &, const RWebDisplayArgs &) override
Replace $geometry placeholder with geometry settings Also RWebDisplayArgs::GetExtraArgs() are appende...
std::string MakeProfile(std::string &exec, bool) override
Handle profile argument.
FirefoxCreator()
Constructor.
std::string MakeProfile(std::string &exec, bool batch) override
Create Firefox profile to run independent browser window.
void ProcessGeometry(std::string &, const RWebDisplayArgs &) override
Process window geometry for Firefox.
static std::map< std::string, std::unique_ptr< Creator > > & GetMap()
Static holder of registered creators of web displays.
static bool CheckIfCanProduceImages(RWebDisplayArgs &args)
Checks if configured browser can be used for image production.
static bool ProduceImages(const std::string &fname, const std::vector< std::string > &jsons, const std::vector< int > &widths, const std::vector< int > &heights, const char *batch_file=nullptr)
Produce image file(s) using JSON data as source Invokes JSROOT drawing functionality in headless brow...
void SetContent(const std::string &cont)
set content
RWebDisplayHandle(const std::string &url)
constructor
static bool ProduceImage(const std::string &fname, const std::string &json, int width=800, int height=600, const char *batch_file=nullptr)
Produce image file using JSON data as source Invokes JSROOT drawing functionality in headless browser...
static bool CanProduceImages(const std::string &browser="")
Returns true if image production for specified browser kind is supported If browser not specified - u...
static bool NeedHttpServer(const RWebDisplayArgs &args)
Check if http server required for display.
static bool DisplayUrl(const std::string &url)
Display provided url in configured web browser.
static std::unique_ptr< RWebDisplayHandle > Display(const RWebDisplayArgs &args)
Create web display.
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.
static TString Decode(const char *data)
Decode a base64 string date into a generic TString.
static TString ToJSON(const T *obj, Int_t compact=0, const char *member_name=nullptr)
@ kNoSpaces
no new lines plus remove all spaces around "," and ":" symbols
static char * ReadFileContent(const char *filename, Int_t &len)
Reads content of file from the disk.
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
static const TString & GetDataDir()
Get the data directory in the installation. Static utility function.
void Clear()
Clear string without changing its capacity.
const char * Data() const
Ssiz_t Last(char c) const
Find last occurrence of a character c.
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
TString & Remove(Ssiz_t pos)
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
ROOT::Experimental::RLogChannel & WebGUILog()
Log channel for WebGUI diagnostics.