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.
|
|
|
|
|
|
2020-02-04 20:19:40 +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>
|
2018-09-13 00:25:56 +00:00
|
|
|
|
#include <memory>
|
2015-04-25 04:43:52 +00:00
|
|
|
|
#include <set>
|
2015-12-11 15:54:32 +00:00
|
|
|
|
#include <string>
|
2020-03-12 01:07:54 +00:00
|
|
|
|
#include <unordered_set>
|
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
|
|
|
|
|
2019-08-24 01:14:23 +00:00
|
|
|
|
#include "base/message_loop/message_loop_current.h"
|
2019-01-10 16:28:15 +00:00
|
|
|
|
#include "base/no_destructor.h"
|
2019-05-21 18:34:04 +00:00
|
|
|
|
#include "base/optional.h"
|
2014-04-25 08:13:16 +00:00
|
|
|
|
#include "base/strings/utf_string_conversions.h"
|
2018-09-18 18:00:31 +00:00
|
|
|
|
#include "base/threading/thread_restrictions.h"
|
2016-11-30 07:30:03 +00:00
|
|
|
|
#include "base/threading/thread_task_runner_handle.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"
|
2017-01-24 01:51:11 +00:00
|
|
|
|
#include "chrome/browser/ssl/security_state_tab_helper.h"
|
2019-03-05 05:08:55 +00:00
|
|
|
|
#include "content/browser/frame_host/frame_tree_node.h" // nogncheck
|
|
|
|
|
#include "content/browser/frame_host/render_frame_host_manager.h" // nogncheck
|
|
|
|
|
#include "content/browser/renderer_host/render_widget_host_impl.h" // nogncheck
|
|
|
|
|
#include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck
|
2019-01-12 01:00:43 +00:00
|
|
|
|
#include "content/common/widget_messages.h"
|
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"
|
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"
|
2015-09-18 06:20:31 +00:00
|
|
|
|
#include "content/public/browser/native_web_keyboard_event.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"
|
2015-05-12 19:35:56 +00:00
|
|
|
|
#include "content/public/browser/plugin_service.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"
|
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-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"
|
2019-10-28 22:12:35 +00:00
|
|
|
|
#include "mojo/public/cpp/bindings/associated_remote.h"
|
2019-04-02 22:38:16 +00:00
|
|
|
|
#include "mojo/public/cpp/system/platform_handle.h"
|
2019-10-09 17:59:37 +00:00
|
|
|
|
#include "ppapi/buildflags/buildflags.h"
|
2020-02-04 20:19:40 +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-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"
|
2020-02-04 20:19:40 +00:00
|
|
|
|
#include "shell/browser/electron_autofill_driver_factory.h"
|
|
|
|
|
#include "shell/browser/electron_browser_client.h"
|
|
|
|
|
#include "shell/browser/electron_browser_context.h"
|
|
|
|
|
#include "shell/browser/electron_browser_main_parts.h"
|
|
|
|
|
#include "shell/browser/electron_javascript_dialog_manager.h"
|
|
|
|
|
#include "shell/browser/electron_navigation_throttle.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/browser/lib/bluetooth_chooser.h"
|
|
|
|
|
#include "shell/browser/native_window.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"
|
|
|
|
|
#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"
|
2020-02-04 20:19:40 +00:00
|
|
|
|
#include "shell/common/api/electron_api_native_image.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/common/color_util.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"
|
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"
|
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"
|
2019-10-25 13:03:28 +00:00
|
|
|
|
#include "shell/common/gin_helper/object_template_builder.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/mouse_util.h"
|
|
|
|
|
#include "shell/common/node_includes.h"
|
|
|
|
|
#include "shell/common/options_switches.h"
|
2020-03-12 01:07:54 +00:00
|
|
|
|
#include "shell/common/v8_value_serializer.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-03-03 21:35:05 +00:00
|
|
|
|
#include "ui/base/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
|
|
|
|
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_OSR)
|
2019-06-19 20:46:59 +00:00
|
|
|
|
#include "shell/browser/osr/osr_render_widget_host_view.h"
|
|
|
|
|
#include "shell/browser/osr/osr_web_contents_view.h"
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2016-08-15 21:13:24 +00:00
|
|
|
|
#if !defined(OS_MACOSX)
|
|
|
|
|
#include "ui/aura/window.h"
|
2019-08-30 14:39:46 +00:00
|
|
|
|
#else
|
|
|
|
|
#include "ui/base/cocoa/defaults_utils.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(OS_LINUX)
|
|
|
|
|
#include "ui/views/linux_ui/linux_ui.h"
|
2016-08-15 21:13:24 +00:00
|
|
|
|
#endif
|
2014-10-23 06:04:13 +00:00
|
|
|
|
|
2018-02-22 08:56:48 +00:00
|
|
|
|
#if defined(OS_LINUX) || defined(OS_WIN)
|
|
|
|
|
#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-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
|
|
|
|
|
|
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)
|
2018-04-18 01:55:30 +00:00
|
|
|
|
template <>
|
2017-02-06 09:18:04 +00:00
|
|
|
|
struct Converter<printing::PrinterBasicInfo> {
|
2017-05-18 17:26:22 +00:00
|
|
|
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
|
|
|
|
const printing::PrinterBasicInfo& val) {
|
2019-10-18 00:31:29 +00:00
|
|
|
|
gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
|
2017-05-18 17:26:22 +00:00
|
|
|
|
dict.Set("name", val.printer_name);
|
2019-11-13 05:31:28 +00:00
|
|
|
|
dict.Set("displayName", val.display_name);
|
2017-05-18 17:26:22 +00:00
|
|
|
|
dict.Set("description", val.printer_description);
|
|
|
|
|
dict.Set("status", val.printer_status);
|
2017-05-18 17:51:44 +00:00
|
|
|
|
dict.Set("isDefault", val.is_default ? true : false);
|
2017-05-18 17:26:22 +00:00
|
|
|
|
dict.Set("options", val.options);
|
|
|
|
|
return dict.GetHandle();
|
|
|
|
|
}
|
2017-02-06 09:18:04 +00:00
|
|
|
|
};
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
struct Converter<printing::MarginType> {
|
|
|
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
|
|
|
v8::Local<v8::Value> val,
|
|
|
|
|
printing::MarginType* out) {
|
|
|
|
|
std::string type;
|
|
|
|
|
if (ConvertFromV8(isolate, val, &type)) {
|
|
|
|
|
if (type == "default") {
|
|
|
|
|
*out = printing::DEFAULT_MARGINS;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (type == "none") {
|
|
|
|
|
*out = printing::NO_MARGINS;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (type == "printableArea") {
|
|
|
|
|
*out = printing::PRINTABLE_AREA_MARGINS;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (type == "custom") {
|
|
|
|
|
*out = printing::CUSTOM_MARGINS;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
struct Converter<printing::DuplexMode> {
|
|
|
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
|
|
|
v8::Local<v8::Value> val,
|
|
|
|
|
printing::DuplexMode* out) {
|
|
|
|
|
std::string mode;
|
|
|
|
|
if (ConvertFromV8(isolate, val, &mode)) {
|
|
|
|
|
if (mode == "simplex") {
|
|
|
|
|
*out = printing::SIMPLEX;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (mode == "longEdge") {
|
|
|
|
|
*out = printing::LONG_EDGE;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (mode == "shortEdge") {
|
|
|
|
|
*out = printing::SHORT_EDGE;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
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) {
|
|
|
|
|
std::string save_type;
|
|
|
|
|
if (!ConvertFromV8(isolate, val, &save_type))
|
|
|
|
|
return false;
|
2015-12-07 11:56:23 +00:00
|
|
|
|
save_type = base::ToLowerASCII(save_type);
|
2015-11-02 13:19:00 +00:00
|
|
|
|
if (save_type == "htmlonly") {
|
2015-10-14 04:41:31 +00:00
|
|
|
|
*out = content::SAVE_PAGE_TYPE_AS_ONLY_HTML;
|
2015-11-02 13:19:00 +00:00
|
|
|
|
} else if (save_type == "htmlcomplete") {
|
2015-10-14 04:41:31 +00:00
|
|
|
|
*out = content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML;
|
2015-11-02 13:19:00 +00:00
|
|
|
|
} else if (save_type == "mhtml") {
|
2015-10-14 04:41:31 +00:00
|
|
|
|
*out = content::SAVE_PAGE_TYPE_AS_MHTML;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
|
template <>
|
2019-06-19 21:23:04 +00:00
|
|
|
|
struct Converter<electron::api::WebContents::Type> {
|
2016-06-14 16:09:54 +00:00
|
|
|
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
2019-06-19 21:23:04 +00:00
|
|
|
|
electron::api::WebContents::Type val) {
|
|
|
|
|
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) {
|
2018-04-18 01:55:30 +00:00
|
|
|
|
case Type::BACKGROUND_PAGE:
|
|
|
|
|
type = "backgroundPage";
|
|
|
|
|
break;
|
|
|
|
|
case Type::BROWSER_WINDOW:
|
|
|
|
|
type = "window";
|
|
|
|
|
break;
|
|
|
|
|
case Type::BROWSER_VIEW:
|
|
|
|
|
type = "browserView";
|
|
|
|
|
break;
|
|
|
|
|
case Type::REMOTE:
|
|
|
|
|
type = "remote";
|
|
|
|
|
break;
|
|
|
|
|
case Type::WEB_VIEW:
|
|
|
|
|
type = "webview";
|
|
|
|
|
break;
|
|
|
|
|
case Type::OFF_SCREEN:
|
|
|
|
|
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,
|
2019-06-19 21:23:04 +00:00
|
|
|
|
electron::api::WebContents::Type* out) {
|
|
|
|
|
using Type = electron::api::WebContents::Type;
|
2016-06-14 16:23:03 +00:00
|
|
|
|
std::string type;
|
|
|
|
|
if (!ConvertFromV8(isolate, val, &type))
|
|
|
|
|
return false;
|
Implement initial, experimental BrowserView API
Right now, `<webview>` is the only way to embed additional content in a
`BrowserWindow`. Unfortunately `<webview>` suffers from a [number of
problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20).
To make matters worse, many of these are upstream Chromium bugs instead
of Electron-specific bugs.
For us at [Figma](https://www.figma.com), the main issue is very slow
performance.
Despite the upstream improvements to `<webview>` through the OOPIF work, it is
probable that there will continue to be `<webview>`-specific bugs in the
future.
Therefore, this introduces a `<webview>` alternative to called `BrowserView`,
which...
- is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will
likely also be bugs in `BrowserWindow` web contents)
- is instantiated in the main process like `BrowserWindow` (and unlike
`<webview>`, which lives in the DOM of a `BrowserWindow` web contents)
- needs to be added to a `BrowserWindow` to display something on the screen
This implements the most basic API. The API is expected to evolve and change in
the near future and has consequently been marked as experimental. Please do not
use this API in production unless you are prepared to deal with breaking
changes.
In the future, we will want to change the API to support multiple
`BrowserView`s per window. We will also want to consider z-ordering
auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
|
|
|
|
if (type == "backgroundPage") {
|
2016-06-14 17:05:25 +00:00
|
|
|
|
*out = Type::BACKGROUND_PAGE;
|
Implement initial, experimental BrowserView API
Right now, `<webview>` is the only way to embed additional content in a
`BrowserWindow`. Unfortunately `<webview>` suffers from a [number of
problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20).
To make matters worse, many of these are upstream Chromium bugs instead
of Electron-specific bugs.
For us at [Figma](https://www.figma.com), the main issue is very slow
performance.
Despite the upstream improvements to `<webview>` through the OOPIF work, it is
probable that there will continue to be `<webview>`-specific bugs in the
future.
Therefore, this introduces a `<webview>` alternative to called `BrowserView`,
which...
- is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will
likely also be bugs in `BrowserWindow` web contents)
- is instantiated in the main process like `BrowserWindow` (and unlike
`<webview>`, which lives in the DOM of a `BrowserWindow` web contents)
- needs to be added to a `BrowserWindow` to display something on the screen
This implements the most basic API. The API is expected to evolve and change in
the near future and has consequently been marked as experimental. Please do not
use this API in production unless you are prepared to deal with breaking
changes.
In the future, we will want to change the API to support multiple
`BrowserView`s per window. We will also want to consider z-ordering
auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
|
|
|
|
} else if (type == "browserView") {
|
|
|
|
|
*out = Type::BROWSER_VIEW;
|
|
|
|
|
} else if (type == "webview") {
|
|
|
|
|
*out = Type::WEB_VIEW;
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_OSR)
|
2016-07-28 10:10:56 +00:00
|
|
|
|
} else if (type == "offscreen") {
|
|
|
|
|
*out = Type::OFF_SCREEN;
|
2017-06-26 09:13:05 +00:00
|
|
|
|
#endif
|
2016-06-14 16:23:03 +00:00
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
};
|
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();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
} // namespace gin
|
2015-05-29 03:12:55 +00:00
|
|
|
|
|
2019-06-19 21:23:04 +00:00
|
|
|
|
namespace electron {
|
2014-04-24 08:45:25 +00:00
|
|
|
|
|
|
|
|
|
namespace api {
|
|
|
|
|
|
2014-10-23 05:31:10 +00:00
|
|
|
|
namespace {
|
|
|
|
|
|
2016-07-06 16:32:58 +00:00
|
|
|
|
// Called when CapturePage is done.
|
2019-11-01 06:10:32 +00:00
|
|
|
|
void OnCapturePageDone(gin_helper::Promise<gfx::Image> promise,
|
2019-08-23 00:03:28 +00:00
|
|
|
|
const SkBitmap& bitmap) {
|
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));
|
2016-07-06 16:32:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-19 18:43:21 +00:00
|
|
|
|
base::Optional<base::TimeDelta> GetCursorBlinkInterval() {
|
|
|
|
|
#if defined(OS_MACOSX)
|
|
|
|
|
base::TimeDelta interval;
|
|
|
|
|
if (ui::TextInsertionCaretBlinkPeriod(&interval))
|
|
|
|
|
return interval;
|
|
|
|
|
#elif defined(OS_LINUX)
|
|
|
|
|
if (auto* linux_ui = views::LinuxUI::instance())
|
|
|
|
|
return linux_ui->GetCursorBlinkInterval();
|
|
|
|
|
#elif defined(OS_WIN)
|
|
|
|
|
const auto system_msec = ::GetCaretBlinkTime();
|
|
|
|
|
if (system_msec != 0) {
|
|
|
|
|
return (system_msec == INFINITE)
|
|
|
|
|
? base::TimeDelta()
|
|
|
|
|
: base::TimeDelta::FromMilliseconds(system_msec);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return base::nullopt;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-31 02:49:13 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_PRINTING)
|
|
|
|
|
// This will return false if no printer with the provided device_name can be
|
|
|
|
|
// found on the network. We need to check this because Chromium does not do
|
|
|
|
|
// sanity checking of device_name validity and so will crash on invalid names.
|
|
|
|
|
bool IsDeviceNameValid(const base::string16& device_name) {
|
|
|
|
|
#if defined(OS_MACOSX)
|
|
|
|
|
base::ScopedCFTypeRef<CFStringRef> new_printer_id(
|
|
|
|
|
base::SysUTF16ToCFStringRef(device_name));
|
|
|
|
|
PMPrinter new_printer = PMPrinterCreateFromPrinterID(new_printer_id.get());
|
|
|
|
|
bool printer_exists = new_printer != nullptr;
|
|
|
|
|
PMRelease(new_printer);
|
|
|
|
|
return printer_exists;
|
|
|
|
|
#elif defined(OS_WIN)
|
|
|
|
|
printing::ScopedPrinterHandle printer;
|
|
|
|
|
return printer.OpenPrinterWithName(device_name.c_str());
|
|
|
|
|
#endif
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-01-31 19:20:11 +00:00
|
|
|
|
|
|
|
|
|
base::string16 GetDefaultPrinterAsync() {
|
|
|
|
|
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
|
|
|
|
|
base::BlockingType::MAY_BLOCK);
|
|
|
|
|
|
|
|
|
|
scoped_refptr<printing::PrintBackend> backend =
|
|
|
|
|
printing::PrintBackend::CreateInstance(
|
|
|
|
|
nullptr, g_browser_process->GetApplicationLocale());
|
|
|
|
|
std::string printer_name = backend->GetDefaultPrinterName();
|
|
|
|
|
return base::UTF8ToUTF16(printer_name);
|
|
|
|
|
}
|
2020-01-31 02:49:13 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2014-10-23 05:31:10 +00:00
|
|
|
|
} // namespace
|
|
|
|
|
|
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),
|
|
|
|
|
type_(Type::REMOTE),
|
|
|
|
|
weak_factory_(this) {
|
2020-04-13 23:39:26 +00:00
|
|
|
|
web_contents->SetUserAgentOverride(blink::UserAgentOverride::UserAgentOnly(
|
|
|
|
|
GetBrowserContext()->GetUserAgent()),
|
2018-10-19 08:52:07 +00:00
|
|
|
|
false);
|
|
|
|
|
Init(isolate);
|
|
|
|
|
AttachAsUserData(web_contents);
|
2019-10-25 13:03:28 +00:00
|
|
|
|
InitZoomController(web_contents, gin::Dictionary::CreateEmpty(isolate));
|
2020-01-13 22:55:58 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
2020-02-03 22:01:10 +00:00
|
|
|
|
extensions::ElectronExtensionWebContentsObserver::CreateForWebContents(
|
2020-01-13 22:55:58 +00:00
|
|
|
|
web_contents);
|
2020-01-15 23:11:51 +00:00
|
|
|
|
script_executor_.reset(new extensions::ScriptExecutor(web_contents));
|
2020-01-13 22:55:58 +00:00
|
|
|
|
#endif
|
2019-04-02 22:38:16 +00:00
|
|
|
|
registry_.AddInterface(base::BindRepeating(&WebContents::BindElectronBrowser,
|
|
|
|
|
base::Unretained(this)));
|
2019-04-03 21:22:23 +00:00
|
|
|
|
bindings_.set_connection_error_handler(base::BindRepeating(
|
|
|
|
|
&WebContents::OnElectronBrowserConnectionError, base::Unretained(this)));
|
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),
|
|
|
|
|
weak_factory_(this) {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
DCHECK(type != Type::REMOTE)
|
|
|
|
|
<< "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)
|
2019-06-14 02:44:36 +00:00
|
|
|
|
: weak_factory_(this) {
|
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_);
|
|
|
|
|
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_OSR)
|
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)
|
2019-05-03 18:11:41 +00:00
|
|
|
|
type_ = Type::OFF_SCREEN;
|
2017-06-26 09:13:05 +00:00
|
|
|
|
#endif
|
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
|
|
|
|
|
2019-12-05 17:37:42 +00:00
|
|
|
|
// BrowserViews are not attached to a window initially so they should start
|
|
|
|
|
// off as hidden. This is also important for compositor recycling. See:
|
|
|
|
|
// https://github.com/electron/electron/pull/21372
|
|
|
|
|
bool initially_shown = type_ != Type::BROWSER_VIEW;
|
2019-09-05 17:56:06 +00:00
|
|
|
|
options.Get(options::kShow, &initially_shown);
|
|
|
|
|
|
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;
|
2016-06-14 16:23:03 +00:00
|
|
|
|
if (IsGuest()) {
|
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
|
|
|
|
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_OSR)
|
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 {
|
2017-06-26 09:13:05 +00:00
|
|
|
|
#endif
|
2017-03-04 02:09:16 +00:00
|
|
|
|
web_contents = content::WebContents::Create(params);
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_OSR)
|
2017-03-04 02:09:16 +00:00
|
|
|
|
}
|
2016-07-31 10:19:56 +00:00
|
|
|
|
} else if (IsOffScreen()) {
|
2016-08-01 11:27:39 +00:00
|
|
|
|
bool transparent = false;
|
|
|
|
|
options.Get("transparent", &transparent);
|
|
|
|
|
|
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());
|
2017-06-26 09:13:05 +00:00
|
|
|
|
#endif
|
2016-07-29 12:50:27 +00:00
|
|
|
|
} else {
|
|
|
|
|
content::WebContents::CreateParams params(session->browser_context());
|
2019-09-05 17:56:06 +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);
|
|
|
|
|
}
|
|
|
|
|
|
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());
|
|
|
|
|
// TODO(zcbenz): Make InitWithWebContents take unique_ptr.
|
|
|
|
|
// At the time of writing we are going through a refactoring and I don't want
|
|
|
|
|
// to make other people's work harder.
|
|
|
|
|
InitWithWebContents(owned_web_contents.release(), session->browser_context(),
|
|
|
|
|
IsGuest());
|
2015-06-05 07:01:51 +00:00
|
|
|
|
|
2015-10-01 03:14:19 +00:00
|
|
|
|
managed_web_contents()->GetView()->SetDelegate(this);
|
|
|
|
|
|
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
|
|
|
|
|
2018-02-22 08:56:48 +00:00
|
|
|
|
#if defined(OS_LINUX) || defined(OS_WIN)
|
|
|
|
|
// Update font settings.
|
2019-01-10 16:28:15 +00:00
|
|
|
|
static const base::NoDestructor<gfx::FontRenderParams> params(
|
|
|
|
|
gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr));
|
|
|
|
|
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++.
|
2018-10-22 18:02:25 +00:00
|
|
|
|
new WebContentsPreferences(web_contents(), options);
|
2015-09-04 16:44:22 +00:00
|
|
|
|
|
2018-10-22 18:02:25 +00:00
|
|
|
|
WebContentsPermissionHelper::CreateForWebContents(web_contents());
|
|
|
|
|
SecurityStateTabHelper::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());
|
2020-01-15 23:11:51 +00:00
|
|
|
|
script_executor_.reset(new extensions::ScriptExecutor(web_contents()));
|
2019-07-24 23:01:08 +00:00
|
|
|
|
#endif
|
2016-01-23 13:29:47 +00:00
|
|
|
|
|
2019-04-02 22:38:16 +00:00
|
|
|
|
registry_.AddInterface(base::BindRepeating(&WebContents::BindElectronBrowser,
|
|
|
|
|
base::Unretained(this)));
|
2019-04-03 21:22:23 +00:00
|
|
|
|
bindings_.set_connection_error_handler(base::BindRepeating(
|
|
|
|
|
&WebContents::OnElectronBrowserConnectionError, base::Unretained(this)));
|
2019-08-19 20:13:24 +00:00
|
|
|
|
AutofillDriverFactory::CreateForWebContents(web_contents());
|
2019-04-02 22:38:16 +00:00
|
|
|
|
|
2020-04-13 23:39:26 +00:00
|
|
|
|
web_contents()->SetUserAgentOverride(blink::UserAgentOverride::UserAgentOnly(
|
|
|
|
|
GetBrowserContext()->GetUserAgent()),
|
2018-10-22 18:02:25 +00:00
|
|
|
|
false);
|
2015-07-14 19:13:25 +00:00
|
|
|
|
|
2016-06-14 16:23:03 +00:00
|
|
|
|
if (IsGuest()) {
|
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
|
|
|
|
|
|
|
|
|
Init(isolate);
|
2018-10-22 18:02:25 +00:00
|
|
|
|
AttachAsUserData(web_contents());
|
2014-10-23 06:04:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebContents::~WebContents() {
|
2016-01-13 09:59:59 +00:00
|
|
|
|
// The destroy() is called.
|
|
|
|
|
if (managed_web_contents()) {
|
2018-02-22 07:52:08 +00:00
|
|
|
|
managed_web_contents()->GetView()->SetDelegate(nullptr);
|
|
|
|
|
|
2016-02-22 07:20:23 +00:00
|
|
|
|
RenderViewDeleted(web_contents()->GetRenderViewHost());
|
2017-04-03 20:03:51 +00:00
|
|
|
|
|
2019-07-11 22:25:27 +00:00
|
|
|
|
if (type_ == Type::BROWSER_WINDOW && owner_window()) {
|
2018-11-08 15:57:28 +00:00
|
|
|
|
// For BrowserWindow we should close the window and clean up everything
|
|
|
|
|
// before WebContents is destroyed.
|
|
|
|
|
for (ExtendedWebContentsObserver& observer : observers_)
|
|
|
|
|
observer.OnCloseContents();
|
|
|
|
|
// BrowserWindow destroys WebContents asynchronously, manually emit the
|
|
|
|
|
// destroyed event here.
|
|
|
|
|
WebContentsDestroyed();
|
|
|
|
|
} else if (Browser::Get()->is_shutting_down()) {
|
|
|
|
|
// Destroy WebContents directly when app is shutting down.
|
2018-09-07 06:41:48 +00:00
|
|
|
|
DestroyWebContents(false /* async */);
|
2017-04-03 20:03:51 +00:00
|
|
|
|
} else {
|
2018-11-08 15:57:28 +00:00
|
|
|
|
// Destroy WebContents asynchronously unless app is shutting down,
|
|
|
|
|
// because destroy() might be called inside WebContents's event handler.
|
2019-07-11 22:25:27 +00:00
|
|
|
|
DestroyWebContents(!IsGuest() /* async */);
|
2018-09-07 06:41:48 +00:00
|
|
|
|
// The WebContentsDestroyed will not be called automatically because we
|
|
|
|
|
// destroy the webContents in the next tick. So we have to manually
|
|
|
|
|
// call it here to make sure "destroyed" event is emitted.
|
|
|
|
|
WebContentsDestroyed();
|
2017-04-03 20:03:51 +00:00
|
|
|
|
}
|
2016-01-13 09:59:59 +00:00
|
|
|
|
}
|
2014-04-24 08:45:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-03 20:03:51 +00:00
|
|
|
|
void WebContents::DestroyWebContents(bool async) {
|
2017-03-18 19:40:30 +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
|
|
|
|
ResetManagedWebContents(async);
|
2017-03-18 19:40:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-01 00:18:22 +00:00
|
|
|
|
bool WebContents::DidAddMessageToConsole(
|
|
|
|
|
content::WebContents* source,
|
|
|
|
|
blink::mojom::ConsoleMessageLevel level,
|
|
|
|
|
const base::string16& message,
|
|
|
|
|
int32_t line_no,
|
|
|
|
|
const base::string16& source_id) {
|
|
|
|
|
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;
|
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,
|
|
|
|
|
const std::string& frame_name,
|
|
|
|
|
const GURL& target_url) {
|
|
|
|
|
if (Emit("-will-add-new-contents", target_url, frame_name)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
const std::string& partition_id,
|
|
|
|
|
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,
|
|
|
|
|
WindowOpenDisposition disposition,
|
|
|
|
|
const gfx::Rect& initial_rect,
|
|
|
|
|
bool user_gesture,
|
|
|
|
|
bool* was_blocked) {
|
2018-10-22 18:02:25 +00:00
|
|
|
|
auto* tracker = ChildWebContentsTracker::FromWebContents(new_contents.get());
|
|
|
|
|
DCHECK(tracker);
|
|
|
|
|
|
2016-08-16 00:13:18 +00:00
|
|
|
|
v8::Locker locker(isolate());
|
|
|
|
|
v8::HandleScope handle_scope(isolate());
|
2018-10-22 18:02:25 +00:00
|
|
|
|
auto api_web_contents =
|
2019-05-03 18:11:41 +00:00
|
|
|
|
CreateAndTake(isolate(), std::move(new_contents), Type::BROWSER_WINDOW);
|
2017-01-10 23:40:07 +00:00
|
|
|
|
if (Emit("-add-new-contents", api_web_contents, disposition, user_gesture,
|
2018-04-18 01:55:30 +00:00
|
|
|
|
initial_rect.x(), initial_rect.y(), initial_rect.width(),
|
2020-03-26 18:05:45 +00:00
|
|
|
|
initial_rect.height(), tracker->url, tracker->frame_name,
|
|
|
|
|
tracker->referrer, tracker->raw_features, tracker->body)) {
|
2018-11-08 15:57:28 +00:00
|
|
|
|
// TODO(zcbenz): Can we make this sync?
|
2017-04-19 16:24:04 +00:00
|
|
|
|
api_web_contents->DestroyWebContents(true /* async */);
|
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,
|
|
|
|
|
const content::OpenURLParams& params) {
|
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
|
|
|
|
|
2014-12-17 22:55:22 +00:00
|
|
|
|
// Give user a chance to cancel navigation.
|
2015-01-15 01:51:54 +00:00
|
|
|
|
if (Emit("will-navigate", params.url))
|
2014-12-17 22:55:22 +00:00
|
|
|
|
return nullptr;
|
|
|
|
|
|
2016-12-21 00:51:03 +00:00
|
|
|
|
// Don't load the URL if the web contents was marked as destroyed from a
|
|
|
|
|
// will-navigate event listener
|
|
|
|
|
if (IsDestroyed())
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
2015-06-05 09:45:17 +00:00
|
|
|
|
return CommonWebContentsDelegate::OpenURLFromTab(source, params);
|
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) {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::BROWSER_WINDOW || type_ == Type::OFF_SCREEN)
|
2015-06-25 03:07:23 +00:00
|
|
|
|
*proceed_to_fire_unload = proceed;
|
|
|
|
|
else
|
|
|
|
|
*proceed_to_fire_unload = true;
|
|
|
|
|
}
|
|
|
|
|
|
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) {
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-22 07:52:08 +00:00
|
|
|
|
if (managed_web_contents())
|
|
|
|
|
managed_web_contents()->GetView()->SetDelegate(nullptr);
|
|
|
|
|
for (ExtendedWebContentsObserver& observer : observers_)
|
|
|
|
|
observer.OnCloseContents();
|
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,
|
|
|
|
|
const content::NativeWebKeyboardEvent& event) {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::WEB_VIEW && 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 {
|
|
|
|
|
// Go to the default keyboard handling.
|
2019-01-09 20:01:49 +00:00
|
|
|
|
return CommonWebContentsDelegate::HandleKeyboardEvent(source, event);
|
2015-06-25 03:07:23 +00:00
|
|
|
|
}
|
2014-10-24 13:46:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-16 21:35:43 +00:00
|
|
|
|
content::KeyboardEventProcessingResult WebContents::PreHandleKeyboardEvent(
|
2016-12-06 22:41:18 +00:00
|
|
|
|
content::WebContents* source,
|
2017-06-16 21:35:43 +00:00
|
|
|
|
const content::NativeWebKeyboardEvent& event) {
|
2017-06-16 20:42:33 +00:00
|
|
|
|
if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown ||
|
|
|
|
|
event.GetType() == blink::WebInputEvent::Type::kKeyUp) {
|
2017-06-16 21:35:43 +00:00
|
|
|
|
bool prevent_default = Emit("before-input-event", event);
|
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 00:17:50 +00:00
|
|
|
|
void WebContents::EnterFullscreenModeForTab(
|
|
|
|
|
content::WebContents* source,
|
|
|
|
|
const GURL& origin,
|
2019-10-28 22:12:35 +00:00
|
|
|
|
const blink::mojom::FullscreenOptions& options) {
|
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,
|
|
|
|
|
base::Unretained(this), source, origin, options);
|
2016-02-01 10:03:38 +00:00
|
|
|
|
permission_helper->RequestFullscreenPermission(callback);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 00:17:50 +00:00
|
|
|
|
void WebContents::OnEnterFullscreenModeForTab(
|
|
|
|
|
content::WebContents* source,
|
|
|
|
|
const GURL& origin,
|
2019-10-28 22:12:35 +00:00
|
|
|
|
const blink::mojom::FullscreenOptions& options,
|
2018-09-15 00:17:50 +00:00
|
|
|
|
bool allowed) {
|
2016-02-01 10:03:38 +00:00
|
|
|
|
if (!allowed)
|
|
|
|
|
return;
|
2018-09-15 00:17:50 +00:00
|
|
|
|
CommonWebContentsDelegate::EnterFullscreenModeForTab(source, origin, options);
|
2015-06-05 09:27:24 +00:00
|
|
|
|
Emit("enter-html-full-screen");
|
2015-05-08 06:18:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-09 12:17:40 +00:00
|
|
|
|
void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
|
2015-06-05 09:27:24 +00:00
|
|
|
|
CommonWebContentsDelegate::ExitFullscreenModeForTab(source);
|
|
|
|
|
Emit("leave-html-full-screen");
|
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");
|
2018-02-22 06:57:03 +00:00
|
|
|
|
for (ExtendedWebContentsObserver& observer : observers_)
|
|
|
|
|
observer.OnRendererResponsive();
|
2015-06-25 03:07:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-27 07:49:59 +00:00
|
|
|
|
bool WebContents::HandleContextMenu(content::RenderFrameHost* render_frame_host,
|
|
|
|
|
const content::ContextMenuParams& params) {
|
2016-05-03 00:02:33 +00:00
|
|
|
|
if (params.custom_context.is_pepper_menu) {
|
2018-04-18 01:55:30 +00:00
|
|
|
|
Emit("pepper-context-menu", std::make_pair(params, web_contents()),
|
2019-05-03 19:08:41 +00:00
|
|
|
|
base::BindOnce(&content::WebContents::NotifyContextMenuClosed,
|
|
|
|
|
base::Unretained(web_contents()),
|
|
|
|
|
params.custom_context));
|
2016-05-03 00:02:33 +00:00
|
|
|
|
} else {
|
|
|
|
|
Emit("context-menu", std::make_pair(params, web_contents()));
|
|
|
|
|
}
|
2015-11-02 15:28:45 +00:00
|
|
|
|
|
2015-10-31 13:39:07 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-19 19:53:47 +00:00
|
|
|
|
bool WebContents::OnGoToEntryOffset(int offset) {
|
|
|
|
|
GoToOffset(offset);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
|
|
2015-12-17 17:27:56 +00:00
|
|
|
|
v8::Locker locker(isolate());
|
|
|
|
|
v8::HandleScope handle_scope(isolate());
|
2019-10-21 07:05:40 +00:00
|
|
|
|
gin_helper::Dictionary result = gin::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
|
|
|
|
}
|
|
|
|
|
|
2018-09-09 14:30:28 +00:00
|
|
|
|
bool WebContents::CheckMediaAccessPermission(
|
|
|
|
|
content::RenderFrameHost* render_frame_host,
|
|
|
|
|
const GURL& 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
|
|
|
|
}
|
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
|
void WebContents::RequestToLockMouse(content::WebContents* web_contents,
|
|
|
|
|
bool user_gesture,
|
|
|
|
|
bool last_unlocked_by_target) {
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* permission_helper =
|
2016-02-01 09:43:49 +00:00
|
|
|
|
WebContentsPermissionHelper::FromWebContents(web_contents);
|
|
|
|
|
permission_helper->RequestPointerLockPermission(user_gesture);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-30 12:38:09 +00:00
|
|
|
|
std::unique_ptr<content::BluetoothChooser> WebContents::RunBluetoothChooser(
|
|
|
|
|
content::RenderFrameHost* frame,
|
|
|
|
|
const content::BluetoothChooser::EventHandler& event_handler) {
|
2018-06-18 07:32:55 +00:00
|
|
|
|
return std::make_unique<BluetoothChooser>(this, event_handler);
|
2016-05-30 12:38:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
|
content::JavaScriptDialogManager* WebContents::GetJavaScriptDialogManager(
|
2017-04-28 00:28:48 +00:00
|
|
|
|
content::WebContents* source) {
|
|
|
|
|
if (!dialog_manager_)
|
2020-02-04 20:19:40 +00:00
|
|
|
|
dialog_manager_ = std::make_unique<ElectronJavaScriptDialogManager>(this);
|
2017-04-28 00:28:48 +00:00
|
|
|
|
|
|
|
|
|
return dialog_manager_.get();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 00:18:14 +00:00
|
|
|
|
void WebContents::OnAudioStateChanged(bool audible) {
|
2018-09-05 21:00:05 +00:00
|
|
|
|
Emit("-audio-state-changed", audible);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-12 01:00:43 +00:00
|
|
|
|
void WebContents::BeforeUnloadFired(bool proceed,
|
|
|
|
|
const base::TimeTicks& proceed_time) {
|
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.
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-28 23:44:44 +00:00
|
|
|
|
void WebContents::RenderViewCreated(content::RenderViewHost* render_view_host) {
|
2019-12-02 18:29:03 +00:00
|
|
|
|
if (!background_throttling_)
|
|
|
|
|
render_view_host->SetSchedulerThrottling(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::RenderFrameCreated(
|
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
|
|
|
|
auto* rwhv = render_frame_host->GetView();
|
|
|
|
|
if (!rwhv)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
auto* rwh_impl =
|
|
|
|
|
static_cast<content::RenderWidgetHostImpl*>(rwhv->GetRenderWidgetHost());
|
|
|
|
|
if (rwh_impl)
|
|
|
|
|
rwh_impl->disable_hidden_ = !background_throttling_;
|
2016-12-28 23:44:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-05 08:03:39 +00:00
|
|
|
|
void WebContents::RenderViewHostChanged(content::RenderViewHost* old_host,
|
|
|
|
|
content::RenderViewHost* new_host) {
|
|
|
|
|
currently_committed_process_id_ = new_host->GetProcess()->GetID();
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
if (-1 == currently_committed_process_id_ ||
|
|
|
|
|
render_view_host->GetProcess()->GetID() ==
|
|
|
|
|
currently_committed_process_id_) {
|
|
|
|
|
currently_committed_process_id_ = -1;
|
|
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
// Currently tracked by guest-window-manager.js to destroy the
|
|
|
|
|
// BrowserWindow.
|
|
|
|
|
Emit("current-render-view-deleted",
|
|
|
|
|
render_view_host->GetProcess()->GetID());
|
|
|
|
|
}
|
2014-04-25 03:51:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::RenderProcessGone(base::TerminationStatus status) {
|
2016-09-18 00:00:45 +00:00
|
|
|
|
Emit("crashed", status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
|
2020-05-11 20:42:24 +00:00
|
|
|
|
v8::HandleScope handle_scope(isolate());
|
|
|
|
|
gin_helper::Dictionary details =
|
|
|
|
|
gin_helper::Dictionary::CreateEmpty(isolate());
|
|
|
|
|
details.Set("reason", status);
|
|
|
|
|
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);
|
2019-10-09 17:59:37 +00:00
|
|
|
|
#endif // BUILDFLAG(ENABLE_PLUIGNS)
|
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) {
|
2019-06-19 21:23:04 +00:00
|
|
|
|
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-04-02 22:38:16 +00:00
|
|
|
|
void WebContents::OnInterfaceRequestFromFrame(
|
|
|
|
|
content::RenderFrameHost* render_frame_host,
|
|
|
|
|
const std::string& interface_name,
|
|
|
|
|
mojo::ScopedMessagePipeHandle* interface_pipe) {
|
|
|
|
|
registry_.TryBindInterface(interface_name, interface_pipe, render_frame_host);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-13 21:02:56 +00:00
|
|
|
|
void WebContents::DidAcquireFullscreen(content::RenderFrameHost* rfh) {
|
|
|
|
|
set_fullscreen_frame(rfh);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-18 19:57:34 +00:00
|
|
|
|
void WebContents::DOMContentLoaded(
|
2015-04-29 13:49:31 +00:00
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
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.
|
|
|
|
|
if (is_main_frame && weak_this)
|
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) {
|
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() {
|
2014-04-25 04:22:16 +00:00
|
|
|
|
Emit("did-stop-loading");
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 15:42:43 +00:00
|
|
|
|
bool WebContents::EmitNavigationEvent(
|
|
|
|
|
const std::string& event,
|
2018-04-26 10:17:55 +00:00
|
|
|
|
content::NavigationHandle* navigation_handle) {
|
|
|
|
|
bool is_main_frame = navigation_handle->IsInMainFrame();
|
|
|
|
|
int frame_tree_node_id = navigation_handle->GetFrameTreeNodeId();
|
|
|
|
|
content::FrameTreeNode* frame_tree_node =
|
2018-05-10 20:52:42 +00:00
|
|
|
|
content::FrameTreeNode::GloballyFindByID(frame_tree_node_id);
|
2018-04-26 10:17:55 +00:00
|
|
|
|
content::RenderFrameHostManager* render_manager =
|
2018-05-10 20:52:42 +00:00
|
|
|
|
frame_tree_node->render_manager();
|
2018-04-26 10:17:55 +00:00
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
bool is_same_document = navigation_handle->IsSameDocument();
|
|
|
|
|
auto url = navigation_handle->GetURL();
|
2018-09-15 15:42:43 +00:00
|
|
|
|
return Emit(event, url, is_same_document, is_main_frame, frame_process_id,
|
|
|
|
|
frame_routing_id);
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-02 22:38:16 +00:00
|
|
|
|
void WebContents::BindElectronBrowser(
|
|
|
|
|
mojom::ElectronBrowserRequest request,
|
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
|
|
|
|
auto id = bindings_.AddBinding(this, std::move(request), render_frame_host);
|
|
|
|
|
frame_to_bindings_map_[render_frame_host].push_back(id);
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-03 21:22:23 +00:00
|
|
|
|
void WebContents::OnElectronBrowserConnectionError() {
|
|
|
|
|
auto binding_id = bindings_.dispatch_binding();
|
|
|
|
|
auto* frame_host = bindings_.dispatch_context();
|
|
|
|
|
base::Erase(frame_to_bindings_map_[frame_host], binding_id);
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-02 22:38:16 +00:00
|
|
|
|
void WebContents::Message(bool internal,
|
|
|
|
|
const std::string& channel,
|
2019-10-09 17:59:08 +00:00
|
|
|
|
blink::CloneableMessage arguments) {
|
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);
|
2019-10-31 07:56:00 +00:00
|
|
|
|
EmitWithSender("-ipc-message", bindings_.dispatch_context(), InvokeCallback(),
|
2019-04-02 22:38:16 +00:00
|
|
|
|
internal, channel, std::move(arguments));
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-23 22:45:50 +00:00
|
|
|
|
void WebContents::Invoke(bool internal,
|
|
|
|
|
const std::string& channel,
|
2019-10-09 17:59:08 +00:00
|
|
|
|
blink::CloneableMessage arguments,
|
2019-05-31 17:25:19 +00:00
|
|
|
|
InvokeCallback callback) {
|
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);
|
2019-05-31 17:25:19 +00:00
|
|
|
|
EmitWithSender("-ipc-invoke", bindings_.dispatch_context(),
|
2019-08-23 22:45:50 +00:00
|
|
|
|
std::move(callback), internal, channel, std::move(arguments));
|
2019-05-31 17:25:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-12 01:07:54 +00:00
|
|
|
|
void WebContents::ReceivePostMessage(const std::string& channel,
|
|
|
|
|
blink::TransferableMessage message) {
|
|
|
|
|
v8::HandleScope handle_scope(isolate());
|
|
|
|
|
auto wrapped_ports =
|
|
|
|
|
MessagePort::EntanglePorts(isolate(), std::move(message.ports));
|
|
|
|
|
v8::Local<v8::Value> message_value =
|
|
|
|
|
electron::DeserializeV8Value(isolate(), message);
|
|
|
|
|
EmitWithSender("-ipc-ports", bindings_.dispatch_context(), InvokeCallback(),
|
|
|
|
|
false, channel, message_value, std::move(wrapped_ports));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::PostMessage(const std::string& channel,
|
|
|
|
|
v8::Local<v8::Value> message_value,
|
|
|
|
|
base::Optional<v8::Local<v8::Value>> transfer) {
|
|
|
|
|
blink::TransferableMessage transferable_message;
|
|
|
|
|
if (!electron::SerializeV8Value(isolate(), message_value,
|
|
|
|
|
&transferable_message)) {
|
|
|
|
|
// SerializeV8Value sets an exception.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<gin::Handle<MessagePort>> wrapped_ports;
|
|
|
|
|
if (transfer) {
|
|
|
|
|
if (!gin::ConvertFromV8(isolate(), *transfer, &wrapped_ports)) {
|
|
|
|
|
isolate()->ThrowException(v8::Exception::Error(
|
|
|
|
|
gin::StringToV8(isolate(), "Invalid value for transfer")));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool threw_exception = false;
|
|
|
|
|
transferable_message.ports =
|
|
|
|
|
MessagePort::DisentanglePorts(isolate(), wrapped_ports, &threw_exception);
|
|
|
|
|
if (threw_exception)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
content::RenderFrameHost* frame_host = web_contents()->GetMainFrame();
|
|
|
|
|
mojo::AssociatedRemote<mojom::ElectronRenderer> electron_renderer;
|
|
|
|
|
frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&electron_renderer);
|
|
|
|
|
electron_renderer->ReceivePostMessage(channel,
|
|
|
|
|
std::move(transferable_message));
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-02 22:38:16 +00:00
|
|
|
|
void WebContents::MessageSync(bool internal,
|
|
|
|
|
const std::string& channel,
|
2019-10-09 17:59:08 +00:00
|
|
|
|
blink::CloneableMessage arguments,
|
2019-04-02 22:38:16 +00:00
|
|
|
|
MessageSyncCallback callback) {
|
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);
|
|
|
|
|
EmitWithSender("-ipc-message-sync", bindings_.dispatch_context(),
|
|
|
|
|
std::move(callback), internal, channel, std::move(arguments));
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-03 21:22:23 +00:00
|
|
|
|
void WebContents::MessageTo(bool internal,
|
|
|
|
|
bool send_to_all,
|
|
|
|
|
int32_t web_contents_id,
|
|
|
|
|
const std::string& channel,
|
2019-10-09 17:59:08 +00:00
|
|
|
|
blink::CloneableMessage arguments) {
|
2019-12-06 21:15:23 +00:00
|
|
|
|
TRACE_EVENT1("electron", "WebContents::MessageTo", "channel", channel);
|
2019-10-25 13:03:28 +00:00
|
|
|
|
auto* web_contents = gin_helper::TrackableObject<WebContents>::FromWeakMapID(
|
2019-04-03 21:22:23 +00:00
|
|
|
|
isolate(), web_contents_id);
|
|
|
|
|
|
|
|
|
|
if (web_contents) {
|
|
|
|
|
web_contents->SendIPCMessageWithSender(internal, send_to_all, channel,
|
2019-10-09 17:59:08 +00:00
|
|
|
|
std::move(arguments), ID());
|
2019-04-03 21:22:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::MessageHost(const std::string& channel,
|
2019-10-09 17:59:08 +00:00
|
|
|
|
blink::CloneableMessage arguments) {
|
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);
|
|
|
|
|
EmitWithSender("ipc-message-host", bindings_.dispatch_context(),
|
2019-10-31 07:56:00 +00:00
|
|
|
|
InvokeCallback(), channel, std::move(arguments));
|
2019-04-03 21:22:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-09 17:59:08 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_REMOTE_MODULE)
|
|
|
|
|
void WebContents::DereferenceRemoteJSObject(const std::string& context_id,
|
|
|
|
|
int object_id,
|
|
|
|
|
int ref_count) {
|
|
|
|
|
base::ListValue args;
|
|
|
|
|
args.Append(context_id);
|
|
|
|
|
args.Append(object_id);
|
|
|
|
|
args.Append(ref_count);
|
2019-10-31 07:56:00 +00:00
|
|
|
|
EmitWithSender("-ipc-message", bindings_.dispatch_context(), InvokeCallback(),
|
2019-10-09 17:59:08 +00:00
|
|
|
|
/* internal */ true, "ELECTRON_BROWSER_DEREFERENCE",
|
|
|
|
|
std::move(args));
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-06-03 17:43:04 +00:00
|
|
|
|
void WebContents::UpdateDraggableRegions(
|
|
|
|
|
std::vector<mojom::DraggableRegionPtr> regions) {
|
|
|
|
|
for (ExtendedWebContentsObserver& observer : observers_)
|
|
|
|
|
observer.OnDraggableRegionsUpdated(regions);
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-02 22:38:16 +00:00
|
|
|
|
void WebContents::RenderFrameDeleted(
|
|
|
|
|
content::RenderFrameHost* render_frame_host) {
|
|
|
|
|
// A RenderFrameHost can be destroyed before the related Mojo binding is
|
|
|
|
|
// closed, which can result in Mojo calls being sent for RenderFrameHosts
|
|
|
|
|
// that no longer exist. To prevent this from happening, when a
|
|
|
|
|
// RenderFrameHost goes away, we close all the bindings related to that
|
|
|
|
|
// frame.
|
|
|
|
|
auto it = frame_to_bindings_map_.find(render_frame_host);
|
|
|
|
|
if (it == frame_to_bindings_map_.end())
|
|
|
|
|
return;
|
|
|
|
|
for (auto id : it->second)
|
|
|
|
|
bindings_.RemoveBinding(id);
|
|
|
|
|
frame_to_bindings_map_.erase(it);
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2016-07-14 00:19:28 +00:00
|
|
|
|
void WebContents::DidFinishNavigation(
|
|
|
|
|
content::NavigationHandle* navigation_handle) {
|
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
|
|
|
|
}
|
2018-08-16 22:57:40 +00:00
|
|
|
|
if (IsGuest())
|
|
|
|
|
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.
|
|
|
|
|
if (code != net::ERR_ABORTED)
|
2018-05-10 20:52:42 +00:00
|
|
|
|
Emit("did-fail-load", code, description, url, is_main_frame,
|
|
|
|
|
frame_process_id, frame_routing_id);
|
2016-07-14 00:19:28 +00:00
|
|
|
|
}
|
2014-12-09 22:38:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-18 00:19:21 +00:00
|
|
|
|
void WebContents::TitleWasSet(content::NavigationEntry* entry) {
|
2017-12-18 07:54:44 +00:00
|
|
|
|
base::string16 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;
|
|
|
|
|
}
|
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-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() {
|
|
|
|
|
v8::Locker locker(isolate());
|
|
|
|
|
v8::HandleScope handle_scope(isolate());
|
2018-10-19 08:52:07 +00:00
|
|
|
|
auto handle =
|
|
|
|
|
FromOrCreate(isolate(), managed_web_contents()->GetDevToolsWebContents());
|
2015-10-01 03:14:19 +00:00
|
|
|
|
devtools_web_contents_.Reset(isolate(), handle.ToV8());
|
|
|
|
|
|
2016-05-26 10:29:39 +00:00
|
|
|
|
// Set inspected tabID.
|
2017-04-05 08:34:53 +00:00
|
|
|
|
base::Value tab_id(ID());
|
2018-04-18 01:55:30 +00:00
|
|
|
|
managed_web_contents()->CallClientFunction("DevToolsAPI.setInspectedTabId",
|
|
|
|
|
&tab_id, nullptr, nullptr);
|
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.
|
2017-11-30 07:37:26 +00:00
|
|
|
|
auto* devtools = managed_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() {
|
|
|
|
|
v8::Locker locker(isolate());
|
|
|
|
|
v8::HandleScope handle_scope(isolate());
|
|
|
|
|
devtools_web_contents_.Reset();
|
|
|
|
|
|
|
|
|
|
Emit("devtools-closed");
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-25 08:13:16 +00:00
|
|
|
|
bool WebContents::OnMessageReceived(const IPC::Message& message) {
|
|
|
|
|
bool handled = true;
|
|
|
|
|
IPC_BEGIN_MESSAGE_MAP(WebContents, message)
|
2019-01-12 01:00:43 +00:00
|
|
|
|
IPC_MESSAGE_HANDLER_CODE(WidgetHostMsg_SetCursor, OnCursorChange,
|
2017-12-19 00:57:10 +00:00
|
|
|
|
handled = false)
|
2017-05-26 01:38:27 +00:00
|
|
|
|
IPC_MESSAGE_UNHANDLED(handled = false)
|
|
|
|
|
IPC_END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
|
|
return handled;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-13 09:59:59 +00:00
|
|
|
|
// There are three ways of destroying a webContents:
|
2016-07-28 22:48:01 +00:00
|
|
|
|
// 1. call webContents.destroy();
|
2016-01-13 09:59:59 +00:00
|
|
|
|
// 2. garbage collection;
|
|
|
|
|
// 3. user closes the window of webContents;
|
2018-08-16 22:57:40 +00:00
|
|
|
|
// 4. the embedder detaches the frame.
|
2019-07-11 22:25:27 +00:00
|
|
|
|
// For webview only #4 will happen, for BrowserWindow both #1 and #3 may
|
2016-01-13 09:59:59 +00:00
|
|
|
|
// happen. The #2 should never happen for webContents, because webview is
|
|
|
|
|
// managed by GuestViewManager, and BrowserWindow's webContents is managed
|
2018-02-22 03:49:17 +00:00
|
|
|
|
// by api::BrowserWindow.
|
2016-01-13 09:59:59 +00:00
|
|
|
|
// For #1, the destructor will do the cleanup work and we only need to make
|
|
|
|
|
// sure "destroyed" event is emitted. For #3, the content::WebContents will
|
|
|
|
|
// be destroyed on close, and WebContentsDestroyed would be called for it, so
|
|
|
|
|
// we need to make sure the api::WebContents is also deleted.
|
2018-08-16 22:57:40 +00:00
|
|
|
|
// For #4, the WebContents will be destroyed by embedder.
|
2014-07-28 07:29:51 +00:00
|
|
|
|
void WebContents::WebContentsDestroyed() {
|
2016-01-13 06:47:39 +00:00
|
|
|
|
// Cleanup relationships with other parts.
|
2015-06-24 09:58:12 +00:00
|
|
|
|
RemoveFromWeakMap();
|
2016-01-12 13:10:24 +00:00
|
|
|
|
|
|
|
|
|
// We can not call Destroy here because we need to call Emit first, but we
|
|
|
|
|
// also do not want any method to be used, so just mark as destroyed here.
|
|
|
|
|
MarkDestroyed();
|
|
|
|
|
|
|
|
|
|
Emit("destroyed");
|
|
|
|
|
|
2018-08-16 22:57:40 +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.
|
|
|
|
|
if (IsGuest() && managed_web_contents()) {
|
|
|
|
|
managed_web_contents()->ReleaseWebContents();
|
|
|
|
|
ResetManagedWebContents(false);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-12 13:10:24 +00:00
|
|
|
|
// Destroy the native class in next tick.
|
2018-04-18 01:55:30 +00:00
|
|
|
|
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, GetDestroyClosure());
|
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
|
|
|
|
}
|
|
|
|
|
|
2018-10-19 00:32:22 +00:00
|
|
|
|
void WebContents::SetBackgroundThrottling(bool allowed) {
|
|
|
|
|
background_throttling_ = allowed;
|
|
|
|
|
|
2019-12-02 18:29:03 +00:00
|
|
|
|
auto* rfh = web_contents()->GetMainFrame();
|
|
|
|
|
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()) {
|
|
|
|
|
rwh_impl->WasShown(base::nullopt);
|
2018-10-19 00:32:22 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-06 01:28:40 +00:00
|
|
|
|
int WebContents::GetProcessID() const {
|
2017-12-18 02:46:23 +00:00
|
|
|
|
return web_contents()->GetMainFrame()->GetProcess()->GetID();
|
2015-06-23 08:16:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-15 20:29:34 +00:00
|
|
|
|
base::ProcessId WebContents::GetOSProcessID() const {
|
2018-06-25 20:30:00 +00:00
|
|
|
|
base::ProcessHandle process_handle =
|
2018-09-15 00:13:02 +00:00
|
|
|
|
web_contents()->GetMainFrame()->GetProcess()->GetProcess().Handle();
|
2017-04-18 10:31:20 +00:00
|
|
|
|
return base::GetProcId(process_handle);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-20 10:10:56 +00:00
|
|
|
|
base::ProcessId WebContents::GetOSProcessIdForFrame(
|
|
|
|
|
const std::string& name,
|
|
|
|
|
const std::string& document_url) const {
|
|
|
|
|
for (auto* frame : web_contents()->GetAllFrames()) {
|
|
|
|
|
if (frame->GetFrameName() == name &&
|
|
|
|
|
frame->GetLastCommittedURL().spec() == document_url) {
|
|
|
|
|
return base::GetProcId(frame->GetProcess()->GetProcess().Handle());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return base::kNullProcessId;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-14 16:09:54 +00:00
|
|
|
|
WebContents::Type WebContents::GetType() const {
|
|
|
|
|
return type_;
|
2016-06-08 18:41:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
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))
|
2020-04-13 23:39:26 +00:00
|
|
|
|
web_contents()->SetUserAgentOverride(
|
|
|
|
|
blink::UserAgentOverride::UserAgentOnly(user_agent), false);
|
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();
|
|
|
|
|
|
2014-12-07 15:43:26 +00:00
|
|
|
|
params.transition_type = ui::PAGE_TRANSITION_TYPED;
|
2015-04-26 13:31:48 +00:00
|
|
|
|
params.should_clear_history_list = true;
|
2014-04-25 04:52:30 +00:00
|
|
|
|
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
|
2019-03-28 18:13:05 +00:00
|
|
|
|
// Discord non-committed entries to ensure that we don't re-use a pending
|
|
|
|
|
// entry
|
|
|
|
|
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.
|
|
|
|
|
if (!weak_this)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-04-07 17:34:14 +00:00
|
|
|
|
// Set the background color of RenderWidgetHostView.
|
2016-04-03 01:37:48 +00:00
|
|
|
|
// We have to call it right after LoadURL because the RenderViewHost is only
|
|
|
|
|
// created after loading a page.
|
2019-09-30 22:00:47 +00:00
|
|
|
|
auto* const view = weak_this->web_contents()->GetRenderWidgetHostView();
|
2017-04-07 17:34:14 +00:00
|
|
|
|
if (view) {
|
2018-03-08 07:12:45 +00:00
|
|
|
|
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
2017-04-07 17:34:14 +00:00
|
|
|
|
std::string color_name;
|
2018-08-03 21:23:07 +00:00
|
|
|
|
if (web_preferences->GetPreference(options::kBackgroundColor,
|
|
|
|
|
&color_name)) {
|
2017-04-07 17:34:14 +00:00
|
|
|
|
view->SetBackgroundColor(ParseHexColor(color_name));
|
|
|
|
|
} else {
|
|
|
|
|
view->SetBackgroundColor(SK_ColorTRANSPARENT);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-04-25 04:52:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-02 21:49:30 +00:00
|
|
|
|
void WebContents::DownloadURL(const GURL& url) {
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* browser_context = web_contents()->GetBrowserContext();
|
|
|
|
|
auto* download_manager =
|
2018-04-18 01:55:30 +00:00
|
|
|
|
content::BrowserContext::GetDownloadManager(browser_context);
|
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));
|
2018-04-12 07:30:51 +00:00
|
|
|
|
download_manager->DownloadUrl(std::move(download_params));
|
2015-12-02 21:49:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-09-15 01:17:45 +00:00
|
|
|
|
GURL WebContents::GetURL() const {
|
|
|
|
|
return web_contents()->GetURL();
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 11:36:57 +00:00
|
|
|
|
base::string16 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 {
|
2018-04-06 07:22:52 +00:00
|
|
|
|
return web_contents()->IsLoadingToDifferentDocument();
|
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
|
|
|
|
}
|
|
|
|
|
|
2015-05-11 06:30:26 +00:00
|
|
|
|
void WebContents::GoBack() {
|
2020-02-24 19:43:55 +00:00
|
|
|
|
if (!ElectronBrowserClient::Get()->CanUseCustomSiteInstance()) {
|
|
|
|
|
electron::ElectronBrowserClient::SuppressRendererProcessRestartForOnce();
|
|
|
|
|
}
|
2015-05-11 06:30:26 +00:00
|
|
|
|
web_contents()->GetController().GoBack();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::GoForward() {
|
2020-02-24 19:43:55 +00:00
|
|
|
|
if (!ElectronBrowserClient::Get()->CanUseCustomSiteInstance()) {
|
|
|
|
|
electron::ElectronBrowserClient::SuppressRendererProcessRestartForOnce();
|
|
|
|
|
}
|
2015-05-11 06:30:26 +00:00
|
|
|
|
web_contents()->GetController().GoForward();
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-11 08:44:01 +00:00
|
|
|
|
void WebContents::GoToOffset(int offset) {
|
2020-02-24 19:43:55 +00:00
|
|
|
|
if (!ElectronBrowserClient::Get()->CanUseCustomSiteInstance()) {
|
|
|
|
|
electron::ElectronBrowserClient::SuppressRendererProcessRestartForOnce();
|
|
|
|
|
}
|
2015-05-11 08:44:01 +00:00
|
|
|
|
web_contents()->GetController().GoToOffset(offset);
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2016-06-22 06:57:51 +00:00
|
|
|
|
void WebContents::SetUserAgent(const std::string& user_agent,
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin_helper::Arguments* args) {
|
2020-04-13 23:39:26 +00:00
|
|
|
|
web_contents()->SetUserAgentOverride(
|
|
|
|
|
blink::UserAgentOverride::UserAgentOnly(user_agent), 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) {
|
2019-11-01 06:10:32 +00:00
|
|
|
|
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
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
void WebContents::OpenDevTools(gin_helper::Arguments* args) {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::REMOTE)
|
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;
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::WEB_VIEW || !owner_window()) {
|
2016-04-19 12:42:05 +00:00
|
|
|
|
state = "detach";
|
2017-12-01 02:11:37 +00:00
|
|
|
|
}
|
2018-11-27 09:34:44 +00:00
|
|
|
|
bool activate = true;
|
2017-12-01 02:11:37 +00:00
|
|
|
|
if (args && args->Length() == 1) {
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin_helper::Dictionary options;
|
2016-04-19 12:42:05 +00:00
|
|
|
|
if (args->GetNext(&options)) {
|
|
|
|
|
options.Get("mode", &state);
|
2018-11-27 09:34:44 +00:00
|
|
|
|
options.Get("activate", &activate);
|
2016-04-19 12:42:05 +00:00
|
|
|
|
}
|
2015-06-05 09:01:17 +00:00
|
|
|
|
}
|
2016-04-19 12:42:05 +00:00
|
|
|
|
managed_web_contents()->SetDockState(state);
|
2018-11-27 09:34:44 +00:00
|
|
|
|
managed_web_contents()->ShowDevTools(activate);
|
2014-11-02 14:34:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-11-03 14:12:56 +00:00
|
|
|
|
void WebContents::CloseDevTools() {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::REMOTE)
|
2015-06-05 07:41:03 +00:00
|
|
|
|
return;
|
2015-06-24 14:23:38 +00:00
|
|
|
|
|
2015-06-25 06:32:38 +00:00
|
|
|
|
managed_web_contents()->CloseDevTools();
|
2014-11-03 14:12:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::IsDevToolsOpened() {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::REMOTE)
|
2015-06-05 07:41:03 +00:00
|
|
|
|
return false;
|
2015-06-25 06:32:38 +00:00
|
|
|
|
|
|
|
|
|
return managed_web_contents()->IsDevToolsViewShowing();
|
2014-11-03 14:12:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-01 05:11:21 +00:00
|
|
|
|
bool WebContents::IsDevToolsFocused() {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::REMOTE)
|
2016-01-01 05:11:21 +00:00
|
|
|
|
return false;
|
2016-01-01 09:45:03 +00:00
|
|
|
|
|
2016-01-01 05:11:21 +00:00
|
|
|
|
return managed_web_contents()->GetView()->IsDevToolsViewFocused();
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-18 03:06:38 +00:00
|
|
|
|
void WebContents::EnableDeviceEmulation(
|
|
|
|
|
const blink::WebDeviceEmulationParams& params) {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::REMOTE)
|
2015-08-31 09:19:19 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* frame_host = web_contents()->GetMainFrame();
|
2017-12-30 16:25:09 +00:00
|
|
|
|
if (frame_host) {
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* widget_host =
|
2017-12-30 16:25:09 +00:00
|
|
|
|
frame_host ? frame_host->GetView()->GetRenderWidgetHost() : nullptr;
|
|
|
|
|
if (!widget_host)
|
|
|
|
|
return;
|
2019-01-12 01:00:43 +00:00
|
|
|
|
widget_host->Send(new WidgetMsg_EnableDeviceEmulation(
|
|
|
|
|
widget_host->GetRoutingID(), params));
|
2017-12-30 16:25:09 +00:00
|
|
|
|
}
|
2015-08-31 09:19:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DisableDeviceEmulation() {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::REMOTE)
|
2015-08-31 09:19:19 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* frame_host = web_contents()->GetMainFrame();
|
2017-12-30 16:25:09 +00:00
|
|
|
|
if (frame_host) {
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* widget_host =
|
2017-12-30 16:25:09 +00:00
|
|
|
|
frame_host ? frame_host->GetView()->GetRenderWidgetHost() : nullptr;
|
|
|
|
|
if (!widget_host)
|
|
|
|
|
return;
|
|
|
|
|
widget_host->Send(
|
2019-01-12 01:00:43 +00:00
|
|
|
|
new WidgetMsg_DisableDeviceEmulation(widget_host->GetRoutingID()));
|
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) {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::REMOTE)
|
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;
|
|
|
|
|
|
2016-08-23 22:26:13 +00:00
|
|
|
|
if (!managed_web_contents()->GetDevToolsWebContents())
|
|
|
|
|
OpenDevTools(nullptr);
|
2016-12-20 00:25:32 +00:00
|
|
|
|
managed_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) {
|
|
|
|
|
if (type_ == Type::REMOTE)
|
|
|
|
|
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);
|
|
|
|
|
managed_web_contents()->AttachTo(agent_host);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<scoped_refptr<content::DevToolsAgentHost>>
|
|
|
|
|
WebContents::GetAllSharedWorkers() {
|
|
|
|
|
std::vector<scoped_refptr<content::DevToolsAgentHost>> shared_workers;
|
|
|
|
|
|
|
|
|
|
if (type_ == Type::REMOTE)
|
|
|
|
|
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() {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::REMOTE)
|
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);
|
|
|
|
|
managed_web_contents()->AttachTo(agent_host);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-05 07:41:03 +00:00
|
|
|
|
void WebContents::InspectServiceWorker() {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (type_ == Type::REMOTE)
|
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);
|
2015-06-25 06:32:38 +00:00
|
|
|
|
managed_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);
|
|
|
|
|
web_preferences->preference()->SetKey("ignoreMenuShortcuts",
|
|
|
|
|
base::Value(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)
|
2020-01-31 19:20:11 +00:00
|
|
|
|
void WebContents::OnGetDefaultPrinter(
|
|
|
|
|
base::Value print_settings,
|
|
|
|
|
printing::CompletionCallback print_callback,
|
|
|
|
|
base::string16 device_name,
|
|
|
|
|
bool silent,
|
|
|
|
|
base::string16 default_printer) {
|
2020-02-05 15:48:51 +00:00
|
|
|
|
// The content::WebContents might be already deleted at this point, and the
|
|
|
|
|
// PrintViewManagerBasic class does not do null check.
|
|
|
|
|
if (!web_contents()) {
|
|
|
|
|
if (print_callback)
|
|
|
|
|
std::move(print_callback).Run(false, "failed");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-31 19:20:11 +00:00
|
|
|
|
base::string16 printer_name =
|
|
|
|
|
device_name.empty() ? default_printer : device_name;
|
2020-03-04 02:20:31 +00:00
|
|
|
|
|
|
|
|
|
// If there are no valid printers available on the network, we bail.
|
|
|
|
|
if (printer_name.empty() || !IsDeviceNameValid(printer_name)) {
|
|
|
|
|
if (print_callback)
|
|
|
|
|
std::move(print_callback).Run(false, "no valid printers available");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-31 19:20:11 +00:00
|
|
|
|
print_settings.SetStringKey(printing::kSettingDeviceName, printer_name);
|
|
|
|
|
|
|
|
|
|
auto* print_view_manager =
|
|
|
|
|
printing::PrintViewManagerBasic::FromWebContents(web_contents());
|
|
|
|
|
auto* focused_frame = web_contents()->GetFocusedFrame();
|
|
|
|
|
auto* rfh = focused_frame && focused_frame->HasSelection()
|
|
|
|
|
? focused_frame
|
|
|
|
|
: web_contents()->GetMainFrame();
|
|
|
|
|
|
|
|
|
|
print_view_manager->PrintNow(rfh, silent, std::move(print_settings),
|
|
|
|
|
std::move(print_callback));
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
void WebContents::Print(gin_helper::Arguments* args) {
|
|
|
|
|
gin_helper::Dictionary options =
|
|
|
|
|
gin::Dictionary::CreateEmpty(args->isolate());
|
2019-11-08 18:01:50 +00:00
|
|
|
|
base::Value settings(base::Value::Type::DICTIONARY);
|
2019-08-07 14:47:24 +00:00
|
|
|
|
|
2018-11-09 03:42:34 +00:00
|
|
|
|
if (args->Length() >= 1 && !args->GetNext(&options)) {
|
2019-08-07 14:47:24 +00:00
|
|
|
|
args->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)) {
|
2019-08-07 14:47:24 +00:00
|
|
|
|
args->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
|
|
|
|
|
|
|
|
|
// Set optional silent printing
|
|
|
|
|
bool silent = false;
|
2018-11-09 03:42:34 +00:00
|
|
|
|
options.Get("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);
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetBoolKey(printing::kSettingShouldPrintBackgrounds,
|
2019-08-07 14:47:24 +00:00
|
|
|
|
print_background);
|
|
|
|
|
|
2019-06-30 05:12:00 +00:00
|
|
|
|
// Set custom margin settings
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin_helper::Dictionary margins =
|
|
|
|
|
gin::Dictionary::CreateEmpty(args->isolate());
|
2019-06-30 05:12:00 +00:00
|
|
|
|
if (options.Get("margins", &margins)) {
|
|
|
|
|
printing::MarginType margin_type = printing::DEFAULT_MARGINS;
|
|
|
|
|
margins.Get("marginType", &margin_type);
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetIntKey(printing::kSettingMarginsType, margin_type);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
|
|
|
|
if (margin_type == printing::CUSTOM_MARGINS) {
|
2020-02-13 17:15:25 +00:00
|
|
|
|
base::Value custom_margins(base::Value::Type::DICTIONARY);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int top = 0;
|
|
|
|
|
margins.Get("top", &top);
|
2020-02-13 17:15:25 +00:00
|
|
|
|
custom_margins.SetIntKey(printing::kSettingMarginTop, top);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int bottom = 0;
|
|
|
|
|
margins.Get("bottom", &bottom);
|
2020-02-13 17:15:25 +00:00
|
|
|
|
custom_margins.SetIntKey(printing::kSettingMarginBottom, bottom);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int left = 0;
|
|
|
|
|
margins.Get("left", &left);
|
2020-02-13 17:15:25 +00:00
|
|
|
|
custom_margins.SetIntKey(printing::kSettingMarginLeft, left);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int right = 0;
|
|
|
|
|
margins.Get("right", &right);
|
2020-02-13 17:15:25 +00:00
|
|
|
|
custom_margins.SetIntKey(printing::kSettingMarginRight, right);
|
|
|
|
|
settings.SetPath(printing::kSettingMarginsCustom,
|
|
|
|
|
std::move(custom_margins));
|
2019-06-30 05:12:00 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetIntKey(printing::kSettingMarginsType,
|
|
|
|
|
printing::DEFAULT_MARGINS);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set whether to print color or greyscale
|
|
|
|
|
bool print_color = true;
|
|
|
|
|
options.Get("color", &print_color);
|
|
|
|
|
int color_setting = print_color ? printing::COLOR : printing::GRAY;
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetIntKey(printing::kSettingColor, color_setting);
|
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);
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetBoolKey(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.
|
2019-06-30 05:12:00 +00:00
|
|
|
|
base::string16 device_name;
|
|
|
|
|
options.Get("deviceName", &device_name);
|
2020-01-31 02:49:13 +00:00
|
|
|
|
if (!device_name.empty() && !IsDeviceNameValid(device_name)) {
|
|
|
|
|
args->ThrowError("webContents.print(): Invalid deviceName provided.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
|
|
|
|
int scale_factor = 100;
|
|
|
|
|
options.Get("scaleFactor", &scale_factor);
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetIntKey(printing::kSettingScaleFactor, scale_factor);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
|
|
|
|
|
int pages_per_sheet = 1;
|
|
|
|
|
options.Get("pagesPerSheet", &pages_per_sheet);
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetIntKey(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);
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetBoolKey(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);
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetIntKey(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())) {
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetBoolKey(printing::kSettingHeaderFooterEnabled, true);
|
2019-08-09 20:16:25 +00:00
|
|
|
|
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetStringKey(printing::kSettingHeaderFooterTitle, header);
|
|
|
|
|
settings.SetStringKey(printing::kSettingHeaderFooterURL, footer);
|
2019-08-24 01:14:23 +00:00
|
|
|
|
} else {
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetBoolKey(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.
|
2020-04-15 00:14:38 +00:00
|
|
|
|
settings.SetIntKey(printing::kSettingPrinterType,
|
|
|
|
|
static_cast<int>(printing::PrinterType::kLocal));
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetBoolKey(printing::kSettingShouldPrintSelectionOnly, false);
|
|
|
|
|
settings.SetBoolKey(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)) {
|
2019-11-08 18:01:50 +00:00
|
|
|
|
base::Value page_range_list(base::Value::Type::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)) {
|
2019-11-08 18:01:50 +00:00
|
|
|
|
base::Value range(base::Value::Type::DICTIONARY);
|
|
|
|
|
range.SetIntKey(printing::kSettingPageRangeFrom, from);
|
|
|
|
|
range.SetIntKey(printing::kSettingPageRangeTo, to);
|
|
|
|
|
page_range_list.Append(std::move(range));
|
2019-06-30 05:12:00 +00:00
|
|
|
|
} else {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-08 18:01:50 +00:00
|
|
|
|
if (page_range_list.GetList().size() > 0)
|
|
|
|
|
settings.SetPath(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.
|
2019-06-30 05:12:00 +00:00
|
|
|
|
printing::DuplexMode duplex_mode;
|
|
|
|
|
options.Get("duplexMode", &duplex_mode);
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetIntKey(printing::kSettingDuplexMode, 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.
|
|
|
|
|
base::Value media_size(base::Value::Type::DICTIONARY);
|
|
|
|
|
if (options.Get("mediaSize", &media_size))
|
|
|
|
|
settings.SetKey(printing::kSettingMediaSize, std::move(media_size));
|
|
|
|
|
|
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
|
|
|
|
int dpi = 72;
|
|
|
|
|
if (options.Get("dpi", &dpi_settings)) {
|
|
|
|
|
int horizontal = 72;
|
|
|
|
|
dpi_settings.Get("horizontal", &horizontal);
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetIntKey(printing::kSettingDpiHorizontal, horizontal);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
int vertical = 72;
|
|
|
|
|
dpi_settings.Get("vertical", &vertical);
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetIntKey(printing::kSettingDpiVertical, vertical);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
} else {
|
2019-11-08 18:01:50 +00:00
|
|
|
|
settings.SetIntKey(printing::kSettingDpiHorizontal, dpi);
|
|
|
|
|
settings.SetIntKey(printing::kSettingDpiVertical, dpi);
|
2019-06-30 05:12:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-09 16:13:59 +00:00
|
|
|
|
base::ThreadPool::PostTaskAndReplyWithResult(
|
|
|
|
|
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
|
2020-01-31 19:20:11 +00:00
|
|
|
|
base::BindOnce(&GetDefaultPrinterAsync),
|
|
|
|
|
base::BindOnce(&WebContents::OnGetDefaultPrinter,
|
|
|
|
|
weak_factory_.GetWeakPtr(), std::move(settings),
|
|
|
|
|
std::move(callback), device_name, silent));
|
2017-02-06 09:18:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-18 17:26:22 +00:00
|
|
|
|
std::vector<printing::PrinterBasicInfo> WebContents::GetPrinterList() {
|
2017-05-09 02:38:03 +00:00
|
|
|
|
std::vector<printing::PrinterBasicInfo> printers;
|
2019-12-11 00:22:35 +00:00
|
|
|
|
auto print_backend = printing::PrintBackend::CreateInstance(
|
|
|
|
|
nullptr, g_browser_process->GetApplicationLocale());
|
2018-11-09 03:42:34 +00:00
|
|
|
|
{
|
|
|
|
|
// TODO(deepak1556): Deprecate this api in favor of an
|
|
|
|
|
// async version and post a non blocing task call.
|
|
|
|
|
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
|
|
|
|
print_backend->EnumeratePrinters(&printers);
|
|
|
|
|
}
|
2017-05-09 02:38:03 +00:00
|
|
|
|
return printers;
|
2015-06-13 13:23:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-30 05:30:59 +00:00
|
|
|
|
v8::Local<v8::Promise> WebContents::PrintToPDF(base::DictionaryValue settings) {
|
2019-11-01 06:10:32 +00:00
|
|
|
|
gin_helper::Promise<v8::Local<v8::Value>> promise(isolate());
|
2019-02-21 12:32:44 +00:00
|
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
2018-11-09 03:42:34 +00:00
|
|
|
|
PrintPreviewMessageHandler::FromWebContents(web_contents())
|
2019-10-30 05:30:59 +00:00
|
|
|
|
->PrintToPDF(std::move(settings), std::move(promise));
|
2019-02-21 12:32:44 +00:00
|
|
|
|
return handle;
|
2015-06-09 05:07:40 +00:00
|
|
|
|
}
|
2018-11-09 03:42:34 +00:00
|
|
|
|
#endif
|
2015-06-09 05:07:40 +00:00
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
void WebContents::AddWorkSpace(gin_helper::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()) {
|
2015-09-07 08:12:31 +00:00
|
|
|
|
args->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
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
void WebContents::RemoveWorkSpace(gin_helper::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()) {
|
2015-09-07 08:12:31 +00:00
|
|
|
|
args->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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::Replace(const base::string16& word) {
|
|
|
|
|
web_contents()->Replace(word);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::ReplaceMisspelling(const base::string16& word) {
|
|
|
|
|
web_contents()->ReplaceMisspelling(word);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
uint32_t WebContents::FindInPage(gin_helper::Arguments* args) {
|
2015-12-17 17:27:56 +00:00
|
|
|
|
base::string16 search_text;
|
2015-12-17 23:10:42 +00:00
|
|
|
|
if (!args->GetNext(&search_text) || search_text.empty()) {
|
2015-12-17 17:27:56 +00:00
|
|
|
|
args->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
|
|
|
|
}
|
|
|
|
|
|
2019-01-12 01:00:43 +00:00
|
|
|
|
uint32_t request_id = GetNextRequestId();
|
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);
|
|
|
|
|
dict.Get("findNext", &options->find_next);
|
|
|
|
|
}
|
2015-12-17 17:27:56 +00:00
|
|
|
|
|
2019-01-12 01:00:43 +00:00
|
|
|
|
web_contents()->Find(request_id, search_text, std::move(options));
|
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() {
|
2016-06-07 20:20:06 +00:00
|
|
|
|
#if defined(OS_MACOSX)
|
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) {
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* const host = web_contents()->GetMainFrame();
|
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.
|
|
|
|
|
#if defined(OS_MACOSX) || defined(OS_LINUX)
|
|
|
|
|
if (owner_window())
|
|
|
|
|
owner_window()->Focus(true);
|
|
|
|
|
#endif
|
2015-07-24 04:58:28 +00:00
|
|
|
|
web_contents()->Focus();
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-03 03:29:55 +00:00
|
|
|
|
#if !defined(OS_MACOSX)
|
|
|
|
|
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
|
|
|
|
|
2019-05-03 18:11:41 +00:00
|
|
|
|
if (GetType() != Type::BACKGROUND_PAGE) {
|
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-07-24 04:58:28 +00:00
|
|
|
|
void WebContents::TabTraverse(bool reverse) {
|
|
|
|
|
web_contents()->FocusThroughTabTraversal(reverse);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-06 11:48:00 +00:00
|
|
|
|
bool WebContents::SendIPCMessage(bool internal,
|
|
|
|
|
bool send_to_all,
|
2018-08-24 15:30:37 +00:00
|
|
|
|
const std::string& channel,
|
2019-10-09 17:59:08 +00:00
|
|
|
|
v8::Local<v8::Value> args) {
|
|
|
|
|
blink::CloneableMessage message;
|
2019-10-25 13:03:28 +00:00
|
|
|
|
if (!gin::ConvertFromV8(isolate(), args, &message)) {
|
2019-10-09 17:59:08 +00:00
|
|
|
|
isolate()->ThrowException(v8::Exception::Error(
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin::StringToV8(isolate(), "Failed to serialize arguments")));
|
2019-10-09 17:59:08 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return SendIPCMessageWithSender(internal, send_to_all, channel,
|
|
|
|
|
std::move(message));
|
2018-09-01 01:13:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-06 11:48:00 +00:00
|
|
|
|
bool WebContents::SendIPCMessageWithSender(bool internal,
|
|
|
|
|
bool send_to_all,
|
2018-09-01 01:13:51 +00:00
|
|
|
|
const std::string& channel,
|
2019-10-09 17:59:08 +00:00
|
|
|
|
blink::CloneableMessage args,
|
2018-09-01 01:13:51 +00:00
|
|
|
|
int32_t sender_id) {
|
2019-03-31 00:36:13 +00:00
|
|
|
|
std::vector<content::RenderFrameHost*> target_hosts;
|
|
|
|
|
if (!send_to_all) {
|
|
|
|
|
auto* frame_host = web_contents()->GetMainFrame();
|
|
|
|
|
if (frame_host) {
|
|
|
|
|
target_hosts.push_back(frame_host);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
target_hosts = web_contents()->GetAllFrames();
|
2018-03-09 09:31:09 +00:00
|
|
|
|
}
|
2019-03-31 00:36:13 +00:00
|
|
|
|
|
|
|
|
|
for (auto* frame_host : target_hosts) {
|
2019-10-28 22:12:35 +00:00
|
|
|
|
mojo::AssociatedRemote<mojom::ElectronRenderer> electron_renderer;
|
2019-04-02 22:38:16 +00:00
|
|
|
|
frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
|
2019-10-28 22:12:35 +00:00
|
|
|
|
&electron_renderer);
|
2019-12-06 20:35:57 +00:00
|
|
|
|
electron_renderer->Message(internal, false, channel, args.ShallowClone(),
|
2019-10-28 22:12:35 +00:00
|
|
|
|
sender_id);
|
2019-03-31 00:36:13 +00:00
|
|
|
|
}
|
2019-04-02 22:38:16 +00:00
|
|
|
|
return true;
|
2014-04-25 05:10:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-10 00:37:42 +00:00
|
|
|
|
bool WebContents::SendIPCMessageToFrame(bool internal,
|
|
|
|
|
bool send_to_all,
|
|
|
|
|
int32_t frame_id,
|
|
|
|
|
const std::string& channel,
|
2019-10-09 17:59:08 +00:00
|
|
|
|
v8::Local<v8::Value> args) {
|
|
|
|
|
blink::CloneableMessage message;
|
2019-10-25 13:03:28 +00:00
|
|
|
|
if (!gin::ConvertFromV8(isolate(), args, &message)) {
|
2019-10-09 17:59:08 +00:00
|
|
|
|
isolate()->ThrowException(v8::Exception::Error(
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin::StringToV8(isolate(), "Failed to serialize arguments")));
|
2019-10-09 17:59:08 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-12-10 00:37:42 +00:00
|
|
|
|
auto frames = web_contents()->GetAllFrames();
|
|
|
|
|
auto iter = std::find_if(frames.begin(), frames.end(), [frame_id](auto* f) {
|
|
|
|
|
return f->GetRoutingID() == frame_id;
|
|
|
|
|
});
|
|
|
|
|
if (iter == frames.end())
|
|
|
|
|
return false;
|
|
|
|
|
if (!(*iter)->IsRenderFrameLive())
|
|
|
|
|
return false;
|
2019-04-02 22:38:16 +00:00
|
|
|
|
|
2019-10-28 22:12:35 +00:00
|
|
|
|
mojo::AssociatedRemote<mojom::ElectronRenderer> electron_renderer;
|
|
|
|
|
(*iter)->GetRemoteAssociatedInterfaces()->GetInterface(&electron_renderer);
|
|
|
|
|
electron_renderer->Message(internal, send_to_all, channel, std::move(message),
|
|
|
|
|
0 /* sender_id */);
|
2019-04-02 22:38:16 +00:00
|
|
|
|
return true;
|
2018-12-10 00:37:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
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()) {
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_OSR)
|
2018-05-15 01:59:22 +00:00
|
|
|
|
GetOffScreenRenderWidgetHostView()->SendMouseEvent(mouse_event);
|
|
|
|
|
#endif
|
|
|
|
|
} 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)) {
|
2017-04-13 10:21:30 +00:00
|
|
|
|
content::NativeWebKeyboardEvent keyboard_event(
|
2017-06-16 20:42:33 +00:00
|
|
|
|
blink::WebKeyboardEvent::kRawKeyDown,
|
2018-04-18 01:55:30 +00:00
|
|
|
|
blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
|
2019-10-25 13:03:28 +00:00
|
|
|
|
if (gin::ConvertFromV8(isolate, input_event, &keyboard_event)) {
|
2018-04-12 12:54:04 +00:00
|
|
|
|
rwh->ForwardKeyboardEvent(keyboard_event);
|
2015-09-18 06:20:31 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2017-06-16 20:42:33 +00:00
|
|
|
|
} else if (type == blink::WebInputEvent::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()) {
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_OSR)
|
2018-05-15 01:59:22 +00:00
|
|
|
|
GetOffScreenRenderWidgetHostView()->SendMouseWheelEvent(
|
|
|
|
|
mouse_wheel_event);
|
|
|
|
|
#endif
|
|
|
|
|
} 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
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
void WebContents::BeginFrameSubscription(gin_helper::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
|
|
|
|
|
2018-05-14 17:09:05 +00:00
|
|
|
|
args->GetNext(&only_dirty);
|
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,
|
|
|
|
|
gin_helper::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);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin::Handle<NativeImage> icon;
|
2020-05-11 01:24:45 +00:00
|
|
|
|
if (!item.Get("icon", &icon) || icon->image().IsEmpty()) {
|
2017-01-26 18:34:27 +00:00
|
|
|
|
args->ThrowError("Must specify non-empty 'icon' option");
|
2016-07-03 04:58:31 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start dragging.
|
|
|
|
|
if (!files.empty()) {
|
2019-01-09 20:10:26 +00:00
|
|
|
|
base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
|
2016-07-03 04:58:31 +00:00
|
|
|
|
DragFileItems(files, icon->image(), web_contents()->GetNativeView());
|
|
|
|
|
} else {
|
2017-01-26 18:34:27 +00:00
|
|
|
|
args->ThrowError("Must specify either 'file' or 'files' option");
|
2016-07-03 04:58:31 +00:00
|
|
|
|
}
|
2016-07-03 03:26:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
|
v8::Local<v8::Promise> WebContents::CapturePage(gin_helper::Arguments* args) {
|
2016-07-05 22:43:57 +00:00
|
|
|
|
gfx::Rect rect;
|
2019-11-01 06:10:32 +00:00
|
|
|
|
gin_helper::Promise<gfx::Image> promise(isolate());
|
2019-02-21 12:32:44 +00:00
|
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
2016-07-05 22:43:57 +00:00
|
|
|
|
|
2018-11-28 04:50:53 +00:00
|
|
|
|
// get rect arguments if they exist
|
|
|
|
|
args->GetNext(&rect);
|
2016-07-05 22:43:57 +00:00
|
|
|
|
|
2018-04-17 22:41:47 +00:00
|
|
|
|
auto* const view = web_contents()->GetRenderWidgetHostView();
|
2017-04-13 10:21:30 +00:00
|
|
|
|
if (!view) {
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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,
|
2019-02-21 12:32:44 +00:00
|
|
|
|
base::BindOnce(&OnCapturePageDone, std::move(promise)));
|
|
|
|
|
return handle;
|
2016-07-05 22:43:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-25 00:43:42 +00:00
|
|
|
|
void WebContents::IncrementCapturerCount(gin_helper::Arguments* args) {
|
|
|
|
|
gfx::Size size;
|
|
|
|
|
bool stay_hidden = false;
|
|
|
|
|
|
|
|
|
|
// get size arguments if they exist
|
|
|
|
|
args->GetNext(&size);
|
|
|
|
|
// get stayHidden arguments if they exist
|
|
|
|
|
args->GetNext(&stay_hidden);
|
|
|
|
|
|
|
|
|
|
web_contents()->IncrementCapturerCount(size, stay_hidden);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebContents::DecrementCapturerCount(gin_helper::Arguments* args) {
|
|
|
|
|
bool stay_hidden = false;
|
|
|
|
|
|
|
|
|
|
// get stayHidden arguments if they exist
|
|
|
|
|
args->GetNext(&stay_hidden);
|
|
|
|
|
|
|
|
|
|
web_contents()->DecrementCapturerCount(stay_hidden);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WebContents::IsBeingCaptured() {
|
|
|
|
|
return web_contents()->IsBeingCaptured();
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-14 20:54:14 +00:00
|
|
|
|
void WebContents::OnCursorChange(const content::WebCursor& webcursor) {
|
|
|
|
|
const ui::Cursor& cursor = webcursor.cursor();
|
2016-01-31 16:00:14 +00:00
|
|
|
|
|
2020-03-14 20:54:14 +00:00
|
|
|
|
if (cursor.type() == ui::mojom::CursorType::kCustom) {
|
|
|
|
|
Emit("cursor-changed", CursorTypeToString(cursor),
|
|
|
|
|
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 {
|
2020-03-14 20:54:14 +00:00
|
|
|
|
Emit("cursor-changed", CursorTypeToString(cursor));
|
2016-01-31 16:00:14 +00:00
|
|
|
|
}
|
2016-01-30 05:33:55 +00:00
|
|
|
|
}
|
2016-07-18 06:54:52 +00:00
|
|
|
|
|
2015-06-05 07:18:15 +00:00
|
|
|
|
bool WebContents::IsGuest() const {
|
2019-05-03 18:11:41 +00:00
|
|
|
|
return type_ == Type::WEB_VIEW;
|
2015-06-05 07:18:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-16 22:57:40 +00:00
|
|
|
|
void WebContents::AttachToIframe(content::WebContents* embedder_web_contents,
|
|
|
|
|
int embedder_frame_id) {
|
|
|
|
|
if (guest_delegate_)
|
|
|
|
|
guest_delegate_->AttachToIframe(embedder_web_contents, embedder_frame_id);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 10:10:56 +00:00
|
|
|
|
bool WebContents::IsOffScreen() const {
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_OSR)
|
2019-05-03 18:11:41 +00:00
|
|
|
|
return type_ == Type::OFF_SCREEN;
|
2017-06-26 09:13:05 +00:00
|
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
2016-07-28 10:10:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_OSR)
|
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
|
|
|
|
}
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#endif
|
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-10-01 20:00:53 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_OSR)
|
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-06-26 09:13:05 +00:00
|
|
|
|
#endif
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-18 19:57:34 +00:00
|
|
|
|
auto level = blink::PageZoomFactorToZoomLevel(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();
|
2019-10-18 19:57:34 +00:00
|
|
|
|
return blink::PageZoomLevelToZoomFactor(level);
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-04 01:18:23 +00:00
|
|
|
|
void WebContents::DoGetZoomLevel(DoGetZoomLevelCallback callback) {
|
|
|
|
|
std::move(callback).Run(GetZoomLevel());
|
2016-09-01 17:25:12 +00:00
|
|
|
|
}
|
2016-08-03 03:29:55 +00:00
|
|
|
|
|
2019-07-03 15:05:45 +00:00
|
|
|
|
std::vector<base::FilePath::StringType> WebContents::GetPreloadPaths() const {
|
|
|
|
|
auto result = SessionPreferences::GetValidPreloads(GetBrowserContext());
|
|
|
|
|
|
2018-08-10 22:19:49 +00:00
|
|
|
|
if (auto* web_preferences = WebContentsPreferences::From(web_contents())) {
|
|
|
|
|
base::FilePath::StringType preload;
|
|
|
|
|
if (web_preferences->GetPreloadPath(&preload)) {
|
2019-07-03 15:05:45 +00:00
|
|
|
|
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::GetWebPreferences(
|
|
|
|
|
v8::Isolate* isolate) const {
|
2018-03-08 07:12:45 +00:00
|
|
|
|
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
2018-03-14 02:19:22 +00:00
|
|
|
|
if (!web_preferences)
|
|
|
|
|
return v8::Null(isolate);
|
2019-10-25 13:03:28 +00:00
|
|
|
|
return gin::ConvertToV8(isolate, *web_preferences->preference());
|
2015-09-22 13:56:56 +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
|
|
|
|
}
|
|
|
|
|
|
2018-08-09 17:15:23 +00:00
|
|
|
|
v8::Local<v8::Value> WebContents::GetOwnerBrowserWindow() const {
|
2015-10-01 05:45:59 +00:00
|
|
|
|
if (owner_window())
|
2018-02-22 03:49:17 +00:00
|
|
|
|
return BrowserWindow::From(isolate(), owner_window());
|
2015-10-01 05:45:59 +00:00
|
|
|
|
else
|
|
|
|
|
return v8::Null(isolate());
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-17 12:56:47 +00:00
|
|
|
|
int32_t WebContents::ID() const {
|
|
|
|
|
return weak_map_id();
|
|
|
|
|
}
|
|
|
|
|
|
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) {
|
|
|
|
|
if (managed_web_contents())
|
|
|
|
|
managed_web_contents()->SetDevToolsWebContents(devtools->web_contents());
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-21 10:50:12 +00:00
|
|
|
|
v8::Local<v8::Value> WebContents::GetNativeView() const {
|
|
|
|
|
gfx::NativeView ptr = web_contents()->GetNativeView();
|
2018-04-18 01:55:30 +00:00
|
|
|
|
auto buffer = node::Buffer::Copy(isolate(), reinterpret_cast<char*>(&ptr),
|
|
|
|
|
sizeof(gfx::NativeView));
|
2017-08-21 10:50:12 +00:00
|
|
|
|
if (buffer.IsEmpty())
|
|
|
|
|
return v8::Null(isolate());
|
|
|
|
|
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()) {
|
2019-06-19 21:23:04 +00:00
|
|
|
|
auto handle = electron::api::Debugger::Create(isolate, web_contents());
|
2016-01-21 18:22:23 +00:00
|
|
|
|
debugger_.Reset(isolate, handle.ToV8());
|
|
|
|
|
}
|
|
|
|
|
return v8::Local<v8::Value>::New(isolate, debugger_);
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-30 22:47:41 +00:00
|
|
|
|
void WebContents::GrantOriginAccess(const GURL& url) {
|
2018-10-02 19:01:04 +00:00
|
|
|
|
content::ChildProcessSecurityPolicy::GetInstance()->GrantCommitOrigin(
|
2018-04-12 07:37:54 +00:00
|
|
|
|
web_contents()->GetMainFrame()->GetProcess()->GetID(),
|
|
|
|
|
url::Origin::Create(url));
|
2017-06-30 22:47:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-29 17:11:11 +00:00
|
|
|
|
v8::Local<v8::Promise> WebContents::TakeHeapSnapshot(
|
|
|
|
|
const base::FilePath& file_path) {
|
2019-11-01 06:10:32 +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
|
|
|
|
|
2019-04-29 17:11:11 +00:00
|
|
|
|
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
2018-09-18 18:00:31 +00:00
|
|
|
|
base::File file(file_path,
|
|
|
|
|
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
|
2019-04-02 22:38:16 +00:00
|
|
|
|
if (!file.IsValid()) {
|
2019-04-29 17:11:11 +00:00
|
|
|
|
promise.RejectWithErrorMessage("takeHeapSnapshot failed");
|
|
|
|
|
return handle;
|
2019-04-02 22:38:16 +00:00
|
|
|
|
}
|
2018-09-18 18:00:31 +00:00
|
|
|
|
|
|
|
|
|
auto* frame_host = web_contents()->GetMainFrame();
|
2019-04-02 22:38:16 +00:00
|
|
|
|
if (!frame_host) {
|
2019-04-29 17:11:11 +00:00
|
|
|
|
promise.RejectWithErrorMessage("takeHeapSnapshot failed");
|
|
|
|
|
return handle;
|
2019-04-02 22:38:16 +00:00
|
|
|
|
}
|
2018-09-18 18:00:31 +00:00
|
|
|
|
|
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 =
|
|
|
|
|
std::make_unique<mojo::AssociatedRemote<mojom::ElectronRenderer>>();
|
2019-04-02 22:38:16 +00:00
|
|
|
|
frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
|
2019-10-28 22:12:35 +00:00
|
|
|
|
electron_renderer.get());
|
|
|
|
|
auto* raw_ptr = electron_renderer.get();
|
2019-04-02 22:38:16 +00:00
|
|
|
|
(*raw_ptr)->TakeHeapSnapshot(
|
|
|
|
|
mojo::WrapPlatformFile(file.TakePlatformFile()),
|
2019-04-29 17:11:11 +00:00
|
|
|
|
base::BindOnce(
|
2019-10-28 22:12:35 +00:00
|
|
|
|
[](mojo::AssociatedRemote<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 {
|
|
|
|
|
promise.RejectWithErrorMessage("takeHeapSnapshot failed");
|
|
|
|
|
}
|
|
|
|
|
},
|
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
|
|
|
|
}
|
|
|
|
|
|
2015-12-03 08:04:46 +00:00
|
|
|
|
// static
|
|
|
|
|
void WebContents::BuildPrototype(v8::Isolate* isolate,
|
2016-08-02 09:08:12 +00:00
|
|
|
|
v8::Local<v8::FunctionTemplate> prototype) {
|
2019-10-25 13:03:28 +00:00
|
|
|
|
prototype->SetClassName(gin::StringToV8(isolate, "WebContents"));
|
2019-09-04 02:14:16 +00:00
|
|
|
|
gin_helper::Destroyable::MakeDestroyable(isolate, prototype);
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
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)
|
2019-06-20 10:10:56 +00:00
|
|
|
|
.SetMethod("_getOSProcessIdForFrame",
|
|
|
|
|
&WebContents::GetOSProcessIdForFrame)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("equal", &WebContents::Equal)
|
|
|
|
|
.SetMethod("_loadURL", &WebContents::LoadURL)
|
2015-12-03 18:31:51 +00:00
|
|
|
|
.SetMethod("downloadURL", &WebContents::DownloadURL)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("_getURL", &WebContents::GetURL)
|
|
|
|
|
.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)
|
|
|
|
|
.SetMethod("_stop", &WebContents::Stop)
|
|
|
|
|
.SetMethod("_goBack", &WebContents::GoBack)
|
|
|
|
|
.SetMethod("_goForward", &WebContents::GoForward)
|
|
|
|
|
.SetMethod("_goToOffset", &WebContents::GoToOffset)
|
|
|
|
|
.SetMethod("isCrashed", &WebContents::IsCrashed)
|
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)
|
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)
|
|
|
|
|
.SetMethod("paste", &WebContents::Paste)
|
|
|
|
|
.SetMethod("pasteAndMatchStyle", &WebContents::PasteAndMatchStyle)
|
|
|
|
|
.SetMethod("delete", &WebContents::Delete)
|
|
|
|
|
.SetMethod("selectAll", &WebContents::SelectAll)
|
|
|
|
|
.SetMethod("unselect", &WebContents::Unselect)
|
|
|
|
|
.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("tabTraverse", &WebContents::TabTraverse)
|
|
|
|
|
.SetMethod("_send", &WebContents::SendIPCMessage)
|
2020-03-12 01:07:54 +00:00
|
|
|
|
.SetMethod("_postMessage", &WebContents::PostMessage)
|
2018-12-10 00:37:42 +00:00
|
|
|
|
.SetMethod("_sendToFrame", &WebContents::SendIPCMessageToFrame)
|
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)
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#if BUILDFLAG(ENABLE_OSR)
|
2016-08-03 03:29:55 +00:00
|
|
|
|
.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)
|
2018-10-01 20:00:53 +00:00
|
|
|
|
#endif
|
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)
|
2016-06-08 18:41:14 +00:00
|
|
|
|
.SetMethod("getType", &WebContents::GetType)
|
2019-07-03 15:05:45 +00:00
|
|
|
|
.SetMethod("_getPreloadPaths", &WebContents::GetPreloadPaths)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
|
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)
|
|
|
|
|
.SetMethod("_getPrinters", &WebContents::GetPrinterList)
|
2015-12-03 08:04:46 +00:00
|
|
|
|
.SetMethod("_printToPDF", &WebContents::PrintToPDF)
|
2018-11-09 03:42:34 +00:00
|
|
|
|
#endif
|
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("incrementCapturerCount", &WebContents::IncrementCapturerCount)
|
|
|
|
|
.SetMethod("decrementCapturerCount", &WebContents::DecrementCapturerCount)
|
|
|
|
|
.SetMethod("isBeingCaptured", &WebContents::IsBeingCaptured)
|
2017-03-08 14:55:59 +00:00
|
|
|
|
.SetMethod("setWebRTCIPHandlingPolicy",
|
|
|
|
|
&WebContents::SetWebRTCIPHandlingPolicy)
|
|
|
|
|
.SetMethod("getWebRTCIPHandlingPolicy",
|
|
|
|
|
&WebContents::GetWebRTCIPHandlingPolicy)
|
2017-06-30 22:47:41 +00:00
|
|
|
|
.SetMethod("_grantOriginAccess", &WebContents::GrantOriginAccess)
|
2019-04-29 17:11:11 +00:00
|
|
|
|
.SetMethod("takeHeapSnapshot", &WebContents::TakeHeapSnapshot)
|
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)
|
|
|
|
|
.SetProperty("debugger", &WebContents::Debugger);
|
2015-07-06 10:21:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-04 20:19:40 +00:00
|
|
|
|
ElectronBrowserContext* WebContents::GetBrowserContext() const {
|
|
|
|
|
return static_cast<ElectronBrowserContext*>(
|
|
|
|
|
web_contents()->GetBrowserContext());
|
2015-07-14 19:13:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-04-24 08:45:25 +00:00
|
|
|
|
// static
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin::Handle<WebContents> WebContents::Create(
|
|
|
|
|
v8::Isolate* isolate,
|
|
|
|
|
const gin_helper::Dictionary& options) {
|
|
|
|
|
return gin::CreateHandle(isolate, new WebContents(isolate, options));
|
2016-08-17 00:15:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
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) {
|
2019-10-25 13:03:28 +00:00
|
|
|
|
return gin::CreateHandle(
|
2018-10-22 18:02:25 +00:00
|
|
|
|
isolate, new WebContents(isolate, std::move(web_contents), type));
|
2014-04-24 08:45:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-10-23 06:04:13 +00:00
|
|
|
|
// static
|
2019-10-25 13:03:28 +00:00
|
|
|
|
gin::Handle<WebContents> WebContents::From(v8::Isolate* isolate,
|
|
|
|
|
content::WebContents* web_contents) {
|
2018-10-19 08:52:07 +00:00
|
|
|
|
auto* existing = TrackableObject::FromWrappedClass(isolate, web_contents);
|
|
|
|
|
if (existing)
|
2019-10-25 13:03:28 +00:00
|
|
|
|
return gin::CreateHandle(isolate, static_cast<WebContents*>(existing));
|
2018-10-19 08:52:07 +00:00
|
|
|
|
else
|
2019-10-25 13:03:28 +00:00
|
|
|
|
return gin::Handle<WebContents>();
|
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) {
|
|
|
|
|
auto existing = From(isolate, web_contents);
|
|
|
|
|
if (!existing.IsEmpty())
|
|
|
|
|
return existing;
|
|
|
|
|
else
|
2019-10-25 13:03:28 +00:00
|
|
|
|
return gin::CreateHandle(isolate, new WebContents(isolate, web_contents));
|
2014-10-23 06:04:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-04-24 08:45:25 +00:00
|
|
|
|
} // namespace api
|
|
|
|
|
|
2019-06-19 21:23:04 +00:00
|
|
|
|
} // namespace electron
|
2014-10-23 06:04:13 +00:00
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
2019-06-19 21:23:04 +00:00
|
|
|
|
using electron::api::WebContents;
|
2016-08-02 11:38:35 +00:00
|
|
|
|
|
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);
|
2019-01-09 19:17:05 +00:00
|
|
|
|
dict.Set("WebContents", WebContents::GetConstructor(isolate)
|
|
|
|
|
->GetFunction(context)
|
|
|
|
|
.ToLocalChecked());
|
2016-08-02 11:38:35 +00:00
|
|
|
|
dict.SetMethod("create", &WebContents::Create);
|
2019-10-21 07:05:40 +00:00
|
|
|
|
dict.SetMethod("fromId", &WebContents::FromWeakMapID);
|
|
|
|
|
dict.SetMethod("getAllWebContents", &WebContents::GetAll);
|
2014-10-23 06:04:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
2020-02-14 11:25:39 +00:00
|
|
|
|
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_browser_web_contents, Initialize)
|