2014-10-31 18:17:05 +00:00
|
|
|
|
// Copyright (c) 2014 GitHub, Inc.
|
2014-04-25 09:49:37 +00:00
|
|
|
|
// Use of this source code is governed by the MIT license that can be
|
2014-04-24 08:45:25 +00:00
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/browser/api/electron_api_web_contents.h"
|
2014-04-24 08:45:25 +00:00
|
|
|
|
|
2020-03-13 23:13:05 +00:00
|
|
|
|
#include <limits>
|
2024-07-25 09:25:45 +00:00
|
|
|
|
#include <list>
|
2018-09-13 00:25:56 +00:00
|
|
|
|
#include <memory>
|
2024-01-10 22:23:35 +00:00
|
|
|
|
#include <optional>
|
2015-04-25 04:43:52 +00:00
|
|
|
|
#include <set>
|
2015-12-11 15:54:32 +00:00
|
|
|
|
#include <string>
|
2024-01-11 01:00:37 +00:00
|
|
|
|
#include <string_view>
|
2018-09-13 00:25:56 +00:00
|
|
|
|
#include <utility>
|
2019-10-02 12:38:27 +00:00
|
|
|
|
#include <vector>
|
2015-04-25 04:43:52 +00:00
|
|
|
|
|
2024-06-07 21:18:35 +00:00
|
|
|
|
#include "base/base64.h"
|
2023-05-30 08:28:43 +00:00
|
|
|
|
#include "base/containers/contains.h"
|
2023-06-22 12:33:44 +00:00
|
|
|
|
#include "base/containers/fixed_flat_map.h"
|
2020-07-30 16:17:57 +00:00
|
|
|
|
#include "base/containers/id_map.h"
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#include "base/files/file_util.h"
|
|
|
|
|
#include "base/json/json_reader.h"
|
2019-01-10 16:28:15 +00:00
|
|
|
|
#include "base/no_destructor.h"
|
2014-04-25 08:13:16 +00:00
|
|
|
|
#include "base/strings/utf_string_conversions.h"
|
2020-07-22 05:34:34 +00:00
|
|
|
|
#include "base/task/current_thread.h"
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#include "base/threading/scoped_blocking_call.h"
|
2017-02-06 09:18:04 +00:00
|
|
|
|
#include "base/values.h"
|
2018-04-02 03:47:00 +00:00
|
|
|
|
#include "chrome/browser/browser_process.h"
|
2024-07-29 17:42:57 +00:00
|
|
|
|
#include "chrome/browser/devtools/devtools_eye_dropper.h"
|
2023-06-08 06:56:31 +00:00
|
|
|
|
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
|
2021-10-28 14:23:05 +00:00
|
|
|
|
#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
|
2021-01-21 21:02:29 +00:00
|
|
|
|
#include "chrome/browser/ui/views/eye_dropper/eye_dropper.h"
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#include "chrome/common/pref_names.h"
|
2022-06-13 16:35:42 +00:00
|
|
|
|
#include "components/embedder_support/user_agent_utils.h"
|
2024-06-07 21:18:35 +00:00
|
|
|
|
#include "components/input/native_web_keyboard_event.h"
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#include "components/prefs/pref_service.h"
|
|
|
|
|
#include "components/prefs/scoped_user_pref_update.h"
|
|
|
|
|
#include "components/security_state/content/content_utils.h"
|
|
|
|
|
#include "components/security_state/core/security_state.h"
|
2020-09-21 08:00:36 +00:00
|
|
|
|
#include "content/browser/renderer_host/frame_tree_node.h" // nogncheck
|
2023-10-10 10:46:04 +00:00
|
|
|
|
#include "content/browser/renderer_host/navigation_controller_impl.h" // nogncheck
|
2020-09-21 08:00:36 +00:00
|
|
|
|
#include "content/browser/renderer_host/render_frame_host_manager.h" // nogncheck
|
2019-03-05 05:08:55 +00:00
|
|
|
|
#include "content/browser/renderer_host/render_widget_host_impl.h" // nogncheck
|
|
|
|
|
#include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck
|
2017-06-30 22:47:41 +00:00
|
|
|
|
#include "content/public/browser/child_process_security_policy.h"
|
2020-03-14 20:54:14 +00:00
|
|
|
|
#include "content/public/browser/context_menu_params.h"
|
2021-10-26 00:03:59 +00:00
|
|
|
|
#include "content/public/browser/desktop_media_id.h"
|
|
|
|
|
#include "content/public/browser/desktop_streams_registry.h"
|
2018-04-12 07:30:51 +00:00
|
|
|
|
#include "content/public/browser/download_request_utils.h"
|
2015-04-20 06:50:04 +00:00
|
|
|
|
#include "content/public/browser/favicon_status.h"
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#include "content/public/browser/file_select_listener.h"
|
2024-07-29 17:42:57 +00:00
|
|
|
|
#include "content/public/browser/keyboard_event_processing_result.h"
|
2014-12-09 22:38:43 +00:00
|
|
|
|
#include "content/public/browser/navigation_details.h"
|
2015-03-05 14:39:27 +00:00
|
|
|
|
#include "content/public/browser/navigation_entry.h"
|
2016-07-14 00:19:28 +00:00
|
|
|
|
#include "content/public/browser/navigation_handle.h"
|
2014-07-28 07:29:51 +00:00
|
|
|
|
#include "content/public/browser/render_frame_host.h"
|
2018-03-16 07:28:06 +00:00
|
|
|
|
#include "content/public/browser/render_process_host.h"
|
|
|
|
|
#include "content/public/browser/render_view_host.h"
|
2016-03-08 14:28:53 +00:00
|
|
|
|
#include "content/public/browser/render_widget_host.h"
|
2015-09-18 06:20:31 +00:00
|
|
|
|
#include "content/public/browser/render_widget_host_view.h"
|
2015-04-30 13:15:19 +00:00
|
|
|
|
#include "content/public/browser/service_worker_context.h"
|
2014-10-24 12:20:56 +00:00
|
|
|
|
#include "content/public/browser/site_instance.h"
|
2016-08-26 22:30:02 +00:00
|
|
|
|
#include "content/public/browser/storage_partition.h"
|
2014-04-24 08:45:25 +00:00
|
|
|
|
#include "content/public/browser/web_contents.h"
|
2020-03-26 18:05:45 +00:00
|
|
|
|
#include "content/public/common/referrer_type_converters.h"
|
2022-09-07 07:46:37 +00:00
|
|
|
|
#include "content/public/common/result_codes.h"
|
2020-11-14 00:16:56 +00:00
|
|
|
|
#include "content/public/common/webplugininfo.h"
|
2019-07-24 23:01:08 +00:00
|
|
|
|
#include "electron/buildflags/buildflags.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "electron/shell/common/api/api.mojom.h"
|
2020-07-20 18:07:02 +00:00
|
|
|
|
#include "gin/arguments.h"
|
2020-03-12 01:07:54 +00:00
|
|
|
|
#include "gin/data_object_builder.h"
|
|
|
|
|
#include "gin/handle.h"
|
|
|
|
|
#include "gin/object_template_builder.h"
|
|
|
|
|
#include "gin/wrappable.h"
|
2023-04-06 08:23:34 +00:00
|
|
|
|
#include "media/base/mime_util.h"
|
2019-10-28 22:12:35 +00:00
|
|
|
|
#include "mojo/public/cpp/bindings/associated_remote.h"
|
2020-06-22 17:35:10 +00:00
|
|
|
|
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
|
|
|
|
#include "mojo/public/cpp/bindings/remote.h"
|
2019-04-02 22:38:16 +00:00
|
|
|
|
#include "mojo/public/cpp/system/platform_handle.h"
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#include "printing/buildflags/buildflags.h"
|
2021-10-05 22:30:31 +00:00
|
|
|
|
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
|
2021-02-09 20:16:21 +00:00
|
|
|
|
#include "services/service_manager/public/cpp/interface_provider.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/browser/api/electron_api_browser_window.h"
|
|
|
|
|
#include "shell/browser/api/electron_api_debugger.h"
|
|
|
|
|
#include "shell/browser/api/electron_api_session.h"
|
2020-10-09 16:50:46 +00:00
|
|
|
|
#include "shell/browser/api/electron_api_web_frame_main.h"
|
2024-07-29 17:42:57 +00:00
|
|
|
|
#include "shell/browser/api/frame_subscriber.h"
|
2020-03-12 01:07:54 +00:00
|
|
|
|
#include "shell/browser/api/message_port.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/browser/browser.h"
|
|
|
|
|
#include "shell/browser/child_web_contents_tracker.h"
|
2019-08-19 20:13:24 +00:00
|
|
|
|
#include "shell/browser/electron_autofill_driver_factory.h"
|
2020-02-03 22:01:10 +00:00
|
|
|
|
#include "shell/browser/electron_browser_context.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/browser/electron_browser_main_parts.h"
|
|
|
|
|
#include "shell/browser/electron_navigation_throttle.h"
|
2021-09-14 10:16:34 +00:00
|
|
|
|
#include "shell/browser/file_select_helper.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/browser/native_window.h"
|
2023-06-13 18:48:53 +00:00
|
|
|
|
#include "shell/browser/osr/osr_render_widget_host_view.h"
|
|
|
|
|
#include "shell/browser/osr/osr_web_contents_view.h"
|
2019-07-03 15:05:45 +00:00
|
|
|
|
#include "shell/browser/session_preferences.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/browser/ui/drag_util.h"
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#include "shell/browser/ui/file_dialog.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/browser/ui/inspectable_web_contents.h"
|
|
|
|
|
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
|
|
|
|
#include "shell/browser/web_contents_permission_helper.h"
|
|
|
|
|
#include "shell/browser/web_contents_preferences.h"
|
|
|
|
|
#include "shell/browser/web_contents_zoom_controller.h"
|
|
|
|
|
#include "shell/browser/web_view_guest_delegate.h"
|
2021-07-02 00:56:29 +00:00
|
|
|
|
#include "shell/browser/web_view_manager.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/common/api/electron_api_native_image.h"
|
2021-10-05 22:30:31 +00:00
|
|
|
|
#include "shell/common/api/electron_bindings.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/common/color_util.h"
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#include "shell/common/electron_constants.h"
|
2020-11-17 19:13:58 +00:00
|
|
|
|
#include "shell/common/gin_converters/base_converter.h"
|
2019-10-31 07:56:00 +00:00
|
|
|
|
#include "shell/common/gin_converters/blink_converter.h"
|
2019-10-21 07:05:40 +00:00
|
|
|
|
#include "shell/common/gin_converters/callback_converter.h"
|
2019-10-25 13:03:28 +00:00
|
|
|
|
#include "shell/common/gin_converters/content_converter.h"
|
|
|
|
|
#include "shell/common/gin_converters/file_path_converter.h"
|
2020-10-09 16:50:46 +00:00
|
|
|
|
#include "shell/common/gin_converters/frame_converter.h"
|
2019-10-21 07:05:40 +00:00
|
|
|
|
#include "shell/common/gin_converters/gfx_converter.h"
|
2019-10-25 13:03:28 +00:00
|
|
|
|
#include "shell/common/gin_converters/gurl_converter.h"
|
|
|
|
|
#include "shell/common/gin_converters/image_converter.h"
|
|
|
|
|
#include "shell/common/gin_converters/net_converter.h"
|
2023-02-28 19:08:22 +00:00
|
|
|
|
#include "shell/common/gin_converters/optional_converter.h"
|
2019-10-31 07:56:00 +00:00
|
|
|
|
#include "shell/common/gin_converters/value_converter.h"
|
2019-10-18 00:31:29 +00:00
|
|
|
|
#include "shell/common/gin_helper/dictionary.h"
|
2024-07-29 17:42:57 +00:00
|
|
|
|
#include "shell/common/gin_helper/error_thrower.h"
|
2019-10-25 13:03:28 +00:00
|
|
|
|
#include "shell/common/gin_helper/object_template_builder.h"
|
2024-07-29 17:42:57 +00:00
|
|
|
|
#include "shell/common/gin_helper/promise.h"
|
2020-05-04 17:49:29 +00:00
|
|
|
|
#include "shell/common/language_util.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/common/node_includes.h"
|
|
|
|
|
#include "shell/common/options_switches.h"
|
2021-01-13 09:01:51 +00:00
|
|
|
|
#include "shell/common/process_util.h"
|
2022-11-17 19:59:23 +00:00
|
|
|
|
#include "shell/common/thread_restrictions.h"
|
2020-03-12 01:07:54 +00:00
|
|
|
|
#include "shell/common/v8_value_serializer.h"
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#include "storage/browser/file_system/isolated_context.h"
|
2019-04-02 22:38:16 +00:00
|
|
|
|
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
|
2020-01-17 18:41:52 +00:00
|
|
|
|
#include "third_party/blink/public/common/input/web_input_event.h"
|
2020-03-12 01:07:54 +00:00
|
|
|
|
#include "third_party/blink/public/common/messaging/transferable_message_mojom_traits.h"
|
2019-10-18 19:57:34 +00:00
|
|
|
|
#include "third_party/blink/public/common/page/page_zoom.h"
|
2019-01-12 01:00:43 +00:00
|
|
|
|
#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
|
2019-10-28 22:12:35 +00:00
|
|
|
|
#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
|
2020-03-12 01:07:54 +00:00
|
|
|
|
#include "third_party/blink/public/mojom/messaging/transferable_message.mojom.h"
|
2020-05-04 17:49:29 +00:00
|
|
|
|
#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
|
2020-03-11 11:15:07 +00:00
|
|
|
|
#include "ui/base/cursor/cursor.h"
|
2020-05-26 20:06:26 +00:00
|
|
|
|
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
|
2016-07-21 12:03:38 +00:00
|
|
|
|
#include "ui/display/screen.h"
|
2017-04-13 10:21:30 +00:00
|
|
|
|
#include "ui/events/base_event_utils.h"
|
2014-04-24 08:45:25 +00:00
|
|
|
|
|
2024-07-25 09:25:45 +00:00
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
2019-08-30 14:39:46 +00:00
|
|
|
|
#include "ui/base/cocoa/defaults_utils.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if BUILDFLAG(IS_LINUX)
|
2022-07-20 11:03:34 +00:00
|
|
|
|
#include "ui/linux/linux_ui.h"
|
2016-08-15 21:13:24 +00:00
|
|
|
|
#endif
|
2014-10-23 06:04:13 +00:00
|
|
|
|
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
|
2024-07-25 09:25:45 +00:00
|
|
|
|
#include "ui/aura/window.h"
|
2018-02-22 08:56:48 +00:00
|
|
|
|
#include "ui/gfx/font_render_params.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-07-24 23:01:08 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
2020-03-05 14:56:21 +00:00
|
|
|
|
#include "extensions/browser/script_executor.h"
|
2020-09-08 11:55:40 +00:00
|
|
|
|
#include "extensions/browser/view_type_utils.h"
|
2021-03-05 23:41:32 +00:00
|
|
|
|
#include "extensions/common/mojom/view_type.mojom.h"
|
2020-02-03 22:01:10 +00:00
|
|
|
|
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
|
2019-07-24 23:01:08 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2020-08-15 01:51:28 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_PRINTING)
|
2022-06-28 14:34:00 +00:00
|
|
|
|
#include "chrome/browser/printing/print_view_manager_base.h"
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#include "components/printing/browser/print_manager_utils.h"
|
2022-10-20 18:30:40 +00:00
|
|
|
|
#include "components/printing/browser/print_to_pdf/pdf_print_result.h"
|
2022-05-31 06:21:25 +00:00
|
|
|
|
#include "components/printing/browser/print_to_pdf/pdf_print_utils.h"
|
2024-04-11 23:56:39 +00:00
|
|
|
|
#include "printing/mojom/print.mojom.h" // nogncheck
|
2022-05-31 06:21:25 +00:00
|
|
|
|
#include "printing/page_range.h"
|
2021-05-19 23:15:47 +00:00
|
|
|
|
#include "shell/browser/printing/print_view_manager_electron.h"
|
2024-04-11 23:56:39 +00:00
|
|
|
|
#include "shell/browser/printing/printing_utils.h"
|
2020-11-17 22:14:09 +00:00
|
|
|
|
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if BUILDFLAG(IS_WIN)
|
2020-11-17 22:14:09 +00:00
|
|
|
|
#include "printing/backend/win_helper.h"
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#endif
|
2022-09-15 17:29:10 +00:00
|
|
|
|
#endif // BUILDFLAG(ENABLE_PRINTING)
|
2020-11-10 17:06:56 +00:00
|
|
|
|
|
|
|
|
|
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
chore: bump chromium to 118.0.5975.0 (main) (#39531)
* chore: bump chromium in DEPS to 118.0.5951.0
* chore: update printing.patch
Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4727894
No logic changes, but patch needed to be manually re-applied due to upstream code shear
* chore: update port_autofill_colors_to_the_color_pipeline.patch
No manual changes; patch applied with fuzz
* chore: update patches
* chore: bump chromium in DEPS to 118.0.5953.0
* chore: update patches
* chore: bump chromium in DEPS to 118.0.5955.0
* chore: update patches
* chore: bump chromium in DEPS to 118.0.5957.0
* chore: update patches
* chore: include path of native_web_keyboard_event.h
Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4758689
* chore: remove reference to eextensions/browser/notification-types.h
Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4771627
* chore: update references to renamed upstream field NativeWebKeyboardEvent.skip_if_unhandled (formerly known as skip_in_browser
Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4758689
Need a second pair of eyes on this commit. In particular the reference in content_converter.cc, skipInBrowser, seems to not be set or documented anywhere? Is this unused/vestigal code?
* chore: sync signature of ElectronExtensionsBrowserClient::IsValidContext() to upstream change
Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4784198
* chore: add auto_pip_setting_helper.[cc,h] to chromium_src build
Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4688277
Exiting upstream code used by chromium_src now depends on this new upstream class
* chore: bump chromium in DEPS to 118.0.5959.0
* chore: update add_maximized_parameter_to_linuxui_getwindowframeprovider.patch
Xref: add_maximized_parameter_to_linuxui_getwindowframeprovider.patch
manually adjust patch to minor upstream chagnes
* chore: update patches
* chore: bump chromium in DEPS to 118.0.5961.0
* chore: bump chromium in DEPS to 118.0.5963.0
* chore: update patches
* 4780994: Rename various base files to "apple" since iOS uses them too
https://chromium-review.googlesource.com/c/chromium/src/+/4780994
* Many files moved from `mac` -> `apple`
This commit follows a handful of CLs that simply rename files/symbols to change `mac`
to `apple`
to signify their use across both macOS and iOS:
- 4784010: Move scoped_nsautorelease_pool to base/apple, leave a forwarding header
- 4790744: Move foundation_util to base/apple, leave a forwarding header
- 4790741: Move scoped_cftypreref to base/apple, leave a forwarding header
- 4787627: Move and rename macOS+iOS base/ files in PA to "apple"
- 4780399: Move OSStatus logging to base/apple
- 4787387: Remove forwarding headers
- 4781113: Rename message_pump_mac to "apple" because iOS uses it too
* fixup minor patch update error
A function param got dropped from this patch somewhere earlier
* chore: bump chromium in DEPS to 118.0.5965.2
* chore: update patches
* 4799213: Move ScopedTypeRef and ScopedCFTypeRef into base::apple::
https://chromium-review.googlesource.com/c/chromium/src/+/4799213
* Fix removed include to BrowserContext
In crrev.com/c/4767962 an include to BrowserContext was removed,
which was necessary for compilation. This broke only for us because
"chrome/browser/profiles/profile.h" includes that class, but we remove
all references to profiles.
* chore: bump chromium in DEPS to 118.0.5967.0
* chore: update patches
* chore: bump chromium in DEPS to 118.0.5969.0
* chore: update patches
* chore: bump chromium in DEPS to 118.0.5971.0
* chore: bump chromium in DEPS to 118.0.5973.0
* chore: update patches
* 4772121: [OOPIF PDF] Replace PDFWebContentsHelper with PDFDocumentHelper
https://chromium-review.googlesource.com/c/chromium/src/+/4772121
* 4811164: [Extensions] Do some cleanup in ChromeManagementAPIDelegate.
https://chromium-review.googlesource.com/c/chromium/src/+/4811164
* 4809488: Remove duplicate dnd functionality between Web and Renderer prefs
https://chromium-review.googlesource.com/c/chromium/src/+/4809488
Given that this is no longer an option of web preferences, we should
consider deprecating this option and then removing it.
* chore: bump chromium in DEPS to 118.0.5975.0
* chore: update patches
* fixup! chore: add auto_pip_settings_helper.{cc|h} to chromium_src build
* Reland "[windows] Remove RegKey::DeleteEmptyKey"
Refs https://chromium-review.googlesource.com/c/chromium/src/+/4813255
* Ensure StrCat means StrCat
Refs https://chromium-review.googlesource.com/c/chromium/src/+/1117180
* fixup! Remove RegKey::DeleteEmptyKey
* Consistently reject large p and large q in DH
Refs https://boringssl-review.googlesource.com/c/boringssl/+/62226
---------
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: clavin <clavin@electronjs.org>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
2023-09-01 06:54:59 +00:00
|
|
|
|
#include "components/pdf/browser/pdf_document_helper.h" // nogncheck
|
2020-08-15 01:51:28 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2021-07-08 07:18:11 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_PLUGINS)
|
|
|
|
|
#include "content/public/browser/plugin_service.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-11-14 20:46:52 +00:00
|
|
|
|
#if !IS_MAS_BUILD()
|
2020-11-16 17:47:09 +00:00
|
|
|
|
#include "chrome/browser/hang_monitor/hang_crash_dump.h" // nogncheck
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
namespace gin {
|
2015-05-29 03:12:55 +00:00
|
|
|
|
|
2018-11-09 03:42:34 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_PRINTING)
|
2019-06-30 05:12:00 +00:00
|
|
|
|
template <>
|
2020-08-15 01:51:28 +00:00
|
|
|
|
struct Converter<printing::mojom::MarginType> {
|
2019-06-30 05:12:00 +00:00
|
|
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
|
|
|
v8::Local<v8::Value> val,
|
2020-08-15 01:51:28 +00:00
|
|
|
|
printing::mojom::MarginType* out) {
|
2023-06-22 12:33:44 +00:00
|
|
|
|
using Val = printing::mojom::MarginType;
|
|
|
|
|
static constexpr auto Lookup =
|
2024-01-11 01:00:37 +00:00
|
|
|
|
base::MakeFixedFlatMap<std::string_view, Val>({
|
2023-06-22 12:33:44 +00:00
|
|
|
|
{"custom", Val::kCustomMargins},
|
|
|
|
|
{"default", Val::kDefaultMargins},
|
|
|
|
|
{"none", Val::kNoMargins},
|
|
|
|
|
{"printableArea", Val::kPrintableAreaMargins},
|
|
|
|
|
});
|
|
|
|
|
return FromV8WithLookup(isolate, val, Lookup, out);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <>
|
2020-05-26 20:06:26 +00:00
|
|
|
|
struct Converter<printing::mojom::DuplexMode> {
|
2019-06-30 05:12:00 +00:00
|
|
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
|
|
|
v8::Local<v8::Value> val,
|
2020-05-26 20:06:26 +00:00
|
|
|
|
printing::mojom::DuplexMode* out) {
|
2023-06-22 12:33:44 +00:00
|
|
|
|
using Val = printing::mojom::DuplexMode;
|
|
|
|
|
static constexpr auto Lookup =
|
2024-01-11 01:00:37 +00:00
|
|
|
|
base::MakeFixedFlatMap<std::string_view, Val>({
|
2023-06-22 12:33:44 +00:00
|
|
|
|
{"longEdge", Val::kLongEdge},
|
|
|
|
|
{"shortEdge", Val::kShortEdge},
|
|
|
|
|
{"simplex", Val::kSimplex},
|
|
|
|
|
});
|
|
|
|
|
return FromV8WithLookup(isolate, val, Lookup, out);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-09 03:42:34 +00:00
|
|
|
|
#endif
|
2017-02-06 09:18:04 +00:00
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
|
template <>
|
2015-06-23 08:34:22 +00:00
|
|
|
|
struct Converter<WindowOpenDisposition> {
|
|
|
|
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
|
|
|
|
WindowOpenDisposition val) {
|
|
|
|
|
std::string disposition = "other";
|
|
|
|
|
switch (val) {
|
2017-01-24 07:50:02 +00:00
|
|
|
|
case WindowOpenDisposition::CURRENT_TAB:
|
|
|
|
|
disposition = "default";
|
|
|
|
|
break;
|
|
|
|
|
case WindowOpenDisposition::NEW_FOREGROUND_TAB:
|
|
|
|
|
disposition = "foreground-tab";
|
|
|
|
|
break;
|
|
|
|
|
case WindowOpenDisposition::NEW_BACKGROUND_TAB:
|
|
|
|
|
disposition = "background-tab";
|
|
|
|
|
break;
|
|
|
|
|
case WindowOpenDisposition::NEW_POPUP:
|
|
|
|
|
case WindowOpenDisposition::NEW_WINDOW:
|
|
|
|
|
disposition = "new-window";
|
|
|
|
|
break;
|
|
|
|
|
case WindowOpenDisposition::SAVE_TO_DISK:
|
|
|
|
|
disposition = "save-to-disk";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2015-06-23 08:34:22 +00:00
|
|
|
|
}
|
2019-10-25 13:03:28 +00:00
|
|
|
|
return gin::ConvertToV8(isolate, disposition);
|
2015-06-23 08:34:22 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-12-06 01:36:23 +00:00
|
|
|
|
template <>
|
|
|
|
|
struct Converter<content::JavaScriptDialogType> {
|
|
|
|
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
|
|
|
|
content::JavaScriptDialogType val) {
|
|
|
|
|
switch (val) {
|
|
|
|
|
case content::JAVASCRIPT_DIALOG_TYPE_ALERT:
|
|
|
|
|
return gin::ConvertToV8(isolate, "alert");
|
|
|
|
|
case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM:
|
|
|
|
|
return gin::ConvertToV8(isolate, "confirm");
|
|
|
|
|
case content::JAVASCRIPT_DIALOG_TYPE_PROMPT:
|
|
|
|
|
return gin::ConvertToV8(isolate, "prompt");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
|
template <>
|
2015-10-14 04:41:31 +00:00
|
|
|
|
struct Converter<content::SavePageType> {
|
2018-04-18 01:55:30 +00:00
|
|
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
|
|
|
v8::Local<v8::Value> val,
|
2015-10-14 04:41:31 +00:00
|
|
|
|
content::SavePageType* out) {
|
2023-06-22 12:33:44 +00:00
|
|
|
|
using Val = content::SavePageType;
|
|
|
|
|
static constexpr auto Lookup =
|
2024-01-11 01:00:37 +00:00
|
|
|
|
base::MakeFixedFlatMap<std::string_view, Val>({
|
2023-06-22 12:33:44 +00:00
|
|
|
|
{"htmlcomplete", Val::SAVE_PAGE_TYPE_AS_COMPLETE_HTML},
|
|
|
|
|
{"htmlonly", Val::SAVE_PAGE_TYPE_AS_ONLY_HTML},
|
|
|
|
|
{"mhtml", Val::SAVE_PAGE_TYPE_AS_MHTML},
|
|
|
|
|
});
|
|
|
|
|
return FromV8WithLowerLookup(isolate, val, Lookup, out);
|
2015-10-14 04:41:31 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
|
template <>
|
2016-06-14 16:09:54 +00:00
|
|
|
|
struct Converter<electron::api::WebContents::Type> {
|
|
|
|
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
|
|
|
|
electron::api::WebContents::Type val) {
|
2016-06-14 17:05:25 +00:00
|
|
|
|
using Type = electron::api::WebContents::Type;
|
2019-09-13 14:26:59 +00:00
|
|
|
|
std::string type;
|
2016-06-14 16:09:54 +00:00
|
|
|
|
switch (val) {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
case Type::kBackgroundPage:
|
2018-04-18 01:55:30 +00:00
|
|
|
|
type = "backgroundPage";
|
|
|
|
|
break;
|
2020-10-27 17:51:45 +00:00
|
|
|
|
case Type::kBrowserWindow:
|
2018-04-18 01:55:30 +00:00
|
|
|
|
type = "window";
|
|
|
|
|
break;
|
2020-10-27 17:51:45 +00:00
|
|
|
|
case Type::kBrowserView:
|
2018-04-18 01:55:30 +00:00
|
|
|
|
type = "browserView";
|
|
|
|
|
break;
|
2020-10-27 17:51:45 +00:00
|
|
|
|
case Type::kRemote:
|
2018-04-18 01:55:30 +00:00
|
|
|
|
type = "remote";
|
|
|
|
|
break;
|
2020-10-27 17:51:45 +00:00
|
|
|
|
case Type::kWebView:
|
2018-04-18 01:55:30 +00:00
|
|
|
|
type = "webview";
|
|
|
|
|
break;
|
2020-10-27 17:51:45 +00:00
|
|
|
|
case Type::kOffScreen:
|
2018-04-18 01:55:30 +00:00
|
|
|
|
type = "offscreen";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2016-06-14 16:09:54 +00:00
|
|
|
|
}
|
2019-10-25 13:03:28 +00:00
|
|
|
|
return gin::ConvertToV8(isolate, type);
|
2016-06-14 16:09:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
|
|
|
v8::Local<v8::Value> val,
|
2016-06-14 16:23:03 +00:00
|
|
|
|
electron::api::WebContents::Type* out) {
|
2023-06-22 12:33:44 +00:00
|
|
|
|
using Val = electron::api::WebContents::Type;
|
|
|
|
|
static constexpr auto Lookup =
|
2024-01-11 01:00:37 +00:00
|
|
|
|
base::MakeFixedFlatMap<std::string_view, Val>({
|
2023-06-22 12:33:44 +00:00
|
|
|
|
{"backgroundPage", Val::kBackgroundPage},
|
|
|
|
|
{"browserView", Val::kBrowserView},
|
|
|
|
|
{"offscreen", Val::kOffScreen},
|
|
|
|
|
{"webview", Val::kWebView},
|
|
|
|
|
});
|
|
|
|
|
return FromV8WithLookup(isolate, val, Lookup, out);
|
2016-06-14 16:23:03 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
2016-06-14 16:09:54 +00:00
|
|
|
|
|
2019-10-02 12:38:27 +00:00
|
|
|
|
template <>
|
|
|
|
|
struct Converter<scoped_refptr<content::DevToolsAgentHost>> {
|
|
|
|
|
static v8::Local<v8::Value> ToV8(
|
|
|
|
|
v8::Isolate* isolate,
|
|
|
|
|
const scoped_refptr<content::DevToolsAgentHost>& val) {
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin_helper::Dictionary dict(isolate, v8::Object::New(isolate));
|
2019-10-02 12:38:27 +00:00
|
|
|
|
dict.Set("id", val->GetId());
|
|
|
|
|
dict.Set("url", val->GetURL().spec());
|
|
|
|
|
return dict.GetHandle();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-21 21:59:23 +00:00
|
|
|
|
template <>
|
|
|
|
|
struct Converter<content::NavigationEntry*> {
|
|
|
|
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
|
|
|
|
content::NavigationEntry* entry) {
|
|
|
|
|
if (!entry) {
|
|
|
|
|
return v8::Null(isolate);
|
|
|
|
|
}
|
|
|
|
|
gin_helper::Dictionary dict(isolate, v8::Object::New(isolate));
|
|
|
|
|
dict.Set("url", entry->GetURL().spec());
|
|
|
|
|
dict.Set("title", entry->GetTitleForDisplay());
|
|
|
|
|
return dict.GetHandle();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
} // namespace gin
|
2015-05-29 03:12:55 +00:00
|
|
|
|
|
2022-06-29 19:55:47 +00:00
|
|
|
|
namespace electron::api {
|
2014-04-24 08:45:25 +00:00
|
|
|
|
|
2014-10-23 05:31:10 +00:00
|
|
|
|
namespace {
|
|
|
|
|
|
2024-01-11 01:00:37 +00:00
|
|
|
|
constexpr std::string_view CursorTypeToString(
|
2023-06-12 07:55:22 +00:00
|
|
|
|
ui::mojom::CursorType cursor_type) {
|
|
|
|
|
switch (cursor_type) {
|
2023-05-08 07:50:30 +00:00
|
|
|
|
case ui::mojom::CursorType::kPointer:
|
2023-05-15 08:27:09 +00:00
|
|
|
|
return "pointer";
|
2023-05-08 07:50:30 +00:00
|
|
|
|
case ui::mojom::CursorType::kCross:
|
|
|
|
|
return "crosshair";
|
|
|
|
|
case ui::mojom::CursorType::kHand:
|
2023-05-15 08:27:09 +00:00
|
|
|
|
return "hand";
|
2023-05-08 07:50:30 +00:00
|
|
|
|
case ui::mojom::CursorType::kIBeam:
|
|
|
|
|
return "text";
|
|
|
|
|
case ui::mojom::CursorType::kWait:
|
|
|
|
|
return "wait";
|
|
|
|
|
case ui::mojom::CursorType::kHelp:
|
|
|
|
|
return "help";
|
|
|
|
|
case ui::mojom::CursorType::kEastResize:
|
|
|
|
|
return "e-resize";
|
|
|
|
|
case ui::mojom::CursorType::kNorthResize:
|
|
|
|
|
return "n-resize";
|
|
|
|
|
case ui::mojom::CursorType::kNorthEastResize:
|
|
|
|
|
return "ne-resize";
|
|
|
|
|
case ui::mojom::CursorType::kNorthWestResize:
|
|
|
|
|
return "nw-resize";
|
|
|
|
|
case ui::mojom::CursorType::kSouthResize:
|
|
|
|
|
return "s-resize";
|
|
|
|
|
case ui::mojom::CursorType::kSouthEastResize:
|
|
|
|
|
return "se-resize";
|
|
|
|
|
case ui::mojom::CursorType::kSouthWestResize:
|
|
|
|
|
return "sw-resize";
|
|
|
|
|
case ui::mojom::CursorType::kWestResize:
|
|
|
|
|
return "w-resize";
|
|
|
|
|
case ui::mojom::CursorType::kNorthSouthResize:
|
|
|
|
|
return "ns-resize";
|
|
|
|
|
case ui::mojom::CursorType::kEastWestResize:
|
|
|
|
|
return "ew-resize";
|
|
|
|
|
case ui::mojom::CursorType::kNorthEastSouthWestResize:
|
|
|
|
|
return "nesw-resize";
|
|
|
|
|
case ui::mojom::CursorType::kNorthWestSouthEastResize:
|
|
|
|
|
return "nwse-resize";
|
|
|
|
|
case ui::mojom::CursorType::kColumnResize:
|
|
|
|
|
return "col-resize";
|
|
|
|
|
case ui::mojom::CursorType::kRowResize:
|
|
|
|
|
return "row-resize";
|
|
|
|
|
case ui::mojom::CursorType::kMiddlePanning:
|
|
|
|
|
return "m-panning";
|
2023-05-15 08:27:09 +00:00
|
|
|
|
case ui::mojom::CursorType::kMiddlePanningVertical:
|
|
|
|
|
return "m-panning-vertical";
|
|
|
|
|
case ui::mojom::CursorType::kMiddlePanningHorizontal:
|
|
|
|
|
return "m-panning-horizontal";
|
2023-05-08 07:50:30 +00:00
|
|
|
|
case ui::mojom::CursorType::kEastPanning:
|
|
|
|
|
return "e-panning";
|
|
|
|
|
case ui::mojom::CursorType::kNorthPanning:
|
|
|
|
|
return "n-panning";
|
|
|
|
|
case ui::mojom::CursorType::kNorthEastPanning:
|
|
|
|
|
return "ne-panning";
|
|
|
|
|
case ui::mojom::CursorType::kNorthWestPanning:
|
|
|
|
|
return "nw-panning";
|
|
|
|
|
case ui::mojom::CursorType::kSouthPanning:
|
|
|
|
|
return "s-panning";
|
|
|
|
|
case ui::mojom::CursorType::kSouthEastPanning:
|
|
|
|
|
return "se-panning";
|
|
|
|
|
case ui::mojom::CursorType::kSouthWestPanning:
|
|
|
|
|
return "sw-panning";
|
|
|
|
|
case ui::mojom::CursorType::kWestPanning:
|
|
|
|
|
return "w-panning";
|
|
|
|
|
case ui::mojom::CursorType::kMove:
|
|
|
|
|
return "move";
|
|
|
|
|
case ui::mojom::CursorType::kVerticalText:
|
|
|
|
|
return "vertical-text";
|
|
|
|
|
case ui::mojom::CursorType::kCell:
|
|
|
|
|
return "cell";
|
|
|
|
|
case ui::mojom::CursorType::kContextMenu:
|
|
|
|
|
return "context-menu";
|
|
|
|
|
case ui::mojom::CursorType::kAlias:
|
|
|
|
|
return "alias";
|
|
|
|
|
case ui::mojom::CursorType::kProgress:
|
|
|
|
|
return "progress";
|
|
|
|
|
case ui::mojom::CursorType::kNoDrop:
|
|
|
|
|
return "nodrop";
|
|
|
|
|
case ui::mojom::CursorType::kCopy:
|
|
|
|
|
return "copy";
|
|
|
|
|
case ui::mojom::CursorType::kNone:
|
|
|
|
|
return "none";
|
|
|
|
|
case ui::mojom::CursorType::kNotAllowed:
|
|
|
|
|
return "not-allowed";
|
|
|
|
|
case ui::mojom::CursorType::kZoomIn:
|
|
|
|
|
return "zoom-in";
|
|
|
|
|
case ui::mojom::CursorType::kZoomOut:
|
|
|
|
|
return "zoom-out";
|
|
|
|
|
case ui::mojom::CursorType::kGrab:
|
|
|
|
|
return "grab";
|
|
|
|
|
case ui::mojom::CursorType::kGrabbing:
|
|
|
|
|
return "grabbing";
|
|
|
|
|
case ui::mojom::CursorType::kCustom:
|
|
|
|
|
return "custom";
|
2023-05-15 08:27:09 +00:00
|
|
|
|
case ui::mojom::CursorType::kNull:
|
|
|
|
|
return "null";
|
|
|
|
|
case ui::mojom::CursorType::kDndNone:
|
|
|
|
|
return "drag-drop-none";
|
|
|
|
|
case ui::mojom::CursorType::kDndMove:
|
|
|
|
|
return "drag-drop-move";
|
|
|
|
|
case ui::mojom::CursorType::kDndCopy:
|
|
|
|
|
return "drag-drop-copy";
|
|
|
|
|
case ui::mojom::CursorType::kDndLink:
|
|
|
|
|
return "drag-drop-link";
|
|
|
|
|
case ui::mojom::CursorType::kNorthSouthNoResize:
|
|
|
|
|
return "ns-no-resize";
|
|
|
|
|
case ui::mojom::CursorType::kEastWestNoResize:
|
|
|
|
|
return "ew-no-resize";
|
|
|
|
|
case ui::mojom::CursorType::kNorthEastSouthWestNoResize:
|
|
|
|
|
return "nesw-no-resize";
|
|
|
|
|
case ui::mojom::CursorType::kNorthWestSouthEastNoResize:
|
|
|
|
|
return "nwse-no-resize";
|
2023-05-08 07:50:30 +00:00
|
|
|
|
default:
|
|
|
|
|
return "default";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-30 16:17:57 +00:00
|
|
|
|
base::IDMap<WebContents*>& GetAllWebContents() {
|
|
|
|
|
static base::NoDestructor<base::IDMap<WebContents*>> s_all_web_contents;
|
|
|
|
|
return *s_all_web_contents;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-01 06:10:32 +00:00
|
|
|
|
void OnCapturePageDone(gin_helper::Promise<gfx::Image> promise,
|
2022-10-05 17:51:33 +00:00
|
|
|
|
base::ScopedClosureRunner capture_handle,
|
2019-08-23 00:03:28 +00:00
|
|
|
|
const SkBitmap& bitmap) {
|
2023-10-12 07:35:23 +00:00
|
|
|
|
auto ui_task_runner = content::GetUIThreadTaskRunner({});
|
|
|
|
|
if (!ui_task_runner->RunsTasksInCurrentSequence()) {
|
|
|
|
|
ui_task_runner->PostTask(
|
|
|
|
|
FROM_HERE, base::BindOnce(&OnCapturePageDone, std::move(promise),
|
|
|
|
|
std::move(capture_handle), bitmap));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-10 10:07:15 +00:00
|
|
|
|
// Hack to enable transparency in captured image
|
2019-11-01 06:10:32 +00:00
|
|
|
|
promise.Resolve(gfx::Image::CreateFrom1xBitmap(bitmap));
|
2022-10-05 17:51:33 +00:00
|
|
|
|
capture_handle.RunAndReset();
|
2016-07-06 16:32:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-01-10 22:23:35 +00:00
|
|
|
|
std::optional<base::TimeDelta> GetCursorBlinkInterval() {
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
2024-01-10 22:23:35 +00:00
|
|
|
|
std::optional<base::TimeDelta> system_value(
|
2022-02-25 18:17:35 +00:00
|
|
|
|
ui::TextInsertionCaretBlinkPeriodFromDefaults());
|
|
|
|
|
if (system_value)
|
|
|
|
|
return *system_value;
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#elif BUILDFLAG(IS_LINUX)
|
2022-07-20 11:03:34 +00:00
|
|
|
|
if (auto* linux_ui = ui::LinuxUi::instance())
|
2019-09-19 18:43:21 +00:00
|
|
|
|
return linux_ui->GetCursorBlinkInterval();
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#elif BUILDFLAG(IS_WIN)
|
2019-09-19 18:43:21 +00:00
|
|
|
|
const auto system_msec = ::GetCaretBlinkTime();
|
|
|
|
|
if (system_msec != 0) {
|
2021-11-24 08:45:59 +00:00
|
|
|
|
return (system_msec == INFINITE) ? base::TimeDelta()
|
|
|
|
|
: base::Milliseconds(system_msec);
|
2019-09-19 18:43:21 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
2024-01-10 22:23:35 +00:00
|
|
|
|
return std::nullopt;
|
2019-09-19 18:43:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-30 16:17:57 +00:00
|
|
|
|
struct UserDataLink : public base::SupportsUserData::Data {
|
|
|
|
|
explicit UserDataLink(base::WeakPtr<WebContents> contents)
|
|
|
|
|
: web_contents(contents) {}
|
|
|
|
|
|
|
|
|
|
base::WeakPtr<WebContents> web_contents;
|
|
|
|
|
};
|
|
|
|
|
const void* kElectronApiWebContentsKey = &kElectronApiWebContentsKey;
|
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
const char kRootName[] = "<root>";
|
|
|
|
|
|
|
|
|
|
struct FileSystem {
|
|
|
|
|
FileSystem() = default;
|
|
|
|
|
FileSystem(const std::string& type,
|
|
|
|
|
const std::string& file_system_name,
|
|
|
|
|
const std::string& root_url,
|
|
|
|
|
const std::string& file_system_path)
|
|
|
|
|
: type(type),
|
|
|
|
|
file_system_name(file_system_name),
|
|
|
|
|
root_url(root_url),
|
|
|
|
|
file_system_path(file_system_path) {}
|
|
|
|
|
|
|
|
|
|
std::string type;
|
|
|
|
|
std::string file_system_name;
|
|
|
|
|
std::string root_url;
|
|
|
|
|
std::string file_system_path;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::string RegisterFileSystem(content::WebContents* web_contents,
|
|
|
|
|
const base::FilePath& path) {
|
|
|
|
|
auto* isolated_context = storage::IsolatedContext::GetInstance();
|
|
|
|
|
std::string root_name(kRootName);
|
|
|
|
|
storage::IsolatedContext::ScopedFSHandle file_system =
|
|
|
|
|
isolated_context->RegisterFileSystemForPath(
|
2021-03-04 17:27:05 +00:00
|
|
|
|
storage::kFileSystemTypeLocal, std::string(), path, &root_name);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
|
|
|
|
|
content::ChildProcessSecurityPolicy* policy =
|
|
|
|
|
content::ChildProcessSecurityPolicy::GetInstance();
|
|
|
|
|
content::RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
|
|
|
|
|
int renderer_id = render_view_host->GetProcess()->GetID();
|
|
|
|
|
policy->GrantReadFileSystem(renderer_id, file_system.id());
|
|
|
|
|
policy->GrantWriteFileSystem(renderer_id, file_system.id());
|
|
|
|
|
policy->GrantCreateFileForFileSystem(renderer_id, file_system.id());
|
|
|
|
|
policy->GrantDeleteFromFileSystem(renderer_id, file_system.id());
|
|
|
|
|
|
|
|
|
|
if (!policy->CanReadFile(renderer_id, path))
|
|
|
|
|
policy->GrantReadFile(renderer_id, path);
|
|
|
|
|
|
|
|
|
|
return file_system.id();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileSystem CreateFileSystemStruct(content::WebContents* web_contents,
|
|
|
|
|
const std::string& file_system_id,
|
|
|
|
|
const std::string& file_system_path,
|
|
|
|
|
const std::string& type) {
|
2021-11-24 08:45:59 +00:00
|
|
|
|
const GURL origin = web_contents->GetURL().DeprecatedGetOriginAsURL();
|
2020-11-10 17:06:56 +00:00
|
|
|
|
std::string file_system_name =
|
|
|
|
|
storage::GetIsolatedFileSystemName(origin, file_system_id);
|
|
|
|
|
std::string root_url = storage::GetIsolatedFileSystemRootURIString(
|
|
|
|
|
origin, file_system_id, kRootName);
|
|
|
|
|
return FileSystem(type, file_system_name, root_url, file_system_path);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-29 16:39:48 +00:00
|
|
|
|
base::Value::Dict CreateFileSystemValue(const FileSystem& file_system) {
|
|
|
|
|
base::Value::Dict value;
|
|
|
|
|
value.Set("type", file_system.type);
|
|
|
|
|
value.Set("fileSystemName", file_system.file_system_name);
|
|
|
|
|
value.Set("rootURL", file_system.root_url);
|
|
|
|
|
value.Set("fileSystemPath", file_system.file_system_path);
|
|
|
|
|
return value;
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-07 21:18:35 +00:00
|
|
|
|
void WriteToFile(const base::FilePath& path,
|
|
|
|
|
const std::string& content,
|
|
|
|
|
bool is_base64) {
|
2020-11-10 17:06:56 +00:00
|
|
|
|
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
|
|
|
|
|
base::BlockingType::WILL_BLOCK);
|
|
|
|
|
DCHECK(!path.empty());
|
|
|
|
|
|
2024-06-07 21:18:35 +00:00
|
|
|
|
if (!is_base64) {
|
|
|
|
|
base::WriteFile(path, content);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::optional<std::vector<uint8_t>> decoded_content =
|
|
|
|
|
base::Base64Decode(content);
|
|
|
|
|
if (decoded_content) {
|
|
|
|
|
base::WriteFile(path, decoded_content.value());
|
|
|
|
|
} else {
|
|
|
|
|
LOG(ERROR) << "Invalid base64. Not writing " << path;
|
|
|
|
|
}
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AppendToFile(const base::FilePath& path, const std::string& content) {
|
|
|
|
|
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
|
|
|
|
|
base::BlockingType::WILL_BLOCK);
|
|
|
|
|
DCHECK(!path.empty());
|
|
|
|
|
|
2021-05-19 23:15:47 +00:00
|
|
|
|
base::AppendToFile(path, content);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PrefService* GetPrefService(content::WebContents* web_contents) {
|
|
|
|
|
auto* context = web_contents->GetBrowserContext();
|
|
|
|
|
return static_cast<electron::ElectronBrowserContext*>(context)->prefs();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::map<std::string, std::string> GetAddedFileSystemPaths(
|
|
|
|
|
content::WebContents* web_contents) {
|
|
|
|
|
auto* pref_service = GetPrefService(web_contents);
|
2022-10-03 20:21:00 +00:00
|
|
|
|
const base::Value::Dict& file_system_paths =
|
|
|
|
|
pref_service->GetDict(prefs::kDevToolsFileSystemPaths);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
std::map<std::string, std::string> result;
|
2022-10-03 20:21:00 +00:00
|
|
|
|
for (auto it : file_system_paths) {
|
|
|
|
|
std::string type =
|
|
|
|
|
it.second.is_string() ? it.second.GetString() : std::string();
|
|
|
|
|
result[it.first] = type;
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsDevToolsFileSystemAdded(content::WebContents* web_contents,
|
|
|
|
|
const std::string& file_system_path) {
|
2023-05-30 08:28:43 +00:00
|
|
|
|
return base::Contains(GetAddedFileSystemPaths(web_contents),
|
|
|
|
|
file_system_path);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-28 14:55:41 +00:00
|
|
|
|
content::RenderFrameHost* GetRenderFrameHost(
|
|
|
|
|
content::NavigationHandle* navigation_handle) {
|
|
|
|
|
int frame_tree_node_id = navigation_handle->GetFrameTreeNodeId();
|
|
|
|
|
content::FrameTreeNode* frame_tree_node =
|
|
|
|
|
content::FrameTreeNode::GloballyFindByID(frame_tree_node_id);
|
|
|
|
|
content::RenderFrameHostManager* render_manager =
|
|
|
|
|
frame_tree_node->render_manager();
|
|
|
|
|
content::RenderFrameHost* frame_host = nullptr;
|
|
|
|
|
if (render_manager) {
|
|
|
|
|
frame_host = render_manager->speculative_frame_host();
|
|
|
|
|
if (!frame_host)
|
|
|
|
|
frame_host = render_manager->current_frame_host();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return frame_host;
|
|
|
|
|
}
|
2014-10-23 05:31:10 +00:00
|
|
|
|
} // namespace
|
|
|
|
|
|
2020-09-08 11:55:40 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
|
|
|
|
|
2021-03-05 00:23:10 +00:00
|
|
|
|
WebContents::Type GetTypeFromViewType(extensions::mojom::ViewType view_type) {
|
2020-09-08 11:55:40 +00:00
|
|
|
|
switch (view_type) {
|
2021-03-05 23:41:32 +00:00
|
|
|
|
case extensions::mojom::ViewType::kExtensionBackgroundPage:
|
2020-10-27 17:51:45 +00:00
|
|
|
|
return WebContents::Type::kBackgroundPage;
|
2020-09-08 11:55:40 +00:00
|
|
|
|
|
2021-03-05 23:41:32 +00:00
|
|
|
|
case extensions::mojom::ViewType::kAppWindow:
|
|
|
|
|
case extensions::mojom::ViewType::kComponent:
|
|
|
|
|
case extensions::mojom::ViewType::kExtensionPopup:
|
|
|
|
|
case extensions::mojom::ViewType::kBackgroundContents:
|
|
|
|
|
case extensions::mojom::ViewType::kExtensionGuest:
|
|
|
|
|
case extensions::mojom::ViewType::kTabContents:
|
2022-07-13 21:26:16 +00:00
|
|
|
|
case extensions::mojom::ViewType::kOffscreenDocument:
|
2023-01-06 02:35:34 +00:00
|
|
|
|
case extensions::mojom::ViewType::kExtensionSidePanel:
|
2021-03-05 23:41:32 +00:00
|
|
|
|
case extensions::mojom::ViewType::kInvalid:
|
2020-10-27 17:51:45 +00:00
|
|
|
|
return WebContents::Type::kRemote;
|
2020-09-08 11:55:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-10-19 08:52:07 +00:00
|
|
|
|
WebContents::WebContents(v8::Isolate* isolate,
|
|
|
|
|
content::WebContents* web_contents)
|
2019-06-14 02:44:36 +00:00
|
|
|
|
: content::WebContentsObserver(web_contents),
|
2020-10-27 17:51:45 +00:00
|
|
|
|
type_(Type::kRemote),
|
2023-06-09 20:28:11 +00:00
|
|
|
|
id_(GetAllWebContents().Add(this))
|
2021-01-25 16:27:25 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_PRINTING)
|
2021-01-26 18:16:21 +00:00
|
|
|
|
,
|
|
|
|
|
print_task_runner_(CreatePrinterHandlerTaskRunner())
|
2021-01-25 16:27:25 +00:00
|
|
|
|
#endif
|
2021-01-26 18:16:21 +00:00
|
|
|
|
{
|
2020-09-08 11:55:40 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
|
|
|
|
// WebContents created by extension host will have valid ViewType set.
|
2021-03-05 00:23:10 +00:00
|
|
|
|
extensions::mojom::ViewType view_type = extensions::GetViewType(web_contents);
|
2021-03-05 23:41:32 +00:00
|
|
|
|
if (view_type != extensions::mojom::ViewType::kInvalid) {
|
2020-09-08 11:55:40 +00:00
|
|
|
|
InitWithExtensionView(isolate, web_contents, view_type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extensions::ElectronExtensionWebContentsObserver::CreateForWebContents(
|
|
|
|
|
web_contents);
|
2021-06-08 02:00:05 +00:00
|
|
|
|
script_executor_ = std::make_unique<extensions::ScriptExecutor>(web_contents);
|
2020-09-08 11:55:40 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2020-06-11 03:57:51 +00:00
|
|
|
|
auto session = Session::CreateFrom(isolate, GetBrowserContext());
|
|
|
|
|
session_.Reset(isolate, session.ToV8());
|
|
|
|
|
|
2022-07-29 15:09:47 +00:00
|
|
|
|
SetUserAgent(GetBrowserContext()->GetUserAgent());
|
|
|
|
|
|
2020-07-30 16:17:57 +00:00
|
|
|
|
web_contents->SetUserData(kElectronApiWebContentsKey,
|
|
|
|
|
std::make_unique<UserDataLink>(GetWeakPtr()));
|
2019-10-25 13:03:28 +00:00
|
|
|
|
InitZoomController(web_contents, gin::Dictionary::CreateEmpty(isolate));
|
2018-10-19 08:52:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-25 01:17:54 +00:00
|
|
|
|
WebContents::WebContents(v8::Isolate* isolate,
|
2018-10-22 18:02:25 +00:00
|
|
|
|
std::unique_ptr<content::WebContents> web_contents,
|
2016-08-17 00:15:10 +00:00
|
|
|
|
Type type)
|
2019-06-14 02:44:36 +00:00
|
|
|
|
: content::WebContentsObserver(web_contents.get()),
|
|
|
|
|
type_(type),
|
2023-06-09 20:28:11 +00:00
|
|
|
|
id_(GetAllWebContents().Add(this))
|
2021-01-25 16:27:25 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_PRINTING)
|
2021-01-26 18:16:21 +00:00
|
|
|
|
,
|
|
|
|
|
print_task_runner_(CreatePrinterHandlerTaskRunner())
|
2021-01-25 16:27:25 +00:00
|
|
|
|
#endif
|
2021-01-26 18:16:21 +00:00
|
|
|
|
{
|
2020-10-27 17:51:45 +00:00
|
|
|
|
DCHECK(type != Type::kRemote)
|
2019-05-03 18:11:41 +00:00
|
|
|
|
<< "Can't take ownership of a remote WebContents";
|
2018-10-19 08:52:07 +00:00
|
|
|
|
auto session = Session::CreateFrom(isolate, GetBrowserContext());
|
|
|
|
|
session_.Reset(isolate, session.ToV8());
|
2018-10-22 18:02:25 +00:00
|
|
|
|
InitWithSessionAndOptions(isolate, std::move(web_contents), session,
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin::Dictionary::CreateEmpty(isolate));
|
2014-10-23 06:04:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
WebContents::WebContents(v8::Isolate* isolate,
|
|
|
|
|
const gin_helper::Dictionary& options)
|
2023-06-09 20:28:11 +00:00
|
|
|
|
: id_(GetAllWebContents().Add(this))
|
2021-01-25 16:27:25 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_PRINTING)
|
2021-01-26 18:16:21 +00:00
|
|
|
|
,
|
|
|
|
|
print_task_runner_(CreatePrinterHandlerTaskRunner())
|
2021-01-25 16:27:25 +00:00
|
|
|
|
#endif
|
2021-01-26 18:16:21 +00:00
|
|
|
|
{
|
2016-04-08 06:54:33 +00:00
|
|
|
|
// Read options.
|
|
|
|
|
options.Get("backgroundThrottling", &background_throttling_);
|
|
|
|
|
|
2019-05-20 10:55:46 +00:00
|
|
|
|
// Get type
|
|
|
|
|
options.Get("type", &type_);
|
|
|
|
|
|
2024-01-05 04:00:27 +00:00
|
|
|
|
// Get transparent for guest view
|
|
|
|
|
options.Get("transparent", &guest_transparent_);
|
|
|
|
|
|
2019-07-31 12:34:04 +00:00
|
|
|
|
bool b = false;
|
2019-05-20 10:55:46 +00:00
|
|
|
|
if (options.Get(options::kOffscreen, &b) && b)
|
2020-10-27 17:51:45 +00:00
|
|
|
|
type_ = Type::kOffScreen;
|
2015-06-24 15:29:32 +00:00
|
|
|
|
|
2017-03-04 02:09:16 +00:00
|
|
|
|
// Init embedder earlier
|
|
|
|
|
options.Get("embedder", &embedder_);
|
|
|
|
|
|
2016-09-07 02:16:52 +00:00
|
|
|
|
// Whether to enable DevTools.
|
|
|
|
|
options.Get("devTools", &enable_devtools_);
|
2016-09-05 08:27:56 +00:00
|
|
|
|
|
2023-12-13 21:01:03 +00:00
|
|
|
|
bool initially_shown = true;
|
2021-05-19 09:27:35 +00:00
|
|
|
|
options.Get(options::kShow, &initially_shown);
|
2019-09-05 17:56:06 +00:00
|
|
|
|
|
2015-09-05 14:39:48 +00:00
|
|
|
|
// Obtain the session.
|
|
|
|
|
std::string partition;
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin::Handle<api::Session> session;
|
2018-02-12 19:46:29 +00:00
|
|
|
|
if (options.Get("session", &session) && !session.IsEmpty()) {
|
2016-07-12 12:01:49 +00:00
|
|
|
|
} else if (options.Get("partition", &partition)) {
|
|
|
|
|
session = Session::FromPartition(isolate, partition);
|
2015-09-05 14:39:48 +00:00
|
|
|
|
} else {
|
|
|
|
|
// Use the default session if not specified.
|
2016-07-12 12:01:49 +00:00
|
|
|
|
session = Session::FromPartition(isolate, "");
|
2015-09-05 14:39:48 +00:00
|
|
|
|
}
|
|
|
|
|
session_.Reset(isolate, session.ToV8());
|
|
|
|
|
|
2018-09-15 00:16:22 +00:00
|
|
|
|
std::unique_ptr<content::WebContents> web_contents;
|
2024-02-09 09:29:14 +00:00
|
|
|
|
if (is_guest()) {
|
2016-05-23 03:28:59 +00:00
|
|
|
|
scoped_refptr<content::SiteInstance> site_instance =
|
2018-04-18 01:55:30 +00:00
|
|
|
|
content::SiteInstance::CreateForURL(session->browser_context(),
|
|
|
|
|
GURL("chrome-guest://fake-host"));
|
|
|
|
|
content::WebContents::CreateParams params(session->browser_context(),
|
|
|
|
|
site_instance);
|
2019-09-16 22:12:00 +00:00
|
|
|
|
guest_delegate_ =
|
|
|
|
|
std::make_unique<WebViewGuestDelegate>(embedder_->web_contents(), this);
|
2015-06-25 06:28:13 +00:00
|
|
|
|
params.guest_delegate = guest_delegate_.get();
|
2017-03-05 15:18:57 +00:00
|
|
|
|
|
2017-03-04 02:09:16 +00:00
|
|
|
|
if (embedder_ && embedder_->IsOffScreen()) {
|
2018-04-18 01:55:30 +00:00
|
|
|
|
auto* view = new OffScreenWebContentsView(
|
2019-05-03 19:08:41 +00:00
|
|
|
|
false,
|
|
|
|
|
base::BindRepeating(&WebContents::OnPaint, base::Unretained(this)));
|
2017-03-04 02:09:16 +00:00
|
|
|
|
params.view = view;
|
|
|
|
|
params.delegate_view = view;
|
2017-03-05 15:18:57 +00:00
|
|
|
|
|
2017-03-04 02:09:16 +00:00
|
|
|
|
web_contents = content::WebContents::Create(params);
|
2018-10-05 18:03:35 +00:00
|
|
|
|
view->SetWebContents(web_contents.get());
|
2017-03-04 02:09:16 +00:00
|
|
|
|
} else {
|
|
|
|
|
web_contents = content::WebContents::Create(params);
|
|
|
|
|
}
|
2016-07-31 10:19:56 +00:00
|
|
|
|
} else if (IsOffScreen()) {
|
2022-02-23 10:33:42 +00:00
|
|
|
|
// webPreferences does not have a transparent option, so if the window needs
|
|
|
|
|
// to be transparent, that will be set at electron_api_browser_window.cc#L57
|
|
|
|
|
// and we then need to pull it back out and check it here.
|
|
|
|
|
std::string background_color;
|
|
|
|
|
options.GetHidden(options::kBackgroundColor, &background_color);
|
2022-03-21 17:35:54 +00:00
|
|
|
|
bool transparent = ParseCSSColor(background_color) == SK_ColorTRANSPARENT;
|
2016-08-01 11:27:39 +00:00
|
|
|
|
|
2016-07-29 12:50:27 +00:00
|
|
|
|
content::WebContents::CreateParams params(session->browser_context());
|
2018-04-18 01:55:30 +00:00
|
|
|
|
auto* view = new OffScreenWebContentsView(
|
2019-05-03 19:08:41 +00:00
|
|
|
|
transparent,
|
|
|
|
|
base::BindRepeating(&WebContents::OnPaint, base::Unretained(this)));
|
2016-08-03 04:04:36 +00:00
|
|
|
|
params.view = view;
|
|
|
|
|
params.delegate_view = view;
|
2016-07-25 13:55:00 +00:00
|
|
|
|
|
2015-06-24 15:29:32 +00:00
|
|
|
|
web_contents = content::WebContents::Create(params);
|
2018-10-05 18:03:35 +00:00
|
|
|
|
view->SetWebContents(web_contents.get());
|
2016-07-29 12:50:27 +00:00
|
|
|
|
} else {
|
|
|
|
|
content::WebContents::CreateParams params(session->browser_context());
|
2021-05-19 09:27:35 +00:00
|
|
|
|
params.initially_hidden = !initially_shown;
|
2016-07-27 23:58:23 +00:00
|
|
|
|
web_contents = content::WebContents::Create(params);
|
2015-06-24 14:14:46 +00:00
|
|
|
|
}
|
2015-06-09 07:50:20 +00:00
|
|
|
|
|
2018-10-22 18:02:25 +00:00
|
|
|
|
InitWithSessionAndOptions(isolate, std::move(web_contents), session, options);
|
2016-08-17 00:15:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-21 20:21:24 +00:00
|
|
|
|
void WebContents::InitZoomController(content::WebContents* web_contents,
|
2019-10-25 13:03:28 +00:00
|
|
|
|
const gin_helper::Dictionary& options) {
|
2017-10-21 20:21:24 +00:00
|
|
|
|
WebContentsZoomController::CreateForWebContents(web_contents);
|
|
|
|
|
zoom_controller_ = WebContentsZoomController::FromWebContents(web_contents);
|
|
|
|
|
double zoom_factor;
|
|
|
|
|
if (options.Get(options::kZoomFactor, &zoom_factor))
|
|
|
|
|
zoom_controller_->SetDefaultZoomFactor(zoom_factor);
|
2022-09-27 19:47:46 +00:00
|
|
|
|
|
|
|
|
|
// Nothing to do with ZoomController, but this function gets called in all
|
|
|
|
|
// init cases!
|
|
|
|
|
content::RenderViewHost* host = web_contents->GetRenderViewHost();
|
|
|
|
|
if (host)
|
|
|
|
|
host->GetWidget()->AddInputEventObserver(this);
|
2017-10-21 20:21:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-22 18:02:25 +00:00
|
|
|
|
void WebContents::InitWithSessionAndOptions(
|
|
|
|
|
v8::Isolate* isolate,
|
|
|
|
|
std::unique_ptr<content::WebContents> owned_web_contents,
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin::Handle<api::Session> session,
|
|
|
|
|
const gin_helper::Dictionary& options) {
|
2018-10-22 18:02:25 +00:00
|
|
|
|
Observe(owned_web_contents.get());
|
2021-09-20 00:34:11 +00:00
|
|
|
|
InitWithWebContents(std::move(owned_web_contents), session->browser_context(),
|
2024-02-09 09:29:14 +00:00
|
|
|
|
is_guest());
|
2015-06-05 07:01:51 +00:00
|
|
|
|
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->GetView()->SetDelegate(this);
|
2015-10-01 03:14:19 +00:00
|
|
|
|
|
2018-10-22 18:02:25 +00:00
|
|
|
|
auto* prefs = web_contents()->GetMutableRendererPrefs();
|
2020-05-04 17:49:29 +00:00
|
|
|
|
|
|
|
|
|
// Collect preferred languages from OS and browser process. accept_languages
|
|
|
|
|
// effects HTTP header, navigator.languages, and CJK fallback font selection.
|
|
|
|
|
//
|
|
|
|
|
// Note that an application locale set to the browser process might be
|
|
|
|
|
// different with the one set to the preference list.
|
|
|
|
|
// (e.g. overridden with --lang)
|
|
|
|
|
std::string accept_languages =
|
|
|
|
|
g_browser_process->GetApplicationLocale() + ",";
|
|
|
|
|
for (auto const& language : electron::GetPreferredLanguages()) {
|
|
|
|
|
if (language == g_browser_process->GetApplicationLocale())
|
|
|
|
|
continue;
|
|
|
|
|
accept_languages += language + ",";
|
|
|
|
|
}
|
|
|
|
|
accept_languages.pop_back();
|
|
|
|
|
prefs->accept_languages = accept_languages;
|
2018-04-02 03:47:00 +00:00
|
|
|
|
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
|
2018-02-22 08:56:48 +00:00
|
|
|
|
// Update font settings.
|
2021-07-06 12:17:13 +00:00
|
|
|
|
static const gfx::FontRenderParams params(
|
2019-01-10 16:28:15 +00:00
|
|
|
|
gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr));
|
2021-07-06 12:17:13 +00:00
|
|
|
|
prefs->should_antialias_text = params.antialiasing;
|
|
|
|
|
prefs->use_subpixel_positioning = params.subpixel_positioning;
|
|
|
|
|
prefs->hinting = params.hinting;
|
|
|
|
|
prefs->use_autohinter = params.autohinter;
|
|
|
|
|
prefs->use_bitmaps = params.use_bitmaps;
|
|
|
|
|
prefs->subpixel_rendering = params.subpixel_rendering;
|
2018-02-22 08:56:48 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2019-09-19 18:43:21 +00:00
|
|
|
|
// Honor the system's cursor blink rate settings
|
|
|
|
|
if (auto interval = GetCursorBlinkInterval())
|
|
|
|
|
prefs->caret_blink_interval = *interval;
|
2019-08-30 14:39:46 +00:00
|
|
|
|
|
2015-09-22 13:56:56 +00:00
|
|
|
|
// Save the preferences in C++.
|
2020-11-10 17:06:03 +00:00
|
|
|
|
// If there's already a WebContentsPreferences object, we created it as part
|
|
|
|
|
// of the webContents.setWindowOpenHandler path, so don't overwrite it.
|
|
|
|
|
if (!WebContentsPreferences::From(web_contents())) {
|
|
|
|
|
new WebContentsPreferences(web_contents(), options);
|
|
|
|
|
}
|
2020-08-12 18:33:58 +00:00
|
|
|
|
// Trigger re-calculation of webkit prefs.
|
|
|
|
|
web_contents()->NotifyPreferencesChanged();
|
2015-09-04 16:44:22 +00:00
|
|
|
|
|
2018-10-22 18:02:25 +00:00
|
|
|
|
WebContentsPermissionHelper::CreateForWebContents(web_contents());
|
|
|
|
|
InitZoomController(web_contents(), options);
|
2019-07-24 23:01:08 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
2020-02-03 22:01:10 +00:00
|
|
|
|
extensions::ElectronExtensionWebContentsObserver::CreateForWebContents(
|
2019-07-24 23:01:08 +00:00
|
|
|
|
web_contents());
|
2021-06-08 02:00:05 +00:00
|
|
|
|
script_executor_ =
|
|
|
|
|
std::make_unique<extensions::ScriptExecutor>(web_contents());
|
2019-07-24 23:01:08 +00:00
|
|
|
|
#endif
|
2016-01-23 13:29:47 +00:00
|
|
|
|
|
2019-08-19 20:13:24 +00:00
|
|
|
|
AutofillDriverFactory::CreateForWebContents(web_contents());
|
2019-04-02 22:38:16 +00:00
|
|
|
|
|
2022-07-29 15:09:47 +00:00
|
|
|
|
SetUserAgent(GetBrowserContext()->GetUserAgent());
|
2015-07-14 19:13:25 +00:00
|
|
|
|
|
2024-02-09 09:29:14 +00:00
|
|
|
|
if (is_guest()) {
|
2015-06-24 15:29:32 +00:00
|
|
|
|
NativeWindow* owner_window = nullptr;
|
2017-03-04 02:09:16 +00:00
|
|
|
|
if (embedder_) {
|
2015-06-24 15:29:32 +00:00
|
|
|
|
// New WebContents's owner_window is the embedder's owner_window.
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* relay =
|
2016-02-17 08:52:19 +00:00
|
|
|
|
NativeWindowRelay::FromWebContents(embedder_->web_contents());
|
2015-06-24 15:29:32 +00:00
|
|
|
|
if (relay)
|
2018-10-02 22:14:43 +00:00
|
|
|
|
owner_window = relay->GetNativeWindow();
|
2015-06-24 15:29:32 +00:00
|
|
|
|
}
|
|
|
|
|
if (owner_window)
|
|
|
|
|
SetOwnerWindow(owner_window);
|
|
|
|
|
}
|
2016-04-25 01:17:54 +00:00
|
|
|
|
|
2020-07-30 16:17:57 +00:00
|
|
|
|
web_contents()->SetUserData(kElectronApiWebContentsKey,
|
|
|
|
|
std::make_unique<UserDataLink>(GetWeakPtr()));
|
2014-10-23 06:04:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-08 11:55:40 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
|
|
|
|
void WebContents::InitWithExtensionView(v8::Isolate* isolate,
|
|
|
|
|
content::WebContents* web_contents,
|
2021-03-05 00:23:10 +00:00
|
|
|
|
extensions::mojom::ViewType view_type) {
|
2020-09-08 11:55:40 +00:00
|
|
|
|
// Must reassign type prior to calling `Init`.
|
|
|
|
|
type_ = GetTypeFromViewType(view_type);
|
2021-07-26 16:02:16 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2020-09-08 11:55:40 +00:00
|
|
|
|
return;
|
2021-07-26 16:02:16 +00:00
|
|
|
|
if (type_ == Type::kBackgroundPage)
|
|
|
|
|
// non-background-page WebContents are retained by other classes. We need
|
|
|
|
|
// to pin here to prevent background-page WebContents from being GC'd.
|
|
|
|
|
// The background page api::WebContents will live until the underlying
|
|
|
|
|
// content::WebContents is destroyed.
|
|
|
|
|
Pin(isolate);
|
2020-09-08 11:55:40 +00:00
|
|
|
|
|
|
|
|
|
// Allow toggling DevTools for background pages
|
|
|
|
|
Observe(web_contents);
|
2021-09-20 00:34:11 +00:00
|
|
|
|
InitWithWebContents(std::unique_ptr<content::WebContents>(web_contents),
|
2024-02-09 09:29:14 +00:00
|
|
|
|
GetBrowserContext(), is_guest());
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->GetView()->SetDelegate(this);
|
2020-09-08 11:55:40 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2021-09-20 00:34:11 +00:00
|
|
|
|
void WebContents::InitWithWebContents(
|
|
|
|
|
std::unique_ptr<content::WebContents> web_contents,
|
|
|
|
|
ElectronBrowserContext* browser_context,
|
|
|
|
|
bool is_guest) {
|
2020-11-10 17:06:56 +00:00
|
|
|
|
browser_context_ = browser_context;
|
|
|
|
|
web_contents->SetDelegate(this);
|
|
|
|
|
|
|
|
|
|
#if BUILDFLAG(ENABLE_PRINTING)
|
2021-09-20 00:34:11 +00:00
|
|
|
|
PrintViewManagerElectron::CreateForWebContents(web_contents.get());
|
2020-11-10 17:06:56 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Determine whether the WebContents is offscreen.
|
2021-09-20 00:34:11 +00:00
|
|
|
|
auto* web_preferences = WebContentsPreferences::From(web_contents.get());
|
2021-07-26 16:04:09 +00:00
|
|
|
|
offscreen_ = web_preferences && web_preferences->IsOffscreen();
|
2020-11-10 17:06:56 +00:00
|
|
|
|
|
|
|
|
|
// Create InspectableWebContents.
|
2021-06-08 02:00:05 +00:00
|
|
|
|
inspectable_web_contents_ = std::make_unique<InspectableWebContents>(
|
2021-09-20 00:34:11 +00:00
|
|
|
|
std::move(web_contents), browser_context->prefs(), is_guest);
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->SetDelegate(this);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-10-23 06:04:13 +00:00
|
|
|
|
WebContents::~WebContents() {
|
2023-09-26 20:00:46 +00:00
|
|
|
|
if (owner_window_) {
|
|
|
|
|
owner_window_->RemoveBackgroundThrottlingSource(this);
|
|
|
|
|
}
|
2022-09-27 19:47:46 +00:00
|
|
|
|
if (web_contents()) {
|
|
|
|
|
content::RenderViewHost* host = web_contents()->GetRenderViewHost();
|
|
|
|
|
if (host)
|
|
|
|
|
host->GetWidget()->RemoveInputEventObserver(this);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-15 22:43:25 +00:00
|
|
|
|
if (!inspectable_web_contents_) {
|
|
|
|
|
WebContentsDestroyed();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-09-08 11:55:40 +00:00
|
|
|
|
|
2021-03-22 01:56:30 +00:00
|
|
|
|
inspectable_web_contents_->GetView()->SetDelegate(nullptr);
|
2018-02-22 07:52:08 +00:00
|
|
|
|
|
2021-03-15 22:43:25 +00:00
|
|
|
|
// This event is only for internal use, which is emitted when WebContents is
|
|
|
|
|
// being destroyed.
|
|
|
|
|
Emit("will-destroy");
|
2017-04-03 20:03:51 +00:00
|
|
|
|
|
2021-03-15 22:43:25 +00:00
|
|
|
|
// For guest view based on OOPIF, the WebContents is released by the embedder
|
|
|
|
|
// frame, and we need to clear the reference to the memory.
|
2024-02-09 09:29:14 +00:00
|
|
|
|
bool not_owned_by_this = is_guest() && attached_;
|
2021-03-15 22:43:25 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
|
|
|
|
// And background pages are owned by extensions::ExtensionHost.
|
|
|
|
|
if (type_ == Type::kBackgroundPage)
|
|
|
|
|
not_owned_by_this = true;
|
|
|
|
|
#endif
|
|
|
|
|
if (not_owned_by_this) {
|
|
|
|
|
inspectable_web_contents_->ReleaseWebContents();
|
|
|
|
|
WebContentsDestroyed();
|
2016-01-13 09:59:59 +00:00
|
|
|
|
}
|
2021-03-15 22:43:25 +00:00
|
|
|
|
|
|
|
|
|
// InspectableWebContents will be automatically destroyed.
|
2014-04-24 08:45:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-27 07:20:55 +00:00
|
|
|
|
void WebContents::DeleteThisIfAlive() {
|
|
|
|
|
// It is possible that the FirstWeakCallback has been called but the
|
|
|
|
|
// SecondWeakCallback has not, in this case the garbage collection of
|
|
|
|
|
// WebContents has already started and we should not |delete this|.
|
|
|
|
|
// Calling |GetWrapper| can detect this corner case.
|
|
|
|
|
auto* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope scope(isolate);
|
|
|
|
|
v8::Local<v8::Object> wrapper;
|
|
|
|
|
if (!GetWrapper(isolate).ToLocal(&wrapper))
|
|
|
|
|
return;
|
|
|
|
|
delete this;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-15 22:43:25 +00:00
|
|
|
|
void WebContents::Destroy() {
|
2022-06-16 07:46:11 +00:00
|
|
|
|
// The content::WebContents should be destroyed asynchronously when possible
|
2021-03-15 22:43:25 +00:00
|
|
|
|
// as user may choose to destroy WebContents during an event of it.
|
2024-02-09 09:29:14 +00:00
|
|
|
|
if (Browser::Get()->is_shutting_down() || is_guest()) {
|
2021-09-27 07:20:55 +00:00
|
|
|
|
DeleteThisIfAlive();
|
2021-03-15 22:43:25 +00:00
|
|
|
|
} else {
|
2022-05-17 16:48:40 +00:00
|
|
|
|
content::GetUIThreadTaskRunner({})->PostTask(
|
2022-08-31 15:16:27 +00:00
|
|
|
|
FROM_HERE,
|
|
|
|
|
base::BindOnce(&WebContents::DeleteThisIfAlive, GetWeakPtr()));
|
2021-03-15 22:43:25 +00:00
|
|
|
|
}
|
2017-03-18 19:40:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-01-10 22:23:35 +00:00
|
|
|
|
void WebContents::Close(std::optional<gin_helper::Dictionary> options) {
|
2022-09-16 23:22:59 +00:00
|
|
|
|
bool dispatch_beforeunload = false;
|
|
|
|
|
if (options)
|
|
|
|
|
options->Get("waitForBeforeUnload", &dispatch_beforeunload);
|
|
|
|
|
if (dispatch_beforeunload &&
|
|
|
|
|
web_contents()->NeedToFireBeforeUnloadOrUnloadEvents()) {
|
|
|
|
|
NotifyUserActivation();
|
|
|
|
|
web_contents()->DispatchBeforeUnload(false /* auto_cancel */);
|
|
|
|
|
} else {
|
|
|
|
|
web_contents()->Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-01 00:18:22 +00:00
|
|
|
|
bool WebContents::DidAddMessageToConsole(
|
|
|
|
|
content::WebContents* source,
|
|
|
|
|
blink::mojom::ConsoleMessageLevel level,
|
2021-03-16 16:18:45 +00:00
|
|
|
|
const std::u16string& message,
|
2019-05-01 00:18:22 +00:00
|
|
|
|
int32_t line_no,
|
2021-03-16 16:18:45 +00:00
|
|
|
|
const std::u16string& source_id) {
|
2019-05-01 00:18:22 +00:00
|
|
|
|
return Emit("console-message", static_cast<int32_t>(level), message, line_no,
|
|
|
|
|
source_id);
|
2014-10-25 02:01:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-10-09 23:30:38 +00:00
|
|
|
|
void WebContents::OnCreateWindow(
|
|
|
|
|
const GURL& target_url,
|
2018-04-05 23:13:24 +00:00
|
|
|
|
const content::Referrer& referrer,
|
2016-10-09 23:30:38 +00:00
|
|
|
|
const std::string& frame_name,
|
|
|
|
|
WindowOpenDisposition disposition,
|
2020-03-26 18:05:45 +00:00
|
|
|
|
const std::string& features,
|
2018-04-11 08:42:14 +00:00
|
|
|
|
const scoped_refptr<network::ResourceRequestBody>& body) {
|
2020-03-26 18:05:45 +00:00
|
|
|
|
Emit("-new-window", target_url, frame_name, disposition, features, referrer,
|
|
|
|
|
body);
|
2014-10-25 05:21:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-26 18:05:45 +00:00
|
|
|
|
void WebContents::WebContentsCreatedWithFullParams(
|
|
|
|
|
content::WebContents* source_contents,
|
|
|
|
|
int opener_render_process_id,
|
|
|
|
|
int opener_render_frame_id,
|
|
|
|
|
const content::mojom::CreateNewWindowParams& params,
|
|
|
|
|
content::WebContents* new_contents) {
|
2018-10-22 18:02:25 +00:00
|
|
|
|
ChildWebContentsTracker::CreateForWebContents(new_contents);
|
|
|
|
|
auto* tracker = ChildWebContentsTracker::FromWebContents(new_contents);
|
2020-03-26 18:05:45 +00:00
|
|
|
|
tracker->url = params.target_url;
|
|
|
|
|
tracker->frame_name = params.frame_name;
|
|
|
|
|
tracker->referrer = params.referrer.To<content::Referrer>();
|
|
|
|
|
tracker->raw_features = params.raw_features;
|
|
|
|
|
tracker->body = params.body;
|
2020-11-10 17:06:03 +00:00
|
|
|
|
|
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
|
|
|
|
|
|
|
|
|
gin_helper::Dictionary dict;
|
|
|
|
|
gin::ConvertFromV8(isolate, pending_child_web_preferences_.Get(isolate),
|
|
|
|
|
&dict);
|
|
|
|
|
pending_child_web_preferences_.Reset();
|
|
|
|
|
|
|
|
|
|
// Associate the preferences passed in via `setWindowOpenHandler` with the
|
|
|
|
|
// content::WebContents that was just created for the child window. These
|
|
|
|
|
// preferences will be picked up by the RenderWidgetHost via its call to the
|
|
|
|
|
// delegate's OverrideWebkitPrefs.
|
|
|
|
|
new WebContentsPreferences(new_contents, dict);
|
2016-08-16 00:13:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-13 15:37:41 +00:00
|
|
|
|
bool WebContents::IsWebContentsCreationOverridden(
|
|
|
|
|
content::SiteInstance* source_site_instance,
|
|
|
|
|
content::mojom::WindowContainerType window_container_type,
|
|
|
|
|
const GURL& opener_url,
|
2020-11-10 17:06:03 +00:00
|
|
|
|
const content::mojom::CreateNewWindowParams& params) {
|
2021-04-13 19:35:27 +00:00
|
|
|
|
bool default_prevented = Emit(
|
|
|
|
|
"-will-add-new-contents", params.target_url, params.frame_name,
|
|
|
|
|
params.raw_features, params.disposition, *params.referrer, params.body);
|
2020-11-10 17:06:03 +00:00
|
|
|
|
// If the app prevented the default, redirect to CreateCustomWebContents,
|
|
|
|
|
// which always returns nullptr, which will result in the window open being
|
|
|
|
|
// prevented (window.open() will return null in the renderer).
|
|
|
|
|
return default_prevented;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::SetNextChildWebPreferences(
|
|
|
|
|
const gin_helper::Dictionary preferences) {
|
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
|
|
|
|
// Store these prefs for when Chrome calls WebContentsCreatedWithFullParams
|
|
|
|
|
// with the new child contents.
|
|
|
|
|
pending_child_web_preferences_.Reset(isolate, preferences.GetHandle());
|
2020-04-13 15:37:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
content::WebContents* WebContents::CreateCustomWebContents(
|
|
|
|
|
content::RenderFrameHost* opener,
|
|
|
|
|
content::SiteInstance* source_site_instance,
|
|
|
|
|
bool is_new_browsing_instance,
|
|
|
|
|
const GURL& opener_url,
|
|
|
|
|
const std::string& frame_name,
|
|
|
|
|
const GURL& target_url,
|
2022-02-25 18:17:35 +00:00
|
|
|
|
const content::StoragePartitionConfig& partition_config,
|
2020-04-13 15:37:41 +00:00
|
|
|
|
content::SessionStorageNamespace* session_storage_namespace) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 00:16:22 +00:00
|
|
|
|
void WebContents::AddNewContents(
|
|
|
|
|
content::WebContents* source,
|
|
|
|
|
std::unique_ptr<content::WebContents> new_contents,
|
2020-05-26 20:06:26 +00:00
|
|
|
|
const GURL& target_url,
|
2018-09-15 00:16:22 +00:00
|
|
|
|
WindowOpenDisposition disposition,
|
2022-09-07 07:46:37 +00:00
|
|
|
|
const blink::mojom::WindowFeatures& window_features,
|
2018-09-15 00:16:22 +00:00
|
|
|
|
bool user_gesture,
|
|
|
|
|
bool* was_blocked) {
|
2018-10-22 18:02:25 +00:00
|
|
|
|
auto* tracker = ChildWebContentsTracker::FromWebContents(new_contents.get());
|
|
|
|
|
DCHECK(tracker);
|
|
|
|
|
|
2020-07-16 21:11:44 +00:00
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
2018-10-22 18:02:25 +00:00
|
|
|
|
auto api_web_contents =
|
2020-10-27 17:51:45 +00:00
|
|
|
|
CreateAndTake(isolate, std::move(new_contents), Type::kBrowserWindow);
|
2021-03-15 22:43:25 +00:00
|
|
|
|
|
|
|
|
|
// We call RenderFrameCreated here as at this point the empty "about:blank"
|
|
|
|
|
// render frame has already been created. If the window never navigates again
|
|
|
|
|
// RenderFrameCreated won't be called and certain prefs like
|
|
|
|
|
// "kBackgroundColor" will not be applied.
|
|
|
|
|
auto* frame = api_web_contents->MainFrame();
|
|
|
|
|
if (frame) {
|
|
|
|
|
api_web_contents->HandleNewRenderFrame(frame);
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-10 23:40:07 +00:00
|
|
|
|
if (Emit("-add-new-contents", api_web_contents, disposition, user_gesture,
|
2022-09-07 07:46:37 +00:00
|
|
|
|
window_features.bounds.x(), window_features.bounds.y(),
|
|
|
|
|
window_features.bounds.width(), window_features.bounds.height(),
|
|
|
|
|
tracker->url, tracker->frame_name, tracker->referrer,
|
|
|
|
|
tracker->raw_features, tracker->body)) {
|
2021-03-15 22:43:25 +00:00
|
|
|
|
api_web_contents->Destroy();
|
2017-01-10 23:40:07 +00:00
|
|
|
|
}
|
2016-08-16 00:13:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-10-24 10:06:32 +00:00
|
|
|
|
content::WebContents* WebContents::OpenURLFromTab(
|
|
|
|
|
content::WebContents* source,
|
2024-04-15 22:10:32 +00:00
|
|
|
|
const content::OpenURLParams& params,
|
|
|
|
|
base::OnceCallback<void(content::NavigationHandle&)>
|
|
|
|
|
navigation_handle_callback) {
|
2020-07-30 16:17:57 +00:00
|
|
|
|
auto weak_this = GetWeakPtr();
|
2017-01-24 07:50:02 +00:00
|
|
|
|
if (params.disposition != WindowOpenDisposition::CURRENT_TAB) {
|
2020-03-26 18:05:45 +00:00
|
|
|
|
Emit("-new-window", params.url, "", params.disposition, "", params.referrer,
|
|
|
|
|
params.post_data);
|
2014-12-17 22:55:22 +00:00
|
|
|
|
return nullptr;
|
2014-11-04 09:59:15 +00:00
|
|
|
|
}
|
2014-10-24 10:06:32 +00:00
|
|
|
|
|
2021-03-02 17:38:56 +00:00
|
|
|
|
if (!weak_this || !web_contents())
|
2016-12-21 00:51:03 +00:00
|
|
|
|
return nullptr;
|
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
content::NavigationController::LoadURLParams load_url_params(params.url);
|
|
|
|
|
load_url_params.referrer = params.referrer;
|
|
|
|
|
load_url_params.transition_type = params.transition;
|
|
|
|
|
load_url_params.extra_headers = params.extra_headers;
|
|
|
|
|
load_url_params.should_replace_current_entry =
|
|
|
|
|
params.should_replace_current_entry;
|
|
|
|
|
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
|
|
|
|
|
load_url_params.started_from_context_menu = params.started_from_context_menu;
|
|
|
|
|
load_url_params.initiator_origin = params.initiator_origin;
|
|
|
|
|
load_url_params.source_site_instance = params.source_site_instance;
|
|
|
|
|
load_url_params.frame_tree_node_id = params.frame_tree_node_id;
|
|
|
|
|
load_url_params.redirect_chain = params.redirect_chain;
|
|
|
|
|
load_url_params.has_user_gesture = params.user_gesture;
|
|
|
|
|
load_url_params.blob_url_loader_factory = params.blob_url_loader_factory;
|
|
|
|
|
load_url_params.href_translate = params.href_translate;
|
|
|
|
|
load_url_params.reload_type = params.reload_type;
|
|
|
|
|
|
|
|
|
|
if (params.post_data) {
|
|
|
|
|
load_url_params.load_type =
|
|
|
|
|
content::NavigationController::LOAD_TYPE_HTTP_POST;
|
|
|
|
|
load_url_params.post_data = params.post_data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
source->GetController().LoadURLWithParams(load_url_params);
|
|
|
|
|
return source;
|
2014-10-24 10:06:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 03:07:23 +00:00
|
|
|
|
void WebContents::BeforeUnloadFired(content::WebContents* tab,
|
|
|
|
|
bool proceed,
|
|
|
|
|
bool* proceed_to_fire_unload) {
|
2020-05-26 13:21:38 +00:00
|
|
|
|
// Note that Chromium does not emit this for navigations.
|
2023-12-13 21:01:03 +00:00
|
|
|
|
|
|
|
|
|
// Emit returns true if preventDefault() was called, so !Emit will be true if
|
|
|
|
|
// the event should proceed.
|
|
|
|
|
*proceed_to_fire_unload = !Emit("-before-unload-fired", proceed);
|
2015-06-25 03:07:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-02 21:56:09 +00:00
|
|
|
|
void WebContents::SetContentsBounds(content::WebContents* source,
|
2020-02-11 00:37:46 +00:00
|
|
|
|
const gfx::Rect& rect) {
|
2022-09-13 17:49:34 +00:00
|
|
|
|
if (!Emit("content-bounds-updated", rect))
|
|
|
|
|
for (ExtendedWebContentsObserver& observer : observers_)
|
|
|
|
|
observer.OnSetContentBounds(rect);
|
2015-06-25 03:07:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::CloseContents(content::WebContents* source) {
|
2015-07-10 02:38:15 +00:00
|
|
|
|
Emit("close");
|
2019-08-19 20:13:24 +00:00
|
|
|
|
|
|
|
|
|
auto* autofill_driver_factory =
|
|
|
|
|
AutofillDriverFactory::FromWebContents(web_contents());
|
|
|
|
|
if (autofill_driver_factory) {
|
|
|
|
|
autofill_driver_factory->CloseAllPopups();
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-13 21:01:03 +00:00
|
|
|
|
Destroy();
|
2015-06-25 03:07:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::ActivateContents(content::WebContents* source) {
|
2020-02-11 00:37:46 +00:00
|
|
|
|
for (ExtendedWebContentsObserver& observer : observers_)
|
|
|
|
|
observer.OnActivateContents();
|
2015-06-25 03:07:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-06-07 06:56:19 +00:00
|
|
|
|
void WebContents::UpdateTargetURL(content::WebContents* source,
|
|
|
|
|
const GURL& url) {
|
|
|
|
|
Emit("update-target-url", url);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-09 20:01:49 +00:00
|
|
|
|
bool WebContents::HandleKeyboardEvent(
|
2014-10-24 13:46:47 +00:00
|
|
|
|
content::WebContents* source,
|
2024-06-07 21:18:35 +00:00
|
|
|
|
const input::NativeWebKeyboardEvent& event) {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kWebView && embedder_) {
|
2015-06-25 03:07:23 +00:00
|
|
|
|
// Send the unhandled keyboard events back to the embedder.
|
2019-01-09 20:01:49 +00:00
|
|
|
|
return embedder_->HandleKeyboardEvent(source, event);
|
2016-05-18 04:47:50 +00:00
|
|
|
|
} else {
|
2020-11-10 17:06:56 +00:00
|
|
|
|
return PlatformHandleKeyboardEvent(source, event);
|
2015-06-25 03:07:23 +00:00
|
|
|
|
}
|
2014-10-24 13:46:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if !BUILDFLAG(IS_MAC)
|
2020-11-10 17:06:56 +00:00
|
|
|
|
// NOTE: The macOS version of this function is found in
|
|
|
|
|
// electron_api_web_contents_mac.mm, as it requires calling into objective-C
|
|
|
|
|
// code.
|
|
|
|
|
bool WebContents::PlatformHandleKeyboardEvent(
|
|
|
|
|
content::WebContents* source,
|
2024-06-07 21:18:35 +00:00
|
|
|
|
const input::NativeWebKeyboardEvent& event) {
|
2020-11-10 17:06:56 +00:00
|
|
|
|
// Check if the webContents has preferences and to ignore shortcuts
|
|
|
|
|
auto* web_preferences = WebContentsPreferences::From(source);
|
2021-07-26 16:04:09 +00:00
|
|
|
|
if (web_preferences && web_preferences->ShouldIgnoreMenuShortcuts())
|
2020-11-10 17:06:56 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// Let the NativeWindow handle other parts.
|
|
|
|
|
if (owner_window()) {
|
|
|
|
|
owner_window()->HandleKeyboardEvent(source, event);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-06-16 21:35:43 +00:00
|
|
|
|
content::KeyboardEventProcessingResult WebContents::PreHandleKeyboardEvent(
|
2016-12-06 22:41:18 +00:00
|
|
|
|
content::WebContents* source,
|
2024-06-07 21:18:35 +00:00
|
|
|
|
const input::NativeWebKeyboardEvent& event) {
|
2023-06-09 20:28:11 +00:00
|
|
|
|
if (exclusive_access_manager_.HandleUserKeyEvent(event))
|
2022-02-09 09:40:50 +00:00
|
|
|
|
return content::KeyboardEventProcessingResult::HANDLED;
|
|
|
|
|
|
2017-06-16 20:42:33 +00:00
|
|
|
|
if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown ||
|
|
|
|
|
event.GetType() == blink::WebInputEvent::Type::kKeyUp) {
|
2022-09-27 19:47:46 +00:00
|
|
|
|
// For backwards compatibility, pretend that `kRawKeyDown` events are
|
|
|
|
|
// actually `kKeyDown`.
|
2024-06-07 21:18:35 +00:00
|
|
|
|
input::NativeWebKeyboardEvent tweaked_event(event);
|
2022-09-27 19:47:46 +00:00
|
|
|
|
if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown)
|
|
|
|
|
tweaked_event.SetType(blink::WebInputEvent::Type::kKeyDown);
|
|
|
|
|
bool prevent_default = Emit("before-input-event", tweaked_event);
|
2017-06-16 21:35:43 +00:00
|
|
|
|
if (prevent_default) {
|
|
|
|
|
return content::KeyboardEventProcessingResult::HANDLED;
|
|
|
|
|
}
|
2017-06-25 19:01:05 +00:00
|
|
|
|
}
|
2017-06-16 21:35:43 +00:00
|
|
|
|
|
|
|
|
|
return content::KeyboardEventProcessingResult::NOT_HANDLED;
|
2016-12-06 22:41:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-14 06:40:40 +00:00
|
|
|
|
void WebContents::ContentsZoomChange(bool zoom_in) {
|
|
|
|
|
Emit("zoom-changed", zoom_in ? "in" : "out");
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-28 14:23:05 +00:00
|
|
|
|
Profile* WebContents::GetProfile() {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::IsFullscreen() const {
|
2023-02-21 11:11:34 +00:00
|
|
|
|
if (!owner_window())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return owner_window()->IsFullscreen() || is_html_fullscreen();
|
2021-10-28 14:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::EnterFullscreen(const GURL& url,
|
|
|
|
|
ExclusiveAccessBubbleType bubble_type,
|
|
|
|
|
const int64_t display_id) {}
|
|
|
|
|
|
chore: bump chromium to 128.0.6611.0 (main) (#42779)
* chore: bump chromium in DEPS to 128.0.6577.0
* chore: bump chromium in DEPS to 128.0.6579.0
* 5675706: Reland "Reland "Reland "Reland "Add toolchains without PartitionAlloc-Everywhere for dump_syms et al""""
https://chromium-review.googlesource.com/c/chromium/src/+/5675706
* 5668597: [PDF Ink Signatures] Prompt download menu on save when there are edits
https://chromium-review.googlesource.com/c/chromium/src/+/5668597
* 5677014: Reland "Pull data_sharing_sdk from CIPD"
https://chromium-review.googlesource.com/c/chromium/src/+/5677014
* chore: fixup patch indices
* chore: bump chromium in DEPS to 128.0.6581.0
* chore: bump chromium in DEPS to 128.0.6583.0
* update patches
* 5455480: [Extensions] Allow service worker requests to continue without a cert
https://chromium-review.googlesource.com/c/chromium/src/+/5455480
* try to get some debugging output from script/push-patch.js
* chore: bump chromium in DEPS to 128.0.6585.0
* chore: bump chromium in DEPS to 128.0.6587.0
* update patches
* chore: bump chromium in DEPS to 128.0.6589.0
* more patch work
* maybe over here?
* chore: update patches
* 5673207: [HTTPS Upgrades] Disable in captive portal login webview
https://chromium-review.googlesource.com/c/chromium/src/+/5673207
* 5636785: Extensions: WAR: manifest.json's use_dynamic_url requires a dynamic url
https://chromium-review.googlesource.com/c/chromium/src/+/5636785
* chore: bump chromium in DEPS to 128.0.6591.0
* 5665458: Trigger WN2 page when feature is enabled
https://chromium-review.googlesource.com/c/chromium/src/+/5665458
* update patches
* chore: bump chromium in DEPS to 128.0.6593.0
* chore: bump chromium in DEPS to 128.0.6595.0
* chore: bump chromium in DEPS to 128.0.6597.0
* (patch update) 5694586: [compile hints] Remove the usage of v8::Isolate::SetJavaScriptCompileHintsMagicEnabledCallback API
https://chromium-review.googlesource.com/c/chromium/src/+/5694586
* update patches
* 5691287: Reland "Change blink::WebKeyboardEvent to use std::array in is members"
https://chromium-review.googlesource.com/c/chromium/src/+/5691287
The code changed here is modeled after code in `content/renderer/pepper/event_conversion.cc` that was also modified in this CL, so I took the same approach.
* 5529018: Cleanup EnableWebHidOnExtensionServiceWorker flag
https://chromium-review.googlesource.com/c/chromium/src/+/5529018
* 5526324: [Code Health] Add deprecation comment for base::SupportsWeakPtr.
https://chromium-review.googlesource.com/c/chromium/src/+/5526324
Note that this CL actually does make `SupportsWeakPtr` strictly restricted to existing implementations, no new ones. We could add a patch to add ourselves to this list, but it looks like we'll have to refactor this anyways in the near future. Since the refactor seems straightforward, let's try that first.
* chore: bump chromium in DEPS to 128.0.6598.0
* chore: update patches
* 5704737: Rename ExclusiveAccessContext::GetActiveWebContents to avoid conflict
https://chromium-review.googlesource.com/c/chromium/src/+/5704737
* chore: bump chromium in DEPS to 128.0.6601.0
* chore: update patches
* Add `base::StringPiece` header includes
Chromium is working on replacing `base::StringPiece` with `std::string_view`. (See the Chromium Bug below.) They're currently running mass codemods (across many multiple changes) to replace uses of `StringPiece` with `string_view`, including removing the header include for `StringPiece` in those files. This cascades down to our files that were implicitly depending on those includes through some other include.
They're on track to eventually deprecate and remove `StringPiece` so our code should be converted, but that can be done as an upgrade follow-up task. For now, adding the header back to files that need it should suffice for minimal upgrade changes.
Chromium Bug: https://issues.chromium.org/issues/40506050
* 5702737: GlobalRequestID: Avoid unwanted inlining and narrowing int conversions
https://chromium-review.googlesource.com/c/chromium/src/+/5702737
contender for smallest commit 2024
* 5706534: Rename GlobalFeatures to GlobalDesktopFeatures.
https://chromium-review.googlesource.com/c/chromium/src/+/5706534
* 5691321: ui: remove params variants of SelectFile listener functions
https://chromium-review.googlesource.com/c/chromium/src/+/5691321
* 5714949: [Extensions] Display re-enable dialog for MV2 disabled stage
https://chromium-review.googlesource.com/c/chromium/src/+/5714949
* chore: update libc++ filenames
* patch: disable scope reuse & associated dchecks in v8 (hopefully temp, upgrade follow-up)
* fixup! Add `base::StringPiece` header includes
* update MAS patch
5710330: Add crash keys to debug NativeWidgetMacNSWindowBorderlessFrame exception
https://chromium-review.googlesource.com/c/chromium/src/+/5710330
* chore: bump chromium in DEPS to 128.0.6603.0
* chore: update patches
* 5713258: Reland "Preparation for decoupling creation/initialization of context"
https://chromium-review.googlesource.com/c/chromium/src/+/5713258
When destroying a context, it must already be shutdown, and this change enforces it with a new CHECK.
We were overriding `BrowserContextKeyedServiceFactory::BrowserContextShutdown` with an empty implementation, which differed from the default implementation that notifies the `KeyedServiceFactory` that the context has shutdown. Since we were missing this notification, the CHECK would later trip when the service was being destoryed because it was not registered as shutdown when it was shutdown.
* chore: bump chromium in DEPS to 128.0.6605.2
* chore: update patches
* refactor: linux open/save dialog patch
Our existing implementation was relying on an opaque `void* params` parameter that was passed through `ui::SelectFileDialog`.
Recently, that parameter has been getting removed:
- 5691321: ui: remove params variants of SelectFile listener functions | https://chromium-review.googlesource.com/c/chromium/src/+/5691321
- 5709097: ui: remove SelectFileDialog impl params | https://chromium-review.googlesource.com/c/chromium/src/+/5709097
- https://issues.chromium.org/issues/340178601 "reconsider SelectFileDialog"
This restructures the patch to work with mostly the same mechanics, but directly on the `ui::SelectFileDialog` object. This nets us some wins in terms of a smaller patch.
* 5713262: DevTools UI binding AIDA client event returns response
https://chromium-review.googlesource.com/c/chromium/src/+/5713262
* fixup! refactor: linux open/save dialog patch
* chore: bump chromium in DEPS to 128.0.6606.0
* chore: update patches
* fixup! refactor: linux open/save dialog patch
* chore: bump chromium in DEPS to 128.0.6607.0
* chore: update printing.patch
Xref: https://chromium-review.googlesource.com/c/chromium/src/+/5722937
* fix: pwd error in electron-test, nan-test
fix: unshallow depot_tools before 3-way apply
* chore: e patches all
* fixup! fix: pwd error in electron-test, nan-test
* chore: bump chromium in DEPS to 128.0.6609.0
* chore: bump chromium in DEPS to 128.0.6611.0
* chore: update patches
* chore: update libcxx filenames
---------
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: clavin <clavin@electronjs.org>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
Co-authored-by: Alice Zhao <alice@makenotion.com>
2024-07-23 15:59:44 +00:00
|
|
|
|
content::WebContents* WebContents::GetWebContentsForExclusiveAccess() {
|
2021-10-28 14:23:05 +00:00
|
|
|
|
return web_contents();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::CanUserExitFullscreen() const {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::IsExclusiveAccessBubbleDisplayed() const {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 00:17:50 +00:00
|
|
|
|
void WebContents::EnterFullscreenModeForTab(
|
2020-06-01 20:34:34 +00:00
|
|
|
|
content::RenderFrameHost* requesting_frame,
|
2019-10-28 22:12:35 +00:00
|
|
|
|
const blink::mojom::FullscreenOptions& options) {
|
2020-06-01 20:34:34 +00:00
|
|
|
|
auto* source = content::WebContents::FromRenderFrameHost(requesting_frame);
|
2018-04-18 10:09:45 +00:00
|
|
|
|
auto* permission_helper =
|
|
|
|
|
WebContentsPermissionHelper::FromWebContents(source);
|
2019-05-03 19:08:41 +00:00
|
|
|
|
auto callback =
|
|
|
|
|
base::BindRepeating(&WebContents::OnEnterFullscreenModeForTab,
|
2020-06-01 20:34:34 +00:00
|
|
|
|
base::Unretained(this), requesting_frame, options);
|
2022-08-26 10:31:33 +00:00
|
|
|
|
permission_helper->RequestFullscreenPermission(requesting_frame, callback);
|
2016-02-01 10:03:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 00:17:50 +00:00
|
|
|
|
void WebContents::OnEnterFullscreenModeForTab(
|
2020-06-01 20:34:34 +00:00
|
|
|
|
content::RenderFrameHost* requesting_frame,
|
2019-10-28 22:12:35 +00:00
|
|
|
|
const blink::mojom::FullscreenOptions& options,
|
2018-09-15 00:17:50 +00:00
|
|
|
|
bool allowed) {
|
2023-02-21 11:11:34 +00:00
|
|
|
|
if (!allowed || !owner_window())
|
2020-11-10 17:06:56 +00:00
|
|
|
|
return;
|
2021-08-17 07:03:45 +00:00
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
auto* source = content::WebContents::FromRenderFrameHost(requesting_frame);
|
|
|
|
|
if (IsFullscreenForTabOrPending(source)) {
|
|
|
|
|
DCHECK_EQ(fullscreen_frame_, source->GetFocusedFrame());
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-08-17 07:03:45 +00:00
|
|
|
|
|
2022-08-01 20:52:58 +00:00
|
|
|
|
owner_window()->set_fullscreen_transition_type(
|
2023-05-12 13:24:01 +00:00
|
|
|
|
NativeWindow::FullScreenTransitionType::kHTML);
|
2023-06-09 20:28:11 +00:00
|
|
|
|
exclusive_access_manager_.fullscreen_controller()->EnterFullscreenModeForTab(
|
2022-05-25 04:38:38 +00:00
|
|
|
|
requesting_frame, options.display_id);
|
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
SetHtmlApiFullscreen(true);
|
|
|
|
|
|
|
|
|
|
if (native_fullscreen_) {
|
|
|
|
|
// Explicitly trigger a view resize, as the size is not actually changing if
|
|
|
|
|
// the browser is fullscreened, too.
|
|
|
|
|
source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
|
|
|
|
|
}
|
2015-05-08 06:18:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-09 12:17:40 +00:00
|
|
|
|
void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
|
2023-02-21 11:11:34 +00:00
|
|
|
|
if (!owner_window())
|
2020-11-10 17:06:56 +00:00
|
|
|
|
return;
|
2021-08-17 07:03:45 +00:00
|
|
|
|
|
2022-04-14 10:35:36 +00:00
|
|
|
|
// This needs to be called before we exit fullscreen on the native window,
|
|
|
|
|
// or the controller will incorrectly think we weren't fullscreen and bail.
|
2023-06-09 20:28:11 +00:00
|
|
|
|
exclusive_access_manager_.fullscreen_controller()->ExitFullscreenModeForTab(
|
2022-04-14 10:35:36 +00:00
|
|
|
|
source);
|
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
SetHtmlApiFullscreen(false);
|
|
|
|
|
|
|
|
|
|
if (native_fullscreen_) {
|
|
|
|
|
// Explicitly trigger a view resize, as the size is not actually changing if
|
|
|
|
|
// the browser is fullscreened, too. Chrome does this indirectly from
|
|
|
|
|
// `chrome/browser/ui/exclusive_access/fullscreen_controller.cc`.
|
|
|
|
|
source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
|
|
|
|
|
}
|
2015-05-08 06:18:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-01-23 09:59:40 +00:00
|
|
|
|
void WebContents::RendererUnresponsive(
|
|
|
|
|
content::WebContents* source,
|
2018-10-02 21:57:14 +00:00
|
|
|
|
content::RenderWidgetHost* render_widget_host,
|
|
|
|
|
base::RepeatingClosure hang_monitor_restarter) {
|
2015-06-25 03:07:23 +00:00
|
|
|
|
Emit("unresponsive");
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-11 15:23:16 +00:00
|
|
|
|
void WebContents::RendererResponsive(
|
|
|
|
|
content::WebContents* source,
|
|
|
|
|
content::RenderWidgetHost* render_widget_host) {
|
2015-06-25 03:07:23 +00:00
|
|
|
|
Emit("responsive");
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-24 08:45:59 +00:00
|
|
|
|
bool WebContents::HandleContextMenu(content::RenderFrameHost& render_frame_host,
|
2019-02-27 07:49:59 +00:00
|
|
|
|
const content::ContextMenuParams& params) {
|
2021-11-24 08:45:59 +00:00
|
|
|
|
Emit("context-menu", std::make_pair(params, &render_frame_host));
|
2015-11-02 15:28:45 +00:00
|
|
|
|
|
2015-10-31 13:39:07 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-17 17:27:56 +00:00
|
|
|
|
void WebContents::FindReply(content::WebContents* web_contents,
|
|
|
|
|
int request_id,
|
|
|
|
|
int number_of_matches,
|
|
|
|
|
const gfx::Rect& selection_rect,
|
|
|
|
|
int active_match_ordinal,
|
|
|
|
|
bool final_update) {
|
2016-09-09 10:50:43 +00:00
|
|
|
|
if (!final_update)
|
|
|
|
|
return;
|
|
|
|
|
|
2020-07-16 21:11:44 +00:00
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
2023-08-21 01:43:41 +00:00
|
|
|
|
auto result = gin_helper::Dictionary::CreateEmpty(isolate);
|
2016-09-08 05:27:10 +00:00
|
|
|
|
result.Set("requestId", request_id);
|
|
|
|
|
result.Set("matches", number_of_matches);
|
|
|
|
|
result.Set("selectionArea", selection_rect);
|
|
|
|
|
result.Set("activeMatchOrdinal", active_match_ordinal);
|
2016-09-09 10:50:43 +00:00
|
|
|
|
result.Set("finalUpdate", final_update); // Deprecate after 2.0
|
2019-10-21 07:05:40 +00:00
|
|
|
|
Emit("found-in-page", result.GetHandle());
|
2015-12-17 17:27:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-01-31 23:04:13 +00:00
|
|
|
|
void WebContents::OnRequestPointerLock(content::WebContents* web_contents,
|
2023-11-06 19:54:31 +00:00
|
|
|
|
bool user_gesture,
|
|
|
|
|
bool last_unlocked_by_target,
|
|
|
|
|
bool allowed) {
|
2022-02-09 09:40:50 +00:00
|
|
|
|
if (allowed) {
|
2024-01-31 23:04:13 +00:00
|
|
|
|
exclusive_access_manager_.pointer_lock_controller()->RequestToLockPointer(
|
2022-02-09 09:40:50 +00:00
|
|
|
|
web_contents, user_gesture, last_unlocked_by_target);
|
|
|
|
|
} else {
|
2024-01-31 23:04:13 +00:00
|
|
|
|
web_contents->GotResponseToPointerLockRequest(
|
2022-02-09 09:40:50 +00:00
|
|
|
|
blink::mojom::PointerLockResult::kPermissionDenied);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-31 23:04:13 +00:00
|
|
|
|
void WebContents::RequestPointerLock(content::WebContents* web_contents,
|
2022-02-09 09:40:50 +00:00
|
|
|
|
bool user_gesture,
|
|
|
|
|
bool last_unlocked_by_target) {
|
|
|
|
|
auto* permission_helper =
|
|
|
|
|
WebContentsPermissionHelper::FromWebContents(web_contents);
|
|
|
|
|
permission_helper->RequestPointerLockPermission(
|
|
|
|
|
user_gesture, last_unlocked_by_target,
|
2024-01-31 23:04:13 +00:00
|
|
|
|
base::BindOnce(&WebContents::OnRequestPointerLock,
|
2022-02-09 09:40:50 +00:00
|
|
|
|
base::Unretained(this)));
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-31 23:04:13 +00:00
|
|
|
|
void WebContents::LostPointerLock() {
|
2024-03-15 18:03:42 +00:00
|
|
|
|
exclusive_access_manager_.pointer_lock_controller()
|
|
|
|
|
->ExitExclusiveAccessToPreviousState();
|
2022-02-09 09:40:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-06 19:54:31 +00:00
|
|
|
|
void WebContents::OnRequestKeyboardLock(content::WebContents* web_contents,
|
|
|
|
|
bool esc_key_locked,
|
|
|
|
|
bool allowed) {
|
|
|
|
|
if (allowed) {
|
|
|
|
|
exclusive_access_manager_.keyboard_lock_controller()->RequestKeyboardLock(
|
|
|
|
|
web_contents, esc_key_locked);
|
|
|
|
|
} else {
|
|
|
|
|
web_contents->GotResponseToKeyboardLockRequest(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-28 14:23:05 +00:00
|
|
|
|
void WebContents::RequestKeyboardLock(content::WebContents* web_contents,
|
|
|
|
|
bool esc_key_locked) {
|
2023-11-06 19:54:31 +00:00
|
|
|
|
auto* permission_helper =
|
|
|
|
|
WebContentsPermissionHelper::FromWebContents(web_contents);
|
|
|
|
|
permission_helper->RequestKeyboardLockPermission(
|
|
|
|
|
esc_key_locked, base::BindOnce(&WebContents::OnRequestKeyboardLock,
|
|
|
|
|
base::Unretained(this)));
|
2021-10-28 14:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::CancelKeyboardLockRequest(
|
|
|
|
|
content::WebContents* web_contents) {
|
2023-06-09 20:28:11 +00:00
|
|
|
|
exclusive_access_manager_.keyboard_lock_controller()
|
2021-10-28 14:23:05 +00:00
|
|
|
|
->CancelKeyboardLockRequest(web_contents);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-09 14:30:28 +00:00
|
|
|
|
bool WebContents::CheckMediaAccessPermission(
|
|
|
|
|
content::RenderFrameHost* render_frame_host,
|
2023-11-28 21:40:12 +00:00
|
|
|
|
const url::Origin& security_origin,
|
2019-07-03 01:22:09 +00:00
|
|
|
|
blink::mojom::MediaStreamType type) {
|
2018-09-09 14:30:28 +00:00
|
|
|
|
auto* web_contents =
|
|
|
|
|
content::WebContents::FromRenderFrameHost(render_frame_host);
|
2018-08-28 14:05:08 +00:00
|
|
|
|
auto* permission_helper =
|
|
|
|
|
WebContentsPermissionHelper::FromWebContents(web_contents);
|
|
|
|
|
return permission_helper->CheckMediaAccessPermission(security_origin, type);
|
2016-02-26 10:17:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-23 13:29:47 +00:00
|
|
|
|
void WebContents::RequestMediaAccessPermission(
|
|
|
|
|
content::WebContents* web_contents,
|
|
|
|
|
const content::MediaStreamRequest& request,
|
2018-10-02 18:09:25 +00:00
|
|
|
|
content::MediaResponseCallback callback) {
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* permission_helper =
|
2016-01-23 13:29:47 +00:00
|
|
|
|
WebContentsPermissionHelper::FromWebContents(web_contents);
|
2018-10-02 18:09:25 +00:00
|
|
|
|
permission_helper->RequestMediaAccessPermission(request, std::move(callback));
|
2016-01-23 13:29:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-13 21:01:03 +00:00
|
|
|
|
const void* const kJavaScriptDialogManagerKey = &kJavaScriptDialogManagerKey;
|
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
|
content::JavaScriptDialogManager* WebContents::GetJavaScriptDialogManager(
|
2017-04-28 00:28:48 +00:00
|
|
|
|
content::WebContents* source) {
|
2023-12-13 21:01:03 +00:00
|
|
|
|
// Indirect these delegate methods through a helper object whose lifetime is
|
|
|
|
|
// bound to that of the content::WebContents. This prevents the
|
|
|
|
|
// content::WebContents from calling methods on the Electron WebContents in
|
|
|
|
|
// the event that the Electron one is destroyed before the content one, as
|
|
|
|
|
// happens sometimes during shutdown or when webviews are involved.
|
|
|
|
|
class JSDialogManagerHelper : public content::JavaScriptDialogManager,
|
|
|
|
|
public base::SupportsUserData::Data {
|
|
|
|
|
public:
|
|
|
|
|
void RunJavaScriptDialog(content::WebContents* web_contents,
|
|
|
|
|
content::RenderFrameHost* rfh,
|
|
|
|
|
content::JavaScriptDialogType dialog_type,
|
|
|
|
|
const std::u16string& message_text,
|
|
|
|
|
const std::u16string& default_prompt_text,
|
|
|
|
|
DialogClosedCallback callback,
|
|
|
|
|
bool* did_suppress_message) override {
|
|
|
|
|
auto* wc = WebContents::From(web_contents);
|
|
|
|
|
if (wc)
|
|
|
|
|
wc->RunJavaScriptDialog(web_contents, rfh, dialog_type, message_text,
|
|
|
|
|
default_prompt_text, std::move(callback),
|
|
|
|
|
did_suppress_message);
|
|
|
|
|
}
|
|
|
|
|
void RunBeforeUnloadDialog(content::WebContents* web_contents,
|
|
|
|
|
content::RenderFrameHost* rfh,
|
|
|
|
|
bool is_reload,
|
|
|
|
|
DialogClosedCallback callback) override {
|
|
|
|
|
auto* wc = WebContents::From(web_contents);
|
|
|
|
|
if (wc)
|
|
|
|
|
wc->RunBeforeUnloadDialog(web_contents, rfh, is_reload,
|
|
|
|
|
std::move(callback));
|
|
|
|
|
}
|
|
|
|
|
void CancelDialogs(content::WebContents* web_contents,
|
|
|
|
|
bool reset_state) override {
|
|
|
|
|
auto* wc = WebContents::From(web_contents);
|
|
|
|
|
if (wc)
|
|
|
|
|
wc->CancelDialogs(web_contents, reset_state);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
if (!source->GetUserData(kJavaScriptDialogManagerKey))
|
|
|
|
|
source->SetUserData(kJavaScriptDialogManagerKey,
|
|
|
|
|
std::make_unique<JSDialogManagerHelper>());
|
|
|
|
|
|
|
|
|
|
return static_cast<JSDialogManagerHelper*>(
|
|
|
|
|
source->GetUserData(kJavaScriptDialogManagerKey));
|
2017-04-28 00:28:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 00:18:14 +00:00
|
|
|
|
void WebContents::OnAudioStateChanged(bool audible) {
|
2023-03-06 16:00:24 +00:00
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
|
|
|
|
gin::Handle<gin_helper::internal::Event> event =
|
|
|
|
|
gin_helper::internal::Event::New(isolate);
|
|
|
|
|
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>();
|
|
|
|
|
gin::Dictionary dict(isolate, event_object);
|
|
|
|
|
dict.Set("audible", audible);
|
|
|
|
|
EmitWithoutEvent("audio-state-changed", event);
|
2018-09-05 21:00:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-10 16:07:42 +00:00
|
|
|
|
void WebContents::BeforeUnloadFired(bool proceed) {
|
2015-06-25 03:07:23 +00:00
|
|
|
|
// Do nothing, we override this method just to avoid compilation error since
|
|
|
|
|
// there are two virtual functions named BeforeUnloadFired.
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-15 22:43:25 +00:00
|
|
|
|
void WebContents::HandleNewRenderFrame(
|
2021-03-04 17:27:05 +00:00
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
|
|
|
|
auto* rwhv = render_frame_host->GetView();
|
|
|
|
|
if (!rwhv)
|
|
|
|
|
return;
|
2021-02-10 20:03:48 +00:00
|
|
|
|
|
2021-07-15 20:18:39 +00:00
|
|
|
|
// Set the background color of RenderWidgetHostView.
|
|
|
|
|
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
2023-12-13 21:01:03 +00:00
|
|
|
|
if (web_preferences)
|
|
|
|
|
SetBackgroundColor(web_preferences->GetBackgroundColor());
|
2021-07-15 20:18:39 +00:00
|
|
|
|
|
2021-03-04 17:27:05 +00:00
|
|
|
|
if (!background_throttling_)
|
|
|
|
|
render_frame_host->GetRenderViewHost()->SetSchedulerThrottling(false);
|
2019-12-02 18:29:03 +00:00
|
|
|
|
|
|
|
|
|
auto* rwh_impl =
|
|
|
|
|
static_cast<content::RenderWidgetHostImpl*>(rwhv->GetRenderWidgetHost());
|
|
|
|
|
if (rwh_impl)
|
|
|
|
|
rwh_impl->disable_hidden_ = !background_throttling_;
|
2021-02-09 20:16:21 +00:00
|
|
|
|
|
2021-08-18 18:23:41 +00:00
|
|
|
|
auto* web_frame = WebFrameMain::FromRenderFrameHost(render_frame_host);
|
|
|
|
|
if (web_frame)
|
2022-05-19 18:34:58 +00:00
|
|
|
|
web_frame->MaybeSetupMojoConnection();
|
2016-12-28 23:44:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-27 14:56:35 +00:00
|
|
|
|
void WebContents::OnBackgroundColorChanged() {
|
2024-01-10 22:23:35 +00:00
|
|
|
|
std::optional<SkColor> color = web_contents()->GetBackgroundColor();
|
2022-01-27 14:56:35 +00:00
|
|
|
|
if (color.has_value()) {
|
|
|
|
|
auto* const view = web_contents()->GetRenderWidgetHostView();
|
|
|
|
|
static_cast<content::RenderWidgetHostViewBase*>(view)
|
|
|
|
|
->SetContentBackgroundColor(color.value());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-15 22:43:25 +00:00
|
|
|
|
void WebContents::RenderFrameCreated(
|
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
|
|
|
|
HandleNewRenderFrame(render_frame_host);
|
2021-09-01 22:21:15 +00:00
|
|
|
|
|
|
|
|
|
// RenderFrameCreated is called for speculative frames which may not be
|
|
|
|
|
// used in certain cross-origin navigations. Invoking
|
|
|
|
|
// RenderFrameHost::GetLifecycleState currently crashes when called for
|
|
|
|
|
// speculative frames so we need to filter it out for now. Check
|
|
|
|
|
// https://crbug.com/1183639 for details on when this can be removed.
|
|
|
|
|
auto* rfh_impl =
|
|
|
|
|
static_cast<content::RenderFrameHostImpl*>(render_frame_host);
|
|
|
|
|
if (rfh_impl->lifecycle_state() ==
|
|
|
|
|
content::RenderFrameHostImpl::LifecycleStateImpl::kSpeculative) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
content::RenderFrameHost::LifecycleState lifecycle_state =
|
|
|
|
|
render_frame_host->GetLifecycleState();
|
|
|
|
|
if (lifecycle_state == content::RenderFrameHost::LifecycleState::kActive) {
|
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
2023-10-10 10:45:44 +00:00
|
|
|
|
auto details = gin_helper::Dictionary::CreateEmpty(isolate);
|
2021-09-01 22:21:15 +00:00
|
|
|
|
details.SetGetter("frame", render_frame_host);
|
|
|
|
|
Emit("frame-created", details);
|
|
|
|
|
}
|
2021-03-15 22:43:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 18:23:41 +00:00
|
|
|
|
void WebContents::RenderFrameDeleted(
|
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
|
|
|
|
// A RenderFrameHost can be deleted when:
|
|
|
|
|
// - A WebContents is removed and its containing frames are disposed.
|
|
|
|
|
// - An <iframe> is removed from the DOM.
|
|
|
|
|
// - Cross-origin navigation creates a new RFH in a separate process which
|
|
|
|
|
// is swapped by content::RenderFrameHostManager.
|
|
|
|
|
//
|
2021-09-23 11:00:11 +00:00
|
|
|
|
|
2021-08-18 18:23:41 +00:00
|
|
|
|
// WebFrameMain::FromRenderFrameHost(rfh) will use the RFH's FrameTreeNode ID
|
|
|
|
|
// to find an existing instance of WebFrameMain. During a cross-origin
|
|
|
|
|
// navigation, the deleted RFH will be the old host which was swapped out. In
|
|
|
|
|
// this special case, we need to also ensure that WebFrameMain's internal RFH
|
|
|
|
|
// matches before marking it as disposed.
|
|
|
|
|
auto* web_frame = WebFrameMain::FromRenderFrameHost(render_frame_host);
|
|
|
|
|
if (web_frame && web_frame->render_frame_host() == render_frame_host)
|
|
|
|
|
web_frame->MarkRenderFrameDisposed();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::RenderFrameHostChanged(content::RenderFrameHost* old_host,
|
|
|
|
|
content::RenderFrameHost* new_host) {
|
2023-02-03 11:43:42 +00:00
|
|
|
|
if (new_host->IsInPrimaryMainFrame()) {
|
|
|
|
|
if (old_host)
|
|
|
|
|
old_host->GetRenderWidgetHost()->RemoveInputEventObserver(this);
|
|
|
|
|
if (new_host)
|
|
|
|
|
new_host->GetRenderWidgetHost()->AddInputEventObserver(this);
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 18:23:41 +00:00
|
|
|
|
// During cross-origin navigation, a FrameTreeNode will swap out its RFH.
|
|
|
|
|
// If an instance of WebFrameMain exists, it will need to have its RFH
|
|
|
|
|
// swapped as well.
|
|
|
|
|
//
|
2021-09-01 22:21:15 +00:00
|
|
|
|
// |old_host| can be a nullptr so we use |new_host| for looking up the
|
2021-08-18 18:23:41 +00:00
|
|
|
|
// WebFrameMain instance.
|
2023-02-28 19:08:22 +00:00
|
|
|
|
auto* web_frame = WebFrameMain::FromRenderFrameHost(new_host);
|
2021-08-18 18:23:41 +00:00
|
|
|
|
if (web_frame) {
|
|
|
|
|
web_frame->UpdateRenderFrameHost(new_host);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::FrameDeleted(int frame_tree_node_id) {
|
|
|
|
|
auto* web_frame = WebFrameMain::FromFrameTreeNodeId(frame_tree_node_id);
|
|
|
|
|
if (web_frame)
|
|
|
|
|
web_frame->Destroyed();
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-25 04:40:04 +00:00
|
|
|
|
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
|
2018-12-05 08:03:39 +00:00
|
|
|
|
// This event is necessary for tracking any states with respect to
|
|
|
|
|
// intermediate render view hosts aka speculative render view hosts. Currently
|
|
|
|
|
// used by object-registry.js to ref count remote objects.
|
2018-09-11 18:18:10 +00:00
|
|
|
|
Emit("render-view-deleted", render_view_host->GetProcess()->GetID());
|
2018-12-05 08:03:39 +00:00
|
|
|
|
|
2020-10-07 23:11:19 +00:00
|
|
|
|
if (web_contents()->GetRenderViewHost() == render_view_host) {
|
2018-12-05 08:03:39 +00:00
|
|
|
|
// When the RVH that has been deleted is the current RVH it means that the
|
|
|
|
|
// the web contents are being closed. This is communicated by this event.
|
2020-11-10 17:06:03 +00:00
|
|
|
|
// Currently tracked by guest-window-manager.ts to destroy the
|
2018-12-05 08:03:39 +00:00
|
|
|
|
// BrowserWindow.
|
|
|
|
|
Emit("current-render-view-deleted",
|
|
|
|
|
render_view_host->GetProcess()->GetID());
|
|
|
|
|
}
|
2014-04-25 03:51:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-24 08:45:59 +00:00
|
|
|
|
void WebContents::PrimaryMainFrameRenderProcessGone(
|
|
|
|
|
base::TerminationStatus status) {
|
2020-07-16 21:11:44 +00:00
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
2023-10-10 10:45:44 +00:00
|
|
|
|
auto details = gin_helper::Dictionary::CreateEmpty(isolate);
|
2020-05-11 20:42:24 +00:00
|
|
|
|
details.Set("reason", status);
|
2021-02-09 01:08:11 +00:00
|
|
|
|
details.Set("exitCode", web_contents()->GetCrashedErrorCode());
|
2020-05-11 20:42:24 +00:00
|
|
|
|
Emit("render-process-gone", details);
|
2014-04-25 03:51:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-12 19:35:56 +00:00
|
|
|
|
void WebContents::PluginCrashed(const base::FilePath& plugin_path,
|
|
|
|
|
base::ProcessId plugin_pid) {
|
2019-10-09 17:59:37 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_PLUGINS)
|
2015-05-12 19:35:56 +00:00
|
|
|
|
content::WebPluginInfo info;
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* plugin_service = content::PluginService::GetInstance();
|
2015-05-12 19:35:56 +00:00
|
|
|
|
plugin_service->GetPluginInfoByPath(plugin_path, &info);
|
|
|
|
|
Emit("plugin-crashed", info.name, info.version);
|
2020-10-13 17:25:21 +00:00
|
|
|
|
#endif // BUILDFLAG(ENABLE_PLUGINS)
|
2015-05-12 19:35:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-01-23 09:59:40 +00:00
|
|
|
|
void WebContents::MediaStartedPlaying(const MediaPlayerInfo& video_type,
|
2019-04-20 17:20:37 +00:00
|
|
|
|
const content::MediaPlayerId& id) {
|
2015-12-20 03:16:22 +00:00
|
|
|
|
Emit("media-started-playing");
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-11 15:27:14 +00:00
|
|
|
|
void WebContents::MediaStoppedPlaying(
|
|
|
|
|
const MediaPlayerInfo& video_type,
|
2019-04-20 17:20:37 +00:00
|
|
|
|
const content::MediaPlayerId& id,
|
2018-04-11 15:27:14 +00:00
|
|
|
|
content::WebContentsObserver::MediaStoppedReason reason) {
|
2015-12-20 03:16:22 +00:00
|
|
|
|
Emit("media-paused");
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-17 18:41:52 +00:00
|
|
|
|
void WebContents::DidChangeThemeColor() {
|
|
|
|
|
auto theme_color = web_contents()->GetThemeColor();
|
2019-04-20 17:20:37 +00:00
|
|
|
|
if (theme_color) {
|
|
|
|
|
Emit("did-change-theme-color", electron::ToRGBHex(theme_color.value()));
|
2017-08-20 14:48:13 +00:00
|
|
|
|
} else {
|
2017-11-13 07:20:54 +00:00
|
|
|
|
Emit("did-change-theme-color", nullptr);
|
2017-08-20 14:48:13 +00:00
|
|
|
|
}
|
2015-12-22 22:16:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-06-13 21:02:56 +00:00
|
|
|
|
void WebContents::DidAcquireFullscreen(content::RenderFrameHost* rfh) {
|
|
|
|
|
set_fullscreen_frame(rfh);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-01 10:28:57 +00:00
|
|
|
|
void WebContents::OnWebContentsFocused(
|
|
|
|
|
content::RenderWidgetHost* render_widget_host) {
|
|
|
|
|
Emit("focus");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::OnWebContentsLostFocus(
|
|
|
|
|
content::RenderWidgetHost* render_widget_host) {
|
|
|
|
|
Emit("blur");
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-18 19:57:34 +00:00
|
|
|
|
void WebContents::DOMContentLoaded(
|
2015-04-29 13:49:31 +00:00
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
2021-09-01 22:21:15 +00:00
|
|
|
|
auto* web_frame = WebFrameMain::FromRenderFrameHost(render_frame_host);
|
|
|
|
|
if (web_frame)
|
|
|
|
|
web_frame->DOMContentLoaded();
|
|
|
|
|
|
2016-08-04 04:03:24 +00:00
|
|
|
|
if (!render_frame_host->GetParent())
|
2015-04-29 13:49:31 +00:00
|
|
|
|
Emit("dom-ready");
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-11 11:11:34 +00:00
|
|
|
|
void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host,
|
|
|
|
|
const GURL& validated_url) {
|
|
|
|
|
bool is_main_frame = !render_frame_host->GetParent();
|
2018-04-26 10:17:55 +00:00
|
|
|
|
int frame_process_id = render_frame_host->GetProcess()->GetID();
|
|
|
|
|
int frame_routing_id = render_frame_host->GetRoutingID();
|
2019-09-30 22:00:47 +00:00
|
|
|
|
auto weak_this = GetWeakPtr();
|
2018-05-10 20:52:42 +00:00
|
|
|
|
Emit("did-frame-finish-load", is_main_frame, frame_process_id,
|
2018-04-26 10:17:55 +00:00
|
|
|
|
frame_routing_id);
|
2014-06-09 04:03:19 +00:00
|
|
|
|
|
2019-09-30 22:00:47 +00:00
|
|
|
|
// ⚠️WARNING!⚠️
|
|
|
|
|
// Emit() triggers JS which can call destroy() on |this|. It's not safe to
|
|
|
|
|
// assume that |this| points to valid memory at this point.
|
2021-03-02 17:38:56 +00:00
|
|
|
|
if (is_main_frame && weak_this && web_contents())
|
2014-06-09 04:03:19 +00:00
|
|
|
|
Emit("did-finish-load");
|
2014-04-25 04:22:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-10-24 15:05:25 +00:00
|
|
|
|
void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
|
2016-04-13 10:33:59 +00:00
|
|
|
|
const GURL& url,
|
2020-01-29 12:01:37 +00:00
|
|
|
|
int error_code) {
|
2023-04-06 08:23:34 +00:00
|
|
|
|
// See DocumentLoader::StartLoadingResponse() - when we navigate to a media
|
|
|
|
|
// resource the original request for the media resource, which resulted in a
|
|
|
|
|
// committed navigation, is simply discarded. The media element created
|
|
|
|
|
// inside the MediaDocument then makes *another new* request for the same
|
|
|
|
|
// media resource.
|
|
|
|
|
bool is_media_document =
|
|
|
|
|
media::IsSupportedMediaMimeType(web_contents()->GetContentsMimeType());
|
|
|
|
|
if (error_code == net::ERR_ABORTED && is_media_document)
|
|
|
|
|
return;
|
|
|
|
|
|
2016-04-05 02:24:58 +00:00
|
|
|
|
bool is_main_frame = !render_frame_host->GetParent();
|
2018-04-26 10:17:55 +00:00
|
|
|
|
int frame_process_id = render_frame_host->GetProcess()->GetID();
|
|
|
|
|
int frame_routing_id = render_frame_host->GetRoutingID();
|
2020-01-29 12:01:37 +00:00
|
|
|
|
Emit("did-fail-load", error_code, "", url, is_main_frame, frame_process_id,
|
|
|
|
|
frame_routing_id);
|
2014-10-24 15:05:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-22 07:24:34 +00:00
|
|
|
|
void WebContents::DidStartLoading() {
|
2014-04-25 04:22:16 +00:00
|
|
|
|
Emit("did-start-loading");
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-22 07:24:34 +00:00
|
|
|
|
void WebContents::DidStopLoading() {
|
2020-10-21 22:44:19 +00:00
|
|
|
|
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
2021-07-26 16:04:09 +00:00
|
|
|
|
if (web_preferences && web_preferences->ShouldUsePreferredSizeMode())
|
2020-10-21 22:44:19 +00:00
|
|
|
|
web_contents()->GetRenderViewHost()->EnablePreferredSizeMode();
|
2020-11-30 05:03:07 +00:00
|
|
|
|
|
|
|
|
|
Emit("did-stop-loading");
|
2014-04-25 04:22:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 15:42:43 +00:00
|
|
|
|
bool WebContents::EmitNavigationEvent(
|
2023-02-28 19:08:22 +00:00
|
|
|
|
const std::string& event_name,
|
2018-04-26 10:17:55 +00:00
|
|
|
|
content::NavigationHandle* navigation_handle) {
|
|
|
|
|
bool is_main_frame = navigation_handle->IsInMainFrame();
|
|
|
|
|
int frame_process_id = -1, frame_routing_id = -1;
|
2023-03-28 14:55:41 +00:00
|
|
|
|
content::RenderFrameHost* frame_host = GetRenderFrameHost(navigation_handle);
|
2018-04-26 10:17:55 +00:00
|
|
|
|
if (frame_host) {
|
|
|
|
|
frame_process_id = frame_host->GetProcess()->GetID();
|
|
|
|
|
frame_routing_id = frame_host->GetRoutingID();
|
|
|
|
|
}
|
|
|
|
|
bool is_same_document = navigation_handle->IsSameDocument();
|
|
|
|
|
auto url = navigation_handle->GetURL();
|
2023-02-28 19:08:22 +00:00
|
|
|
|
content::RenderFrameHost* initiator_frame_host =
|
|
|
|
|
navigation_handle->GetInitiatorFrameToken().has_value()
|
|
|
|
|
? content::RenderFrameHost::FromFrameToken(
|
2023-11-14 21:21:32 +00:00
|
|
|
|
content::GlobalRenderFrameHostToken(
|
|
|
|
|
navigation_handle->GetInitiatorProcessId(),
|
|
|
|
|
navigation_handle->GetInitiatorFrameToken().value()))
|
2023-02-28 19:08:22 +00:00
|
|
|
|
: nullptr;
|
|
|
|
|
|
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
|
|
|
|
|
|
|
|
|
gin::Handle<gin_helper::internal::Event> event =
|
|
|
|
|
gin_helper::internal::Event::New(isolate);
|
|
|
|
|
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>();
|
|
|
|
|
|
|
|
|
|
gin_helper::Dictionary dict(isolate, event_object);
|
|
|
|
|
dict.Set("url", url);
|
|
|
|
|
dict.Set("isSameDocument", is_same_document);
|
|
|
|
|
dict.Set("isMainFrame", is_main_frame);
|
2023-10-16 00:16:51 +00:00
|
|
|
|
dict.SetGetter("frame", frame_host);
|
2023-02-28 19:08:22 +00:00
|
|
|
|
dict.SetGetter("initiator", initiator_frame_host);
|
|
|
|
|
|
|
|
|
|
EmitWithoutEvent(event_name, event, url, is_same_document, is_main_frame,
|
|
|
|
|
frame_process_id, frame_routing_id);
|
|
|
|
|
return event->GetDefaultPrevented();
|
2018-09-15 15:42:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-02 22:38:16 +00:00
|
|
|
|
void WebContents::Message(bool internal,
|
|
|
|
|
const std::string& channel,
|
2020-12-14 18:57:36 +00:00
|
|
|
|
blink::CloneableMessage arguments,
|
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
2019-12-06 21:15:23 +00:00
|
|
|
|
TRACE_EVENT1("electron", "WebContents::Message", "channel", channel);
|
2019-04-02 22:38:16 +00:00
|
|
|
|
// webContents.emit('-ipc-message', new Event(), internal, channel,
|
|
|
|
|
// arguments);
|
2020-12-14 18:57:36 +00:00
|
|
|
|
EmitWithSender("-ipc-message", render_frame_host,
|
2022-03-19 02:50:05 +00:00
|
|
|
|
electron::mojom::ElectronApiIPC::InvokeCallback(), internal,
|
2020-12-14 18:57:36 +00:00
|
|
|
|
channel, std::move(arguments));
|
2019-04-02 22:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-14 18:57:36 +00:00
|
|
|
|
void WebContents::Invoke(
|
|
|
|
|
bool internal,
|
|
|
|
|
const std::string& channel,
|
|
|
|
|
blink::CloneableMessage arguments,
|
2022-03-19 02:50:05 +00:00
|
|
|
|
electron::mojom::ElectronApiIPC::InvokeCallback callback,
|
2020-12-14 18:57:36 +00:00
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
2019-12-06 21:15:23 +00:00
|
|
|
|
TRACE_EVENT1("electron", "WebContents::Invoke", "channel", channel);
|
2019-08-23 22:45:50 +00:00
|
|
|
|
// webContents.emit('-ipc-invoke', new Event(), internal, channel, arguments);
|
2020-12-14 18:57:36 +00:00
|
|
|
|
EmitWithSender("-ipc-invoke", render_frame_host, std::move(callback),
|
|
|
|
|
internal, channel, std::move(arguments));
|
2019-05-31 17:25:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-14 18:57:36 +00:00
|
|
|
|
void WebContents::OnFirstNonEmptyLayout(
|
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
2022-06-27 20:50:08 +00:00
|
|
|
|
if (render_frame_host == web_contents()->GetPrimaryMainFrame()) {
|
2020-09-28 20:36:45 +00:00
|
|
|
|
Emit("ready-to-show");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-10 22:00:20 +00:00
|
|
|
|
namespace {
|
|
|
|
|
|
2023-02-13 21:39:18 +00:00
|
|
|
|
// This object wraps the InvokeCallback so that if it gets GC'd by V8, we can
|
|
|
|
|
// still call the callback and send an error. Not doing so causes a Mojo DCHECK,
|
|
|
|
|
// since Mojo requires callbacks to be called before they are destroyed.
|
|
|
|
|
class ReplyChannel : public gin::Wrappable<ReplyChannel> {
|
|
|
|
|
public:
|
|
|
|
|
using InvokeCallback = electron::mojom::ElectronApiIPC::InvokeCallback;
|
|
|
|
|
static gin::Handle<ReplyChannel> Create(v8::Isolate* isolate,
|
|
|
|
|
InvokeCallback callback) {
|
|
|
|
|
return gin::CreateHandle(isolate, new ReplyChannel(std::move(callback)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// gin::Wrappable
|
|
|
|
|
static gin::WrapperInfo kWrapperInfo;
|
|
|
|
|
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
|
|
|
|
v8::Isolate* isolate) override {
|
|
|
|
|
return gin::Wrappable<ReplyChannel>::GetObjectTemplateBuilder(isolate)
|
|
|
|
|
.SetMethod("sendReply", &ReplyChannel::SendReply);
|
|
|
|
|
}
|
|
|
|
|
const char* GetTypeName() override { return "ReplyChannel"; }
|
|
|
|
|
|
2023-03-02 09:03:52 +00:00
|
|
|
|
void SendError(const std::string& msg) {
|
|
|
|
|
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
|
|
|
|
|
// If there's no current context, it means we're shutting down, so we
|
|
|
|
|
// don't need to send an event.
|
|
|
|
|
if (!isolate->GetCurrentContext().IsEmpty()) {
|
|
|
|
|
v8::HandleScope scope(isolate);
|
|
|
|
|
auto message = gin::DataObjectBuilder(isolate).Set("error", msg).Build();
|
|
|
|
|
SendReply(isolate, message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-13 21:39:18 +00:00
|
|
|
|
private:
|
|
|
|
|
explicit ReplyChannel(InvokeCallback callback)
|
|
|
|
|
: callback_(std::move(callback)) {}
|
|
|
|
|
~ReplyChannel() override {
|
2023-03-02 09:03:52 +00:00
|
|
|
|
if (callback_)
|
|
|
|
|
SendError("reply was never sent");
|
2023-02-13 21:39:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SendReply(v8::Isolate* isolate, v8::Local<v8::Value> arg) {
|
|
|
|
|
if (!callback_)
|
|
|
|
|
return false;
|
|
|
|
|
blink::CloneableMessage message;
|
|
|
|
|
if (!gin::ConvertFromV8(isolate, arg, &message)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::move(callback_).Run(std::move(message));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InvokeCallback callback_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
gin::WrapperInfo ReplyChannel::kWrapperInfo = {gin::kEmbedderNativeGin};
|
|
|
|
|
|
2024-06-10 22:00:20 +00:00
|
|
|
|
} // namespace
|
|
|
|
|
|
2023-02-13 21:39:18 +00:00
|
|
|
|
gin::Handle<gin_helper::internal::Event> WebContents::MakeEventWithSender(
|
|
|
|
|
v8::Isolate* isolate,
|
|
|
|
|
content::RenderFrameHost* frame,
|
|
|
|
|
electron::mojom::ElectronApiIPC::InvokeCallback callback) {
|
|
|
|
|
v8::Local<v8::Object> wrapper;
|
2023-03-02 09:03:52 +00:00
|
|
|
|
if (!GetWrapper(isolate).ToLocal(&wrapper)) {
|
|
|
|
|
if (callback) {
|
|
|
|
|
// We must always invoke the callback if present.
|
|
|
|
|
ReplyChannel::Create(isolate, std::move(callback))
|
|
|
|
|
->SendError("WebContents was destroyed");
|
|
|
|
|
}
|
2023-02-13 21:39:18 +00:00
|
|
|
|
return gin::Handle<gin_helper::internal::Event>();
|
2023-03-02 09:03:52 +00:00
|
|
|
|
}
|
2023-02-13 21:39:18 +00:00
|
|
|
|
gin::Handle<gin_helper::internal::Event> event =
|
|
|
|
|
gin_helper::internal::Event::New(isolate);
|
|
|
|
|
gin_helper::Dictionary dict(isolate, event.ToV8().As<v8::Object>());
|
|
|
|
|
if (callback)
|
|
|
|
|
dict.Set("_replyChannel",
|
|
|
|
|
ReplyChannel::Create(isolate, std::move(callback)));
|
|
|
|
|
if (frame) {
|
|
|
|
|
dict.Set("frameId", frame->GetRoutingID());
|
|
|
|
|
dict.Set("processId", frame->GetProcess()->GetID());
|
|
|
|
|
}
|
|
|
|
|
return event;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-14 18:57:36 +00:00
|
|
|
|
void WebContents::ReceivePostMessage(
|
|
|
|
|
const std::string& channel,
|
|
|
|
|
blink::TransferableMessage message,
|
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
2020-07-16 21:11:44 +00:00
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
2020-03-12 01:07:54 +00:00
|
|
|
|
auto wrapped_ports =
|
2020-07-16 21:11:44 +00:00
|
|
|
|
MessagePort::EntanglePorts(isolate, std::move(message.ports));
|
2020-03-12 01:07:54 +00:00
|
|
|
|
v8::Local<v8::Value> message_value =
|
2020-07-16 21:11:44 +00:00
|
|
|
|
electron::DeserializeV8Value(isolate, message);
|
2020-12-14 18:57:36 +00:00
|
|
|
|
EmitWithSender("-ipc-ports", render_frame_host,
|
2022-03-19 02:50:05 +00:00
|
|
|
|
electron::mojom::ElectronApiIPC::InvokeCallback(), false,
|
2020-12-14 18:57:36 +00:00
|
|
|
|
channel, message_value, std::move(wrapped_ports));
|
2020-03-12 01:07:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-14 18:57:36 +00:00
|
|
|
|
void WebContents::MessageSync(
|
|
|
|
|
bool internal,
|
|
|
|
|
const std::string& channel,
|
|
|
|
|
blink::CloneableMessage arguments,
|
2022-03-19 02:50:05 +00:00
|
|
|
|
electron::mojom::ElectronApiIPC::MessageSyncCallback callback,
|
2020-12-14 18:57:36 +00:00
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
2019-12-06 21:15:23 +00:00
|
|
|
|
TRACE_EVENT1("electron", "WebContents::MessageSync", "channel", channel);
|
2019-04-02 22:38:16 +00:00
|
|
|
|
// webContents.emit('-ipc-message-sync', new Event(sender, message), internal,
|
|
|
|
|
// channel, arguments);
|
2020-12-14 18:57:36 +00:00
|
|
|
|
EmitWithSender("-ipc-message-sync", render_frame_host, std::move(callback),
|
|
|
|
|
internal, channel, std::move(arguments));
|
2019-04-02 22:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-03 21:22:23 +00:00
|
|
|
|
void WebContents::MessageHost(const std::string& channel,
|
2020-12-14 18:57:36 +00:00
|
|
|
|
blink::CloneableMessage arguments,
|
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
2019-12-06 21:15:23 +00:00
|
|
|
|
TRACE_EVENT1("electron", "WebContents::MessageHost", "channel", channel);
|
2019-04-03 21:22:23 +00:00
|
|
|
|
// webContents.emit('ipc-message-host', new Event(), channel, args);
|
2020-12-14 18:57:36 +00:00
|
|
|
|
EmitWithSender("ipc-message-host", render_frame_host,
|
2022-03-19 02:50:05 +00:00
|
|
|
|
electron::mojom::ElectronApiIPC::InvokeCallback(), channel,
|
2020-12-14 18:57:36 +00:00
|
|
|
|
std::move(arguments));
|
2019-04-03 21:22:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-04-15 22:10:32 +00:00
|
|
|
|
void WebContents::DraggableRegionsChanged(
|
|
|
|
|
const std::vector<blink::mojom::DraggableRegionPtr>& regions,
|
|
|
|
|
content::WebContents* contents) {
|
|
|
|
|
if (owner_window() && owner_window()->has_frame()) {
|
2023-03-28 14:52:28 +00:00
|
|
|
|
return;
|
2024-04-15 22:10:32 +00:00
|
|
|
|
}
|
2023-03-28 14:52:28 +00:00
|
|
|
|
|
2022-11-07 18:15:57 +00:00
|
|
|
|
draggable_region_ = DraggableRegionsToSkRegion(regions);
|
2019-06-03 17:43:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 15:42:43 +00:00
|
|
|
|
void WebContents::DidStartNavigation(
|
|
|
|
|
content::NavigationHandle* navigation_handle) {
|
|
|
|
|
EmitNavigationEvent("did-start-navigation", navigation_handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DidRedirectNavigation(
|
|
|
|
|
content::NavigationHandle* navigation_handle) {
|
|
|
|
|
EmitNavigationEvent("did-redirect-navigation", navigation_handle);
|
2018-04-26 10:17:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-19 09:27:35 +00:00
|
|
|
|
void WebContents::ReadyToCommitNavigation(
|
|
|
|
|
content::NavigationHandle* navigation_handle) {
|
|
|
|
|
// Don't focus content in an inactive window.
|
|
|
|
|
if (!owner_window())
|
|
|
|
|
return;
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
2021-05-19 09:27:35 +00:00
|
|
|
|
if (!owner_window()->IsActive())
|
|
|
|
|
return;
|
|
|
|
|
#else
|
|
|
|
|
if (!owner_window()->widget()->IsActive())
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
// Don't focus content after subframe navigations.
|
|
|
|
|
if (!navigation_handle->IsInMainFrame())
|
|
|
|
|
return;
|
|
|
|
|
// Only focus for top-level contents.
|
|
|
|
|
if (type_ != Type::kBrowserWindow)
|
|
|
|
|
return;
|
|
|
|
|
web_contents()->SetInitialFocus();
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-14 00:19:28 +00:00
|
|
|
|
void WebContents::DidFinishNavigation(
|
|
|
|
|
content::NavigationHandle* navigation_handle) {
|
2021-07-01 19:25:40 +00:00
|
|
|
|
if (owner_window_) {
|
|
|
|
|
owner_window_->NotifyLayoutWindowControlsOverlay();
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-26 10:17:55 +00:00
|
|
|
|
if (!navigation_handle->HasCommitted())
|
|
|
|
|
return;
|
2016-07-14 00:19:28 +00:00
|
|
|
|
bool is_main_frame = navigation_handle->IsInMainFrame();
|
2018-04-26 10:17:55 +00:00
|
|
|
|
content::RenderFrameHost* frame_host =
|
2018-05-10 20:52:42 +00:00
|
|
|
|
navigation_handle->GetRenderFrameHost();
|
2018-04-26 10:17:55 +00:00
|
|
|
|
int frame_process_id = -1, frame_routing_id = -1;
|
|
|
|
|
if (frame_host) {
|
|
|
|
|
frame_process_id = frame_host->GetProcess()->GetID();
|
|
|
|
|
frame_routing_id = frame_host->GetRoutingID();
|
|
|
|
|
}
|
|
|
|
|
if (!navigation_handle->IsErrorPage()) {
|
2019-09-30 22:00:47 +00:00
|
|
|
|
// FIXME: All the Emit() calls below could potentially result in |this|
|
|
|
|
|
// being destroyed (by JS listening for the event and calling
|
|
|
|
|
// webContents.destroy()).
|
2016-07-14 00:19:28 +00:00
|
|
|
|
auto url = navigation_handle->GetURL();
|
2017-08-08 00:49:20 +00:00
|
|
|
|
bool is_same_document = navigation_handle->IsSameDocument();
|
2018-05-01 04:34:41 +00:00
|
|
|
|
if (is_same_document) {
|
2018-05-10 20:52:42 +00:00
|
|
|
|
Emit("did-navigate-in-page", url, is_main_frame, frame_process_id,
|
|
|
|
|
frame_routing_id);
|
2018-05-01 04:34:41 +00:00
|
|
|
|
} else {
|
2018-05-10 20:52:42 +00:00
|
|
|
|
const net::HttpResponseHeaders* http_response =
|
|
|
|
|
navigation_handle->GetResponseHeaders();
|
2018-05-01 04:34:41 +00:00
|
|
|
|
std::string http_status_text;
|
|
|
|
|
int http_response_code = -1;
|
|
|
|
|
if (http_response) {
|
|
|
|
|
http_status_text = http_response->GetStatusText();
|
|
|
|
|
http_response_code = http_response->response_code();
|
|
|
|
|
}
|
2018-05-10 20:52:42 +00:00
|
|
|
|
Emit("did-frame-navigate", url, http_response_code, http_status_text,
|
|
|
|
|
is_main_frame, frame_process_id, frame_routing_id);
|
2018-05-01 04:34:41 +00:00
|
|
|
|
if (is_main_frame) {
|
|
|
|
|
Emit("did-navigate", url, http_response_code, http_status_text);
|
|
|
|
|
}
|
2016-07-14 00:19:28 +00:00
|
|
|
|
}
|
2024-02-09 09:29:14 +00:00
|
|
|
|
if (is_guest())
|
2018-08-16 22:57:40 +00:00
|
|
|
|
Emit("load-commit", url, is_main_frame);
|
2016-07-14 00:19:28 +00:00
|
|
|
|
} else {
|
|
|
|
|
auto url = navigation_handle->GetURL();
|
|
|
|
|
int code = navigation_handle->GetNetErrorCode();
|
|
|
|
|
auto description = net::ErrorToShortString(code);
|
2018-05-10 20:52:42 +00:00
|
|
|
|
Emit("did-fail-provisional-load", code, description, url, is_main_frame,
|
|
|
|
|
frame_process_id, frame_routing_id);
|
2016-07-14 00:19:28 +00:00
|
|
|
|
|
|
|
|
|
// Do not emit "did-fail-load" for canceled requests.
|
2021-01-13 09:01:51 +00:00
|
|
|
|
if (code != net::ERR_ABORTED) {
|
|
|
|
|
EmitWarning(
|
|
|
|
|
node::Environment::GetCurrent(JavascriptEnvironment::GetIsolate()),
|
|
|
|
|
"Failed to load URL: " + url.possibly_invalid_spec() +
|
|
|
|
|
" with error: " + description,
|
|
|
|
|
"electron");
|
2018-05-10 20:52:42 +00:00
|
|
|
|
Emit("did-fail-load", code, description, url, is_main_frame,
|
|
|
|
|
frame_process_id, frame_routing_id);
|
2021-01-13 09:01:51 +00:00
|
|
|
|
}
|
2016-07-14 00:19:28 +00:00
|
|
|
|
}
|
2021-02-17 18:23:45 +00:00
|
|
|
|
content::NavigationEntry* entry = navigation_handle->GetNavigationEntry();
|
|
|
|
|
|
|
|
|
|
// This check is needed due to an issue in Chromium
|
|
|
|
|
// Check the Chromium issue to keep updated:
|
|
|
|
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=1178663
|
|
|
|
|
// If a history entry has been made and the forward/back call has been made,
|
|
|
|
|
// proceed with setting the new title
|
|
|
|
|
if (entry && (entry->GetTransitionType() & ui::PAGE_TRANSITION_FORWARD_BACK))
|
|
|
|
|
WebContents::TitleWasSet(entry);
|
2014-12-09 22:38:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-18 00:19:21 +00:00
|
|
|
|
void WebContents::TitleWasSet(content::NavigationEntry* entry) {
|
2021-03-16 16:18:45 +00:00
|
|
|
|
std::u16string final_title;
|
2017-12-24 12:42:23 +00:00
|
|
|
|
bool explicit_set = true;
|
|
|
|
|
if (entry) {
|
|
|
|
|
auto title = entry->GetTitle();
|
|
|
|
|
auto url = entry->GetURL();
|
|
|
|
|
if (url.SchemeIsFile() && title.empty()) {
|
|
|
|
|
final_title = base::UTF8ToUTF16(url.ExtractFileName());
|
|
|
|
|
explicit_set = false;
|
|
|
|
|
} else {
|
|
|
|
|
final_title = title;
|
|
|
|
|
}
|
2021-06-30 17:53:10 +00:00
|
|
|
|
} else {
|
|
|
|
|
final_title = web_contents()->GetTitle();
|
2017-12-18 00:19:21 +00:00
|
|
|
|
}
|
2020-02-11 00:37:46 +00:00
|
|
|
|
for (ExtendedWebContentsObserver& observer : observers_)
|
|
|
|
|
observer.OnPageTitleUpdated(final_title, explicit_set);
|
2017-12-18 07:54:44 +00:00
|
|
|
|
Emit("page-title-updated", final_title, explicit_set);
|
2015-04-05 09:20:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-17 19:55:31 +00:00
|
|
|
|
void WebContents::DidUpdateFaviconURL(
|
2020-06-22 17:35:10 +00:00
|
|
|
|
content::RenderFrameHost* render_frame_host,
|
2020-03-03 21:35:05 +00:00
|
|
|
|
const std::vector<blink::mojom::FaviconURLPtr>& urls) {
|
2015-04-17 19:55:31 +00:00
|
|
|
|
std::set<GURL> unique_urls;
|
2016-07-10 11:32:40 +00:00
|
|
|
|
for (const auto& iter : urls) {
|
2020-03-03 21:35:05 +00:00
|
|
|
|
if (iter->icon_type != blink::mojom::FaviconIconType::kFavicon)
|
2015-04-17 19:55:31 +00:00
|
|
|
|
continue;
|
2020-03-03 21:35:05 +00:00
|
|
|
|
const GURL& url = iter->icon_url;
|
2015-04-17 19:55:31 +00:00
|
|
|
|
if (url.is_valid())
|
|
|
|
|
unique_urls.insert(url);
|
|
|
|
|
}
|
2015-04-20 06:50:04 +00:00
|
|
|
|
Emit("page-favicon-updated", unique_urls);
|
2015-04-17 19:55:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-12 07:36:12 +00:00
|
|
|
|
void WebContents::DevToolsReloadPage() {
|
|
|
|
|
Emit("devtools-reload-page");
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-01 03:14:19 +00:00
|
|
|
|
void WebContents::DevToolsFocused() {
|
|
|
|
|
Emit("devtools-focused");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DevToolsOpened() {
|
2020-07-16 21:11:44 +00:00
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
2020-11-17 22:15:20 +00:00
|
|
|
|
DCHECK(inspectable_web_contents_);
|
2021-03-22 01:56:30 +00:00
|
|
|
|
DCHECK(inspectable_web_contents_->GetDevToolsWebContents());
|
2020-11-17 22:15:20 +00:00
|
|
|
|
auto handle = FromOrCreate(
|
|
|
|
|
isolate, inspectable_web_contents_->GetDevToolsWebContents());
|
2020-07-16 21:11:44 +00:00
|
|
|
|
devtools_web_contents_.Reset(isolate, handle.ToV8());
|
2015-10-01 03:14:19 +00:00
|
|
|
|
|
2016-05-26 10:29:39 +00:00
|
|
|
|
// Set inspected tabID.
|
2022-06-29 16:39:48 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction(
|
|
|
|
|
"DevToolsAPI", "setInspectedTabId", base::Value(ID()));
|
2016-05-26 10:29:39 +00:00
|
|
|
|
|
2017-12-01 02:11:37 +00:00
|
|
|
|
// Inherit owner window in devtools when it doesn't have one.
|
2020-11-17 22:15:20 +00:00
|
|
|
|
auto* devtools = inspectable_web_contents_->GetDevToolsWebContents();
|
2019-01-21 16:56:54 +00:00
|
|
|
|
bool has_window = devtools->GetUserData(NativeWindowRelay::UserDataKey());
|
2017-12-01 02:11:37 +00:00
|
|
|
|
if (owner_window() && !has_window)
|
2017-11-30 07:37:26 +00:00
|
|
|
|
handle->SetOwnerWindow(devtools, owner_window());
|
2015-10-01 06:41:01 +00:00
|
|
|
|
|
2015-10-01 03:14:19 +00:00
|
|
|
|
Emit("devtools-opened");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DevToolsClosed() {
|
2020-07-16 21:11:44 +00:00
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
2015-10-01 03:14:19 +00:00
|
|
|
|
devtools_web_contents_.Reset();
|
|
|
|
|
|
|
|
|
|
Emit("devtools-closed");
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-09 21:54:04 +00:00
|
|
|
|
void WebContents::DevToolsResized() {
|
|
|
|
|
for (ExtendedWebContentsObserver& observer : observers_)
|
|
|
|
|
observer.OnDevToolsResized();
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
void WebContents::SetOwnerWindow(NativeWindow* owner_window) {
|
|
|
|
|
SetOwnerWindow(GetWebContents(), owner_window);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-10 22:23:35 +00:00
|
|
|
|
void WebContents::SetOwnerBaseWindow(std::optional<BaseWindow*> owner_window) {
|
2023-12-13 21:01:03 +00:00
|
|
|
|
SetOwnerWindow(GetWebContents(),
|
|
|
|
|
owner_window ? (*owner_window)->window() : nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
void WebContents::SetOwnerWindow(content::WebContents* web_contents,
|
|
|
|
|
NativeWindow* owner_window) {
|
2023-09-26 20:00:46 +00:00
|
|
|
|
if (owner_window_) {
|
|
|
|
|
owner_window_->RemoveBackgroundThrottlingSource(this);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
if (owner_window) {
|
|
|
|
|
owner_window_ = owner_window->GetWeakPtr();
|
|
|
|
|
NativeWindowRelay::CreateForWebContents(web_contents,
|
|
|
|
|
owner_window->GetWeakPtr());
|
2023-09-26 20:00:46 +00:00
|
|
|
|
owner_window_->AddBackgroundThrottlingSource(this);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
} else {
|
|
|
|
|
owner_window_ = nullptr;
|
|
|
|
|
web_contents->RemoveUserData(NativeWindowRelay::UserDataKey());
|
|
|
|
|
}
|
|
|
|
|
auto* osr_wcv = GetOffScreenWebContentsView();
|
|
|
|
|
if (osr_wcv)
|
|
|
|
|
osr_wcv->SetNativeWindow(owner_window);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
content::WebContents* WebContents::GetWebContents() const {
|
2020-11-17 22:15:20 +00:00
|
|
|
|
if (!inspectable_web_contents_)
|
2020-11-10 17:06:56 +00:00
|
|
|
|
return nullptr;
|
2020-11-17 22:15:20 +00:00
|
|
|
|
return inspectable_web_contents_->GetWebContents();
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
content::WebContents* WebContents::GetDevToolsWebContents() const {
|
2020-11-17 22:15:20 +00:00
|
|
|
|
if (!inspectable_web_contents_)
|
2020-11-10 17:06:56 +00:00
|
|
|
|
return nullptr;
|
2020-11-17 22:15:20 +00:00
|
|
|
|
return inspectable_web_contents_->GetDevToolsWebContents();
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-15 22:43:25 +00:00
|
|
|
|
void WebContents::WebContentsDestroyed() {
|
|
|
|
|
// Clear the pointer stored in wrapper.
|
2020-07-30 16:17:57 +00:00
|
|
|
|
if (GetAllWebContents().Lookup(id_))
|
|
|
|
|
GetAllWebContents().Remove(id_);
|
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope scope(isolate);
|
|
|
|
|
v8::Local<v8::Object> wrapper;
|
|
|
|
|
if (!GetWrapper(isolate).ToLocal(&wrapper))
|
|
|
|
|
return;
|
|
|
|
|
wrapper->SetAlignedPointerInInternalField(0, nullptr);
|
2016-01-12 13:10:24 +00:00
|
|
|
|
|
2021-10-11 00:33:35 +00:00
|
|
|
|
// Tell WebViewGuestDelegate that the WebContents has been destroyed.
|
|
|
|
|
if (guest_delegate_)
|
|
|
|
|
guest_delegate_->WillDestroy();
|
|
|
|
|
|
2021-03-15 22:43:25 +00:00
|
|
|
|
Observe(nullptr);
|
2016-01-12 13:10:24 +00:00
|
|
|
|
Emit("destroyed");
|
2014-04-25 03:22:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-05 14:39:27 +00:00
|
|
|
|
void WebContents::NavigationEntryCommitted(
|
2015-05-11 05:51:52 +00:00
|
|
|
|
const content::LoadCommittedDetails& details) {
|
2020-01-29 09:42:25 +00:00
|
|
|
|
Emit("navigation-entry-committed", details.entry->GetURL(),
|
2017-08-08 00:49:20 +00:00
|
|
|
|
details.is_same_document, details.did_replace_entry);
|
2015-03-05 14:39:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-14 13:11:45 +00:00
|
|
|
|
bool WebContents::GetBackgroundThrottling() const {
|
|
|
|
|
return background_throttling_;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-19 00:32:22 +00:00
|
|
|
|
void WebContents::SetBackgroundThrottling(bool allowed) {
|
|
|
|
|
background_throttling_ = allowed;
|
|
|
|
|
|
2023-09-26 20:00:46 +00:00
|
|
|
|
if (owner_window_) {
|
|
|
|
|
owner_window_->UpdateBackgroundThrottlingState();
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-27 20:50:08 +00:00
|
|
|
|
auto* rfh = web_contents()->GetPrimaryMainFrame();
|
2019-12-02 18:29:03 +00:00
|
|
|
|
if (!rfh)
|
2018-10-19 00:32:22 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2019-12-02 18:29:03 +00:00
|
|
|
|
auto* rwhv = rfh->GetView();
|
|
|
|
|
if (!rwhv)
|
2018-10-19 00:32:22 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2019-12-02 18:29:03 +00:00
|
|
|
|
auto* rwh_impl =
|
|
|
|
|
static_cast<content::RenderWidgetHostImpl*>(rwhv->GetRenderWidgetHost());
|
|
|
|
|
if (!rwh_impl)
|
2018-10-19 00:32:22 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2019-12-02 18:29:03 +00:00
|
|
|
|
rwh_impl->disable_hidden_ = !background_throttling_;
|
|
|
|
|
web_contents()->GetRenderViewHost()->SetSchedulerThrottling(allowed);
|
2018-10-19 00:32:22 +00:00
|
|
|
|
|
2019-12-02 18:29:03 +00:00
|
|
|
|
if (rwh_impl->is_hidden()) {
|
2020-09-21 08:00:36 +00:00
|
|
|
|
rwh_impl->WasShown({});
|
2018-10-19 00:32:22 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-06 01:28:40 +00:00
|
|
|
|
int WebContents::GetProcessID() const {
|
2022-06-27 20:50:08 +00:00
|
|
|
|
return web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID();
|
2015-06-23 08:16:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-15 20:29:34 +00:00
|
|
|
|
base::ProcessId WebContents::GetOSProcessID() const {
|
2022-06-27 20:50:08 +00:00
|
|
|
|
base::ProcessHandle process_handle = web_contents()
|
|
|
|
|
->GetPrimaryMainFrame()
|
|
|
|
|
->GetProcess()
|
|
|
|
|
->GetProcess()
|
|
|
|
|
.Handle();
|
2017-04-18 10:31:20 +00:00
|
|
|
|
return base::GetProcId(process_handle);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-23 08:16:10 +00:00
|
|
|
|
bool WebContents::Equal(const WebContents* web_contents) const {
|
2018-07-23 09:08:36 +00:00
|
|
|
|
return ID() == web_contents->ID();
|
2015-06-23 08:16:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 23:11:18 +00:00
|
|
|
|
GURL WebContents::GetURL() const {
|
|
|
|
|
return web_contents()->GetLastCommittedURL();
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
void WebContents::LoadURL(const GURL& url,
|
|
|
|
|
const gin_helper::Dictionary& options) {
|
2017-01-21 09:29:20 +00:00
|
|
|
|
if (!url.is_valid() || url.spec().size() > url::kMaxURLChars) {
|
2018-04-18 01:55:30 +00:00
|
|
|
|
Emit("did-fail-load", static_cast<int>(net::ERR_INVALID_URL),
|
2016-02-11 02:54:50 +00:00
|
|
|
|
net::ErrorToShortString(net::ERR_INVALID_URL),
|
2018-04-18 01:55:30 +00:00
|
|
|
|
url.possibly_invalid_spec(), true);
|
2016-02-11 02:54:50 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-25 04:52:30 +00:00
|
|
|
|
content::NavigationController::LoadURLParams params(url);
|
2014-11-06 19:29:41 +00:00
|
|
|
|
|
2018-04-05 23:13:24 +00:00
|
|
|
|
if (!options.Get("httpReferrer", ¶ms.referrer)) {
|
|
|
|
|
GURL http_referrer;
|
|
|
|
|
if (options.Get("httpReferrer", &http_referrer))
|
2019-01-09 20:13:49 +00:00
|
|
|
|
params.referrer =
|
|
|
|
|
content::Referrer(http_referrer.GetAsReferrer(),
|
|
|
|
|
network::mojom::ReferrerPolicy::kDefault);
|
2018-04-05 23:13:24 +00:00
|
|
|
|
}
|
2014-11-06 19:29:41 +00:00
|
|
|
|
|
2015-05-06 04:01:41 +00:00
|
|
|
|
std::string user_agent;
|
2015-06-09 01:27:57 +00:00
|
|
|
|
if (options.Get("userAgent", &user_agent))
|
2022-06-13 16:35:42 +00:00
|
|
|
|
SetUserAgent(user_agent);
|
2015-05-06 04:01:41 +00:00
|
|
|
|
|
2015-10-26 21:18:16 +00:00
|
|
|
|
std::string extra_headers;
|
|
|
|
|
if (options.Get("extraHeaders", &extra_headers))
|
|
|
|
|
params.extra_headers = extra_headers;
|
|
|
|
|
|
2018-04-11 08:42:14 +00:00
|
|
|
|
scoped_refptr<network::ResourceRequestBody> body;
|
2016-10-09 23:30:38 +00:00
|
|
|
|
if (options.Get("postData", &body)) {
|
|
|
|
|
params.post_data = body;
|
|
|
|
|
params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-01 00:49:03 +00:00
|
|
|
|
GURL base_url_for_data_url;
|
|
|
|
|
if (options.Get("baseURLForDataURL", &base_url_for_data_url)) {
|
|
|
|
|
params.base_url_for_data_url = base_url_for_data_url;
|
|
|
|
|
params.load_type = content::NavigationController::LOAD_TYPE_DATA;
|
|
|
|
|
}
|
2017-03-02 18:50:48 +00:00
|
|
|
|
|
2019-11-25 19:12:58 +00:00
|
|
|
|
bool reload_ignoring_cache = false;
|
|
|
|
|
if (options.Get("reloadIgnoringCache", &reload_ignoring_cache) &&
|
|
|
|
|
reload_ignoring_cache) {
|
|
|
|
|
params.reload_type = content::ReloadType::BYPASSING_CACHE;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-30 22:00:47 +00:00
|
|
|
|
// Calling LoadURLWithParams() can trigger JS which destroys |this|.
|
|
|
|
|
auto weak_this = GetWeakPtr();
|
|
|
|
|
|
2021-06-02 00:17:15 +00:00
|
|
|
|
params.transition_type = ui::PageTransitionFromInt(
|
|
|
|
|
ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
|
2014-04-25 04:52:30 +00:00
|
|
|
|
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
|
2023-10-10 10:46:04 +00:00
|
|
|
|
|
|
|
|
|
// It's not safe to start a new navigation or otherwise discard the current
|
|
|
|
|
// one while the call that started it is still on the stack. See
|
|
|
|
|
// http://crbug.com/347742.
|
|
|
|
|
auto& ctrl_impl = static_cast<content::NavigationControllerImpl&>(
|
|
|
|
|
web_contents()->GetController());
|
|
|
|
|
if (ctrl_impl.in_navigate_to_pending_entry()) {
|
|
|
|
|
Emit("did-fail-load", static_cast<int>(net::ERR_FAILED),
|
|
|
|
|
net::ErrorToShortString(net::ERR_FAILED), url.possibly_invalid_spec(),
|
|
|
|
|
true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Discard non-committed entries to ensure we don't re-use a pending entry.
|
2019-03-28 18:13:05 +00:00
|
|
|
|
web_contents()->GetController().DiscardNonCommittedEntries();
|
2017-02-19 20:43:17 +00:00
|
|
|
|
web_contents()->GetController().LoadURLWithParams(params);
|
2017-04-07 17:34:14 +00:00
|
|
|
|
|
2019-09-30 22:00:47 +00:00
|
|
|
|
// ⚠️WARNING!⚠️
|
|
|
|
|
// LoadURLWithParams() triggers JS events which can call destroy() on |this|.
|
|
|
|
|
// It's not safe to assume that |this| points to valid memory at this point.
|
2021-03-02 17:38:56 +00:00
|
|
|
|
if (!weak_this || !web_contents())
|
2019-09-30 22:00:47 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2021-02-09 20:16:21 +00:00
|
|
|
|
// Required to make beforeunload handler work.
|
|
|
|
|
NotifyUserActivation();
|
2014-04-25 04:52:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 23:11:18 +00:00
|
|
|
|
// TODO(MarshallOfSound): Figure out what we need to do with post data here, I
|
|
|
|
|
// believe the default behavior when we pass "true" is to phone out to the
|
|
|
|
|
// delegate and then the controller expects this method to be called again with
|
|
|
|
|
// "false" if the user approves the reload. For now this would result in
|
|
|
|
|
// ".reload()" calls on POST data domains failing silently. Passing false would
|
|
|
|
|
// result in them succeeding, but reposting which although more correct could be
|
|
|
|
|
// considering a breaking change.
|
|
|
|
|
void WebContents::Reload() {
|
|
|
|
|
web_contents()->GetController().Reload(content::ReloadType::NORMAL,
|
|
|
|
|
/* check_for_repost */ true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::ReloadIgnoringCache() {
|
|
|
|
|
web_contents()->GetController().Reload(content::ReloadType::BYPASSING_CACHE,
|
|
|
|
|
/* check_for_repost */ true);
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-17 12:17:55 +00:00
|
|
|
|
void WebContents::DownloadURL(const GURL& url, gin::Arguments* args) {
|
|
|
|
|
std::map<std::string, std::string> headers;
|
|
|
|
|
gin_helper::Dictionary options;
|
|
|
|
|
if (args->GetNext(&options)) {
|
|
|
|
|
if (options.Has("headers") && !options.Get("headers", &headers)) {
|
|
|
|
|
args->ThrowTypeError("Invalid value for headers - must be an object");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-12 07:30:51 +00:00
|
|
|
|
std::unique_ptr<download::DownloadUrlParameters> download_params(
|
|
|
|
|
content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
|
2019-07-03 21:48:55 +00:00
|
|
|
|
web_contents(), url, MISSING_TRAFFIC_ANNOTATION));
|
2023-08-17 12:17:55 +00:00
|
|
|
|
for (const auto& [name, value] : headers) {
|
|
|
|
|
download_params->add_request_header(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto* download_manager =
|
|
|
|
|
web_contents()->GetBrowserContext()->GetDownloadManager();
|
2018-04-12 07:30:51 +00:00
|
|
|
|
download_manager->DownloadUrl(std::move(download_params));
|
2015-12-02 21:49:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-16 16:18:45 +00:00
|
|
|
|
std::u16string WebContents::GetTitle() const {
|
2014-04-25 05:10:16 +00:00
|
|
|
|
return web_contents()->GetTitle();
|
2014-04-24 09:00:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::IsLoading() const {
|
2014-04-25 05:10:16 +00:00
|
|
|
|
return web_contents()->IsLoading();
|
2014-04-24 09:00:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-18 17:37:08 +00:00
|
|
|
|
bool WebContents::IsLoadingMainFrame() const {
|
2021-11-24 08:45:59 +00:00
|
|
|
|
return web_contents()->ShouldShowLoadingUI();
|
2016-04-18 17:37:08 +00:00
|
|
|
|
}
|
2014-04-24 09:00:41 +00:00
|
|
|
|
|
|
|
|
|
bool WebContents::IsWaitingForResponse() const {
|
2014-04-25 05:10:16 +00:00
|
|
|
|
return web_contents()->IsWaitingForResponse();
|
2014-04-24 09:00:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::Stop() {
|
2014-04-25 05:10:16 +00:00
|
|
|
|
web_contents()->Stop();
|
2014-04-24 09:00:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 23:11:18 +00:00
|
|
|
|
bool WebContents::CanGoBack() const {
|
|
|
|
|
return web_contents()->GetController().CanGoBack();
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-11 06:30:26 +00:00
|
|
|
|
void WebContents::GoBack() {
|
2021-04-27 23:11:18 +00:00
|
|
|
|
if (CanGoBack())
|
|
|
|
|
web_contents()->GetController().GoBack();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::CanGoForward() const {
|
|
|
|
|
return web_contents()->GetController().CanGoForward();
|
2015-05-11 06:30:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::GoForward() {
|
2021-04-27 23:11:18 +00:00
|
|
|
|
if (CanGoForward())
|
|
|
|
|
web_contents()->GetController().GoForward();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::CanGoToOffset(int offset) const {
|
|
|
|
|
return web_contents()->GetController().CanGoToOffset(offset);
|
2015-05-11 06:30:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-11 08:44:01 +00:00
|
|
|
|
void WebContents::GoToOffset(int offset) {
|
2021-04-27 23:11:18 +00:00
|
|
|
|
if (CanGoToOffset(offset))
|
|
|
|
|
web_contents()->GetController().GoToOffset(offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::CanGoToIndex(int index) const {
|
|
|
|
|
return index >= 0 && index < GetHistoryLength();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::GoToIndex(int index) {
|
|
|
|
|
if (CanGoToIndex(index))
|
|
|
|
|
web_contents()->GetController().GoToIndex(index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int WebContents::GetActiveIndex() const {
|
|
|
|
|
return web_contents()->GetController().GetCurrentEntryIndex();
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-21 21:59:23 +00:00
|
|
|
|
content::NavigationEntry* WebContents::GetNavigationEntryAtIndex(
|
|
|
|
|
int index) const {
|
|
|
|
|
return web_contents()->GetController().GetEntryAtIndex(index);
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-19 19:46:04 +00:00
|
|
|
|
bool WebContents::RemoveNavigationEntryAtIndex(int index) {
|
|
|
|
|
if (!CanGoToIndex(index))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return web_contents()->GetController().RemoveEntryAtIndex(index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<content::NavigationEntry*> WebContents::GetHistory() const {
|
|
|
|
|
const int history_length = GetHistoryLength();
|
|
|
|
|
auto& controller = web_contents()->GetController();
|
|
|
|
|
|
|
|
|
|
// If the history is empty, it contains only one entry and that is
|
|
|
|
|
// "InitialEntry"
|
|
|
|
|
if (history_length == 1 && controller.GetEntryAtIndex(0)->IsInitialEntry())
|
|
|
|
|
return std::vector<content::NavigationEntry*>();
|
|
|
|
|
|
|
|
|
|
std::vector<content::NavigationEntry*> history;
|
|
|
|
|
history.reserve(history_length);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < history_length; i++)
|
|
|
|
|
history.push_back(controller.GetEntryAtIndex(i));
|
|
|
|
|
|
|
|
|
|
return history;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 23:11:18 +00:00
|
|
|
|
void WebContents::ClearHistory() {
|
|
|
|
|
// In some rare cases (normally while there is no real history) we are in a
|
|
|
|
|
// state where we can't prune navigation entries
|
|
|
|
|
if (web_contents()->GetController().CanPruneAllButLastCommitted()) {
|
|
|
|
|
web_contents()->GetController().PruneAllButLastCommitted();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int WebContents::GetHistoryLength() const {
|
|
|
|
|
return web_contents()->GetController().GetEntryCount();
|
2015-05-11 08:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-09 03:06:26 +00:00
|
|
|
|
const std::string WebContents::GetWebRTCIPHandlingPolicy() const {
|
2018-04-18 01:55:30 +00:00
|
|
|
|
return web_contents()->GetMutableRendererPrefs()->webrtc_ip_handling_policy;
|
2017-03-08 14:55:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::SetWebRTCIPHandlingPolicy(
|
2017-03-09 03:06:26 +00:00
|
|
|
|
const std::string& webrtc_ip_handling_policy) {
|
2017-03-08 14:55:59 +00:00
|
|
|
|
if (GetWebRTCIPHandlingPolicy() == webrtc_ip_handling_policy)
|
|
|
|
|
return;
|
|
|
|
|
web_contents()->GetMutableRendererPrefs()->webrtc_ip_handling_policy =
|
2018-04-18 01:55:30 +00:00
|
|
|
|
webrtc_ip_handling_policy;
|
2017-03-08 14:55:59 +00:00
|
|
|
|
|
2019-10-28 22:12:35 +00:00
|
|
|
|
web_contents()->SyncRendererPrefs();
|
2017-03-08 14:55:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-24 21:21:22 +00:00
|
|
|
|
v8::Local<v8::Value> WebContents::GetWebRTCUDPPortRange(
|
|
|
|
|
v8::Isolate* isolate) const {
|
|
|
|
|
auto* prefs = web_contents()->GetMutableRendererPrefs();
|
|
|
|
|
|
2023-10-10 10:45:44 +00:00
|
|
|
|
auto dict = gin_helper::Dictionary::CreateEmpty(isolate);
|
2023-08-24 21:21:22 +00:00
|
|
|
|
dict.Set("min", static_cast<uint32_t>(prefs->webrtc_udp_min_port));
|
|
|
|
|
dict.Set("max", static_cast<uint32_t>(prefs->webrtc_udp_max_port));
|
|
|
|
|
return dict.GetHandle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::SetWebRTCUDPPortRange(gin::Arguments* args) {
|
|
|
|
|
uint32_t min = 0, max = 0;
|
|
|
|
|
gin_helper::Dictionary range;
|
|
|
|
|
|
|
|
|
|
if (!args->GetNext(&range) || !range.Get("min", &min) ||
|
|
|
|
|
!range.Get("max", &max)) {
|
|
|
|
|
gin_helper::ErrorThrower(args->isolate())
|
|
|
|
|
.ThrowError("'min' and 'max' are both required");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((0 == min && 0 != max) || max > UINT16_MAX) {
|
|
|
|
|
gin_helper::ErrorThrower(args->isolate())
|
|
|
|
|
.ThrowError(
|
|
|
|
|
"'min' and 'max' must be in the (0, 65535] range or [0, 0]");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (min > max) {
|
|
|
|
|
gin_helper::ErrorThrower(args->isolate())
|
|
|
|
|
.ThrowError("'max' must be greater than or equal to 'min'");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto* prefs = web_contents()->GetMutableRendererPrefs();
|
|
|
|
|
|
|
|
|
|
if (prefs->webrtc_udp_min_port == static_cast<uint16_t>(min) &&
|
|
|
|
|
prefs->webrtc_udp_max_port == static_cast<uint16_t>(max)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prefs->webrtc_udp_min_port = min;
|
|
|
|
|
prefs->webrtc_udp_max_port = max;
|
|
|
|
|
|
|
|
|
|
web_contents()->SyncRendererPrefs();
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-26 00:03:59 +00:00
|
|
|
|
std::string WebContents::GetMediaSourceID(
|
|
|
|
|
content::WebContents* request_web_contents) {
|
2022-06-27 20:50:08 +00:00
|
|
|
|
auto* frame_host = web_contents()->GetPrimaryMainFrame();
|
2021-10-26 00:03:59 +00:00
|
|
|
|
if (!frame_host)
|
|
|
|
|
return std::string();
|
|
|
|
|
|
|
|
|
|
content::DesktopMediaID media_id(
|
|
|
|
|
content::DesktopMediaID::TYPE_WEB_CONTENTS,
|
|
|
|
|
content::DesktopMediaID::kNullId,
|
|
|
|
|
content::WebContentsMediaCaptureId(frame_host->GetProcess()->GetID(),
|
|
|
|
|
frame_host->GetRoutingID()));
|
|
|
|
|
|
2022-06-27 20:50:08 +00:00
|
|
|
|
auto* request_frame_host = request_web_contents->GetPrimaryMainFrame();
|
2021-10-26 00:03:59 +00:00
|
|
|
|
if (!request_frame_host)
|
|
|
|
|
return std::string();
|
|
|
|
|
|
|
|
|
|
std::string id =
|
|
|
|
|
content::DesktopStreamsRegistry::GetInstance()->RegisterStream(
|
|
|
|
|
request_frame_host->GetProcess()->GetID(),
|
|
|
|
|
request_frame_host->GetRoutingID(),
|
2021-11-24 08:45:59 +00:00
|
|
|
|
url::Origin::Create(request_frame_host->GetLastCommittedURL()
|
|
|
|
|
.DeprecatedGetOriginAsURL()),
|
2023-05-23 19:58:58 +00:00
|
|
|
|
media_id, content::kRegistryStreamTypeTab);
|
2021-10-26 00:03:59 +00:00
|
|
|
|
|
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-24 09:00:41 +00:00
|
|
|
|
bool WebContents::IsCrashed() const {
|
2014-04-25 05:10:16 +00:00
|
|
|
|
return web_contents()->IsCrashed();
|
2014-04-24 09:00:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-02 21:50:24 +00:00
|
|
|
|
void WebContents::ForcefullyCrashRenderer() {
|
|
|
|
|
content::RenderWidgetHostView* view =
|
|
|
|
|
web_contents()->GetRenderWidgetHostView();
|
|
|
|
|
if (!view)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
content::RenderWidgetHost* rwh = view->GetRenderWidgetHost();
|
|
|
|
|
if (!rwh)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
content::RenderProcessHost* rph = rwh->GetProcess();
|
|
|
|
|
if (rph) {
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
2020-10-02 21:50:24 +00:00
|
|
|
|
// A generic |CrashDumpHungChildProcess()| is not implemented for Linux.
|
|
|
|
|
// Instead we send an explicit IPC to crash on the renderer's IO thread.
|
|
|
|
|
rph->ForceCrash();
|
|
|
|
|
#else
|
|
|
|
|
// Try to generate a crash report for the hung process.
|
2022-11-14 20:46:52 +00:00
|
|
|
|
#if !IS_MAS_BUILD()
|
2020-10-02 21:50:24 +00:00
|
|
|
|
CrashDumpHungChildProcess(rph->GetProcess().Handle());
|
2020-11-16 17:47:09 +00:00
|
|
|
|
#endif
|
2020-10-02 21:50:24 +00:00
|
|
|
|
rph->Shutdown(content::RESULT_CODE_HUNG);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-20 18:07:02 +00:00
|
|
|
|
void WebContents::SetUserAgent(const std::string& user_agent) {
|
2022-06-13 16:35:42 +00:00
|
|
|
|
blink::UserAgentOverride ua_override;
|
|
|
|
|
ua_override.ua_string_override = user_agent;
|
|
|
|
|
if (!user_agent.empty())
|
|
|
|
|
ua_override.ua_metadata_override = embedder_support::GetUserAgentMetadata();
|
|
|
|
|
|
|
|
|
|
web_contents()->SetUserAgentOverride(ua_override, false);
|
2014-10-24 12:57:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-22 04:25:10 +00:00
|
|
|
|
std::string WebContents::GetUserAgent() {
|
2020-04-13 23:39:26 +00:00
|
|
|
|
return web_contents()->GetUserAgentOverride().ua_string_override;
|
2015-07-22 04:25:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-14 17:03:28 +00:00
|
|
|
|
v8::Local<v8::Promise> WebContents::SavePage(
|
|
|
|
|
const base::FilePath& full_file_path,
|
|
|
|
|
const content::SavePageType& save_type) {
|
2020-07-16 21:11:44 +00:00
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
gin_helper::Promise<void> promise(isolate);
|
2019-03-13 21:30:21 +00:00
|
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
2019-02-14 17:03:28 +00:00
|
|
|
|
|
2022-02-07 08:51:59 +00:00
|
|
|
|
if (!full_file_path.IsAbsolute()) {
|
|
|
|
|
promise.RejectWithErrorMessage("Path must be absolute");
|
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-21 12:32:44 +00:00
|
|
|
|
auto* handler = new SavePageHandler(web_contents(), std::move(promise));
|
|
|
|
|
handler->Handle(full_file_path, save_type);
|
2019-03-13 21:30:21 +00:00
|
|
|
|
|
|
|
|
|
return handle;
|
2015-10-14 04:41:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-20 18:07:02 +00:00
|
|
|
|
void WebContents::OpenDevTools(gin::Arguments* args) {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2015-06-05 07:41:03 +00:00
|
|
|
|
return;
|
2015-06-24 14:23:38 +00:00
|
|
|
|
|
2016-09-07 02:16:52 +00:00
|
|
|
|
if (!enable_devtools_)
|
2016-09-05 08:27:56 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2016-04-19 12:42:05 +00:00
|
|
|
|
std::string state;
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kWebView || type_ == Type::kBackgroundPage ||
|
2020-09-08 11:55:40 +00:00
|
|
|
|
!owner_window()) {
|
2016-04-19 12:42:05 +00:00
|
|
|
|
state = "detach";
|
2017-12-01 02:11:37 +00:00
|
|
|
|
}
|
2020-09-08 11:55:40 +00:00
|
|
|
|
|
2022-09-22 08:44:27 +00:00
|
|
|
|
bool activate = true;
|
2023-08-15 05:32:53 +00:00
|
|
|
|
std::string title;
|
2022-09-22 08:44:27 +00:00
|
|
|
|
if (args && args->Length() == 1) {
|
|
|
|
|
gin_helper::Dictionary options;
|
|
|
|
|
if (args->GetNext(&options)) {
|
|
|
|
|
options.Get("mode", &state);
|
|
|
|
|
options.Get("activate", &activate);
|
2023-08-15 05:32:53 +00:00
|
|
|
|
options.Get("title", &title);
|
2022-09-22 08:44:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-17 22:15:20 +00:00
|
|
|
|
DCHECK(inspectable_web_contents_);
|
|
|
|
|
inspectable_web_contents_->SetDockState(state);
|
2023-08-15 05:32:53 +00:00
|
|
|
|
inspectable_web_contents_->SetDevToolsTitle(base::UTF8ToUTF16(title));
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->ShowDevTools(activate);
|
2014-11-02 14:34:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-11-03 14:12:56 +00:00
|
|
|
|
void WebContents::CloseDevTools() {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2015-06-05 07:41:03 +00:00
|
|
|
|
return;
|
2015-06-24 14:23:38 +00:00
|
|
|
|
|
2020-11-17 22:15:20 +00:00
|
|
|
|
DCHECK(inspectable_web_contents_);
|
|
|
|
|
inspectable_web_contents_->CloseDevTools();
|
2014-11-03 14:12:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::IsDevToolsOpened() {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2015-06-05 07:41:03 +00:00
|
|
|
|
return false;
|
2015-06-25 06:32:38 +00:00
|
|
|
|
|
2020-11-17 22:15:20 +00:00
|
|
|
|
DCHECK(inspectable_web_contents_);
|
|
|
|
|
return inspectable_web_contents_->IsDevToolsViewShowing();
|
2014-11-03 14:12:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-15 05:32:53 +00:00
|
|
|
|
std::u16string WebContents::GetDevToolsTitle() {
|
|
|
|
|
if (type_ == Type::kRemote)
|
|
|
|
|
return std::u16string();
|
|
|
|
|
|
|
|
|
|
DCHECK(inspectable_web_contents_);
|
|
|
|
|
return inspectable_web_contents_->GetDevToolsTitle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::SetDevToolsTitle(const std::u16string& title) {
|
|
|
|
|
inspectable_web_contents_->SetDevToolsTitle(title);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-01 05:11:21 +00:00
|
|
|
|
bool WebContents::IsDevToolsFocused() {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2016-01-01 05:11:21 +00:00
|
|
|
|
return false;
|
2016-01-01 09:45:03 +00:00
|
|
|
|
|
2020-11-17 22:15:20 +00:00
|
|
|
|
DCHECK(inspectable_web_contents_);
|
|
|
|
|
return inspectable_web_contents_->GetView()->IsDevToolsViewFocused();
|
2016-01-01 05:11:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-09-18 03:06:38 +00:00
|
|
|
|
void WebContents::EnableDeviceEmulation(
|
2020-08-12 18:33:58 +00:00
|
|
|
|
const blink::DeviceEmulationParams& params) {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2015-08-31 09:19:19 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2020-09-08 11:55:40 +00:00
|
|
|
|
DCHECK(web_contents());
|
2022-06-27 20:50:08 +00:00
|
|
|
|
auto* frame_host = web_contents()->GetPrimaryMainFrame();
|
2017-12-30 16:25:09 +00:00
|
|
|
|
if (frame_host) {
|
2021-05-24 02:32:55 +00:00
|
|
|
|
auto* widget_host_impl = static_cast<content::RenderWidgetHostImpl*>(
|
|
|
|
|
frame_host->GetView()->GetRenderWidgetHost());
|
2020-08-12 18:33:58 +00:00
|
|
|
|
if (widget_host_impl) {
|
|
|
|
|
auto& frame_widget = widget_host_impl->GetAssociatedFrameWidget();
|
|
|
|
|
frame_widget->EnableDeviceEmulation(params);
|
|
|
|
|
}
|
2017-12-30 16:25:09 +00:00
|
|
|
|
}
|
2015-08-31 09:19:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DisableDeviceEmulation() {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2015-08-31 09:19:19 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2020-09-08 11:55:40 +00:00
|
|
|
|
DCHECK(web_contents());
|
2022-06-27 20:50:08 +00:00
|
|
|
|
auto* frame_host = web_contents()->GetPrimaryMainFrame();
|
2017-12-30 16:25:09 +00:00
|
|
|
|
if (frame_host) {
|
2021-05-24 02:32:55 +00:00
|
|
|
|
auto* widget_host_impl = static_cast<content::RenderWidgetHostImpl*>(
|
|
|
|
|
frame_host->GetView()->GetRenderWidgetHost());
|
2020-08-12 18:33:58 +00:00
|
|
|
|
if (widget_host_impl) {
|
|
|
|
|
auto& frame_widget = widget_host_impl->GetAssociatedFrameWidget();
|
|
|
|
|
frame_widget->DisableDeviceEmulation();
|
|
|
|
|
}
|
2017-12-30 16:25:09 +00:00
|
|
|
|
}
|
2015-08-31 09:19:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-05 09:01:17 +00:00
|
|
|
|
void WebContents::ToggleDevTools() {
|
|
|
|
|
if (IsDevToolsOpened())
|
|
|
|
|
CloseDevTools();
|
|
|
|
|
else
|
|
|
|
|
OpenDevTools(nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-22 07:30:10 +00:00
|
|
|
|
void WebContents::InspectElement(int x, int y) {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2015-06-05 07:41:03 +00:00
|
|
|
|
return;
|
2015-06-24 14:23:38 +00:00
|
|
|
|
|
2016-09-07 02:16:52 +00:00
|
|
|
|
if (!enable_devtools_)
|
2016-09-06 09:53:42 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2020-11-17 22:15:20 +00:00
|
|
|
|
DCHECK(inspectable_web_contents_);
|
|
|
|
|
if (!inspectable_web_contents_->GetDevToolsWebContents())
|
2016-08-23 22:26:13 +00:00
|
|
|
|
OpenDevTools(nullptr);
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->InspectElement(x, y);
|
2015-04-22 07:30:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-02 12:38:27 +00:00
|
|
|
|
void WebContents::InspectSharedWorkerById(const std::string& workerId) {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2019-10-02 12:38:27 +00:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!enable_devtools_)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
|
|
|
|
|
if (agent_host->GetType() ==
|
|
|
|
|
content::DevToolsAgentHost::kTypeSharedWorker) {
|
|
|
|
|
if (agent_host->GetId() == workerId) {
|
|
|
|
|
OpenDevTools(nullptr);
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->AttachTo(agent_host);
|
2019-10-02 12:38:27 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<scoped_refptr<content::DevToolsAgentHost>>
|
|
|
|
|
WebContents::GetAllSharedWorkers() {
|
|
|
|
|
std::vector<scoped_refptr<content::DevToolsAgentHost>> shared_workers;
|
|
|
|
|
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2019-10-02 12:38:27 +00:00
|
|
|
|
return shared_workers;
|
|
|
|
|
|
|
|
|
|
if (!enable_devtools_)
|
|
|
|
|
return shared_workers;
|
|
|
|
|
|
|
|
|
|
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
|
|
|
|
|
if (agent_host->GetType() ==
|
|
|
|
|
content::DevToolsAgentHost::kTypeSharedWorker) {
|
|
|
|
|
shared_workers.push_back(agent_host);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return shared_workers;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-01 18:44:24 +00:00
|
|
|
|
void WebContents::InspectSharedWorker() {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2019-02-01 18:44:24 +00:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!enable_devtools_)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
|
|
|
|
|
if (agent_host->GetType() ==
|
|
|
|
|
content::DevToolsAgentHost::kTypeSharedWorker) {
|
|
|
|
|
OpenDevTools(nullptr);
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->AttachTo(agent_host);
|
2019-02-01 18:44:24 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-05 07:41:03 +00:00
|
|
|
|
void WebContents::InspectServiceWorker() {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
if (type_ == Type::kRemote)
|
2015-06-05 07:41:03 +00:00
|
|
|
|
return;
|
2015-06-24 14:23:38 +00:00
|
|
|
|
|
2016-09-07 02:16:52 +00:00
|
|
|
|
if (!enable_devtools_)
|
2016-09-06 09:53:42 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2015-06-05 07:41:03 +00:00
|
|
|
|
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
|
|
|
|
|
if (agent_host->GetType() ==
|
2017-01-24 07:50:02 +00:00
|
|
|
|
content::DevToolsAgentHost::kTypeServiceWorker) {
|
2015-06-05 09:01:17 +00:00
|
|
|
|
OpenDevTools(nullptr);
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->AttachTo(agent_host);
|
2015-06-05 07:41:03 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-25 19:01:05 +00:00
|
|
|
|
void WebContents::SetIgnoreMenuShortcuts(bool ignore) {
|
2018-09-10 10:06:16 +00:00
|
|
|
|
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
|
|
|
|
DCHECK(web_preferences);
|
2021-07-26 16:04:09 +00:00
|
|
|
|
web_preferences->SetIgnoreMenuShortcuts(ignore);
|
2017-06-25 19:01:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-15 13:40:49 +00:00
|
|
|
|
void WebContents::SetAudioMuted(bool muted) {
|
|
|
|
|
web_contents()->SetAudioMuted(muted);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::IsAudioMuted() {
|
|
|
|
|
return web_contents()->IsAudioMuted();
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-12 11:35:11 +00:00
|
|
|
|
bool WebContents::IsCurrentlyAudible() {
|
|
|
|
|
return web_contents()->IsCurrentlyAudible();
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-13 01:57:04 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_PRINTING)
|
2022-07-13 10:23:24 +00:00
|
|
|
|
void WebContents::OnGetDeviceNameToUse(
|
2022-05-19 08:05:07 +00:00
|
|
|
|
base::Value::Dict print_settings,
|
2020-01-31 19:20:11 +00:00
|
|
|
|
printing::CompletionCallback print_callback,
|
2022-07-13 10:23:24 +00:00
|
|
|
|
// <error, device_name>
|
2021-10-05 07:16:04 +00:00
|
|
|
|
std::pair<std::string, std::u16string> info) {
|
2020-02-05 15:48:51 +00:00
|
|
|
|
// The content::WebContents might be already deleted at this point, and the
|
2021-05-19 23:15:47 +00:00
|
|
|
|
// PrintViewManagerElectron class does not do null check.
|
2020-02-05 15:48:51 +00:00
|
|
|
|
if (!web_contents()) {
|
|
|
|
|
if (print_callback)
|
|
|
|
|
std::move(print_callback).Run(false, "failed");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-05 07:16:04 +00:00
|
|
|
|
if (!info.first.empty()) {
|
|
|
|
|
if (print_callback)
|
|
|
|
|
std::move(print_callback).Run(false, info.first);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the user has passed a deviceName use it, otherwise use default printer.
|
2022-07-13 10:23:24 +00:00
|
|
|
|
print_settings.Set(printing::kSettingDeviceName, info.second);
|
2020-01-31 19:20:11 +00:00
|
|
|
|
|
2024-04-11 23:56:39 +00:00
|
|
|
|
if (!print_settings.FindInt(printing::kSettingDpiHorizontal)) {
|
|
|
|
|
gfx::Size dpi = GetDefaultPrinterDPI(info.second);
|
|
|
|
|
print_settings.Set(printing::kSettingDpiHorizontal, dpi.width());
|
|
|
|
|
print_settings.Set(printing::kSettingDpiVertical, dpi.height());
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-31 19:20:11 +00:00
|
|
|
|
auto* print_view_manager =
|
2021-05-19 23:15:47 +00:00
|
|
|
|
PrintViewManagerElectron::FromWebContents(web_contents());
|
|
|
|
|
if (!print_view_manager)
|
|
|
|
|
return;
|
|
|
|
|
|
2024-08-14 19:47:47 +00:00
|
|
|
|
content::RenderFrameHost* rfh = GetRenderFrameHostToUse(web_contents());
|
2024-04-17 16:04:47 +00:00
|
|
|
|
print_view_manager->PrintNow(rfh, std::move(print_settings),
|
2020-01-31 19:20:11 +00:00
|
|
|
|
std::move(print_callback));
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-20 18:07:02 +00:00
|
|
|
|
void WebContents::Print(gin::Arguments* args) {
|
2023-10-10 10:45:44 +00:00
|
|
|
|
auto options = gin_helper::Dictionary::CreateEmpty(args->isolate());
|
2022-05-19 08:05:07 +00:00
|
|
|
|
base::Value::Dict settings;
|
2019-08-07 14:47:24 +00:00
|
|
|
|
|
2018-11-09 03:42:34 +00:00
|
|
|
|
if (args->Length() >= 1 && !args->GetNext(&options)) {
|
2020-07-20 18:07:02 +00:00
|
|
|
|
gin_helper::ErrorThrower(args->isolate())
|
|
|
|
|
.ThrowError("webContents.print(): Invalid print settings specified.");
|
2015-06-13 13:23:45 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2019-08-07 14:47:24 +00:00
|
|
|
|
|
2018-11-09 03:42:34 +00:00
|
|
|
|
printing::CompletionCallback callback;
|
|
|
|
|
if (args->Length() == 2 && !args->GetNext(&callback)) {
|
2020-07-20 18:07:02 +00:00
|
|
|
|
gin_helper::ErrorThrower(args->isolate())
|
|
|
|
|
.ThrowError("webContents.print(): Invalid optional callback provided.");
|
2018-11-09 03:42:34 +00:00
|
|
|
|
return;
|
2017-07-21 07:16:27 +00:00
|
|
|
|
}
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
2024-04-17 16:04:47 +00:00
|
|
|
|
// Set optional silent printing.
|
2019-06-30 05:12:00 +00:00
|
|
|
|
bool silent = false;
|
2018-11-09 03:42:34 +00:00
|
|
|
|
options.Get("silent", &silent);
|
2024-04-17 16:04:47 +00:00
|
|
|
|
settings.Set("silent", silent);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
2019-08-07 14:47:24 +00:00
|
|
|
|
bool print_background = false;
|
|
|
|
|
options.Get("printBackground", &print_background);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingShouldPrintBackgrounds, print_background);
|
2019-08-07 14:47:24 +00:00
|
|
|
|
|
2019-06-30 05:12:00 +00:00
|
|
|
|
// Set custom margin settings
|
2023-10-10 10:45:44 +00:00
|
|
|
|
auto margins = gin_helper::Dictionary::CreateEmpty(args->isolate());
|
2019-06-30 05:12:00 +00:00
|
|
|
|
if (options.Get("margins", &margins)) {
|
2020-08-15 01:51:28 +00:00
|
|
|
|
printing::mojom::MarginType margin_type =
|
|
|
|
|
printing::mojom::MarginType::kDefaultMargins;
|
2019-06-30 05:12:00 +00:00
|
|
|
|
margins.Get("marginType", &margin_type);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingMarginsType, static_cast<int>(margin_type));
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
2020-08-15 01:51:28 +00:00
|
|
|
|
if (margin_type == printing::mojom::MarginType::kCustomMargins) {
|
2022-05-19 08:05:07 +00:00
|
|
|
|
base::Value::Dict custom_margins;
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int top = 0;
|
|
|
|
|
margins.Get("top", &top);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
custom_margins.Set(printing::kSettingMarginTop, top);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int bottom = 0;
|
|
|
|
|
margins.Get("bottom", &bottom);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
custom_margins.Set(printing::kSettingMarginBottom, bottom);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int left = 0;
|
|
|
|
|
margins.Get("left", &left);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
custom_margins.Set(printing::kSettingMarginLeft, left);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int right = 0;
|
|
|
|
|
margins.Get("right", &right);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
custom_margins.Set(printing::kSettingMarginRight, right);
|
|
|
|
|
settings.Set(printing::kSettingMarginsCustom, std::move(custom_margins));
|
2019-06-30 05:12:00 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(
|
2020-08-15 01:51:28 +00:00
|
|
|
|
printing::kSettingMarginsType,
|
|
|
|
|
static_cast<int>(printing::mojom::MarginType::kDefaultMargins));
|
2019-06-30 05:12:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set whether to print color or greyscale
|
|
|
|
|
bool print_color = true;
|
|
|
|
|
options.Get("color", &print_color);
|
2020-09-21 08:00:36 +00:00
|
|
|
|
auto const color_model = print_color ? printing::mojom::ColorModel::kColor
|
|
|
|
|
: printing::mojom::ColorModel::kGray;
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingColor, static_cast<int>(color_model));
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
2019-08-09 20:16:25 +00:00
|
|
|
|
// Is the orientation landscape or portrait.
|
2019-06-30 05:12:00 +00:00
|
|
|
|
bool landscape = false;
|
|
|
|
|
options.Get("landscape", &landscape);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingLandscape, landscape);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
2020-01-31 19:20:11 +00:00
|
|
|
|
// We set the default to the system's default printer and only update
|
|
|
|
|
// if at the Chromium level if the user overrides.
|
2019-08-09 20:16:25 +00:00
|
|
|
|
// Printer device name as opened by the OS.
|
2021-03-16 16:18:45 +00:00
|
|
|
|
std::u16string device_name;
|
2019-06-30 05:12:00 +00:00
|
|
|
|
options.Get("deviceName", &device_name);
|
|
|
|
|
|
|
|
|
|
int scale_factor = 100;
|
|
|
|
|
options.Get("scaleFactor", &scale_factor);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingScaleFactor, scale_factor);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
|
|
|
|
int pages_per_sheet = 1;
|
|
|
|
|
options.Get("pagesPerSheet", &pages_per_sheet);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingPagesPerSheet, pages_per_sheet);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
2019-08-09 20:16:25 +00:00
|
|
|
|
// True if the user wants to print with collate.
|
2019-06-30 05:12:00 +00:00
|
|
|
|
bool collate = true;
|
|
|
|
|
options.Get("collate", &collate);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingCollate, collate);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
2019-08-09 20:16:25 +00:00
|
|
|
|
// The number of individual copies to print
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int copies = 1;
|
|
|
|
|
options.Get("copies", &copies);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingCopies, copies);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
2019-08-09 20:16:25 +00:00
|
|
|
|
// Strings to be printed as headers and footers if requested by the user.
|
|
|
|
|
std::string header;
|
|
|
|
|
options.Get("header", &header);
|
|
|
|
|
std::string footer;
|
|
|
|
|
options.Get("footer", &footer);
|
|
|
|
|
|
|
|
|
|
if (!(header.empty() && footer.empty())) {
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingHeaderFooterEnabled, true);
|
2019-08-09 20:16:25 +00:00
|
|
|
|
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingHeaderFooterTitle, header);
|
|
|
|
|
settings.Set(printing::kSettingHeaderFooterURL, footer);
|
2019-08-24 01:14:23 +00:00
|
|
|
|
} else {
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingHeaderFooterEnabled, false);
|
2019-08-09 20:16:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We don't want to allow the user to enable these settings
|
2019-06-30 05:12:00 +00:00
|
|
|
|
// but we need to set them or a CHECK is hit.
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingPrinterType,
|
|
|
|
|
static_cast<int>(printing::mojom::PrinterType::kLocal));
|
|
|
|
|
settings.Set(printing::kSettingShouldPrintSelectionOnly, false);
|
|
|
|
|
settings.Set(printing::kSettingRasterizePdf, false);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
|
|
|
|
// Set custom page ranges to print
|
2019-10-25 13:03:28 +00:00
|
|
|
|
std::vector<gin_helper::Dictionary> page_ranges;
|
2019-06-30 05:12:00 +00:00
|
|
|
|
if (options.Get("pageRanges", &page_ranges)) {
|
2022-05-19 08:05:07 +00:00
|
|
|
|
base::Value::List page_range_list;
|
2019-09-13 14:26:59 +00:00
|
|
|
|
for (auto& range : page_ranges) {
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int from, to;
|
2019-09-13 14:26:59 +00:00
|
|
|
|
if (range.Get("from", &from) && range.Get("to", &to)) {
|
2022-09-07 07:46:37 +00:00
|
|
|
|
base::Value::Dict range_dict;
|
2020-08-28 03:21:29 +00:00
|
|
|
|
// Chromium uses 1-based page ranges, so increment each by 1.
|
2022-09-07 07:46:37 +00:00
|
|
|
|
range_dict.Set(printing::kSettingPageRangeFrom, from + 1);
|
|
|
|
|
range_dict.Set(printing::kSettingPageRangeTo, to + 1);
|
|
|
|
|
page_range_list.Append(std::move(range_dict));
|
2019-06-30 05:12:00 +00:00
|
|
|
|
} else {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-19 08:05:07 +00:00
|
|
|
|
if (!page_range_list.empty())
|
|
|
|
|
settings.Set(printing::kSettingPageRange, std::move(page_range_list));
|
2018-11-09 03:42:34 +00:00
|
|
|
|
}
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
2019-08-09 20:16:25 +00:00
|
|
|
|
// Duplex type user wants to use.
|
2020-07-13 15:31:39 +00:00
|
|
|
|
printing::mojom::DuplexMode duplex_mode =
|
|
|
|
|
printing::mojom::DuplexMode::kSimplex;
|
2019-06-30 05:12:00 +00:00
|
|
|
|
options.Get("duplexMode", &duplex_mode);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingDuplexMode, static_cast<int>(duplex_mode));
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
2020-02-05 04:25:02 +00:00
|
|
|
|
// We've already done necessary parameter sanitization at the
|
|
|
|
|
// JS level, so we can simply pass this through.
|
2023-03-10 16:07:42 +00:00
|
|
|
|
base::Value media_size(base::Value::Type::DICT);
|
2020-02-05 04:25:02 +00:00
|
|
|
|
if (options.Get("mediaSize", &media_size))
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingMediaSize, std::move(media_size));
|
2020-02-05 04:25:02 +00:00
|
|
|
|
|
2019-06-30 05:12:00 +00:00
|
|
|
|
// Set custom dots per inch (dpi)
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin_helper::Dictionary dpi_settings;
|
2019-06-30 05:12:00 +00:00
|
|
|
|
if (options.Get("dpi", &dpi_settings)) {
|
|
|
|
|
int horizontal = 72;
|
|
|
|
|
dpi_settings.Get("horizontal", &horizontal);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingDpiHorizontal, horizontal);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int vertical = 72;
|
|
|
|
|
dpi_settings.Get("vertical", &vertical);
|
2022-05-19 08:05:07 +00:00
|
|
|
|
settings.Set(printing::kSettingDpiVertical, vertical);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-13 17:17:11 +00:00
|
|
|
|
print_task_runner_->PostTaskAndReplyWithResult(
|
2022-07-13 10:23:24 +00:00
|
|
|
|
FROM_HERE, base::BindOnce(&GetDeviceNameToUse, device_name),
|
|
|
|
|
base::BindOnce(&WebContents::OnGetDeviceNameToUse,
|
2020-01-31 19:20:11 +00:00
|
|
|
|
weak_factory_.GetWeakPtr(), std::move(settings),
|
2024-04-17 16:04:47 +00:00
|
|
|
|
std::move(callback)));
|
2017-02-06 09:18:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-31 06:21:25 +00:00
|
|
|
|
// Partially duplicated and modified from
|
|
|
|
|
// headless/lib/browser/protocol/page_handler.cc;l=41
|
|
|
|
|
v8::Local<v8::Promise> WebContents::PrintToPDF(const base::Value& settings) {
|
2020-07-16 21:11:44 +00:00
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
|
2019-02-21 12:32:44 +00:00
|
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
2022-05-31 06:21:25 +00:00
|
|
|
|
|
|
|
|
|
// This allows us to track headless printing calls.
|
|
|
|
|
auto unique_id = settings.GetDict().FindInt(printing::kPreviewRequestID);
|
|
|
|
|
auto landscape = settings.GetDict().FindBool("landscape");
|
|
|
|
|
auto display_header_footer =
|
|
|
|
|
settings.GetDict().FindBool("displayHeaderFooter");
|
2024-01-30 20:47:55 +00:00
|
|
|
|
auto print_background = settings.GetDict().FindBool("printBackground");
|
2022-05-31 06:21:25 +00:00
|
|
|
|
auto scale = settings.GetDict().FindDouble("scale");
|
2022-10-11 23:06:34 +00:00
|
|
|
|
auto paper_width = settings.GetDict().FindDouble("paperWidth");
|
|
|
|
|
auto paper_height = settings.GetDict().FindDouble("paperHeight");
|
|
|
|
|
auto margin_top = settings.GetDict().FindDouble("marginTop");
|
|
|
|
|
auto margin_bottom = settings.GetDict().FindDouble("marginBottom");
|
|
|
|
|
auto margin_left = settings.GetDict().FindDouble("marginLeft");
|
|
|
|
|
auto margin_right = settings.GetDict().FindDouble("marginRight");
|
2022-05-31 06:21:25 +00:00
|
|
|
|
auto page_ranges = *settings.GetDict().FindString("pageRanges");
|
|
|
|
|
auto header_template = *settings.GetDict().FindString("headerTemplate");
|
|
|
|
|
auto footer_template = *settings.GetDict().FindString("footerTemplate");
|
|
|
|
|
auto prefer_css_page_size = settings.GetDict().FindBool("preferCSSPageSize");
|
2023-10-19 19:38:30 +00:00
|
|
|
|
auto generate_tagged_pdf = settings.GetDict().FindBool("generateTaggedPDF");
|
2023-11-28 21:40:12 +00:00
|
|
|
|
auto generate_document_outline =
|
|
|
|
|
settings.GetDict().FindBool("generateDocumentOutline");
|
2022-05-31 06:21:25 +00:00
|
|
|
|
|
2024-08-14 19:47:47 +00:00
|
|
|
|
content::RenderFrameHost* rfh = GetRenderFrameHostToUse(web_contents());
|
2022-05-31 06:21:25 +00:00
|
|
|
|
absl::variant<printing::mojom::PrintPagesParamsPtr, std::string>
|
|
|
|
|
print_pages_params = print_to_pdf::GetPrintPagesParams(
|
2024-08-14 19:47:47 +00:00
|
|
|
|
rfh->GetLastCommittedURL(), landscape, display_header_footer,
|
|
|
|
|
print_background, scale, paper_width, paper_height, margin_top,
|
|
|
|
|
margin_bottom, margin_left, margin_right,
|
|
|
|
|
std::make_optional(header_template),
|
2024-01-10 22:23:35 +00:00
|
|
|
|
std::make_optional(footer_template), prefer_css_page_size,
|
2023-11-28 21:40:12 +00:00
|
|
|
|
generate_tagged_pdf, generate_document_outline);
|
2022-05-31 06:21:25 +00:00
|
|
|
|
|
|
|
|
|
if (absl::holds_alternative<std::string>(print_pages_params)) {
|
|
|
|
|
auto error = absl::get<std::string>(print_pages_params);
|
|
|
|
|
promise.RejectWithErrorMessage("Invalid print parameters: " + error);
|
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto* manager = PrintViewManagerElectron::FromWebContents(web_contents());
|
|
|
|
|
if (!manager) {
|
|
|
|
|
promise.RejectWithErrorMessage("Failed to find print manager");
|
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto params = std::move(
|
|
|
|
|
absl::get<printing::mojom::PrintPagesParamsPtr>(print_pages_params));
|
|
|
|
|
params->params->document_cookie = unique_id.value_or(0);
|
|
|
|
|
|
2024-08-14 19:47:47 +00:00
|
|
|
|
manager->PrintToPdf(rfh, page_ranges, std::move(params),
|
2022-05-31 06:21:25 +00:00
|
|
|
|
base::BindOnce(&WebContents::OnPDFCreated, GetWeakPtr(),
|
|
|
|
|
std::move(promise)));
|
|
|
|
|
|
2019-02-21 12:32:44 +00:00
|
|
|
|
return handle;
|
2015-06-09 05:07:40 +00:00
|
|
|
|
}
|
2022-05-31 06:21:25 +00:00
|
|
|
|
|
|
|
|
|
void WebContents::OnPDFCreated(
|
|
|
|
|
gin_helper::Promise<v8::Local<v8::Value>> promise,
|
2022-10-20 18:30:40 +00:00
|
|
|
|
print_to_pdf::PdfPrintResult print_result,
|
2022-05-31 06:21:25 +00:00
|
|
|
|
scoped_refptr<base::RefCountedMemory> data) {
|
2022-10-20 18:30:40 +00:00
|
|
|
|
if (print_result != print_to_pdf::PdfPrintResult::kPrintSuccess) {
|
2022-05-31 06:21:25 +00:00
|
|
|
|
promise.RejectWithErrorMessage(
|
|
|
|
|
"Failed to generate PDF: " +
|
2022-10-20 18:30:40 +00:00
|
|
|
|
print_to_pdf::PdfPrintResultToString(print_result));
|
2022-05-31 06:21:25 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
v8::Isolate* isolate = promise.isolate();
|
|
|
|
|
gin_helper::Locker locker(isolate);
|
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
|
|
|
|
v8::Context::Scope context_scope(
|
|
|
|
|
v8::Local<v8::Context>::New(isolate, promise.GetContext()));
|
|
|
|
|
|
|
|
|
|
v8::Local<v8::Value> buffer =
|
|
|
|
|
node::Buffer::Copy(isolate, reinterpret_cast<const char*>(data->front()),
|
|
|
|
|
data->size())
|
|
|
|
|
.ToLocalChecked();
|
|
|
|
|
|
|
|
|
|
promise.Resolve(buffer);
|
|
|
|
|
}
|
2018-11-09 03:42:34 +00:00
|
|
|
|
#endif
|
2015-06-09 05:07:40 +00:00
|
|
|
|
|
2020-07-20 18:07:02 +00:00
|
|
|
|
void WebContents::AddWorkSpace(gin::Arguments* args,
|
2015-09-07 08:12:31 +00:00
|
|
|
|
const base::FilePath& path) {
|
2015-07-24 09:39:11 +00:00
|
|
|
|
if (path.empty()) {
|
2020-07-20 18:07:02 +00:00
|
|
|
|
gin_helper::ErrorThrower(args->isolate())
|
|
|
|
|
.ThrowError("path cannot be empty");
|
2015-07-24 09:39:11 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2018-09-12 13:45:08 +00:00
|
|
|
|
DevToolsAddFileSystem(std::string(), path);
|
2015-07-24 09:39:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-20 18:07:02 +00:00
|
|
|
|
void WebContents::RemoveWorkSpace(gin::Arguments* args,
|
2015-09-07 08:12:31 +00:00
|
|
|
|
const base::FilePath& path) {
|
2015-07-24 09:39:11 +00:00
|
|
|
|
if (path.empty()) {
|
2020-07-20 18:07:02 +00:00
|
|
|
|
gin_helper::ErrorThrower(args->isolate())
|
|
|
|
|
.ThrowError("path cannot be empty");
|
2015-07-24 09:39:11 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
DevToolsRemoveFileSystem(path);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-19 20:09:47 +00:00
|
|
|
|
void WebContents::Undo() {
|
|
|
|
|
web_contents()->Undo();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::Redo() {
|
|
|
|
|
web_contents()->Redo();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::Cut() {
|
|
|
|
|
web_contents()->Cut();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::Copy() {
|
|
|
|
|
web_contents()->Copy();
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-03 01:14:29 +00:00
|
|
|
|
void WebContents::CenterSelection() {
|
|
|
|
|
web_contents()->CenterSelection();
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-19 20:09:47 +00:00
|
|
|
|
void WebContents::Paste() {
|
|
|
|
|
web_contents()->Paste();
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-15 07:15:19 +00:00
|
|
|
|
void WebContents::PasteAndMatchStyle() {
|
|
|
|
|
web_contents()->PasteAndMatchStyle();
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-19 20:09:47 +00:00
|
|
|
|
void WebContents::Delete() {
|
|
|
|
|
web_contents()->Delete();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::SelectAll() {
|
|
|
|
|
web_contents()->SelectAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::Unselect() {
|
2017-04-13 10:21:30 +00:00
|
|
|
|
web_contents()->CollapseSelection();
|
2015-01-19 20:09:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-03 01:14:29 +00:00
|
|
|
|
void WebContents::ScrollToTopOfDocument() {
|
|
|
|
|
web_contents()->ScrollToTopOfDocument();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::ScrollToBottomOfDocument() {
|
|
|
|
|
web_contents()->ScrollToBottomOfDocument();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::AdjustSelectionByCharacterOffset(gin::Arguments* args) {
|
|
|
|
|
int start_adjust = 0;
|
|
|
|
|
int end_adjust = 0;
|
|
|
|
|
|
|
|
|
|
gin_helper::Dictionary dict;
|
|
|
|
|
if (args->GetNext(&dict)) {
|
|
|
|
|
dict.Get("start", &start_adjust);
|
|
|
|
|
dict.Get("matchCase", &end_adjust);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The selection menu is a Chrome-specific piece of UI.
|
|
|
|
|
// TODO(codebytere): maybe surface as an event in the future?
|
|
|
|
|
web_contents()->AdjustSelectionByCharacterOffset(
|
|
|
|
|
start_adjust, end_adjust, false /* show_selection_menu */);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-16 16:18:45 +00:00
|
|
|
|
void WebContents::Replace(const std::u16string& word) {
|
2015-01-19 20:09:47 +00:00
|
|
|
|
web_contents()->Replace(word);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-16 16:18:45 +00:00
|
|
|
|
void WebContents::ReplaceMisspelling(const std::u16string& word) {
|
2015-01-19 20:09:47 +00:00
|
|
|
|
web_contents()->ReplaceMisspelling(word);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-20 18:07:02 +00:00
|
|
|
|
uint32_t WebContents::FindInPage(gin::Arguments* args) {
|
2021-03-16 16:18:45 +00:00
|
|
|
|
std::u16string search_text;
|
2015-12-17 23:10:42 +00:00
|
|
|
|
if (!args->GetNext(&search_text) || search_text.empty()) {
|
2020-07-20 18:07:02 +00:00
|
|
|
|
gin_helper::ErrorThrower(args->isolate())
|
|
|
|
|
.ThrowError("Must provide a non-empty search content");
|
2015-12-17 23:10:42 +00:00
|
|
|
|
return 0;
|
2015-12-17 17:27:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-17 22:15:07 +00:00
|
|
|
|
uint32_t request_id = ++find_in_page_request_id_;
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin_helper::Dictionary dict;
|
2019-01-12 01:00:43 +00:00
|
|
|
|
auto options = blink::mojom::FindOptions::New();
|
|
|
|
|
if (args->GetNext(&dict)) {
|
|
|
|
|
dict.Get("forward", &options->forward);
|
|
|
|
|
dict.Get("matchCase", &options->match_case);
|
2020-06-22 17:35:10 +00:00
|
|
|
|
dict.Get("findNext", &options->new_session);
|
2019-01-12 01:00:43 +00:00
|
|
|
|
}
|
2015-12-17 17:27:56 +00:00
|
|
|
|
|
2024-07-05 07:51:21 +00:00
|
|
|
|
web_contents()->Find(request_id, search_text, std::move(options),
|
|
|
|
|
/*skip_delay=*/false);
|
2015-12-17 23:10:42 +00:00
|
|
|
|
return request_id;
|
2015-12-17 17:27:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::StopFindInPage(content::StopFindAction action) {
|
|
|
|
|
web_contents()->StopFinding(action);
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-02 17:12:38 +00:00
|
|
|
|
void WebContents::ShowDefinitionForSelection() {
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* const view = web_contents()->GetRenderWidgetHostView();
|
2016-06-02 17:12:38 +00:00
|
|
|
|
if (view)
|
|
|
|
|
view->ShowDefinitionForSelection();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-26 19:06:11 +00:00
|
|
|
|
void WebContents::CopyImageAt(int x, int y) {
|
2022-06-27 20:50:08 +00:00
|
|
|
|
auto* const host = web_contents()->GetPrimaryMainFrame();
|
2016-07-26 19:06:11 +00:00
|
|
|
|
if (host)
|
|
|
|
|
host->CopyImageAt(x, y);
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-24 04:58:28 +00:00
|
|
|
|
void WebContents::Focus() {
|
2020-03-02 07:51:02 +00:00
|
|
|
|
// Focusing on WebContents does not automatically focus the window on macOS
|
|
|
|
|
// and Linux, do it manually to match the behavior on Windows.
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
|
2020-03-02 07:51:02 +00:00
|
|
|
|
if (owner_window())
|
|
|
|
|
owner_window()->Focus(true);
|
|
|
|
|
#endif
|
2015-07-24 04:58:28 +00:00
|
|
|
|
web_contents()->Focus();
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if !BUILDFLAG(IS_MAC)
|
2016-08-03 03:29:55 +00:00
|
|
|
|
bool WebContents::IsFocused() const {
|
2018-05-16 19:12:45 +00:00
|
|
|
|
auto* view = web_contents()->GetRenderWidgetHostView();
|
2018-04-18 01:55:30 +00:00
|
|
|
|
if (!view)
|
|
|
|
|
return false;
|
2016-08-15 21:13:24 +00:00
|
|
|
|
|
2024-02-09 09:29:14 +00:00
|
|
|
|
if (type() != Type::kBackgroundPage) {
|
2018-05-16 19:12:45 +00:00
|
|
|
|
auto* window = web_contents()->GetNativeView()->GetToplevelWindow();
|
2016-08-15 21:13:24 +00:00
|
|
|
|
if (window && !window->IsVisible())
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return view->HasFocus();
|
2016-08-03 03:29:55 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-09-18 06:20:31 +00:00
|
|
|
|
void WebContents::SendInputEvent(v8::Isolate* isolate,
|
|
|
|
|
v8::Local<v8::Value> input_event) {
|
2018-04-12 12:54:04 +00:00
|
|
|
|
content::RenderWidgetHostView* view =
|
|
|
|
|
web_contents()->GetRenderWidgetHostView();
|
2015-09-18 06:20:31 +00:00
|
|
|
|
if (!view)
|
|
|
|
|
return;
|
|
|
|
|
|
2018-04-12 12:54:04 +00:00
|
|
|
|
content::RenderWidgetHost* rwh = view->GetRenderWidgetHost();
|
2018-04-18 01:55:30 +00:00
|
|
|
|
blink::WebInputEvent::Type type =
|
2019-10-31 07:56:00 +00:00
|
|
|
|
gin::GetWebInputEventType(isolate, input_event);
|
2017-06-16 20:42:33 +00:00
|
|
|
|
if (blink::WebInputEvent::IsMouseEventType(type)) {
|
2015-09-18 06:20:31 +00:00
|
|
|
|
blink::WebMouseEvent mouse_event;
|
2019-10-31 07:56:00 +00:00
|
|
|
|
if (gin::ConvertFromV8(isolate, input_event, &mouse_event)) {
|
2018-05-15 01:59:22 +00:00
|
|
|
|
if (IsOffScreen()) {
|
|
|
|
|
GetOffScreenRenderWidgetHostView()->SendMouseEvent(mouse_event);
|
|
|
|
|
} else {
|
|
|
|
|
rwh->ForwardMouseEvent(mouse_event);
|
|
|
|
|
}
|
2015-09-18 06:20:31 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2017-06-16 20:42:33 +00:00
|
|
|
|
} else if (blink::WebInputEvent::IsKeyboardEventType(type)) {
|
2024-06-07 21:18:35 +00:00
|
|
|
|
input::NativeWebKeyboardEvent keyboard_event(
|
2020-05-26 20:06:26 +00:00
|
|
|
|
blink::WebKeyboardEvent::Type::kRawKeyDown,
|
|
|
|
|
blink::WebInputEvent::Modifiers::kNoModifiers, ui::EventTimeForNow());
|
2019-10-25 13:03:28 +00:00
|
|
|
|
if (gin::ConvertFromV8(isolate, input_event, &keyboard_event)) {
|
2022-09-27 19:47:46 +00:00
|
|
|
|
// For backwards compatibility, convert `kKeyDown` to `kRawKeyDown`.
|
|
|
|
|
if (keyboard_event.GetType() == blink::WebKeyboardEvent::Type::kKeyDown)
|
|
|
|
|
keyboard_event.SetType(blink::WebKeyboardEvent::Type::kRawKeyDown);
|
2018-04-12 12:54:04 +00:00
|
|
|
|
rwh->ForwardKeyboardEvent(keyboard_event);
|
2015-09-18 06:20:31 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2020-05-26 20:06:26 +00:00
|
|
|
|
} else if (type == blink::WebInputEvent::Type::kMouseWheel) {
|
2015-09-18 06:20:31 +00:00
|
|
|
|
blink::WebMouseWheelEvent mouse_wheel_event;
|
2019-10-31 07:56:00 +00:00
|
|
|
|
if (gin::ConvertFromV8(isolate, input_event, &mouse_wheel_event)) {
|
2018-05-15 01:59:22 +00:00
|
|
|
|
if (IsOffScreen()) {
|
|
|
|
|
GetOffScreenRenderWidgetHostView()->SendMouseWheelEvent(
|
|
|
|
|
mouse_wheel_event);
|
|
|
|
|
} else {
|
2019-04-16 16:23:38 +00:00
|
|
|
|
// Chromium expects phase info in wheel events (and applies a
|
|
|
|
|
// DCHECK to verify it). See: https://crbug.com/756524.
|
|
|
|
|
mouse_wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
|
2020-04-21 00:25:38 +00:00
|
|
|
|
mouse_wheel_event.dispatch_type =
|
|
|
|
|
blink::WebInputEvent::DispatchType::kBlocking;
|
2019-04-16 16:23:38 +00:00
|
|
|
|
rwh->ForwardWheelEvent(mouse_wheel_event);
|
|
|
|
|
|
|
|
|
|
// Send a synthetic wheel event with phaseEnded to finish scrolling.
|
|
|
|
|
mouse_wheel_event.has_synthetic_phase = true;
|
|
|
|
|
mouse_wheel_event.delta_x = 0;
|
|
|
|
|
mouse_wheel_event.delta_y = 0;
|
|
|
|
|
mouse_wheel_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
|
|
|
|
|
mouse_wheel_event.dispatch_type =
|
2020-04-21 00:25:38 +00:00
|
|
|
|
blink::WebInputEvent::DispatchType::kEventNonBlocking;
|
2018-05-15 01:59:22 +00:00
|
|
|
|
rwh->ForwardWheelEvent(mouse_wheel_event);
|
|
|
|
|
}
|
2015-09-18 06:20:31 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
|
isolate->ThrowException(
|
2019-10-25 13:03:28 +00:00
|
|
|
|
v8::Exception::Error(gin::StringToV8(isolate, "Invalid event object")));
|
2015-09-18 06:20:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-20 18:07:02 +00:00
|
|
|
|
void WebContents::BeginFrameSubscription(gin::Arguments* args) {
|
2018-05-14 17:09:05 +00:00
|
|
|
|
bool only_dirty = false;
|
2016-06-26 02:46:40 +00:00
|
|
|
|
FrameSubscriber::FrameCaptureCallback callback;
|
2016-06-21 00:15:39 +00:00
|
|
|
|
|
2020-07-20 18:07:02 +00:00
|
|
|
|
if (args->Length() > 1) {
|
|
|
|
|
if (!args->GetNext(&only_dirty)) {
|
|
|
|
|
args->ThrowError();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-06-25 16:23:40 +00:00
|
|
|
|
if (!args->GetNext(&callback)) {
|
2016-06-26 02:46:40 +00:00
|
|
|
|
args->ThrowError();
|
|
|
|
|
return;
|
2016-06-25 16:23:40 +00:00
|
|
|
|
}
|
2016-06-21 00:15:39 +00:00
|
|
|
|
|
2019-09-16 22:12:00 +00:00
|
|
|
|
frame_subscriber_ =
|
|
|
|
|
std::make_unique<FrameSubscriber>(web_contents(), callback, only_dirty);
|
2015-09-18 07:57:43 +00:00
|
|
|
|
}
|
2015-09-18 06:20:31 +00:00
|
|
|
|
|
2015-09-18 07:57:43 +00:00
|
|
|
|
void WebContents::EndFrameSubscription() {
|
2018-04-18 00:45:15 +00:00
|
|
|
|
frame_subscriber_.reset();
|
2015-09-18 07:57:43 +00:00
|
|
|
|
}
|
2015-09-18 06:20:31 +00:00
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
void WebContents::StartDrag(const gin_helper::Dictionary& item,
|
2020-07-20 18:07:02 +00:00
|
|
|
|
gin::Arguments* args) {
|
2016-07-03 04:58:31 +00:00
|
|
|
|
base::FilePath file;
|
|
|
|
|
std::vector<base::FilePath> files;
|
|
|
|
|
if (!item.Get("files", &files) && item.Get("file", &file)) {
|
|
|
|
|
files.push_back(file);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-04 20:58:31 +00:00
|
|
|
|
v8::Local<v8::Value> icon_value;
|
|
|
|
|
if (!item.Get("icon", &icon_value)) {
|
2020-07-20 18:07:02 +00:00
|
|
|
|
gin_helper::ErrorThrower(args->isolate())
|
2021-01-04 20:58:31 +00:00
|
|
|
|
.ThrowError("'icon' parameter is required");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NativeImage* icon = nullptr;
|
|
|
|
|
if (!NativeImage::TryConvertNativeImage(args->isolate(), icon_value, &icon) ||
|
|
|
|
|
icon->image().IsEmpty()) {
|
2016-07-03 04:58:31 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start dragging.
|
|
|
|
|
if (!files.empty()) {
|
2022-12-05 22:59:19 +00:00
|
|
|
|
base::CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop allow;
|
2016-07-03 04:58:31 +00:00
|
|
|
|
DragFileItems(files, icon->image(), web_contents()->GetNativeView());
|
|
|
|
|
} else {
|
2020-07-20 18:07:02 +00:00
|
|
|
|
gin_helper::ErrorThrower(args->isolate())
|
|
|
|
|
.ThrowError("Must specify either 'file' or 'files' option");
|
2016-07-03 04:58:31 +00:00
|
|
|
|
}
|
2016-07-03 03:26:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-20 18:07:02 +00:00
|
|
|
|
v8::Local<v8::Promise> WebContents::CapturePage(gin::Arguments* args) {
|
2020-07-16 21:11:44 +00:00
|
|
|
|
gin_helper::Promise<gfx::Image> promise(args->isolate());
|
2019-02-21 12:32:44 +00:00
|
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
2016-07-05 22:43:57 +00:00
|
|
|
|
|
2022-10-05 17:51:33 +00:00
|
|
|
|
gfx::Rect rect;
|
2018-11-28 04:50:53 +00:00
|
|
|
|
args->GetNext(&rect);
|
2016-07-05 22:43:57 +00:00
|
|
|
|
|
2022-10-05 17:51:33 +00:00
|
|
|
|
bool stay_hidden = false;
|
|
|
|
|
bool stay_awake = false;
|
|
|
|
|
if (args && args->Length() == 2) {
|
|
|
|
|
gin_helper::Dictionary options;
|
|
|
|
|
if (args->GetNext(&options)) {
|
|
|
|
|
options.Get("stayHidden", &stay_hidden);
|
|
|
|
|
options.Get("stayAwake", &stay_awake);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* const view = web_contents()->GetRenderWidgetHostView();
|
2023-10-12 07:35:23 +00:00
|
|
|
|
if (!view || view->GetViewBounds().size().IsEmpty()) {
|
2019-11-01 06:10:32 +00:00
|
|
|
|
promise.Resolve(gfx::Image());
|
2019-02-21 12:32:44 +00:00
|
|
|
|
return handle;
|
2016-07-05 22:43:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-12 07:35:23 +00:00
|
|
|
|
if (!view->IsSurfaceAvailableForCopy()) {
|
|
|
|
|
promise.RejectWithErrorMessage(
|
|
|
|
|
"Current display surface not available for capture");
|
2021-03-15 22:43:25 +00:00
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-05 17:51:33 +00:00
|
|
|
|
auto capture_handle = web_contents()->IncrementCapturerCount(
|
2024-07-05 07:51:21 +00:00
|
|
|
|
rect.size(), stay_hidden, stay_awake, /*is_activity=*/true);
|
2022-10-05 17:51:33 +00:00
|
|
|
|
|
2016-07-05 22:43:57 +00:00
|
|
|
|
// Capture full page if user doesn't specify a |rect|.
|
2018-04-18 01:55:30 +00:00
|
|
|
|
const gfx::Size view_size =
|
|
|
|
|
rect.IsEmpty() ? view->GetViewBounds().size() : rect.size();
|
2016-07-05 22:43:57 +00:00
|
|
|
|
|
|
|
|
|
// By default, the requested bitmap size is the view size in screen
|
|
|
|
|
// coordinates. However, if there's more pixel detail available on the
|
|
|
|
|
// current system, increase the requested bitmap size to capture it all.
|
|
|
|
|
gfx::Size bitmap_size = view_size;
|
|
|
|
|
const gfx::NativeView native_view = view->GetNativeView();
|
2018-04-18 01:55:30 +00:00
|
|
|
|
const float scale = display::Screen::GetScreen()
|
|
|
|
|
->GetDisplayNearestView(native_view)
|
|
|
|
|
.device_scale_factor();
|
2016-07-05 22:43:57 +00:00
|
|
|
|
if (scale > 1.0f)
|
|
|
|
|
bitmap_size = gfx::ScaleToCeiledSize(view_size, scale);
|
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
|
view->CopyFromSurface(gfx::Rect(rect.origin(), view_size), bitmap_size,
|
2022-10-05 17:51:33 +00:00
|
|
|
|
base::BindOnce(&OnCapturePageDone, std::move(promise),
|
|
|
|
|
std::move(capture_handle)));
|
2019-02-21 12:32:44 +00:00
|
|
|
|
return handle;
|
2016-07-05 22:43:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-25 00:43:42 +00:00
|
|
|
|
bool WebContents::IsBeingCaptured() {
|
|
|
|
|
return web_contents()->IsBeingCaptured();
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-03 11:43:42 +00:00
|
|
|
|
void WebContents::OnCursorChanged(const ui::Cursor& cursor) {
|
2020-03-14 20:54:14 +00:00
|
|
|
|
if (cursor.type() == ui::mojom::CursorType::kCustom) {
|
2023-06-12 07:55:22 +00:00
|
|
|
|
Emit("cursor-changed", CursorTypeToString(cursor.type()),
|
2020-03-14 20:54:14 +00:00
|
|
|
|
gfx::Image::CreateFrom1xBitmap(cursor.custom_bitmap()),
|
|
|
|
|
cursor.image_scale_factor(),
|
|
|
|
|
gfx::Size(cursor.custom_bitmap().width(),
|
|
|
|
|
cursor.custom_bitmap().height()),
|
|
|
|
|
cursor.custom_hotspot());
|
2016-01-31 16:00:14 +00:00
|
|
|
|
} else {
|
2023-06-12 07:55:22 +00:00
|
|
|
|
Emit("cursor-changed", CursorTypeToString(cursor.type()));
|
2016-01-31 16:00:14 +00:00
|
|
|
|
}
|
2016-01-30 05:33:55 +00:00
|
|
|
|
}
|
2016-07-18 06:54:52 +00:00
|
|
|
|
|
2018-08-16 22:57:40 +00:00
|
|
|
|
void WebContents::AttachToIframe(content::WebContents* embedder_web_contents,
|
|
|
|
|
int embedder_frame_id) {
|
2021-03-15 22:43:25 +00:00
|
|
|
|
attached_ = true;
|
2018-08-16 22:57:40 +00:00
|
|
|
|
if (guest_delegate_)
|
|
|
|
|
guest_delegate_->AttachToIframe(embedder_web_contents, embedder_frame_id);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 10:10:56 +00:00
|
|
|
|
bool WebContents::IsOffScreen() const {
|
2020-10-27 17:51:45 +00:00
|
|
|
|
return type_ == Type::kOffScreen;
|
2016-07-28 10:10:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-04 04:47:52 +00:00
|
|
|
|
void WebContents::OnPaint(const gfx::Rect& dirty_rect, const SkBitmap& bitmap) {
|
2017-04-12 14:16:27 +00:00
|
|
|
|
Emit("paint", dirty_rect, gfx::Image::CreateFrom1xBitmap(bitmap));
|
2016-08-03 03:29:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::StartPainting() {
|
2018-03-20 01:25:51 +00:00
|
|
|
|
auto* osr_wcv = GetOffScreenWebContentsView();
|
2018-01-25 13:46:30 +00:00
|
|
|
|
if (osr_wcv)
|
|
|
|
|
osr_wcv->SetPainting(true);
|
2016-08-03 03:29:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::StopPainting() {
|
2018-03-20 01:25:51 +00:00
|
|
|
|
auto* osr_wcv = GetOffScreenWebContentsView();
|
2018-01-25 13:46:30 +00:00
|
|
|
|
if (osr_wcv)
|
|
|
|
|
osr_wcv->SetPainting(false);
|
2016-08-03 03:29:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::IsPainting() const {
|
2018-03-20 01:25:51 +00:00
|
|
|
|
auto* osr_wcv = GetOffScreenWebContentsView();
|
2018-01-25 13:46:30 +00:00
|
|
|
|
return osr_wcv && osr_wcv->IsPainting();
|
2016-08-03 03:29:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::SetFrameRate(int frame_rate) {
|
2018-03-20 01:25:51 +00:00
|
|
|
|
auto* osr_wcv = GetOffScreenWebContentsView();
|
2018-01-25 13:46:30 +00:00
|
|
|
|
if (osr_wcv)
|
|
|
|
|
osr_wcv->SetFrameRate(frame_rate);
|
2016-08-03 03:29:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int WebContents::GetFrameRate() const {
|
2018-03-20 01:25:51 +00:00
|
|
|
|
auto* osr_wcv = GetOffScreenWebContentsView();
|
2018-01-25 13:46:30 +00:00
|
|
|
|
return osr_wcv ? osr_wcv->GetFrameRate() : 0;
|
2016-08-03 03:29:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-01 17:25:12 +00:00
|
|
|
|
void WebContents::Invalidate() {
|
2017-02-08 07:08:03 +00:00
|
|
|
|
if (IsOffScreen()) {
|
2018-05-15 01:59:22 +00:00
|
|
|
|
auto* osr_rwhv = GetOffScreenRenderWidgetHostView();
|
2017-02-08 07:08:03 +00:00
|
|
|
|
if (osr_rwhv)
|
|
|
|
|
osr_rwhv->Invalidate();
|
2017-02-08 08:05:16 +00:00
|
|
|
|
} else {
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* const window = owner_window();
|
2017-02-14 20:30:23 +00:00
|
|
|
|
if (window)
|
|
|
|
|
window->Invalidate();
|
2017-02-08 07:08:03 +00:00
|
|
|
|
}
|
2016-09-01 17:25:12 +00:00
|
|
|
|
}
|
2016-08-03 03:29:55 +00:00
|
|
|
|
|
2019-07-03 01:22:09 +00:00
|
|
|
|
gfx::Size WebContents::GetSizeForNewRenderView(content::WebContents* wc) {
|
2017-05-11 21:48:14 +00:00
|
|
|
|
if (IsOffScreen() && wc == web_contents()) {
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* relay = NativeWindowRelay::FromWebContents(web_contents());
|
2017-05-11 21:48:14 +00:00
|
|
|
|
if (relay) {
|
2018-10-02 22:14:43 +00:00
|
|
|
|
auto* owner_window = relay->GetNativeWindow();
|
|
|
|
|
return owner_window ? owner_window->GetSize() : gfx::Size();
|
2017-05-11 21:48:14 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return gfx::Size();
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-29 14:13:20 +00:00
|
|
|
|
void WebContents::SetZoomLevel(double level) {
|
2017-01-30 11:18:40 +00:00
|
|
|
|
zoom_controller_->SetZoomLevel(level);
|
2017-01-29 14:13:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-09 17:15:23 +00:00
|
|
|
|
double WebContents::GetZoomLevel() const {
|
2017-01-30 11:18:40 +00:00
|
|
|
|
return zoom_controller_->GetZoomLevel();
|
2017-01-29 14:13:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 23:13:05 +00:00
|
|
|
|
void WebContents::SetZoomFactor(gin_helper::ErrorThrower thrower,
|
|
|
|
|
double factor) {
|
|
|
|
|
if (factor < std::numeric_limits<double>::epsilon()) {
|
|
|
|
|
thrower.ThrowError("'zoomFactor' must be a double greater than 0.0");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-02 07:51:33 +00:00
|
|
|
|
auto level = blink::ZoomFactorToZoomLevel(factor);
|
2017-01-29 14:13:20 +00:00
|
|
|
|
SetZoomLevel(level);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-09 17:15:23 +00:00
|
|
|
|
double WebContents::GetZoomFactor() const {
|
2017-01-29 14:13:20 +00:00
|
|
|
|
auto level = GetZoomLevel();
|
2024-07-02 07:51:33 +00:00
|
|
|
|
return blink::ZoomLevelToZoomFactor(level);
|
2019-10-18 19:57:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-06-04 01:18:23 +00:00
|
|
|
|
void WebContents::SetTemporaryZoomLevel(double level) {
|
2017-01-30 17:06:50 +00:00
|
|
|
|
zoom_controller_->SetTemporaryZoomLevel(level);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-14 18:57:36 +00:00
|
|
|
|
void WebContents::DoGetZoomLevel(
|
2022-03-19 02:50:05 +00:00
|
|
|
|
electron::mojom::ElectronWebContentsUtility::DoGetZoomLevelCallback
|
|
|
|
|
callback) {
|
2019-06-04 01:18:23 +00:00
|
|
|
|
std::move(callback).Run(GetZoomLevel());
|
2016-09-01 17:25:12 +00:00
|
|
|
|
}
|
2016-08-03 03:29:55 +00:00
|
|
|
|
|
2020-11-10 17:06:03 +00:00
|
|
|
|
std::vector<base::FilePath> WebContents::GetPreloadPaths() const {
|
2019-07-03 15:05:45 +00:00
|
|
|
|
auto result = SessionPreferences::GetValidPreloads(GetBrowserContext());
|
|
|
|
|
|
2018-08-10 22:19:49 +00:00
|
|
|
|
if (auto* web_preferences = WebContentsPreferences::From(web_contents())) {
|
2024-07-19 17:26:57 +00:00
|
|
|
|
if (auto preload = web_preferences->GetPreloadPath()) {
|
|
|
|
|
result.emplace_back(*preload);
|
2018-08-10 22:19:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-07-03 15:05:45 +00:00
|
|
|
|
|
|
|
|
|
return result;
|
2018-08-10 22:19:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-09 17:15:23 +00:00
|
|
|
|
v8::Local<v8::Value> WebContents::GetLastWebPreferences(
|
|
|
|
|
v8::Isolate* isolate) const {
|
|
|
|
|
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
2018-03-15 04:56:46 +00:00
|
|
|
|
if (!web_preferences)
|
|
|
|
|
return v8::Null(isolate);
|
2019-10-25 13:03:28 +00:00
|
|
|
|
return gin::ConvertToV8(isolate, *web_preferences->last_preference());
|
2018-03-15 04:56:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-16 21:11:44 +00:00
|
|
|
|
v8::Local<v8::Value> WebContents::GetOwnerBrowserWindow(
|
|
|
|
|
v8::Isolate* isolate) const {
|
2015-10-01 05:45:59 +00:00
|
|
|
|
if (owner_window())
|
2020-07-16 21:11:44 +00:00
|
|
|
|
return BrowserWindow::From(isolate, owner_window());
|
2015-10-01 05:45:59 +00:00
|
|
|
|
else
|
2020-07-16 21:11:44 +00:00
|
|
|
|
return v8::Null(isolate);
|
2015-10-01 05:45:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-01 03:14:19 +00:00
|
|
|
|
v8::Local<v8::Value> WebContents::Session(v8::Isolate* isolate) {
|
|
|
|
|
return v8::Local<v8::Value>::New(isolate, session_);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-19 20:13:24 +00:00
|
|
|
|
content::WebContents* WebContents::HostWebContents() const {
|
2016-02-17 08:52:19 +00:00
|
|
|
|
if (!embedder_)
|
|
|
|
|
return nullptr;
|
|
|
|
|
return embedder_->web_contents();
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-08 17:01:01 +00:00
|
|
|
|
void WebContents::SetEmbedder(const WebContents* embedder) {
|
|
|
|
|
if (embedder) {
|
|
|
|
|
NativeWindow* owner_window = nullptr;
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* relay = NativeWindowRelay::FromWebContents(embedder->web_contents());
|
2016-09-08 17:01:01 +00:00
|
|
|
|
if (relay) {
|
2018-10-02 22:14:43 +00:00
|
|
|
|
owner_window = relay->GetNativeWindow();
|
2016-09-08 17:01:01 +00:00
|
|
|
|
}
|
|
|
|
|
if (owner_window)
|
|
|
|
|
SetOwnerWindow(owner_window);
|
|
|
|
|
|
|
|
|
|
content::RenderWidgetHostView* rwhv =
|
|
|
|
|
web_contents()->GetRenderWidgetHostView();
|
|
|
|
|
if (rwhv) {
|
|
|
|
|
rwhv->Hide();
|
|
|
|
|
rwhv->Show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-30 07:37:26 +00:00
|
|
|
|
void WebContents::SetDevToolsWebContents(const WebContents* devtools) {
|
2020-11-17 22:15:20 +00:00
|
|
|
|
if (inspectable_web_contents_)
|
|
|
|
|
inspectable_web_contents_->SetDevToolsWebContents(devtools->web_contents());
|
2017-11-30 07:37:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-16 21:11:44 +00:00
|
|
|
|
v8::Local<v8::Value> WebContents::GetNativeView(v8::Isolate* isolate) const {
|
2017-08-21 10:50:12 +00:00
|
|
|
|
gfx::NativeView ptr = web_contents()->GetNativeView();
|
2020-07-16 21:11:44 +00:00
|
|
|
|
auto buffer = node::Buffer::Copy(isolate, reinterpret_cast<char*>(&ptr),
|
2018-04-18 01:55:30 +00:00
|
|
|
|
sizeof(gfx::NativeView));
|
2017-08-21 10:50:12 +00:00
|
|
|
|
if (buffer.IsEmpty())
|
2020-07-16 21:11:44 +00:00
|
|
|
|
return v8::Null(isolate);
|
2017-08-21 10:50:12 +00:00
|
|
|
|
else
|
|
|
|
|
return buffer.ToLocalChecked();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-01 03:14:19 +00:00
|
|
|
|
v8::Local<v8::Value> WebContents::DevToolsWebContents(v8::Isolate* isolate) {
|
|
|
|
|
if (devtools_web_contents_.IsEmpty())
|
|
|
|
|
return v8::Null(isolate);
|
|
|
|
|
else
|
|
|
|
|
return v8::Local<v8::Value>::New(isolate, devtools_web_contents_);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-21 18:22:23 +00:00
|
|
|
|
v8::Local<v8::Value> WebContents::Debugger(v8::Isolate* isolate) {
|
|
|
|
|
if (debugger_.IsEmpty()) {
|
|
|
|
|
auto handle = electron::api::Debugger::Create(isolate, web_contents());
|
|
|
|
|
debugger_.Reset(isolate, handle.ToV8());
|
|
|
|
|
}
|
|
|
|
|
return v8::Local<v8::Value>::New(isolate, debugger_);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-09 16:50:46 +00:00
|
|
|
|
content::RenderFrameHost* WebContents::MainFrame() {
|
2022-06-27 20:50:08 +00:00
|
|
|
|
return web_contents()->GetPrimaryMainFrame();
|
2020-10-09 16:50:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-26 16:37:08 +00:00
|
|
|
|
content::RenderFrameHost* WebContents::Opener() {
|
|
|
|
|
return web_contents()->GetOpener();
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 13:21:38 +00:00
|
|
|
|
void WebContents::NotifyUserActivation() {
|
2022-06-27 20:50:08 +00:00
|
|
|
|
content::RenderFrameHost* frame = web_contents()->GetPrimaryMainFrame();
|
2021-02-09 20:16:21 +00:00
|
|
|
|
if (frame)
|
|
|
|
|
frame->NotifyUserActivation(
|
|
|
|
|
blink::mojom::UserActivationNotificationType::kInteraction);
|
2020-05-26 13:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-08 02:00:22 +00:00
|
|
|
|
void WebContents::SetImageAnimationPolicy(const std::string& new_policy) {
|
|
|
|
|
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
2021-07-26 16:04:09 +00:00
|
|
|
|
web_preferences->SetImageAnimationPolicy(new_policy);
|
2021-06-08 02:00:22 +00:00
|
|
|
|
web_contents()->OnWebPreferencesChanged();
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-10 22:23:35 +00:00
|
|
|
|
void WebContents::SetBackgroundColor(std::optional<SkColor> maybe_color) {
|
2024-02-09 09:29:14 +00:00
|
|
|
|
SkColor color = maybe_color.value_or((is_guest() && guest_transparent_) ||
|
2024-01-04 15:04:56 +00:00
|
|
|
|
type_ == Type::kBrowserView
|
|
|
|
|
? SK_ColorTRANSPARENT
|
|
|
|
|
: SK_ColorWHITE);
|
2024-07-16 18:11:49 +00:00
|
|
|
|
bool is_opaque = SkColorGetA(color) == SK_AlphaOPAQUE;
|
2024-01-04 15:04:56 +00:00
|
|
|
|
web_contents()->SetPageBaseBackgroundColor(color);
|
2023-12-13 21:01:03 +00:00
|
|
|
|
|
|
|
|
|
content::RenderFrameHost* rfh = web_contents()->GetPrimaryMainFrame();
|
|
|
|
|
if (!rfh)
|
|
|
|
|
return;
|
2024-07-16 18:11:49 +00:00
|
|
|
|
|
2023-12-13 21:01:03 +00:00
|
|
|
|
content::RenderWidgetHostView* rwhv = rfh->GetView();
|
|
|
|
|
if (rwhv) {
|
2024-07-16 18:11:49 +00:00
|
|
|
|
// RenderWidgetHostView doesn't allow setting an alpha that's not 0 or 255.
|
|
|
|
|
rwhv->SetBackgroundColor(is_opaque ? color : SK_ColorTRANSPARENT);
|
2023-12-13 21:01:03 +00:00
|
|
|
|
static_cast<content::RenderWidgetHostViewBase*>(rwhv)
|
|
|
|
|
->SetContentBackgroundColor(color);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 22:16:22 +00:00
|
|
|
|
void WebContents::PDFReadyToPrint() {
|
|
|
|
|
Emit("-pdf-ready-to-print");
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-27 19:47:46 +00:00
|
|
|
|
void WebContents::OnInputEvent(const blink::WebInputEvent& event) {
|
|
|
|
|
Emit("input-event", event);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-06 01:36:23 +00:00
|
|
|
|
void WebContents::RunJavaScriptDialog(content::WebContents* web_contents,
|
|
|
|
|
content::RenderFrameHost* rfh,
|
|
|
|
|
content::JavaScriptDialogType dialog_type,
|
|
|
|
|
const std::u16string& message_text,
|
|
|
|
|
const std::u16string& default_prompt_text,
|
|
|
|
|
DialogClosedCallback callback,
|
|
|
|
|
bool* did_suppress_message) {
|
|
|
|
|
CHECK_EQ(web_contents, this->web_contents());
|
|
|
|
|
|
|
|
|
|
auto* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope scope(isolate);
|
|
|
|
|
auto info = gin::DataObjectBuilder(isolate)
|
|
|
|
|
.Set("frame", rfh)
|
|
|
|
|
.Set("dialogType", dialog_type)
|
|
|
|
|
.Set("messageText", message_text)
|
|
|
|
|
.Set("defaultPromptText", default_prompt_text)
|
|
|
|
|
.Build();
|
|
|
|
|
|
|
|
|
|
EmitWithoutEvent("-run-dialog", info, std::move(callback));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::RunBeforeUnloadDialog(content::WebContents* web_contents,
|
|
|
|
|
content::RenderFrameHost* rfh,
|
|
|
|
|
bool is_reload,
|
|
|
|
|
DialogClosedCallback callback) {
|
|
|
|
|
// TODO: asyncify?
|
|
|
|
|
bool default_prevented = Emit("will-prevent-unload");
|
|
|
|
|
std::move(callback).Run(default_prevented, std::u16string());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::CancelDialogs(content::WebContents* web_contents,
|
|
|
|
|
bool reset_state) {
|
|
|
|
|
auto* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
|
v8::HandleScope scope(isolate);
|
|
|
|
|
EmitWithoutEvent(
|
|
|
|
|
"-cancel-dialogs",
|
|
|
|
|
gin::DataObjectBuilder(isolate).Set("resetState", reset_state).Build());
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-05 22:30:31 +00:00
|
|
|
|
v8::Local<v8::Promise> WebContents::GetProcessMemoryInfo(v8::Isolate* isolate) {
|
|
|
|
|
gin_helper::Promise<gin_helper::Dictionary> promise(isolate);
|
|
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
|
|
|
|
|
2022-06-27 20:50:08 +00:00
|
|
|
|
auto* frame_host = web_contents()->GetPrimaryMainFrame();
|
2021-10-05 22:30:31 +00:00
|
|
|
|
if (!frame_host) {
|
|
|
|
|
promise.RejectWithErrorMessage("Failed to create memory dump");
|
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto pid = frame_host->GetProcess()->GetProcess().Pid();
|
|
|
|
|
v8::Global<v8::Context> context(isolate, isolate->GetCurrentContext());
|
|
|
|
|
memory_instrumentation::MemoryInstrumentation::GetInstance()
|
|
|
|
|
->RequestGlobalDumpForPid(
|
|
|
|
|
pid, std::vector<std::string>(),
|
|
|
|
|
base::BindOnce(&ElectronBindings::DidReceiveMemoryDump,
|
|
|
|
|
std::move(context), std::move(promise), pid));
|
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-29 17:11:11 +00:00
|
|
|
|
v8::Local<v8::Promise> WebContents::TakeHeapSnapshot(
|
2020-07-16 21:11:44 +00:00
|
|
|
|
v8::Isolate* isolate,
|
2019-04-29 17:11:11 +00:00
|
|
|
|
const base::FilePath& file_path) {
|
2020-07-16 21:11:44 +00:00
|
|
|
|
gin_helper::Promise<void> promise(isolate);
|
2019-04-29 17:11:11 +00:00
|
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
2018-09-18 18:00:31 +00:00
|
|
|
|
|
2022-11-17 19:59:23 +00:00
|
|
|
|
ScopedAllowBlockingForElectron allow_blocking;
|
2023-02-03 11:43:42 +00:00
|
|
|
|
uint32_t flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE;
|
|
|
|
|
// The snapshot file is passed to an untrusted process.
|
|
|
|
|
flags = base::File::AddFlagsForPassingToUntrustedProcess(flags);
|
|
|
|
|
base::File file(file_path, flags);
|
2019-04-02 22:38:16 +00:00
|
|
|
|
if (!file.IsValid()) {
|
2023-03-01 15:50:36 +00:00
|
|
|
|
promise.RejectWithErrorMessage(
|
|
|
|
|
"Failed to take heap snapshot with invalid file path " +
|
|
|
|
|
#if BUILDFLAG(IS_WIN)
|
|
|
|
|
base::WideToUTF8(file_path.value()));
|
|
|
|
|
#else
|
|
|
|
|
file_path.value());
|
|
|
|
|
#endif
|
2019-04-29 17:11:11 +00:00
|
|
|
|
return handle;
|
2019-04-02 22:38:16 +00:00
|
|
|
|
}
|
2018-09-18 18:00:31 +00:00
|
|
|
|
|
2022-06-27 20:50:08 +00:00
|
|
|
|
auto* frame_host = web_contents()->GetPrimaryMainFrame();
|
2019-04-02 22:38:16 +00:00
|
|
|
|
if (!frame_host) {
|
2023-03-01 15:50:36 +00:00
|
|
|
|
promise.RejectWithErrorMessage(
|
|
|
|
|
"Failed to take heap snapshot with invalid webContents main frame");
|
2019-04-29 17:11:11 +00:00
|
|
|
|
return handle;
|
2019-04-02 22:38:16 +00:00
|
|
|
|
}
|
2018-09-18 18:00:31 +00:00
|
|
|
|
|
2022-06-27 20:50:08 +00:00
|
|
|
|
if (!frame_host->IsRenderFrameLive()) {
|
2023-03-01 15:50:36 +00:00
|
|
|
|
promise.RejectWithErrorMessage(
|
|
|
|
|
"Failed to take heap snapshot with nonexistent render frame");
|
2021-02-09 20:16:21 +00:00
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-02 22:38:16 +00:00
|
|
|
|
// This dance with `base::Owned` is to ensure that the interface stays alive
|
|
|
|
|
// until the callback is called. Otherwise it would be closed at the end of
|
|
|
|
|
// this function.
|
2019-10-28 22:12:35 +00:00
|
|
|
|
auto electron_renderer =
|
2021-02-09 20:16:21 +00:00
|
|
|
|
std::make_unique<mojo::Remote<mojom::ElectronRenderer>>();
|
|
|
|
|
frame_host->GetRemoteInterfaces()->GetInterface(
|
|
|
|
|
electron_renderer->BindNewPipeAndPassReceiver());
|
2019-10-28 22:12:35 +00:00
|
|
|
|
auto* raw_ptr = electron_renderer.get();
|
2019-04-02 22:38:16 +00:00
|
|
|
|
(*raw_ptr)->TakeHeapSnapshot(
|
2020-10-28 00:33:04 +00:00
|
|
|
|
mojo::WrapPlatformFile(base::ScopedPlatformFile(file.TakePlatformFile())),
|
2019-04-29 17:11:11 +00:00
|
|
|
|
base::BindOnce(
|
2021-02-09 20:16:21 +00:00
|
|
|
|
[](mojo::Remote<mojom::ElectronRenderer>* ep,
|
2019-11-01 06:10:32 +00:00
|
|
|
|
gin_helper::Promise<void> promise, bool success) {
|
2019-04-29 17:11:11 +00:00
|
|
|
|
if (success) {
|
|
|
|
|
promise.Resolve();
|
|
|
|
|
} else {
|
2023-03-01 15:50:36 +00:00
|
|
|
|
promise.RejectWithErrorMessage("Failed to take heap snapshot");
|
2019-04-29 17:11:11 +00:00
|
|
|
|
}
|
|
|
|
|
},
|
2019-10-28 22:12:35 +00:00
|
|
|
|
base::Owned(std::move(electron_renderer)), std::move(promise)));
|
2019-04-29 17:11:11 +00:00
|
|
|
|
return handle;
|
2018-09-18 18:00:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-21 22:44:19 +00:00
|
|
|
|
void WebContents::UpdatePreferredSize(content::WebContents* web_contents,
|
|
|
|
|
const gfx::Size& pref_size) {
|
|
|
|
|
Emit("preferred-size-changed", pref_size);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
bool WebContents::CanOverscrollContent() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-21 21:02:29 +00:00
|
|
|
|
std::unique_ptr<content::EyeDropper> WebContents::OpenEyeDropper(
|
|
|
|
|
content::RenderFrameHost* frame,
|
|
|
|
|
content::EyeDropperListener* listener) {
|
|
|
|
|
return ShowEyeDropper(frame, listener);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
void WebContents::RunFileChooser(
|
|
|
|
|
content::RenderFrameHost* render_frame_host,
|
|
|
|
|
scoped_refptr<content::FileSelectListener> listener,
|
|
|
|
|
const blink::mojom::FileChooserParams& params) {
|
2021-09-14 10:16:34 +00:00
|
|
|
|
FileSelectHelper::RunFileChooser(render_frame_host, std::move(listener),
|
|
|
|
|
params);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::EnumerateDirectory(
|
2021-09-14 10:16:34 +00:00
|
|
|
|
content::WebContents* web_contents,
|
2020-11-10 17:06:56 +00:00
|
|
|
|
scoped_refptr<content::FileSelectListener> listener,
|
|
|
|
|
const base::FilePath& path) {
|
2021-09-14 10:16:34 +00:00
|
|
|
|
FileSelectHelper::EnumerateDirectory(web_contents, std::move(listener), path);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::IsFullscreenForTabOrPending(
|
|
|
|
|
const content::WebContents* source) {
|
2022-08-01 20:52:58 +00:00
|
|
|
|
if (!owner_window())
|
2023-02-21 11:11:34 +00:00
|
|
|
|
return is_html_fullscreen();
|
2022-08-01 20:52:58 +00:00
|
|
|
|
|
|
|
|
|
bool in_transition = owner_window()->fullscreen_transition_state() !=
|
2023-05-12 13:24:01 +00:00
|
|
|
|
NativeWindow::FullScreenTransitionState::kNone;
|
2022-08-01 20:52:58 +00:00
|
|
|
|
bool is_html_transition = owner_window()->fullscreen_transition_type() ==
|
2023-05-12 13:24:01 +00:00
|
|
|
|
NativeWindow::FullScreenTransitionType::kHTML;
|
2022-06-07 16:59:50 +00:00
|
|
|
|
|
2023-02-21 11:11:34 +00:00
|
|
|
|
return is_html_fullscreen() || (in_transition && is_html_transition);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-03 13:55:47 +00:00
|
|
|
|
content::FullscreenState WebContents::GetFullscreenState(
|
|
|
|
|
const content::WebContents* source) const {
|
2023-06-09 20:28:11 +00:00
|
|
|
|
// `const_cast` here because EAM does not have const getters
|
|
|
|
|
return const_cast<ExclusiveAccessManager*>(&exclusive_access_manager_)
|
|
|
|
|
->fullscreen_controller()
|
|
|
|
|
->GetFullscreenState(source);
|
2023-05-03 13:55:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
bool WebContents::TakeFocus(content::WebContents* source, bool reverse) {
|
|
|
|
|
if (source && source->GetOutermostWebContents() == source) {
|
|
|
|
|
// If this is the outermost web contents and the user has tabbed or
|
|
|
|
|
// shift + tabbed through all the elements, reset the focus back to
|
|
|
|
|
// the first or last element so that it doesn't stay in the body.
|
|
|
|
|
source->FocusThroughTabTraversal(reverse);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
content::PictureInPictureResult WebContents::EnterPictureInPicture(
|
2022-02-25 18:17:35 +00:00
|
|
|
|
content::WebContents* web_contents) {
|
|
|
|
|
return PictureInPictureWindowManager::GetInstance()
|
|
|
|
|
->EnterVideoPictureInPicture(web_contents);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::ExitPictureInPicture() {
|
|
|
|
|
PictureInPictureWindowManager::GetInstance()->ExitPictureInPicture();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DevToolsSaveToFile(const std::string& url,
|
|
|
|
|
const std::string& content,
|
2024-06-07 21:18:35 +00:00
|
|
|
|
bool save_as,
|
|
|
|
|
bool is_base64) {
|
2020-11-10 17:06:56 +00:00
|
|
|
|
base::FilePath path;
|
|
|
|
|
auto it = saved_files_.find(url);
|
|
|
|
|
if (it != saved_files_.end() && !save_as) {
|
|
|
|
|
path = it->second;
|
|
|
|
|
} else {
|
|
|
|
|
file_dialog::DialogSettings settings;
|
|
|
|
|
settings.parent_window = owner_window();
|
|
|
|
|
settings.force_detached = offscreen_;
|
|
|
|
|
settings.title = url;
|
|
|
|
|
settings.default_path = base::FilePath::FromUTF8Unsafe(url);
|
|
|
|
|
if (!file_dialog::ShowSaveDialogSync(settings, &path)) {
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction(
|
2022-06-29 16:39:48 +00:00
|
|
|
|
"DevToolsAPI", "canceledSaveURL", base::Value(url));
|
2020-11-10 17:06:56 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
saved_files_[url] = path;
|
|
|
|
|
// Notify DevTools.
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction(
|
2022-06-29 16:39:48 +00:00
|
|
|
|
"DevToolsAPI", "savedURL", base::Value(url),
|
|
|
|
|
base::Value(path.AsUTF8Unsafe()));
|
2024-06-07 21:18:35 +00:00
|
|
|
|
file_task_runner_->PostTask(
|
|
|
|
|
FROM_HERE, base::BindOnce(&WriteToFile, path, content, is_base64));
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DevToolsAppendToFile(const std::string& url,
|
|
|
|
|
const std::string& content) {
|
|
|
|
|
auto it = saved_files_.find(url);
|
|
|
|
|
if (it == saved_files_.end())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Notify DevTools.
|
2022-06-29 16:39:48 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction("DevToolsAPI", "appendedToURL",
|
|
|
|
|
base::Value(url));
|
2020-11-10 17:06:56 +00:00
|
|
|
|
file_task_runner_->PostTask(
|
|
|
|
|
FROM_HERE, base::BindOnce(&AppendToFile, it->second, content));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DevToolsRequestFileSystems() {
|
|
|
|
|
auto file_system_paths = GetAddedFileSystemPaths(GetDevToolsWebContents());
|
|
|
|
|
if (file_system_paths.empty()) {
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction(
|
2022-06-29 16:39:48 +00:00
|
|
|
|
"DevToolsAPI", "fileSystemsLoaded", base::Value(base::Value::List()));
|
2020-11-10 17:06:56 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<FileSystem> file_systems;
|
|
|
|
|
for (const auto& file_system_path : file_system_paths) {
|
|
|
|
|
base::FilePath path =
|
|
|
|
|
base::FilePath::FromUTF8Unsafe(file_system_path.first);
|
|
|
|
|
std::string file_system_id =
|
|
|
|
|
RegisterFileSystem(GetDevToolsWebContents(), path);
|
|
|
|
|
FileSystem file_system =
|
|
|
|
|
CreateFileSystemStruct(GetDevToolsWebContents(), file_system_id,
|
|
|
|
|
file_system_path.first, file_system_path.second);
|
|
|
|
|
file_systems.push_back(file_system);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-29 16:39:48 +00:00
|
|
|
|
base::Value::List file_system_value;
|
2020-11-10 17:06:56 +00:00
|
|
|
|
for (const auto& file_system : file_systems)
|
2022-06-29 16:39:48 +00:00
|
|
|
|
file_system_value.Append(CreateFileSystemValue(file_system));
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction(
|
2022-06-29 16:39:48 +00:00
|
|
|
|
"DevToolsAPI", "fileSystemsLoaded",
|
|
|
|
|
base::Value(std::move(file_system_value)));
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DevToolsAddFileSystem(
|
|
|
|
|
const std::string& type,
|
|
|
|
|
const base::FilePath& file_system_path) {
|
|
|
|
|
base::FilePath path = file_system_path;
|
|
|
|
|
if (path.empty()) {
|
|
|
|
|
std::vector<base::FilePath> paths;
|
|
|
|
|
file_dialog::DialogSettings settings;
|
|
|
|
|
settings.parent_window = owner_window();
|
|
|
|
|
settings.force_detached = offscreen_;
|
|
|
|
|
settings.properties = file_dialog::OPEN_DIALOG_OPEN_DIRECTORY;
|
|
|
|
|
if (!file_dialog::ShowOpenDialogSync(settings, &paths))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
path = paths[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string file_system_id =
|
|
|
|
|
RegisterFileSystem(GetDevToolsWebContents(), path);
|
|
|
|
|
if (IsDevToolsFileSystemAdded(GetDevToolsWebContents(), path.AsUTF8Unsafe()))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
FileSystem file_system = CreateFileSystemStruct(
|
|
|
|
|
GetDevToolsWebContents(), file_system_id, path.AsUTF8Unsafe(), type);
|
2022-06-29 16:39:48 +00:00
|
|
|
|
base::Value::Dict file_system_value = CreateFileSystemValue(file_system);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
|
|
|
|
|
auto* pref_service = GetPrefService(GetDevToolsWebContents());
|
2023-01-06 02:35:34 +00:00
|
|
|
|
ScopedDictPrefUpdate update(pref_service, prefs::kDevToolsFileSystemPaths);
|
|
|
|
|
update->Set(path.AsUTF8Unsafe(), type);
|
2022-06-29 16:39:48 +00:00
|
|
|
|
std::string error = ""; // No error
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction(
|
2022-06-29 16:39:48 +00:00
|
|
|
|
"DevToolsAPI", "fileSystemAdded", base::Value(error),
|
|
|
|
|
base::Value(std::move(file_system_value)));
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DevToolsRemoveFileSystem(
|
|
|
|
|
const base::FilePath& file_system_path) {
|
2020-11-17 22:15:20 +00:00
|
|
|
|
if (!inspectable_web_contents_)
|
2020-11-10 17:06:56 +00:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
std::string path = file_system_path.AsUTF8Unsafe();
|
|
|
|
|
storage::IsolatedContext::GetInstance()->RevokeFileSystemByPath(
|
|
|
|
|
file_system_path);
|
|
|
|
|
|
|
|
|
|
auto* pref_service = GetPrefService(GetDevToolsWebContents());
|
2023-01-06 02:35:34 +00:00
|
|
|
|
ScopedDictPrefUpdate update(pref_service, prefs::kDevToolsFileSystemPaths);
|
|
|
|
|
update->Remove(path);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
|
2022-06-29 16:39:48 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction(
|
|
|
|
|
"DevToolsAPI", "fileSystemRemoved", base::Value(path));
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DevToolsIndexPath(
|
|
|
|
|
int request_id,
|
|
|
|
|
const std::string& file_system_path,
|
|
|
|
|
const std::string& excluded_folders_message) {
|
|
|
|
|
if (!IsDevToolsFileSystemAdded(GetDevToolsWebContents(), file_system_path)) {
|
|
|
|
|
OnDevToolsIndexingDone(request_id, file_system_path);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (devtools_indexing_jobs_.count(request_id) != 0)
|
|
|
|
|
return;
|
|
|
|
|
std::vector<std::string> excluded_folders;
|
2024-01-10 22:23:35 +00:00
|
|
|
|
std::optional<base::Value> parsed_excluded_folders =
|
2023-03-10 16:07:42 +00:00
|
|
|
|
base::JSONReader::Read(excluded_folders_message);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
if (parsed_excluded_folders && parsed_excluded_folders->is_list()) {
|
2023-01-06 02:35:34 +00:00
|
|
|
|
for (const base::Value& folder_path : parsed_excluded_folders->GetList()) {
|
2020-11-10 17:06:56 +00:00
|
|
|
|
if (folder_path.is_string())
|
|
|
|
|
excluded_folders.push_back(folder_path.GetString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
devtools_indexing_jobs_[request_id] =
|
|
|
|
|
scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>(
|
|
|
|
|
devtools_file_system_indexer_->IndexPath(
|
|
|
|
|
file_system_path, excluded_folders,
|
|
|
|
|
base::BindRepeating(
|
|
|
|
|
&WebContents::OnDevToolsIndexingWorkCalculated,
|
|
|
|
|
weak_factory_.GetWeakPtr(), request_id, file_system_path),
|
|
|
|
|
base::BindRepeating(&WebContents::OnDevToolsIndexingWorked,
|
|
|
|
|
weak_factory_.GetWeakPtr(), request_id,
|
|
|
|
|
file_system_path),
|
|
|
|
|
base::BindRepeating(&WebContents::OnDevToolsIndexingDone,
|
|
|
|
|
weak_factory_.GetWeakPtr(), request_id,
|
|
|
|
|
file_system_path)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DevToolsStopIndexing(int request_id) {
|
|
|
|
|
auto it = devtools_indexing_jobs_.find(request_id);
|
|
|
|
|
if (it == devtools_indexing_jobs_.end())
|
|
|
|
|
return;
|
|
|
|
|
it->second->Stop();
|
|
|
|
|
devtools_indexing_jobs_.erase(it);
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-26 08:54:26 +00:00
|
|
|
|
void WebContents::DevToolsOpenInNewTab(const std::string& url) {
|
|
|
|
|
Emit("devtools-open-url", url);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-29 09:31:13 +00:00
|
|
|
|
void WebContents::DevToolsOpenSearchResultsInNewTab(const std::string& query) {
|
|
|
|
|
Emit("devtools-search-query", query);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 17:06:56 +00:00
|
|
|
|
void WebContents::DevToolsSearchInPath(int request_id,
|
|
|
|
|
const std::string& file_system_path,
|
|
|
|
|
const std::string& query) {
|
|
|
|
|
if (!IsDevToolsFileSystemAdded(GetDevToolsWebContents(), file_system_path)) {
|
|
|
|
|
OnDevToolsSearchCompleted(request_id, file_system_path,
|
|
|
|
|
std::vector<std::string>());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
devtools_file_system_indexer_->SearchInPath(
|
|
|
|
|
file_system_path, query,
|
|
|
|
|
base::BindRepeating(&WebContents::OnDevToolsSearchCompleted,
|
|
|
|
|
weak_factory_.GetWeakPtr(), request_id,
|
|
|
|
|
file_system_path));
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-17 13:42:51 +00:00
|
|
|
|
void WebContents::DevToolsSetEyeDropperActive(bool active) {
|
|
|
|
|
auto* web_contents = GetWebContents();
|
|
|
|
|
if (!web_contents)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (active) {
|
|
|
|
|
eye_dropper_ = std::make_unique<DevToolsEyeDropper>(
|
|
|
|
|
web_contents, base::BindRepeating(&WebContents::ColorPickedInEyeDropper,
|
|
|
|
|
base::Unretained(this)));
|
|
|
|
|
} else {
|
|
|
|
|
eye_dropper_.reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::ColorPickedInEyeDropper(int r, int g, int b, int a) {
|
2022-06-29 16:39:48 +00:00
|
|
|
|
base::Value::Dict color;
|
|
|
|
|
color.Set("r", r);
|
|
|
|
|
color.Set("g", g);
|
|
|
|
|
color.Set("b", b);
|
|
|
|
|
color.Set("a", a);
|
2021-06-17 13:42:51 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction(
|
2022-06-29 16:39:48 +00:00
|
|
|
|
"DevToolsAPI", "eyeDropperPickedColor", base::Value(std::move(color)));
|
2021-06-17 13:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_MAC)
|
2021-06-08 20:22:43 +00:00
|
|
|
|
ui::ImageModel WebContents::GetDevToolsWindowIcon() {
|
|
|
|
|
return owner_window() ? owner_window()->GetWindowAppIcon() : ui::ImageModel{};
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-02-10 02:58:52 +00:00
|
|
|
|
#if BUILDFLAG(IS_LINUX)
|
2020-11-10 17:06:56 +00:00
|
|
|
|
void WebContents::GetDevToolsWindowWMClass(std::string* name,
|
|
|
|
|
std::string* class_name) {
|
|
|
|
|
*class_name = Browser::Get()->GetName();
|
|
|
|
|
*name = base::ToLowerASCII(*class_name);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void WebContents::OnDevToolsIndexingWorkCalculated(
|
|
|
|
|
int request_id,
|
|
|
|
|
const std::string& file_system_path,
|
|
|
|
|
int total_work) {
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction(
|
2022-06-29 16:39:48 +00:00
|
|
|
|
"DevToolsAPI", "indexingTotalWorkCalculated", base::Value(request_id),
|
|
|
|
|
base::Value(file_system_path), base::Value(total_work));
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::OnDevToolsIndexingWorked(int request_id,
|
|
|
|
|
const std::string& file_system_path,
|
|
|
|
|
int worked) {
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction(
|
2022-06-29 16:39:48 +00:00
|
|
|
|
"DevToolsAPI", "indexingWorked", base::Value(request_id),
|
|
|
|
|
base::Value(file_system_path), base::Value(worked));
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::OnDevToolsIndexingDone(int request_id,
|
|
|
|
|
const std::string& file_system_path) {
|
|
|
|
|
devtools_indexing_jobs_.erase(request_id);
|
2022-06-29 16:39:48 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction("DevToolsAPI", "indexingDone",
|
|
|
|
|
base::Value(request_id),
|
|
|
|
|
base::Value(file_system_path));
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::OnDevToolsSearchCompleted(
|
|
|
|
|
int request_id,
|
|
|
|
|
const std::string& file_system_path,
|
|
|
|
|
const std::vector<std::string>& file_paths) {
|
2022-06-29 16:39:48 +00:00
|
|
|
|
base::Value::List file_paths_value;
|
|
|
|
|
for (const auto& file_path : file_paths)
|
2021-10-06 02:21:00 +00:00
|
|
|
|
file_paths_value.Append(file_path);
|
2020-11-17 22:15:20 +00:00
|
|
|
|
inspectable_web_contents_->CallClientFunction(
|
2022-06-29 16:39:48 +00:00
|
|
|
|
"DevToolsAPI", "searchCompleted", base::Value(request_id),
|
|
|
|
|
base::Value(file_system_path), base::Value(std::move(file_paths_value)));
|
2020-11-10 17:06:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::SetHtmlApiFullscreen(bool enter_fullscreen) {
|
|
|
|
|
// Window is already in fullscreen mode, save the state.
|
2023-02-21 11:11:34 +00:00
|
|
|
|
if (enter_fullscreen && owner_window()->IsFullscreen()) {
|
2020-11-10 17:06:56 +00:00
|
|
|
|
native_fullscreen_ = true;
|
2021-07-02 00:56:29 +00:00
|
|
|
|
UpdateHtmlApiFullscreen(true);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Exit html fullscreen state but not window's fullscreen mode.
|
|
|
|
|
if (!enter_fullscreen && native_fullscreen_) {
|
2021-07-02 00:56:29 +00:00
|
|
|
|
UpdateHtmlApiFullscreen(false);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set fullscreen on window if allowed.
|
|
|
|
|
auto* web_preferences = WebContentsPreferences::From(GetWebContents());
|
|
|
|
|
bool html_fullscreenable =
|
2021-07-26 16:04:09 +00:00
|
|
|
|
web_preferences
|
|
|
|
|
? !web_preferences->ShouldDisableHtmlFullscreenWindowResize()
|
|
|
|
|
: true;
|
2020-11-10 17:06:56 +00:00
|
|
|
|
|
2022-06-07 16:59:50 +00:00
|
|
|
|
if (html_fullscreenable)
|
2020-11-10 17:06:56 +00:00
|
|
|
|
owner_window_->SetFullScreen(enter_fullscreen);
|
|
|
|
|
|
2021-07-02 00:56:29 +00:00
|
|
|
|
UpdateHtmlApiFullscreen(enter_fullscreen);
|
2020-11-10 17:06:56 +00:00
|
|
|
|
native_fullscreen_ = false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-02 00:56:29 +00:00
|
|
|
|
void WebContents::UpdateHtmlApiFullscreen(bool fullscreen) {
|
2021-08-17 07:03:45 +00:00
|
|
|
|
if (fullscreen == is_html_fullscreen())
|
2021-07-02 00:56:29 +00:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
html_fullscreen_ = fullscreen;
|
|
|
|
|
|
|
|
|
|
// Notify renderer of the html fullscreen change.
|
|
|
|
|
web_contents()
|
|
|
|
|
->GetRenderViewHost()
|
|
|
|
|
->GetWidget()
|
|
|
|
|
->SynchronizeVisualProperties();
|
|
|
|
|
|
2021-08-17 07:03:45 +00:00
|
|
|
|
// The embedder WebContents is separated from the frame tree of webview, so
|
2021-07-02 00:56:29 +00:00
|
|
|
|
// we must manually sync their fullscreen states.
|
|
|
|
|
if (embedder_)
|
|
|
|
|
embedder_->SetHtmlApiFullscreen(fullscreen);
|
|
|
|
|
|
2021-08-17 07:03:45 +00:00
|
|
|
|
if (fullscreen) {
|
|
|
|
|
Emit("enter-html-full-screen");
|
|
|
|
|
owner_window_->NotifyWindowEnterHtmlFullScreen();
|
|
|
|
|
} else {
|
|
|
|
|
Emit("leave-html-full-screen");
|
|
|
|
|
owner_window_->NotifyWindowLeaveHtmlFullScreen();
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-02 00:56:29 +00:00
|
|
|
|
// Make sure all child webviews quit html fullscreen.
|
2024-02-09 09:29:14 +00:00
|
|
|
|
if (!fullscreen && !is_guest()) {
|
2021-07-02 00:56:29 +00:00
|
|
|
|
auto* manager = WebViewManager::GetWebViewManager(web_contents());
|
2023-11-28 21:40:12 +00:00
|
|
|
|
manager->ForEachGuest(web_contents(), [&](content::WebContents* guest) {
|
|
|
|
|
WebContents* api_web_contents = WebContents::From(guest);
|
|
|
|
|
api_web_contents->SetHtmlApiFullscreen(false);
|
|
|
|
|
return false;
|
|
|
|
|
});
|
2021-07-02 00:56:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-03 08:04:46 +00:00
|
|
|
|
// static
|
2023-02-06 20:59:49 +00:00
|
|
|
|
void WebContents::FillObjectTemplate(v8::Isolate* isolate,
|
|
|
|
|
v8::Local<v8::ObjectTemplate> templ) {
|
2020-07-30 16:17:57 +00:00
|
|
|
|
gin::InvokerOptions options;
|
|
|
|
|
options.holder_is_first_argument = true;
|
2023-07-10 09:49:20 +00:00
|
|
|
|
options.holder_type = GetClassName();
|
2020-07-30 16:17:57 +00:00
|
|
|
|
templ->Set(
|
|
|
|
|
gin::StringToSymbol(isolate, "isDestroyed"),
|
|
|
|
|
gin::CreateFunctionTemplate(
|
|
|
|
|
isolate, base::BindRepeating(&gin_helper::Destroyable::IsDestroyed),
|
|
|
|
|
options));
|
|
|
|
|
// We use gin_helper::ObjectTemplateBuilder instead of
|
|
|
|
|
// gin::ObjectTemplateBuilder here to handle the fact that WebContents is
|
|
|
|
|
// destroyable.
|
2023-02-06 20:59:49 +00:00
|
|
|
|
gin_helper::ObjectTemplateBuilder(isolate, templ)
|
2021-03-15 22:43:25 +00:00
|
|
|
|
.SetMethod("destroy", &WebContents::Destroy)
|
2022-09-16 23:22:59 +00:00
|
|
|
|
.SetMethod("close", &WebContents::Close)
|
2020-05-14 13:11:45 +00:00
|
|
|
|
.SetMethod("getBackgroundThrottling",
|
|
|
|
|
&WebContents::GetBackgroundThrottling)
|
2018-10-19 00:32:22 +00:00
|
|
|
|
.SetMethod("setBackgroundThrottling",
|
|
|
|
|
&WebContents::SetBackgroundThrottling)
|
2016-09-06 01:28:40 +00:00
|
|
|
|
.SetMethod("getProcessId", &WebContents::GetProcessID)
|
2017-04-18 10:31:20 +00:00
|
|
|
|
.SetMethod("getOSProcessId", &WebContents::GetOSProcessID)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("equal", &WebContents::Equal)
|
|
|
|
|
.SetMethod("_loadURL", &WebContents::LoadURL)
|
2021-04-27 23:11:18 +00:00
|
|
|
|
.SetMethod("reload", &WebContents::Reload)
|
|
|
|
|
.SetMethod("reloadIgnoringCache", &WebContents::ReloadIgnoringCache)
|
2015-12-03 18:31:51 +00:00
|
|
|
|
.SetMethod("downloadURL", &WebContents::DownloadURL)
|
2021-04-27 23:11:18 +00:00
|
|
|
|
.SetMethod("getURL", &WebContents::GetURL)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("getTitle", &WebContents::GetTitle)
|
|
|
|
|
.SetMethod("isLoading", &WebContents::IsLoading)
|
2016-04-18 17:37:08 +00:00
|
|
|
|
.SetMethod("isLoadingMainFrame", &WebContents::IsLoadingMainFrame)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
|
2021-04-27 23:11:18 +00:00
|
|
|
|
.SetMethod("stop", &WebContents::Stop)
|
2024-06-05 16:34:47 +00:00
|
|
|
|
.SetMethod("_canGoBack", &WebContents::CanGoBack)
|
|
|
|
|
.SetMethod("_goBack", &WebContents::GoBack)
|
|
|
|
|
.SetMethod("_canGoForward", &WebContents::CanGoForward)
|
|
|
|
|
.SetMethod("_goForward", &WebContents::GoForward)
|
|
|
|
|
.SetMethod("_canGoToOffset", &WebContents::CanGoToOffset)
|
|
|
|
|
.SetMethod("_goToOffset", &WebContents::GoToOffset)
|
2021-04-27 23:11:18 +00:00
|
|
|
|
.SetMethod("canGoToIndex", &WebContents::CanGoToIndex)
|
2024-06-05 16:34:47 +00:00
|
|
|
|
.SetMethod("_goToIndex", &WebContents::GoToIndex)
|
2024-03-21 21:59:23 +00:00
|
|
|
|
.SetMethod("_getActiveIndex", &WebContents::GetActiveIndex)
|
|
|
|
|
.SetMethod("_getNavigationEntryAtIndex",
|
|
|
|
|
&WebContents::GetNavigationEntryAtIndex)
|
|
|
|
|
.SetMethod("_historyLength", &WebContents::GetHistoryLength)
|
2024-08-19 19:46:04 +00:00
|
|
|
|
.SetMethod("_removeNavigationEntryAtIndex",
|
|
|
|
|
&WebContents::RemoveNavigationEntryAtIndex)
|
|
|
|
|
.SetMethod("_getHistory", &WebContents::GetHistory)
|
2024-06-05 16:34:47 +00:00
|
|
|
|
.SetMethod("_clearHistory", &WebContents::ClearHistory)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("isCrashed", &WebContents::IsCrashed)
|
2020-10-02 21:50:24 +00:00
|
|
|
|
.SetMethod("forcefullyCrashRenderer",
|
|
|
|
|
&WebContents::ForcefullyCrashRenderer)
|
2020-03-13 17:16:08 +00:00
|
|
|
|
.SetMethod("setUserAgent", &WebContents::SetUserAgent)
|
|
|
|
|
.SetMethod("getUserAgent", &WebContents::GetUserAgent)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("savePage", &WebContents::SavePage)
|
|
|
|
|
.SetMethod("openDevTools", &WebContents::OpenDevTools)
|
|
|
|
|
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
|
|
|
|
|
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
|
2016-01-01 05:11:21 +00:00
|
|
|
|
.SetMethod("isDevToolsFocused", &WebContents::IsDevToolsFocused)
|
2023-08-15 05:32:53 +00:00
|
|
|
|
.SetMethod("getDevToolsTitle", &WebContents::GetDevToolsTitle)
|
|
|
|
|
.SetMethod("setDevToolsTitle", &WebContents::SetDevToolsTitle)
|
2017-06-25 19:01:05 +00:00
|
|
|
|
.SetMethod("enableDeviceEmulation", &WebContents::EnableDeviceEmulation)
|
|
|
|
|
.SetMethod("disableDeviceEmulation", &WebContents::DisableDeviceEmulation)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
|
|
|
|
|
.SetMethod("inspectElement", &WebContents::InspectElement)
|
2018-04-18 01:55:30 +00:00
|
|
|
|
.SetMethod("setIgnoreMenuShortcuts", &WebContents::SetIgnoreMenuShortcuts)
|
2020-03-13 17:16:08 +00:00
|
|
|
|
.SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
|
|
|
|
|
.SetMethod("isAudioMuted", &WebContents::IsAudioMuted)
|
2018-07-12 11:35:11 +00:00
|
|
|
|
.SetMethod("isCurrentlyAudible", &WebContents::IsCurrentlyAudible)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("undo", &WebContents::Undo)
|
|
|
|
|
.SetMethod("redo", &WebContents::Redo)
|
|
|
|
|
.SetMethod("cut", &WebContents::Cut)
|
|
|
|
|
.SetMethod("copy", &WebContents::Copy)
|
2023-05-03 01:14:29 +00:00
|
|
|
|
.SetMethod("centerSelection", &WebContents::CenterSelection)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("paste", &WebContents::Paste)
|
|
|
|
|
.SetMethod("pasteAndMatchStyle", &WebContents::PasteAndMatchStyle)
|
|
|
|
|
.SetMethod("delete", &WebContents::Delete)
|
|
|
|
|
.SetMethod("selectAll", &WebContents::SelectAll)
|
|
|
|
|
.SetMethod("unselect", &WebContents::Unselect)
|
2023-05-03 01:14:29 +00:00
|
|
|
|
.SetMethod("scrollToTop", &WebContents::ScrollToTopOfDocument)
|
|
|
|
|
.SetMethod("scrollToBottom", &WebContents::ScrollToBottomOfDocument)
|
|
|
|
|
.SetMethod("adjustSelection",
|
|
|
|
|
&WebContents::AdjustSelectionByCharacterOffset)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("replace", &WebContents::Replace)
|
|
|
|
|
.SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling)
|
2015-12-17 17:27:56 +00:00
|
|
|
|
.SetMethod("findInPage", &WebContents::FindInPage)
|
|
|
|
|
.SetMethod("stopFindInPage", &WebContents::StopFindInPage)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("focus", &WebContents::Focus)
|
2016-08-03 03:29:55 +00:00
|
|
|
|
.SetMethod("isFocused", &WebContents::IsFocused)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("sendInputEvent", &WebContents::SendInputEvent)
|
2017-06-25 19:01:05 +00:00
|
|
|
|
.SetMethod("beginFrameSubscription", &WebContents::BeginFrameSubscription)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
|
2016-07-03 03:26:43 +00:00
|
|
|
|
.SetMethod("startDrag", &WebContents::StartDrag)
|
2018-08-16 22:57:40 +00:00
|
|
|
|
.SetMethod("attachToIframe", &WebContents::AttachToIframe)
|
2019-01-12 06:50:33 +00:00
|
|
|
|
.SetMethod("detachFromOuterFrame", &WebContents::DetachFromOuterFrame)
|
2016-08-03 03:29:55 +00:00
|
|
|
|
.SetMethod("isOffscreen", &WebContents::IsOffScreen)
|
|
|
|
|
.SetMethod("startPainting", &WebContents::StartPainting)
|
|
|
|
|
.SetMethod("stopPainting", &WebContents::StopPainting)
|
|
|
|
|
.SetMethod("isPainting", &WebContents::IsPainting)
|
2020-03-13 17:16:08 +00:00
|
|
|
|
.SetMethod("setFrameRate", &WebContents::SetFrameRate)
|
|
|
|
|
.SetMethod("getFrameRate", &WebContents::GetFrameRate)
|
2016-09-01 17:25:12 +00:00
|
|
|
|
.SetMethod("invalidate", &WebContents::Invalidate)
|
2020-03-13 17:16:08 +00:00
|
|
|
|
.SetMethod("setZoomLevel", &WebContents::SetZoomLevel)
|
|
|
|
|
.SetMethod("getZoomLevel", &WebContents::GetZoomLevel)
|
|
|
|
|
.SetMethod("setZoomFactor", &WebContents::SetZoomFactor)
|
|
|
|
|
.SetMethod("getZoomFactor", &WebContents::GetZoomFactor)
|
2024-02-09 09:29:14 +00:00
|
|
|
|
.SetMethod("getType", &WebContents::type)
|
2019-07-03 15:05:45 +00:00
|
|
|
|
.SetMethod("_getPreloadPaths", &WebContents::GetPreloadPaths)
|
2018-03-15 04:56:46 +00:00
|
|
|
|
.SetMethod("getLastWebPreferences", &WebContents::GetLastWebPreferences)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
|
|
|
|
.SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker)
|
2019-02-01 18:44:24 +00:00
|
|
|
|
.SetMethod("inspectSharedWorker", &WebContents::InspectSharedWorker)
|
2019-10-02 12:38:27 +00:00
|
|
|
|
.SetMethod("inspectSharedWorkerById",
|
|
|
|
|
&WebContents::InspectSharedWorkerById)
|
|
|
|
|
.SetMethod("getAllSharedWorkers", &WebContents::GetAllSharedWorkers)
|
2018-11-09 03:42:34 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_PRINTING)
|
|
|
|
|
.SetMethod("_print", &WebContents::Print)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("_printToPDF", &WebContents::PrintToPDF)
|
2018-11-09 03:42:34 +00:00
|
|
|
|
#endif
|
2020-11-10 17:06:03 +00:00
|
|
|
|
.SetMethod("_setNextChildWebPreferences",
|
|
|
|
|
&WebContents::SetNextChildWebPreferences)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("addWorkSpace", &WebContents::AddWorkSpace)
|
|
|
|
|
.SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
|
2016-06-07 20:13:49 +00:00
|
|
|
|
.SetMethod("showDefinitionForSelection",
|
|
|
|
|
&WebContents::ShowDefinitionForSelection)
|
2016-07-26 19:06:11 +00:00
|
|
|
|
.SetMethod("copyImageAt", &WebContents::CopyImageAt)
|
2016-07-05 22:43:57 +00:00
|
|
|
|
.SetMethod("capturePage", &WebContents::CapturePage)
|
2016-09-08 17:01:01 +00:00
|
|
|
|
.SetMethod("setEmbedder", &WebContents::SetEmbedder)
|
2017-11-30 07:37:26 +00:00
|
|
|
|
.SetMethod("setDevToolsWebContents", &WebContents::SetDevToolsWebContents)
|
2017-08-21 10:50:12 +00:00
|
|
|
|
.SetMethod("getNativeView", &WebContents::GetNativeView)
|
2020-01-25 00:43:42 +00:00
|
|
|
|
.SetMethod("isBeingCaptured", &WebContents::IsBeingCaptured)
|
2017-03-08 14:55:59 +00:00
|
|
|
|
.SetMethod("setWebRTCIPHandlingPolicy",
|
|
|
|
|
&WebContents::SetWebRTCIPHandlingPolicy)
|
2023-08-24 21:21:22 +00:00
|
|
|
|
.SetMethod("setWebRTCUDPPortRange", &WebContents::SetWebRTCUDPPortRange)
|
2021-10-26 00:03:59 +00:00
|
|
|
|
.SetMethod("getMediaSourceId", &WebContents::GetMediaSourceID)
|
2017-03-08 14:55:59 +00:00
|
|
|
|
.SetMethod("getWebRTCIPHandlingPolicy",
|
|
|
|
|
&WebContents::GetWebRTCIPHandlingPolicy)
|
2023-08-24 21:21:22 +00:00
|
|
|
|
.SetMethod("getWebRTCUDPPortRange", &WebContents::GetWebRTCUDPPortRange)
|
2019-04-29 17:11:11 +00:00
|
|
|
|
.SetMethod("takeHeapSnapshot", &WebContents::TakeHeapSnapshot)
|
2021-06-08 02:00:22 +00:00
|
|
|
|
.SetMethod("setImageAnimationPolicy",
|
|
|
|
|
&WebContents::SetImageAnimationPolicy)
|
2021-10-05 22:30:31 +00:00
|
|
|
|
.SetMethod("_getProcessMemoryInfo", &WebContents::GetProcessMemoryInfo)
|
2016-05-17 12:56:47 +00:00
|
|
|
|
.SetProperty("id", &WebContents::ID)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetProperty("session", &WebContents::Session)
|
2016-02-17 08:52:19 +00:00
|
|
|
|
.SetProperty("hostWebContents", &WebContents::HostWebContents)
|
2016-01-21 18:22:23 +00:00
|
|
|
|
.SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents)
|
2020-07-30 16:17:57 +00:00
|
|
|
|
.SetProperty("debugger", &WebContents::Debugger)
|
2020-10-09 16:50:46 +00:00
|
|
|
|
.SetProperty("mainFrame", &WebContents::MainFrame)
|
2022-09-26 16:37:08 +00:00
|
|
|
|
.SetProperty("opener", &WebContents::Opener)
|
2023-12-13 21:01:03 +00:00
|
|
|
|
.SetMethod("_setOwnerWindow", &WebContents::SetOwnerBaseWindow)
|
2020-07-30 16:17:57 +00:00
|
|
|
|
.Build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char* WebContents::GetTypeName() {
|
2023-07-10 09:49:20 +00:00
|
|
|
|
return GetClassName();
|
2015-07-06 10:21:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-14 19:13:25 +00:00
|
|
|
|
ElectronBrowserContext* WebContents::GetBrowserContext() const {
|
|
|
|
|
return static_cast<ElectronBrowserContext*>(
|
|
|
|
|
web_contents()->GetBrowserContext());
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-24 08:45:25 +00:00
|
|
|
|
// static
|
2020-11-17 22:14:33 +00:00
|
|
|
|
gin::Handle<WebContents> WebContents::New(
|
2019-10-25 13:03:28 +00:00
|
|
|
|
v8::Isolate* isolate,
|
|
|
|
|
const gin_helper::Dictionary& options) {
|
2020-07-30 16:17:57 +00:00
|
|
|
|
gin::Handle<WebContents> handle =
|
|
|
|
|
gin::CreateHandle(isolate, new WebContents(isolate, options));
|
2021-05-11 20:57:11 +00:00
|
|
|
|
v8::TryCatch try_catch(isolate);
|
2020-07-30 16:17:57 +00:00
|
|
|
|
gin_helper::CallMethod(isolate, handle.get(), "_init");
|
2021-05-11 20:57:11 +00:00
|
|
|
|
if (try_catch.HasCaught()) {
|
|
|
|
|
node::errors::TriggerUncaughtException(isolate, try_catch);
|
|
|
|
|
}
|
2020-07-30 16:17:57 +00:00
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-19 08:52:07 +00:00
|
|
|
|
// static
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin::Handle<WebContents> WebContents::CreateAndTake(
|
2018-04-18 01:55:30 +00:00
|
|
|
|
v8::Isolate* isolate,
|
2018-10-22 18:02:25 +00:00
|
|
|
|
std::unique_ptr<content::WebContents> web_contents,
|
2018-04-18 01:55:30 +00:00
|
|
|
|
Type type) {
|
2020-07-30 16:17:57 +00:00
|
|
|
|
gin::Handle<WebContents> handle = gin::CreateHandle(
|
2018-10-22 18:02:25 +00:00
|
|
|
|
isolate, new WebContents(isolate, std::move(web_contents), type));
|
2021-05-11 20:57:11 +00:00
|
|
|
|
v8::TryCatch try_catch(isolate);
|
2020-07-30 16:17:57 +00:00
|
|
|
|
gin_helper::CallMethod(isolate, handle.get(), "_init");
|
2021-05-11 20:57:11 +00:00
|
|
|
|
if (try_catch.HasCaught()) {
|
|
|
|
|
node::errors::TriggerUncaughtException(isolate, try_catch);
|
|
|
|
|
}
|
2020-07-30 16:17:57 +00:00
|
|
|
|
return handle;
|
2014-04-24 08:45:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-10-23 06:04:13 +00:00
|
|
|
|
// static
|
2020-07-16 23:16:05 +00:00
|
|
|
|
WebContents* WebContents::From(content::WebContents* web_contents) {
|
2020-07-30 16:17:57 +00:00
|
|
|
|
if (!web_contents)
|
|
|
|
|
return nullptr;
|
2020-10-26 18:56:31 +00:00
|
|
|
|
auto* data = static_cast<UserDataLink*>(
|
2020-07-30 16:17:57 +00:00
|
|
|
|
web_contents->GetUserData(kElectronApiWebContentsKey));
|
|
|
|
|
return data ? data->web_contents.get() : nullptr;
|
2018-10-19 08:52:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// static
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin::Handle<WebContents> WebContents::FromOrCreate(
|
2018-10-19 08:52:07 +00:00
|
|
|
|
v8::Isolate* isolate,
|
|
|
|
|
content::WebContents* web_contents) {
|
2020-07-16 23:16:05 +00:00
|
|
|
|
WebContents* api_web_contents = From(web_contents);
|
2020-07-30 16:17:57 +00:00
|
|
|
|
if (!api_web_contents) {
|
2020-07-16 23:16:05 +00:00
|
|
|
|
api_web_contents = new WebContents(isolate, web_contents);
|
2021-05-11 20:57:11 +00:00
|
|
|
|
v8::TryCatch try_catch(isolate);
|
2020-07-30 16:17:57 +00:00
|
|
|
|
gin_helper::CallMethod(isolate, api_web_contents, "_init");
|
2021-05-11 20:57:11 +00:00
|
|
|
|
if (try_catch.HasCaught()) {
|
|
|
|
|
node::errors::TriggerUncaughtException(isolate, try_catch);
|
|
|
|
|
}
|
2020-07-30 16:17:57 +00:00
|
|
|
|
}
|
2020-07-16 23:16:05 +00:00
|
|
|
|
return gin::CreateHandle(isolate, api_web_contents);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-15 23:52:43 +00:00
|
|
|
|
// static
|
|
|
|
|
gin::Handle<WebContents> WebContents::CreateFromWebPreferences(
|
|
|
|
|
v8::Isolate* isolate,
|
|
|
|
|
const gin_helper::Dictionary& web_preferences) {
|
|
|
|
|
// Check if webPreferences has |webContents| option.
|
|
|
|
|
gin::Handle<WebContents> web_contents;
|
|
|
|
|
if (web_preferences.GetHidden("webContents", &web_contents) &&
|
|
|
|
|
!web_contents.IsEmpty()) {
|
|
|
|
|
// Set webPreferences from options if using an existing webContents.
|
|
|
|
|
// These preferences will be used when the webContent launches new
|
|
|
|
|
// render processes.
|
|
|
|
|
auto* existing_preferences =
|
|
|
|
|
WebContentsPreferences::From(web_contents->web_contents());
|
2021-07-26 16:04:09 +00:00
|
|
|
|
gin_helper::Dictionary web_preferences_dict;
|
2020-12-15 23:52:43 +00:00
|
|
|
|
if (gin::ConvertFromV8(isolate, web_preferences.GetHandle(),
|
|
|
|
|
&web_preferences_dict)) {
|
2021-07-26 16:04:09 +00:00
|
|
|
|
existing_preferences->SetFromDictionary(web_preferences_dict);
|
2023-12-13 21:01:03 +00:00
|
|
|
|
web_contents->SetBackgroundColor(
|
|
|
|
|
existing_preferences->GetBackgroundColor());
|
2020-12-15 23:52:43 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Create one if not.
|
|
|
|
|
web_contents = WebContents::New(isolate, web_preferences);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return web_contents;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-16 23:16:05 +00:00
|
|
|
|
// static
|
|
|
|
|
WebContents* WebContents::FromID(int32_t id) {
|
2020-07-30 16:17:57 +00:00
|
|
|
|
return GetAllWebContents().Lookup(id);
|
2014-10-23 06:04:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-09 12:47:19 +00:00
|
|
|
|
// static
|
|
|
|
|
std::list<WebContents*> WebContents::GetWebContentsList() {
|
|
|
|
|
std::list<WebContents*> list;
|
|
|
|
|
for (auto iter = base::IDMap<WebContents*>::iterator(&GetAllWebContents());
|
|
|
|
|
!iter.IsAtEnd(); iter.Advance()) {
|
|
|
|
|
list.push_back(iter.GetCurrentValue());
|
|
|
|
|
}
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-30 16:17:57 +00:00
|
|
|
|
// static
|
|
|
|
|
gin::WrapperInfo WebContents::kWrapperInfo = {gin::kEmbedderNativeGin};
|
|
|
|
|
|
2022-06-29 19:55:47 +00:00
|
|
|
|
} // namespace electron::api
|
2014-10-23 06:04:13 +00:00
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
2020-07-30 16:17:57 +00:00
|
|
|
|
using electron::api::GetAllWebContents;
|
2016-08-02 11:38:35 +00:00
|
|
|
|
using electron::api::WebContents;
|
2022-09-26 16:37:08 +00:00
|
|
|
|
using electron::api::WebFrameMain;
|
2016-08-02 11:38:35 +00:00
|
|
|
|
|
2020-11-23 17:21:00 +00:00
|
|
|
|
gin::Handle<WebContents> WebContentsFromID(v8::Isolate* isolate, int32_t id) {
|
|
|
|
|
WebContents* contents = WebContents::FromID(id);
|
|
|
|
|
return contents ? gin::CreateHandle(isolate, contents)
|
|
|
|
|
: gin::Handle<WebContents>();
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-26 16:37:08 +00:00
|
|
|
|
gin::Handle<WebContents> WebContentsFromFrame(v8::Isolate* isolate,
|
|
|
|
|
WebFrameMain* web_frame) {
|
|
|
|
|
content::RenderFrameHost* rfh = web_frame->render_frame_host();
|
|
|
|
|
content::WebContents* source = content::WebContents::FromRenderFrameHost(rfh);
|
|
|
|
|
WebContents* contents = WebContents::From(source);
|
|
|
|
|
return contents ? gin::CreateHandle(isolate, contents)
|
|
|
|
|
: gin::Handle<WebContents>();
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-27 21:01:24 +00:00
|
|
|
|
gin::Handle<WebContents> WebContentsFromDevToolsTargetID(
|
|
|
|
|
v8::Isolate* isolate,
|
|
|
|
|
std::string target_id) {
|
|
|
|
|
auto agent_host = content::DevToolsAgentHost::GetForId(target_id);
|
|
|
|
|
WebContents* contents =
|
|
|
|
|
agent_host ? WebContents::From(agent_host->GetWebContents()) : nullptr;
|
|
|
|
|
return contents ? gin::CreateHandle(isolate, contents)
|
|
|
|
|
: gin::Handle<WebContents>();
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-30 16:17:57 +00:00
|
|
|
|
std::vector<gin::Handle<WebContents>> GetAllWebContentsAsV8(
|
|
|
|
|
v8::Isolate* isolate) {
|
|
|
|
|
std::vector<gin::Handle<WebContents>> list;
|
|
|
|
|
for (auto iter = base::IDMap<WebContents*>::iterator(&GetAllWebContents());
|
|
|
|
|
!iter.IsAtEnd(); iter.Advance()) {
|
|
|
|
|
list.push_back(gin::CreateHandle(isolate, iter.GetCurrentValue()));
|
|
|
|
|
}
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
|
void Initialize(v8::Local<v8::Object> exports,
|
|
|
|
|
v8::Local<v8::Value> unused,
|
|
|
|
|
v8::Local<v8::Context> context,
|
|
|
|
|
void* priv) {
|
2014-10-23 06:04:13 +00:00
|
|
|
|
v8::Isolate* isolate = context->GetIsolate();
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin_helper::Dictionary dict(isolate, exports);
|
2020-07-30 16:17:57 +00:00
|
|
|
|
dict.Set("WebContents", WebContents::GetConstructor(context));
|
2020-11-23 17:21:00 +00:00
|
|
|
|
dict.SetMethod("fromId", &WebContentsFromID);
|
2022-09-26 16:37:08 +00:00
|
|
|
|
dict.SetMethod("fromFrame", &WebContentsFromFrame);
|
2021-08-27 21:01:24 +00:00
|
|
|
|
dict.SetMethod("fromDevToolsTargetId", &WebContentsFromDevToolsTargetID);
|
2020-07-30 16:17:57 +00:00
|
|
|
|
dict.SetMethod("getAllWebContents", &GetAllWebContentsAsV8);
|
2014-10-23 06:04:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
2023-02-09 01:31:38 +00:00
|
|
|
|
NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_web_contents, Initialize)
|