Commit ad57375e authored by Sam McNally's avatar Sam McNally Committed by Commit Bot

Add support for beforeunload for mime handler guests.

QuickOffice uses beforeunload events. When running inside a mime
handler, these beforeunload event handlers are ignored. Add a
beforeunload event handler to PluginDocument when a plugin requires it.

This event handler is controlled over a mojo interface, exposed to the
mime handler as chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog().

Bug: 819761
Cq-Include-Trybots: luci.chromium.try:closure_compilation
Change-Id: Ieb61cf98ce2bf719fc128499f8d0e57d8fe7ad33
Reviewed-on: https://chromium-review.googlesource.com/1139946
Commit-Queue: Sam McNally <sammc@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#576283}
parent 5c9266c5
...@@ -91,6 +91,7 @@ ...@@ -91,6 +91,7 @@
"dom_distiller.mojom.DistillabilityService", "dom_distiller.mojom.DistillabilityService",
"dom_distiller.mojom.DistillerJavaScriptService", "dom_distiller.mojom.DistillerJavaScriptService",
"extensions.KeepAlive", "extensions.KeepAlive",
"extensions.mime_handler.BeforeUnloadControl",
"extensions.mime_handler.MimeHandlerService", "extensions.mime_handler.MimeHandlerService",
"extensions.mojom.InlineInstall", "extensions.mojom.InlineInstall",
"media_router.mojom.MediaRouter", "media_router.mojom.MediaRouter",
......
...@@ -118,7 +118,7 @@ var tests = [ ...@@ -118,7 +118,7 @@ var tests = [
} else if (event.data == expectedMessages[messagesReceived]) { } else if (event.data == expectedMessages[messagesReceived]) {
event.source.postMessage(event.data, '*'); event.source.postMessage(event.data, '*');
messagesReceived++; messagesReceived++;
} else { } else if (event.data != 'initBeforeUnload') {
chrome.test.fail('unexpected message ' + event.data); chrome.test.fail('unexpected message ' + event.data);
} }
} }
...@@ -246,6 +246,18 @@ var tests = [ ...@@ -246,6 +246,18 @@ var tests = [
anchor.click(); anchor.click();
chrome.test.succeed(); chrome.test.succeed();
}, },
function testBeforeUnloadNoDialog() {
checkStreamDetails('testBeforeUnloadNoDialog.csv', false);
chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog(false);
chrome.test.succeed();
},
function testBeforeUnloadShowDialog() {
checkStreamDetails('testBeforeUnloadShowDialog.csv', false);
chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog(true);
chrome.test.succeed();
},
]; ];
var testsByName = {}; var testsByName = {};
......
...@@ -284,6 +284,7 @@ source_set("chrome_extensions_browsertests") { ...@@ -284,6 +284,7 @@ source_set("chrome_extensions_browsertests") {
"//chrome/browser", "//chrome/browser",
"//chrome/common/extensions/api", "//chrome/common/extensions/api",
"//chrome/renderer", "//chrome/renderer",
"//components/app_modal",
"//components/autofill/content/browser:risk_proto", "//components/autofill/content/browser:risk_proto",
"//components/autofill/content/renderer:test_support", "//components/autofill/content/renderer:test_support",
"//components/captive_portal:test_support", "//components/captive_portal:test_support",
......
...@@ -42,6 +42,7 @@ include_rules = [ ...@@ -42,6 +42,7 @@ include_rules = [
specific_include_rules = { specific_include_rules = {
".*(test|test_util)\.(cc|h)$": [ ".*(test|test_util)\.(cc|h)$": [
"+components/app_modal",
"+components/user_prefs", "+components/user_prefs",
"+storage/browser/test", "+storage/browser/test",
......
...@@ -56,7 +56,6 @@ void ExtensionsGuestViewMessageFilter::OverrideThreadForMessage( ...@@ -56,7 +56,6 @@ void ExtensionsGuestViewMessageFilter::OverrideThreadForMessage(
const IPC::Message& message, const IPC::Message& message,
BrowserThread::ID* thread) { BrowserThread::ID* thread) {
switch (message.type()) { switch (message.type()) {
case ExtensionsGuestViewHostMsg_CreateMimeHandlerViewGuest::ID:
case ExtensionsGuestViewHostMsg_ResizeGuest::ID: case ExtensionsGuestViewHostMsg_ResizeGuest::ID:
*thread = BrowserThread::UI; *thread = BrowserThread::UI;
break; break;
...@@ -71,8 +70,6 @@ bool ExtensionsGuestViewMessageFilter::OnMessageReceived( ...@@ -71,8 +70,6 @@ bool ExtensionsGuestViewMessageFilter::OnMessageReceived(
IPC_BEGIN_MESSAGE_MAP(ExtensionsGuestViewMessageFilter, message) IPC_BEGIN_MESSAGE_MAP(ExtensionsGuestViewMessageFilter, message)
IPC_MESSAGE_HANDLER(ExtensionsGuestViewHostMsg_CanExecuteContentScriptSync, IPC_MESSAGE_HANDLER(ExtensionsGuestViewHostMsg_CanExecuteContentScriptSync,
OnCanExecuteContentScript) OnCanExecuteContentScript)
IPC_MESSAGE_HANDLER(ExtensionsGuestViewHostMsg_CreateMimeHandlerViewGuest,
OnCreateMimeHandlerViewGuest)
IPC_MESSAGE_HANDLER(ExtensionsGuestViewHostMsg_ResizeGuest, OnResizeGuest) IPC_MESSAGE_HANDLER(ExtensionsGuestViewHostMsg_ResizeGuest, OnResizeGuest)
IPC_MESSAGE_UNHANDLED( IPC_MESSAGE_UNHANDLED(
handled = GuestViewMessageFilter::OnMessageReceived(message)) handled = GuestViewMessageFilter::OnMessageReceived(message))
...@@ -104,11 +101,26 @@ void ExtensionsGuestViewMessageFilter::OnCanExecuteContentScript( ...@@ -104,11 +101,26 @@ void ExtensionsGuestViewMessageFilter::OnCanExecuteContentScript(
info.content_script_ids.find(script_id) != info.content_script_ids.end(); info.content_script_ids.find(script_id) != info.content_script_ids.end();
} }
void ExtensionsGuestViewMessageFilter::OnCreateMimeHandlerViewGuest( void ExtensionsGuestViewMessageFilter::CreateMimeHandlerViewGuest(
int32_t render_frame_id,
const std::string& view_id,
int32_t element_instance_id,
const gfx::Size& element_size,
mime_handler::BeforeUnloadControlPtr before_unload_control) {
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::BindOnce(&ExtensionsGuestViewMessageFilter::
CreateMimeHandlerViewGuestOnUIThread,
this, render_frame_id, view_id, element_instance_id,
element_size, before_unload_control.PassInterface()));
}
void ExtensionsGuestViewMessageFilter::CreateMimeHandlerViewGuestOnUIThread(
int render_frame_id, int render_frame_id,
const std::string& view_id, const std::string& view_id,
int element_instance_id, int element_instance_id,
const gfx::Size& element_size) { const gfx::Size& element_size,
mime_handler::BeforeUnloadControlPtrInfo before_unload_control) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto* manager = GetOrCreateGuestViewManager(); auto* manager = GetOrCreateGuestViewManager();
...@@ -120,7 +132,7 @@ void ExtensionsGuestViewMessageFilter::OnCreateMimeHandlerViewGuest( ...@@ -120,7 +132,7 @@ void ExtensionsGuestViewMessageFilter::OnCreateMimeHandlerViewGuest(
GuestViewManager::WebContentsCreatedCallback callback = base::BindOnce( GuestViewManager::WebContentsCreatedCallback callback = base::BindOnce(
&ExtensionsGuestViewMessageFilter::MimeHandlerViewGuestCreatedCallback, &ExtensionsGuestViewMessageFilter::MimeHandlerViewGuestCreatedCallback,
this, element_instance_id, render_process_id_, render_frame_id, this, element_instance_id, render_process_id_, render_frame_id,
element_size); element_size, std::move(before_unload_control));
base::DictionaryValue create_params; base::DictionaryValue create_params;
create_params.SetString(mime_handler_view::kViewId, view_id); create_params.SetString(mime_handler_view::kViewId, view_id);
...@@ -203,8 +215,8 @@ void ExtensionsGuestViewMessageFilter::CreateEmbeddedMimeHandlerViewGuest( ...@@ -203,8 +215,8 @@ void ExtensionsGuestViewMessageFilter::CreateEmbeddedMimeHandlerViewGuest(
-1 /* frame_tree_node_id*/, render_process_id_, -1 /* frame_tree_node_id*/, render_process_id_,
render_frame_id); render_frame_id);
OnCreateMimeHandlerViewGuest(render_frame_id, view_id, element_instance_id, CreateMimeHandlerViewGuestOnUIThread(
element_size); render_frame_id, view_id, element_instance_id, element_size, nullptr);
} }
void ExtensionsGuestViewMessageFilter::MimeHandlerViewGuestCreatedCallback( void ExtensionsGuestViewMessageFilter::MimeHandlerViewGuestCreatedCallback(
...@@ -212,11 +224,13 @@ void ExtensionsGuestViewMessageFilter::MimeHandlerViewGuestCreatedCallback( ...@@ -212,11 +224,13 @@ void ExtensionsGuestViewMessageFilter::MimeHandlerViewGuestCreatedCallback(
int embedder_render_process_id, int embedder_render_process_id,
int embedder_render_frame_id, int embedder_render_frame_id,
const gfx::Size& element_size, const gfx::Size& element_size,
mime_handler::BeforeUnloadControlPtrInfo before_unload_control,
WebContents* web_contents) { WebContents* web_contents) {
auto* guest_view = MimeHandlerViewGuest::FromWebContents(web_contents); auto* guest_view = MimeHandlerViewGuest::FromWebContents(web_contents);
if (!guest_view) if (!guest_view)
return; return;
guest_view->SetBeforeUnloadController(std::move(before_unload_control));
int guest_instance_id = guest_view->guest_instance_id(); int guest_instance_id = guest_view->guest_instance_id();
auto* rfh = RenderFrameHost::FromID(embedder_render_process_id, auto* rfh = RenderFrameHost::FromID(embedder_render_process_id,
embedder_render_frame_id); embedder_render_frame_id);
......
...@@ -76,13 +76,28 @@ class ExtensionsGuestViewMessageFilter ...@@ -76,13 +76,28 @@ class ExtensionsGuestViewMessageFilter
const gfx::Size& element_size, const gfx::Size& element_size,
content::mojom::TransferrableURLLoaderPtr transferrable_url_loader) content::mojom::TransferrableURLLoaderPtr transferrable_url_loader)
override; override;
void CreateMimeHandlerViewGuest(
int32_t render_frame_id,
const std::string& view_id,
int32_t element_instance_id,
const gfx::Size& element_size,
mime_handler::BeforeUnloadControlPtr before_unload_control) override;
void CreateMimeHandlerViewGuestOnUIThread(
int32_t render_frame_id,
const std::string& view_id,
int32_t element_instance_id,
const gfx::Size& element_size,
mime_handler::BeforeUnloadControlPtrInfo before_unload_control);
// Runs on UI thread. // Runs on UI thread.
void MimeHandlerViewGuestCreatedCallback(int element_instance_id, void MimeHandlerViewGuestCreatedCallback(
int embedder_render_process_id, int element_instance_id,
int embedder_render_frame_id, int embedder_render_process_id,
const gfx::Size& element_size, int embedder_render_frame_id,
content::WebContents* web_contents); const gfx::Size& element_size,
mime_handler::BeforeUnloadControlPtrInfo before_unload_control,
content::WebContents* web_contents);
static const uint32_t kFilteredMessageClasses[]; static const uint32_t kFilteredMessageClasses[];
......
...@@ -11,8 +11,10 @@ ...@@ -11,8 +11,10 @@
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h" #include "chrome/test/base/ui_test_utils.h"
#include "components/app_modal/javascript_app_modal_dialog.h"
#include "components/guest_view/browser/test_guest_view_manager.h" #include "components/guest_view/browser/test_guest_view_manager.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h" #include "content/public/common/content_features.h"
...@@ -230,3 +232,27 @@ IN_PROC_BROWSER_TEST_P(MimeHandlerViewTest, TargetBlankAnchor) { ...@@ -230,3 +232,27 @@ IN_PROC_BROWSER_TEST_P(MimeHandlerViewTest, TargetBlankAnchor) {
GURL("about:blank"), GURL("about:blank"),
browser()->tab_strip_model()->GetWebContentsAt(1)->GetLastCommittedURL()); browser()->tab_strip_model()->GetWebContentsAt(1)->GetLastCommittedURL());
} }
IN_PROC_BROWSER_TEST_P(MimeHandlerViewTest, BeforeUnload_NoDialog) {
ASSERT_NO_FATAL_FAILURE(RunTest("testBeforeUnloadNoDialog.csv"));
content::PrepContentsForBeforeUnloadTest(
browser()->tab_strip_model()->GetWebContentsAt(0));
// Try to navigate away from the page. If the beforeunload listener is
// triggered and a dialog is shown, this navigation will never complete,
// causing the test to timeout and fail.
ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
}
IN_PROC_BROWSER_TEST_P(MimeHandlerViewTest, BeforeUnload_ShowDialog) {
ASSERT_NO_FATAL_FAILURE(RunTest("testBeforeUnloadShowDialog.csv"));
auto* web_contents = browser()->tab_strip_model()->GetWebContentsAt(0);
content::PrepContentsForBeforeUnloadTest(web_contents);
web_contents->GetController().Reload(content::ReloadType::NORMAL, false);
app_modal::JavaScriptAppModalDialog* before_unload_dialog =
ui_test_utils::WaitForAppModalDialog();
EXPECT_TRUE(before_unload_dialog->is_before_unload_dialog());
EXPECT_TRUE(before_unload_dialog->is_reload());
before_unload_dialog->OnAccept(base::string16(), false);
}
...@@ -140,6 +140,11 @@ void MimeHandlerViewGuest::SetEmbedderFrame(int process_id, int routing_id) { ...@@ -140,6 +140,11 @@ void MimeHandlerViewGuest::SetEmbedderFrame(int process_id, int routing_id) {
DCHECK_NE(MSG_ROUTING_NONE, embedder_widget_routing_id_); DCHECK_NE(MSG_ROUTING_NONE, embedder_widget_routing_id_);
} }
void MimeHandlerViewGuest::SetBeforeUnloadController(
mime_handler::BeforeUnloadControlPtrInfo pending_before_unload_control) {
pending_before_unload_control_ = std::move(pending_before_unload_control);
}
const char* MimeHandlerViewGuest::GetAPINamespace() const { const char* MimeHandlerViewGuest::GetAPINamespace() const {
return "mimeHandlerViewGuestInternal"; return "mimeHandlerViewGuestInternal";
} }
...@@ -203,6 +208,8 @@ void MimeHandlerViewGuest::CreateWebContents( ...@@ -203,6 +208,8 @@ void MimeHandlerViewGuest::CreateWebContents(
registry_.AddInterface( registry_.AddInterface(
base::Bind(&MimeHandlerServiceImpl::Create, stream_->GetWeakPtr())); base::Bind(&MimeHandlerServiceImpl::Create, stream_->GetWeakPtr()));
registry_.AddInterface(base::BindRepeating(
&MimeHandlerViewGuest::FuseBeforeUnloadControl, base::Unretained(this)));
} }
void MimeHandlerViewGuest::DidAttachToEmbedder() { void MimeHandlerViewGuest::DidAttachToEmbedder() {
...@@ -394,4 +401,13 @@ void MimeHandlerViewGuest::ReadyToCommitNavigation( ...@@ -394,4 +401,13 @@ void MimeHandlerViewGuest::ReadyToCommitNavigation(
stream_->TakeTransferrableURLLoader()); stream_->TakeTransferrableURLLoader());
} }
void MimeHandlerViewGuest::FuseBeforeUnloadControl(
mime_handler::BeforeUnloadControlRequest request) {
if (!pending_before_unload_control_)
return;
mojo::FuseInterface(std::move(request),
std::move(pending_before_unload_control_));
}
} // namespace extensions } // namespace extensions
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "components/guest_view/browser/guest_view.h" #include "components/guest_view/browser/guest_view.h"
#include "content/public/common/transferrable_url_loader.mojom.h" #include "content/public/common/transferrable_url_loader.mojom.h"
#include "extensions/common/api/mime_handler.mojom.h"
#include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/binder_registry.h"
namespace content { namespace content {
...@@ -74,8 +75,8 @@ class StreamContainer { ...@@ -74,8 +75,8 @@ class StreamContainer {
DISALLOW_COPY_AND_ASSIGN(StreamContainer); DISALLOW_COPY_AND_ASSIGN(StreamContainer);
}; };
class MimeHandlerViewGuest : class MimeHandlerViewGuest
public guest_view::GuestView<MimeHandlerViewGuest> { : public guest_view::GuestView<MimeHandlerViewGuest> {
public: public:
static guest_view::GuestViewBase* Create( static guest_view::GuestViewBase* Create(
content::WebContents* owner_web_contents); content::WebContents* owner_web_contents);
...@@ -90,6 +91,9 @@ class MimeHandlerViewGuest : ...@@ -90,6 +91,9 @@ class MimeHandlerViewGuest :
void SetEmbedderFrame(int process_id, int routing_id); void SetEmbedderFrame(int process_id, int routing_id);
void SetBeforeUnloadController(
mime_handler::BeforeUnloadControlPtrInfo pending_before_unload_control);
protected: protected:
explicit MimeHandlerViewGuest(content::WebContents* owner_web_contents); explicit MimeHandlerViewGuest(content::WebContents* owner_web_contents);
~MimeHandlerViewGuest() override; ~MimeHandlerViewGuest() override;
...@@ -155,6 +159,9 @@ class MimeHandlerViewGuest : ...@@ -155,6 +159,9 @@ class MimeHandlerViewGuest :
void ReadyToCommitNavigation( void ReadyToCommitNavigation(
content::NavigationHandle* navigation_handle) final; content::NavigationHandle* navigation_handle) final;
void FuseBeforeUnloadControl(
mime_handler::BeforeUnloadControlRequest request);
std::unique_ptr<MimeHandlerViewGuestDelegate> delegate_; std::unique_ptr<MimeHandlerViewGuestDelegate> delegate_;
std::unique_ptr<StreamContainer> stream_; std::unique_ptr<StreamContainer> stream_;
...@@ -167,6 +174,8 @@ class MimeHandlerViewGuest : ...@@ -167,6 +174,8 @@ class MimeHandlerViewGuest :
bool is_guest_fullscreen_ = false; bool is_guest_fullscreen_ = false;
bool is_embedder_fullscreen_ = false; bool is_embedder_fullscreen_ = false;
mime_handler::BeforeUnloadControlPtrInfo pending_before_unload_control_;
DISALLOW_COPY_AND_ASSIGN(MimeHandlerViewGuest); DISALLOW_COPY_AND_ASSIGN(MimeHandlerViewGuest);
}; };
......
...@@ -42,6 +42,7 @@ if (enable_extensions) { ...@@ -42,6 +42,7 @@ if (enable_extensions) {
public_deps = [ public_deps = [
"//content/public/common:interfaces", "//content/public/common:interfaces",
"//extensions/common/api:mojom",
"//mojo/public/mojom/base", "//mojo/public/mojom/base",
"//ui/gfx/geometry/mojo", "//ui/gfx/geometry/mojo",
"//url/mojom:url_mojom_gurl", "//url/mojom:url_mojom_gurl",
......
...@@ -6,4 +6,7 @@ per-file *.idl=file://extensions/common/api/API_OWNERS ...@@ -6,4 +6,7 @@ per-file *.idl=file://extensions/common/api/API_OWNERS
per-file *view*.json=file://components/guest_view/OWNERS per-file *view*.json=file://components/guest_view/OWNERS
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
# COMPONENT: Platform>Extensions>API # COMPONENT: Platform>Extensions>API
...@@ -37,4 +37,18 @@ interface MimeHandlerService { ...@@ -37,4 +37,18 @@ interface MimeHandlerService {
// Aborts the stream associated with this service instance. This is an // Aborts the stream associated with this service instance. This is an
// idempotent operation. // idempotent operation.
AbortStream() => (); AbortStream() => ();
};
// Provides a mime handler guest with control over beforeunload event handling
// when running in a PluginDocument.
//
// For full-frame mime handler guests, an instance of this interface is passed
// from the embedding renderer to the browser when creating the mime handler
// guest. If the frame hosting the guest requests this interface from the
// browser, that instance is provided to the guest.
interface BeforeUnloadControl {
// Instructs the containing PluginDocument whether to show a beforeunload
// dialog.
SetShowBeforeUnloadDialog(bool show_dialog) => ();
}; };
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
callback AbortCallback = void (); callback AbortCallback = void ();
callback GetStreamDetailsCallback = void (StreamInfo streamInfo); callback GetStreamDetailsCallback = void (StreamInfo streamInfo);
callback SetShowBeforeUnloadDialogCallback = void ();
interface Functions { interface Functions {
// Returns the StreamInfo for the stream for this context if there is one. // Returns the StreamInfo for the stream for this context if there is one.
...@@ -37,5 +38,11 @@ ...@@ -37,5 +38,11 @@
// Aborts the stream for this context if there is one. // Aborts the stream for this context if there is one.
[nocompile] static void abortStream(optional AbortCallback callback); [nocompile] static void abortStream(optional AbortCallback callback);
// Instructs the PluginDocument, if running in one, to show a dialog in
// response to beforeunload events.
[nocompile] static void setShowBeforeUnloadDialog(
boolean showDialog,
optional SetShowBeforeUnloadDialogCallback callback);
}; };
}; };
...@@ -35,13 +35,6 @@ IPC_SYNC_MESSAGE_CONTROL2_1( ...@@ -35,13 +35,6 @@ IPC_SYNC_MESSAGE_CONTROL2_1(
int /* script_id */, int /* script_id */,
bool /* allowed */) bool /* allowed */)
// Tells the browser to create a mime handler guest view for a plugin.
IPC_MESSAGE_CONTROL4(ExtensionsGuestViewHostMsg_CreateMimeHandlerViewGuest,
int /* render_frame_id */,
std::string /* view_id */,
int /* element_instance_id */,
gfx::Size /* element_size */)
// A renderer sends this message when it wants to resize a guest. // A renderer sends this message when it wants to resize a guest.
IPC_MESSAGE_CONTROL3(ExtensionsGuestViewHostMsg_ResizeGuest, IPC_MESSAGE_CONTROL3(ExtensionsGuestViewHostMsg_ResizeGuest,
int /* routing_id */, int /* routing_id */,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
module extensions.mojom; module extensions.mojom;
import "content/public/common/transferrable_url_loader.mojom"; import "content/public/common/transferrable_url_loader.mojom";
import "extensions/common/api/mime_handler.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom";
import "url/mojom/url.mojom"; import "url/mojom/url.mojom";
...@@ -19,4 +20,14 @@ interface GuestView { ...@@ -19,4 +20,14 @@ interface GuestView {
int32 element_instance_id, int32 element_instance_id,
gfx.mojom.Size element_size, gfx.mojom.Size element_size,
content.mojom.TransferrableURLLoader transferrable_url_loader); content.mojom.TransferrableURLLoader transferrable_url_loader);
// Tells the browser to create a mime handler guest view for a plugin.
// This method is called for full-frame plugins or for all plugins when the
// network service is disabled.
CreateMimeHandlerViewGuest(
int32 render_frame_id,
string view_id,
int32 element_instance_id,
gfx.mojom.Size element_size,
extensions.mime_handler.BeforeUnloadControl? before_unload_control);
}; };
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "third_party/blink/public/web/web_associated_url_loader_options.h" #include "third_party/blink/public/web/web_associated_url_loader_options.h"
#include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_plugin_document.h"
#include "third_party/blink/public/web/web_remote_frame.h" #include "third_party/blink/public/web/web_remote_frame.h"
#include "third_party/blink/public/web/web_view.h" #include "third_party/blink/public/web/web_view.h"
...@@ -179,6 +180,7 @@ MimeHandlerViewContainer::MimeHandlerViewContainer( ...@@ -179,6 +180,7 @@ MimeHandlerViewContainer::MimeHandlerViewContainer(
original_url_(original_url), original_url_(original_url),
guest_proxy_routing_id_(-1), guest_proxy_routing_id_(-1),
guest_loaded_(false), guest_loaded_(false),
before_unload_control_binding_(this),
weak_factory_(this) { weak_factory_(this) {
DCHECK(!mime_type_.empty()); DCHECK(!mime_type_.empty());
is_embedded_ = !render_frame->GetWebFrame()->GetDocument().IsPluginDocument(); is_embedded_ = !render_frame->GetWebFrame()->GetDocument().IsPluginDocument();
...@@ -441,12 +443,28 @@ void MimeHandlerViewContainer::CreateMimeHandlerViewGuestIfNecessary() { ...@@ -441,12 +443,28 @@ void MimeHandlerViewContainer::CreateMimeHandlerViewGuestIfNecessary() {
if (!render_frame()) if (!render_frame())
return; return;
render_frame()->Send( mime_handler::BeforeUnloadControlPtr before_unload_control;
new ExtensionsGuestViewHostMsg_CreateMimeHandlerViewGuest( if (!is_embedded_) {
render_frame()->GetRoutingID(), view_id_, element_instance_id(), before_unload_control_binding_.Bind(
*element_size_)); mojo::MakeRequest(&before_unload_control));
}
GetGuestView()->CreateMimeHandlerViewGuest(
render_frame()->GetRoutingID(), view_id_, element_instance_id(),
*element_size_, std::move(before_unload_control));
guest_created_ = true; guest_created_ = true;
} }
void MimeHandlerViewContainer::SetShowBeforeUnloadDialog(
bool show_dialog,
SetShowBeforeUnloadDialogCallback callback) {
DCHECK(!is_embedded_);
render_frame()
->GetWebFrame()
->GetDocument()
.To<blink::WebPluginDocument>()
.SetShowBeforeUnloadDialog(show_dialog);
std::move(callback).Run();
}
} // namespace extensions } // namespace extensions
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "base/optional.h" #include "base/optional.h"
#include "components/guest_view/renderer/guest_view_container.h" #include "components/guest_view/renderer/guest_view_container.h"
#include "content/public/common/transferrable_url_loader.mojom.h" #include "content/public/common/transferrable_url_loader.mojom.h"
#include "extensions/common/api/mime_handler.mojom.h"
#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding.h"
#include "services/network/public/mojom/url_loader.mojom.h" #include "services/network/public/mojom/url_loader.mojom.h"
#include "third_party/blink/public/web/web_associated_url_loader_client.h" #include "third_party/blink/public/web/web_associated_url_loader_client.h"
...@@ -50,7 +51,8 @@ namespace extensions { ...@@ -50,7 +51,8 @@ namespace extensions {
// |didFinishLoading| (from WebAssociatedURLLoaderClient) when data is // |didFinishLoading| (from WebAssociatedURLLoaderClient) when data is
// received and when it has finished being received. // received and when it has finished being received.
class MimeHandlerViewContainer : public guest_view::GuestViewContainer, class MimeHandlerViewContainer : public guest_view::GuestViewContainer,
public blink::WebAssociatedURLLoaderClient { public blink::WebAssociatedURLLoaderClient,
public mime_handler::BeforeUnloadControl {
public: public:
MimeHandlerViewContainer(content::RenderFrame* render_frame, MimeHandlerViewContainer(content::RenderFrame* render_frame,
const content::WebPluginInfo& info, const content::WebPluginInfo& info,
...@@ -112,6 +114,11 @@ class MimeHandlerViewContainer : public guest_view::GuestViewContainer, ...@@ -112,6 +114,11 @@ class MimeHandlerViewContainer : public guest_view::GuestViewContainer,
// to are available. // to are available.
void CreateMimeHandlerViewGuestIfNecessary(); void CreateMimeHandlerViewGuestIfNecessary();
// mime_handler::BeforeUnloadControl implementation.
void SetShowBeforeUnloadDialog(
bool show_dialog,
SetShowBeforeUnloadDialogCallback callback) override;
// Path of the plugin. // Path of the plugin.
const std::string plugin_path_; const std::string plugin_path_;
...@@ -157,6 +164,9 @@ class MimeHandlerViewContainer : public guest_view::GuestViewContainer, ...@@ -157,6 +164,9 @@ class MimeHandlerViewContainer : public guest_view::GuestViewContainer,
// The size of the element. // The size of the element.
base::Optional<gfx::Size> element_size_; base::Optional<gfx::Size> element_size_;
mojo::Binding<mime_handler::BeforeUnloadControl>
before_unload_control_binding_;
base::WeakPtrFactory<MimeHandlerViewContainer> weak_factory_; base::WeakPtrFactory<MimeHandlerViewContainer> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MimeHandlerViewContainer); DISALLOW_COPY_AND_ASSIGN(MimeHandlerViewContainer);
......
...@@ -22,6 +22,11 @@ loadScript('extensions/common/api/mime_handler.mojom'); ...@@ -22,6 +22,11 @@ loadScript('extensions/common/api/mime_handler.mojom');
var servicePtr = new extensions.mimeHandler.MimeHandlerServicePtr; var servicePtr = new extensions.mimeHandler.MimeHandlerServicePtr;
Mojo.bindInterface(extensions.mimeHandler.MimeHandlerService.name, Mojo.bindInterface(extensions.mimeHandler.MimeHandlerService.name,
mojo.makeRequest(servicePtr).handle); mojo.makeRequest(servicePtr).handle);
var beforeUnloadControlPtr =
new extensions.mimeHandler.BeforeUnloadControlPtr;
Mojo.bindInterface(
extensions.mimeHandler.BeforeUnloadControl.name,
mojo.makeRequest(beforeUnloadControlPtr).handle);
// Stores a promise to the GetStreamInfo() result to avoid making additional // Stores a promise to the GetStreamInfo() result to avoid making additional
// calls in response to getStreamInfo() calls. // calls in response to getStreamInfo() calls.
...@@ -69,6 +74,12 @@ binding.registerCustomHook(function(bindingsAPI) { ...@@ -69,6 +74,12 @@ binding.registerCustomHook(function(bindingsAPI) {
function() { function() {
return servicePtr.abortStream().then(function() {}); return servicePtr.abortStream().then(function() {});
}); });
utils.handleRequestWithPromiseDoNotUse(
apiFunctions, 'mimeHandlerPrivate', 'setShowBeforeUnloadDialog',
function(showDialog) {
return beforeUnloadControlPtr.setShowBeforeUnloadDialog(showDialog);
});
}); });
if (!apiBridge) if (!apiBridge)
......
...@@ -52,6 +52,8 @@ class WebPluginDocument final : public WebDocument { ...@@ -52,6 +52,8 @@ class WebPluginDocument final : public WebDocument {
BLINK_EXPORT WebPlugin* Plugin(); BLINK_EXPORT WebPlugin* Plugin();
BLINK_EXPORT void SetShowBeforeUnloadDialog(bool show_dialog);
#if INSIDE_BLINK #if INSIDE_BLINK
WebPluginDocument(PluginDocument*); WebPluginDocument(PluginDocument*);
WebPluginDocument& operator=(PluginDocument*); WebPluginDocument& operator=(PluginDocument*);
......
...@@ -61,4 +61,12 @@ WebPluginDocument::operator PluginDocument*() const { ...@@ -61,4 +61,12 @@ WebPluginDocument::operator PluginDocument*() const {
return static_cast<PluginDocument*>(private_.Get()); return static_cast<PluginDocument*>(private_.Get());
} }
void WebPluginDocument::SetShowBeforeUnloadDialog(bool show_dialog) {
if (!IsPluginDocument())
return;
PluginDocument* doc = Unwrap<PluginDocument>();
doc->SetShowBeforeUnloadDialog(show_dialog);
}
} // namespace blink } // namespace blink
...@@ -25,8 +25,11 @@ ...@@ -25,8 +25,11 @@
#include "third_party/blink/renderer/core/html/plugin_document.h" #include "third_party/blink/renderer/core/html/plugin_document.h"
#include "third_party/blink/renderer/core/css/css_color_value.h" #include "third_party/blink/renderer/core/css/css_color_value.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/raw_data_document_parser.h" #include "third_party/blink/renderer/core/dom/raw_data_document_parser.h"
#include "third_party/blink/renderer/core/events/before_unload_event.h"
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h" #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h"
...@@ -45,6 +48,39 @@ namespace blink { ...@@ -45,6 +48,39 @@ namespace blink {
using namespace HTMLNames; using namespace HTMLNames;
class PluginDocument::BeforeUnloadEventListener : public EventListener {
public:
static BeforeUnloadEventListener* Create(PluginDocument* document) {
return new BeforeUnloadEventListener(document);
}
bool operator==(const EventListener& listener) const override {
return this == &listener;
}
void SetShowBeforeUnloadDialog(bool show_dialog) {
show_dialog_ = show_dialog;
}
void Trace(blink::Visitor* visitor) override {
visitor->Trace(doc_);
EventListener::Trace(visitor);
}
private:
explicit BeforeUnloadEventListener(PluginDocument* document)
: EventListener(kCPPEventListenerType), doc_(document) {}
void handleEvent(ExecutionContext*, Event* event) override {
DCHECK_EQ(event->type(), EventTypeNames::beforeunload);
if (show_dialog_)
ToBeforeUnloadEvent(event)->setReturnValue(g_empty_string);
}
Member<PluginDocument> doc_;
bool show_dialog_;
};
// FIXME: Share more code with MediaDocumentParser. // FIXME: Share more code with MediaDocumentParser.
class PluginDocumentParser : public RawDataDocumentParser { class PluginDocumentParser : public RawDataDocumentParser {
public: public:
...@@ -186,14 +222,28 @@ WebPluginContainerImpl* PluginDocument::GetPluginView() { ...@@ -186,14 +222,28 @@ WebPluginContainerImpl* PluginDocument::GetPluginView() {
return plugin_node_ ? plugin_node_->OwnedPlugin() : nullptr; return plugin_node_ ? plugin_node_->OwnedPlugin() : nullptr;
} }
void PluginDocument::SetShowBeforeUnloadDialog(bool show_dialog) {
if (!before_unload_event_listener_) {
if (!show_dialog)
return;
before_unload_event_listener_ = BeforeUnloadEventListener::Create(this);
domWindow()->addEventListener(EventTypeNames::beforeunload,
before_unload_event_listener_, false);
}
before_unload_event_listener_->SetShowBeforeUnloadDialog(show_dialog);
}
void PluginDocument::Shutdown() { void PluginDocument::Shutdown() {
// Release the plugin node so that we don't have a circular reference. // Release the plugin node so that we don't have a circular reference.
plugin_node_ = nullptr; plugin_node_ = nullptr;
before_unload_event_listener_ = nullptr;
HTMLDocument::Shutdown(); HTMLDocument::Shutdown();
} }
void PluginDocument::Trace(blink::Visitor* visitor) { void PluginDocument::Trace(blink::Visitor* visitor) {
visitor->Trace(plugin_node_); visitor->Trace(plugin_node_);
visitor->Trace(before_unload_event_listener_);
HTMLDocument::Trace(visitor); HTMLDocument::Trace(visitor);
} }
......
...@@ -48,16 +48,22 @@ class CORE_EXPORT PluginDocument final : public HTMLDocument { ...@@ -48,16 +48,22 @@ class CORE_EXPORT PluginDocument final : public HTMLDocument {
WebPluginContainerImpl* GetPluginView(); WebPluginContainerImpl* GetPluginView();
void SetShowBeforeUnloadDialog(bool show_dialog);
void Shutdown() override; void Shutdown() override;
void Trace(blink::Visitor*) override; void Trace(blink::Visitor*) override;
private: private:
class BeforeUnloadEventListener;
PluginDocument(const DocumentInit&, Color background_color); PluginDocument(const DocumentInit&, Color background_color);
DocumentParser* CreateParser() override; DocumentParser* CreateParser() override;
Member<HTMLPlugInElement> plugin_node_; Member<HTMLPlugInElement> plugin_node_;
Member<BeforeUnloadEventListener> before_unload_event_listener_;
const Color background_color_; const Color background_color_;
}; };
......
// Copyright 2017 The Chromium Authors. All rights reserved. // Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// This file was generated by:
// tools/json_schema_compiler/compiler.py.
// NOTE: The format of types has changed. 'FooType' is now
// 'chrome.mimeHandlerPrivate.FooType'.
// Please run the closure compiler before committing changes.
// See https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md
/** @fileoverview Externs generated from namespace: mimeHandlerPrivate */ /** @fileoverview Externs generated from namespace: mimeHandlerPrivate */
/** @const */ /**
* @const
*/
chrome.mimeHandlerPrivate = {}; chrome.mimeHandlerPrivate = {};
/** /**
* @typedef {?{ * @typedef {{
* embedded: boolean,
* mimeType: string, * mimeType: string,
* originalUrl: string, * originalUrl: string,
* responseHeaders: !Object,
* streamUrl: string, * streamUrl: string,
* tabId: number * tabId: number,
* responseHeaders: Object,
* embedded: boolean
* }} * }}
*/ */
chrome.mimeHandlerPrivate.StreamInfo; chrome.mimeHandlerPrivate.StreamInfo;
/** /**
* @param {function(!chrome.mimeHandlerPrivate.StreamInfo): void} callback * Returns the StreamInfo for the stream for this context if there is one.
* @param {function(!chrome.mimeHandlerPrivate.StreamInfo):void} callback
*/
chrome.mimeHandlerPrivate.getStreamInfo = function(callback) {};
/**
* Aborts the stream for this context if there is one.
* @param {function():void=} callback
*/ */
chrome.mimeHandlerPrivate.getStreamInfo = function(callback) {} chrome.mimeHandlerPrivate.abortStream = function(callback) {};
/** /**
* @param {function(): void=} opt_callback * Instructs the PluginDocument, if running in one, to show a dialog in response
* to beforeunload events.
* @param {boolean} showDialog
* @param {function():void=} callback
*/ */
chrome.mimeHandlerPrivate.abortStream = function(opt_callback) {} chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog = function(showDialog, callback) {};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment