refactor: move JS dialog handling to JS (#40598)
This commit is contained in:
parent
ee8d97d7fe
commit
85bc005cd6
8 changed files with 302 additions and 200 deletions
|
@ -88,7 +88,6 @@
|
|||
#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"
|
||||
#include "shell/browser/file_select_helper.h"
|
||||
#include "shell/browser/native_window.h"
|
||||
|
@ -263,6 +262,21 @@ struct Converter<WindowOpenDisposition> {
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<content::JavaScriptDialogType> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
content::JavaScriptDialogType val) {
|
||||
switch (val) {
|
||||
case content::JAVASCRIPT_DIALOG_TYPE_ALERT:
|
||||
return gin::ConvertToV8(isolate, "alert");
|
||||
case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM:
|
||||
return gin::ConvertToV8(isolate, "confirm");
|
||||
case content::JAVASCRIPT_DIALOG_TYPE_PROMPT:
|
||||
return gin::ConvertToV8(isolate, "prompt");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<content::SavePageType> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
|
@ -1587,10 +1601,7 @@ void WebContents::RequestMediaAccessPermission(
|
|||
|
||||
content::JavaScriptDialogManager* WebContents::GetJavaScriptDialogManager(
|
||||
content::WebContents* source) {
|
||||
if (!dialog_manager_)
|
||||
dialog_manager_ = std::make_unique<ElectronJavaScriptDialogManager>();
|
||||
|
||||
return dialog_manager_.get();
|
||||
return this;
|
||||
}
|
||||
|
||||
void WebContents::OnAudioStateChanged(bool audible) {
|
||||
|
@ -3747,6 +3758,45 @@ void WebContents::OnInputEvent(const blink::WebInputEvent& event) {
|
|||
Emit("input-event", event);
|
||||
}
|
||||
|
||||
void WebContents::RunJavaScriptDialog(content::WebContents* web_contents,
|
||||
content::RenderFrameHost* rfh,
|
||||
content::JavaScriptDialogType dialog_type,
|
||||
const std::u16string& message_text,
|
||||
const std::u16string& default_prompt_text,
|
||||
DialogClosedCallback callback,
|
||||
bool* did_suppress_message) {
|
||||
CHECK_EQ(web_contents, this->web_contents());
|
||||
|
||||
auto* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
auto info = gin::DataObjectBuilder(isolate)
|
||||
.Set("frame", rfh)
|
||||
.Set("dialogType", dialog_type)
|
||||
.Set("messageText", message_text)
|
||||
.Set("defaultPromptText", default_prompt_text)
|
||||
.Build();
|
||||
|
||||
EmitWithoutEvent("-run-dialog", info, std::move(callback));
|
||||
}
|
||||
|
||||
void WebContents::RunBeforeUnloadDialog(content::WebContents* web_contents,
|
||||
content::RenderFrameHost* rfh,
|
||||
bool is_reload,
|
||||
DialogClosedCallback callback) {
|
||||
// TODO: asyncify?
|
||||
bool default_prevented = Emit("will-prevent-unload");
|
||||
std::move(callback).Run(default_prevented, std::u16string());
|
||||
}
|
||||
|
||||
void WebContents::CancelDialogs(content::WebContents* web_contents,
|
||||
bool reset_state) {
|
||||
auto* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
EmitWithoutEvent(
|
||||
"-cancel-dialogs",
|
||||
gin::DataObjectBuilder(isolate).Set("resetState", reset_state).Build());
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> WebContents::GetProcessMemoryInfo(v8::Isolate* isolate) {
|
||||
gin_helper::Promise<gin_helper::Dictionary> promise(isolate);
|
||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
|
||||
#include "content/common/frame.mojom.h"
|
||||
#include "content/public/browser/devtools_agent_host.h"
|
||||
#include "content/public/browser/javascript_dialog_manager.h"
|
||||
#include "content/public/browser/keyboard_event_processing_result.h"
|
||||
#include "content/public/browser/render_widget_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
@ -85,7 +86,6 @@ class SkRegion;
|
|||
namespace electron {
|
||||
|
||||
class ElectronBrowserContext;
|
||||
class ElectronJavaScriptDialogManager;
|
||||
class InspectableWebContents;
|
||||
class WebContentsZoomController;
|
||||
class WebViewGuestDelegate;
|
||||
|
@ -107,6 +107,7 @@ class WebContents : public ExclusiveAccessContext,
|
|||
public content::WebContentsObserver,
|
||||
public content::WebContentsDelegate,
|
||||
public content::RenderWidgetHost::InputEventObserver,
|
||||
public content::JavaScriptDialogManager,
|
||||
public InspectableWebContentsDelegate,
|
||||
public InspectableWebContentsViewDelegate,
|
||||
public BackgroundThrottlingSource {
|
||||
|
@ -453,6 +454,21 @@ class WebContents : public ExclusiveAccessContext,
|
|||
// content::RenderWidgetHost::InputEventObserver:
|
||||
void OnInputEvent(const blink::WebInputEvent& event) override;
|
||||
|
||||
// content::JavaScriptDialogManager:
|
||||
void RunJavaScriptDialog(content::WebContents* web_contents,
|
||||
content::RenderFrameHost* rfh,
|
||||
content::JavaScriptDialogType dialog_type,
|
||||
const std::u16string& message_text,
|
||||
const std::u16string& default_prompt_text,
|
||||
DialogClosedCallback callback,
|
||||
bool* did_suppress_message) override;
|
||||
void RunBeforeUnloadDialog(content::WebContents* web_contents,
|
||||
content::RenderFrameHost* rfh,
|
||||
bool is_reload,
|
||||
DialogClosedCallback callback) override;
|
||||
void CancelDialogs(content::WebContents* web_contents,
|
||||
bool reset_state) override;
|
||||
|
||||
SkRegion* draggable_region() {
|
||||
return force_non_draggable_ ? nullptr : draggable_region_.get();
|
||||
}
|
||||
|
@ -762,7 +778,6 @@ class WebContents : public ExclusiveAccessContext,
|
|||
v8::Global<v8::Value> devtools_web_contents_;
|
||||
v8::Global<v8::Value> debugger_;
|
||||
|
||||
std::unique_ptr<ElectronJavaScriptDialogManager> dialog_manager_;
|
||||
std::unique_ptr<WebViewGuestDelegate> guest_delegate_;
|
||||
std::unique_ptr<FrameSubscriber> frame_subscriber_;
|
||||
|
||||
|
|
|
@ -1,137 +0,0 @@
|
|||
// Copyright (c) 2013 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/electron_javascript_dialog_manager.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/native_window.h"
|
||||
#include "shell/browser/ui/message_box.h"
|
||||
#include "shell/browser/web_contents_preferences.h"
|
||||
#include "shell/common/options_switches.h"
|
||||
#include "ui/gfx/image/image_skia.h"
|
||||
|
||||
using content::JavaScriptDialogType;
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kUserWantsNoMoreDialogs = -1;
|
||||
|
||||
} // namespace
|
||||
|
||||
ElectronJavaScriptDialogManager::ElectronJavaScriptDialogManager() = default;
|
||||
ElectronJavaScriptDialogManager::~ElectronJavaScriptDialogManager() = default;
|
||||
|
||||
void ElectronJavaScriptDialogManager::RunJavaScriptDialog(
|
||||
content::WebContents* web_contents,
|
||||
content::RenderFrameHost* rfh,
|
||||
JavaScriptDialogType dialog_type,
|
||||
const std::u16string& message_text,
|
||||
const std::u16string& default_prompt_text,
|
||||
DialogClosedCallback callback,
|
||||
bool* did_suppress_message) {
|
||||
auto origin_url = rfh->GetLastCommittedURL();
|
||||
|
||||
std::string origin;
|
||||
// For file:// URLs we do the alert filtering by the
|
||||
// file path currently loaded
|
||||
if (origin_url.SchemeIsFile()) {
|
||||
origin = origin_url.path();
|
||||
} else {
|
||||
origin = origin_url.DeprecatedGetOriginAsURL().spec();
|
||||
}
|
||||
|
||||
if (origin_counts_[origin] == kUserWantsNoMoreDialogs) {
|
||||
return std::move(callback).Run(false, std::u16string());
|
||||
}
|
||||
|
||||
if (dialog_type != JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_ALERT &&
|
||||
dialog_type != JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_CONFIRM) {
|
||||
std::move(callback).Run(false, std::u16string());
|
||||
return;
|
||||
}
|
||||
|
||||
auto* web_preferences = WebContentsPreferences::From(web_contents);
|
||||
|
||||
if (web_preferences && web_preferences->ShouldDisableDialogs()) {
|
||||
return std::move(callback).Run(false, std::u16string());
|
||||
}
|
||||
|
||||
// No default button
|
||||
int default_id = -1;
|
||||
int cancel_id = 0;
|
||||
|
||||
std::vector<std::string> buttons = {"OK"};
|
||||
if (dialog_type == JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_CONFIRM) {
|
||||
buttons.emplace_back("Cancel");
|
||||
// First button is default, second button is cancel
|
||||
default_id = 0;
|
||||
cancel_id = 1;
|
||||
}
|
||||
|
||||
origin_counts_[origin]++;
|
||||
|
||||
std::string checkbox;
|
||||
if (origin_counts_[origin] > 1 && web_preferences &&
|
||||
web_preferences->ShouldUseSafeDialogs() &&
|
||||
!web_preferences->GetSafeDialogsMessage(&checkbox)) {
|
||||
checkbox = "Prevent this app from creating additional dialogs";
|
||||
}
|
||||
|
||||
// Don't set parent for offscreen window.
|
||||
NativeWindow* window = nullptr;
|
||||
if (web_preferences && !web_preferences->IsOffscreen()) {
|
||||
auto* relay = NativeWindowRelay::FromWebContents(web_contents);
|
||||
if (relay)
|
||||
window = relay->GetNativeWindow();
|
||||
}
|
||||
|
||||
electron::MessageBoxSettings settings;
|
||||
settings.parent_window = window;
|
||||
settings.checkbox_label = checkbox;
|
||||
settings.buttons = buttons;
|
||||
settings.default_id = default_id;
|
||||
settings.cancel_id = cancel_id;
|
||||
settings.message = base::UTF16ToUTF8(message_text);
|
||||
|
||||
electron::ShowMessageBox(
|
||||
settings,
|
||||
base::BindOnce(&ElectronJavaScriptDialogManager::OnMessageBoxCallback,
|
||||
base::Unretained(this), std::move(callback), origin));
|
||||
}
|
||||
|
||||
void ElectronJavaScriptDialogManager::RunBeforeUnloadDialog(
|
||||
content::WebContents* web_contents,
|
||||
content::RenderFrameHost* rfh,
|
||||
bool is_reload,
|
||||
DialogClosedCallback callback) {
|
||||
auto* api_web_contents = api::WebContents::From(web_contents);
|
||||
if (api_web_contents) {
|
||||
bool default_prevented = api_web_contents->Emit("will-prevent-unload");
|
||||
std::move(callback).Run(default_prevented, std::u16string());
|
||||
}
|
||||
}
|
||||
|
||||
void ElectronJavaScriptDialogManager::CancelDialogs(
|
||||
content::WebContents* web_contents,
|
||||
bool reset_state) {}
|
||||
|
||||
void ElectronJavaScriptDialogManager::OnMessageBoxCallback(
|
||||
DialogClosedCallback callback,
|
||||
const std::string& origin,
|
||||
int code,
|
||||
bool checkbox_checked) {
|
||||
if (checkbox_checked)
|
||||
origin_counts_[origin] = kUserWantsNoMoreDialogs;
|
||||
std::move(callback).Run(code == 0, std::u16string());
|
||||
}
|
||||
|
||||
} // namespace electron
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright (c) 2013 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_ELECTRON_JAVASCRIPT_DIALOG_MANAGER_H_
|
||||
#define ELECTRON_SHELL_BROWSER_ELECTRON_JAVASCRIPT_DIALOG_MANAGER_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "content/public/browser/javascript_dialog_manager.h"
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace electron {
|
||||
|
||||
class ElectronJavaScriptDialogManager
|
||||
: public content::JavaScriptDialogManager {
|
||||
public:
|
||||
ElectronJavaScriptDialogManager();
|
||||
~ElectronJavaScriptDialogManager() override;
|
||||
|
||||
// content::JavaScriptDialogManager implementations.
|
||||
void RunJavaScriptDialog(content::WebContents* web_contents,
|
||||
content::RenderFrameHost* rfh,
|
||||
content::JavaScriptDialogType dialog_type,
|
||||
const std::u16string& message_text,
|
||||
const std::u16string& default_prompt_text,
|
||||
DialogClosedCallback callback,
|
||||
bool* did_suppress_message) override;
|
||||
void RunBeforeUnloadDialog(content::WebContents* web_contents,
|
||||
content::RenderFrameHost* rfh,
|
||||
bool is_reload,
|
||||
DialogClosedCallback callback) override;
|
||||
void CancelDialogs(content::WebContents* web_contents,
|
||||
bool reset_state) override;
|
||||
|
||||
private:
|
||||
void OnMessageBoxCallback(DialogClosedCallback callback,
|
||||
const std::string& origin,
|
||||
int code,
|
||||
bool checkbox_checked);
|
||||
|
||||
std::map<std::string, int> origin_counts_;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_ELECTRON_JAVASCRIPT_DIALOG_MANAGER_H_
|
|
@ -391,6 +391,9 @@ void WebContentsPreferences::SaveLastPreferences() {
|
|||
allow_running_insecure_content_);
|
||||
dict.Set(options::kExperimentalFeatures, experimental_features_);
|
||||
dict.Set(options::kEnableBlinkFeatures, enable_blink_features_.value_or(""));
|
||||
dict.Set("disableDialogs", disable_dialogs_);
|
||||
dict.Set("safeDialogs", safe_dialogs_);
|
||||
dict.Set("safeDialogsMessage", safe_dialogs_message_.value_or(""));
|
||||
|
||||
last_web_preferences_ = base::Value(std::move(dict));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue