web_dialog_ui.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/web_dialogs/web_dialog_ui.h"
  5. #include "base/bind.h"
  6. #include "base/callback_helpers.h"
  7. #include "base/lazy_instance.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/values.h"
  11. #include "content/public/browser/render_frame_host.h"
  12. #include "content/public/browser/web_contents.h"
  13. #include "content/public/browser/web_ui.h"
  14. #include "content/public/browser/web_ui_message_handler.h"
  15. #include "content/public/common/bindings_policy.h"
  16. #include "ui/web_dialogs/web_dialog_delegate.h"
  17. using content::RenderFrameHost;
  18. using content::WebUIMessageHandler;
  19. namespace ui {
  20. namespace {
  21. const char kWebDialogDelegateUserDataKey[] = "WebDialogDelegateUserData";
  22. class WebDialogDelegateUserData : public base::SupportsUserData::Data {
  23. public:
  24. explicit WebDialogDelegateUserData(WebDialogDelegate* delegate)
  25. : delegate_(delegate) {}
  26. ~WebDialogDelegateUserData() override {}
  27. WebDialogDelegate* delegate() { return delegate_; }
  28. private:
  29. raw_ptr<WebDialogDelegate> delegate_; // unowned
  30. };
  31. } // namespace
  32. // static
  33. void WebDialogUIBase::SetDelegate(content::WebContents* web_contents,
  34. WebDialogDelegate* delegate) {
  35. web_contents->SetUserData(
  36. &kWebDialogDelegateUserDataKey,
  37. std::make_unique<WebDialogDelegateUserData>(delegate));
  38. }
  39. WebDialogUIBase::WebDialogUIBase(content::WebUI* web_ui) : web_ui_(web_ui) {}
  40. // Don't unregister our user data. During the teardown of the WebContents, this
  41. // will be deleted, but the WebContents will already be destroyed.
  42. //
  43. // This object is owned indirectly by the WebContents. WebUIs can change, so
  44. // it's scary if this WebUI is changed out and replaced with something else,
  45. // since the user data will still point to the old delegate. But the delegate is
  46. // itself the owner of the WebContents for a dialog so will be in scope, and the
  47. // HTML dialogs won't swap WebUIs anyway since they don't navigate.
  48. WebDialogUIBase::~WebDialogUIBase() = default;
  49. void WebDialogUIBase::CloseDialog(const base::Value::List& args) {
  50. OnDialogClosed(args);
  51. }
  52. WebDialogDelegate* WebDialogUIBase::GetDelegate(
  53. content::WebContents* web_contents) {
  54. WebDialogDelegateUserData* user_data =
  55. static_cast<WebDialogDelegateUserData*>(
  56. web_contents->GetUserData(&kWebDialogDelegateUserDataKey));
  57. return user_data ? user_data->delegate() : NULL;
  58. }
  59. void WebDialogUIBase::HandleRenderFrameCreated(
  60. RenderFrameHost* render_frame_host) {
  61. // Hook up the javascript function calls, also known as chrome.send("foo")
  62. // calls in the HTML, to the actual C++ functions.
  63. web_ui_->RegisterMessageCallback(
  64. "dialogClose", base::BindRepeating(&WebDialogUIBase::OnDialogClosed,
  65. base::Unretained(this)));
  66. // Pass the arguments to the renderer supplied by the delegate.
  67. std::string dialog_args;
  68. std::vector<WebUIMessageHandler*> handlers;
  69. WebDialogDelegate* delegate = GetDelegate(web_ui_->GetWebContents());
  70. if (delegate) {
  71. dialog_args = delegate->GetDialogArgs();
  72. delegate->GetWebUIMessageHandlers(&handlers);
  73. }
  74. if (content::BINDINGS_POLICY_NONE !=
  75. (web_ui_->GetBindings() & content::BINDINGS_POLICY_WEB_UI)) {
  76. render_frame_host->SetWebUIProperty("dialogArguments", dialog_args);
  77. }
  78. for (WebUIMessageHandler* handler : handlers)
  79. web_ui_->AddMessageHandler(base::WrapUnique(handler));
  80. if (delegate)
  81. delegate->OnDialogShown(web_ui_);
  82. }
  83. void WebDialogUIBase::OnDialogClosed(const base::Value::List& args) {
  84. WebDialogDelegate* delegate = GetDelegate(web_ui_->GetWebContents());
  85. if (delegate) {
  86. std::string json_retval;
  87. if (!args.empty()) {
  88. if (args[0].is_string())
  89. json_retval = args[0].GetString();
  90. else
  91. NOTREACHED() << "Could not read JSON argument";
  92. }
  93. delegate->OnDialogCloseFromWebUI(json_retval);
  94. }
  95. }
  96. WebDialogUI::WebDialogUI(content::WebUI* web_ui)
  97. : WebDialogUIBase(web_ui), content::WebUIController(web_ui) {}
  98. WebDialogUI::~WebDialogUI() = default;
  99. void WebDialogUI::WebUIRenderFrameCreated(RenderFrameHost* render_frame_host) {
  100. HandleRenderFrameCreated(render_frame_host);
  101. }
  102. // Note: chrome.send() must always be enabled for dialogs, since dialogs rely on
  103. // chrome.send() to notify their handlers that the dialog should be closed. See
  104. // the "dialogClose" message handler above in
  105. // WebDialogUIBase::HandleRenderFrameCreated().
  106. MojoWebDialogUI::MojoWebDialogUI(content::WebUI* web_ui)
  107. : WebDialogUIBase(web_ui),
  108. MojoWebUIController(web_ui, /*enable_chrome_send=*/true) {}
  109. MojoWebDialogUI::~MojoWebDialogUI() = default;
  110. void MojoWebDialogUI::WebUIRenderFrameCreated(
  111. content::RenderFrameHost* render_frame_host) {
  112. content::WebUIController::WebUIRenderFrameCreated(render_frame_host);
  113. HandleRenderFrameCreated(render_frame_host);
  114. }
  115. } // namespace ui