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.
5 #include "content/browser/webui/web_ui_impl.h"
7 #include "base/json/json_writer.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/values.h"
10 #include "content/browser/child_process_security_policy_impl.h"
11 #include "content/browser/renderer_host/dip_util.h"
12 #include "content/browser/renderer_host/render_process_host_impl.h"
13 #include "content/browser/web_contents/web_contents_impl.h"
14 #include "content/browser/web_contents/web_contents_view.h"
15 #include "content/browser/webui/web_ui_controller_factory_registry.h"
16 #include "content/common/view_messages.h"
17 #include "content/public/browser/content_browser_client.h"
18 #include "content/public/browser/render_frame_host.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/web_ui_controller.h"
21 #include "content/public/browser/web_ui_message_handler.h"
22 #include "content/public/common/bindings_policy.h"
23 #include "content/public/common/content_client.h"
27 const WebUI::TypeID
WebUI::kNoWebUI
= NULL
;
30 base::string16
WebUI::GetJavascriptCall(
31 const std::string
& function_name
,
32 const std::vector
<const base::Value
*>& arg_list
) {
33 base::string16 parameters
;
35 for (size_t i
= 0; i
< arg_list
.size(); ++i
) {
37 parameters
+= base::char16(',');
39 base::JSONWriter::Write(*arg_list
[i
], &json
);
40 parameters
+= base::UTF8ToUTF16(json
);
42 return base::ASCIIToUTF16(function_name
) +
43 base::char16('(') + parameters
+ base::char16(')') + base::char16(';');
46 WebUIImpl::WebUIImpl(WebContents
* contents
)
47 : link_transition_type_(ui::PAGE_TRANSITION_LINK
),
48 bindings_(BINDINGS_POLICY_WEB_UI
),
49 web_contents_(contents
) {
53 WebUIImpl::~WebUIImpl() {
54 // Delete the controller first, since it may also be keeping a pointer to some
55 // of the handlers and can call them at destruction.
59 // WebUIImpl, public: ----------------------------------------------------------
61 bool WebUIImpl::OnMessageReceived(const IPC::Message
& message
) {
63 IPC_BEGIN_MESSAGE_MAP(WebUIImpl
, message
)
64 IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend
, OnWebUISend
)
65 IPC_MESSAGE_UNHANDLED(handled
= false)
70 void WebUIImpl::OnWebUISend(const GURL
& source_url
,
71 const std::string
& message
,
72 const base::ListValue
& args
) {
73 if (!ChildProcessSecurityPolicyImpl::GetInstance()->
74 HasWebUIBindings(web_contents_
->GetRenderProcessHost()->GetID()) ||
75 !WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
76 web_contents_
->GetBrowserContext(), source_url
)) {
77 NOTREACHED() << "Blocked unauthorized use of WebUIBindings.";
81 ProcessWebUIMessage(source_url
, message
, args
);
84 void WebUIImpl::RenderViewCreated(RenderViewHost
* render_view_host
) {
85 controller_
->RenderViewCreated(render_view_host
);
88 WebContents
* WebUIImpl::GetWebContents() const {
92 float WebUIImpl::GetDeviceScaleFactor() const {
93 return GetScaleFactorForView(web_contents_
->GetRenderWidgetHostView());
96 const base::string16
& WebUIImpl::GetOverriddenTitle() const {
97 return overridden_title_
;
100 void WebUIImpl::OverrideTitle(const base::string16
& title
) {
101 overridden_title_
= title
;
104 ui::PageTransition
WebUIImpl::GetLinkTransitionType() const {
105 return link_transition_type_
;
108 void WebUIImpl::SetLinkTransitionType(ui::PageTransition type
) {
109 link_transition_type_
= type
;
112 int WebUIImpl::GetBindings() const {
116 void WebUIImpl::SetBindings(int bindings
) {
117 bindings_
= bindings
;
120 void WebUIImpl::OverrideJavaScriptFrame(const std::string
& frame_name
) {
121 frame_name_
= frame_name
;
124 WebUIController
* WebUIImpl::GetController() const {
125 return controller_
.get();
128 void WebUIImpl::SetController(WebUIController
* controller
) {
129 controller_
.reset(controller
);
132 void WebUIImpl::CallJavascriptFunction(const std::string
& function_name
) {
133 DCHECK(base::IsStringASCII(function_name
));
134 base::string16 javascript
= base::ASCIIToUTF16(function_name
+ "();");
135 ExecuteJavascript(javascript
);
138 void WebUIImpl::CallJavascriptFunction(const std::string
& function_name
,
139 const base::Value
& arg
) {
140 DCHECK(base::IsStringASCII(function_name
));
141 std::vector
<const base::Value
*> args
;
142 args
.push_back(&arg
);
143 ExecuteJavascript(GetJavascriptCall(function_name
, args
));
146 void WebUIImpl::CallJavascriptFunction(
147 const std::string
& function_name
,
148 const base::Value
& arg1
, const base::Value
& arg2
) {
149 DCHECK(base::IsStringASCII(function_name
));
150 std::vector
<const base::Value
*> args
;
151 args
.push_back(&arg1
);
152 args
.push_back(&arg2
);
153 ExecuteJavascript(GetJavascriptCall(function_name
, args
));
156 void WebUIImpl::CallJavascriptFunction(
157 const std::string
& function_name
,
158 const base::Value
& arg1
, const base::Value
& arg2
, const base::Value
& arg3
) {
159 DCHECK(base::IsStringASCII(function_name
));
160 std::vector
<const base::Value
*> args
;
161 args
.push_back(&arg1
);
162 args
.push_back(&arg2
);
163 args
.push_back(&arg3
);
164 ExecuteJavascript(GetJavascriptCall(function_name
, args
));
167 void WebUIImpl::CallJavascriptFunction(
168 const std::string
& function_name
,
169 const base::Value
& arg1
,
170 const base::Value
& arg2
,
171 const base::Value
& arg3
,
172 const base::Value
& arg4
) {
173 DCHECK(base::IsStringASCII(function_name
));
174 std::vector
<const base::Value
*> args
;
175 args
.push_back(&arg1
);
176 args
.push_back(&arg2
);
177 args
.push_back(&arg3
);
178 args
.push_back(&arg4
);
179 ExecuteJavascript(GetJavascriptCall(function_name
, args
));
182 void WebUIImpl::CallJavascriptFunction(
183 const std::string
& function_name
,
184 const std::vector
<const base::Value
*>& args
) {
185 DCHECK(base::IsStringASCII(function_name
));
186 ExecuteJavascript(GetJavascriptCall(function_name
, args
));
189 void WebUIImpl::RegisterMessageCallback(const std::string
&message
,
190 const MessageCallback
& callback
) {
191 message_callbacks_
.insert(std::make_pair(message
, callback
));
194 void WebUIImpl::ProcessWebUIMessage(const GURL
& source_url
,
195 const std::string
& message
,
196 const base::ListValue
& args
) {
197 if (controller_
->OverrideHandleWebUIMessage(source_url
, message
, args
))
200 // Look up the callback for this message.
201 MessageCallbackMap::const_iterator callback
=
202 message_callbacks_
.find(message
);
203 if (callback
!= message_callbacks_
.end()) {
204 // Forward this message and content on.
205 callback
->second
.Run(&args
);
207 NOTREACHED() << "Unhandled chrome.send(\"" << message
<< "\");";
211 // WebUIImpl, protected: -------------------------------------------------------
213 void WebUIImpl::AddMessageHandler(WebUIMessageHandler
* handler
) {
214 DCHECK(!handler
->web_ui());
215 handler
->set_web_ui(this);
216 handler
->RegisterMessages();
217 handlers_
.push_back(handler
);
220 void WebUIImpl::ExecuteJavascript(const base::string16
& javascript
) {
221 RenderFrameHost
* target_frame
= TargetFrame();
223 target_frame
->ExecuteJavaScript(javascript
);
226 RenderFrameHost
* WebUIImpl::TargetFrame() {
227 if (frame_name_
.empty())
228 return web_contents_
->GetMainFrame();
230 std::set
<RenderFrameHost
*> frame_set
;
231 web_contents_
->ForEachFrame(base::Bind(&WebUIImpl::AddToSetIfFrameNameMatches
,
232 base::Unretained(this),
235 // It happens that some sub-pages attempt to send JavaScript messages before
236 // their frames are loaded.
237 DCHECK_GE(1U, frame_set
.size());
238 if (frame_set
.empty())
240 return *frame_set
.begin();
243 void WebUIImpl::AddToSetIfFrameNameMatches(
244 std::set
<RenderFrameHost
*>* frame_set
,
245 RenderFrameHost
* host
) {
246 if (host
->GetFrameName() == frame_name_
)
247 frame_set
->insert(host
);
250 } // namespace content