refactor: merge CommonWebContentsDelegate into api::WebContents (#26189)

This commit is contained in:
Jeremy Rose 2020-11-10 09:06:56 -08:00 committed by GitHub
parent 0b85fdf26c
commit ff33fa1970
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 872 additions and 1030 deletions

View file

@ -127,7 +127,6 @@ filenames = {
"shell/browser/api/electron_api_web_contents_mac.mm", "shell/browser/api/electron_api_web_contents_mac.mm",
"shell/browser/auto_updater_mac.mm", "shell/browser/auto_updater_mac.mm",
"shell/browser/browser_mac.mm", "shell/browser/browser_mac.mm",
"shell/browser/common_web_contents_delegate_mac.mm",
"shell/browser/electron_browser_main_parts_mac.mm", "shell/browser/electron_browser_main_parts_mac.mm",
"shell/browser/mac/dict_util.h", "shell/browser/mac/dict_util.h",
"shell/browser/mac/dict_util.mm", "shell/browser/mac/dict_util.mm",
@ -203,7 +202,6 @@ filenames = {
"shell/browser/api/electron_api_browser_window_views.cc", "shell/browser/api/electron_api_browser_window_views.cc",
"shell/browser/api/electron_api_menu_views.cc", "shell/browser/api/electron_api_menu_views.cc",
"shell/browser/api/electron_api_menu_views.h", "shell/browser/api/electron_api_menu_views.h",
"shell/browser/common_web_contents_delegate_views.cc",
"shell/browser/native_browser_view_views.cc", "shell/browser/native_browser_view_views.cc",
"shell/browser/native_browser_view_views.h", "shell/browser/native_browser_view_views.h",
"shell/browser/native_window_views.cc", "shell/browser/native_window_views.cc",
@ -336,8 +334,6 @@ filenames = {
"shell/browser/browser_process_impl.h", "shell/browser/browser_process_impl.h",
"shell/browser/child_web_contents_tracker.cc", "shell/browser/child_web_contents_tracker.cc",
"shell/browser/child_web_contents_tracker.h", "shell/browser/child_web_contents_tracker.h",
"shell/browser/common_web_contents_delegate.cc",
"shell/browser/common_web_contents_delegate.h",
"shell/browser/cookie_change_notifier.cc", "shell/browser/cookie_change_notifier.cc",
"shell/browser/cookie_change_notifier.h", "shell/browser/cookie_change_notifier.h",
"shell/browser/electron_autofill_driver.cc", "shell/browser/electron_autofill_driver.cc",

View file

@ -5,7 +5,7 @@ Subject: content_browser_main_loop.patch
Pass idle quit closure for main message loop, so that pending tasks are Pass idle quit closure for main message loop, so that pending tasks are
run before shutdown. This is required to cleanup WebContents asynchronously run before shutdown. This is required to cleanup WebContents asynchronously
in atom::CommonWebContentsDelegate::ResetManageWebContents. in electron::api::WebContents::ResetManagedWebContents.
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index d35d26b1f572f084d5ffd25d191c62fdf5064ed4..c274bd867d5ca66f49d72eeffee5702825b4c067 100644 index d35d26b1f572f084d5ffd25d191c62fdf5064ed4..c274bd867d5ca66f49d72eeffee5702825b4c067 100644

View file

@ -13,25 +13,38 @@
#include <vector> #include <vector>
#include "base/containers/id_map.h" #include "base/containers/id_map.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/task/current_thread.h" #include "base/task/current_thread.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/hang_monitor/hang_crash_dump.h" #include "chrome/browser/hang_monitor/hang_crash_dump.h"
#include "chrome/browser/ssl/security_state_tab_helper.h" #include "chrome/browser/ssl/security_state_tab_helper.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/security_state/content/content_utils.h"
#include "components/security_state/core/security_state.h"
#include "content/browser/renderer_host/frame_tree_node.h" // nogncheck #include "content/browser/renderer_host/frame_tree_node.h" // nogncheck
#include "content/browser/renderer_host/render_frame_host_manager.h" // nogncheck #include "content/browser/renderer_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_impl.h" // nogncheck
#include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck #include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck
#include "content/common/widget_messages.h" #include "content/common/widget_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/context_menu_params.h" #include "content/public/browser/context_menu_params.h"
#include "content/public/browser/download_request_utils.h" #include "content/public/browser/download_request_utils.h"
#include "content/public/browser/favicon_status.h" #include "content/public/browser/favicon_status.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_entry.h"
@ -42,6 +55,8 @@
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/security_style_explanation.h"
#include "content/public/browser/security_style_explanations.h"
#include "content/public/browser/service_worker_context.h" #include "content/public/browser/service_worker_context.h"
#include "content/public/browser/site_instance.h" #include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
@ -59,6 +74,7 @@
#include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/platform_handle.h" #include "mojo/public/cpp/system/platform_handle.h"
#include "ppapi/buildflags/buildflags.h" #include "ppapi/buildflags/buildflags.h"
#include "printing/buildflags/buildflags.h"
#include "shell/browser/api/electron_api_browser_window.h" #include "shell/browser/api/electron_api_browser_window.h"
#include "shell/browser/api/electron_api_debugger.h" #include "shell/browser/api/electron_api_debugger.h"
#include "shell/browser/api/electron_api_session.h" #include "shell/browser/api/electron_api_session.h"
@ -76,14 +92,17 @@
#include "shell/browser/native_window.h" #include "shell/browser/native_window.h"
#include "shell/browser/session_preferences.h" #include "shell/browser/session_preferences.h"
#include "shell/browser/ui/drag_util.h" #include "shell/browser/ui/drag_util.h"
#include "shell/browser/ui/file_dialog.h"
#include "shell/browser/ui/inspectable_web_contents.h" #include "shell/browser/ui/inspectable_web_contents.h"
#include "shell/browser/ui/inspectable_web_contents_view.h" #include "shell/browser/ui/inspectable_web_contents_view.h"
#include "shell/browser/web_contents_permission_helper.h" #include "shell/browser/web_contents_permission_helper.h"
#include "shell/browser/web_contents_preferences.h" #include "shell/browser/web_contents_preferences.h"
#include "shell/browser/web_contents_zoom_controller.h" #include "shell/browser/web_contents_zoom_controller.h"
#include "shell/browser/web_dialog_helper.h"
#include "shell/browser/web_view_guest_delegate.h" #include "shell/browser/web_view_guest_delegate.h"
#include "shell/common/api/electron_api_native_image.h" #include "shell/common/api/electron_api_native_image.h"
#include "shell/common/color_util.h" #include "shell/common/color_util.h"
#include "shell/common/electron_constants.h"
#include "shell/common/gin_converters/blink_converter.h" #include "shell/common/gin_converters/blink_converter.h"
#include "shell/common/gin_converters/callback_converter.h" #include "shell/common/gin_converters/callback_converter.h"
#include "shell/common/gin_converters/content_converter.h" #include "shell/common/gin_converters/content_converter.h"
@ -101,6 +120,7 @@
#include "shell/common/node_includes.h" #include "shell/common/node_includes.h"
#include "shell/common/options_switches.h" #include "shell/common/options_switches.h"
#include "shell/common/v8_value_serializer.h" #include "shell/common/v8_value_serializer.h"
#include "storage/browser/file_system/isolated_context.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/input/web_input_event.h" #include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/messaging/transferable_message_mojom_traits.h" #include "third_party/blink/public/common/messaging/transferable_message_mojom_traits.h"
@ -140,7 +160,23 @@
#endif #endif
#if BUILDFLAG(ENABLE_PRINTING) #if BUILDFLAG(ENABLE_PRINTING)
#include "chrome/browser/printing/print_view_manager_basic.h"
#include "components/printing/browser/print_manager_utils.h"
#include "printing/mojom/print.mojom.h" #include "printing/mojom/print.mojom.h"
#include "shell/browser/printing/print_preview_message_handler.h"
#endif
#if BUILDFLAG(ENABLE_COLOR_CHOOSER)
#include "chrome/browser/ui/color_chooser.h"
#endif
#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
#endif
#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "components/pdf/browser/pdf_web_contents_helper.h" // nogncheck
#include "shell/browser/electron_pdf_web_contents_helper_client.h"
#endif #endif
namespace gin { namespace gin {
@ -421,6 +457,115 @@ struct UserDataLink : public base::SupportsUserData::Data {
}; };
const void* kElectronApiWebContentsKey = &kElectronApiWebContentsKey; const void* kElectronApiWebContentsKey = &kElectronApiWebContentsKey;
const char kRootName[] = "<root>";
struct FileSystem {
FileSystem() = default;
FileSystem(const std::string& type,
const std::string& file_system_name,
const std::string& root_url,
const std::string& file_system_path)
: type(type),
file_system_name(file_system_name),
root_url(root_url),
file_system_path(file_system_path) {}
std::string type;
std::string file_system_name;
std::string root_url;
std::string file_system_path;
};
std::string RegisterFileSystem(content::WebContents* web_contents,
const base::FilePath& path) {
auto* isolated_context = storage::IsolatedContext::GetInstance();
std::string root_name(kRootName);
storage::IsolatedContext::ScopedFSHandle file_system =
isolated_context->RegisterFileSystemForPath(
storage::kFileSystemTypeNativeLocal, std::string(), path, &root_name);
content::ChildProcessSecurityPolicy* policy =
content::ChildProcessSecurityPolicy::GetInstance();
content::RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
int renderer_id = render_view_host->GetProcess()->GetID();
policy->GrantReadFileSystem(renderer_id, file_system.id());
policy->GrantWriteFileSystem(renderer_id, file_system.id());
policy->GrantCreateFileForFileSystem(renderer_id, file_system.id());
policy->GrantDeleteFromFileSystem(renderer_id, file_system.id());
if (!policy->CanReadFile(renderer_id, path))
policy->GrantReadFile(renderer_id, path);
return file_system.id();
}
FileSystem CreateFileSystemStruct(content::WebContents* web_contents,
const std::string& file_system_id,
const std::string& file_system_path,
const std::string& type) {
const GURL origin = web_contents->GetURL().GetOrigin();
std::string file_system_name =
storage::GetIsolatedFileSystemName(origin, file_system_id);
std::string root_url = storage::GetIsolatedFileSystemRootURIString(
origin, file_system_id, kRootName);
return FileSystem(type, file_system_name, root_url, file_system_path);
}
std::unique_ptr<base::DictionaryValue> CreateFileSystemValue(
const FileSystem& file_system) {
std::unique_ptr<base::DictionaryValue> file_system_value(
new base::DictionaryValue());
file_system_value->SetString("type", file_system.type);
file_system_value->SetString("fileSystemName", file_system.file_system_name);
file_system_value->SetString("rootURL", file_system.root_url);
file_system_value->SetString("fileSystemPath", file_system.file_system_path);
return file_system_value;
}
void WriteToFile(const base::FilePath& path, const std::string& content) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::WILL_BLOCK);
DCHECK(!path.empty());
base::WriteFile(path, content.data(), content.size());
}
void AppendToFile(const base::FilePath& path, const std::string& content) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::WILL_BLOCK);
DCHECK(!path.empty());
base::AppendToFile(path, content.data(), content.size());
}
PrefService* GetPrefService(content::WebContents* web_contents) {
auto* context = web_contents->GetBrowserContext();
return static_cast<electron::ElectronBrowserContext*>(context)->prefs();
}
std::map<std::string, std::string> GetAddedFileSystemPaths(
content::WebContents* web_contents) {
auto* pref_service = GetPrefService(web_contents);
const base::DictionaryValue* file_system_paths_value =
pref_service->GetDictionary(prefs::kDevToolsFileSystemPaths);
std::map<std::string, std::string> result;
if (file_system_paths_value) {
base::DictionaryValue::Iterator it(*file_system_paths_value);
for (; !it.IsAtEnd(); it.Advance()) {
std::string type =
it.value().is_string() ? it.value().GetString() : std::string();
result[it.key()] = type;
}
}
return result;
}
bool IsDevToolsFileSystemAdded(content::WebContents* web_contents,
const std::string& file_system_path) {
auto file_system_paths = GetAddedFileSystemPaths(web_contents);
return file_system_paths.find(file_system_path) != file_system_paths.end();
}
} // namespace } // namespace
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS) #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
@ -449,6 +594,9 @@ WebContents::WebContents(v8::Isolate* isolate,
: content::WebContentsObserver(web_contents), : content::WebContentsObserver(web_contents),
type_(Type::kRemote), type_(Type::kRemote),
id_(GetAllWebContents().Add(this)), id_(GetAllWebContents().Add(this)),
devtools_file_system_indexer_(new DevToolsFileSystemIndexer),
file_task_runner_(
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
weak_factory_(this) { weak_factory_(this) {
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS) #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
// WebContents created by extension host will have valid ViewType set. // WebContents created by extension host will have valid ViewType set.
@ -484,6 +632,9 @@ WebContents::WebContents(v8::Isolate* isolate,
: content::WebContentsObserver(web_contents.get()), : content::WebContentsObserver(web_contents.get()),
type_(type), type_(type),
id_(GetAllWebContents().Add(this)), id_(GetAllWebContents().Add(this)),
devtools_file_system_indexer_(new DevToolsFileSystemIndexer),
file_task_runner_(
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
weak_factory_(this) { weak_factory_(this) {
DCHECK(type != Type::kRemote) DCHECK(type != Type::kRemote)
<< "Can't take ownership of a remote WebContents"; << "Can't take ownership of a remote WebContents";
@ -495,7 +646,11 @@ WebContents::WebContents(v8::Isolate* isolate,
WebContents::WebContents(v8::Isolate* isolate, WebContents::WebContents(v8::Isolate* isolate,
const gin_helper::Dictionary& options) const gin_helper::Dictionary& options)
: id_(GetAllWebContents().Add(this)), weak_factory_(this) { : id_(GetAllWebContents().Add(this)),
devtools_file_system_indexer_(new DevToolsFileSystemIndexer),
file_task_runner_(
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
weak_factory_(this) {
// Read options. // Read options.
options.Get("backgroundThrottling", &background_throttling_); options.Get("backgroundThrottling", &background_throttling_);
@ -700,6 +855,35 @@ void WebContents::InitWithExtensionView(v8::Isolate* isolate,
} }
#endif #endif
void WebContents::InitWithWebContents(content::WebContents* web_contents,
ElectronBrowserContext* browser_context,
bool is_guest) {
browser_context_ = browser_context;
web_contents->SetDelegate(this);
#if BUILDFLAG(ENABLE_PRINTING)
PrintPreviewMessageHandler::CreateForWebContents(web_contents);
printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
printing::CreateCompositeClientIfNeeded(web_contents,
browser_context->GetUserAgent());
#endif
#if BUILDFLAG(ENABLE_PDF_VIEWER)
pdf::PDFWebContentsHelper::CreateForWebContentsWithClient(
web_contents, std::make_unique<ElectronPDFWebContentsHelperClient>());
#endif
// Determine whether the WebContents is offscreen.
auto* web_preferences = WebContentsPreferences::From(web_contents);
offscreen_ =
web_preferences && web_preferences->IsEnabled(options::kOffscreen);
// Create InspectableWebContents.
web_contents_.reset(new InspectableWebContents(
web_contents, browser_context->prefs(), is_guest));
web_contents_->SetDelegate(this);
}
WebContents::~WebContents() { WebContents::~WebContents() {
MarkDestroyed(); MarkDestroyed();
// The destroy() is called. // The destroy() is called.
@ -872,7 +1056,31 @@ content::WebContents* WebContents::OpenURLFromTab(
if (!weak_this) if (!weak_this)
return nullptr; return nullptr;
return CommonWebContentsDelegate::OpenURLFromTab(source, params); content::NavigationController::LoadURLParams load_url_params(params.url);
load_url_params.referrer = params.referrer;
load_url_params.transition_type = params.transition;
load_url_params.extra_headers = params.extra_headers;
load_url_params.should_replace_current_entry =
params.should_replace_current_entry;
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.started_from_context_menu = params.started_from_context_menu;
load_url_params.initiator_origin = params.initiator_origin;
load_url_params.source_site_instance = params.source_site_instance;
load_url_params.frame_tree_node_id = params.frame_tree_node_id;
load_url_params.redirect_chain = params.redirect_chain;
load_url_params.has_user_gesture = params.user_gesture;
load_url_params.blob_url_loader_factory = params.blob_url_loader_factory;
load_url_params.href_translate = params.href_translate;
load_url_params.reload_type = params.reload_type;
if (params.post_data) {
load_url_params.load_type =
content::NavigationController::LOAD_TYPE_HTTP_POST;
load_url_params.post_data = params.post_data;
}
source->GetController().LoadURLWithParams(load_url_params);
return source;
} }
void WebContents::BeforeUnloadFired(content::WebContents* tab, void WebContents::BeforeUnloadFired(content::WebContents* tab,
@ -924,11 +1132,39 @@ bool WebContents::HandleKeyboardEvent(
// Send the unhandled keyboard events back to the embedder. // Send the unhandled keyboard events back to the embedder.
return embedder_->HandleKeyboardEvent(source, event); return embedder_->HandleKeyboardEvent(source, event);
} else { } else {
// Go to the default keyboard handling. return PlatformHandleKeyboardEvent(source, event);
return CommonWebContentsDelegate::HandleKeyboardEvent(source, event);
} }
} }
#if !defined(OS_MAC)
// NOTE: The macOS version of this function is found in
// electron_api_web_contents_mac.mm, as it requires calling into objective-C
// code.
bool WebContents::PlatformHandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) {
// Escape exits tabbed fullscreen mode.
if (event.windows_key_code == ui::VKEY_ESCAPE && is_html_fullscreen()) {
ExitFullscreenModeForTab(source);
return true;
}
// Check if the webContents has preferences and to ignore shortcuts
auto* web_preferences = WebContentsPreferences::From(source);
if (web_preferences &&
web_preferences->IsEnabled("ignoreMenuShortcuts", false))
return false;
// Let the NativeWindow handle other parts.
if (owner_window()) {
owner_window()->HandleKeyboardEvent(source, event);
return true;
}
return false;
}
#endif
content::KeyboardEventProcessingResult WebContents::PreHandleKeyboardEvent( content::KeyboardEventProcessingResult WebContents::PreHandleKeyboardEvent(
content::WebContents* source, content::WebContents* source,
const content::NativeWebKeyboardEvent& event) { const content::NativeWebKeyboardEvent& event) {
@ -965,13 +1201,36 @@ void WebContents::OnEnterFullscreenModeForTab(
bool allowed) { bool allowed) {
if (!allowed) if (!allowed)
return; return;
CommonWebContentsDelegate::EnterFullscreenModeForTab(requesting_frame, if (!owner_window_)
options); return;
auto* source = content::WebContents::FromRenderFrameHost(requesting_frame);
if (IsFullscreenForTabOrPending(source)) {
DCHECK_EQ(fullscreen_frame_, source->GetFocusedFrame());
return;
}
SetHtmlApiFullscreen(true);
owner_window_->NotifyWindowEnterHtmlFullScreen();
if (native_fullscreen_) {
// Explicitly trigger a view resize, as the size is not actually changing if
// the browser is fullscreened, too.
source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
}
Emit("enter-html-full-screen"); Emit("enter-html-full-screen");
} }
void WebContents::ExitFullscreenModeForTab(content::WebContents* source) { void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
CommonWebContentsDelegate::ExitFullscreenModeForTab(source); if (!owner_window_)
return;
SetHtmlApiFullscreen(false);
owner_window_->NotifyWindowLeaveHtmlFullScreen();
if (native_fullscreen_) {
// Explicitly trigger a view resize, as the size is not actually changing if
// the browser is fullscreened, too. Chrome does this indirectly from
// `chrome/browser/ui/exclusive_access/fullscreen_controller.cc`.
source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
}
Emit("leave-html-full-screen"); Emit("leave-html-full-screen");
} }
@ -1525,6 +1784,54 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) {
return handled; return handled;
} }
void WebContents::SetOwnerWindow(NativeWindow* owner_window) {
SetOwnerWindow(GetWebContents(), owner_window);
}
void WebContents::SetOwnerWindow(content::WebContents* web_contents,
NativeWindow* owner_window) {
if (owner_window) {
owner_window_ = owner_window->GetWeakPtr();
NativeWindowRelay::CreateForWebContents(web_contents,
owner_window->GetWeakPtr());
} else {
owner_window_ = nullptr;
web_contents->RemoveUserData(NativeWindowRelay::UserDataKey());
}
#if BUILDFLAG(ENABLE_OSR)
auto* osr_wcv = GetOffScreenWebContentsView();
if (osr_wcv)
osr_wcv->SetNativeWindow(owner_window);
#endif
}
void WebContents::ResetManagedWebContents(bool async) {
if (async) {
// Browser context should be destroyed only after the WebContents,
// this is guaranteed in the sync mode by the order of declaration,
// in the async version we maintain a reference until the WebContents
// is destroyed.
// //electron/patches/chromium/content_browser_main_loop.patch
// is required to get the right quit closure for the main message loop.
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
web_contents_.release());
} else {
web_contents_.reset();
}
}
content::WebContents* WebContents::GetWebContents() const {
if (!web_contents_)
return nullptr;
return web_contents_->GetWebContents();
}
content::WebContents* WebContents::GetDevToolsWebContents() const {
if (!web_contents_)
return nullptr;
return web_contents_->GetDevToolsWebContents();
}
void WebContents::MarkDestroyed() { void WebContents::MarkDestroyed() {
if (GetAllWebContents().Lookup(id_)) if (GetAllWebContents().Lookup(id_))
GetAllWebContents().Remove(id_); GetAllWebContents().Remove(id_);
@ -2935,6 +3242,364 @@ void WebContents::UpdatePreferredSize(content::WebContents* web_contents,
Emit("preferred-size-changed", pref_size); Emit("preferred-size-changed", pref_size);
} }
bool WebContents::CanOverscrollContent() {
return false;
}
content::ColorChooser* WebContents::OpenColorChooser(
content::WebContents* web_contents,
SkColor color,
const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions) {
#if BUILDFLAG(ENABLE_COLOR_CHOOSER)
return chrome::ShowColorChooser(web_contents, color);
#else
return nullptr;
#endif
}
void WebContents::RunFileChooser(
content::RenderFrameHost* render_frame_host,
scoped_refptr<content::FileSelectListener> listener,
const blink::mojom::FileChooserParams& params) {
if (!web_dialog_helper_)
web_dialog_helper_ =
std::make_unique<WebDialogHelper>(owner_window(), offscreen_);
web_dialog_helper_->RunFileChooser(render_frame_host, std::move(listener),
params);
}
void WebContents::EnumerateDirectory(
content::WebContents* guest,
scoped_refptr<content::FileSelectListener> listener,
const base::FilePath& path) {
if (!web_dialog_helper_)
web_dialog_helper_ =
std::make_unique<WebDialogHelper>(owner_window(), offscreen_);
web_dialog_helper_->EnumerateDirectory(guest, std::move(listener), path);
}
bool WebContents::IsFullscreenForTabOrPending(
const content::WebContents* source) {
return html_fullscreen_;
}
blink::SecurityStyle WebContents::GetSecurityStyle(
content::WebContents* web_contents,
content::SecurityStyleExplanations* security_style_explanations) {
SecurityStateTabHelper* helper =
SecurityStateTabHelper::FromWebContents(web_contents);
DCHECK(helper);
return security_state::GetSecurityStyle(helper->GetSecurityLevel(),
*helper->GetVisibleSecurityState(),
security_style_explanations);
}
bool WebContents::TakeFocus(content::WebContents* source, bool reverse) {
if (source && source->GetOutermostWebContents() == source) {
// If this is the outermost web contents and the user has tabbed or
// shift + tabbed through all the elements, reset the focus back to
// the first or last element so that it doesn't stay in the body.
source->FocusThroughTabTraversal(reverse);
return true;
}
return false;
}
content::PictureInPictureResult WebContents::EnterPictureInPicture(
content::WebContents* web_contents,
const viz::SurfaceId& surface_id,
const gfx::Size& natural_size) {
#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
return PictureInPictureWindowManager::GetInstance()->EnterPictureInPicture(
web_contents, surface_id, natural_size);
#else
return content::PictureInPictureResult::kNotSupported;
#endif
}
void WebContents::ExitPictureInPicture() {
#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
PictureInPictureWindowManager::GetInstance()->ExitPictureInPicture();
#endif
}
void WebContents::DevToolsSaveToFile(const std::string& url,
const std::string& content,
bool save_as) {
base::FilePath path;
auto it = saved_files_.find(url);
if (it != saved_files_.end() && !save_as) {
path = it->second;
} else {
file_dialog::DialogSettings settings;
settings.parent_window = owner_window();
settings.force_detached = offscreen_;
settings.title = url;
settings.default_path = base::FilePath::FromUTF8Unsafe(url);
if (!file_dialog::ShowSaveDialogSync(settings, &path)) {
base::Value url_value(url);
web_contents_->CallClientFunction("DevToolsAPI.canceledSaveURL",
&url_value, nullptr, nullptr);
return;
}
}
saved_files_[url] = path;
// Notify DevTools.
base::Value url_value(url);
base::Value file_system_path_value(path.AsUTF8Unsafe());
web_contents_->CallClientFunction("DevToolsAPI.savedURL", &url_value,
&file_system_path_value, nullptr);
file_task_runner_->PostTask(FROM_HERE,
base::BindOnce(&WriteToFile, path, content));
}
void WebContents::DevToolsAppendToFile(const std::string& url,
const std::string& content) {
auto it = saved_files_.find(url);
if (it == saved_files_.end())
return;
// Notify DevTools.
base::Value url_value(url);
web_contents_->CallClientFunction("DevToolsAPI.appendedToURL", &url_value,
nullptr, nullptr);
file_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&AppendToFile, it->second, content));
}
void WebContents::DevToolsRequestFileSystems() {
auto file_system_paths = GetAddedFileSystemPaths(GetDevToolsWebContents());
if (file_system_paths.empty()) {
base::ListValue empty_file_system_value;
web_contents_->CallClientFunction("DevToolsAPI.fileSystemsLoaded",
&empty_file_system_value, nullptr,
nullptr);
return;
}
std::vector<FileSystem> file_systems;
for (const auto& file_system_path : file_system_paths) {
base::FilePath path =
base::FilePath::FromUTF8Unsafe(file_system_path.first);
std::string file_system_id =
RegisterFileSystem(GetDevToolsWebContents(), path);
FileSystem file_system =
CreateFileSystemStruct(GetDevToolsWebContents(), file_system_id,
file_system_path.first, file_system_path.second);
file_systems.push_back(file_system);
}
base::ListValue file_system_value;
for (const auto& file_system : file_systems)
file_system_value.Append(CreateFileSystemValue(file_system));
web_contents_->CallClientFunction("DevToolsAPI.fileSystemsLoaded",
&file_system_value, nullptr, nullptr);
}
void WebContents::DevToolsAddFileSystem(
const std::string& type,
const base::FilePath& file_system_path) {
base::FilePath path = file_system_path;
if (path.empty()) {
std::vector<base::FilePath> paths;
file_dialog::DialogSettings settings;
settings.parent_window = owner_window();
settings.force_detached = offscreen_;
settings.properties = file_dialog::OPEN_DIALOG_OPEN_DIRECTORY;
if (!file_dialog::ShowOpenDialogSync(settings, &paths))
return;
path = paths[0];
}
std::string file_system_id =
RegisterFileSystem(GetDevToolsWebContents(), path);
if (IsDevToolsFileSystemAdded(GetDevToolsWebContents(), path.AsUTF8Unsafe()))
return;
FileSystem file_system = CreateFileSystemStruct(
GetDevToolsWebContents(), file_system_id, path.AsUTF8Unsafe(), type);
std::unique_ptr<base::DictionaryValue> file_system_value(
CreateFileSystemValue(file_system));
auto* pref_service = GetPrefService(GetDevToolsWebContents());
DictionaryPrefUpdate update(pref_service, prefs::kDevToolsFileSystemPaths);
update.Get()->SetWithoutPathExpansion(path.AsUTF8Unsafe(),
std::make_unique<base::Value>(type));
web_contents_->CallClientFunction("DevToolsAPI.fileSystemAdded", nullptr,
file_system_value.get(), nullptr);
}
void WebContents::DevToolsRemoveFileSystem(
const base::FilePath& file_system_path) {
if (!web_contents_)
return;
std::string path = file_system_path.AsUTF8Unsafe();
storage::IsolatedContext::GetInstance()->RevokeFileSystemByPath(
file_system_path);
auto* pref_service = GetPrefService(GetDevToolsWebContents());
DictionaryPrefUpdate update(pref_service, prefs::kDevToolsFileSystemPaths);
update.Get()->RemoveWithoutPathExpansion(path, nullptr);
base::Value file_system_path_value(path);
web_contents_->CallClientFunction("DevToolsAPI.fileSystemRemoved",
&file_system_path_value, nullptr, nullptr);
}
void WebContents::DevToolsIndexPath(
int request_id,
const std::string& file_system_path,
const std::string& excluded_folders_message) {
if (!IsDevToolsFileSystemAdded(GetDevToolsWebContents(), file_system_path)) {
OnDevToolsIndexingDone(request_id, file_system_path);
return;
}
if (devtools_indexing_jobs_.count(request_id) != 0)
return;
std::vector<std::string> excluded_folders;
std::unique_ptr<base::Value> parsed_excluded_folders =
base::JSONReader::ReadDeprecated(excluded_folders_message);
if (parsed_excluded_folders && parsed_excluded_folders->is_list()) {
for (const base::Value& folder_path : parsed_excluded_folders->GetList()) {
if (folder_path.is_string())
excluded_folders.push_back(folder_path.GetString());
}
}
devtools_indexing_jobs_[request_id] =
scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>(
devtools_file_system_indexer_->IndexPath(
file_system_path, excluded_folders,
base::BindRepeating(
&WebContents::OnDevToolsIndexingWorkCalculated,
weak_factory_.GetWeakPtr(), request_id, file_system_path),
base::BindRepeating(&WebContents::OnDevToolsIndexingWorked,
weak_factory_.GetWeakPtr(), request_id,
file_system_path),
base::BindRepeating(&WebContents::OnDevToolsIndexingDone,
weak_factory_.GetWeakPtr(), request_id,
file_system_path)));
}
void WebContents::DevToolsStopIndexing(int request_id) {
auto it = devtools_indexing_jobs_.find(request_id);
if (it == devtools_indexing_jobs_.end())
return;
it->second->Stop();
devtools_indexing_jobs_.erase(it);
}
void WebContents::DevToolsSearchInPath(int request_id,
const std::string& file_system_path,
const std::string& query) {
if (!IsDevToolsFileSystemAdded(GetDevToolsWebContents(), file_system_path)) {
OnDevToolsSearchCompleted(request_id, file_system_path,
std::vector<std::string>());
return;
}
devtools_file_system_indexer_->SearchInPath(
file_system_path, query,
base::BindRepeating(&WebContents::OnDevToolsSearchCompleted,
weak_factory_.GetWeakPtr(), request_id,
file_system_path));
}
#if defined(TOOLKIT_VIEWS) && !defined(OS_MAC)
gfx::ImageSkia WebContents::GetDevToolsWindowIcon() {
if (!owner_window())
return gfx::ImageSkia();
return owner_window()->GetWindowAppIcon();
}
#endif
#if defined(OS_LINUX)
void WebContents::GetDevToolsWindowWMClass(std::string* name,
std::string* class_name) {
*class_name = Browser::Get()->GetName();
*name = base::ToLowerASCII(*class_name);
}
#endif
void WebContents::OnDevToolsIndexingWorkCalculated(
int request_id,
const std::string& file_system_path,
int total_work) {
base::Value request_id_value(request_id);
base::Value file_system_path_value(file_system_path);
base::Value total_work_value(total_work);
web_contents_->CallClientFunction("DevToolsAPI.indexingTotalWorkCalculated",
&request_id_value, &file_system_path_value,
&total_work_value);
}
void WebContents::OnDevToolsIndexingWorked(int request_id,
const std::string& file_system_path,
int worked) {
base::Value request_id_value(request_id);
base::Value file_system_path_value(file_system_path);
base::Value worked_value(worked);
web_contents_->CallClientFunction("DevToolsAPI.indexingWorked",
&request_id_value, &file_system_path_value,
&worked_value);
}
void WebContents::OnDevToolsIndexingDone(int request_id,
const std::string& file_system_path) {
devtools_indexing_jobs_.erase(request_id);
base::Value request_id_value(request_id);
base::Value file_system_path_value(file_system_path);
web_contents_->CallClientFunction("DevToolsAPI.indexingDone",
&request_id_value, &file_system_path_value,
nullptr);
}
void WebContents::OnDevToolsSearchCompleted(
int request_id,
const std::string& file_system_path,
const std::vector<std::string>& file_paths) {
base::ListValue file_paths_value;
for (const auto& file_path : file_paths) {
file_paths_value.AppendString(file_path);
}
base::Value request_id_value(request_id);
base::Value file_system_path_value(file_system_path);
web_contents_->CallClientFunction("DevToolsAPI.searchCompleted",
&request_id_value, &file_system_path_value,
&file_paths_value);
}
void WebContents::SetHtmlApiFullscreen(bool enter_fullscreen) {
// Window is already in fullscreen mode, save the state.
if (enter_fullscreen && owner_window_->IsFullscreen()) {
native_fullscreen_ = true;
html_fullscreen_ = true;
return;
}
// Exit html fullscreen state but not window's fullscreen mode.
if (!enter_fullscreen && native_fullscreen_) {
html_fullscreen_ = false;
return;
}
// Set fullscreen on window if allowed.
auto* web_preferences = WebContentsPreferences::From(GetWebContents());
bool html_fullscreenable =
web_preferences ? !web_preferences->IsEnabled(
options::kDisableHtmlFullscreenWindowResize)
: true;
if (html_fullscreenable) {
owner_window_->SetFullScreen(enter_fullscreen);
}
html_fullscreen_ = enter_fullscreen;
native_fullscreen_ = false;
}
// static // static
v8::Local<v8::ObjectTemplate> WebContents::FillObjectTemplate( v8::Local<v8::ObjectTemplate> WebContents::FillObjectTemplate(
v8::Isolate* isolate, v8::Isolate* isolate,

View file

@ -11,14 +11,17 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/observer_list_types.h" #include "base/observer_list_types.h"
#include "chrome/browser/devtools/devtools_file_system_indexer.h"
#include "content/common/cursors/webcursor.h" #include "content/common/cursors/webcursor.h"
#include "content/common/frame.mojom.h" #include "content/common/frame.mojom.h"
#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/keyboard_event_processing_result.h" #include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
#include "electron/buildflags/buildflags.h" #include "electron/buildflags/buildflags.h"
#include "electron/shell/common/api/api.mojom.h" #include "electron/shell/common/api/api.mojom.h"
@ -29,9 +32,11 @@
#include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/binder_registry.h"
#include "shell/browser/api/frame_subscriber.h" #include "shell/browser/api/frame_subscriber.h"
#include "shell/browser/api/save_page_handler.h" #include "shell/browser/api/save_page_handler.h"
#include "shell/browser/common_web_contents_delegate.h"
#include "shell/browser/event_emitter_mixin.h" #include "shell/browser/event_emitter_mixin.h"
#include "shell/browser/extended_web_contents_observer.h" #include "shell/browser/extended_web_contents_observer.h"
#include "shell/browser/ui/inspectable_web_contents.h"
#include "shell/browser/ui/inspectable_web_contents_delegate.h"
#include "shell/browser/ui/inspectable_web_contents_view_delegate.h"
#include "shell/common/gin_helper/cleaned_up_at_exit.h" #include "shell/common/gin_helper/cleaned_up_at_exit.h"
#include "shell/common/gin_helper/constructible.h" #include "shell/common/gin_helper/constructible.h"
#include "shell/common/gin_helper/error_thrower.h" #include "shell/common/gin_helper/error_thrower.h"
@ -114,9 +119,12 @@ class InspectableWebContents;
class WebContentsZoomController; class WebContentsZoomController;
class WebViewGuestDelegate; class WebViewGuestDelegate;
class FrameSubscriber; class FrameSubscriber;
class WebDialogHelper;
class NativeWindow;
#if BUILDFLAG(ENABLE_OSR) #if BUILDFLAG(ENABLE_OSR)
class OffScreenRenderWidgetHostView; class OffScreenRenderWidgetHostView;
class OffScreenWebContentsView;
#endif #endif
namespace api { namespace api {
@ -126,8 +134,10 @@ class WebContents : public gin::Wrappable<WebContents>,
public gin_helper::EventEmitterMixin<WebContents>, public gin_helper::EventEmitterMixin<WebContents>,
public gin_helper::Constructible<WebContents>, public gin_helper::Constructible<WebContents>,
public gin_helper::CleanedUpAtExit, public gin_helper::CleanedUpAtExit,
public CommonWebContentsDelegate,
public content::WebContentsObserver, public content::WebContentsObserver,
public content::WebContentsDelegate,
public InspectableWebContentsDelegate,
public InspectableWebContentsViewDelegate,
public mojom::ElectronBrowser { public mojom::ElectronBrowser {
public: public:
enum class Type { enum class Type {
@ -425,7 +435,30 @@ class WebContents : public gin::Wrappable<WebContents>,
} }
#endif #endif
protected: // Set the window as owner window.
void SetOwnerWindow(NativeWindow* owner_window);
void SetOwnerWindow(content::WebContents* web_contents,
NativeWindow* owner_window);
// Returns the WebContents managed by this delegate.
content::WebContents* GetWebContents() const;
// Returns the WebContents of devtools.
content::WebContents* GetDevToolsWebContents() const;
InspectableWebContents* managed_web_contents() const {
return web_contents_.get();
}
NativeWindow* owner_window() const { return owner_window_.get(); }
bool is_html_fullscreen() const { return html_fullscreen_; }
void set_fullscreen_frame(content::RenderFrameHost* rfh) {
fullscreen_frame_ = rfh;
}
private:
// Does not manage lifetime of |web_contents|. // Does not manage lifetime of |web_contents|.
WebContents(v8::Isolate* isolate, content::WebContents* web_contents); WebContents(v8::Isolate* isolate, content::WebContents* web_contents);
// Takes over ownership of |web_contents|. // Takes over ownership of |web_contents|.
@ -436,6 +469,12 @@ class WebContents : public gin::Wrappable<WebContents>,
WebContents(v8::Isolate* isolate, const gin_helper::Dictionary& options); WebContents(v8::Isolate* isolate, const gin_helper::Dictionary& options);
~WebContents() override; ~WebContents() override;
// Creates a InspectableWebContents object and takes ownership of
// |web_contents|.
void InitWithWebContents(content::WebContents* web_contents,
ElectronBrowserContext* browser_context,
bool is_guest);
void InitWithSessionAndOptions( void InitWithSessionAndOptions(
v8::Isolate* isolate, v8::Isolate* isolate,
std::unique_ptr<content::WebContents> web_contents, std::unique_ptr<content::WebContents> web_contents,
@ -495,6 +534,9 @@ class WebContents : public gin::Wrappable<WebContents>,
bool HandleKeyboardEvent( bool HandleKeyboardEvent(
content::WebContents* source, content::WebContents* source,
const content::NativeWebKeyboardEvent& event) override; const content::NativeWebKeyboardEvent& event) override;
bool PlatformHandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event);
content::KeyboardEventProcessingResult PreHandleKeyboardEvent( content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
content::WebContents* source, content::WebContents* source,
const content::NativeWebKeyboardEvent& event) override; const content::NativeWebKeyboardEvent& event) override;
@ -606,7 +648,7 @@ class WebContents : public gin::Wrappable<WebContents>,
uint32_t GetNextRequestId() { return ++request_id_; } uint32_t GetNextRequestId() { return ++request_id_; }
#if BUILDFLAG(ENABLE_OSR) #if BUILDFLAG(ENABLE_OSR)
OffScreenWebContentsView* GetOffScreenWebContentsView() const override; OffScreenWebContentsView* GetOffScreenWebContentsView() const;
OffScreenRenderWidgetHostView* GetOffScreenRenderWidgetHostView() const; OffScreenRenderWidgetHostView* GetOffScreenRenderWidgetHostView() const;
#endif #endif
@ -645,6 +687,77 @@ class WebContents : public gin::Wrappable<WebContents>,
void InitZoomController(content::WebContents* web_contents, void InitZoomController(content::WebContents* web_contents,
const gin_helper::Dictionary& options); const gin_helper::Dictionary& options);
// content::WebContentsDelegate:
bool CanOverscrollContent() override;
content::ColorChooser* OpenColorChooser(
content::WebContents* web_contents,
SkColor color,
const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions)
override;
void RunFileChooser(content::RenderFrameHost* render_frame_host,
scoped_refptr<content::FileSelectListener> listener,
const blink::mojom::FileChooserParams& params) override;
void EnumerateDirectory(content::WebContents* web_contents,
scoped_refptr<content::FileSelectListener> listener,
const base::FilePath& path) override;
bool IsFullscreenForTabOrPending(const content::WebContents* source) override;
blink::SecurityStyle GetSecurityStyle(
content::WebContents* web_contents,
content::SecurityStyleExplanations* explanations) override;
bool TakeFocus(content::WebContents* source, bool reverse) override;
content::PictureInPictureResult EnterPictureInPicture(
content::WebContents* web_contents,
const viz::SurfaceId&,
const gfx::Size& natural_size) override;
void ExitPictureInPicture() override;
// InspectableWebContentsDelegate:
void DevToolsSaveToFile(const std::string& url,
const std::string& content,
bool save_as) override;
void DevToolsAppendToFile(const std::string& url,
const std::string& content) override;
void DevToolsRequestFileSystems() override;
void DevToolsAddFileSystem(const std::string& type,
const base::FilePath& file_system_path) override;
void DevToolsRemoveFileSystem(
const base::FilePath& file_system_path) override;
void DevToolsIndexPath(int request_id,
const std::string& file_system_path,
const std::string& excluded_folders_message) override;
void DevToolsStopIndexing(int request_id) override;
void DevToolsSearchInPath(int request_id,
const std::string& file_system_path,
const std::string& query) override;
// InspectableWebContentsViewDelegate:
#if defined(TOOLKIT_VIEWS) && !defined(OS_MAC)
gfx::ImageSkia GetDevToolsWindowIcon() override;
#endif
#if defined(OS_LINUX)
void GetDevToolsWindowWMClass(std::string* name,
std::string* class_name) override;
#endif
// Destroy the managed InspectableWebContents object.
void ResetManagedWebContents(bool async);
// DevTools index event callbacks.
void OnDevToolsIndexingWorkCalculated(int request_id,
const std::string& file_system_path,
int total_work);
void OnDevToolsIndexingWorked(int request_id,
const std::string& file_system_path,
int worked);
void OnDevToolsIndexingDone(int request_id,
const std::string& file_system_path);
void OnDevToolsSearchCompleted(int request_id,
const std::string& file_system_path,
const std::vector<std::string>& file_paths);
// Set fullscreen mode triggered by html api.
void SetHtmlApiFullscreen(bool enter_fullscreen);
v8::Global<v8::Value> session_; v8::Global<v8::Value> session_;
v8::Global<v8::Value> devtools_web_contents_; v8::Global<v8::Value> devtools_web_contents_;
v8::Global<v8::Value> debugger_; v8::Global<v8::Value> debugger_;
@ -684,6 +797,45 @@ class WebContents : public gin::Wrappable<WebContents>,
bool initially_shown_ = true; bool initially_shown_ = true;
// The window that this WebContents belongs to.
base::WeakPtr<NativeWindow> owner_window_;
bool offscreen_ = false;
// Whether window is fullscreened by HTML5 api.
bool html_fullscreen_ = false;
// Whether window is fullscreened by window api.
bool native_fullscreen_ = false;
// UI related helper classes.
std::unique_ptr<WebDialogHelper> web_dialog_helper_;
scoped_refptr<DevToolsFileSystemIndexer> devtools_file_system_indexer_;
ElectronBrowserContext* browser_context_;
// The stored InspectableWebContents object.
// Notice that web_contents_ must be placed after dialog_manager_, so we can
// make sure web_contents_ is destroyed before dialog_manager_, otherwise a
// crash would happen.
std::unique_ptr<InspectableWebContents> web_contents_;
// Maps url to file path, used by the file requests sent from devtools.
typedef std::map<std::string, base::FilePath> PathsMap;
PathsMap saved_files_;
// Map id to index job, used for file system indexing requests from devtools.
typedef std::
map<int, scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>>
DevToolsIndexingJobsMap;
DevToolsIndexingJobsMap devtools_indexing_jobs_;
scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
// Stores the frame thats currently in fullscreen, nullptr if there is none.
content::RenderFrameHost* fullscreen_frame_ = nullptr;
service_manager::BinderRegistryWithArgs<content::RenderFrameHost*> registry_; service_manager::BinderRegistryWithArgs<content::RenderFrameHost*> registry_;
mojo::ReceiverSet<mojom::ElectronBrowser, content::RenderFrameHost*> mojo::ReceiverSet<mojom::ElectronBrowser, content::RenderFrameHost*>
receivers_; receivers_;

View file

@ -4,9 +4,16 @@
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "shell/browser/api/electron_api_web_contents.h" #include "shell/browser/api/electron_api_web_contents.h"
#include "shell/browser/ui/cocoa/event_dispatching_window.h"
#include "shell/browser/web_contents_preferences.h"
#include "ui/events/keycodes/keyboard_codes.h"
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
@interface NSWindow (EventDispatchingWindow)
- (void)redispatchKeyEvent:(NSEvent*)event;
@end
namespace electron { namespace electron {
namespace api { namespace api {
@ -27,6 +34,42 @@ bool WebContents::IsFocused() const {
return view->HasFocus(); return view->HasFocus();
} }
bool WebContents::PlatformHandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) {
if (event.skip_in_browser ||
event.GetType() == content::NativeWebKeyboardEvent::Type::kChar)
return false;
// Escape exits tabbed fullscreen mode.
if (event.windows_key_code == ui::VKEY_ESCAPE && is_html_fullscreen()) {
ExitFullscreenModeForTab(source);
return true;
}
// Check if the webContents has preferences and to ignore shortcuts
auto* web_preferences = WebContentsPreferences::From(source);
if (web_preferences &&
web_preferences->IsEnabled("ignoreMenuShortcuts", false))
return false;
// Send the event to the menu before sending it to the window
if (event.os_event.type == NSKeyDown &&
[[NSApp mainMenu] performKeyEquivalent:event.os_event])
return true;
if (event.os_event.window &&
[event.os_event.window isKindOfClass:[EventDispatchingWindow class]]) {
[event.os_event.window redispatchKeyEvent:event.os_event];
// FIXME(nornagon): this isn't the right return value; we should implement
// devtools windows as Widgets in order to take advantage of the
// pre-existing redispatch code in bridged_native_widget.
return false;
}
return false;
}
} // namespace api } // namespace api
} // namespace electron } // namespace electron

View file

@ -1,693 +0,0 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/common_web_contents_delegate.h"
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "chrome/browser/ssl/security_state_tab_helper.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/security_state/content/content_utils.h"
#include "components/security_state/core/security_state.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/security_style_explanation.h"
#include "content/public/browser/security_style_explanations.h"
#include "printing/buildflags/buildflags.h"
#include "shell/browser/electron_browser_client.h"
#include "shell/browser/electron_browser_context.h"
#include "shell/browser/native_window.h"
#include "shell/browser/ui/file_dialog.h"
#include "shell/browser/web_contents_preferences.h"
#include "shell/browser/web_dialog_helper.h"
#include "shell/common/electron_constants.h"
#include "shell/common/options_switches.h"
#include "storage/browser/file_system/isolated_context.h"
#if BUILDFLAG(ENABLE_COLOR_CHOOSER)
#include "chrome/browser/ui/color_chooser.h"
#endif
#if BUILDFLAG(ENABLE_OSR)
#include "shell/browser/osr/osr_web_contents_view.h"
#endif
#if BUILDFLAG(ENABLE_PRINTING)
#include "chrome/browser/printing/print_view_manager_basic.h"
#include "components/printing/browser/print_manager_utils.h"
#include "shell/browser/printing/print_preview_message_handler.h"
#endif
#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
#endif
#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "components/pdf/browser/pdf_web_contents_helper.h" // nogncheck
#include "shell/browser/electron_pdf_web_contents_helper_client.h"
#endif
using content::BrowserThread;
namespace electron {
namespace {
const char kRootName[] = "<root>";
struct FileSystem {
FileSystem() = default;
FileSystem(const std::string& type,
const std::string& file_system_name,
const std::string& root_url,
const std::string& file_system_path)
: type(type),
file_system_name(file_system_name),
root_url(root_url),
file_system_path(file_system_path) {}
std::string type;
std::string file_system_name;
std::string root_url;
std::string file_system_path;
};
std::string RegisterFileSystem(content::WebContents* web_contents,
const base::FilePath& path) {
auto* isolated_context = storage::IsolatedContext::GetInstance();
std::string root_name(kRootName);
storage::IsolatedContext::ScopedFSHandle file_system =
isolated_context->RegisterFileSystemForPath(
storage::kFileSystemTypeNativeLocal, std::string(), path, &root_name);
content::ChildProcessSecurityPolicy* policy =
content::ChildProcessSecurityPolicy::GetInstance();
content::RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
int renderer_id = render_view_host->GetProcess()->GetID();
policy->GrantReadFileSystem(renderer_id, file_system.id());
policy->GrantWriteFileSystem(renderer_id, file_system.id());
policy->GrantCreateFileForFileSystem(renderer_id, file_system.id());
policy->GrantDeleteFromFileSystem(renderer_id, file_system.id());
if (!policy->CanReadFile(renderer_id, path))
policy->GrantReadFile(renderer_id, path);
return file_system.id();
}
FileSystem CreateFileSystemStruct(content::WebContents* web_contents,
const std::string& file_system_id,
const std::string& file_system_path,
const std::string& type) {
const GURL origin = web_contents->GetURL().GetOrigin();
std::string file_system_name =
storage::GetIsolatedFileSystemName(origin, file_system_id);
std::string root_url = storage::GetIsolatedFileSystemRootURIString(
origin, file_system_id, kRootName);
return FileSystem(type, file_system_name, root_url, file_system_path);
}
std::unique_ptr<base::DictionaryValue> CreateFileSystemValue(
const FileSystem& file_system) {
std::unique_ptr<base::DictionaryValue> file_system_value(
new base::DictionaryValue());
file_system_value->SetString("type", file_system.type);
file_system_value->SetString("fileSystemName", file_system.file_system_name);
file_system_value->SetString("rootURL", file_system.root_url);
file_system_value->SetString("fileSystemPath", file_system.file_system_path);
return file_system_value;
}
void WriteToFile(const base::FilePath& path, const std::string& content) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::WILL_BLOCK);
DCHECK(!path.empty());
base::WriteFile(path, content.data(), content.size());
}
void AppendToFile(const base::FilePath& path, const std::string& content) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::WILL_BLOCK);
DCHECK(!path.empty());
base::AppendToFile(path, content.data(), content.size());
}
PrefService* GetPrefService(content::WebContents* web_contents) {
auto* context = web_contents->GetBrowserContext();
return static_cast<electron::ElectronBrowserContext*>(context)->prefs();
}
std::map<std::string, std::string> GetAddedFileSystemPaths(
content::WebContents* web_contents) {
auto* pref_service = GetPrefService(web_contents);
const base::DictionaryValue* file_system_paths_value =
pref_service->GetDictionary(prefs::kDevToolsFileSystemPaths);
std::map<std::string, std::string> result;
if (file_system_paths_value) {
base::DictionaryValue::Iterator it(*file_system_paths_value);
for (; !it.IsAtEnd(); it.Advance()) {
std::string type =
it.value().is_string() ? it.value().GetString() : std::string();
result[it.key()] = type;
}
}
return result;
}
bool IsDevToolsFileSystemAdded(content::WebContents* web_contents,
const std::string& file_system_path) {
auto file_system_paths = GetAddedFileSystemPaths(web_contents);
return file_system_paths.find(file_system_path) != file_system_paths.end();
}
} // namespace
CommonWebContentsDelegate::CommonWebContentsDelegate()
: devtools_file_system_indexer_(new DevToolsFileSystemIndexer),
file_task_runner_(
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
weak_factory_(this) {}
CommonWebContentsDelegate::~CommonWebContentsDelegate() = default;
void CommonWebContentsDelegate::InitWithWebContents(
content::WebContents* web_contents,
ElectronBrowserContext* browser_context,
bool is_guest) {
browser_context_ = browser_context;
web_contents->SetDelegate(this);
#if BUILDFLAG(ENABLE_PRINTING)
PrintPreviewMessageHandler::CreateForWebContents(web_contents);
printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
printing::CreateCompositeClientIfNeeded(web_contents,
browser_context->GetUserAgent());
#endif
#if BUILDFLAG(ENABLE_PDF_VIEWER)
pdf::PDFWebContentsHelper::CreateForWebContentsWithClient(
web_contents, std::make_unique<ElectronPDFWebContentsHelperClient>());
#endif
// Determine whether the WebContents is offscreen.
auto* web_preferences = WebContentsPreferences::From(web_contents);
offscreen_ =
web_preferences && web_preferences->IsEnabled(options::kOffscreen);
// Create InspectableWebContents.
web_contents_.reset(new InspectableWebContents(
web_contents, browser_context->prefs(), is_guest));
web_contents_->SetDelegate(this);
}
void CommonWebContentsDelegate::SetOwnerWindow(NativeWindow* owner_window) {
SetOwnerWindow(GetWebContents(), owner_window);
}
void CommonWebContentsDelegate::SetOwnerWindow(
content::WebContents* web_contents,
NativeWindow* owner_window) {
if (owner_window) {
owner_window_ = owner_window->GetWeakPtr();
NativeWindowRelay::CreateForWebContents(web_contents,
owner_window->GetWeakPtr());
} else {
owner_window_ = nullptr;
web_contents->RemoveUserData(NativeWindowRelay::UserDataKey());
}
#if BUILDFLAG(ENABLE_OSR)
auto* osr_wcv = GetOffScreenWebContentsView();
if (osr_wcv)
osr_wcv->SetNativeWindow(owner_window);
#endif
}
void CommonWebContentsDelegate::ResetManagedWebContents(bool async) {
if (async) {
// Browser context should be destroyed only after the WebContents,
// this is guaranteed in the sync mode by the order of declaration,
// in the async version we maintain a reference until the WebContents
// is destroyed.
// //electron/patches/chromium/content_browser_main_loop.patch
// is required to get the right quit closure for the main message loop.
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
web_contents_.release());
} else {
web_contents_.reset();
}
}
content::WebContents* CommonWebContentsDelegate::GetWebContents() const {
if (!web_contents_)
return nullptr;
return web_contents_->GetWebContents();
}
content::WebContents* CommonWebContentsDelegate::GetDevToolsWebContents()
const {
if (!web_contents_)
return nullptr;
return web_contents_->GetDevToolsWebContents();
}
#if BUILDFLAG(ENABLE_OSR)
OffScreenWebContentsView*
CommonWebContentsDelegate::GetOffScreenWebContentsView() const {
return nullptr;
}
#endif
content::WebContents* CommonWebContentsDelegate::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
content::NavigationController::LoadURLParams load_url_params(params.url);
load_url_params.referrer = params.referrer;
load_url_params.transition_type = params.transition;
load_url_params.extra_headers = params.extra_headers;
load_url_params.should_replace_current_entry =
params.should_replace_current_entry;
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.started_from_context_menu = params.started_from_context_menu;
load_url_params.initiator_origin = params.initiator_origin;
load_url_params.source_site_instance = params.source_site_instance;
load_url_params.frame_tree_node_id = params.frame_tree_node_id;
load_url_params.redirect_chain = params.redirect_chain;
load_url_params.has_user_gesture = params.user_gesture;
load_url_params.blob_url_loader_factory = params.blob_url_loader_factory;
load_url_params.href_translate = params.href_translate;
load_url_params.reload_type = params.reload_type;
if (params.post_data) {
load_url_params.load_type =
content::NavigationController::LOAD_TYPE_HTTP_POST;
load_url_params.post_data = params.post_data;
}
source->GetController().LoadURLWithParams(load_url_params);
return source;
}
bool CommonWebContentsDelegate::CanOverscrollContent() {
return false;
}
content::ColorChooser* CommonWebContentsDelegate::OpenColorChooser(
content::WebContents* web_contents,
SkColor color,
const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions) {
#if BUILDFLAG(ENABLE_COLOR_CHOOSER)
return chrome::ShowColorChooser(web_contents, color);
#else
return nullptr;
#endif
}
void CommonWebContentsDelegate::RunFileChooser(
content::RenderFrameHost* render_frame_host,
scoped_refptr<content::FileSelectListener> listener,
const blink::mojom::FileChooserParams& params) {
if (!web_dialog_helper_)
web_dialog_helper_ =
std::make_unique<WebDialogHelper>(owner_window(), offscreen_);
web_dialog_helper_->RunFileChooser(render_frame_host, std::move(listener),
params);
}
void CommonWebContentsDelegate::EnumerateDirectory(
content::WebContents* guest,
scoped_refptr<content::FileSelectListener> listener,
const base::FilePath& path) {
if (!web_dialog_helper_)
web_dialog_helper_ =
std::make_unique<WebDialogHelper>(owner_window(), offscreen_);
web_dialog_helper_->EnumerateDirectory(guest, std::move(listener), path);
}
void CommonWebContentsDelegate::EnterFullscreenModeForTab(
content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) {
if (!owner_window_)
return;
auto* source = content::WebContents::FromRenderFrameHost(requesting_frame);
if (IsFullscreenForTabOrPending(source)) {
DCHECK_EQ(fullscreen_frame_, source->GetFocusedFrame());
return;
}
SetHtmlApiFullscreen(true);
owner_window_->NotifyWindowEnterHtmlFullScreen();
if (native_fullscreen_) {
// Explicitly trigger a view resize, as the size is not actually changing if
// the browser is fullscreened, too.
source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
}
}
void CommonWebContentsDelegate::ExitFullscreenModeForTab(
content::WebContents* source) {
if (!owner_window_)
return;
SetHtmlApiFullscreen(false);
owner_window_->NotifyWindowLeaveHtmlFullScreen();
if (native_fullscreen_) {
// Explicitly trigger a view resize, as the size is not actually changing if
// the browser is fullscreened, too. Chrome does this indirectly from
// `chrome/browser/ui/exclusive_access/fullscreen_controller.cc`.
source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
}
}
bool CommonWebContentsDelegate::IsFullscreenForTabOrPending(
const content::WebContents* source) {
return html_fullscreen_;
}
blink::SecurityStyle CommonWebContentsDelegate::GetSecurityStyle(
content::WebContents* web_contents,
content::SecurityStyleExplanations* security_style_explanations) {
SecurityStateTabHelper* helper =
SecurityStateTabHelper::FromWebContents(web_contents);
DCHECK(helper);
return security_state::GetSecurityStyle(helper->GetSecurityLevel(),
*helper->GetVisibleSecurityState(),
security_style_explanations);
}
bool CommonWebContentsDelegate::TakeFocus(content::WebContents* source,
bool reverse) {
if (source && source->GetOutermostWebContents() == source) {
// If this is the outermost web contents and the user has tabbed or
// shift + tabbed through all the elements, reset the focus back to
// the first or last element so that it doesn't stay in the body.
source->FocusThroughTabTraversal(reverse);
return true;
}
return false;
}
void CommonWebContentsDelegate::DevToolsSaveToFile(const std::string& url,
const std::string& content,
bool save_as) {
base::FilePath path;
auto it = saved_files_.find(url);
if (it != saved_files_.end() && !save_as) {
path = it->second;
} else {
file_dialog::DialogSettings settings;
settings.parent_window = owner_window();
settings.force_detached = offscreen_;
settings.title = url;
settings.default_path = base::FilePath::FromUTF8Unsafe(url);
if (!file_dialog::ShowSaveDialogSync(settings, &path)) {
base::Value url_value(url);
web_contents_->CallClientFunction("DevToolsAPI.canceledSaveURL",
&url_value, nullptr, nullptr);
return;
}
}
saved_files_[url] = path;
// Notify DevTools.
base::Value url_value(url);
base::Value file_system_path_value(path.AsUTF8Unsafe());
web_contents_->CallClientFunction("DevToolsAPI.savedURL", &url_value,
&file_system_path_value, nullptr);
file_task_runner_->PostTask(FROM_HERE,
base::BindOnce(&WriteToFile, path, content));
}
void CommonWebContentsDelegate::DevToolsAppendToFile(
const std::string& url,
const std::string& content) {
auto it = saved_files_.find(url);
if (it == saved_files_.end())
return;
// Notify DevTools.
base::Value url_value(url);
web_contents_->CallClientFunction("DevToolsAPI.appendedToURL", &url_value,
nullptr, nullptr);
file_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&AppendToFile, it->second, content));
}
void CommonWebContentsDelegate::DevToolsRequestFileSystems() {
auto file_system_paths = GetAddedFileSystemPaths(GetDevToolsWebContents());
if (file_system_paths.empty()) {
base::ListValue empty_file_system_value;
web_contents_->CallClientFunction("DevToolsAPI.fileSystemsLoaded",
&empty_file_system_value, nullptr,
nullptr);
return;
}
std::vector<FileSystem> file_systems;
for (const auto& file_system_path : file_system_paths) {
base::FilePath path =
base::FilePath::FromUTF8Unsafe(file_system_path.first);
std::string file_system_id =
RegisterFileSystem(GetDevToolsWebContents(), path);
FileSystem file_system =
CreateFileSystemStruct(GetDevToolsWebContents(), file_system_id,
file_system_path.first, file_system_path.second);
file_systems.push_back(file_system);
}
base::ListValue file_system_value;
for (const auto& file_system : file_systems)
file_system_value.Append(CreateFileSystemValue(file_system));
web_contents_->CallClientFunction("DevToolsAPI.fileSystemsLoaded",
&file_system_value, nullptr, nullptr);
}
void CommonWebContentsDelegate::DevToolsAddFileSystem(
const std::string& type,
const base::FilePath& file_system_path) {
base::FilePath path = file_system_path;
if (path.empty()) {
std::vector<base::FilePath> paths;
file_dialog::DialogSettings settings;
settings.parent_window = owner_window();
settings.force_detached = offscreen_;
settings.properties = file_dialog::OPEN_DIALOG_OPEN_DIRECTORY;
if (!file_dialog::ShowOpenDialogSync(settings, &paths))
return;
path = paths[0];
}
std::string file_system_id =
RegisterFileSystem(GetDevToolsWebContents(), path);
if (IsDevToolsFileSystemAdded(GetDevToolsWebContents(), path.AsUTF8Unsafe()))
return;
FileSystem file_system = CreateFileSystemStruct(
GetDevToolsWebContents(), file_system_id, path.AsUTF8Unsafe(), type);
std::unique_ptr<base::DictionaryValue> file_system_value(
CreateFileSystemValue(file_system));
auto* pref_service = GetPrefService(GetDevToolsWebContents());
DictionaryPrefUpdate update(pref_service, prefs::kDevToolsFileSystemPaths);
update.Get()->SetWithoutPathExpansion(path.AsUTF8Unsafe(),
std::make_unique<base::Value>(type));
web_contents_->CallClientFunction("DevToolsAPI.fileSystemAdded", nullptr,
file_system_value.get(), nullptr);
}
void CommonWebContentsDelegate::DevToolsRemoveFileSystem(
const base::FilePath& file_system_path) {
if (!web_contents_)
return;
std::string path = file_system_path.AsUTF8Unsafe();
storage::IsolatedContext::GetInstance()->RevokeFileSystemByPath(
file_system_path);
auto* pref_service = GetPrefService(GetDevToolsWebContents());
DictionaryPrefUpdate update(pref_service, prefs::kDevToolsFileSystemPaths);
update.Get()->RemoveWithoutPathExpansion(path, nullptr);
base::Value file_system_path_value(path);
web_contents_->CallClientFunction("DevToolsAPI.fileSystemRemoved",
&file_system_path_value, nullptr, nullptr);
}
void CommonWebContentsDelegate::DevToolsIndexPath(
int request_id,
const std::string& file_system_path,
const std::string& excluded_folders_message) {
if (!IsDevToolsFileSystemAdded(GetDevToolsWebContents(), file_system_path)) {
OnDevToolsIndexingDone(request_id, file_system_path);
return;
}
if (devtools_indexing_jobs_.count(request_id) != 0)
return;
std::vector<std::string> excluded_folders;
std::unique_ptr<base::Value> parsed_excluded_folders =
base::JSONReader::ReadDeprecated(excluded_folders_message);
if (parsed_excluded_folders && parsed_excluded_folders->is_list()) {
for (const base::Value& folder_path : parsed_excluded_folders->GetList()) {
if (folder_path.is_string())
excluded_folders.push_back(folder_path.GetString());
}
}
devtools_indexing_jobs_[request_id] =
scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>(
devtools_file_system_indexer_->IndexPath(
file_system_path, excluded_folders,
base::BindRepeating(
&CommonWebContentsDelegate::OnDevToolsIndexingWorkCalculated,
weak_factory_.GetWeakPtr(), request_id, file_system_path),
base::BindRepeating(
&CommonWebContentsDelegate::OnDevToolsIndexingWorked,
weak_factory_.GetWeakPtr(), request_id, file_system_path),
base::BindRepeating(
&CommonWebContentsDelegate::OnDevToolsIndexingDone,
weak_factory_.GetWeakPtr(), request_id, file_system_path)));
}
void CommonWebContentsDelegate::DevToolsStopIndexing(int request_id) {
auto it = devtools_indexing_jobs_.find(request_id);
if (it == devtools_indexing_jobs_.end())
return;
it->second->Stop();
devtools_indexing_jobs_.erase(it);
}
void CommonWebContentsDelegate::DevToolsSearchInPath(
int request_id,
const std::string& file_system_path,
const std::string& query) {
if (!IsDevToolsFileSystemAdded(GetDevToolsWebContents(), file_system_path)) {
OnDevToolsSearchCompleted(request_id, file_system_path,
std::vector<std::string>());
return;
}
devtools_file_system_indexer_->SearchInPath(
file_system_path, query,
base::BindRepeating(&CommonWebContentsDelegate::OnDevToolsSearchCompleted,
weak_factory_.GetWeakPtr(), request_id,
file_system_path));
}
void CommonWebContentsDelegate::OnDevToolsIndexingWorkCalculated(
int request_id,
const std::string& file_system_path,
int total_work) {
base::Value request_id_value(request_id);
base::Value file_system_path_value(file_system_path);
base::Value total_work_value(total_work);
web_contents_->CallClientFunction("DevToolsAPI.indexingTotalWorkCalculated",
&request_id_value, &file_system_path_value,
&total_work_value);
}
void CommonWebContentsDelegate::OnDevToolsIndexingWorked(
int request_id,
const std::string& file_system_path,
int worked) {
base::Value request_id_value(request_id);
base::Value file_system_path_value(file_system_path);
base::Value worked_value(worked);
web_contents_->CallClientFunction("DevToolsAPI.indexingWorked",
&request_id_value, &file_system_path_value,
&worked_value);
}
void CommonWebContentsDelegate::OnDevToolsIndexingDone(
int request_id,
const std::string& file_system_path) {
devtools_indexing_jobs_.erase(request_id);
base::Value request_id_value(request_id);
base::Value file_system_path_value(file_system_path);
web_contents_->CallClientFunction("DevToolsAPI.indexingDone",
&request_id_value, &file_system_path_value,
nullptr);
}
void CommonWebContentsDelegate::OnDevToolsSearchCompleted(
int request_id,
const std::string& file_system_path,
const std::vector<std::string>& file_paths) {
base::ListValue file_paths_value;
for (const auto& file_path : file_paths) {
file_paths_value.AppendString(file_path);
}
base::Value request_id_value(request_id);
base::Value file_system_path_value(file_system_path);
web_contents_->CallClientFunction("DevToolsAPI.searchCompleted",
&request_id_value, &file_system_path_value,
&file_paths_value);
}
void CommonWebContentsDelegate::SetHtmlApiFullscreen(bool enter_fullscreen) {
// Window is already in fullscreen mode, save the state.
if (enter_fullscreen && owner_window_->IsFullscreen()) {
native_fullscreen_ = true;
html_fullscreen_ = true;
return;
}
// Exit html fullscreen state but not window's fullscreen mode.
if (!enter_fullscreen && native_fullscreen_) {
html_fullscreen_ = false;
return;
}
// Set fullscreen on window if allowed.
auto* web_preferences = WebContentsPreferences::From(GetWebContents());
bool html_fullscreenable =
web_preferences ? !web_preferences->IsEnabled(
options::kDisableHtmlFullscreenWindowResize)
: true;
if (html_fullscreenable) {
owner_window_->SetFullScreen(enter_fullscreen);
}
html_fullscreen_ = enter_fullscreen;
native_fullscreen_ = false;
}
content::PictureInPictureResult
CommonWebContentsDelegate::EnterPictureInPicture(
content::WebContents* web_contents,
const viz::SurfaceId& surface_id,
const gfx::Size& natural_size) {
#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
return PictureInPictureWindowManager::GetInstance()->EnterPictureInPicture(
web_contents, surface_id, natural_size);
#else
return content::PictureInPictureResult::kNotSupported;
#endif
}
void CommonWebContentsDelegate::ExitPictureInPicture() {
#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
PictureInPictureWindowManager::GetInstance()->ExitPictureInPicture();
#endif
}
} // namespace electron

View file

@ -1,204 +0,0 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef SHELL_BROWSER_COMMON_WEB_CONTENTS_DELEGATE_H_
#define SHELL_BROWSER_COMMON_WEB_CONTENTS_DELEGATE_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "chrome/browser/devtools/devtools_file_system_indexer.h"
#include "content/public/browser/web_contents_delegate.h"
#include "electron/buildflags/buildflags.h"
#include "shell/browser/ui/inspectable_web_contents.h"
#include "shell/browser/ui/inspectable_web_contents_delegate.h"
#include "shell/browser/ui/inspectable_web_contents_view_delegate.h"
namespace base {
class SequencedTaskRunner;
}
namespace electron {
class ElectronBrowserContext;
class NativeWindow;
class WebDialogHelper;
#if BUILDFLAG(ENABLE_OSR)
class OffScreenWebContentsView;
#endif
class CommonWebContentsDelegate : public content::WebContentsDelegate,
public InspectableWebContentsDelegate,
public InspectableWebContentsViewDelegate {
public:
CommonWebContentsDelegate();
~CommonWebContentsDelegate() override;
// Creates a InspectableWebContents object and takes ownership of
// |web_contents|.
void InitWithWebContents(content::WebContents* web_contents,
ElectronBrowserContext* browser_context,
bool is_guest);
// Set the window as owner window.
void SetOwnerWindow(NativeWindow* owner_window);
void SetOwnerWindow(content::WebContents* web_contents,
NativeWindow* owner_window);
// Returns the WebContents managed by this delegate.
content::WebContents* GetWebContents() const;
// Returns the WebContents of devtools.
content::WebContents* GetDevToolsWebContents() const;
InspectableWebContents* managed_web_contents() const {
return web_contents_.get();
}
NativeWindow* owner_window() const { return owner_window_.get(); }
bool is_html_fullscreen() const { return html_fullscreen_; }
void set_fullscreen_frame(content::RenderFrameHost* rfh) {
fullscreen_frame_ = rfh;
}
protected:
#if BUILDFLAG(ENABLE_OSR)
virtual OffScreenWebContentsView* GetOffScreenWebContentsView() const;
#endif
// content::WebContentsDelegate:
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
bool CanOverscrollContent() override;
content::ColorChooser* OpenColorChooser(
content::WebContents* web_contents,
SkColor color,
const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions)
override;
void RunFileChooser(content::RenderFrameHost* render_frame_host,
scoped_refptr<content::FileSelectListener> listener,
const blink::mojom::FileChooserParams& params) override;
void EnumerateDirectory(content::WebContents* web_contents,
scoped_refptr<content::FileSelectListener> listener,
const base::FilePath& path) override;
void EnterFullscreenModeForTab(
content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) override;
void ExitFullscreenModeForTab(content::WebContents* source) override;
bool IsFullscreenForTabOrPending(const content::WebContents* source) override;
blink::SecurityStyle GetSecurityStyle(
content::WebContents* web_contents,
content::SecurityStyleExplanations* explanations) override;
bool TakeFocus(content::WebContents* source, bool reverse) override;
bool HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) override;
content::PictureInPictureResult EnterPictureInPicture(
content::WebContents* web_contents,
const viz::SurfaceId&,
const gfx::Size& natural_size) override;
void ExitPictureInPicture() override;
// InspectableWebContentsDelegate:
void DevToolsSaveToFile(const std::string& url,
const std::string& content,
bool save_as) override;
void DevToolsAppendToFile(const std::string& url,
const std::string& content) override;
void DevToolsRequestFileSystems() override;
void DevToolsAddFileSystem(const std::string& type,
const base::FilePath& file_system_path) override;
void DevToolsRemoveFileSystem(
const base::FilePath& file_system_path) override;
void DevToolsIndexPath(int request_id,
const std::string& file_system_path,
const std::string& excluded_folders_message) override;
void DevToolsStopIndexing(int request_id) override;
void DevToolsSearchInPath(int request_id,
const std::string& file_system_path,
const std::string& query) override;
// InspectableWebContentsViewDelegate:
#if defined(TOOLKIT_VIEWS) && !defined(OS_MAC)
gfx::ImageSkia GetDevToolsWindowIcon() override;
#endif
#if defined(OS_LINUX)
void GetDevToolsWindowWMClass(std::string* name,
std::string* class_name) override;
#endif
// Destroy the managed InspectableWebContents object.
void ResetManagedWebContents(bool async);
private:
// DevTools index event callbacks.
void OnDevToolsIndexingWorkCalculated(int request_id,
const std::string& file_system_path,
int total_work);
void OnDevToolsIndexingWorked(int request_id,
const std::string& file_system_path,
int worked);
void OnDevToolsIndexingDone(int request_id,
const std::string& file_system_path);
void OnDevToolsSearchCompleted(int request_id,
const std::string& file_system_path,
const std::vector<std::string>& file_paths);
// Set fullscreen mode triggered by html api.
void SetHtmlApiFullscreen(bool enter_fullscreen);
// The window that this WebContents belongs to.
base::WeakPtr<NativeWindow> owner_window_;
bool offscreen_ = false;
// Whether window is fullscreened by HTML5 api.
bool html_fullscreen_ = false;
// Whether window is fullscreened by window api.
bool native_fullscreen_ = false;
// UI related helper classes.
std::unique_ptr<WebDialogHelper> web_dialog_helper_;
scoped_refptr<DevToolsFileSystemIndexer> devtools_file_system_indexer_;
ElectronBrowserContext* browser_context_;
// The stored InspectableWebContents object.
// Notice that web_contents_ must be placed after dialog_manager_, so we can
// make sure web_contents_ is destroyed before dialog_manager_, otherwise a
// crash would happen.
std::unique_ptr<InspectableWebContents> web_contents_;
// Maps url to file path, used by the file requests sent from devtools.
typedef std::map<std::string, base::FilePath> PathsMap;
PathsMap saved_files_;
// Map id to index job, used for file system indexing requests from devtools.
typedef std::
map<int, scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>>
DevToolsIndexingJobsMap;
DevToolsIndexingJobsMap devtools_indexing_jobs_;
scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
// Stores the frame thats currently in fullscreen, nullptr if there is none.
content::RenderFrameHost* fullscreen_frame_ = nullptr;
base::WeakPtrFactory<CommonWebContentsDelegate> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CommonWebContentsDelegate);
};
} // namespace electron
#endif // SHELL_BROWSER_COMMON_WEB_CONTENTS_DELEGATE_H_

View file

@ -1,56 +0,0 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/common_web_contents_delegate.h"
#import <Cocoa/Cocoa.h>
#include "content/public/browser/native_web_keyboard_event.h"
#include "shell/browser/ui/cocoa/event_dispatching_window.h"
#include "shell/browser/web_contents_preferences.h"
#include "ui/events/keycodes/keyboard_codes.h"
@interface NSWindow (EventDispatchingWindow)
- (void)redispatchKeyEvent:(NSEvent*)event;
@end
namespace electron {
bool CommonWebContentsDelegate::HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) {
if (event.skip_in_browser ||
event.GetType() == content::NativeWebKeyboardEvent::Type::kChar)
return false;
// Escape exits tabbed fullscreen mode.
if (event.windows_key_code == ui::VKEY_ESCAPE && is_html_fullscreen()) {
ExitFullscreenModeForTab(source);
return true;
}
// Check if the webContents has preferences and to ignore shortcuts
auto* web_preferences = WebContentsPreferences::From(source);
if (web_preferences &&
web_preferences->IsEnabled("ignoreMenuShortcuts", false))
return false;
// Send the event to the menu before sending it to the window
if (event.os_event.type == NSKeyDown &&
[[NSApp mainMenu] performKeyEquivalent:event.os_event])
return true;
if (event.os_event.window &&
[event.os_event.window isKindOfClass:[EventDispatchingWindow class]]) {
[event.os_event.window redispatchKeyEvent:event.os_event];
// FIXME(nornagon): this isn't the right return value; we should implement
// devtools windows as Widgets in order to take advantage of the
// pre-existing redispatch code in bridged_native_widget.
return false;
}
return false;
}
} // namespace electron

View file

@ -1,61 +0,0 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/common_web_contents_delegate.h"
#include "base/strings/string_util.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "shell/browser/api/electron_api_web_contents_view.h"
#include "shell/browser/native_window_views.h"
#include "shell/browser/web_contents_preferences.h"
#include "ui/events/keycodes/keyboard_codes.h"
#if defined(OS_LINUX)
#include "shell/browser/browser.h"
#endif
namespace electron {
bool CommonWebContentsDelegate::HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) {
// Escape exits tabbed fullscreen mode.
if (event.windows_key_code == ui::VKEY_ESCAPE && is_html_fullscreen()) {
ExitFullscreenModeForTab(source);
return true;
}
// Check if the webContents has preferences and to ignore shortcuts
auto* web_preferences = WebContentsPreferences::From(source);
if (web_preferences &&
web_preferences->IsEnabled("ignoreMenuShortcuts", false))
return false;
// Let the NativeWindow handle other parts.
if (owner_window()) {
owner_window()->HandleKeyboardEvent(source, event);
return true;
}
return false;
}
gfx::ImageSkia CommonWebContentsDelegate::GetDevToolsWindowIcon() {
if (!owner_window())
return gfx::ImageSkia();
return static_cast<views::WidgetDelegate*>(
static_cast<NativeWindowViews*>(owner_window()))
->GetWindowAppIcon();
}
#if defined(OS_LINUX)
void CommonWebContentsDelegate::GetDevToolsWindowWMClass(
std::string* name,
std::string* class_name) {
*class_name = Browser::Get()->GetName();
*name = base::ToLowerASCII(*class_name);
}
#endif
} // namespace electron