| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "ui/web_dialogs/web_dialog_ui.h" | 
 |  | 
 | #include "base/bind.h" | 
 | #include "base/bind_helpers.h" | 
 | #include "base/lazy_instance.h" | 
 | #include "base/values.h" | 
 | #include "content/public/browser/render_view_host.h" | 
 | #include "content/public/browser/web_contents.h" | 
 | #include "content/public/browser/web_ui.h" | 
 | #include "content/public/browser/web_ui_message_handler.h" | 
 | #include "content/public/common/bindings_policy.h" | 
 | #include "ui/web_dialogs/web_dialog_delegate.h" | 
 |  | 
 | using content::RenderViewHost; | 
 | using content::WebUIMessageHandler; | 
 |  | 
 | namespace ui { | 
 |  | 
 | namespace { | 
 |  | 
 | const char kWebDialogDelegateUserDataKey[] = "WebDialogDelegateUserData"; | 
 |  | 
 | class WebDialogDelegateUserData : public base::SupportsUserData::Data { | 
 |  public: | 
 |   explicit WebDialogDelegateUserData(WebDialogDelegate* delegate) | 
 |       : delegate_(delegate) {} | 
 |   ~WebDialogDelegateUserData() override {} | 
 |   WebDialogDelegate* delegate() { return delegate_; } | 
 |  | 
 |  private: | 
 |   WebDialogDelegate* delegate_;  // unowned | 
 | }; | 
 |  | 
 | }  // namespace | 
 |  | 
 | WebDialogUI::WebDialogUI(content::WebUI* web_ui) | 
 |     : WebUIController(web_ui) { | 
 | } | 
 |  | 
 | WebDialogUI::~WebDialogUI() { | 
 |   // Don't unregister our user data. During the teardown of the WebContents, | 
 |   // this will be deleted, but the WebContents will already be destroyed. | 
 |   // | 
 |   // This object is owned indirectly by the WebContents. WebUIs can change, so | 
 |   // it's scary if this WebUI is changed out and replaced with something else, | 
 |   // since the user data will still point to the old delegate. But the delegate | 
 |   // is itself the owner of the WebContents for a dialog so will be in scope, | 
 |   // and the HTML dialogs won't swap WebUIs anyway since they don't navigate. | 
 | } | 
 |  | 
 | void WebDialogUI::CloseDialog(const base::ListValue* args) { | 
 |   OnDialogClosed(args); | 
 | } | 
 |  | 
 | // static | 
 | void WebDialogUI::SetDelegate(content::WebContents* web_contents, | 
 |                               WebDialogDelegate* delegate) { | 
 |   web_contents->SetUserData(&kWebDialogDelegateUserDataKey, | 
 |                             new WebDialogDelegateUserData(delegate)); | 
 | } | 
 |  | 
 | //////////////////////////////////////////////////////////////////////////////// | 
 | // Private: | 
 |  | 
 | WebDialogDelegate* WebDialogUI::GetDelegate( | 
 |     content::WebContents* web_contents) { | 
 |   WebDialogDelegateUserData* user_data = | 
 |       static_cast<WebDialogDelegateUserData*>( | 
 |           web_contents->GetUserData(&kWebDialogDelegateUserDataKey)); | 
 |  | 
 |   return user_data ? user_data->delegate() : NULL; | 
 | } | 
 |  | 
 |  | 
 | void WebDialogUI::RenderViewCreated(RenderViewHost* render_view_host) { | 
 |   // Hook up the javascript function calls, also known as chrome.send("foo") | 
 |   // calls in the HTML, to the actual C++ functions. | 
 |   web_ui()->RegisterMessageCallback("dialogClose", | 
 |       base::Bind(&WebDialogUI::OnDialogClosed, base::Unretained(this))); | 
 |  | 
 |   // Pass the arguments to the renderer supplied by the delegate. | 
 |   std::string dialog_args; | 
 |   std::vector<WebUIMessageHandler*> handlers; | 
 |   WebDialogDelegate* delegate = GetDelegate(web_ui()->GetWebContents()); | 
 |   if (delegate) { | 
 |     dialog_args = delegate->GetDialogArgs(); | 
 |     delegate->GetWebUIMessageHandlers(&handlers); | 
 |   } | 
 |  | 
 |   if (0 != (web_ui()->GetBindings() & content::BINDINGS_POLICY_WEB_UI)) | 
 |     render_view_host->SetWebUIProperty("dialogArguments", dialog_args); | 
 |   for (std::vector<WebUIMessageHandler*>::iterator it = handlers.begin(); | 
 |        it != handlers.end(); ++it) { | 
 |     web_ui()->AddMessageHandler(*it); | 
 |   } | 
 |  | 
 |   if (delegate) | 
 |     delegate->OnDialogShown(web_ui(), render_view_host); | 
 | } | 
 |  | 
 | void WebDialogUI::OnDialogClosed(const base::ListValue* args) { | 
 |   WebDialogDelegate* delegate = GetDelegate(web_ui()->GetWebContents()); | 
 |   if (delegate) { | 
 |     std::string json_retval; | 
 |     if (args && !args->empty() && !args->GetString(0, &json_retval)) | 
 |       NOTREACHED() << "Could not read JSON argument"; | 
 |  | 
 |     delegate->OnDialogCloseFromWebUI(json_retval); | 
 |   } | 
 | } | 
 |  | 
 | }  // namespace ui |