mod_chromium.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. #if (defined _WIN32 || defined _WIN64)
  2. #include "stdafx.h"
  3. #include <Windows.h>
  4. #include <WinUser.h>
  5. #endif
  6. #include "baseEx.h"
  7. #include "CWebsocketServer.h"
  8. #include "mod_chromium.h"
  9. #include "base64.h"
  10. #include "CModTools.h"
  11. #include "cJSON.h"
  12. #include "SpIni.h"
  13. #include "CSocketClient.h"
  14. #include "processControl.h"
  15. #include <boost/chrono.hpp>
  16. #include <boost/bind.hpp>
  17. #include "path.h"
  18. #include "guitask/guitask.h"
  19. #include "EventCode.h"
  20. #include "../mod_upload/Upload_client_g.h"
  21. #define COMPKEY_TERMINATE ((UINT_PTR) 0)
  22. #define COMPKEY_STATUS ((UINT_PTR) 1)
  23. #define COMPKEY_JOBOBJECT ((UINT_PTR) 2)
  24. #define LOG_EVT_SELFCHECK_ASSISTANTCHANNEL_IDLE 0x50500001 //协助通道重启
  25. //#define EVENT_UKEY_PULLOUT 0x21000008 // 证书拔出 0x21000008 1 检测到维护证书拔出,用于驱动本地维护状态
  26. #define LOG_EVT_BEGIN_CAMERA_CONFIG 0x21D00001
  27. #define LOG_EVT_END_CAMERA_CONFIG 0x21D00002
  28. #define MSG_EVT_STARTACTIVECAPTURE 0x31400001 //开始主动活体
  29. #define MSG_EVT_STOPACTIVECAPTURE 0x31400002 //停止主动活体
  30. #define LOG_EVT_SHOWACTIVECAPTUREMSG 0x31400003 //显示主动活体提示消息
  31. #define CLIENT_MANAGER_PATH "c:\\Program Files\\CmbWinPad\\CmbWinPad.exe"
  32. namespace Chromium {
  33. CChromiumEntity::CChromiumEntity() :m_pWsServer(NULL), m_iTcpBridgePort(4504), m_pTimerListener(NULL)
  34. {
  35. DbgEx("CChromiumEntity constructor");
  36. boost::thread(boost::bind(&CChromiumEntity::CefClintNotify, this)).detach(); //后台自动运行
  37. }
  38. CChromiumEntity::~CChromiumEntity()
  39. {
  40. if (NULL != m_pWsServer)
  41. {
  42. free(m_pWsServer);
  43. m_pWsServer = NULL;
  44. }
  45. //DeleteCriticalSection(&g_csInvokFreeRDP);
  46. }
  47. #if (defined _WIN32 || defined _WIN64)
  48. void CChromiumEntity::JobNotify() {
  49. TCHAR sz[2000] = _T("");
  50. BOOL fDone = FALSE;
  51. while (!fDone) {
  52. DWORD dwBytesXferred;
  53. ULONG_PTR CompKey;
  54. LPOVERLAPPED po;
  55. GetQueuedCompletionStatus(m_hIOCP, &dwBytesXferred, &CompKey, &po, INFINITE);
  56. fDone = (CompKey == COMPKEY_TERMINATE);
  57. if (CompKey == COMPKEY_JOBOBJECT) {
  58. switch (dwBytesXferred) {
  59. case JOB_OBJECT_MSG_END_OF_JOB_TIME:
  60. Dbg("Job time limit reached");
  61. break;
  62. case JOB_OBJECT_MSG_END_OF_PROCESS_TIME:
  63. Dbg("Job process (Id=%d) time limit reached", po);
  64. break;
  65. case JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT:
  66. Dbg("Too many active processes in job");
  67. break;
  68. case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
  69. Dbg("Job contains no active processes");
  70. break;
  71. case JOB_OBJECT_MSG_NEW_PROCESS:
  72. Dbg("New process (Id=%d) in Job", po);
  73. break;
  74. case JOB_OBJECT_MSG_EXIT_PROCESS:
  75. Dbg("Process (Id=%d) terminated", po);
  76. break;
  77. case JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS:
  78. Dbg("Process (Id=%d) terminated abnormally", po);
  79. break;
  80. case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT:
  81. Dbg("Process (Id=%d) exceeded memory limit", po);
  82. break;
  83. case JOB_OBJECT_MSG_JOB_MEMORY_LIMIT:
  84. Dbg("Process (Id=%d) exceeded job memory limit", po);
  85. break;
  86. default:
  87. Dbg("Unknown notification: %d", dwBytesXferred);
  88. break;
  89. }
  90. CompKey = 1;
  91. }
  92. }
  93. }
  94. #endif
  95. void CChromiumEntity::OnPreStart(CAutoArray<CSimpleStringA> strArgs, CSmartPointer<ITransactionContext> pTransactionContext)
  96. {
  97. GetFunction()->GetSystemStaticInfo(m_sysInfo);
  98. ErrorCodeEnum Error;
  99. Error = GetFunction()->StartTcpBridgeServer(m_iTcpBridgePort);
  100. #if (defined _WIN32 || defined _WIN64)
  101. Error = GetFunction()->SubscribeBroadcast("IEBrowser", "CustomerCmd", this, m_uidBrowserListenser);
  102. if (Error != Error_Succeed) {
  103. LOG_TRACE("subscribe browser CustomerCmd failed!");
  104. pTransactionContext->SendAnswer(Error);
  105. }
  106. else
  107. LOG_TRACE("subscribe browser CustomerCmd success!");
  108. #endif
  109. if (Error != Error_Succeed)
  110. {
  111. LOG_TRACE("start tcp bridge server failed!");
  112. pTransactionContext->SendAnswer(Error);
  113. return;
  114. }
  115. CModTools::get_mutable_instance().InitCModTools(this);
  116. CModTools::get_mutable_instance().killAllChromium();
  117. // load all struct define xml & start websocket server
  118. CSimpleStringA strStructPath;
  119. GetFunction()->GetPath("Base", strStructPath);
  120. strStructPath.Append(CSimpleStringA(SPLIT_SLASH_STR) + "res" + SPLIT_SLASH_STR + "StructConfig" + SPLIT_SLASH_STR);
  121. DbgEx("find struct config files in path %s", strStructPath.GetData());
  122. m_pWsServer = new CWebsocketServer(strStructPath, this);
  123. m_pWsServer->run();
  124. try {
  125. chromiumRpcTask::get_mutable_instance().openrpcServer(DEFAULT_CHROMIUM_RPCPORT);
  126. DbgEx("start rpcTask in port %d", DEFAULT_CHROMIUM_RPCPORT);
  127. }
  128. catch (...) {
  129. DbgEx("open rpcTask failed");
  130. }
  131. /*低柜
  132. //LOG_EVT_BEGIN_CAMERA_CONFIG, LOG_EVT_END_CAMERA_CONFIG
  133. Error = GetFunction()->SubscribeLog(m_uidCameraListener, this, Log_Event, Severity_None, Error_IgnoreAll, -1, "CameraConfigManage");
  134. if (Error != Error_Succeed)
  135. LOG_TRACE("subscribe Camera log failed!"); //非必须
  136. */
  137. Error = GetFunction()->SubscribeLog(m_uuidAccessAuth, this, Log_Event, Severity_None, Error_IgnoreAll, -1, "AccessAuthorization");
  138. if (Error != Error_Succeed)
  139. LOG_TRACE("subscribe AccessAuthorization log failed!");
  140. else
  141. LOG_TRACE("subscribe AccessAuthorization success!");
  142. GetFunction()->SubscribeLog(m_uuidAccessAuth, this, Log_Error, Severity_None, Error_IgnoreAll, -1, "AccessAuthorization");
  143. GetFunction()->RegistSysVarEvent("UIState", this);
  144. generateBussinessLimitTimer();
  145. // 按照单屏方式
  146. pTransactionContext->SendAnswer(Error_Succeed);
  147. }
  148. void CChromiumEntity::OnSysVarEvent(const char* pszKey, const char* pszValue, const char* pszOldValue, const char* pszEntityName)
  149. {
  150. if ((_strnicmp(pszKey, "UIState", strlen("UIState")) == 0))
  151. {
  152. if (_strnicmp(pszValue, "M", strlen("M")) == 0)
  153. {
  154. static bool firstEnter = true;
  155. if (firstEnter)
  156. {
  157. firstEnter = false;
  158. Dbg("first Enter main page");
  159. }
  160. }
  161. }
  162. }
  163. void CChromiumEntity::OnPreClose(EntityCloseCauseEnum eCloseCause, CSmartPointer<ITransactionContext> pTransactionContext)
  164. {
  165. if (m_pTimerListener != NULL)
  166. {
  167. GetFunction()->KillTimer(CHROMIUM_TIMER_ID);
  168. delete m_pTimerListener;
  169. m_pTimerListener = NULL;
  170. }
  171. GetFunction()->UnsubscribeBroadcast("IEBrowser");
  172. pTransactionContext->SendAnswer(Error_Succeed);
  173. }
  174. void CChromiumEntity::OnLog(const CAutoArray<CUUID>& SubIDs, const CUUID nLogID, const LogTypeEnum eLogType, const SeverityLevelEnum eLevel,
  175. const DWORD dwSysError, const DWORD dwUserCode, const DWORD dwEntityInstanceID, const WORD wEntityDevelID,
  176. const CAutoArray<DWORD>& Param, const char* pszEntityName, const char* pszModuleName, const char* pszMessage)
  177. {
  178. switch (dwUserCode)
  179. {
  180. case LOG_EVT_BEGIN_CAMERA_CONFIG:
  181. {
  182. auto openRet = CModTools::get_mutable_instance().StartChromiumBrowser(ERR_PAGE_REASON::CameraConfig);
  183. Dbg("show Screen Camera config, open page cameraconfig, %d", openRet.first);
  184. }
  185. break;
  186. case LOG_EVT_END_CAMERA_CONFIG:
  187. Dbg("end show Screen Camera config, close page cameraconfig");
  188. CModTools::get_mutable_instance().killChromiumByName((+PAGE_TYPE::CameraConfig)._to_string());
  189. break;
  190. case EVENT_ACCESSAUTH_SUCCEED:
  191. Dbg("access auth success, open page mainurl");
  192. {
  193. CSystemRunInfo sysruninfo;
  194. GetFunction()->GetSystemRunInfo(sysruninfo);
  195. if (!(sysruninfo.dwBootOption & SystemBootOptionEnum::BootOption_Test))
  196. generateCefclientTimer();//非--test时,才会打开浏览器
  197. }
  198. break;
  199. case ERR_ACCESSAUTH_FAILED:
  200. case ERR_ACCESSAUTH_TIMEOUT:
  201. {
  202. auto openRet = CModTools::get_mutable_instance().StartChromiumBrowser(ERR_PAGE_REASON::breakdown);
  203. Dbg("access failed, open page breakdown, %d", openRet.first);
  204. }
  205. break;
  206. default:
  207. break;
  208. }
  209. }
  210. void CChromiumEntity::OnTerminalManage(const char* pszEntityName, DWORD dwMessageId, DWORD dwMessageSignature, HealthManager::TerminalManager& evt)
  211. {
  212. Dbg("OnTerminalManage : evt.op = %d", evt.op);
  213. switch (evt.op)
  214. {
  215. case 0:
  216. GetFunction()->SetSysVar("TerminalManagerState", "L", true);
  217. {
  218. auto openRet = CModTools::get_mutable_instance().StartChromiumBrowser(ERR_PAGE_REASON::TerminalManagerOff);
  219. Dbg("TerminalManagerState L, open page TerminalManagerOff, %d", openRet.first);
  220. }
  221. break;
  222. case 1:
  223. GetFunction()->SetSysVar("TerminalManagerState", "N", true);
  224. {
  225. Dbg("TerminalManagerState N, try close TerminalManager");
  226. CModTools::get_mutable_instance().killChromiumByName((+PAGE_TYPE::TerminalManager)._to_string());
  227. }
  228. break;
  229. case 2:
  230. GetFunction()->SetSysVar("TerminalManagerState", "K", true);
  231. {
  232. auto openRet = CModTools::get_mutable_instance().StartChromiumBrowser(ERR_PAGE_REASON::TerminalManagerKickOut);
  233. Dbg("TerminalManagerState K, open page TerminalManagerKickOut, %d", openRet.first);
  234. }
  235. break;
  236. case 99:
  237. GetFunction()->SetSysVar("TerminalManagerState", "N", true);
  238. {
  239. Dbg("TerminalManagerState N, try close TerminalManager");
  240. CModTools::get_mutable_instance().killChromiumByName((+PAGE_TYPE::TerminalManager)._to_string());
  241. }
  242. break;
  243. default:
  244. break;
  245. }
  246. }
  247. // 输入为北京时间 输出为北京时间戳
  248. int CChromiumEntity::StandardToStamp(const char* str_time, bool dateOnly)
  249. {
  250. Dbg("StandardToStamp str = %s", str_time);
  251. struct tm stm;
  252. int iY, iM, iD, iH, iMin, iS;
  253. // 检查有效性
  254. if ('-' != str_time[4] || '-' != str_time[7])
  255. {
  256. return 0;
  257. }
  258. memset(&stm, 0, sizeof(stm));
  259. iY = atoi(str_time);
  260. iM = atoi(str_time + 5);
  261. iD = atoi(str_time + 8);
  262. if (dateOnly)
  263. {
  264. iH = 0;
  265. iMin = 0;
  266. iS = 0;
  267. }
  268. else {
  269. iH = atoi(str_time + 11);
  270. iMin = atoi(str_time + 14);
  271. iS = atoi(str_time + 17);
  272. }
  273. stm.tm_year = iY - 1900;
  274. stm.tm_mon = iM - 1;
  275. stm.tm_mday = iD;
  276. stm.tm_hour = iH;
  277. stm.tm_min = iMin;
  278. stm.tm_sec = iS;
  279. /*printf("%d-%0d-%0d %0d:%0d:%0d\n", iY, iM, iD, iH, iMin, iS);*/ //标准时间格式例如:2016:08:02 12:12:30
  280. return (int)mktime(&stm);
  281. }
  282. TradeManageCodeEnum CChromiumEntity::CheckJobLimited() {
  283. /*if (!isOutsidePad())
  284. {
  285. return Undefined;
  286. }*/
  287. CSmartPointer<IConfigInfo> spConfig;
  288. ErrorCodeEnum BootTimeCfgError = GetFunction()->OpenConfig(Config_Run, spConfig);
  289. CSimpleStringA strLastRecordTime = "", strControl = "", strExpirationDate = "";
  290. time_t now = time(0);
  291. localtime(&now);
  292. ErrorCodeEnum errorRead = Error_Succeed;
  293. errorRead = spConfig->ReadConfigValue("Record", "LastRecordTime", strLastRecordTime);
  294. if (errorRead != Error_Succeed)
  295. {
  296. Dbg("Read Record LastRecordTime -> Failed! Maybe LastRecordTime not exist!");
  297. strLastRecordTime = "";
  298. }
  299. errorRead = spConfig->ReadConfigValue("Record", "Control", strControl);
  300. if (errorRead != Error_Succeed)
  301. {
  302. Dbg("Read Record Control -> Failed! Maybe Control not exist!");
  303. strControl = "";
  304. }
  305. errorRead = spConfig->ReadConfigValue("Record", "ExpirationDate", strExpirationDate);
  306. if (errorRead != Error_Succeed)
  307. {
  308. Dbg("Read Record ExpirationDate -> Failed! Maybe ExpirationDate not exist!");
  309. strExpirationDate = "";
  310. }
  311. if (strControl.Compare("on") == 0)
  312. {
  313. // 控制标识为on时,检查过期时间,过期时间之前都设置为启用
  314. if (strExpirationDate == "")
  315. {
  316. Dbg("CheckJobLimited -> on -> strExpirationDate=null ");
  317. CModTools::get_mutable_instance().setLimitReason("");
  318. return TradeManageCodeEnum::Trade;
  319. }
  320. int timestamp_expiration = StandardToStamp(strExpirationDate.Append(" 23:59:59"), false);
  321. if (now < timestamp_expiration)
  322. {
  323. // 过期之前都可以进行交易
  324. Dbg("CheckJobLimited -> on -> strExpirationDate>now ");
  325. CModTools::get_mutable_instance().setLimitReason("");
  326. return TradeManageCodeEnum::Trade;
  327. }
  328. else {
  329. // 过期之后 设置为normal
  330. Dbg("CheckJobLimited -> on -> strExpirationDate<now -> control to normal");
  331. spConfig->WriteConfigValue("Record", "Control", "normal");
  332. strControl = "normal";
  333. Dbg("过期之后 设置为normal");
  334. }
  335. }
  336. if (strControl.Compare("off") == 0)
  337. {
  338. // 展示交易暂停页面
  339. Dbg("CheckJobLimited -> off ");
  340. CModTools::get_mutable_instance().setLimitReason("disabled");
  341. return TradeManageCodeEnum::Disabled;
  342. }
  343. if (strControl.Compare("normal") == 0 || strControl.IsNullOrEmpty())
  344. {
  345. if (strLastRecordTime == "")
  346. {
  347. Dbg("CheckJobLimited -> normal -> strLastRecordTime=null ");
  348. CModTools::get_mutable_instance().setLimitReason("");
  349. return TradeManageCodeEnum::Trade;
  350. }
  351. int timestamp_lastRecordTime = StandardToStamp(strLastRecordTime, true);
  352. if (now < timestamp_lastRecordTime + 3600 * 24 * 2)
  353. {
  354. Dbg("CheckJobLimited -> normal -> now < lastRecordTime + 3600*24*2 ");
  355. CModTools::get_mutable_instance().setLimitReason("");
  356. return TradeManageCodeEnum::Trade;
  357. }
  358. else if (CheckTradeRecord()) {
  359. // 展示交易暂停页面
  360. Dbg("CheckJobLimited -> normal -> now < CheckTradeRecord = true ");
  361. CModTools::get_mutable_instance().setLimitReason("jobuncomplete");
  362. return TradeManageCodeEnum::JobUncomplete;
  363. }
  364. }
  365. // 理论上不会流转到这里来
  366. CModTools::get_mutable_instance().setLimitReason("");
  367. return TradeManageCodeEnum::Trade;
  368. }
  369. bool CChromiumEntity::CheckTradeRecord() {
  370. std::list<int> timeList;
  371. using namespace Upload;
  372. UploadService_ClientBase* pClient = new UploadService_ClientBase(this);
  373. auto rc = pClient->Connect();
  374. if (rc != Error_Succeed)
  375. {
  376. Dbg("connect to Upload entity fail: %d", rc);
  377. }
  378. else
  379. {
  380. UploadService_UploadDateList_Req req = {};
  381. UploadService_UploadDateList_Ans ans = {};
  382. rc = pClient->UploadDateList(req, ans, 10000);
  383. if (rc != Error_Succeed)
  384. {
  385. Dbg("UploadDateList fail from Upload: %d", rc);
  386. }
  387. else
  388. {
  389. Dbg("UploadDateList succeed from Upload");
  390. for (int i = 0; i < ans.uploadDateStr.GetCount(); ++i)
  391. {
  392. CSimpleStringA str = (CSimpleStringA)ans.uploadDateStr[i];
  393. int t = StandardToStamp(ans.uploadDateStr[i], true);
  394. timeList.push_back(t);
  395. }
  396. }
  397. pClient->SafeDelete();
  398. pClient = NULL;
  399. }
  400. // 比较时间戳 登记时间 <= 列表时间 < 今天 返回true
  401. time_t now = time(0);
  402. localtime(&now);
  403. now -= now % (3600 * 24);
  404. now -= 3600 * 8; //处理东八区问题
  405. CSmartPointer<IEntityFunction> spFunction = GetFunction();
  406. CSmartPointer<IConfigInfo> spConfig;
  407. ErrorCodeEnum BootTimeCfgError = spFunction->OpenConfig(Config_Run, spConfig);
  408. CSimpleStringA strLastRecordTime = "";
  409. ErrorCodeEnum errorRead = Error_Succeed;
  410. errorRead = spConfig->ReadConfigValue("Record", "LastRecordTime", strLastRecordTime);
  411. if (errorRead != Error_Succeed)
  412. {
  413. Dbg("Read Record LastRecordTime -> Failed! Maybe LastRecordTime not exist!");
  414. strLastRecordTime = "";
  415. }
  416. int timestamp_lastRecordTime = now;
  417. if (!strLastRecordTime.IsNullOrEmpty())
  418. {
  419. timestamp_lastRecordTime = StandardToStamp(strLastRecordTime, false);
  420. }
  421. for (std::list<int>::iterator it = timeList.begin(); it != timeList.end(); ++it)
  422. {
  423. if (timestamp_lastRecordTime <= *it && *it < now)
  424. {
  425. Dbg("CheckTradeRecord lastRecordTime=%d, time_list=%d, now=%d", timestamp_lastRecordTime, *it, now);
  426. return true;
  427. }
  428. }
  429. return false;
  430. }
  431. void CChromiumEntity::OnBusinessLimitTimerListener(void* pData)
  432. {
  433. Dbg("定时任务检查业务禁用");
  434. // 检查是否禁用业务
  435. //ShowLimitScreen();
  436. GetFunction()->ResetTimer(BROWSER_TIMER_ID, BROWSER_TIMER_INTERVAL);
  437. }
  438. void CChromiumEntity::CefClintNotify()
  439. {
  440. #if(defined _WIN32 || defined _WIN64)
  441. while (1)
  442. {
  443. for (auto it = m_cefArr.begin(); it != m_cefArr.end(); it++)
  444. {
  445. if (WaitForSingleObject(std::get<1>(it->second), 10) != WAIT_OBJECT_0) //process end
  446. DbgEx("cefclient.exe tag:%s job:%d, process:%d checkOpen", it->first.c_str(), std::get<0>(it->second), std::get<1>(it->second));
  447. else
  448. {
  449. DbgEx("cefclient.exe tag:%s job:%d, process:%d check Closed, try to restart", it->first.c_str(), std::get<0>(it->second), std::get<1>(it->second));
  450. auto info = it->first;
  451. auto cmdline = std::get<2>(it->second);//save the param
  452. TerminateJobObject(std::get<0>(it->second), 0);
  453. m_cefArr.erase(it->first);
  454. auto startRet = startProcessInJob(cmdline, "");
  455. if (std::get<0>(startRet))
  456. m_cefArr.insert(std::make_pair(info, std::make_tuple(std::get<1>(startRet), std::get<2>(startRet), cmdline)));
  457. break;
  458. }
  459. }
  460. boost::this_thread::sleep_for(boost::chrono::seconds(10));
  461. }
  462. #endif
  463. }
  464. #if (defined _WIN32 || defined _WIN64)
  465. void CChromiumEntity::OnCustomerCmd(const char* pszEntityName, DWORD dwMessageId, DWORD dwMessageSignature, IEBrowser::CustomerCmd& evt)
  466. {
  467. DbgEx("OnCustomerCmd %s", evt.cmdStr);
  468. static std::pair<int, std::string> historyChromium;
  469. auto jsDeletor = [](cJSON* p) {
  470. cJSON_Delete(p);
  471. };
  472. std::unique_ptr<cJSON, decltype(jsDeletor)> cmdJs(cJSON_Parse(evt.cmdStr), jsDeletor);
  473. auto cmdStr = cJSON_GetObjectItem(cmdJs.get(), "command")->valuestring;
  474. auto chromiumCLoseInJob = [&](std::string closeJob) -> bool {
  475. auto it = m_cefArr.find(closeJob);
  476. if (m_cefArr.end() != it)
  477. {
  478. TerminateJobObject(std::get<0>(it->second), 0);
  479. m_cefArr.erase(closeJob);
  480. return true;
  481. }
  482. else
  483. {
  484. DbgEx("m_cefArr can not find %s", closeJob.c_str());
  485. return false;
  486. }
  487. };
  488. if (!strcmp(cmdStr, "ChromiumStart"))
  489. {
  490. auto info = cJSON_GetObjectItem(cmdJs.get(), "info")->valuestring;
  491. auto fullscreen = cJSON_GetObjectItem(cmdJs.get(), "fullscreen")->valueint;
  492. auto top = cJSON_GetObjectItem(cmdJs.get(), "top")->valueint;
  493. // 感觉应当通过FreeRDP来启动Chromium,不应该自己管理
  494. // 需要保存启动的chromium的句柄值或者进程Id,通过该进程Id来获取句柄管理chromium运行
  495. // 因为有多个chromium,此时对每一个H5页面,都保存连接。并无法感知到某一个chromium的连接都不存在来重启chromium
  496. chromiumCLoseInJob(info);
  497. CSmartPointer<IConfigInfo> spCerConfig;
  498. GetFunction()->OpenConfig(Config_CenterSetting, spCerConfig);
  499. CSimpleString UserMgrUrlFulture;
  500. SpIniMappingTable table;
  501. // clean cache every time
  502. table.AddEntryString(GetEntityName(), "UserMgrUrlFulture", UserMgrUrlFulture, "");
  503. if (Error_Succeed != table.Load(spCerConfig))
  504. {
  505. DbgEx("load UserMgrUrlFulture failed");
  506. return;
  507. }
  508. CSimpleStringA strChromiumPath;
  509. GetFunction()->GetPath("Base", strChromiumPath);
  510. strChromiumPath.Append("\\bin\\Chromium\\");
  511. auto checkHttpThread = boost::async(boost::bind(checkHttpThreadFun, UserMgrUrlFulture.GetData()));
  512. checkHttpThread.wait_for(boost::chrono::seconds(1));
  513. Dbg("%s http check %s", UserMgrUrlFulture.GetData(), (checkHttpThread.is_ready() && checkHttpThread.get()) ? "sucess" : "failed");
  514. CSimpleStringA cachePath;
  515. GetFunction()->GetPath("Temp", cachePath);
  516. cachePath.Append("\\cefCache");
  517. CSimpleStringA strCmdLine = "";
  518. strCmdLine.Append(strChromiumPath).Append("cefclient.exe --url=").Append(UserMgrUrlFulture);
  519. strCmdLine.Append(" --hide-controls=true --cache-path=").Append(cachePath);
  520. strCmdLine.Append(" --logExtend=").Append(info).Append(" --top=").Append(std::to_string((LONGLONG)top).c_str());
  521. if (fullscreen)
  522. strCmdLine.Append(" --fullscreen");
  523. DbgEx("ChromiumStart cmdline : %s", strCmdLine);
  524. //control cefclient throught job
  525. auto startRet = startProcessInJob(strCmdLine.GetData(), "");
  526. if (std::get<0>(startRet))
  527. m_cefArr.insert(std::make_pair(info, std::make_tuple(std::get<1>(startRet), std::get<2>(startRet), strCmdLine.GetData())));
  528. else
  529. DbgEx("startProcessInJob failed!");
  530. }
  531. else if (!strcmp(cmdStr, "ChromiumClose"))
  532. {
  533. auto info = cJSON_GetObjectItem(cmdJs.get(), "info")->valuestring;
  534. chromiumCLoseInJob(info);
  535. }
  536. }
  537. #endif
  538. void CChromiumEntity::generateCefclientTimer()
  539. {
  540. m_pTimerListener = new TimerOutHelper<CChromiumEntity>(this, &CChromiumEntity::OnTaskTimerListener, NULL, false);
  541. GetFunction()->SetTimer(CHROMIUM_TIMER_ID, m_pTimerListener, 3000); //间隔执行时间
  542. }
  543. void CChromiumEntity::generateBussinessLimitTimer() {
  544. DbgEx("Start BusinessLimitTimer");
  545. pBusinessLimitTimerListener = new TimerOutHelper<CChromiumEntity>(this, &CChromiumEntity::OnBusinessLimitTimerListener, NULL, false);
  546. GetFunction()->SetTimer(BROWSER_TIMER_ID, pBusinessLimitTimerListener, 5000);
  547. }
  548. void CChromiumEntity::OnTaskTimerListener(void* pData)
  549. {
  550. static int max_restartTime = 3;
  551. DbgEx("OnTaskTimerListener");
  552. if (max_restartTime == 0)
  553. {
  554. DbgEx("max_restartTime == 0, do not restart chromium");
  555. GetFunction()->KillTimer(CHROMIUM_TIMER_ID);
  556. return;
  557. }
  558. //基于Desk2S功能判断,当当前并未启动cefclient时,对cefclient.exe进行清理
  559. if (0 == m_cefArr.size())
  560. DbgEx("kill chromium %s", CModTools::get_mutable_instance().killAllChromium() ? "success" : "fail");
  561. auto rc = CModTools::get_mutable_instance().StartChromiumBrowser();
  562. max_restartTime--;
  563. DbgEx("TaskTimerListen, startChromiumBrowser, rc:%d, pid:%d", rc.first, rc.second);
  564. if (0 == rc.first)
  565. GetFunction()->KillTimer(CHROMIUM_TIMER_ID);
  566. #if (defined _WIN32 || defined _WIN64)
  567. if (rc.first == Error_Succeed && rc.second != 0)
  568. {
  569. HANDLE defaultProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, rc.second);
  570. if (defaultProcess == nullptr)
  571. {
  572. DbgEx("OnTaskTimerListener, openProcess failed");
  573. return;
  574. }
  575. auto ret = assigntoJob(defaultProcess, rc.second);
  576. if (!ret.first)
  577. DbgEx("OnTaskTimerListener, assigntoJob failed");
  578. else
  579. {
  580. auto monitorThread = [&](HANDLE job, HANDLE process) {
  581. while (1)
  582. {
  583. if (WaitForSingleObject(process, 10) != WAIT_OBJECT_0) //process end
  584. DbgEx("default cefclient.exe job:%d, process:%d checkOpen", job, process);
  585. else
  586. {
  587. DbgEx("default cefclient.exe job:%d, process:%d check Closed, try to restart", job, process);
  588. TerminateJobObject(job, 0);
  589. max_restartTime--;
  590. generateCefclientTimer();
  591. //modTools.StartChromiumBrowser();
  592. break;
  593. }
  594. boost::this_thread::sleep_for(boost::chrono::seconds(10));
  595. }
  596. };
  597. if (ret.second != nullptr && defaultProcess != nullptr)
  598. boost::thread(monitorThread, ret.second, defaultProcess).detach();
  599. }
  600. }
  601. if (Error_Succeed != rc.first)
  602. {
  603. DbgEx("OnTaskTimerListener will be called after %d secs, rest restart time %d", 15, max_restartTime);
  604. if (max_restartTime)
  605. GetFunction()->ResetTimer(CHROMIUM_TIMER_ID, 15000);
  606. }
  607. else {
  608. DbgEx("OnTaskTimerListener rc = succeed");
  609. GetFunction()->KillTimer(CHROMIUM_TIMER_ID);
  610. }
  611. #endif
  612. }
  613. SP_BEGIN_ENTITY_MAP()
  614. SP_ENTITY(CChromiumEntity)
  615. SP_END_ENTITY_MAP()
  616. }