summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/webui/html_dialog_ui.cc
blob: 1b0dcf6e2da67564e2c8229b73aaf1e9e8cd8ee5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// 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 "chrome/browser/ui/webui/html_dialog_ui.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/lazy_instance.h"
#include "base/property_bag.h"
#include "base/values.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/notification_service.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"

using content::RenderViewHost;
using content::WebUIMessageHandler;

static base::LazyInstance<base::PropertyAccessor<HtmlDialogUIDelegate*> >
    g_html_dialog_ui_property_accessor = LAZY_INSTANCE_INITIALIZER;

HtmlDialogUI::HtmlDialogUI(content::WebUI* web_ui)
    : WebUIController(web_ui) {
}

HtmlDialogUI::~HtmlDialogUI() {
  // Don't unregister our property. 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 property 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 HtmlDialogUI::CloseDialog(const base::ListValue* args) {
  OnDialogClosed(args);
}

// static
base::PropertyAccessor<HtmlDialogUIDelegate*>&
    HtmlDialogUI::GetPropertyAccessor() {
  return g_html_dialog_ui_property_accessor.Get();
}

////////////////////////////////////////////////////////////////////////////////
// Private:

void HtmlDialogUI::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(&HtmlDialogUI::OnDialogClosed, base::Unretained(this)));

  // Pass the arguments to the renderer supplied by the delegate.
  std::string dialog_args;
  std::vector<WebUIMessageHandler*> handlers;
  HtmlDialogUIDelegate** delegate = GetPropertyAccessor().GetProperty(
      web_ui()->GetWebContents()->GetPropertyBag());
  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);
  }

  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_HTML_DIALOG_SHOWN,
      content::Source<content::WebUI>(web_ui()),
      content::Details<RenderViewHost>(render_view_host));
}

void HtmlDialogUI::OnDialogClosed(const ListValue* args) {
  HtmlDialogUIDelegate** delegate = GetPropertyAccessor().GetProperty(
      web_ui()->GetWebContents()->GetPropertyBag());
  if (delegate) {
    std::string json_retval;
    if (args && !args->empty() && !args->GetString(0, &json_retval))
      NOTREACHED() << "Could not read JSON argument";

    (*delegate)->OnDialogClosed(json_retval);
  }
}

ExternalHtmlDialogUI::ExternalHtmlDialogUI(content::WebUI* web_ui)
    : HtmlDialogUI(web_ui) {
  // Non-file based UI needs to not have access to the Web UI bindings
  // for security reasons. The code hosting the dialog should provide
  // dialog specific functionality through other bindings and methods
  // that are scoped in duration to the dialogs existence.
  web_ui->SetBindings(web_ui->GetBindings() & ~content::BINDINGS_POLICY_WEB_UI);
}

ExternalHtmlDialogUI::~ExternalHtmlDialogUI() {
}

std::string HtmlDialogUIDelegate::GetDialogName() const {
  return std::string();
}

void HtmlDialogUIDelegate::GetMinimumDialogSize(gfx::Size* size) const {
  GetDialogSize(size);
}

bool HtmlDialogUIDelegate::HandleContextMenu(
    const content::ContextMenuParams& params) {
  return false;
}

bool HtmlDialogUIDelegate::HandleOpenURLFromTab(
    content::WebContents* source,
    const content::OpenURLParams& params,
    content::WebContents** out_new_contents) {
  return false;
}

bool HtmlDialogUIDelegate::HandleAddNewContents(
    content::WebContents* source,
    content::WebContents* new_contents,
    WindowOpenDisposition disposition,
    const gfx::Rect& initial_pos,
    bool user_gesture) {
  return false;
}