electron-master\electron-master\shell\browser\api\atom_api_web_contents.cc

  1. // Copyright (c) 2014 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4.  
  5. #include "shell/browser/api/atom_api_web_contents.h"
  6.  
  7. #include <memory>
  8. #include <set>
  9. #include <string>
  10. #include <utility>
  11. #include <vector>
  12.  
  13. #include "base/message_loop/message_loop_current.h"
  14. #include "base/no_destructor.h"
  15. #include "base/optional.h"
  16. #include "base/strings/utf_string_conversions.h"
  17. #include "base/threading/thread_restrictions.h"
  18. #include "base/threading/thread_task_runner_handle.h"
  19. #include "base/values.h"
  20. #include "chrome/browser/browser_process.h"
  21. #include "chrome/browser/ssl/security_state_tab_helper.h"
  22. #include "content/browser/frame_host/frame_tree_node.h" // nogncheck
  23. #include "content/browser/frame_host/render_frame_host_manager.h" // nogncheck
  24. #include "content/browser/renderer_host/render_widget_host_impl.h" // nogncheck
  25. #include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck
  26. #include "content/common/widget_messages.h"
  27. #include "content/public/browser/child_process_security_policy.h"
  28. #include "content/public/browser/download_request_utils.h"
  29. #include "content/public/browser/favicon_status.h"
  30. #include "content/public/browser/native_web_keyboard_event.h"
  31. #include "content/public/browser/navigation_details.h"
  32. #include "content/public/browser/navigation_entry.h"
  33. #include "content/public/browser/navigation_handle.h"
  34. #include "content/public/browser/plugin_service.h"
  35. #include "content/public/browser/render_frame_host.h"
  36. #include "content/public/browser/render_process_host.h"
  37. #include "content/public/browser/render_view_host.h"
  38. #include "content/public/browser/render_widget_host.h"
  39. #include "content/public/browser/render_widget_host_view.h"
  40. #include "content/public/browser/service_worker_context.h"
  41. #include "content/public/browser/site_instance.h"
  42. #include "content/public/browser/storage_partition.h"
  43. #include "content/public/browser/web_contents.h"
  44. #include "content/public/common/context_menu_params.h"
  45. #include "electron/buildflags/buildflags.h"
  46. #include "electron/shell/common/api/api.mojom.h"
  47. #include "mojo/public/cpp/bindings/associated_remote.h"
  48. #include "mojo/public/cpp/system/platform_handle.h"
  49. #include "ppapi/buildflags/buildflags.h"
  50. #include "shell/browser/api/atom_api_browser_window.h"
  51. #include "shell/browser/api/atom_api_debugger.h"
  52. #include "shell/browser/api/atom_api_session.h"
  53. #include "shell/browser/atom_autofill_driver_factory.h"
  54. #include "shell/browser/atom_browser_client.h"
  55. #include "shell/browser/atom_browser_context.h"
  56. #include "shell/browser/atom_browser_main_parts.h"
  57. #include "shell/browser/atom_javascript_dialog_manager.h"
  58. #include "shell/browser/atom_navigation_throttle.h"
  59. #include "shell/browser/browser.h"
  60. #include "shell/browser/child_web_contents_tracker.h"
  61. #include "shell/browser/lib/bluetooth_chooser.h"
  62. #include "shell/browser/native_window.h"
  63. #include "shell/browser/session_preferences.h"
  64. #include "shell/browser/ui/drag_util.h"
  65. #include "shell/browser/ui/inspectable_web_contents.h"
  66. #include "shell/browser/ui/inspectable_web_contents_view.h"
  67. #include "shell/browser/web_contents_permission_helper.h"
  68. #include "shell/browser/web_contents_preferences.h"
  69. #include "shell/browser/web_contents_zoom_controller.h"
  70. #include "shell/browser/web_view_guest_delegate.h"
  71. #include "shell/common/api/atom_api_native_image.h"
  72. #include "shell/common/color_util.h"
  73. #include "shell/common/gin_converters/blink_converter.h"
  74. #include "shell/common/gin_converters/callback_converter.h"
  75. #include "shell/common/gin_converters/content_converter.h"
  76. #include "shell/common/gin_converters/file_path_converter.h"
  77. #include "shell/common/gin_converters/gfx_converter.h"
  78. #include "shell/common/gin_converters/gurl_converter.h"
  79. #include "shell/common/gin_converters/image_converter.h"
  80. #include "shell/common/gin_converters/net_converter.h"
  81. #include "shell/common/gin_converters/value_converter.h"
  82. #include "shell/common/gin_helper/dictionary.h"
  83. #include "shell/common/gin_helper/object_template_builder.h"
  84. #include "shell/common/mouse_util.h"
  85. #include "shell/common/node_includes.h"
  86. #include "shell/common/options_switches.h"
  87. #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
  88. #include "third_party/blink/public/common/page/page_zoom.h"
  89. #include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
  90. #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
  91. #include "third_party/blink/public/platform/web_cursor_info.h"
  92. #include "third_party/blink/public/platform/web_input_event.h"
  93. #include "ui/display/screen.h"
  94. #include "ui/events/base_event_utils.h"
  95.  
  96. #if BUILDFLAG(ENABLE_OSR)
  97. #include "shell/browser/osr/osr_render_widget_host_view.h"
  98. #include "shell/browser/osr/osr_web_contents_view.h"
  99. #endif
  100.  
  101. #if !defined(OS_MACOSX)
  102. #include "ui/aura/window.h"
  103. #else
  104. #include "ui/base/cocoa/defaults_utils.h"
  105. #endif
  106.  
  107. #if defined(OS_LINUX)
  108. #include "ui/views/linux_ui/linux_ui.h"
  109. #endif
  110.  
  111. #if defined(OS_LINUX) || defined(OS_WIN)
  112. #include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
  113. #include "ui/gfx/font_render_params.h"
  114. #endif
  115.  
  116. #if BUILDFLAG(ENABLE_PRINTING)
  117. #include "chrome/browser/printing/print_view_manager_basic.h"
  118. #include "components/printing/common/print_messages.h"
  119. #endif
  120.  
  121. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  122. #include "shell/browser/extensions/atom_extension_web_contents_observer.h"
  123. #endif
  124.  
  125. namespace gin {
  126.  
  127. #if BUILDFLAG(ENABLE_PRINTING)
  128. template <>
  129. struct Converter<printing::PrinterBasicInfo> {
  130. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  131. const printing::PrinterBasicInfo& val) {
  132. gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
  133. dict.Set("name", val.printer_name);
  134. dict.Set("displayName", val.display_name);
  135. dict.Set("description", val.printer_description);
  136. dict.Set("status", val.printer_status);
  137. dict.Set("isDefault", val.is_default ? true : false);
  138. dict.Set("options", val.options);
  139. return dict.GetHandle();
  140. }
  141. };
  142.  
  143. template <>
  144. struct Converter<printing::MarginType> {
  145. static bool FromV8(v8::Isolate* isolate,
  146. v8::Local<v8::Value> val,
  147. printing::MarginType* out) {
  148. std::string type;
  149. if (ConvertFromV8(isolate, val, &type)) {
  150. if (type == "default") {
  151. *out = printing::DEFAULT_MARGINS;
  152. return true;
  153. }
  154. if (type == "none") {
  155. *out = printing::NO_MARGINS;
  156. return true;
  157. }
  158. if (type == "printableArea") {
  159. *out = printing::PRINTABLE_AREA_MARGINS;
  160. return true;
  161. }
  162. if (type == "custom") {
  163. *out = printing::CUSTOM_MARGINS;
  164. return true;
  165. }
  166. }
  167. return false;
  168. }
  169. };
  170.  
  171. template <>
  172. struct Converter<printing::DuplexMode> {
  173. static bool FromV8(v8::Isolate* isolate,
  174. v8::Local<v8::Value> val,
  175. printing::DuplexMode* out) {
  176. std::string mode;
  177. if (ConvertFromV8(isolate, val, &mode)) {
  178. if (mode == "simplex") {
  179. *out = printing::SIMPLEX;
  180. return true;
  181. }
  182. if (mode == "longEdge") {
  183. *out = printing::LONG_EDGE;
  184. return true;
  185. }
  186. if (mode == "shortEdge") {
  187. *out = printing::SHORT_EDGE;
  188. return true;
  189. }
  190. }
  191. return false;
  192. }
  193. };
  194.  
  195. #endif
  196.  
  197. template <>
  198. struct Converter<WindowOpenDisposition> {
  199. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  200. WindowOpenDisposition val) {
  201. std::string disposition = "other";
  202. switch (val) {
  203. case WindowOpenDisposition::CURRENT_TAB:
  204. disposition = "default";
  205. break;
  206. case WindowOpenDisposition::NEW_FOREGROUND_TAB:
  207. disposition = "foreground-tab";
  208. break;
  209. case WindowOpenDisposition::NEW_BACKGROUND_TAB:
  210. disposition = "background-tab";
  211. break;
  212. case WindowOpenDisposition::NEW_POPUP:
  213. case WindowOpenDisposition::NEW_WINDOW:
  214. disposition = "new-window";
  215. break;
  216. case WindowOpenDisposition::SAVE_TO_DISK:
  217. disposition = "save-to-disk";
  218. break;
  219. default:
  220. break;
  221. }
  222. return gin::ConvertToV8(isolate, disposition);
  223. }
  224. };
  225.  
  226. template <>
  227. struct Converter<content::SavePageType> {
  228. static bool FromV8(v8::Isolate* isolate,
  229. v8::Local<v8::Value> val,
  230. content::SavePageType* out) {
  231. std::string save_type;
  232. if (!ConvertFromV8(isolate, val, &save_type))
  233. return false;
  234. save_type = base::ToLowerASCII(save_type);
  235. if (save_type == "htmlonly") {
  236. *out = content::SAVE_PAGE_TYPE_AS_ONLY_HTML;
  237. } else if (save_type == "htmlcomplete") {
  238. *out = content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML;
  239. } else if (save_type == "mhtml") {
  240. *out = content::SAVE_PAGE_TYPE_AS_MHTML;
  241. } else {
  242. return false;
  243. }
  244. return true;
  245. }
  246. };
  247.  
  248. template <>
  249. struct Converter<electron::api::WebContents::Type> {
  250. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  251. electron::api::WebContents::Type val) {
  252. using Type = electron::api::WebContents::Type;
  253. std::string type;
  254. switch (val) {
  255. case Type::BACKGROUND_PAGE:
  256. type = "backgroundPage";
  257. break;
  258. case Type::BROWSER_WINDOW:
  259. type = "window";
  260. break;
  261. case Type::BROWSER_VIEW:
  262. type = "browserView";
  263. break;
  264. case Type::REMOTE:
  265. type = "remote";
  266. break;
  267. case Type::WEB_VIEW:
  268. type = "webview";
  269. break;
  270. case Type::OFF_SCREEN:
  271. type = "offscreen";
  272. break;
  273. default:
  274. break;
  275. }
  276. return gin::ConvertToV8(isolate, type);
  277. }
  278.  
  279. static bool FromV8(v8::Isolate* isolate,
  280. v8::Local<v8::Value> val,
  281. electron::api::WebContents::Type* out) {
  282. using Type = electron::api::WebContents::Type;
  283. std::string type;
  284. if (!ConvertFromV8(isolate, val, &type))
  285. return false;
  286. if (type == "backgroundPage") {
  287. *out = Type::BACKGROUND_PAGE;
  288. } else if (type == "browserView") {
  289. *out = Type::BROWSER_VIEW;
  290. } else if (type == "webview") {
  291. *out = Type::WEB_VIEW;
  292. #if BUILDFLAG(ENABLE_OSR)
  293. } else if (type == "offscreen") {
  294. *out = Type::OFF_SCREEN;
  295. #endif
  296. } else {
  297. return false;
  298. }
  299. return true;
  300. }
  301. };
  302.  
  303. template <>
  304. struct Converter<scoped_refptr<content::DevToolsAgentHost>> {
  305. static v8::Local<v8::Value> ToV8(
  306. v8::Isolate* isolate,
  307. const scoped_refptr<content::DevToolsAgentHost>& val) {
  308. gin_helper::Dictionary dict(isolate, v8::Object::New(isolate));
  309. dict.Set("id", val->GetId());
  310. dict.Set("url", val->GetURL().spec());
  311. return dict.GetHandle();
  312. }
  313. };
  314.  
  315. } // namespace gin
  316.  
  317. namespace electron {
  318.  
  319. namespace api {
  320.  
  321. namespace {
  322.  
  323. // Called when CapturePage is done.
  324. void OnCapturePageDone(gin_helper::Promise<gfx::Image> promise,
  325. const SkBitmap& bitmap) {
  326. // Hack to enable transparency in captured image
  327. promise.Resolve(gfx::Image::CreateFrom1xBitmap(bitmap));
  328. }
  329.  
  330. base::Optional<base::TimeDelta> GetCursorBlinkInterval() {
  331. #if defined(OS_MACOSX)
  332. base::TimeDelta interval;
  333. if (ui::TextInsertionCaretBlinkPeriod(&interval))
  334. return interval;
  335. #elif defined(OS_LINUX)
  336. if (auto* linux_ui = views::LinuxUI::instance())
  337. return linux_ui->GetCursorBlinkInterval();
  338. #elif defined(OS_WIN)
  339. const auto system_msec = ::GetCaretBlinkTime();
  340. if (system_msec != ) {
  341. return (system_msec == INFINITE)
  342. ? base::TimeDelta()
  343. : base::TimeDelta::FromMilliseconds(system_msec);
  344. }
  345. #endif
  346. return base::nullopt;
  347. }
  348.  
  349. } // namespace
  350.  
  351. WebContents::WebContents(v8::Isolate* isolate,
  352. content::WebContents* web_contents)
  353. : content::WebContentsObserver(web_contents),
  354. type_(Type::REMOTE),
  355. weak_factory_(this) {
  356. web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent(),
  357. false);
  358. Init(isolate);
  359. AttachAsUserData(web_contents);
  360. InitZoomController(web_contents, gin::Dictionary::CreateEmpty(isolate));
  361. registry_.AddInterface(base::BindRepeating(&WebContents::BindElectronBrowser,
  362. base::Unretained(this)));
  363. bindings_.set_connection_error_handler(base::BindRepeating(
  364. &WebContents::OnElectronBrowserConnectionError, base::Unretained(this)));
  365. }
  366.  
  367. WebContents::WebContents(v8::Isolate* isolate,
  368. std::unique_ptr<content::WebContents> web_contents,
  369. Type type)
  370. : content::WebContentsObserver(web_contents.get()),
  371. type_(type),
  372. weak_factory_(this) {
  373. DCHECK(type != Type::REMOTE)
  374. << "Can't take ownership of a remote WebContents";
  375. auto session = Session::CreateFrom(isolate, GetBrowserContext());
  376. session_.Reset(isolate, session.ToV8());
  377. InitWithSessionAndOptions(isolate, std::move(web_contents), session,
  378. gin::Dictionary::CreateEmpty(isolate));
  379. }
  380.  
  381. WebContents::WebContents(v8::Isolate* isolate,
  382. const gin_helper::Dictionary& options)
  383. : weak_factory_(this) {
  384. // Read options.
  385. options.Get("backgroundThrottling", &background_throttling_);
  386.  
  387. // Get type
  388. options.Get("type", &type_);
  389.  
  390. #if BUILDFLAG(ENABLE_OSR)
  391. bool b = false;
  392. if (options.Get(options::kOffscreen, &b) && b)
  393. type_ = Type::OFF_SCREEN;
  394. #endif
  395.  
  396. // Init embedder earlier
  397. options.Get("embedder", &embedder_);
  398.  
  399. // Whether to enable DevTools.
  400. options.Get("devTools", &enable_devtools_);
  401.  
  402. // BrowserViews are not attached to a window initially so they should start
  403. // off as hidden. This is also important for compositor recycling. See:
  404. // https://github.com/electron/electron/pull/21372
  405. bool initially_shown = type_ != Type::BROWSER_VIEW;
  406. options.Get(options::kShow, &initially_shown);
  407.  
  408. // Obtain the session.
  409. std::string partition;
  410. gin::Handle<api::Session> session;
  411. if (options.Get("session", &session) && !session.IsEmpty()) {
  412. } else if (options.Get("partition", &partition)) {
  413. session = Session::FromPartition(isolate, partition);
  414. } else {
  415. // Use the default session if not specified.
  416. session = Session::FromPartition(isolate, "");
  417. }
  418. session_.Reset(isolate, session.ToV8());
  419.  
  420. std::unique_ptr<content::WebContents> web_contents;
  421. if (IsGuest()) {
  422. scoped_refptr<content::SiteInstance> site_instance =
  423. content::SiteInstance::CreateForURL(session->browser_context(),
  424. GURL("chrome-guest://fake-host"));
  425. content::WebContents::CreateParams params(session->browser_context(),
  426. site_instance);
  427. guest_delegate_ =
  428. std::make_unique<WebViewGuestDelegate>(embedder_->web_contents(), this);
  429. params.guest_delegate = guest_delegate_.get();
  430.  
  431. #if BUILDFLAG(ENABLE_OSR)
  432. if (embedder_ && embedder_->IsOffScreen()) {
  433. auto* view = new OffScreenWebContentsView(
  434. false,
  435. base::BindRepeating(&WebContents::OnPaint, base::Unretained(this)));
  436. params.view = view;
  437. params.delegate_view = view;
  438.  
  439. web_contents = content::WebContents::Create(params);
  440. view->SetWebContents(web_contents.get());
  441. } else {
  442. #endif
  443. web_contents = content::WebContents::Create(params);
  444. #if BUILDFLAG(ENABLE_OSR)
  445. }
  446. } else if (IsOffScreen()) {
  447. bool transparent = false;
  448. options.Get("transparent", &transparent);
  449.  
  450. content::WebContents::CreateParams params(session->browser_context());
  451. auto* view = new OffScreenWebContentsView(
  452. transparent,
  453. base::BindRepeating(&WebContents::OnPaint, base::Unretained(this)));
  454. params.view = view;
  455. params.delegate_view = view;
  456.  
  457. web_contents = content::WebContents::Create(params);
  458. view->SetWebContents(web_contents.get());
  459. #endif
  460. } else {
  461. content::WebContents::CreateParams params(session->browser_context());
  462. params.initially_hidden = !initially_shown;
  463. web_contents = content::WebContents::Create(params);
  464. }
  465.  
  466. InitWithSessionAndOptions(isolate, std::move(web_contents), session, options);
  467. }
  468.  
  469. void WebContents::InitZoomController(content::WebContents* web_contents,
  470. const gin_helper::Dictionary& options) {
  471. WebContentsZoomController::CreateForWebContents(web_contents);
  472. zoom_controller_ = WebContentsZoomController::FromWebContents(web_contents);
  473. double zoom_factor;
  474. if (options.Get(options::kZoomFactor, &zoom_factor))
  475. zoom_controller_->SetDefaultZoomFactor(zoom_factor);
  476. }
  477.  
  478. void WebContents::InitWithSessionAndOptions(
  479. v8::Isolate* isolate,
  480. std::unique_ptr<content::WebContents> owned_web_contents,
  481. gin::Handle<api::Session> session,
  482. const gin_helper::Dictionary& options) {
  483. Observe(owned_web_contents.get());
  484. // TODO(zcbenz): Make InitWithWebContents take unique_ptr.
  485. // At the time of writing we are going through a refactoring and I don't want
  486. // to make other people's work harder.
  487. InitWithWebContents(owned_web_contents.release(), session->browser_context(),
  488. IsGuest());
  489.  
  490. managed_web_contents()->GetView()->SetDelegate(this);
  491.  
  492. auto* prefs = web_contents()->GetMutableRendererPrefs();
  493. prefs->accept_languages = g_browser_process->GetApplicationLocale();
  494.  
  495. #if defined(OS_LINUX) || defined(OS_WIN)
  496. // Update font settings.
  497. static const base::NoDestructor<gfx::FontRenderParams> params(
  498. gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr));
  499. prefs->should_antialias_text = params->antialiasing;
  500. prefs->use_subpixel_positioning = params->subpixel_positioning;
  501. prefs->hinting = params->hinting;
  502. prefs->use_autohinter = params->autohinter;
  503. prefs->use_bitmaps = params->use_bitmaps;
  504. prefs->subpixel_rendering = params->subpixel_rendering;
  505. #endif
  506.  
  507. // Honor the system's cursor blink rate settings
  508. if (auto interval = GetCursorBlinkInterval())
  509. prefs->caret_blink_interval = *interval;
  510.  
  511. // Save the preferences in C++.
  512. new WebContentsPreferences(web_contents(), options);
  513.  
  514. WebContentsPermissionHelper::CreateForWebContents(web_contents());
  515. SecurityStateTabHelper::CreateForWebContents(web_contents());
  516. InitZoomController(web_contents(), options);
  517. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  518. extensions::AtomExtensionWebContentsObserver::CreateForWebContents(
  519. web_contents());
  520. #endif
  521.  
  522. registry_.AddInterface(base::BindRepeating(&WebContents::BindElectronBrowser,
  523. base::Unretained(this)));
  524. bindings_.set_connection_error_handler(base::BindRepeating(
  525. &WebContents::OnElectronBrowserConnectionError, base::Unretained(this)));
  526. AutofillDriverFactory::CreateForWebContents(web_contents());
  527.  
  528. web_contents()->SetUserAgentOverride(GetBrowserContext()->GetUserAgent(),
  529. false);
  530.  
  531. if (IsGuest()) {
  532. NativeWindow* owner_window = nullptr;
  533. if (embedder_) {
  534. // New WebContents's owner_window is the embedder's owner_window.
  535. auto* relay =
  536. NativeWindowRelay::FromWebContents(embedder_->web_contents());
  537. if (relay)
  538. owner_window = relay->GetNativeWindow();
  539. }
  540. if (owner_window)
  541. SetOwnerWindow(owner_window);
  542. }
  543.  
  544. Init(isolate);
  545. AttachAsUserData(web_contents());
  546. }
  547.  
  548. WebContents::~WebContents() {
  549. // The destroy() is called.
  550. if (managed_web_contents()) {
  551. managed_web_contents()->GetView()->SetDelegate(nullptr);
  552.  
  553. RenderViewDeleted(web_contents()->GetRenderViewHost());
  554.  
  555. if (type_ == Type::BROWSER_WINDOW && owner_window()) {
  556. // For BrowserWindow we should close the window and clean up everything
  557. // before WebContents is destroyed.
  558. for (ExtendedWebContentsObserver& observer : observers_)
  559. observer.OnCloseContents();
  560. // BrowserWindow destroys WebContents asynchronously, manually emit the
  561. // destroyed event here.
  562. WebContentsDestroyed();
  563. } else if (Browser::Get()->is_shutting_down()) {
  564. // Destroy WebContents directly when app is shutting down.
  565. DestroyWebContents(false /* async */);
  566. } else {
  567. // Destroy WebContents asynchronously unless app is shutting down,
  568. // because destroy() might be called inside WebContents's event handler.
  569. DestroyWebContents(!IsGuest() /* async */);
  570. // The WebContentsDestroyed will not be called automatically because we
  571. // destroy the webContents in the next tick. So we have to manually
  572. // call it here to make sure "destroyed" event is emitted.
  573. WebContentsDestroyed();
  574. }
  575. }
  576. }
  577.  
  578. void WebContents::DestroyWebContents(bool async) {
  579. // This event is only for internal use, which is emitted when WebContents is
  580. // being destroyed.
  581. Emit("will-destroy");
  582. ResetManagedWebContents(async);
  583. }
  584.  
  585. bool WebContents::DidAddMessageToConsole(
  586. content::WebContents* source,
  587. blink::mojom::ConsoleMessageLevel level,
  588. const base::string16& message,
  589. int32_t line_no,
  590. const base::string16& source_id) {
  591. return Emit("console-message", static_cast<int32_t>(level), message, line_no,
  592. source_id);
  593. }
  594.  
  595. void WebContents::OnCreateWindow(
  596. const GURL& target_url,
  597. const content::Referrer& referrer,
  598. const std::string& frame_name,
  599. WindowOpenDisposition disposition,
  600. const std::vector<std::string>& features,
  601. const scoped_refptr<network::ResourceRequestBody>& body) {
  602. if (type_ == Type::BROWSER_WINDOW || type_ == Type::OFF_SCREEN)
  603. Emit("-new-window", target_url, frame_name, disposition, features, body,
  604. referrer);
  605. else
  606. Emit("new-window", target_url, frame_name, disposition, features);
  607. }
  608.  
  609. void WebContents::WebContentsCreated(content::WebContents* source_contents,
  610. int opener_render_process_id,
  611. int opener_render_frame_id,
  612. const std::string& frame_name,
  613. const GURL& target_url,
  614. content::WebContents* new_contents) {
  615. ChildWebContentsTracker::CreateForWebContents(new_contents);
  616. auto* tracker = ChildWebContentsTracker::FromWebContents(new_contents);
  617. tracker->url = target_url;
  618. tracker->frame_name = frame_name;
  619. }
  620.  
  621. void WebContents::AddNewContents(
  622. content::WebContents* source,
  623. std::unique_ptr<content::WebContents> new_contents,
  624. WindowOpenDisposition disposition,
  625. const gfx::Rect& initial_rect,
  626. bool user_gesture,
  627. bool* was_blocked) {
  628. auto* tracker = ChildWebContentsTracker::FromWebContents(new_contents.get());
  629. DCHECK(tracker);
  630.  
  631. v8::Locker locker(isolate());
  632. v8::HandleScope handle_scope(isolate());
  633. auto api_web_contents =
  634. CreateAndTake(isolate(), std::move(new_contents), Type::BROWSER_WINDOW);
  635. if (Emit("-add-new-contents", api_web_contents, disposition, user_gesture,
  636. initial_rect.x(), initial_rect.y(), initial_rect.width(),
  637. initial_rect.height(), tracker->url, tracker->frame_name)) {
  638. // TODO(zcbenz): Can we make this sync?
  639. api_web_contents->DestroyWebContents(true /* async */);
  640. }
  641. }
  642.  
  643. content::WebContents* WebContents::OpenURLFromTab(
  644. content::WebContents* source,
  645. const content::OpenURLParams& params) {
  646. if (params.disposition != WindowOpenDisposition::CURRENT_TAB) {
  647. if (type_ == Type::BROWSER_WINDOW || type_ == Type::OFF_SCREEN)
  648. Emit("-new-window", params.url, "", params.disposition);
  649. else
  650. Emit("new-window", params.url, "", params.disposition);
  651. return nullptr;
  652. }
  653.  
  654. // Give user a chance to cancel navigation.
  655. if (Emit("will-navigate", params.url))
  656. return nullptr;
  657.  
  658. // Don't load the URL if the web contents was marked as destroyed from a
  659. // will-navigate event listener
  660. if (IsDestroyed())
  661. return nullptr;
  662.  
  663. return CommonWebContentsDelegate::OpenURLFromTab(source, params);
  664. }
  665.  
  666. void WebContents::BeforeUnloadFired(content::WebContents* tab,
  667. bool proceed,
  668. bool* proceed_to_fire_unload) {
  669. if (type_ == Type::BROWSER_WINDOW || type_ == Type::OFF_SCREEN)
  670. *proceed_to_fire_unload = proceed;
  671. else
  672. *proceed_to_fire_unload = true;
  673. }
  674.  
  675. void WebContents::SetContentsBounds(content::WebContents* source,
  676. const gfx::Rect& pos) {
  677. Emit("move", pos);
  678. }
  679.  
  680. void WebContents::CloseContents(content::WebContents* source) {
  681. Emit("close");
  682.  
  683. auto* autofill_driver_factory =
  684. AutofillDriverFactory::FromWebContents(web_contents());
  685. if (autofill_driver_factory) {
  686. autofill_driver_factory->CloseAllPopups();
  687. }
  688.  
  689. if (managed_web_contents())
  690. managed_web_contents()->GetView()->SetDelegate(nullptr);
  691. for (ExtendedWebContentsObserver& observer : observers_)
  692. observer.OnCloseContents();
  693. }
  694.  
  695. void WebContents::ActivateContents(content::WebContents* source) {
  696. Emit("activate");
  697. }
  698.  
  699. void WebContents::UpdateTargetURL(content::WebContents* source,
  700. const GURL& url) {
  701. Emit("update-target-url", url);
  702. }
  703.  
  704. bool WebContents::HandleKeyboardEvent(
  705. content::WebContents* source,
  706. const content::NativeWebKeyboardEvent& event) {
  707. if (type_ == Type::WEB_VIEW && embedder_) {
  708. // Send the unhandled keyboard events back to the embedder.
  709. return embedder_->HandleKeyboardEvent(source, event);
  710. } else {
  711. // Go to the default keyboard handling.
  712. return CommonWebContentsDelegate::HandleKeyboardEvent(source, event);
  713. }
  714. }
  715.  
  716. content::KeyboardEventProcessingResult WebContents::PreHandleKeyboardEvent(
  717. content::WebContents* source,
  718. const content::NativeWebKeyboardEvent& event) {
  719. if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown ||
  720. event.GetType() == blink::WebInputEvent::Type::kKeyUp) {
  721. bool prevent_default = Emit("before-input-event", event);
  722. if (prevent_default) {
  723. return content::KeyboardEventProcessingResult::HANDLED;
  724. }
  725. }
  726.  
  727. return content::KeyboardEventProcessingResult::NOT_HANDLED;
  728. }
  729.  
  730. void WebContents::ContentsZoomChange(bool zoom_in) {
  731. Emit("zoom-changed", zoom_in ? "in" : "out");
  732. }
  733.  
  734. void WebContents::EnterFullscreenModeForTab(
  735. content::WebContents* source,
  736. const GURL& origin,
  737. const blink::mojom::FullscreenOptions& options) {
  738. auto* permission_helper =
  739. WebContentsPermissionHelper::FromWebContents(source);
  740. auto callback =
  741. base::BindRepeating(&WebContents::OnEnterFullscreenModeForTab,
  742. base::Unretained(this), source, origin, options);
  743. permission_helper->RequestFullscreenPermission(callback);
  744. }
  745.  
  746. void WebContents::OnEnterFullscreenModeForTab(
  747. content::WebContents* source,
  748. const GURL& origin,
  749. const blink::mojom::FullscreenOptions& options,
  750. bool allowed) {
  751. if (!allowed)
  752. return;
  753. CommonWebContentsDelegate::EnterFullscreenModeForTab(source, origin, options);
  754. Emit("enter-html-full-screen");
  755. }
  756.  
  757. void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
  758. CommonWebContentsDelegate::ExitFullscreenModeForTab(source);
  759. Emit("leave-html-full-screen");
  760. }
  761.  
  762. void WebContents::RendererUnresponsive(
  763. content::WebContents* source,
  764. content::RenderWidgetHost* render_widget_host,
  765. base::RepeatingClosure hang_monitor_restarter) {
  766. Emit("unresponsive");
  767. }
  768.  
  769. void WebContents::RendererResponsive(
  770. content::WebContents* source,
  771. content::RenderWidgetHost* render_widget_host) {
  772. Emit("responsive");
  773. for (ExtendedWebContentsObserver& observer : observers_)
  774. observer.OnRendererResponsive();
  775. }
  776.  
  777. bool WebContents::HandleContextMenu(content::RenderFrameHost* render_frame_host,
  778. const content::ContextMenuParams& params) {
  779. if (params.custom_context.is_pepper_menu) {
  780. Emit("pepper-context-menu", std::make_pair(params, web_contents()),
  781. base::BindOnce(&content::WebContents::NotifyContextMenuClosed,
  782. base::Unretained(web_contents()),
  783. params.custom_context));
  784. } else {
  785. Emit("context-menu", std::make_pair(params, web_contents()));
  786. }
  787.  
  788. return true;
  789. }
  790.  
  791. bool WebContents::OnGoToEntryOffset(int offset) {
  792. GoToOffset(offset);
  793. return false;
  794. }
  795.  
  796. void WebContents::FindReply(content::WebContents* web_contents,
  797. int request_id,
  798. int number_of_matches,
  799. const gfx::Rect& selection_rect,
  800. int active_match_ordinal,
  801. bool final_update) {
  802. if (!final_update)
  803. return;
  804.  
  805. v8::Locker locker(isolate());
  806. v8::HandleScope handle_scope(isolate());
  807. gin_helper::Dictionary result = gin::Dictionary::CreateEmpty(isolate());
  808. result.Set("requestId", request_id);
  809. result.Set("matches", number_of_matches);
  810. result.Set("selectionArea", selection_rect);
  811. result.Set("activeMatchOrdinal", active_match_ordinal);
  812. result.Set("finalUpdate", final_update); // Deprecate after 2.0
  813. Emit("found-in-page", result.GetHandle());
  814. }
  815.  
  816. bool WebContents::CheckMediaAccessPermission(
  817. content::RenderFrameHost* render_frame_host,
  818. const GURL& security_origin,
  819. blink::mojom::MediaStreamType type) {
  820. auto* web_contents =
  821. content::WebContents::FromRenderFrameHost(render_frame_host);
  822. auto* permission_helper =
  823. WebContentsPermissionHelper::FromWebContents(web_contents);
  824. return permission_helper->CheckMediaAccessPermission(security_origin, type);
  825. }
  826.  
  827. void WebContents::RequestMediaAccessPermission(
  828. content::WebContents* web_contents,
  829. const content::MediaStreamRequest& request,
  830. content::MediaResponseCallback callback) {
  831. auto* permission_helper =
  832. WebContentsPermissionHelper::FromWebContents(web_contents);
  833. permission_helper->RequestMediaAccessPermission(request, std::move(callback));
  834. }
  835.  
  836. void WebContents::RequestToLockMouse(content::WebContents* web_contents,
  837. bool user_gesture,
  838. bool last_unlocked_by_target) {
  839. auto* permission_helper =
  840. WebContentsPermissionHelper::FromWebContents(web_contents);
  841. permission_helper->RequestPointerLockPermission(user_gesture);
  842. }
  843.  
  844. std::unique_ptr<content::BluetoothChooser> WebContents::RunBluetoothChooser(
  845. content::RenderFrameHost* frame,
  846. const content::BluetoothChooser::EventHandler& event_handler) {
  847. return std::make_unique<BluetoothChooser>(this, event_handler);
  848. }
  849.  
  850. content::JavaScriptDialogManager* WebContents::GetJavaScriptDialogManager(
  851. content::WebContents* source) {
  852. if (!dialog_manager_)
  853. dialog_manager_ = std::make_unique<AtomJavaScriptDialogManager>(this);
  854.  
  855. return dialog_manager_.get();
  856. }
  857.  
  858. void WebContents::OnAudioStateChanged(bool audible) {
  859. Emit("-audio-state-changed", audible);
  860. }
  861.  
  862. void WebContents::BeforeUnloadFired(bool proceed,
  863. const base::TimeTicks& proceed_time) {
  864. // Do nothing, we override this method just to avoid compilation error since
  865. // there are two virtual functions named BeforeUnloadFired.
  866. }
  867.  
  868. void WebContents::RenderViewCreated(content::RenderViewHost* render_view_host) {
  869. if (!background_throttling_)
  870. render_view_host->SetSchedulerThrottling(false);
  871. }
  872.  
  873. void WebContents::RenderFrameCreated(
  874. content::RenderFrameHost* render_frame_host) {
  875. auto* rwhv = render_frame_host->GetView();
  876. if (!rwhv)
  877. return;
  878.  
  879. auto* rwh_impl =
  880. static_cast<content::RenderWidgetHostImpl*>(rwhv->GetRenderWidgetHost());
  881. if (rwh_impl)
  882. rwh_impl->disable_hidden_ = !background_throttling_;
  883. }
  884.  
  885. void WebContents::RenderViewHostChanged(content::RenderViewHost* old_host,
  886. content::RenderViewHost* new_host) {
  887. currently_committed_process_id_ = new_host->GetProcess()->GetID();
  888. }
  889.  
  890. void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
  891. // This event is necessary for tracking any states with respect to
  892. // intermediate render view hosts aka speculative render view hosts. Currently
  893. // used by object-registry.js to ref count remote objects.
  894. Emit("render-view-deleted", render_view_host->GetProcess()->GetID());
  895.  
  896. if (- == currently_committed_process_id_ ||
  897. render_view_host->GetProcess()->GetID() ==
  898. currently_committed_process_id_) {
  899. currently_committed_process_id_ = -;
  900.  
  901. // When the RVH that has been deleted is the current RVH it means that the
  902. // the web contents are being closed. This is communicated by this event.
  903. // Currently tracked by guest-window-manager.js to destroy the
  904. // BrowserWindow.
  905. Emit("current-render-view-deleted",
  906. render_view_host->GetProcess()->GetID());
  907. }
  908. }
  909.  
  910. void WebContents::RenderProcessGone(base::TerminationStatus status) {
  911. Emit("crashed", status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
  912. }
  913.  
  914. void WebContents::PluginCrashed(const base::FilePath& plugin_path,
  915. base::ProcessId plugin_pid) {
  916. #if BUILDFLAG(ENABLE_PLUGINS)
  917. content::WebPluginInfo info;
  918. auto* plugin_service = content::PluginService::GetInstance();
  919. plugin_service->GetPluginInfoByPath(plugin_path, &info);
  920. Emit("plugin-crashed", info.name, info.version);
  921. #endif // BUILDFLAG(ENABLE_PLUIGNS)
  922. }
  923.  
  924. void WebContents::MediaStartedPlaying(const MediaPlayerInfo& video_type,
  925. const content::MediaPlayerId& id) {
  926. Emit("media-started-playing");
  927. }
  928.  
  929. void WebContents::MediaStoppedPlaying(
  930. const MediaPlayerInfo& video_type,
  931. const content::MediaPlayerId& id,
  932. content::WebContentsObserver::MediaStoppedReason reason) {
  933. Emit("media-paused");
  934. }
  935.  
  936. void WebContents::DidChangeThemeColor(base::Optional<SkColor> theme_color) {
  937. if (theme_color) {
  938. Emit("did-change-theme-color", electron::ToRGBHex(theme_color.value()));
  939. } else {
  940. Emit("did-change-theme-color", nullptr);
  941. }
  942. }
  943.  
  944. void WebContents::OnInterfaceRequestFromFrame(
  945. content::RenderFrameHost* render_frame_host,
  946. const std::string& interface_name,
  947. mojo::ScopedMessagePipeHandle* interface_pipe) {
  948. registry_.TryBindInterface(interface_name, interface_pipe, render_frame_host);
  949. }
  950.  
  951. void WebContents::DidAcquireFullscreen(content::RenderFrameHost* rfh) {
  952. set_fullscreen_frame(rfh);
  953. }
  954.  
  955. void WebContents::DOMContentLoaded(
  956. content::RenderFrameHost* render_frame_host) {
  957. if (!render_frame_host->GetParent())
  958. Emit("dom-ready");
  959. }
  960.  
  961. void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host,
  962. const GURL& validated_url) {
  963. bool is_main_frame = !render_frame_host->GetParent();
  964. int frame_process_id = render_frame_host->GetProcess()->GetID();
  965. int frame_routing_id = render_frame_host->GetRoutingID();
  966. auto weak_this = GetWeakPtr();
  967. Emit("did-frame-finish-load", is_main_frame, frame_process_id,
  968. frame_routing_id);
  969.  
  970. // ⚠️WARNING!⚠️
  971. // Emit() triggers JS which can call destroy() on |this|. It's not safe to
  972. // assume that |this| points to valid memory at this point.
  973. if (is_main_frame && weak_this)
  974. Emit("did-finish-load");
  975. }
  976.  
  977. void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
  978. const GURL& url,
  979. int error_code,
  980. const base::string16& error_description) {
  981. bool is_main_frame = !render_frame_host->GetParent();
  982. int frame_process_id = render_frame_host->GetProcess()->GetID();
  983. int frame_routing_id = render_frame_host->GetRoutingID();
  984. Emit("did-fail-load", error_code, error_description, url, is_main_frame,
  985. frame_process_id, frame_routing_id);
  986. }
  987.  
  988. void WebContents::DidStartLoading() {
  989. Emit("did-start-loading");
  990. }
  991.  
  992. void WebContents::DidStopLoading() {
  993. Emit("did-stop-loading");
  994. }
  995.  
  996. bool WebContents::EmitNavigationEvent(
  997. const std::string& event,
  998. content::NavigationHandle* navigation_handle) {
  999. bool is_main_frame = navigation_handle->IsInMainFrame();
  1000. int frame_tree_node_id = navigation_handle->GetFrameTreeNodeId();
  1001. content::FrameTreeNode* frame_tree_node =
  1002. content::FrameTreeNode::GloballyFindByID(frame_tree_node_id);
  1003. content::RenderFrameHostManager* render_manager =
  1004. frame_tree_node->render_manager();
  1005. content::RenderFrameHost* frame_host = nullptr;
  1006. if (render_manager) {
  1007. frame_host = render_manager->speculative_frame_host();
  1008. if (!frame_host)
  1009. frame_host = render_manager->current_frame_host();
  1010. }
  1011. int frame_process_id = -, frame_routing_id = -;
  1012. if (frame_host) {
  1013. frame_process_id = frame_host->GetProcess()->GetID();
  1014. frame_routing_id = frame_host->GetRoutingID();
  1015. }
  1016. bool is_same_document = navigation_handle->IsSameDocument();
  1017. auto url = navigation_handle->GetURL();
  1018. return Emit(event, url, is_same_document, is_main_frame, frame_process_id,
  1019. frame_routing_id);
  1020. }
  1021.  
  1022. void WebContents::BindElectronBrowser(
  1023. mojom::ElectronBrowserRequest request,
  1024. content::RenderFrameHost* render_frame_host) {
  1025. auto id = bindings_.AddBinding(this, std::move(request), render_frame_host);
  1026. frame_to_bindings_map_[render_frame_host].push_back(id);
  1027. }
  1028.  
  1029. void WebContents::OnElectronBrowserConnectionError() {
  1030. auto binding_id = bindings_.dispatch_binding();
  1031. auto* frame_host = bindings_.dispatch_context();
  1032. base::Erase(frame_to_bindings_map_[frame_host], binding_id);
  1033. }
  1034.  
  1035. void WebContents::Message(bool internal,
  1036. const std::string& channel,
  1037. blink::CloneableMessage arguments) {
  1038. TRACE_EVENT1("electron", "WebContents::Message", "channel", channel);
  1039. // webContents.emit('-ipc-message', new Event(), internal, channel,
  1040. // arguments);
  1041. EmitWithSender("-ipc-message", bindings_.dispatch_context(), InvokeCallback(),
  1042. internal, channel, std::move(arguments));
  1043. }
  1044.  
  1045. void WebContents::Invoke(bool internal,
  1046. const std::string& channel,
  1047. blink::CloneableMessage arguments,
  1048. InvokeCallback callback) {
  1049. TRACE_EVENT1("electron", "WebContents::Invoke", "channel", channel);
  1050. // webContents.emit('-ipc-invoke', new Event(), internal, channel, arguments);
  1051. EmitWithSender("-ipc-invoke", bindings_.dispatch_context(),
  1052. std::move(callback), internal, channel, std::move(arguments));
  1053. }
  1054.  
  1055. void WebContents::MessageSync(bool internal,
  1056. const std::string& channel,
  1057. blink::CloneableMessage arguments,
  1058. MessageSyncCallback callback) {
  1059. TRACE_EVENT1("electron", "WebContents::MessageSync", "channel", channel);
  1060. // webContents.emit('-ipc-message-sync', new Event(sender, message), internal,
  1061. // channel, arguments);
  1062. EmitWithSender("-ipc-message-sync", bindings_.dispatch_context(),
  1063. std::move(callback), internal, channel, std::move(arguments));
  1064. }
  1065.  
  1066. void WebContents::MessageTo(bool internal,
  1067. bool send_to_all,
  1068. int32_t web_contents_id,
  1069. const std::string& channel,
  1070. blink::CloneableMessage arguments) {
  1071. TRACE_EVENT1("electron", "WebContents::MessageTo", "channel", channel);
  1072. auto* web_contents = gin_helper::TrackableObject<WebContents>::FromWeakMapID(
  1073. isolate(), web_contents_id);
  1074.  
  1075. if (web_contents) {
  1076. web_contents->SendIPCMessageWithSender(internal, send_to_all, channel,
  1077. std::move(arguments), ID());
  1078. }
  1079. }
  1080.  
  1081. void WebContents::MessageHost(const std::string& channel,
  1082. blink::CloneableMessage arguments) {
  1083. TRACE_EVENT1("electron", "WebContents::MessageHost", "channel", channel);
  1084. // webContents.emit('ipc-message-host', new Event(), channel, args);
  1085. EmitWithSender("ipc-message-host", bindings_.dispatch_context(),
  1086. InvokeCallback(), channel, std::move(arguments));
  1087. }
  1088.  
  1089. #if BUILDFLAG(ENABLE_REMOTE_MODULE)
  1090. void WebContents::DereferenceRemoteJSObject(const std::string& context_id,
  1091. int object_id,
  1092. int ref_count) {
  1093. base::ListValue args;
  1094. args.Append(context_id);
  1095. args.Append(object_id);
  1096. args.Append(ref_count);
  1097. EmitWithSender("-ipc-message", bindings_.dispatch_context(), InvokeCallback(),
  1098. /* internal */ true, "ELECTRON_BROWSER_DEREFERENCE",
  1099. std::move(args));
  1100. }
  1101. #endif
  1102.  
  1103. void WebContents::UpdateDraggableRegions(
  1104. std::vector<mojom::DraggableRegionPtr> regions) {
  1105. for (ExtendedWebContentsObserver& observer : observers_)
  1106. observer.OnDraggableRegionsUpdated(regions);
  1107. }
  1108.  
  1109. void WebContents::RenderFrameDeleted(
  1110. content::RenderFrameHost* render_frame_host) {
  1111. // A RenderFrameHost can be destroyed before the related Mojo binding is
  1112. // closed, which can result in Mojo calls being sent for RenderFrameHosts
  1113. // that no longer exist. To prevent this from happening, when a
  1114. // RenderFrameHost goes away, we close all the bindings related to that
  1115. // frame.
  1116. auto it = frame_to_bindings_map_.find(render_frame_host);
  1117. if (it == frame_to_bindings_map_.end())
  1118. return;
  1119. for (auto id : it->second)
  1120. bindings_.RemoveBinding(id);
  1121. frame_to_bindings_map_.erase(it);
  1122. }
  1123.  
  1124. void WebContents::DidStartNavigation(
  1125. content::NavigationHandle* navigation_handle) {
  1126. EmitNavigationEvent("did-start-navigation", navigation_handle);
  1127. }
  1128.  
  1129. void WebContents::DidRedirectNavigation(
  1130. content::NavigationHandle* navigation_handle) {
  1131. EmitNavigationEvent("did-redirect-navigation", navigation_handle);
  1132. }
  1133.  
  1134. void WebContents::DidFinishNavigation(
  1135. content::NavigationHandle* navigation_handle) {
  1136. if (!navigation_handle->HasCommitted())
  1137. return;
  1138. bool is_main_frame = navigation_handle->IsInMainFrame();
  1139. content::RenderFrameHost* frame_host =
  1140. navigation_handle->GetRenderFrameHost();
  1141. int frame_process_id = -, frame_routing_id = -;
  1142. if (frame_host) {
  1143. frame_process_id = frame_host->GetProcess()->GetID();
  1144. frame_routing_id = frame_host->GetRoutingID();
  1145. }
  1146. if (!navigation_handle->IsErrorPage()) {
  1147. // FIXME: All the Emit() calls below could potentially result in |this|
  1148. // being destroyed (by JS listening for the event and calling
  1149. // webContents.destroy()).
  1150. auto url = navigation_handle->GetURL();
  1151. bool is_same_document = navigation_handle->IsSameDocument();
  1152. if (is_same_document) {
  1153. Emit("did-navigate-in-page", url, is_main_frame, frame_process_id,
  1154. frame_routing_id);
  1155. } else {
  1156. const net::HttpResponseHeaders* http_response =
  1157. navigation_handle->GetResponseHeaders();
  1158. std::string http_status_text;
  1159. int http_response_code = -;
  1160. if (http_response) {
  1161. http_status_text = http_response->GetStatusText();
  1162. http_response_code = http_response->response_code();
  1163. }
  1164. Emit("did-frame-navigate", url, http_response_code, http_status_text,
  1165. is_main_frame, frame_process_id, frame_routing_id);
  1166. if (is_main_frame) {
  1167. Emit("did-navigate", url, http_response_code, http_status_text);
  1168. }
  1169. }
  1170. if (IsGuest())
  1171. Emit("load-commit", url, is_main_frame);
  1172. } else {
  1173. auto url = navigation_handle->GetURL();
  1174. int code = navigation_handle->GetNetErrorCode();
  1175. auto description = net::ErrorToShortString(code);
  1176. Emit("did-fail-provisional-load", code, description, url, is_main_frame,
  1177. frame_process_id, frame_routing_id);
  1178.  
  1179. // Do not emit "did-fail-load" for canceled requests.
  1180. if (code != net::ERR_ABORTED)
  1181. Emit("did-fail-load", code, description, url, is_main_frame,
  1182. frame_process_id, frame_routing_id);
  1183. }
  1184. }
  1185.  
  1186. void WebContents::TitleWasSet(content::NavigationEntry* entry) {
  1187. base::string16 final_title;
  1188. bool explicit_set = true;
  1189. if (entry) {
  1190. auto title = entry->GetTitle();
  1191. auto url = entry->GetURL();
  1192. if (url.SchemeIsFile() && title.empty()) {
  1193. final_title = base::UTF8ToUTF16(url.ExtractFileName());
  1194. explicit_set = false;
  1195. } else {
  1196. final_title = title;
  1197. }
  1198. }
  1199. Emit("page-title-updated", final_title, explicit_set);
  1200. }
  1201.  
  1202. void WebContents::DidUpdateFaviconURL(
  1203. const std::vector<content::FaviconURL>& urls) {
  1204. std::set<GURL> unique_urls;
  1205. for (const auto& iter : urls) {
  1206. if (iter.icon_type != content::FaviconURL::IconType::kFavicon)
  1207. continue;
  1208. const GURL& url = iter.icon_url;
  1209. if (url.is_valid())
  1210. unique_urls.insert(url);
  1211. }
  1212. Emit("page-favicon-updated", unique_urls);
  1213. }
  1214.  
  1215. void WebContents::DevToolsReloadPage() {
  1216. Emit("devtools-reload-page");
  1217. }
  1218.  
  1219. void WebContents::DevToolsFocused() {
  1220. Emit("devtools-focused");
  1221. }
  1222.  
  1223. void WebContents::DevToolsOpened() {
  1224. v8::Locker locker(isolate());
  1225. v8::HandleScope handle_scope(isolate());
  1226. auto handle =
  1227. FromOrCreate(isolate(), managed_web_contents()->GetDevToolsWebContents());
  1228. devtools_web_contents_.Reset(isolate(), handle.ToV8());
  1229.  
  1230. // Set inspected tabID.
  1231. base::Value tab_id(ID());
  1232. managed_web_contents()->CallClientFunction("DevToolsAPI.setInspectedTabId",
  1233. &tab_id, nullptr, nullptr);
  1234.  
  1235. // Inherit owner window in devtools when it doesn't have one.
  1236. auto* devtools = managed_web_contents()->GetDevToolsWebContents();
  1237. bool has_window = devtools->GetUserData(NativeWindowRelay::UserDataKey());
  1238. if (owner_window() && !has_window)
  1239. handle->SetOwnerWindow(devtools, owner_window());
  1240.  
  1241. Emit("devtools-opened");
  1242. }
  1243.  
  1244. void WebContents::DevToolsClosed() {
  1245. v8::Locker locker(isolate());
  1246. v8::HandleScope handle_scope(isolate());
  1247. devtools_web_contents_.Reset();
  1248.  
  1249. Emit("devtools-closed");
  1250. }
  1251.  
  1252. bool WebContents::OnMessageReceived(const IPC::Message& message) {
  1253. bool handled = true;
  1254. IPC_BEGIN_MESSAGE_MAP(WebContents, message)
  1255. IPC_MESSAGE_HANDLER_CODE(WidgetHostMsg_SetCursor, OnCursorChange,
  1256. handled = false)
  1257. IPC_MESSAGE_UNHANDLED(handled = false)
  1258. IPC_END_MESSAGE_MAP()
  1259.  
  1260. return handled;
  1261. }
  1262.  
  1263. // There are three ways of destroying a webContents:
  1264. // 1. call webContents.destroy();
  1265. // 2. garbage collection;
  1266. // 3. user closes the window of webContents;
  1267. // 4. the embedder detaches the frame.
  1268. // For webview only #4 will happen, for BrowserWindow both #1 and #3 may
  1269. // happen. The #2 should never happen for webContents, because webview is
  1270. // managed by GuestViewManager, and BrowserWindow's webContents is managed
  1271. // by api::BrowserWindow.
  1272. // For #1, the destructor will do the cleanup work and we only need to make
  1273. // sure "destroyed" event is emitted. For #3, the content::WebContents will
  1274. // be destroyed on close, and WebContentsDestroyed would be called for it, so
  1275. // we need to make sure the api::WebContents is also deleted.
  1276. // For #4, the WebContents will be destroyed by embedder.
  1277. void WebContents::WebContentsDestroyed() {
  1278. // Cleanup relationships with other parts.
  1279. RemoveFromWeakMap();
  1280.  
  1281. // We can not call Destroy here because we need to call Emit first, but we
  1282. // also do not want any method to be used, so just mark as destroyed here.
  1283. MarkDestroyed();
  1284.  
  1285. Emit("destroyed");
  1286.  
  1287. // For guest view based on OOPIF, the WebContents is released by the embedder
  1288. // frame, and we need to clear the reference to the memory.
  1289. if (IsGuest() && managed_web_contents()) {
  1290. managed_web_contents()->ReleaseWebContents();
  1291. ResetManagedWebContents(false);
  1292. }
  1293.  
  1294. // Destroy the native class in next tick.
  1295. base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, GetDestroyClosure());
  1296. }
  1297.  
  1298. void WebContents::NavigationEntryCommitted(
  1299. const content::LoadCommittedDetails& details) {
  1300. Emit("navigation-entry-commited", details.entry->GetURL(),
  1301. details.is_same_document, details.did_replace_entry);
  1302. }
  1303.  
  1304. void WebContents::SetBackgroundThrottling(bool allowed) {
  1305. background_throttling_ = allowed;
  1306.  
  1307. auto* rfh = web_contents()->GetMainFrame();
  1308. if (!rfh)
  1309. return;
  1310.  
  1311. auto* rwhv = rfh->GetView();
  1312. if (!rwhv)
  1313. return;
  1314.  
  1315. auto* rwh_impl =
  1316. static_cast<content::RenderWidgetHostImpl*>(rwhv->GetRenderWidgetHost());
  1317. if (!rwh_impl)
  1318. return;
  1319.  
  1320. rwh_impl->disable_hidden_ = !background_throttling_;
  1321. web_contents()->GetRenderViewHost()->SetSchedulerThrottling(allowed);
  1322.  
  1323. if (rwh_impl->is_hidden()) {
  1324. rwh_impl->WasShown(base::nullopt);
  1325. }
  1326. }
  1327.  
  1328. int WebContents::GetProcessID() const {
  1329. return web_contents()->GetMainFrame()->GetProcess()->GetID();
  1330. }
  1331.  
  1332. base::ProcessId WebContents::GetOSProcessID() const {
  1333. base::ProcessHandle process_handle =
  1334. web_contents()->GetMainFrame()->GetProcess()->GetProcess().Handle();
  1335. return base::GetProcId(process_handle);
  1336. }
  1337.  
  1338. base::ProcessId WebContents::GetOSProcessIdForFrame(
  1339. const std::string& name,
  1340. const std::string& document_url) const {
  1341. for (auto* frame : web_contents()->GetAllFrames()) {
  1342. if (frame->GetFrameName() == name &&
  1343. frame->GetLastCommittedURL().spec() == document_url) {
  1344. return base::GetProcId(frame->GetProcess()->GetProcess().Handle());
  1345. }
  1346. }
  1347. return base::kNullProcessId;
  1348. }
  1349.  
  1350. WebContents::Type WebContents::GetType() const {
  1351. return type_;
  1352. }
  1353.  
  1354. bool WebContents::Equal(const WebContents* web_contents) const {
  1355. return ID() == web_contents->ID();
  1356. }
  1357.  
  1358. void WebContents::LoadURL(const GURL& url,
  1359. const gin_helper::Dictionary& options) {
  1360. if (!url.is_valid() || url.spec().size() > url::kMaxURLChars) {
  1361. Emit("did-fail-load", static_cast<int>(net::ERR_INVALID_URL),
  1362. net::ErrorToShortString(net::ERR_INVALID_URL),
  1363. url.possibly_invalid_spec(), true);
  1364. return;
  1365. }
  1366.  
  1367. content::NavigationController::LoadURLParams params(url);
  1368.  
  1369. if (!options.Get("httpReferrer", &params.referrer)) {
  1370. GURL http_referrer;
  1371. if (options.Get("httpReferrer", &http_referrer))
  1372. params.referrer =
  1373. content::Referrer(http_referrer.GetAsReferrer(),
  1374. network::mojom::ReferrerPolicy::kDefault);
  1375. }
  1376.  
  1377. std::string user_agent;
  1378. if (options.Get("userAgent", &user_agent))
  1379. web_contents()->SetUserAgentOverride(user_agent, false);
  1380.  
  1381. std::string extra_headers;
  1382. if (options.Get("extraHeaders", &extra_headers))
  1383. params.extra_headers = extra_headers;
  1384.  
  1385. scoped_refptr<network::ResourceRequestBody> body;
  1386. if (options.Get("postData", &body)) {
  1387. params.post_data = body;
  1388. params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST;
  1389. }
  1390.  
  1391. GURL base_url_for_data_url;
  1392. if (options.Get("baseURLForDataURL", &base_url_for_data_url)) {
  1393. params.base_url_for_data_url = base_url_for_data_url;
  1394. params.load_type = content::NavigationController::LOAD_TYPE_DATA;
  1395. }
  1396.  
  1397. bool reload_ignoring_cache = false;
  1398. if (options.Get("reloadIgnoringCache", &reload_ignoring_cache) &&
  1399. reload_ignoring_cache) {
  1400. params.reload_type = content::ReloadType::BYPASSING_CACHE;
  1401. }
  1402.  
  1403. // Calling LoadURLWithParams() can trigger JS which destroys |this|.
  1404. auto weak_this = GetWeakPtr();
  1405.  
  1406. params.transition_type = ui::PAGE_TRANSITION_TYPED;
  1407. params.should_clear_history_list = true;
  1408. params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
  1409. // Discord non-committed entries to ensure that we don't re-use a pending
  1410. // entry
  1411. web_contents()->GetController().DiscardNonCommittedEntries();
  1412. web_contents()->GetController().LoadURLWithParams(params);
  1413.  
  1414. // ⚠️WARNING!⚠️
  1415. // LoadURLWithParams() triggers JS events which can call destroy() on |this|.
  1416. // It's not safe to assume that |this| points to valid memory at this point.
  1417. if (!weak_this)
  1418. return;
  1419.  
  1420. // Set the background color of RenderWidgetHostView.
  1421. // We have to call it right after LoadURL because the RenderViewHost is only
  1422. // created after loading a page.
  1423. auto* const view = weak_this->web_contents()->GetRenderWidgetHostView();
  1424. if (view) {
  1425. auto* web_preferences = WebContentsPreferences::From(web_contents());
  1426. std::string color_name;
  1427. if (web_preferences->GetPreference(options::kBackgroundColor,
  1428. &color_name)) {
  1429. view->SetBackgroundColor(ParseHexColor(color_name));
  1430. } else {
  1431. view->SetBackgroundColor(SK_ColorTRANSPARENT);
  1432. }
  1433. }
  1434. }
  1435.  
  1436. void WebContents::DownloadURL(const GURL& url) {
  1437. auto* browser_context = web_contents()->GetBrowserContext();
  1438. auto* download_manager =
  1439. content::BrowserContext::GetDownloadManager(browser_context);
  1440. std::unique_ptr<download::DownloadUrlParameters> download_params(
  1441. content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
  1442. web_contents(), url, MISSING_TRAFFIC_ANNOTATION));
  1443. download_manager->DownloadUrl(std::move(download_params));
  1444. }
  1445.  
  1446. GURL WebContents::GetURL() const {
  1447. return web_contents()->GetURL();
  1448. }
  1449.  
  1450. base::string16 WebContents::GetTitle() const {
  1451. return web_contents()->GetTitle();
  1452. }
  1453.  
  1454. bool WebContents::IsLoading() const {
  1455. return web_contents()->IsLoading();
  1456. }
  1457.  
  1458. bool WebContents::IsLoadingMainFrame() const {
  1459. return web_contents()->IsLoadingToDifferentDocument();
  1460. }
  1461.  
  1462. bool WebContents::IsWaitingForResponse() const {
  1463. return web_contents()->IsWaitingForResponse();
  1464. }
  1465.  
  1466. void WebContents::Stop() {
  1467. web_contents()->Stop();
  1468. }
  1469.  
  1470. void WebContents::GoBack() {
  1471. electron::AtomBrowserClient::SuppressRendererProcessRestartForOnce();
  1472. web_contents()->GetController().GoBack();
  1473. }
  1474.  
  1475. void WebContents::GoForward() {
  1476. electron::AtomBrowserClient::SuppressRendererProcessRestartForOnce();
  1477. web_contents()->GetController().GoForward();
  1478. }
  1479.  
  1480. void WebContents::GoToOffset(int offset) {
  1481. electron::AtomBrowserClient::SuppressRendererProcessRestartForOnce();
  1482. web_contents()->GetController().GoToOffset(offset);
  1483. }
  1484.  
  1485. const std::string WebContents::GetWebRTCIPHandlingPolicy() const {
  1486. return web_contents()->GetMutableRendererPrefs()->webrtc_ip_handling_policy;
  1487. }
  1488.  
  1489. void WebContents::SetWebRTCIPHandlingPolicy(
  1490. const std::string& webrtc_ip_handling_policy) {
  1491. if (GetWebRTCIPHandlingPolicy() == webrtc_ip_handling_policy)
  1492. return;
  1493. web_contents()->GetMutableRendererPrefs()->webrtc_ip_handling_policy =
  1494. webrtc_ip_handling_policy;
  1495.  
  1496. web_contents()->SyncRendererPrefs();
  1497. }
  1498.  
  1499. bool WebContents::IsCrashed() const {
  1500. return web_contents()->IsCrashed();
  1501. }
  1502.  
  1503. void WebContents::SetUserAgent(const std::string& user_agent,
  1504. gin_helper::Arguments* args) {
  1505. web_contents()->SetUserAgentOverride(user_agent, false);
  1506. }
  1507.  
  1508. std::string WebContents::GetUserAgent() {
  1509. return web_contents()->GetUserAgentOverride();
  1510. }
  1511.  
  1512. v8::Local<v8::Promise> WebContents::SavePage(
  1513. const base::FilePath& full_file_path,
  1514. const content::SavePageType& save_type) {
  1515. gin_helper::Promise<void> promise(isolate());
  1516. v8::Local<v8::Promise> handle = promise.GetHandle();
  1517.  
  1518. auto* handler = new SavePageHandler(web_contents(), std::move(promise));
  1519. handler->Handle(full_file_path, save_type);
  1520.  
  1521. return handle;
  1522. }
  1523.  
  1524. void WebContents::OpenDevTools(gin_helper::Arguments* args) {
  1525. if (type_ == Type::REMOTE)
  1526. return;
  1527.  
  1528. if (!enable_devtools_)
  1529. return;
  1530.  
  1531. std::string state;
  1532. if (type_ == Type::WEB_VIEW || !owner_window()) {
  1533. state = "detach";
  1534. }
  1535. bool activate = true;
  1536. if (args && args->Length() == ) {
  1537. gin_helper::Dictionary options;
  1538. if (args->GetNext(&options)) {
  1539. options.Get("mode", &state);
  1540. options.Get("activate", &activate);
  1541. }
  1542. }
  1543. managed_web_contents()->SetDockState(state);
  1544. managed_web_contents()->ShowDevTools(activate);
  1545. }
  1546.  
  1547. void WebContents::CloseDevTools() {
  1548. if (type_ == Type::REMOTE)
  1549. return;
  1550.  
  1551. managed_web_contents()->CloseDevTools();
  1552. }
  1553.  
  1554. bool WebContents::IsDevToolsOpened() {
  1555. if (type_ == Type::REMOTE)
  1556. return false;
  1557.  
  1558. return managed_web_contents()->IsDevToolsViewShowing();
  1559. }
  1560.  
  1561. bool WebContents::IsDevToolsFocused() {
  1562. if (type_ == Type::REMOTE)
  1563. return false;
  1564.  
  1565. return managed_web_contents()->GetView()->IsDevToolsViewFocused();
  1566. }
  1567.  
  1568. void WebContents::EnableDeviceEmulation(
  1569. const blink::WebDeviceEmulationParams& params) {
  1570. if (type_ == Type::REMOTE)
  1571. return;
  1572.  
  1573. auto* frame_host = web_contents()->GetMainFrame();
  1574. if (frame_host) {
  1575. auto* widget_host =
  1576. frame_host ? frame_host->GetView()->GetRenderWidgetHost() : nullptr;
  1577. if (!widget_host)
  1578. return;
  1579. widget_host->Send(new WidgetMsg_EnableDeviceEmulation(
  1580. widget_host->GetRoutingID(), params));
  1581. }
  1582. }
  1583.  
  1584. void WebContents::DisableDeviceEmulation() {
  1585. if (type_ == Type::REMOTE)
  1586. return;
  1587.  
  1588. auto* frame_host = web_contents()->GetMainFrame();
  1589. if (frame_host) {
  1590. auto* widget_host =
  1591. frame_host ? frame_host->GetView()->GetRenderWidgetHost() : nullptr;
  1592. if (!widget_host)
  1593. return;
  1594. widget_host->Send(
  1595. new WidgetMsg_DisableDeviceEmulation(widget_host->GetRoutingID()));
  1596. }
  1597. }
  1598.  
  1599. void WebContents::ToggleDevTools() {
  1600. if (IsDevToolsOpened())
  1601. CloseDevTools();
  1602. else
  1603. OpenDevTools(nullptr);
  1604. }
  1605.  
  1606. void WebContents::InspectElement(int x, int y) {
  1607. if (type_ == Type::REMOTE)
  1608. return;
  1609.  
  1610. if (!enable_devtools_)
  1611. return;
  1612.  
  1613. if (!managed_web_contents()->GetDevToolsWebContents())
  1614. OpenDevTools(nullptr);
  1615. managed_web_contents()->InspectElement(x, y);
  1616. }
  1617.  
  1618. void WebContents::InspectSharedWorkerById(const std::string& workerId) {
  1619. if (type_ == Type::REMOTE)
  1620. return;
  1621.  
  1622. if (!enable_devtools_)
  1623. return;
  1624.  
  1625. for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
  1626. if (agent_host->GetType() ==
  1627. content::DevToolsAgentHost::kTypeSharedWorker) {
  1628. if (agent_host->GetId() == workerId) {
  1629. OpenDevTools(nullptr);
  1630. managed_web_contents()->AttachTo(agent_host);
  1631. break;
  1632. }
  1633. }
  1634. }
  1635. }
  1636.  
  1637. std::vector<scoped_refptr<content::DevToolsAgentHost>>
  1638. WebContents::GetAllSharedWorkers() {
  1639. std::vector<scoped_refptr<content::DevToolsAgentHost>> shared_workers;
  1640.  
  1641. if (type_ == Type::REMOTE)
  1642. return shared_workers;
  1643.  
  1644. if (!enable_devtools_)
  1645. return shared_workers;
  1646.  
  1647. for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
  1648. if (agent_host->GetType() ==
  1649. content::DevToolsAgentHost::kTypeSharedWorker) {
  1650. shared_workers.push_back(agent_host);
  1651. }
  1652. }
  1653. return shared_workers;
  1654. }
  1655.  
  1656. void WebContents::InspectSharedWorker() {
  1657. if (type_ == Type::REMOTE)
  1658. return;
  1659.  
  1660. if (!enable_devtools_)
  1661. return;
  1662.  
  1663. for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
  1664. if (agent_host->GetType() ==
  1665. content::DevToolsAgentHost::kTypeSharedWorker) {
  1666. OpenDevTools(nullptr);
  1667. managed_web_contents()->AttachTo(agent_host);
  1668. break;
  1669. }
  1670. }
  1671. }
  1672.  
  1673. void WebContents::InspectServiceWorker() {
  1674. if (type_ == Type::REMOTE)
  1675. return;
  1676.  
  1677. if (!enable_devtools_)
  1678. return;
  1679.  
  1680. for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
  1681. if (agent_host->GetType() ==
  1682. content::DevToolsAgentHost::kTypeServiceWorker) {
  1683. OpenDevTools(nullptr);
  1684. managed_web_contents()->AttachTo(agent_host);
  1685. break;
  1686. }
  1687. }
  1688. }
  1689.  
  1690. void WebContents::SetIgnoreMenuShortcuts(bool ignore) {
  1691. auto* web_preferences = WebContentsPreferences::From(web_contents());
  1692. DCHECK(web_preferences);
  1693. web_preferences->preference()->SetKey("ignoreMenuShortcuts",
  1694. base::Value(ignore));
  1695. }
  1696.  
  1697. void WebContents::SetAudioMuted(bool muted) {
  1698. web_contents()->SetAudioMuted(muted);
  1699. }
  1700.  
  1701. bool WebContents::IsAudioMuted() {
  1702. return web_contents()->IsAudioMuted();
  1703. }
  1704.  
  1705. bool WebContents::IsCurrentlyAudible() {
  1706. return web_contents()->IsCurrentlyAudible();
  1707. }
  1708.  
  1709. #if BUILDFLAG(ENABLE_PRINTING)
  1710. void WebContents::Print(gin_helper::Arguments* args) {
  1711. gin_helper::Dictionary options =
  1712. gin::Dictionary::CreateEmpty(args->isolate());
  1713. base::Value settings(base::Value::Type::DICTIONARY);
  1714.  
  1715. if (args->Length() >= && !args->GetNext(&options)) {
  1716. args->ThrowError("webContents.print(): Invalid print settings specified.");
  1717. return;
  1718. }
  1719.  
  1720. printing::CompletionCallback callback;
  1721. if (args->Length() == && !args->GetNext(&callback)) {
  1722. args->ThrowError(
  1723. "webContents.print(): Invalid optional callback provided.");
  1724. return;
  1725. }
  1726.  
  1727. // Set optional silent printing
  1728. bool silent = false;
  1729. options.Get("silent", &silent);
  1730.  
  1731. bool print_background = false;
  1732. options.Get("printBackground", &print_background);
  1733. settings.SetBoolKey(printing::kSettingShouldPrintBackgrounds,
  1734. print_background);
  1735.  
  1736. // Set custom margin settings
  1737. gin_helper::Dictionary margins =
  1738. gin::Dictionary::CreateEmpty(args->isolate());
  1739. if (options.Get("margins", &margins)) {
  1740. printing::MarginType margin_type = printing::DEFAULT_MARGINS;
  1741. margins.Get("marginType", &margin_type);
  1742. settings.SetIntKey(printing::kSettingMarginsType, margin_type);
  1743.  
  1744. if (margin_type == printing::CUSTOM_MARGINS) {
  1745. int top = ;
  1746. margins.Get("top", &top);
  1747. settings.SetIntKey(printing::kSettingMarginTop, top);
  1748. int bottom = ;
  1749. margins.Get("bottom", &bottom);
  1750. settings.SetIntKey(printing::kSettingMarginBottom, bottom);
  1751. int left = ;
  1752. margins.Get("left", &left);
  1753. settings.SetIntKey(printing::kSettingMarginLeft, left);
  1754. int right = ;
  1755. margins.Get("right", &right);
  1756. settings.SetIntKey(printing::kSettingMarginRight, right);
  1757. }
  1758. } else {
  1759. settings.SetIntKey(printing::kSettingMarginsType,
  1760. printing::DEFAULT_MARGINS);
  1761. }
  1762.  
  1763. // Set whether to print color or greyscale
  1764. bool print_color = true;
  1765. options.Get("color", &print_color);
  1766. int color_setting = print_color ? printing::COLOR : printing::GRAY;
  1767. settings.SetIntKey(printing::kSettingColor, color_setting);
  1768.  
  1769. // Is the orientation landscape or portrait.
  1770. bool landscape = false;
  1771. options.Get("landscape", &landscape);
  1772. settings.SetBoolKey(printing::kSettingLandscape, landscape);
  1773.  
  1774. // We set the default to empty string here and only update
  1775. // if at the Chromium level if it's non-empty
  1776. // Printer device name as opened by the OS.
  1777. base::string16 device_name;
  1778. options.Get("deviceName", &device_name);
  1779. settings.SetStringKey(printing::kSettingDeviceName, device_name);
  1780.  
  1781. int scale_factor = ;
  1782. options.Get("scaleFactor", &scale_factor);
  1783. settings.SetIntKey(printing::kSettingScaleFactor, scale_factor);
  1784.  
  1785. int pages_per_sheet = ;
  1786. options.Get("pagesPerSheet", &pages_per_sheet);
  1787. settings.SetIntKey(printing::kSettingPagesPerSheet, pages_per_sheet);
  1788.  
  1789. // True if the user wants to print with collate.
  1790. bool collate = true;
  1791. options.Get("collate", &collate);
  1792. settings.SetBoolKey(printing::kSettingCollate, collate);
  1793.  
  1794. // The number of individual copies to print
  1795. int copies = ;
  1796. options.Get("copies", &copies);
  1797. settings.SetIntKey(printing::kSettingCopies, copies);
  1798.  
  1799. // Strings to be printed as headers and footers if requested by the user.
  1800. std::string header;
  1801. options.Get("header", &header);
  1802. std::string footer;
  1803. options.Get("footer", &footer);
  1804.  
  1805. if (!(header.empty() && footer.empty())) {
  1806. settings.SetBoolKey(printing::kSettingHeaderFooterEnabled, true);
  1807.  
  1808. settings.SetStringKey(printing::kSettingHeaderFooterTitle, header);
  1809. settings.SetStringKey(printing::kSettingHeaderFooterURL, footer);
  1810. } else {
  1811. settings.SetBoolKey(printing::kSettingHeaderFooterEnabled, false);
  1812. }
  1813.  
  1814. // We don't want to allow the user to enable these settings
  1815. // but we need to set them or a CHECK is hit.
  1816. settings.SetIntKey(printing::kSettingPrinterType, printing::kLocalPrinter);
  1817. settings.SetBoolKey(printing::kSettingShouldPrintSelectionOnly, false);
  1818. settings.SetBoolKey(printing::kSettingRasterizePdf, false);
  1819.  
  1820. // Set custom page ranges to print
  1821. std::vector<gin_helper::Dictionary> page_ranges;
  1822. if (options.Get("pageRanges", &page_ranges)) {
  1823. base::Value page_range_list(base::Value::Type::LIST);
  1824. for (auto& range : page_ranges) {
  1825. int from, to;
  1826. if (range.Get("from", &from) && range.Get("to", &to)) {
  1827. base::Value range(base::Value::Type::DICTIONARY);
  1828. range.SetIntKey(printing::kSettingPageRangeFrom, from);
  1829. range.SetIntKey(printing::kSettingPageRangeTo, to);
  1830. page_range_list.Append(std::move(range));
  1831. } else {
  1832. continue;
  1833. }
  1834. }
  1835. if (page_range_list.GetList().size() > )
  1836. settings.SetPath(printing::kSettingPageRange, std::move(page_range_list));
  1837. }
  1838.  
  1839. // Duplex type user wants to use.
  1840. printing::DuplexMode duplex_mode;
  1841. options.Get("duplexMode", &duplex_mode);
  1842. settings.SetIntKey(printing::kSettingDuplexMode, duplex_mode);
  1843.  
  1844. // Set custom dots per inch (dpi)
  1845. gin_helper::Dictionary dpi_settings;
  1846. int dpi = ;
  1847. if (options.Get("dpi", &dpi_settings)) {
  1848. int horizontal = ;
  1849. dpi_settings.Get("horizontal", &horizontal);
  1850. settings.SetIntKey(printing::kSettingDpiHorizontal, horizontal);
  1851. int vertical = ;
  1852. dpi_settings.Get("vertical", &vertical);
  1853. settings.SetIntKey(printing::kSettingDpiVertical, vertical);
  1854. } else {
  1855. settings.SetIntKey(printing::kSettingDpiHorizontal, dpi);
  1856. settings.SetIntKey(printing::kSettingDpiVertical, dpi);
  1857. }
  1858.  
  1859. auto* print_view_manager =
  1860. printing::PrintViewManagerBasic::FromWebContents(web_contents());
  1861. auto* focused_frame = web_contents()->GetFocusedFrame();
  1862. auto* rfh = focused_frame && focused_frame->HasSelection()
  1863. ? focused_frame
  1864. : web_contents()->GetMainFrame();
  1865. print_view_manager->PrintNow(rfh, silent, std::move(settings),
  1866. std::move(callback));
  1867. }
  1868.  
  1869. std::vector<printing::PrinterBasicInfo> WebContents::GetPrinterList() {
  1870. std::vector<printing::PrinterBasicInfo> printers;
  1871. auto print_backend = printing::PrintBackend::CreateInstance(
  1872. nullptr, g_browser_process->GetApplicationLocale());
  1873. {
  1874. // TODO(deepak1556): Deprecate this api in favor of an
  1875. // async version and post a non blocing task call.
  1876. base::ThreadRestrictions::ScopedAllowIO allow_io;
  1877. print_backend->EnumeratePrinters(&printers);
  1878. }
  1879. return printers;
  1880. }
  1881.  
  1882. v8::Local<v8::Promise> WebContents::PrintToPDF(base::DictionaryValue settings) {
  1883. gin_helper::Promise<v8::Local<v8::Value>> promise(isolate());
  1884. v8::Local<v8::Promise> handle = promise.GetHandle();
  1885. PrintPreviewMessageHandler::FromWebContents(web_contents())
  1886. ->PrintToPDF(std::move(settings), std::move(promise));
  1887. return handle;
  1888. }
  1889. #endif
  1890.  
  1891. void WebContents::AddWorkSpace(gin_helper::Arguments* args,
  1892. const base::FilePath& path) {
  1893. if (path.empty()) {
  1894. args->ThrowError("path cannot be empty");
  1895. return;
  1896. }
  1897. DevToolsAddFileSystem(std::string(), path);
  1898. }
  1899.  
  1900. void WebContents::RemoveWorkSpace(gin_helper::Arguments* args,
  1901. const base::FilePath& path) {
  1902. if (path.empty()) {
  1903. args->ThrowError("path cannot be empty");
  1904. return;
  1905. }
  1906. DevToolsRemoveFileSystem(path);
  1907. }
  1908.  
  1909. void WebContents::Undo() {
  1910. web_contents()->Undo();
  1911. }
  1912.  
  1913. void WebContents::Redo() {
  1914. web_contents()->Redo();
  1915. }
  1916.  
  1917. void WebContents::Cut() {
  1918. web_contents()->Cut();
  1919. }
  1920.  
  1921. void WebContents::Copy() {
  1922. web_contents()->Copy();
  1923. }
  1924.  
  1925. void WebContents::Paste() {
  1926. web_contents()->Paste();
  1927. }
  1928.  
  1929. void WebContents::PasteAndMatchStyle() {
  1930. web_contents()->PasteAndMatchStyle();
  1931. }
  1932.  
  1933. void WebContents::Delete() {
  1934. web_contents()->Delete();
  1935. }
  1936.  
  1937. void WebContents::SelectAll() {
  1938. web_contents()->SelectAll();
  1939. }
  1940.  
  1941. void WebContents::Unselect() {
  1942. web_contents()->CollapseSelection();
  1943. }
  1944.  
  1945. void WebContents::Replace(const base::string16& word) {
  1946. web_contents()->Replace(word);
  1947. }
  1948.  
  1949. void WebContents::ReplaceMisspelling(const base::string16& word) {
  1950. web_contents()->ReplaceMisspelling(word);
  1951. }
  1952.  
  1953. uint32_t WebContents::FindInPage(gin_helper::Arguments* args) {
  1954. base::string16 search_text;
  1955. if (!args->GetNext(&search_text) || search_text.empty()) {
  1956. args->ThrowError("Must provide a non-empty search content");
  1957. return ;
  1958. }
  1959.  
  1960. uint32_t request_id = GetNextRequestId();
  1961. gin_helper::Dictionary dict;
  1962. auto options = blink::mojom::FindOptions::New();
  1963. if (args->GetNext(&dict)) {
  1964. dict.Get("forward", &options->forward);
  1965. dict.Get("matchCase", &options->match_case);
  1966. dict.Get("findNext", &options->find_next);
  1967. }
  1968.  
  1969. web_contents()->Find(request_id, search_text, std::move(options));
  1970. return request_id;
  1971. }
  1972.  
  1973. void WebContents::StopFindInPage(content::StopFindAction action) {
  1974. web_contents()->StopFinding(action);
  1975. }
  1976.  
  1977. void WebContents::ShowDefinitionForSelection() {
  1978. #if defined(OS_MACOSX)
  1979. auto* const view = web_contents()->GetRenderWidgetHostView();
  1980. if (view)
  1981. view->ShowDefinitionForSelection();
  1982. #endif
  1983. }
  1984.  
  1985. void WebContents::CopyImageAt(int x, int y) {
  1986. auto* const host = web_contents()->GetMainFrame();
  1987. if (host)
  1988. host->CopyImageAt(x, y);
  1989. }
  1990.  
  1991. void WebContents::Focus() {
  1992. web_contents()->Focus();
  1993. }
  1994.  
  1995. #if !defined(OS_MACOSX)
  1996. bool WebContents::IsFocused() const {
  1997. auto* view = web_contents()->GetRenderWidgetHostView();
  1998. if (!view)
  1999. return false;
  2000.  
  2001. if (GetType() != Type::BACKGROUND_PAGE) {
  2002. auto* window = web_contents()->GetNativeView()->GetToplevelWindow();
  2003. if (window && !window->IsVisible())
  2004. return false;
  2005. }
  2006.  
  2007. return view->HasFocus();
  2008. }
  2009. #endif
  2010.  
  2011. void WebContents::TabTraverse(bool reverse) {
  2012. web_contents()->FocusThroughTabTraversal(reverse);
  2013. }
  2014.  
  2015. bool WebContents::SendIPCMessage(bool internal,
  2016. bool send_to_all,
  2017. const std::string& channel,
  2018. v8::Local<v8::Value> args) {
  2019. blink::CloneableMessage message;
  2020. if (!gin::ConvertFromV8(isolate(), args, &message)) {
  2021. isolate()->ThrowException(v8::Exception::Error(
  2022. gin::StringToV8(isolate(), "Failed to serialize arguments")));
  2023. return false;
  2024. }
  2025. return SendIPCMessageWithSender(internal, send_to_all, channel,
  2026. std::move(message));
  2027. }
  2028.  
  2029. bool WebContents::SendIPCMessageWithSender(bool internal,
  2030. bool send_to_all,
  2031. const std::string& channel,
  2032. blink::CloneableMessage args,
  2033. int32_t sender_id) {
  2034. std::vector<content::RenderFrameHost*> target_hosts;
  2035. if (!send_to_all) {
  2036. auto* frame_host = web_contents()->GetMainFrame();
  2037. if (frame_host) {
  2038. target_hosts.push_back(frame_host);
  2039. }
  2040. } else {
  2041. target_hosts = web_contents()->GetAllFrames();
  2042. }
  2043.  
  2044. for (auto* frame_host : target_hosts) {
  2045. mojo::AssociatedRemote<mojom::ElectronRenderer> electron_renderer;
  2046. frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
  2047. &electron_renderer);
  2048. electron_renderer->Message(internal, false, channel, args.ShallowClone(),
  2049. sender_id);
  2050. }
  2051. return true;
  2052. }
  2053.  
  2054. bool WebContents::SendIPCMessageToFrame(bool internal,
  2055. bool send_to_all,
  2056. int32_t frame_id,
  2057. const std::string& channel,
  2058. v8::Local<v8::Value> args) {
  2059. blink::CloneableMessage message;
  2060. if (!gin::ConvertFromV8(isolate(), args, &message)) {
  2061. isolate()->ThrowException(v8::Exception::Error(
  2062. gin::StringToV8(isolate(), "Failed to serialize arguments")));
  2063. return false;
  2064. }
  2065. auto frames = web_contents()->GetAllFrames();
  2066. auto iter = std::find_if(frames.begin(), frames.end(), [frame_id](auto* f) {
  2067. return f->GetRoutingID() == frame_id;
  2068. });
  2069. if (iter == frames.end())
  2070. return false;
  2071. if (!(*iter)->IsRenderFrameLive())
  2072. return false;
  2073.  
  2074. mojo::AssociatedRemote<mojom::ElectronRenderer> electron_renderer;
  2075. (*iter)->GetRemoteAssociatedInterfaces()->GetInterface(&electron_renderer);
  2076. electron_renderer->Message(internal, send_to_all, channel, std::move(message),
  2077. /* sender_id */);
  2078. return true;
  2079. }
  2080.  
  2081. void WebContents::SendInputEvent(v8::Isolate* isolate,
  2082. v8::Local<v8::Value> input_event) {
  2083. content::RenderWidgetHostView* view =
  2084. web_contents()->GetRenderWidgetHostView();
  2085. if (!view)
  2086. return;
  2087.  
  2088. content::RenderWidgetHost* rwh = view->GetRenderWidgetHost();
  2089. blink::WebInputEvent::Type type =
  2090. gin::GetWebInputEventType(isolate, input_event);
  2091. if (blink::WebInputEvent::IsMouseEventType(type)) {
  2092. blink::WebMouseEvent mouse_event;
  2093. if (gin::ConvertFromV8(isolate, input_event, &mouse_event)) {
  2094. if (IsOffScreen()) {
  2095. #if BUILDFLAG(ENABLE_OSR)
  2096. GetOffScreenRenderWidgetHostView()->SendMouseEvent(mouse_event);
  2097. #endif
  2098. } else {
  2099. rwh->ForwardMouseEvent(mouse_event);
  2100. }
  2101. return;
  2102. }
  2103. } else if (blink::WebInputEvent::IsKeyboardEventType(type)) {
  2104. content::NativeWebKeyboardEvent keyboard_event(
  2105. blink::WebKeyboardEvent::kRawKeyDown,
  2106. blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
  2107. if (gin::ConvertFromV8(isolate, input_event, &keyboard_event)) {
  2108. rwh->ForwardKeyboardEvent(keyboard_event);
  2109. return;
  2110. }
  2111. } else if (type == blink::WebInputEvent::kMouseWheel) {
  2112. blink::WebMouseWheelEvent mouse_wheel_event;
  2113. if (gin::ConvertFromV8(isolate, input_event, &mouse_wheel_event)) {
  2114. if (IsOffScreen()) {
  2115. #if BUILDFLAG(ENABLE_OSR)
  2116. GetOffScreenRenderWidgetHostView()->SendMouseWheelEvent(
  2117. mouse_wheel_event);
  2118. #endif
  2119. } else {
  2120. // Chromium expects phase info in wheel events (and applies a
  2121. // DCHECK to verify it). See: https://crbug.com/756524.
  2122. mouse_wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
  2123. mouse_wheel_event.dispatch_type = blink::WebInputEvent::kBlocking;
  2124. rwh->ForwardWheelEvent(mouse_wheel_event);
  2125.  
  2126. // Send a synthetic wheel event with phaseEnded to finish scrolling.
  2127. mouse_wheel_event.has_synthetic_phase = true;
  2128. mouse_wheel_event.delta_x = ;
  2129. mouse_wheel_event.delta_y = ;
  2130. mouse_wheel_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
  2131. mouse_wheel_event.dispatch_type =
  2132. blink::WebInputEvent::kEventNonBlocking;
  2133. rwh->ForwardWheelEvent(mouse_wheel_event);
  2134. }
  2135. return;
  2136. }
  2137. }
  2138.  
  2139. isolate->ThrowException(
  2140. v8::Exception::Error(gin::StringToV8(isolate, "Invalid event object")));
  2141. }
  2142.  
  2143. void WebContents::BeginFrameSubscription(gin_helper::Arguments* args) {
  2144. bool only_dirty = false;
  2145. FrameSubscriber::FrameCaptureCallback callback;
  2146.  
  2147. args->GetNext(&only_dirty);
  2148. if (!args->GetNext(&callback)) {
  2149. args->ThrowError();
  2150. return;
  2151. }
  2152.  
  2153. frame_subscriber_ =
  2154. std::make_unique<FrameSubscriber>(web_contents(), callback, only_dirty);
  2155. }
  2156.  
  2157. void WebContents::EndFrameSubscription() {
  2158. frame_subscriber_.reset();
  2159. }
  2160.  
  2161. void WebContents::StartDrag(const gin_helper::Dictionary& item,
  2162. gin_helper::Arguments* args) {
  2163. base::FilePath file;
  2164. std::vector<base::FilePath> files;
  2165. if (!item.Get("files", &files) && item.Get("file", &file)) {
  2166. files.push_back(file);
  2167. }
  2168.  
  2169. gin::Handle<NativeImage> icon;
  2170. if (!item.Get("icon", &icon)) {
  2171. args->ThrowError("Must specify non-empty 'icon' option");
  2172. return;
  2173. }
  2174.  
  2175. // Start dragging.
  2176. if (!files.empty()) {
  2177. base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
  2178. DragFileItems(files, icon->image(), web_contents()->GetNativeView());
  2179. } else {
  2180. args->ThrowError("Must specify either 'file' or 'files' option");
  2181. }
  2182. }
  2183.  
  2184. v8::Local<v8::Promise> WebContents::CapturePage(gin_helper::Arguments* args) {
  2185. gfx::Rect rect;
  2186. gin_helper::Promise<gfx::Image> promise(isolate());
  2187. v8::Local<v8::Promise> handle = promise.GetHandle();
  2188.  
  2189. // get rect arguments if they exist
  2190. args->GetNext(&rect);
  2191.  
  2192. auto* const view = web_contents()->GetRenderWidgetHostView();
  2193. if (!view) {
  2194. promise.Resolve(gfx::Image());
  2195. return handle;
  2196. }
  2197.  
  2198. // Capture full page if user doesn't specify a |rect|.
  2199. const gfx::Size view_size =
  2200. rect.IsEmpty() ? view->GetViewBounds().size() : rect.size();
  2201.  
  2202. // By default, the requested bitmap size is the view size in screen
  2203. // coordinates. However, if there's more pixel detail available on the
  2204. // current system, increase the requested bitmap size to capture it all.
  2205. gfx::Size bitmap_size = view_size;
  2206. const gfx::NativeView native_view = view->GetNativeView();
  2207. const float scale = display::Screen::GetScreen()
  2208. ->GetDisplayNearestView(native_view)
  2209. .device_scale_factor();
  2210. if (scale > 1.0f)
  2211. bitmap_size = gfx::ScaleToCeiledSize(view_size, scale);
  2212.  
  2213. view->CopyFromSurface(gfx::Rect(rect.origin(), view_size), bitmap_size,
  2214. base::BindOnce(&OnCapturePageDone, std::move(promise)));
  2215. return handle;
  2216. }
  2217.  
  2218. void WebContents::OnCursorChange(const content::WebCursor& cursor) {
  2219. const content::CursorInfo& info = cursor.info();
  2220.  
  2221. if (info.type == ui::CursorType::kCustom) {
  2222. Emit("cursor-changed", CursorTypeToString(info),
  2223. gfx::Image::CreateFrom1xBitmap(info.custom_image),
  2224. info.image_scale_factor,
  2225. gfx::Size(info.custom_image.width(), info.custom_image.height()),
  2226. info.hotspot);
  2227. } else {
  2228. Emit("cursor-changed", CursorTypeToString(info));
  2229. }
  2230. }
  2231.  
  2232. bool WebContents::IsGuest() const {
  2233. return type_ == Type::WEB_VIEW;
  2234. }
  2235.  
  2236. void WebContents::AttachToIframe(content::WebContents* embedder_web_contents,
  2237. int embedder_frame_id) {
  2238. if (guest_delegate_)
  2239. guest_delegate_->AttachToIframe(embedder_web_contents, embedder_frame_id);
  2240. }
  2241.  
  2242. bool WebContents::IsOffScreen() const {
  2243. #if BUILDFLAG(ENABLE_OSR)
  2244. return type_ == Type::OFF_SCREEN;
  2245. #else
  2246. return false;
  2247. #endif
  2248. }
  2249.  
  2250. #if BUILDFLAG(ENABLE_OSR)
  2251. void WebContents::OnPaint(const gfx::Rect& dirty_rect, const SkBitmap& bitmap) {
  2252. Emit("paint", dirty_rect, gfx::Image::CreateFrom1xBitmap(bitmap));
  2253. }
  2254.  
  2255. void WebContents::StartPainting() {
  2256. auto* osr_wcv = GetOffScreenWebContentsView();
  2257. if (osr_wcv)
  2258. osr_wcv->SetPainting(true);
  2259. }
  2260.  
  2261. void WebContents::StopPainting() {
  2262. auto* osr_wcv = GetOffScreenWebContentsView();
  2263. if (osr_wcv)
  2264. osr_wcv->SetPainting(false);
  2265. }
  2266.  
  2267. bool WebContents::IsPainting() const {
  2268. auto* osr_wcv = GetOffScreenWebContentsView();
  2269. return osr_wcv && osr_wcv->IsPainting();
  2270. }
  2271.  
  2272. void WebContents::SetFrameRate(int frame_rate) {
  2273. auto* osr_wcv = GetOffScreenWebContentsView();
  2274. if (osr_wcv)
  2275. osr_wcv->SetFrameRate(frame_rate);
  2276. }
  2277.  
  2278. int WebContents::GetFrameRate() const {
  2279. auto* osr_wcv = GetOffScreenWebContentsView();
  2280. return osr_wcv ? osr_wcv->GetFrameRate() : ;
  2281. }
  2282. #endif
  2283.  
  2284. void WebContents::Invalidate() {
  2285. if (IsOffScreen()) {
  2286. #if BUILDFLAG(ENABLE_OSR)
  2287. auto* osr_rwhv = GetOffScreenRenderWidgetHostView();
  2288. if (osr_rwhv)
  2289. osr_rwhv->Invalidate();
  2290. #endif
  2291. } else {
  2292. auto* const window = owner_window();
  2293. if (window)
  2294. window->Invalidate();
  2295. }
  2296. }
  2297.  
  2298. gfx::Size WebContents::GetSizeForNewRenderView(content::WebContents* wc) {
  2299. if (IsOffScreen() && wc == web_contents()) {
  2300. auto* relay = NativeWindowRelay::FromWebContents(web_contents());
  2301. if (relay) {
  2302. auto* owner_window = relay->GetNativeWindow();
  2303. return owner_window ? owner_window->GetSize() : gfx::Size();
  2304. }
  2305. }
  2306.  
  2307. return gfx::Size();
  2308. }
  2309.  
  2310. void WebContents::SetZoomLevel(double level) {
  2311. zoom_controller_->SetZoomLevel(level);
  2312. }
  2313.  
  2314. double WebContents::GetZoomLevel() const {
  2315. return zoom_controller_->GetZoomLevel();
  2316. }
  2317.  
  2318. void WebContents::SetZoomFactor(double factor) {
  2319. auto level = blink::PageZoomFactorToZoomLevel(factor);
  2320. SetZoomLevel(level);
  2321. }
  2322.  
  2323. double WebContents::GetZoomFactor() const {
  2324. auto level = GetZoomLevel();
  2325. return blink::PageZoomLevelToZoomFactor(level);
  2326. }
  2327.  
  2328. void WebContents::SetTemporaryZoomLevel(double level) {
  2329. zoom_controller_->SetTemporaryZoomLevel(level);
  2330. }
  2331.  
  2332. void WebContents::DoGetZoomLevel(DoGetZoomLevelCallback callback) {
  2333. std::move(callback).Run(GetZoomLevel());
  2334. }
  2335.  
  2336. std::vector<base::FilePath::StringType> WebContents::GetPreloadPaths() const {
  2337. auto result = SessionPreferences::GetValidPreloads(GetBrowserContext());
  2338.  
  2339. if (auto* web_preferences = WebContentsPreferences::From(web_contents())) {
  2340. base::FilePath::StringType preload;
  2341. if (web_preferences->GetPreloadPath(&preload)) {
  2342. result.emplace_back(preload);
  2343. }
  2344. }
  2345.  
  2346. return result;
  2347. }
  2348.  
  2349. v8::Local<v8::Value> WebContents::GetWebPreferences(
  2350. v8::Isolate* isolate) const {
  2351. auto* web_preferences = WebContentsPreferences::From(web_contents());
  2352. if (!web_preferences)
  2353. return v8::Null(isolate);
  2354. return gin::ConvertToV8(isolate, *web_preferences->preference());
  2355. }
  2356.  
  2357. v8::Local<v8::Value> WebContents::GetLastWebPreferences(
  2358. v8::Isolate* isolate) const {
  2359. auto* web_preferences = WebContentsPreferences::From(web_contents());
  2360. if (!web_preferences)
  2361. return v8::Null(isolate);
  2362. return gin::ConvertToV8(isolate, *web_preferences->last_preference());
  2363. }
  2364.  
  2365. v8::Local<v8::Value> WebContents::GetOwnerBrowserWindow() const {
  2366. if (owner_window())
  2367. return BrowserWindow::From(isolate(), owner_window());
  2368. else
  2369. return v8::Null(isolate());
  2370. }
  2371.  
  2372. int32_t WebContents::ID() const {
  2373. return weak_map_id();
  2374. }
  2375.  
  2376. v8::Local<v8::Value> WebContents::Session(v8::Isolate* isolate) {
  2377. return v8::Local<v8::Value>::New(isolate, session_);
  2378. }
  2379.  
  2380. content::WebContents* WebContents::HostWebContents() const {
  2381. if (!embedder_)
  2382. return nullptr;
  2383. return embedder_->web_contents();
  2384. }
  2385.  
  2386. void WebContents::SetEmbedder(const WebContents* embedder) {
  2387. if (embedder) {
  2388. NativeWindow* owner_window = nullptr;
  2389. auto* relay = NativeWindowRelay::FromWebContents(embedder->web_contents());
  2390. if (relay) {
  2391. owner_window = relay->GetNativeWindow();
  2392. }
  2393. if (owner_window)
  2394. SetOwnerWindow(owner_window);
  2395.  
  2396. content::RenderWidgetHostView* rwhv =
  2397. web_contents()->GetRenderWidgetHostView();
  2398. if (rwhv) {
  2399. rwhv->Hide();
  2400. rwhv->Show();
  2401. }
  2402. }
  2403. }
  2404.  
  2405. void WebContents::SetDevToolsWebContents(const WebContents* devtools) {
  2406. if (managed_web_contents())
  2407. managed_web_contents()->SetDevToolsWebContents(devtools->web_contents());
  2408. }
  2409.  
  2410. v8::Local<v8::Value> WebContents::GetNativeView() const {
  2411. gfx::NativeView ptr = web_contents()->GetNativeView();
  2412. auto buffer = node::Buffer::Copy(isolate(), reinterpret_cast<char*>(&ptr),
  2413. sizeof(gfx::NativeView));
  2414. if (buffer.IsEmpty())
  2415. return v8::Null(isolate());
  2416. else
  2417. return buffer.ToLocalChecked();
  2418. }
  2419.  
  2420. v8::Local<v8::Value> WebContents::DevToolsWebContents(v8::Isolate* isolate) {
  2421. if (devtools_web_contents_.IsEmpty())
  2422. return v8::Null(isolate);
  2423. else
  2424. return v8::Local<v8::Value>::New(isolate, devtools_web_contents_);
  2425. }
  2426.  
  2427. v8::Local<v8::Value> WebContents::Debugger(v8::Isolate* isolate) {
  2428. if (debugger_.IsEmpty()) {
  2429. auto handle = electron::api::Debugger::Create(isolate, web_contents());
  2430. debugger_.Reset(isolate, handle.ToV8());
  2431. }
  2432. return v8::Local<v8::Value>::New(isolate, debugger_);
  2433. }
  2434.  
  2435. void WebContents::GrantOriginAccess(const GURL& url) {
  2436. content::ChildProcessSecurityPolicy::GetInstance()->GrantCommitOrigin(
  2437. web_contents()->GetMainFrame()->GetProcess()->GetID(),
  2438. url::Origin::Create(url));
  2439. }
  2440.  
  2441. v8::Local<v8::Promise> WebContents::TakeHeapSnapshot(
  2442. const base::FilePath& file_path) {
  2443. gin_helper::Promise<void> promise(isolate());
  2444. v8::Local<v8::Promise> handle = promise.GetHandle();
  2445.  
  2446. base::ThreadRestrictions::ScopedAllowIO allow_io;
  2447. base::File file(file_path,
  2448. base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
  2449. if (!file.IsValid()) {
  2450. promise.RejectWithErrorMessage("takeHeapSnapshot failed");
  2451. return handle;
  2452. }
  2453.  
  2454. auto* frame_host = web_contents()->GetMainFrame();
  2455. if (!frame_host) {
  2456. promise.RejectWithErrorMessage("takeHeapSnapshot failed");
  2457. return handle;
  2458. }
  2459.  
  2460. // This dance with `base::Owned` is to ensure that the interface stays alive
  2461. // until the callback is called. Otherwise it would be closed at the end of
  2462. // this function.
  2463. auto electron_renderer =
  2464. std::make_unique<mojo::AssociatedRemote<mojom::ElectronRenderer>>();
  2465. frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
  2466. electron_renderer.get());
  2467. auto* raw_ptr = electron_renderer.get();
  2468. (*raw_ptr)->TakeHeapSnapshot(
  2469. mojo::WrapPlatformFile(file.TakePlatformFile()),
  2470. base::BindOnce(
  2471. [](mojo::AssociatedRemote<mojom::ElectronRenderer>* ep,
  2472. gin_helper::Promise<void> promise, bool success) {
  2473. if (success) {
  2474. promise.Resolve();
  2475. } else {
  2476. promise.RejectWithErrorMessage("takeHeapSnapshot failed");
  2477. }
  2478. },
  2479. base::Owned(std::move(electron_renderer)), std::move(promise)));
  2480. return handle;
  2481. }
  2482.  
  2483. // static
  2484. void WebContents::BuildPrototype(v8::Isolate* isolate,
  2485. v8::Local<v8::FunctionTemplate> prototype) {
  2486. prototype->SetClassName(gin::StringToV8(isolate, "WebContents"));
  2487. gin_helper::Destroyable::MakeDestroyable(isolate, prototype);
  2488. gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
  2489. .SetMethod("setBackgroundThrottling",
  2490. &WebContents::SetBackgroundThrottling)
  2491. .SetMethod("getProcessId", &WebContents::GetProcessID)
  2492. .SetMethod("getOSProcessId", &WebContents::GetOSProcessID)
  2493. .SetMethod("_getOSProcessIdForFrame",
  2494. &WebContents::GetOSProcessIdForFrame)
  2495. .SetMethod("equal", &WebContents::Equal)
  2496. .SetMethod("_loadURL", &WebContents::LoadURL)
  2497. .SetMethod("downloadURL", &WebContents::DownloadURL)
  2498. .SetMethod("_getURL", &WebContents::GetURL)
  2499. .SetMethod("getTitle", &WebContents::GetTitle)
  2500. .SetMethod("isLoading", &WebContents::IsLoading)
  2501. .SetMethod("isLoadingMainFrame", &WebContents::IsLoadingMainFrame)
  2502. .SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
  2503. .SetMethod("_stop", &WebContents::Stop)
  2504. .SetMethod("_goBack", &WebContents::GoBack)
  2505. .SetMethod("_goForward", &WebContents::GoForward)
  2506. .SetMethod("_goToOffset", &WebContents::GoToOffset)
  2507. .SetMethod("isCrashed", &WebContents::IsCrashed)
  2508. .SetMethod("_setUserAgent", &WebContents::SetUserAgent)
  2509. .SetMethod("_getUserAgent", &WebContents::GetUserAgent)
  2510. .SetProperty("userAgent", &WebContents::GetUserAgent,
  2511. &WebContents::SetUserAgent)
  2512. .SetMethod("savePage", &WebContents::SavePage)
  2513. .SetMethod("openDevTools", &WebContents::OpenDevTools)
  2514. .SetMethod("closeDevTools", &WebContents::CloseDevTools)
  2515. .SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
  2516. .SetMethod("isDevToolsFocused", &WebContents::IsDevToolsFocused)
  2517. .SetMethod("enableDeviceEmulation", &WebContents::EnableDeviceEmulation)
  2518. .SetMethod("disableDeviceEmulation", &WebContents::DisableDeviceEmulation)
  2519. .SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
  2520. .SetMethod("inspectElement", &WebContents::InspectElement)
  2521. .SetMethod("setIgnoreMenuShortcuts", &WebContents::SetIgnoreMenuShortcuts)
  2522. .SetMethod("_setAudioMuted", &WebContents::SetAudioMuted)
  2523. .SetMethod("_isAudioMuted", &WebContents::IsAudioMuted)
  2524. .SetProperty("audioMuted", &WebContents::IsAudioMuted,
  2525. &WebContents::SetAudioMuted)
  2526. .SetMethod("isCurrentlyAudible", &WebContents::IsCurrentlyAudible)
  2527. .SetMethod("undo", &WebContents::Undo)
  2528. .SetMethod("redo", &WebContents::Redo)
  2529. .SetMethod("cut", &WebContents::Cut)
  2530. .SetMethod("copy", &WebContents::Copy)
  2531. .SetMethod("paste", &WebContents::Paste)
  2532. .SetMethod("pasteAndMatchStyle", &WebContents::PasteAndMatchStyle)
  2533. .SetMethod("delete", &WebContents::Delete)
  2534. .SetMethod("selectAll", &WebContents::SelectAll)
  2535. .SetMethod("unselect", &WebContents::Unselect)
  2536. .SetMethod("replace", &WebContents::Replace)
  2537. .SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling)
  2538. .SetMethod("findInPage", &WebContents::FindInPage)
  2539. .SetMethod("stopFindInPage", &WebContents::StopFindInPage)
  2540. .SetMethod("focus", &WebContents::Focus)
  2541. .SetMethod("isFocused", &WebContents::IsFocused)
  2542. .SetMethod("tabTraverse", &WebContents::TabTraverse)
  2543. .SetMethod("_send", &WebContents::SendIPCMessage)
  2544. .SetMethod("_sendToFrame", &WebContents::SendIPCMessageToFrame)
  2545. .SetMethod("sendInputEvent", &WebContents::SendInputEvent)
  2546. .SetMethod("beginFrameSubscription", &WebContents::BeginFrameSubscription)
  2547. .SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
  2548. .SetMethod("startDrag", &WebContents::StartDrag)
  2549. .SetMethod("attachToIframe", &WebContents::AttachToIframe)
  2550. .SetMethod("detachFromOuterFrame", &WebContents::DetachFromOuterFrame)
  2551. .SetMethod("isOffscreen", &WebContents::IsOffScreen)
  2552. #if BUILDFLAG(ENABLE_OSR)
  2553. .SetMethod("startPainting", &WebContents::StartPainting)
  2554. .SetMethod("stopPainting", &WebContents::StopPainting)
  2555. .SetMethod("isPainting", &WebContents::IsPainting)
  2556. .SetMethod("_setFrameRate", &WebContents::SetFrameRate)
  2557. .SetMethod("_getFrameRate", &WebContents::GetFrameRate)
  2558. .SetProperty("frameRate", &WebContents::GetFrameRate,
  2559. &WebContents::SetFrameRate)
  2560. #endif
  2561. .SetMethod("invalidate", &WebContents::Invalidate)
  2562. .SetMethod("_setZoomLevel", &WebContents::SetZoomLevel)
  2563. .SetMethod("_getZoomLevel", &WebContents::GetZoomLevel)
  2564. .SetProperty("zoomLevel", &WebContents::GetZoomLevel,
  2565. &WebContents::SetZoomLevel)
  2566. .SetMethod("_setZoomFactor", &WebContents::SetZoomFactor)
  2567. .SetMethod("_getZoomFactor", &WebContents::GetZoomFactor)
  2568. .SetProperty("zoomFactor", &WebContents::GetZoomFactor,
  2569. &WebContents::SetZoomFactor)
  2570. .SetMethod("getType", &WebContents::GetType)
  2571. .SetMethod("_getPreloadPaths", &WebContents::GetPreloadPaths)
  2572. .SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
  2573. .SetMethod("getLastWebPreferences", &WebContents::GetLastWebPreferences)
  2574. .SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
  2575. .SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker)
  2576. .SetMethod("inspectSharedWorker", &WebContents::InspectSharedWorker)
  2577. .SetMethod("inspectSharedWorkerById",
  2578. &WebContents::InspectSharedWorkerById)
  2579. .SetMethod("getAllSharedWorkers", &WebContents::GetAllSharedWorkers)
  2580. #if BUILDFLAG(ENABLE_PRINTING)
  2581. .SetMethod("_print", &WebContents::Print)
  2582. .SetMethod("_getPrinters", &WebContents::GetPrinterList)
  2583. .SetMethod("_printToPDF", &WebContents::PrintToPDF)
  2584. #endif
  2585. .SetMethod("addWorkSpace", &WebContents::AddWorkSpace)
  2586. .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
  2587. .SetMethod("showDefinitionForSelection",
  2588. &WebContents::ShowDefinitionForSelection)
  2589. .SetMethod("copyImageAt", &WebContents::CopyImageAt)
  2590. .SetMethod("capturePage", &WebContents::CapturePage)
  2591. .SetMethod("setEmbedder", &WebContents::SetEmbedder)
  2592. .SetMethod("setDevToolsWebContents", &WebContents::SetDevToolsWebContents)
  2593. .SetMethod("getNativeView", &WebContents::GetNativeView)
  2594. .SetMethod("setWebRTCIPHandlingPolicy",
  2595. &WebContents::SetWebRTCIPHandlingPolicy)
  2596. .SetMethod("getWebRTCIPHandlingPolicy",
  2597. &WebContents::GetWebRTCIPHandlingPolicy)
  2598. .SetMethod("_grantOriginAccess", &WebContents::GrantOriginAccess)
  2599. .SetMethod("takeHeapSnapshot", &WebContents::TakeHeapSnapshot)
  2600. .SetProperty("id", &WebContents::ID)
  2601. .SetProperty("session", &WebContents::Session)
  2602. .SetProperty("hostWebContents", &WebContents::HostWebContents)
  2603. .SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents)
  2604. .SetProperty("debugger", &WebContents::Debugger);
  2605. }
  2606.  
  2607. AtomBrowserContext* WebContents::GetBrowserContext() const {
  2608. return static_cast<AtomBrowserContext*>(web_contents()->GetBrowserContext());
  2609. }
  2610.  
  2611. // static
  2612. gin::Handle<WebContents> WebContents::Create(
  2613. v8::Isolate* isolate,
  2614. const gin_helper::Dictionary& options) {
  2615. return gin::CreateHandle(isolate, new WebContents(isolate, options));
  2616. }
  2617.  
  2618. // static
  2619. gin::Handle<WebContents> WebContents::CreateAndTake(
  2620. v8::Isolate* isolate,
  2621. std::unique_ptr<content::WebContents> web_contents,
  2622. Type type) {
  2623. return gin::CreateHandle(
  2624. isolate, new WebContents(isolate, std::move(web_contents), type));
  2625. }
  2626.  
  2627. // static
  2628. gin::Handle<WebContents> WebContents::From(v8::Isolate* isolate,
  2629. content::WebContents* web_contents) {
  2630. auto* existing = TrackableObject::FromWrappedClass(isolate, web_contents);
  2631. if (existing)
  2632. return gin::CreateHandle(isolate, static_cast<WebContents*>(existing));
  2633. else
  2634. return gin::Handle<WebContents>();
  2635. }
  2636.  
  2637. // static
  2638. gin::Handle<WebContents> WebContents::FromOrCreate(
  2639. v8::Isolate* isolate,
  2640. content::WebContents* web_contents) {
  2641. auto existing = From(isolate, web_contents);
  2642. if (!existing.IsEmpty())
  2643. return existing;
  2644. else
  2645. return gin::CreateHandle(isolate, new WebContents(isolate, web_contents));
  2646. }
  2647.  
  2648. } // namespace api
  2649.  
  2650. } // namespace electron
  2651.  
  2652. namespace {
  2653.  
  2654. using electron::api::WebContents;
  2655.  
  2656. void Initialize(v8::Local<v8::Object> exports,
  2657. v8::Local<v8::Value> unused,
  2658. v8::Local<v8::Context> context,
  2659. void* priv) {
  2660. v8::Isolate* isolate = context->GetIsolate();
  2661. gin_helper::Dictionary dict(isolate, exports);
  2662. dict.Set("WebContents", WebContents::GetConstructor(isolate)
  2663. ->GetFunction(context)
  2664. .ToLocalChecked());
  2665. dict.SetMethod("create", &WebContents::Create);
  2666. dict.SetMethod("fromId", &WebContents::FromWeakMapID);
  2667. dict.SetMethod("getAllWebContents", &WebContents::GetAll);
  2668. }
  2669.  
  2670. } // namespace
  2671.  
  2672. NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_web_contents, Initialize)

electron api sendInputEvent 源码的更多相关文章

  1. 通过官方API结合源码,如何分析程序流程

    通过官方API结合源码,如何分析程序流程通过官方API找到我们关注的API的某个方法,然后把整个流程执行起来,然后在idea中,把我们关注的方法打上断点,然后通过Step Out,从内向外一层一层分析 ...

  2. Spring中AOP相关的API及源码解析

    Spring中AOP相关的API及源码解析 本系列文章: 读源码,我们可以从第一行读起 你知道Spring是怎么解析配置类的吗? 配置类为什么要添加@Configuration注解? 谈谈Spring ...

  3. android 隐藏API 在源码下编译报错cannot find symbol symbol

    应该是我对android 不熟悉的缘故,今天使用源码编译了一个调用了隐藏api的应用程序始终报错: cannot find symbol symbol  : class IPackageInstall ...

  4. asp.net web api的源码

    从安装的NuGet packages逆向找回去 <package id="Microsoft.AspNet.WebApi.Core" version="5.2.7& ...

  5. java.io.BufferedWriter API 以及源码解读

    下面是java se 7 API 对于java.io.BufferedWriter 继承关系的描述. BufferedWriter可以将文本写入字符流.它会将字符缓存,目的是提高写入字符的效率. bu ...

  6. java.io.writer API 以及 源码解读

    声明 我看的是java7的API文档. 如下图所示,java.io.writer 继承了java.lang.Object,实现的接口有Closeable, Flushable, Appendable, ...

  7. Vue3全局APi解析-源码学习

    本文章共5314字,预计阅读时间5-15分钟. 前言 不知不觉Vue-next的版本已经来到了3.1.2,最近对照着源码学习Vue3的全局Api,边学习边整理了下来,希望可以和大家一起进步. 我们以官 ...

  8. OutputStreamWriter API 以及源码解读

    OutputStreamWriter是字符流与字节流之间的桥梁. 通过它写入的字符流可以通过特殊的字符集转化为字节流.这个特殊的字符集可以指定,也可以采用平台默认的字符集. 每一次调用write()方 ...

  9. Soul API 网关源码解析 02

    如何读开源项目:对着文档跑demo,对着demo看代码,懂一点就开始试,有问题了问社区. 今日目标: 1.运行examples下面的 http服务 2.学习文档,结合divde插件,发起http请求s ...

随机推荐

  1. MongoDB 实体映射

    @Id主键,不可重复,自带索引,可以在定义的列名上标注,需要自己生成并维护不重复的约束.如果自己不设置@Id主键,mongo会自动生成一个唯一主键,并且插入时效率远高于自己设置主键.在实际业务中不建议 ...

  2. 转:SpringMVC 4.1 新特性(二)内容协商视图

    SpingMVC的内容协商支持三种方式: 使用后缀,如json.xml后缀和处理类型的关系可以自己定义 前面说的使用Accept头 在访问时request请求的参数,比如每次请求request都会加f ...

  3. 概率dp作业

    概率dp特征: 概率DP一般求的是实际结果,在DP过程中,当前状态是由所有子状态的概率共同转移而来,所以概率DP只是利用了DP的动态而没有规划(即只需转移无需决策).-------qkoqhh A - ...

  4. System.arraycopy() 数组复制方法

    一.深度复制和浅度复制的区别    Java数组的复制操作可以分为深度复制和浅度复制,简单来说深度复制,可以将对象的值和对象的内容复制;浅复制是指对对象引用的复制. 二.System.arraycop ...

  5. RocketMQ之十:RocketMQ消息接收源码

    1. 简介 1.1.接收消息 RebalanceService:均衡消息队列服务,负责通过MQClientInstance分配当前 Consumer 可消费的消息队列( MessageQueue ). ...

  6. 关于Linux系统打开最大文件数量

    今天做压力测试 客户端数据提到2000人,在这个过程中,遇到了分配socket失败的问题提示 errno:24 Too many open files查找资料后发现是Linux系统配置了打开文件的最大 ...

  7. antd <BackTop>组件的使用

    <Content className={style.content} style={{ maxHeight: 'calc(100vh - 175px)',overflowY:"auto ...

  8. 在Linux虚拟机里开启Apache服务

    首先第一步我们配置环境:把yum与Linux ping通 1.我们来下载apache服务,输入:yum install httpd * 2.安装完毕之后默认是死的,要给他启动一下,输入命令:syste ...

  9. Git centos 安装

    Git 安装 Centos 下安装 Git,默认在 CentOS 下,我们可以通过 yum 的方式来安装 Git root@ci‐node1 ~]# yum install git –y root@c ...

  10. 阿里redis

    参考: 连接: https://help.aliyun.com/document_detail/43848.html?spm=a2c4g.11186623.2.29.295542efrNOQy0 同R ...