electron_api_app.cc 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859
  1. // Copyright (c) 2013 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/api/electron_api_app.h"
  5. #include <memory>
  6. #include <string>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/callback_helpers.h"
  10. #include "base/command_line.h"
  11. #include "base/containers/span.h"
  12. #include "base/environment.h"
  13. #include "base/files/file_path.h"
  14. #include "base/files/file_util.h"
  15. #include "base/path_service.h"
  16. #include "base/system/sys_info.h"
  17. #include "base/values.h"
  18. #include "chrome/browser/browser_process.h"
  19. #include "chrome/browser/icon_manager.h"
  20. #include "chrome/common/chrome_features.h"
  21. #include "chrome/common/chrome_paths.h"
  22. #include "content/browser/gpu/compositor_util.h" // nogncheck
  23. #include "content/browser/gpu/gpu_data_manager_impl.h" // nogncheck
  24. #include "content/public/browser/browser_accessibility_state.h"
  25. #include "content/public/browser/browser_child_process_host.h"
  26. #include "content/public/browser/child_process_data.h"
  27. #include "content/public/browser/client_certificate_delegate.h"
  28. #include "content/public/browser/gpu_data_manager.h"
  29. #include "content/public/browser/network_service_instance.h"
  30. #include "content/public/browser/render_frame_host.h"
  31. #include "content/public/common/content_switches.h"
  32. #include "media/audio/audio_manager.h"
  33. #include "net/dns/public/util.h"
  34. #include "net/ssl/client_cert_identity.h"
  35. #include "net/ssl/ssl_cert_request_info.h"
  36. #include "net/ssl/ssl_private_key.h"
  37. #include "sandbox/policy/switches.h"
  38. #include "services/network/network_service.h"
  39. #include "shell/app/command_line_args.h"
  40. #include "shell/browser/api/electron_api_menu.h"
  41. #include "shell/browser/api/electron_api_session.h"
  42. #include "shell/browser/api/electron_api_web_contents.h"
  43. #include "shell/browser/api/gpuinfo_manager.h"
  44. #include "shell/browser/electron_browser_context.h"
  45. #include "shell/browser/electron_browser_main_parts.h"
  46. #include "shell/browser/javascript_environment.h"
  47. #include "shell/browser/login_handler.h"
  48. #include "shell/browser/relauncher.h"
  49. #include "shell/common/application_info.h"
  50. #include "shell/common/electron_command_line.h"
  51. #include "shell/common/electron_paths.h"
  52. #include "shell/common/gin_converters/base_converter.h"
  53. #include "shell/common/gin_converters/blink_converter.h"
  54. #include "shell/common/gin_converters/callback_converter.h"
  55. #include "shell/common/gin_converters/file_path_converter.h"
  56. #include "shell/common/gin_converters/gurl_converter.h"
  57. #include "shell/common/gin_converters/image_converter.h"
  58. #include "shell/common/gin_converters/net_converter.h"
  59. #include "shell/common/gin_converters/value_converter.h"
  60. #include "shell/common/gin_helper/dictionary.h"
  61. #include "shell/common/gin_helper/object_template_builder.h"
  62. #include "shell/common/node_includes.h"
  63. #include "shell/common/options_switches.h"
  64. #include "shell/common/platform_util.h"
  65. #include "shell/common/v8_value_serializer.h"
  66. #include "third_party/abseil-cpp/absl/types/optional.h"
  67. #include "ui/gfx/image/image.h"
  68. #if defined(OS_WIN)
  69. #include "base/strings/utf_string_conversions.h"
  70. #include "shell/browser/ui/win/jump_list.h"
  71. #endif
  72. #if defined(OS_MAC)
  73. #include <CoreFoundation/CoreFoundation.h>
  74. #include "shell/browser/ui/cocoa/electron_bundle_mover.h"
  75. #endif
  76. using electron::Browser;
  77. namespace gin {
  78. #if defined(OS_WIN)
  79. template <>
  80. struct Converter<electron::ProcessIntegrityLevel> {
  81. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  82. electron::ProcessIntegrityLevel value) {
  83. switch (value) {
  84. case electron::ProcessIntegrityLevel::kUntrusted:
  85. return StringToV8(isolate, "untrusted");
  86. case electron::ProcessIntegrityLevel::kLow:
  87. return StringToV8(isolate, "low");
  88. case electron::ProcessIntegrityLevel::kMedium:
  89. return StringToV8(isolate, "medium");
  90. case electron::ProcessIntegrityLevel::kHigh:
  91. return StringToV8(isolate, "high");
  92. default:
  93. return StringToV8(isolate, "unknown");
  94. }
  95. }
  96. };
  97. template <>
  98. struct Converter<Browser::UserTask> {
  99. static bool FromV8(v8::Isolate* isolate,
  100. v8::Local<v8::Value> val,
  101. Browser::UserTask* out) {
  102. gin_helper::Dictionary dict;
  103. if (!ConvertFromV8(isolate, val, &dict))
  104. return false;
  105. if (!dict.Get("program", &(out->program)) ||
  106. !dict.Get("title", &(out->title)))
  107. return false;
  108. if (dict.Get("iconPath", &(out->icon_path)) &&
  109. !dict.Get("iconIndex", &(out->icon_index)))
  110. return false;
  111. dict.Get("arguments", &(out->arguments));
  112. dict.Get("description", &(out->description));
  113. dict.Get("workingDirectory", &(out->working_dir));
  114. return true;
  115. }
  116. };
  117. using electron::JumpListCategory;
  118. using electron::JumpListItem;
  119. using electron::JumpListResult;
  120. template <>
  121. struct Converter<JumpListItem::Type> {
  122. static bool FromV8(v8::Isolate* isolate,
  123. v8::Local<v8::Value> val,
  124. JumpListItem::Type* out) {
  125. std::string item_type;
  126. if (!ConvertFromV8(isolate, val, &item_type))
  127. return false;
  128. if (item_type == "task")
  129. *out = JumpListItem::Type::kTask;
  130. else if (item_type == "separator")
  131. *out = JumpListItem::Type::kSeparator;
  132. else if (item_type == "file")
  133. *out = JumpListItem::Type::kFile;
  134. else
  135. return false;
  136. return true;
  137. }
  138. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  139. JumpListItem::Type val) {
  140. std::string item_type;
  141. switch (val) {
  142. case JumpListItem::Type::kTask:
  143. item_type = "task";
  144. break;
  145. case JumpListItem::Type::kSeparator:
  146. item_type = "separator";
  147. break;
  148. case JumpListItem::Type::kFile:
  149. item_type = "file";
  150. break;
  151. }
  152. return gin::ConvertToV8(isolate, item_type);
  153. }
  154. };
  155. template <>
  156. struct Converter<JumpListItem> {
  157. static bool FromV8(v8::Isolate* isolate,
  158. v8::Local<v8::Value> val,
  159. JumpListItem* out) {
  160. gin_helper::Dictionary dict;
  161. if (!ConvertFromV8(isolate, val, &dict))
  162. return false;
  163. if (!dict.Get("type", &(out->type)))
  164. return false;
  165. switch (out->type) {
  166. case JumpListItem::Type::kTask:
  167. if (!dict.Get("program", &(out->path)) ||
  168. !dict.Get("title", &(out->title)))
  169. return false;
  170. if (dict.Get("iconPath", &(out->icon_path)) &&
  171. !dict.Get("iconIndex", &(out->icon_index)))
  172. return false;
  173. dict.Get("args", &(out->arguments));
  174. dict.Get("description", &(out->description));
  175. dict.Get("workingDirectory", &(out->working_dir));
  176. return true;
  177. case JumpListItem::Type::kSeparator:
  178. return true;
  179. case JumpListItem::Type::kFile:
  180. return dict.Get("path", &(out->path));
  181. }
  182. assert(false);
  183. return false;
  184. }
  185. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  186. const JumpListItem& val) {
  187. gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
  188. dict.Set("type", val.type);
  189. switch (val.type) {
  190. case JumpListItem::Type::kTask:
  191. dict.Set("program", val.path);
  192. dict.Set("args", val.arguments);
  193. dict.Set("title", val.title);
  194. dict.Set("iconPath", val.icon_path);
  195. dict.Set("iconIndex", val.icon_index);
  196. dict.Set("description", val.description);
  197. dict.Set("workingDirectory", val.working_dir);
  198. break;
  199. case JumpListItem::Type::kSeparator:
  200. break;
  201. case JumpListItem::Type::kFile:
  202. dict.Set("path", val.path);
  203. break;
  204. }
  205. return dict.GetHandle();
  206. }
  207. };
  208. template <>
  209. struct Converter<JumpListCategory::Type> {
  210. static bool FromV8(v8::Isolate* isolate,
  211. v8::Local<v8::Value> val,
  212. JumpListCategory::Type* out) {
  213. std::string category_type;
  214. if (!ConvertFromV8(isolate, val, &category_type))
  215. return false;
  216. if (category_type == "tasks")
  217. *out = JumpListCategory::Type::kTasks;
  218. else if (category_type == "frequent")
  219. *out = JumpListCategory::Type::kFrequent;
  220. else if (category_type == "recent")
  221. *out = JumpListCategory::Type::kRecent;
  222. else if (category_type == "custom")
  223. *out = JumpListCategory::Type::kCustom;
  224. else
  225. return false;
  226. return true;
  227. }
  228. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  229. JumpListCategory::Type val) {
  230. std::string category_type;
  231. switch (val) {
  232. case JumpListCategory::Type::kTasks:
  233. category_type = "tasks";
  234. break;
  235. case JumpListCategory::Type::kFrequent:
  236. category_type = "frequent";
  237. break;
  238. case JumpListCategory::Type::kRecent:
  239. category_type = "recent";
  240. break;
  241. case JumpListCategory::Type::kCustom:
  242. category_type = "custom";
  243. break;
  244. }
  245. return gin::ConvertToV8(isolate, category_type);
  246. }
  247. };
  248. template <>
  249. struct Converter<JumpListCategory> {
  250. static bool FromV8(v8::Isolate* isolate,
  251. v8::Local<v8::Value> val,
  252. JumpListCategory* out) {
  253. gin_helper::Dictionary dict;
  254. if (!ConvertFromV8(isolate, val, &dict))
  255. return false;
  256. if (dict.Get("name", &(out->name)) && out->name.empty())
  257. return false;
  258. if (!dict.Get("type", &(out->type))) {
  259. if (out->name.empty())
  260. out->type = JumpListCategory::Type::kTasks;
  261. else
  262. out->type = JumpListCategory::Type::kCustom;
  263. }
  264. if ((out->type == JumpListCategory::Type::kTasks) ||
  265. (out->type == JumpListCategory::Type::kCustom)) {
  266. if (!dict.Get("items", &(out->items)))
  267. return false;
  268. }
  269. return true;
  270. }
  271. };
  272. // static
  273. template <>
  274. struct Converter<JumpListResult> {
  275. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, JumpListResult val) {
  276. std::string result_code;
  277. switch (val) {
  278. case JumpListResult::kSuccess:
  279. result_code = "ok";
  280. break;
  281. case JumpListResult::kArgumentError:
  282. result_code = "argumentError";
  283. break;
  284. case JumpListResult::kGenericError:
  285. result_code = "error";
  286. break;
  287. case JumpListResult::kCustomCategorySeparatorError:
  288. result_code = "invalidSeparatorError";
  289. break;
  290. case JumpListResult::kMissingFileTypeRegistrationError:
  291. result_code = "fileTypeRegistrationError";
  292. break;
  293. case JumpListResult::kCustomCategoryAccessDeniedError:
  294. result_code = "customCategoryAccessDeniedError";
  295. break;
  296. }
  297. return ConvertToV8(isolate, result_code);
  298. }
  299. };
  300. #endif
  301. #if defined(OS_WIN)
  302. template <>
  303. struct Converter<Browser::LaunchItem> {
  304. static bool FromV8(v8::Isolate* isolate,
  305. v8::Local<v8::Value> val,
  306. Browser::LaunchItem* out) {
  307. gin_helper::Dictionary dict;
  308. if (!ConvertFromV8(isolate, val, &dict))
  309. return false;
  310. dict.Get("name", &(out->name));
  311. dict.Get("path", &(out->path));
  312. dict.Get("args", &(out->args));
  313. dict.Get("scope", &(out->scope));
  314. dict.Get("enabled", &(out->enabled));
  315. return true;
  316. }
  317. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  318. Browser::LaunchItem val) {
  319. gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
  320. dict.Set("name", val.name);
  321. dict.Set("path", val.path);
  322. dict.Set("args", val.args);
  323. dict.Set("scope", val.scope);
  324. dict.Set("enabled", val.enabled);
  325. return dict.GetHandle();
  326. }
  327. };
  328. #endif
  329. template <>
  330. struct Converter<Browser::LoginItemSettings> {
  331. static bool FromV8(v8::Isolate* isolate,
  332. v8::Local<v8::Value> val,
  333. Browser::LoginItemSettings* out) {
  334. gin_helper::Dictionary dict;
  335. if (!ConvertFromV8(isolate, val, &dict))
  336. return false;
  337. dict.Get("openAtLogin", &(out->open_at_login));
  338. dict.Get("openAsHidden", &(out->open_as_hidden));
  339. dict.Get("path", &(out->path));
  340. dict.Get("args", &(out->args));
  341. #if defined(OS_WIN)
  342. dict.Get("enabled", &(out->enabled));
  343. dict.Get("name", &(out->name));
  344. #endif
  345. return true;
  346. }
  347. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  348. Browser::LoginItemSettings val) {
  349. gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
  350. dict.Set("openAtLogin", val.open_at_login);
  351. dict.Set("openAsHidden", val.open_as_hidden);
  352. dict.Set("restoreState", val.restore_state);
  353. dict.Set("wasOpenedAtLogin", val.opened_at_login);
  354. dict.Set("wasOpenedAsHidden", val.opened_as_hidden);
  355. #if defined(OS_WIN)
  356. dict.Set("launchItems", val.launch_items);
  357. dict.Set("executableWillLaunchAtLogin",
  358. val.executable_will_launch_at_login);
  359. #endif
  360. return dict.GetHandle();
  361. }
  362. };
  363. template <>
  364. struct Converter<content::CertificateRequestResultType> {
  365. static bool FromV8(v8::Isolate* isolate,
  366. v8::Local<v8::Value> val,
  367. content::CertificateRequestResultType* out) {
  368. bool b;
  369. if (!ConvertFromV8(isolate, val, &b))
  370. return false;
  371. *out = b ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE
  372. : content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
  373. return true;
  374. }
  375. };
  376. template <>
  377. struct Converter<net::SecureDnsMode> {
  378. static bool FromV8(v8::Isolate* isolate,
  379. v8::Local<v8::Value> val,
  380. net::SecureDnsMode* out) {
  381. std::string s;
  382. if (!ConvertFromV8(isolate, val, &s))
  383. return false;
  384. if (s == "off") {
  385. *out = net::SecureDnsMode::kOff;
  386. return true;
  387. } else if (s == "automatic") {
  388. *out = net::SecureDnsMode::kAutomatic;
  389. return true;
  390. } else if (s == "secure") {
  391. *out = net::SecureDnsMode::kSecure;
  392. return true;
  393. }
  394. return false;
  395. }
  396. };
  397. } // namespace gin
  398. namespace electron {
  399. namespace api {
  400. gin::WrapperInfo App::kWrapperInfo = {gin::kEmbedderNativeGin};
  401. namespace {
  402. IconLoader::IconSize GetIconSizeByString(const std::string& size) {
  403. if (size == "small") {
  404. return IconLoader::IconSize::SMALL;
  405. } else if (size == "large") {
  406. return IconLoader::IconSize::LARGE;
  407. }
  408. return IconLoader::IconSize::NORMAL;
  409. }
  410. // Return the path constant from string.
  411. int GetPathConstant(const std::string& name) {
  412. if (name == "appData")
  413. return DIR_APP_DATA;
  414. else if (name == "userData")
  415. return chrome::DIR_USER_DATA;
  416. else if (name == "cache")
  417. #if defined(OS_POSIX)
  418. return base::DIR_CACHE;
  419. #else
  420. return base::DIR_ROAMING_APP_DATA;
  421. #endif
  422. else if (name == "userCache")
  423. return DIR_USER_CACHE;
  424. else if (name == "logs")
  425. return DIR_APP_LOGS;
  426. else if (name == "crashDumps")
  427. return DIR_CRASH_DUMPS;
  428. else if (name == "home")
  429. return base::DIR_HOME;
  430. else if (name == "temp")
  431. return base::DIR_TEMP;
  432. else if (name == "userDesktop" || name == "desktop")
  433. return base::DIR_USER_DESKTOP;
  434. else if (name == "exe")
  435. return base::FILE_EXE;
  436. else if (name == "module")
  437. return base::FILE_MODULE;
  438. else if (name == "documents")
  439. return chrome::DIR_USER_DOCUMENTS;
  440. else if (name == "downloads")
  441. return chrome::DIR_DEFAULT_DOWNLOADS;
  442. else if (name == "music")
  443. return chrome::DIR_USER_MUSIC;
  444. else if (name == "pictures")
  445. return chrome::DIR_USER_PICTURES;
  446. else if (name == "videos")
  447. return chrome::DIR_USER_VIDEOS;
  448. #if defined(OS_WIN)
  449. else if (name == "recent")
  450. return electron::DIR_RECENT;
  451. #endif
  452. else
  453. return -1;
  454. }
  455. bool NotificationCallbackWrapper(
  456. const base::RepeatingCallback<
  457. void(const base::CommandLine& command_line,
  458. const base::FilePath& current_directory,
  459. const std::vector<const uint8_t> additional_data)>& callback,
  460. const base::CommandLine& cmd,
  461. const base::FilePath& cwd,
  462. const std::vector<const uint8_t> additional_data) {
  463. // Make sure the callback is called after app gets ready.
  464. if (Browser::Get()->is_ready()) {
  465. callback.Run(cmd, cwd, std::move(additional_data));
  466. } else {
  467. scoped_refptr<base::SingleThreadTaskRunner> task_runner(
  468. base::ThreadTaskRunnerHandle::Get());
  469. // Make a copy of the span so that the data isn't lost.
  470. task_runner->PostTask(FROM_HERE,
  471. base::BindOnce(base::IgnoreResult(callback), cmd, cwd,
  472. std::move(additional_data)));
  473. }
  474. // ProcessSingleton needs to know whether current process is quiting.
  475. return !Browser::Get()->is_shutting_down();
  476. }
  477. void GotPrivateKey(std::shared_ptr<content::ClientCertificateDelegate> delegate,
  478. scoped_refptr<net::X509Certificate> cert,
  479. scoped_refptr<net::SSLPrivateKey> private_key) {
  480. delegate->ContinueWithCertificate(cert, private_key);
  481. }
  482. void OnClientCertificateSelected(
  483. v8::Isolate* isolate,
  484. std::shared_ptr<content::ClientCertificateDelegate> delegate,
  485. std::shared_ptr<net::ClientCertIdentityList> identities,
  486. gin::Arguments* args) {
  487. if (args->Length() == 2) {
  488. delegate->ContinueWithCertificate(nullptr, nullptr);
  489. return;
  490. }
  491. v8::Local<v8::Value> val;
  492. args->GetNext(&val);
  493. if (val->IsNull()) {
  494. delegate->ContinueWithCertificate(nullptr, nullptr);
  495. return;
  496. }
  497. gin_helper::Dictionary cert_data;
  498. if (!gin::ConvertFromV8(isolate, val, &cert_data)) {
  499. gin_helper::ErrorThrower(isolate).ThrowError(
  500. "Must pass valid certificate object.");
  501. return;
  502. }
  503. std::string data;
  504. if (!cert_data.Get("data", &data))
  505. return;
  506. auto certs = net::X509Certificate::CreateCertificateListFromBytes(
  507. base::as_bytes(base::make_span(data.c_str(), data.size())),
  508. net::X509Certificate::FORMAT_AUTO);
  509. if (!certs.empty()) {
  510. scoped_refptr<net::X509Certificate> cert(certs[0].get());
  511. for (auto& identity : *identities) {
  512. scoped_refptr<net::X509Certificate> identity_cert =
  513. identity->certificate();
  514. // Since |cert| was recreated from |data|, it won't include any
  515. // intermediates. That's fine for checking equality, but once a match is
  516. // found then |identity_cert| should be used since it will include the
  517. // intermediates which would otherwise be lost.
  518. if (cert->EqualsExcludingChain(identity_cert.get())) {
  519. net::ClientCertIdentity::SelfOwningAcquirePrivateKey(
  520. std::move(identity), base::BindRepeating(&GotPrivateKey, delegate,
  521. std::move(identity_cert)));
  522. break;
  523. }
  524. }
  525. }
  526. }
  527. #if defined(USE_NSS_CERTS)
  528. int ImportIntoCertStore(CertificateManagerModel* model, base::Value options) {
  529. std::string file_data, cert_path;
  530. std::u16string password;
  531. net::ScopedCERTCertificateList imported_certs;
  532. int rv = -1;
  533. std::string* cert_path_ptr = options.FindStringKey("certificate");
  534. if (cert_path_ptr)
  535. cert_path = *cert_path_ptr;
  536. std::string* pwd = options.FindStringKey("password");
  537. if (pwd)
  538. password = base::UTF8ToUTF16(*pwd);
  539. if (!cert_path.empty()) {
  540. if (base::ReadFileToString(base::FilePath(cert_path), &file_data)) {
  541. auto module = model->cert_db()->GetPrivateSlot();
  542. rv = model->ImportFromPKCS12(module.get(), file_data, password, true,
  543. &imported_certs);
  544. if (imported_certs.size() > 1) {
  545. auto it = imported_certs.begin();
  546. ++it; // skip first which would be the client certificate.
  547. for (; it != imported_certs.end(); ++it)
  548. rv &= model->SetCertTrust(it->get(), net::CA_CERT,
  549. net::NSSCertDatabase::TRUSTED_SSL);
  550. }
  551. }
  552. }
  553. return rv;
  554. }
  555. #endif
  556. void OnIconDataAvailable(gin_helper::Promise<gfx::Image> promise,
  557. gfx::Image icon) {
  558. if (!icon.IsEmpty()) {
  559. promise.Resolve(icon);
  560. } else {
  561. promise.RejectWithErrorMessage("Failed to get file icon.");
  562. }
  563. }
  564. } // namespace
  565. App::App() {
  566. static_cast<ElectronBrowserClient*>(ElectronBrowserClient::Get())
  567. ->set_delegate(this);
  568. Browser::Get()->AddObserver(this);
  569. auto pid = content::ChildProcessHost::kInvalidUniqueID;
  570. auto process_metric = std::make_unique<electron::ProcessMetric>(
  571. content::PROCESS_TYPE_BROWSER, base::GetCurrentProcessHandle(),
  572. base::ProcessMetrics::CreateCurrentProcessMetrics());
  573. app_metrics_[pid] = std::move(process_metric);
  574. }
  575. App::~App() {
  576. static_cast<ElectronBrowserClient*>(ElectronBrowserClient::Get())
  577. ->set_delegate(nullptr);
  578. Browser::Get()->RemoveObserver(this);
  579. content::GpuDataManager::GetInstance()->RemoveObserver(this);
  580. content::BrowserChildProcessObserver::Remove(this);
  581. }
  582. void App::OnBeforeQuit(bool* prevent_default) {
  583. if (Emit("before-quit")) {
  584. *prevent_default = true;
  585. }
  586. }
  587. void App::OnWillQuit(bool* prevent_default) {
  588. if (Emit("will-quit")) {
  589. *prevent_default = true;
  590. }
  591. }
  592. void App::OnWindowAllClosed() {
  593. Emit("window-all-closed");
  594. }
  595. void App::OnQuit() {
  596. const int exitCode = ElectronBrowserMainParts::Get()->GetExitCode();
  597. Emit("quit", exitCode);
  598. if (process_singleton_) {
  599. process_singleton_->Cleanup();
  600. process_singleton_.reset();
  601. }
  602. }
  603. void App::OnOpenFile(bool* prevent_default, const std::string& file_path) {
  604. if (Emit("open-file", file_path)) {
  605. *prevent_default = true;
  606. }
  607. }
  608. void App::OnOpenURL(const std::string& url) {
  609. Emit("open-url", url);
  610. }
  611. void App::OnActivate(bool has_visible_windows) {
  612. Emit("activate", has_visible_windows);
  613. }
  614. void App::OnWillFinishLaunching() {
  615. Emit("will-finish-launching");
  616. }
  617. void App::OnFinishLaunching(const base::DictionaryValue& launch_info) {
  618. #if defined(OS_LINUX)
  619. // Set the application name for audio streams shown in external
  620. // applications. Only affects pulseaudio currently.
  621. media::AudioManager::SetGlobalAppName(Browser::Get()->GetName());
  622. #endif
  623. Emit("ready", launch_info);
  624. }
  625. void App::OnPreMainMessageLoopRun() {
  626. content::BrowserChildProcessObserver::Add(this);
  627. if (process_singleton_) {
  628. process_singleton_->OnBrowserReady();
  629. }
  630. }
  631. void App::OnPreCreateThreads() {
  632. DCHECK(!content::GpuDataManager::Initialized());
  633. content::GpuDataManager* manager = content::GpuDataManager::GetInstance();
  634. manager->AddObserver(this);
  635. if (disable_hw_acceleration_) {
  636. manager->DisableHardwareAcceleration();
  637. }
  638. if (disable_domain_blocking_for_3DAPIs_) {
  639. content::GpuDataManagerImpl::GetInstance()
  640. ->DisableDomainBlockingFor3DAPIsForTesting();
  641. }
  642. }
  643. void App::OnAccessibilitySupportChanged() {
  644. Emit("accessibility-support-changed", IsAccessibilitySupportEnabled());
  645. }
  646. #if defined(OS_MAC)
  647. void App::OnWillContinueUserActivity(bool* prevent_default,
  648. const std::string& type) {
  649. if (Emit("will-continue-activity", type)) {
  650. *prevent_default = true;
  651. }
  652. }
  653. void App::OnDidFailToContinueUserActivity(const std::string& type,
  654. const std::string& error) {
  655. Emit("continue-activity-error", type, error);
  656. }
  657. void App::OnContinueUserActivity(bool* prevent_default,
  658. const std::string& type,
  659. const base::DictionaryValue& user_info,
  660. const base::DictionaryValue& details) {
  661. if (Emit("continue-activity", type, user_info, details)) {
  662. *prevent_default = true;
  663. }
  664. }
  665. void App::OnUserActivityWasContinued(const std::string& type,
  666. const base::DictionaryValue& user_info) {
  667. Emit("activity-was-continued", type, user_info);
  668. }
  669. void App::OnUpdateUserActivityState(bool* prevent_default,
  670. const std::string& type,
  671. const base::DictionaryValue& user_info) {
  672. if (Emit("update-activity-state", type, user_info)) {
  673. *prevent_default = true;
  674. }
  675. }
  676. void App::OnNewWindowForTab() {
  677. Emit("new-window-for-tab");
  678. }
  679. void App::OnDidBecomeActive() {
  680. Emit("did-become-active");
  681. }
  682. #endif
  683. bool App::CanCreateWindow(
  684. content::RenderFrameHost* opener,
  685. const GURL& opener_url,
  686. const GURL& opener_top_level_frame_url,
  687. const url::Origin& source_origin,
  688. content::mojom::WindowContainerType container_type,
  689. const GURL& target_url,
  690. const content::Referrer& referrer,
  691. const std::string& frame_name,
  692. WindowOpenDisposition disposition,
  693. const blink::mojom::WindowFeatures& features,
  694. const std::string& raw_features,
  695. const scoped_refptr<network::ResourceRequestBody>& body,
  696. bool user_gesture,
  697. bool opener_suppressed,
  698. bool* no_javascript_access) {
  699. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  700. v8::Locker locker(isolate);
  701. v8::HandleScope handle_scope(isolate);
  702. content::WebContents* web_contents =
  703. content::WebContents::FromRenderFrameHost(opener);
  704. if (web_contents) {
  705. WebContents* api_web_contents = WebContents::From(web_contents);
  706. // No need to emit any event if the WebContents is not available in JS.
  707. if (api_web_contents) {
  708. api_web_contents->OnCreateWindow(target_url, referrer, frame_name,
  709. disposition, raw_features, body);
  710. }
  711. }
  712. return false;
  713. }
  714. void App::AllowCertificateError(
  715. content::WebContents* web_contents,
  716. int cert_error,
  717. const net::SSLInfo& ssl_info,
  718. const GURL& request_url,
  719. bool is_main_frame_request,
  720. bool strict_enforcement,
  721. base::OnceCallback<void(content::CertificateRequestResultType)> callback) {
  722. auto adapted_callback = base::AdaptCallbackForRepeating(std::move(callback));
  723. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  724. v8::Locker locker(isolate);
  725. v8::HandleScope handle_scope(isolate);
  726. bool prevent_default = Emit(
  727. "certificate-error", WebContents::FromOrCreate(isolate, web_contents),
  728. request_url, net::ErrorToString(cert_error), ssl_info.cert,
  729. adapted_callback, is_main_frame_request);
  730. // Deny the certificate by default.
  731. if (!prevent_default)
  732. adapted_callback.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
  733. }
  734. base::OnceClosure App::SelectClientCertificate(
  735. content::WebContents* web_contents,
  736. net::SSLCertRequestInfo* cert_request_info,
  737. net::ClientCertIdentityList identities,
  738. std::unique_ptr<content::ClientCertificateDelegate> delegate) {
  739. std::shared_ptr<content::ClientCertificateDelegate> shared_delegate(
  740. delegate.release());
  741. // Convert the ClientCertIdentityList to a CertificateList
  742. // to avoid changes in the API.
  743. auto client_certs = net::CertificateList();
  744. for (const std::unique_ptr<net::ClientCertIdentity>& identity : identities)
  745. client_certs.emplace_back(identity->certificate());
  746. auto shared_identities =
  747. std::make_shared<net::ClientCertIdentityList>(std::move(identities));
  748. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  749. v8::HandleScope handle_scope(isolate);
  750. bool prevent_default =
  751. Emit("select-client-certificate",
  752. WebContents::FromOrCreate(isolate, web_contents),
  753. cert_request_info->host_and_port.ToString(), std::move(client_certs),
  754. base::BindOnce(&OnClientCertificateSelected, isolate,
  755. shared_delegate, shared_identities));
  756. // Default to first certificate from the platform store.
  757. if (!prevent_default) {
  758. scoped_refptr<net::X509Certificate> cert =
  759. (*shared_identities)[0]->certificate();
  760. net::ClientCertIdentity::SelfOwningAcquirePrivateKey(
  761. std::move((*shared_identities)[0]),
  762. base::BindRepeating(&GotPrivateKey, shared_delegate, std::move(cert)));
  763. }
  764. return base::OnceClosure();
  765. }
  766. void App::OnGpuInfoUpdate() {
  767. Emit("gpu-info-update");
  768. }
  769. void App::OnGpuProcessCrashed(base::TerminationStatus status) {
  770. Emit("gpu-process-crashed",
  771. status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
  772. }
  773. void App::BrowserChildProcessLaunchedAndConnected(
  774. const content::ChildProcessData& data) {
  775. ChildProcessLaunched(data.process_type, data.id, data.GetProcess().Handle(),
  776. data.metrics_name, base::UTF16ToUTF8(data.name));
  777. }
  778. void App::BrowserChildProcessHostDisconnected(
  779. const content::ChildProcessData& data) {
  780. ChildProcessDisconnected(data.id);
  781. }
  782. void App::BrowserChildProcessCrashed(
  783. const content::ChildProcessData& data,
  784. const content::ChildProcessTerminationInfo& info) {
  785. ChildProcessDisconnected(data.id);
  786. BrowserChildProcessCrashedOrKilled(data, info);
  787. }
  788. void App::BrowserChildProcessKilled(
  789. const content::ChildProcessData& data,
  790. const content::ChildProcessTerminationInfo& info) {
  791. ChildProcessDisconnected(data.id);
  792. BrowserChildProcessCrashedOrKilled(data, info);
  793. }
  794. void App::BrowserChildProcessCrashedOrKilled(
  795. const content::ChildProcessData& data,
  796. const content::ChildProcessTerminationInfo& info) {
  797. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  798. v8::HandleScope handle_scope(isolate);
  799. auto details = gin_helper::Dictionary::CreateEmpty(isolate);
  800. details.Set("type", content::GetProcessTypeNameInEnglish(data.process_type));
  801. details.Set("reason", info.status);
  802. details.Set("exitCode", info.exit_code);
  803. details.Set("serviceName", data.metrics_name);
  804. if (!data.name.empty()) {
  805. details.Set("name", data.name);
  806. }
  807. Emit("child-process-gone", details);
  808. }
  809. void App::RenderProcessReady(content::RenderProcessHost* host) {
  810. ChildProcessLaunched(content::PROCESS_TYPE_RENDERER, host->GetID(),
  811. host->GetProcess().Handle());
  812. }
  813. void App::RenderProcessExited(content::RenderProcessHost* host) {
  814. ChildProcessDisconnected(host->GetID());
  815. }
  816. void App::ChildProcessLaunched(int process_type,
  817. int pid,
  818. base::ProcessHandle handle,
  819. const std::string& service_name,
  820. const std::string& name) {
  821. #if defined(OS_MAC)
  822. auto metrics = base::ProcessMetrics::CreateProcessMetrics(
  823. handle, content::BrowserChildProcessHost::GetPortProvider());
  824. #else
  825. auto metrics = base::ProcessMetrics::CreateProcessMetrics(handle);
  826. #endif
  827. app_metrics_[pid] = std::make_unique<electron::ProcessMetric>(
  828. process_type, handle, std::move(metrics), service_name, name);
  829. }
  830. void App::ChildProcessDisconnected(int pid) {
  831. app_metrics_.erase(pid);
  832. }
  833. base::FilePath App::GetAppPath() const {
  834. return app_path_;
  835. }
  836. void App::SetAppPath(const base::FilePath& app_path) {
  837. app_path_ = app_path;
  838. }
  839. #if !defined(OS_MAC)
  840. void App::SetAppLogsPath(gin_helper::ErrorThrower thrower,
  841. absl::optional<base::FilePath> custom_path) {
  842. if (custom_path.has_value()) {
  843. if (!custom_path->IsAbsolute()) {
  844. thrower.ThrowError("Path must be absolute");
  845. return;
  846. }
  847. {
  848. base::ThreadRestrictions::ScopedAllowIO allow_io;
  849. base::PathService::Override(DIR_APP_LOGS, custom_path.value());
  850. }
  851. } else {
  852. base::FilePath path;
  853. if (base::PathService::Get(chrome::DIR_USER_DATA, &path)) {
  854. path = path.Append(base::FilePath::FromUTF8Unsafe("logs"));
  855. {
  856. base::ThreadRestrictions::ScopedAllowIO allow_io;
  857. base::PathService::Override(DIR_APP_LOGS, path);
  858. }
  859. }
  860. }
  861. }
  862. #endif
  863. // static
  864. bool App::IsPackaged() {
  865. auto env = base::Environment::Create();
  866. if (env->HasVar("ELECTRON_FORCE_IS_PACKAGED"))
  867. return true;
  868. base::FilePath exe_path;
  869. base::PathService::Get(base::FILE_EXE, &exe_path);
  870. base::FilePath::StringType base_name =
  871. base::ToLowerASCII(exe_path.BaseName().value());
  872. #if defined(OS_WIN)
  873. return base_name != FILE_PATH_LITERAL("electron.exe");
  874. #else
  875. return base_name != FILE_PATH_LITERAL("electron");
  876. #endif
  877. }
  878. base::FilePath App::GetPath(gin_helper::ErrorThrower thrower,
  879. const std::string& name) {
  880. base::FilePath path;
  881. int key = GetPathConstant(name);
  882. if (key < 0 || !base::PathService::Get(key, &path))
  883. thrower.ThrowError("Failed to get '" + name + "' path");
  884. return path;
  885. }
  886. void App::SetPath(gin_helper::ErrorThrower thrower,
  887. const std::string& name,
  888. const base::FilePath& path) {
  889. if (!path.IsAbsolute()) {
  890. thrower.ThrowError("Path must be absolute");
  891. return;
  892. }
  893. int key = GetPathConstant(name);
  894. if (key < 0 || !base::PathService::OverrideAndCreateIfNeeded(
  895. key, path, /* is_absolute = */ true, /* create = */ false))
  896. thrower.ThrowError("Failed to set path");
  897. }
  898. void App::SetDesktopName(const std::string& desktop_name) {
  899. #if defined(OS_LINUX)
  900. auto env = base::Environment::Create();
  901. env->SetVar("CHROME_DESKTOP", desktop_name);
  902. #endif
  903. }
  904. std::string App::GetLocale() {
  905. return g_browser_process->GetApplicationLocale();
  906. }
  907. std::string App::GetLocaleCountryCode() {
  908. std::string region;
  909. #if defined(OS_WIN)
  910. WCHAR locale_name[LOCALE_NAME_MAX_LENGTH] = {0};
  911. if (GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SISO3166CTRYNAME,
  912. (LPWSTR)&locale_name,
  913. sizeof(locale_name) / sizeof(WCHAR)) ||
  914. GetLocaleInfoEx(LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_SISO3166CTRYNAME,
  915. (LPWSTR)&locale_name,
  916. sizeof(locale_name) / sizeof(WCHAR))) {
  917. base::WideToUTF8(locale_name, wcslen(locale_name), &region);
  918. }
  919. #elif defined(OS_MAC)
  920. CFLocaleRef locale = CFLocaleCopyCurrent();
  921. CFStringRef value = CFStringRef(
  922. static_cast<CFTypeRef>(CFLocaleGetValue(locale, kCFLocaleCountryCode)));
  923. if (value != nil) {
  924. char temporaryCString[3];
  925. const CFIndex kCStringSize = sizeof(temporaryCString);
  926. if (CFStringGetCString(value, temporaryCString, kCStringSize,
  927. kCFStringEncodingUTF8)) {
  928. region = temporaryCString;
  929. }
  930. }
  931. #else
  932. const char* locale_ptr = setlocale(LC_TIME, nullptr);
  933. if (!locale_ptr)
  934. locale_ptr = setlocale(LC_NUMERIC, nullptr);
  935. if (locale_ptr) {
  936. std::string locale = locale_ptr;
  937. std::string::size_type rpos = locale.find('.');
  938. if (rpos != std::string::npos)
  939. locale = locale.substr(0, rpos);
  940. rpos = locale.find('_');
  941. if (rpos != std::string::npos && rpos + 1 < locale.size())
  942. region = locale.substr(rpos + 1);
  943. }
  944. #endif
  945. return region.size() == 2 ? region : std::string();
  946. }
  947. void App::OnSecondInstance(const base::CommandLine& cmd,
  948. const base::FilePath& cwd,
  949. const std::vector<const uint8_t> additional_data) {
  950. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  951. v8::Locker locker(isolate);
  952. v8::HandleScope handle_scope(isolate);
  953. v8::Local<v8::Value> data_value =
  954. DeserializeV8Value(isolate, std::move(additional_data));
  955. Emit("second-instance", cmd.argv(), cwd, data_value);
  956. }
  957. bool App::HasSingleInstanceLock() const {
  958. if (process_singleton_)
  959. return true;
  960. return false;
  961. }
  962. bool App::RequestSingleInstanceLock(gin::Arguments* args) {
  963. if (HasSingleInstanceLock())
  964. return true;
  965. std::string program_name = electron::Browser::Get()->GetName();
  966. base::FilePath user_dir;
  967. base::PathService::Get(chrome::DIR_USER_DATA, &user_dir);
  968. // The user_dir may not have been created yet.
  969. base::CreateDirectoryAndGetError(user_dir, nullptr);
  970. auto cb = base::BindRepeating(&App::OnSecondInstance, base::Unretained(this));
  971. blink::CloneableMessage additional_data_message;
  972. args->GetNext(&additional_data_message);
  973. #if defined(OS_WIN)
  974. bool app_is_sandboxed =
  975. IsSandboxEnabled(base::CommandLine::ForCurrentProcess());
  976. process_singleton_ = std::make_unique<ProcessSingleton>(
  977. program_name, user_dir, additional_data_message.encoded_message,
  978. app_is_sandboxed, base::BindRepeating(NotificationCallbackWrapper, cb));
  979. #else
  980. process_singleton_ = std::make_unique<ProcessSingleton>(
  981. user_dir, additional_data_message.encoded_message,
  982. base::BindRepeating(NotificationCallbackWrapper, cb));
  983. #endif
  984. switch (process_singleton_->NotifyOtherProcessOrCreate()) {
  985. case ProcessSingleton::NotifyResult::LOCK_ERROR:
  986. case ProcessSingleton::NotifyResult::PROFILE_IN_USE:
  987. case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED: {
  988. process_singleton_.reset();
  989. return false;
  990. }
  991. case ProcessSingleton::NotifyResult::PROCESS_NONE:
  992. default: // Shouldn't be needed, but VS warns if it is not there.
  993. return true;
  994. }
  995. }
  996. void App::ReleaseSingleInstanceLock() {
  997. if (process_singleton_) {
  998. process_singleton_->Cleanup();
  999. process_singleton_.reset();
  1000. }
  1001. }
  1002. bool App::Relaunch(gin::Arguments* js_args) {
  1003. // Parse parameters.
  1004. bool override_argv = false;
  1005. base::FilePath exec_path;
  1006. relauncher::StringVector args;
  1007. gin_helper::Dictionary options;
  1008. if (js_args->GetNext(&options)) {
  1009. if (options.Get("execPath", &exec_path) || options.Get("args", &args))
  1010. override_argv = true;
  1011. }
  1012. if (!override_argv) {
  1013. const relauncher::StringVector& argv =
  1014. electron::ElectronCommandLine::argv();
  1015. return relauncher::RelaunchApp(argv);
  1016. }
  1017. relauncher::StringVector argv;
  1018. argv.reserve(1 + args.size());
  1019. if (exec_path.empty()) {
  1020. base::FilePath current_exe_path;
  1021. base::PathService::Get(base::FILE_EXE, &current_exe_path);
  1022. argv.push_back(current_exe_path.value());
  1023. } else {
  1024. argv.push_back(exec_path.value());
  1025. }
  1026. argv.insert(argv.end(), args.begin(), args.end());
  1027. return relauncher::RelaunchApp(argv);
  1028. }
  1029. void App::DisableHardwareAcceleration(gin_helper::ErrorThrower thrower) {
  1030. if (Browser::Get()->is_ready()) {
  1031. thrower.ThrowError(
  1032. "app.disableHardwareAcceleration() can only be called "
  1033. "before app is ready");
  1034. return;
  1035. }
  1036. if (content::GpuDataManager::Initialized()) {
  1037. content::GpuDataManager::GetInstance()->DisableHardwareAcceleration();
  1038. } else {
  1039. disable_hw_acceleration_ = true;
  1040. }
  1041. }
  1042. void App::DisableDomainBlockingFor3DAPIs(gin_helper::ErrorThrower thrower) {
  1043. if (Browser::Get()->is_ready()) {
  1044. thrower.ThrowError(
  1045. "app.disableDomainBlockingFor3DAPIs() can only be called "
  1046. "before app is ready");
  1047. return;
  1048. }
  1049. if (content::GpuDataManager::Initialized()) {
  1050. content::GpuDataManagerImpl::GetInstance()
  1051. ->DisableDomainBlockingFor3DAPIsForTesting();
  1052. } else {
  1053. disable_domain_blocking_for_3DAPIs_ = true;
  1054. }
  1055. }
  1056. bool App::IsAccessibilitySupportEnabled() {
  1057. auto* ax_state = content::BrowserAccessibilityState::GetInstance();
  1058. return ax_state->IsAccessibleBrowser();
  1059. }
  1060. void App::SetAccessibilitySupportEnabled(gin_helper::ErrorThrower thrower,
  1061. bool enabled) {
  1062. if (!Browser::Get()->is_ready()) {
  1063. thrower.ThrowError(
  1064. "app.setAccessibilitySupportEnabled() can only be called "
  1065. "after app is ready");
  1066. return;
  1067. }
  1068. auto* ax_state = content::BrowserAccessibilityState::GetInstance();
  1069. if (enabled) {
  1070. ax_state->OnScreenReaderDetected();
  1071. } else {
  1072. ax_state->DisableAccessibility();
  1073. }
  1074. Browser::Get()->OnAccessibilitySupportChanged();
  1075. }
  1076. Browser::LoginItemSettings App::GetLoginItemSettings(gin::Arguments* args) {
  1077. Browser::LoginItemSettings options;
  1078. args->GetNext(&options);
  1079. return Browser::Get()->GetLoginItemSettings(options);
  1080. }
  1081. #if defined(USE_NSS_CERTS)
  1082. void App::ImportCertificate(gin_helper::ErrorThrower thrower,
  1083. base::Value options,
  1084. net::CompletionOnceCallback callback) {
  1085. if (!options.is_dict()) {
  1086. thrower.ThrowTypeError("Expected options to be an object");
  1087. return;
  1088. }
  1089. auto* browser_context = ElectronBrowserContext::From("", false);
  1090. if (!certificate_manager_model_) {
  1091. CertificateManagerModel::Create(
  1092. browser_context,
  1093. base::BindOnce(&App::OnCertificateManagerModelCreated,
  1094. base::Unretained(this), std::move(options),
  1095. std::move(callback)));
  1096. return;
  1097. }
  1098. int rv =
  1099. ImportIntoCertStore(certificate_manager_model_.get(), std::move(options));
  1100. std::move(callback).Run(rv);
  1101. }
  1102. void App::OnCertificateManagerModelCreated(
  1103. base::Value options,
  1104. net::CompletionOnceCallback callback,
  1105. std::unique_ptr<CertificateManagerModel> model) {
  1106. certificate_manager_model_ = std::move(model);
  1107. int rv =
  1108. ImportIntoCertStore(certificate_manager_model_.get(), std::move(options));
  1109. std::move(callback).Run(rv);
  1110. }
  1111. #endif
  1112. #if defined(OS_WIN)
  1113. v8::Local<v8::Value> App::GetJumpListSettings() {
  1114. JumpList jump_list(Browser::Get()->GetAppUserModelID());
  1115. int min_items = 10;
  1116. std::vector<JumpListItem> removed_items;
  1117. if (jump_list.Begin(&min_items, &removed_items)) {
  1118. // We don't actually want to change anything, so abort the transaction.
  1119. jump_list.Abort();
  1120. } else {
  1121. LOG(ERROR) << "Failed to begin Jump List transaction.";
  1122. }
  1123. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1124. gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
  1125. dict.Set("minItems", min_items);
  1126. dict.Set("removedItems", gin::ConvertToV8(isolate, removed_items));
  1127. return dict.GetHandle();
  1128. }
  1129. JumpListResult App::SetJumpList(v8::Local<v8::Value> val,
  1130. gin::Arguments* args) {
  1131. std::vector<JumpListCategory> categories;
  1132. bool delete_jump_list = val->IsNull();
  1133. if (!delete_jump_list &&
  1134. !gin::ConvertFromV8(args->isolate(), val, &categories)) {
  1135. gin_helper::ErrorThrower(args->isolate())
  1136. .ThrowError("Argument must be null or an array of categories");
  1137. return JumpListResult::kArgumentError;
  1138. }
  1139. JumpList jump_list(Browser::Get()->GetAppUserModelID());
  1140. if (delete_jump_list) {
  1141. return jump_list.Delete() ? JumpListResult::kSuccess
  1142. : JumpListResult::kGenericError;
  1143. }
  1144. // Start a transaction that updates the JumpList of this application.
  1145. if (!jump_list.Begin())
  1146. return JumpListResult::kGenericError;
  1147. JumpListResult result = jump_list.AppendCategories(categories);
  1148. // AppendCategories may have failed to add some categories, but it's better
  1149. // to have something than nothing so try to commit the changes anyway.
  1150. if (!jump_list.Commit()) {
  1151. LOG(ERROR) << "Failed to commit changes to custom Jump List.";
  1152. // It's more useful to return the earlier error code that might give
  1153. // some indication as to why the transaction actually failed, so don't
  1154. // overwrite it with a "generic error" code here.
  1155. if (result == JumpListResult::kSuccess)
  1156. result = JumpListResult::kGenericError;
  1157. }
  1158. return result;
  1159. }
  1160. #endif // defined(OS_WIN)
  1161. v8::Local<v8::Promise> App::GetFileIcon(const base::FilePath& path,
  1162. gin::Arguments* args) {
  1163. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1164. gin_helper::Promise<gfx::Image> promise(isolate);
  1165. v8::Local<v8::Promise> handle = promise.GetHandle();
  1166. base::FilePath normalized_path = path.NormalizePathSeparators();
  1167. IconLoader::IconSize icon_size;
  1168. gin_helper::Dictionary options;
  1169. if (!args->GetNext(&options)) {
  1170. icon_size = IconLoader::IconSize::NORMAL;
  1171. } else {
  1172. std::string icon_size_string;
  1173. options.Get("size", &icon_size_string);
  1174. icon_size = GetIconSizeByString(icon_size_string);
  1175. }
  1176. auto* icon_manager = ElectronBrowserMainParts::Get()->GetIconManager();
  1177. gfx::Image* icon =
  1178. icon_manager->LookupIconFromFilepath(normalized_path, icon_size, 1.0f);
  1179. if (icon) {
  1180. promise.Resolve(*icon);
  1181. } else {
  1182. icon_manager->LoadIcon(
  1183. normalized_path, icon_size, 1.0f,
  1184. base::BindOnce(&OnIconDataAvailable, std::move(promise)),
  1185. &cancelable_task_tracker_);
  1186. }
  1187. return handle;
  1188. }
  1189. std::vector<gin_helper::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
  1190. std::vector<gin_helper::Dictionary> result;
  1191. result.reserve(app_metrics_.size());
  1192. int processor_count = base::SysInfo::NumberOfProcessors();
  1193. for (const auto& process_metric : app_metrics_) {
  1194. gin_helper::Dictionary pid_dict = gin::Dictionary::CreateEmpty(isolate);
  1195. gin_helper::Dictionary cpu_dict = gin::Dictionary::CreateEmpty(isolate);
  1196. pid_dict.SetHidden("simple", true);
  1197. cpu_dict.SetHidden("simple", true);
  1198. cpu_dict.Set(
  1199. "percentCPUUsage",
  1200. process_metric.second->metrics->GetPlatformIndependentCPUUsage() /
  1201. processor_count);
  1202. #if !defined(OS_WIN)
  1203. cpu_dict.Set("idleWakeupsPerSecond",
  1204. process_metric.second->metrics->GetIdleWakeupsPerSecond());
  1205. #else
  1206. // Chrome's underlying process_metrics.cc will throw a non-fatal warning
  1207. // that this method isn't implemented on Windows, so set it to 0 instead
  1208. // of calling it
  1209. cpu_dict.Set("idleWakeupsPerSecond", 0);
  1210. #endif
  1211. pid_dict.Set("cpu", cpu_dict);
  1212. pid_dict.Set("pid", process_metric.second->process.Pid());
  1213. pid_dict.Set("type", content::GetProcessTypeNameInEnglish(
  1214. process_metric.second->type));
  1215. pid_dict.Set("creationTime",
  1216. process_metric.second->process.CreationTime().ToJsTime());
  1217. if (!process_metric.second->service_name.empty()) {
  1218. pid_dict.Set("serviceName", process_metric.second->service_name);
  1219. }
  1220. if (!process_metric.second->name.empty()) {
  1221. pid_dict.Set("name", process_metric.second->name);
  1222. }
  1223. #if !defined(OS_LINUX)
  1224. auto memory_info = process_metric.second->GetMemoryInfo();
  1225. gin_helper::Dictionary memory_dict = gin::Dictionary::CreateEmpty(isolate);
  1226. memory_dict.SetHidden("simple", true);
  1227. memory_dict.Set("workingSetSize",
  1228. static_cast<double>(memory_info.working_set_size >> 10));
  1229. memory_dict.Set(
  1230. "peakWorkingSetSize",
  1231. static_cast<double>(memory_info.peak_working_set_size >> 10));
  1232. #if defined(OS_WIN)
  1233. memory_dict.Set("privateBytes",
  1234. static_cast<double>(memory_info.private_bytes >> 10));
  1235. #endif
  1236. pid_dict.Set("memory", memory_dict);
  1237. #endif
  1238. #if defined(OS_MAC)
  1239. pid_dict.Set("sandboxed", process_metric.second->IsSandboxed());
  1240. #elif defined(OS_WIN)
  1241. auto integrity_level = process_metric.second->GetIntegrityLevel();
  1242. auto sandboxed = ProcessMetric::IsSandboxed(integrity_level);
  1243. pid_dict.Set("integrityLevel", integrity_level);
  1244. pid_dict.Set("sandboxed", sandboxed);
  1245. #endif
  1246. result.push_back(pid_dict);
  1247. }
  1248. return result;
  1249. }
  1250. v8::Local<v8::Value> App::GetGPUFeatureStatus(v8::Isolate* isolate) {
  1251. return gin::ConvertToV8(isolate, content::GetFeatureStatus());
  1252. }
  1253. v8::Local<v8::Promise> App::GetGPUInfo(v8::Isolate* isolate,
  1254. const std::string& info_type) {
  1255. auto* const gpu_data_manager = content::GpuDataManagerImpl::GetInstance();
  1256. gin_helper::Promise<base::DictionaryValue> promise(isolate);
  1257. v8::Local<v8::Promise> handle = promise.GetHandle();
  1258. if (info_type != "basic" && info_type != "complete") {
  1259. promise.RejectWithErrorMessage(
  1260. "Invalid info type. Use 'basic' or 'complete'");
  1261. return handle;
  1262. }
  1263. std::string reason;
  1264. if (!gpu_data_manager->GpuAccessAllowed(&reason)) {
  1265. promise.RejectWithErrorMessage("GPU access not allowed. Reason: " + reason);
  1266. return handle;
  1267. }
  1268. auto* const info_mgr = GPUInfoManager::GetInstance();
  1269. if (info_type == "complete") {
  1270. #if defined(OS_WIN) || defined(OS_MAC)
  1271. info_mgr->FetchCompleteInfo(std::move(promise));
  1272. #else
  1273. info_mgr->FetchBasicInfo(std::move(promise));
  1274. #endif
  1275. } else /* (info_type == "basic") */ {
  1276. info_mgr->FetchBasicInfo(std::move(promise));
  1277. }
  1278. return handle;
  1279. }
  1280. static void RemoveNoSandboxSwitch(base::CommandLine* command_line) {
  1281. if (command_line->HasSwitch(sandbox::policy::switches::kNoSandbox)) {
  1282. const base::CommandLine::CharType* noSandboxArg =
  1283. FILE_PATH_LITERAL("--no-sandbox");
  1284. base::CommandLine::StringVector modified_command_line;
  1285. for (auto& arg : command_line->argv()) {
  1286. if (arg.compare(noSandboxArg) != 0) {
  1287. modified_command_line.push_back(arg);
  1288. }
  1289. }
  1290. command_line->InitFromArgv(modified_command_line);
  1291. }
  1292. }
  1293. void App::EnableSandbox(gin_helper::ErrorThrower thrower) {
  1294. if (Browser::Get()->is_ready()) {
  1295. thrower.ThrowError(
  1296. "app.enableSandbox() can only be called "
  1297. "before app is ready");
  1298. return;
  1299. }
  1300. auto* command_line = base::CommandLine::ForCurrentProcess();
  1301. RemoveNoSandboxSwitch(command_line);
  1302. command_line->AppendSwitch(switches::kEnableSandbox);
  1303. }
  1304. void App::SetUserAgentFallback(const std::string& user_agent) {
  1305. ElectronBrowserClient::Get()->SetUserAgent(user_agent);
  1306. }
  1307. #if defined(OS_WIN)
  1308. bool App::IsRunningUnderARM64Translation() const {
  1309. USHORT processMachine = 0;
  1310. USHORT nativeMachine = 0;
  1311. auto IsWow64Process2 = reinterpret_cast<decltype(&::IsWow64Process2)>(
  1312. GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process2"));
  1313. if (IsWow64Process2 == nullptr) {
  1314. return false;
  1315. }
  1316. if (!IsWow64Process2(GetCurrentProcess(), &processMachine, &nativeMachine)) {
  1317. return false;
  1318. }
  1319. return nativeMachine == IMAGE_FILE_MACHINE_ARM64;
  1320. }
  1321. #endif
  1322. std::string App::GetUserAgentFallback() {
  1323. return ElectronBrowserClient::Get()->GetUserAgent();
  1324. }
  1325. #if defined(OS_MAC)
  1326. bool App::MoveToApplicationsFolder(gin_helper::ErrorThrower thrower,
  1327. gin::Arguments* args) {
  1328. return ElectronBundleMover::Move(thrower, args);
  1329. }
  1330. bool App::IsInApplicationsFolder() {
  1331. return ElectronBundleMover::IsCurrentAppInApplicationsFolder();
  1332. }
  1333. int DockBounce(gin::Arguments* args) {
  1334. int request_id = -1;
  1335. std::string type = "informational";
  1336. args->GetNext(&type);
  1337. if (type == "critical")
  1338. request_id = Browser::Get()->DockBounce(Browser::BounceType::kCritical);
  1339. else if (type == "informational")
  1340. request_id =
  1341. Browser::Get()->DockBounce(Browser::BounceType::kInformational);
  1342. return request_id;
  1343. }
  1344. void DockSetMenu(electron::api::Menu* menu) {
  1345. Browser::Get()->DockSetMenu(menu->model());
  1346. }
  1347. v8::Local<v8::Value> App::GetDockAPI(v8::Isolate* isolate) {
  1348. if (dock_.IsEmpty()) {
  1349. // Initialize the Dock API, the methods are bound to "dock" which exists
  1350. // for the lifetime of "app"
  1351. auto browser = base::Unretained(Browser::Get());
  1352. gin_helper::Dictionary dock_obj = gin::Dictionary::CreateEmpty(isolate);
  1353. dock_obj.SetMethod("bounce", &DockBounce);
  1354. dock_obj.SetMethod(
  1355. "cancelBounce",
  1356. base::BindRepeating(&Browser::DockCancelBounce, browser));
  1357. dock_obj.SetMethod(
  1358. "downloadFinished",
  1359. base::BindRepeating(&Browser::DockDownloadFinished, browser));
  1360. dock_obj.SetMethod(
  1361. "setBadge", base::BindRepeating(&Browser::DockSetBadgeText, browser));
  1362. dock_obj.SetMethod(
  1363. "getBadge", base::BindRepeating(&Browser::DockGetBadgeText, browser));
  1364. dock_obj.SetMethod("hide",
  1365. base::BindRepeating(&Browser::DockHide, browser));
  1366. dock_obj.SetMethod("show",
  1367. base::BindRepeating(&Browser::DockShow, browser));
  1368. dock_obj.SetMethod("isVisible",
  1369. base::BindRepeating(&Browser::DockIsVisible, browser));
  1370. dock_obj.SetMethod("setMenu", &DockSetMenu);
  1371. dock_obj.SetMethod("setIcon",
  1372. base::BindRepeating(&Browser::DockSetIcon, browser));
  1373. dock_.Reset(isolate, dock_obj.GetHandle());
  1374. }
  1375. return v8::Local<v8::Value>::New(isolate, dock_);
  1376. }
  1377. #endif
  1378. void ConfigureHostResolver(v8::Isolate* isolate,
  1379. const gin_helper::Dictionary& opts) {
  1380. gin_helper::ErrorThrower thrower(isolate);
  1381. net::SecureDnsMode secure_dns_mode = net::SecureDnsMode::kOff;
  1382. std::string default_doh_templates;
  1383. if (base::FeatureList::IsEnabled(features::kDnsOverHttps)) {
  1384. if (features::kDnsOverHttpsFallbackParam.Get()) {
  1385. secure_dns_mode = net::SecureDnsMode::kAutomatic;
  1386. } else {
  1387. secure_dns_mode = net::SecureDnsMode::kSecure;
  1388. }
  1389. default_doh_templates = features::kDnsOverHttpsTemplatesParam.Get();
  1390. }
  1391. std::string server_method;
  1392. std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
  1393. absl::optional<std::vector<network::mojom::DnsOverHttpsServerPtr>>
  1394. servers_mojo;
  1395. if (!default_doh_templates.empty() &&
  1396. secure_dns_mode != net::SecureDnsMode::kOff) {
  1397. for (base::StringPiece server_template :
  1398. SplitStringPiece(default_doh_templates, " ", base::TRIM_WHITESPACE,
  1399. base::SPLIT_WANT_NONEMPTY)) {
  1400. if (!net::dns_util::IsValidDohTemplate(server_template, &server_method)) {
  1401. continue;
  1402. }
  1403. bool use_post = server_method == "POST";
  1404. dns_over_https_servers.emplace_back(std::string(server_template),
  1405. use_post);
  1406. if (!servers_mojo.has_value()) {
  1407. servers_mojo = absl::make_optional<
  1408. std::vector<network::mojom::DnsOverHttpsServerPtr>>();
  1409. }
  1410. network::mojom::DnsOverHttpsServerPtr server_mojo =
  1411. network::mojom::DnsOverHttpsServer::New();
  1412. server_mojo->server_template = std::string(server_template);
  1413. server_mojo->use_post = use_post;
  1414. servers_mojo->emplace_back(std::move(server_mojo));
  1415. }
  1416. }
  1417. bool enable_built_in_resolver =
  1418. base::FeatureList::IsEnabled(features::kAsyncDns);
  1419. bool additional_dns_query_types_enabled = true;
  1420. if (opts.Has("enableBuiltInResolver") &&
  1421. !opts.Get("enableBuiltInResolver", &enable_built_in_resolver)) {
  1422. thrower.ThrowTypeError("enableBuiltInResolver must be a boolean");
  1423. return;
  1424. }
  1425. if (opts.Has("secureDnsMode") &&
  1426. !opts.Get("secureDnsMode", &secure_dns_mode)) {
  1427. thrower.ThrowTypeError(
  1428. "secureDnsMode must be one of: off, automatic, secure");
  1429. return;
  1430. }
  1431. std::vector<std::string> secure_dns_server_strings;
  1432. if (opts.Has("secureDnsServers")) {
  1433. if (!opts.Get("secureDnsServers", &secure_dns_server_strings)) {
  1434. thrower.ThrowTypeError("secureDnsServers must be an array of strings");
  1435. return;
  1436. }
  1437. servers_mojo = absl::nullopt;
  1438. for (const std::string& server_template : secure_dns_server_strings) {
  1439. std::string server_method;
  1440. if (!net::dns_util::IsValidDohTemplate(server_template, &server_method)) {
  1441. thrower.ThrowTypeError(std::string("not a valid DoH template: ") +
  1442. server_template);
  1443. return;
  1444. }
  1445. bool use_post = server_method == "POST";
  1446. if (!servers_mojo.has_value()) {
  1447. servers_mojo = absl::make_optional<
  1448. std::vector<network::mojom::DnsOverHttpsServerPtr>>();
  1449. }
  1450. network::mojom::DnsOverHttpsServerPtr server_mojo =
  1451. network::mojom::DnsOverHttpsServer::New();
  1452. server_mojo->server_template = std::string(server_template);
  1453. server_mojo->use_post = use_post;
  1454. servers_mojo->emplace_back(std::move(server_mojo));
  1455. }
  1456. }
  1457. if (opts.Has("enableAdditionalDnsQueryTypes") &&
  1458. !opts.Get("enableAdditionalDnsQueryTypes",
  1459. &additional_dns_query_types_enabled)) {
  1460. thrower.ThrowTypeError("enableAdditionalDnsQueryTypes must be a boolean");
  1461. return;
  1462. }
  1463. // Configure the stub resolver. This must be done after the system
  1464. // NetworkContext is created, but before anything has the chance to use it.
  1465. content::GetNetworkService()->ConfigureStubHostResolver(
  1466. enable_built_in_resolver, secure_dns_mode, std::move(servers_mojo),
  1467. additional_dns_query_types_enabled);
  1468. }
  1469. // static
  1470. App* App::Get() {
  1471. static base::NoDestructor<App> app;
  1472. return app.get();
  1473. }
  1474. // static
  1475. gin::Handle<App> App::Create(v8::Isolate* isolate) {
  1476. return gin::CreateHandle(isolate, Get());
  1477. }
  1478. gin::ObjectTemplateBuilder App::GetObjectTemplateBuilder(v8::Isolate* isolate) {
  1479. auto browser = base::Unretained(Browser::Get());
  1480. return gin_helper::EventEmitterMixin<App>::GetObjectTemplateBuilder(isolate)
  1481. .SetMethod("quit", base::BindRepeating(&Browser::Quit, browser))
  1482. .SetMethod("exit", base::BindRepeating(&Browser::Exit, browser))
  1483. .SetMethod("focus", base::BindRepeating(&Browser::Focus, browser))
  1484. .SetMethod("getVersion",
  1485. base::BindRepeating(&Browser::GetVersion, browser))
  1486. .SetMethod("setVersion",
  1487. base::BindRepeating(&Browser::SetVersion, browser))
  1488. .SetMethod("getName", base::BindRepeating(&Browser::GetName, browser))
  1489. .SetMethod("setName", base::BindRepeating(&Browser::SetName, browser))
  1490. .SetMethod("isReady", base::BindRepeating(&Browser::is_ready, browser))
  1491. .SetMethod("whenReady", base::BindRepeating(&Browser::WhenReady, browser))
  1492. .SetMethod("addRecentDocument",
  1493. base::BindRepeating(&Browser::AddRecentDocument, browser))
  1494. .SetMethod("clearRecentDocuments",
  1495. base::BindRepeating(&Browser::ClearRecentDocuments, browser))
  1496. #if defined(OS_WIN)
  1497. .SetMethod("setAppUserModelId",
  1498. base::BindRepeating(&Browser::SetAppUserModelID, browser))
  1499. #endif
  1500. .SetMethod(
  1501. "isDefaultProtocolClient",
  1502. base::BindRepeating(&Browser::IsDefaultProtocolClient, browser))
  1503. .SetMethod(
  1504. "setAsDefaultProtocolClient",
  1505. base::BindRepeating(&Browser::SetAsDefaultProtocolClient, browser))
  1506. .SetMethod(
  1507. "removeAsDefaultProtocolClient",
  1508. base::BindRepeating(&Browser::RemoveAsDefaultProtocolClient, browser))
  1509. #if !defined(OS_LINUX)
  1510. .SetMethod(
  1511. "getApplicationInfoForProtocol",
  1512. base::BindRepeating(&Browser::GetApplicationInfoForProtocol, browser))
  1513. #endif
  1514. .SetMethod(
  1515. "getApplicationNameForProtocol",
  1516. base::BindRepeating(&Browser::GetApplicationNameForProtocol, browser))
  1517. .SetMethod("setBadgeCount",
  1518. base::BindRepeating(&Browser::SetBadgeCount, browser))
  1519. .SetMethod("getBadgeCount",
  1520. base::BindRepeating(&Browser::GetBadgeCount, browser))
  1521. .SetMethod("getLoginItemSettings", &App::GetLoginItemSettings)
  1522. .SetMethod("setLoginItemSettings",
  1523. base::BindRepeating(&Browser::SetLoginItemSettings, browser))
  1524. .SetMethod("isEmojiPanelSupported",
  1525. base::BindRepeating(&Browser::IsEmojiPanelSupported, browser))
  1526. #if defined(OS_MAC)
  1527. .SetMethod("hide", base::BindRepeating(&Browser::Hide, browser))
  1528. .SetMethod("show", base::BindRepeating(&Browser::Show, browser))
  1529. .SetMethod("setUserActivity",
  1530. base::BindRepeating(&Browser::SetUserActivity, browser))
  1531. .SetMethod("getCurrentActivityType",
  1532. base::BindRepeating(&Browser::GetCurrentActivityType, browser))
  1533. .SetMethod(
  1534. "invalidateCurrentActivity",
  1535. base::BindRepeating(&Browser::InvalidateCurrentActivity, browser))
  1536. .SetMethod("resignCurrentActivity",
  1537. base::BindRepeating(&Browser::ResignCurrentActivity, browser))
  1538. .SetMethod("updateCurrentActivity",
  1539. base::BindRepeating(&Browser::UpdateCurrentActivity, browser))
  1540. .SetMethod("moveToApplicationsFolder", &App::MoveToApplicationsFolder)
  1541. .SetMethod("isInApplicationsFolder", &App::IsInApplicationsFolder)
  1542. .SetMethod("setActivationPolicy", &App::SetActivationPolicy)
  1543. #endif
  1544. .SetMethod("setAboutPanelOptions",
  1545. base::BindRepeating(&Browser::SetAboutPanelOptions, browser))
  1546. .SetMethod("showAboutPanel",
  1547. base::BindRepeating(&Browser::ShowAboutPanel, browser))
  1548. #if defined(OS_MAC)
  1549. .SetMethod(
  1550. "isSecureKeyboardEntryEnabled",
  1551. base::BindRepeating(&Browser::IsSecureKeyboardEntryEnabled, browser))
  1552. .SetMethod(
  1553. "setSecureKeyboardEntryEnabled",
  1554. base::BindRepeating(&Browser::SetSecureKeyboardEntryEnabled, browser))
  1555. #endif
  1556. #if defined(OS_MAC) || defined(OS_WIN)
  1557. .SetMethod("showEmojiPanel",
  1558. base::BindRepeating(&Browser::ShowEmojiPanel, browser))
  1559. #endif
  1560. #if defined(OS_WIN)
  1561. .SetMethod("setUserTasks",
  1562. base::BindRepeating(&Browser::SetUserTasks, browser))
  1563. .SetMethod("getJumpListSettings", &App::GetJumpListSettings)
  1564. .SetMethod("setJumpList", &App::SetJumpList)
  1565. #endif
  1566. #if defined(OS_LINUX)
  1567. .SetMethod("isUnityRunning",
  1568. base::BindRepeating(&Browser::IsUnityRunning, browser))
  1569. #endif
  1570. .SetProperty("isPackaged", &App::IsPackaged)
  1571. .SetMethod("setAppPath", &App::SetAppPath)
  1572. .SetMethod("getAppPath", &App::GetAppPath)
  1573. .SetMethod("setPath", &App::SetPath)
  1574. .SetMethod("getPath", &App::GetPath)
  1575. .SetMethod("setAppLogsPath", &App::SetAppLogsPath)
  1576. .SetMethod("setDesktopName", &App::SetDesktopName)
  1577. .SetMethod("getLocale", &App::GetLocale)
  1578. .SetMethod("getLocaleCountryCode", &App::GetLocaleCountryCode)
  1579. #if defined(USE_NSS_CERTS)
  1580. .SetMethod("importCertificate", &App::ImportCertificate)
  1581. #endif
  1582. .SetMethod("hasSingleInstanceLock", &App::HasSingleInstanceLock)
  1583. .SetMethod("requestSingleInstanceLock", &App::RequestSingleInstanceLock)
  1584. .SetMethod("releaseSingleInstanceLock", &App::ReleaseSingleInstanceLock)
  1585. .SetMethod("relaunch", &App::Relaunch)
  1586. .SetMethod("isAccessibilitySupportEnabled",
  1587. &App::IsAccessibilitySupportEnabled)
  1588. .SetMethod("setAccessibilitySupportEnabled",
  1589. &App::SetAccessibilitySupportEnabled)
  1590. .SetMethod("disableHardwareAcceleration",
  1591. &App::DisableHardwareAcceleration)
  1592. .SetMethod("disableDomainBlockingFor3DAPIs",
  1593. &App::DisableDomainBlockingFor3DAPIs)
  1594. .SetMethod("getFileIcon", &App::GetFileIcon)
  1595. .SetMethod("getAppMetrics", &App::GetAppMetrics)
  1596. .SetMethod("getGPUFeatureStatus", &App::GetGPUFeatureStatus)
  1597. .SetMethod("getGPUInfo", &App::GetGPUInfo)
  1598. #if defined(MAS_BUILD)
  1599. .SetMethod("startAccessingSecurityScopedResource",
  1600. &App::StartAccessingSecurityScopedResource)
  1601. #endif
  1602. #if defined(OS_MAC)
  1603. .SetProperty("dock", &App::GetDockAPI)
  1604. .SetProperty("runningUnderRosettaTranslation",
  1605. &App::IsRunningUnderRosettaTranslation)
  1606. #endif
  1607. #if defined(OS_MAC) || defined(OS_WIN)
  1608. .SetProperty("runningUnderARM64Translation",
  1609. &App::IsRunningUnderARM64Translation)
  1610. #endif
  1611. .SetProperty("userAgentFallback", &App::GetUserAgentFallback,
  1612. &App::SetUserAgentFallback)
  1613. .SetMethod("configureHostResolver", &ConfigureHostResolver)
  1614. .SetMethod("enableSandbox", &App::EnableSandbox);
  1615. }
  1616. const char* App::GetTypeName() {
  1617. return "App";
  1618. }
  1619. } // namespace api
  1620. } // namespace electron
  1621. namespace {
  1622. void Initialize(v8::Local<v8::Object> exports,
  1623. v8::Local<v8::Value> unused,
  1624. v8::Local<v8::Context> context,
  1625. void* priv) {
  1626. v8::Isolate* isolate = context->GetIsolate();
  1627. gin_helper::Dictionary dict(isolate, exports);
  1628. dict.Set("app", electron::api::App::Create(isolate));
  1629. }
  1630. } // namespace
  1631. NODE_LINKED_MODULE_CONTEXT_AWARE(electron_browser_app, Initialize)