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_(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
);
87 // Do not attempt to set the toolkit property if WebUI is not enabled, e.g.,
88 // the bookmarks manager page.
89 if (!(bindings_
& BINDINGS_POLICY_WEB_UI
))
92 #if defined(TOOLKIT_VIEWS)
93 render_view_host
->SetWebUIProperty("toolkit", "views");
94 #endif // defined(TOOLKIT_VIEWS)
97 WebContents
* WebUIImpl::GetWebContents() const {
101 float WebUIImpl::GetDeviceScaleFactor() const {
102 return GetScaleFactorForView(web_contents_
->GetRenderWidgetHostView());
105 const base::string16
& WebUIImpl::GetOverriddenTitle() const {
106 return overridden_title_
;
109 void WebUIImpl::OverrideTitle(const base::string16
& title
) {
110 overridden_title_
= title
;
113 PageTransition
WebUIImpl::GetLinkTransitionType() const {
114 return link_transition_type_
;
117 void WebUIImpl::SetLinkTransitionType(PageTransition type
) {
118 link_transition_type_
= type
;
121 int WebUIImpl::GetBindings() const {
125 void WebUIImpl::SetBindings(int bindings
) {
126 bindings_
= bindings
;
129 void WebUIImpl::OverrideJavaScriptFrame(const std::string
& frame_name
) {
130 frame_name_
= frame_name
;
133 WebUIController
* WebUIImpl::GetController() const {
134 return controller_
.get();
137 void WebUIImpl::SetController(WebUIController
* controller
) {
138 controller_
.reset(controller
);
141 void WebUIImpl::CallJavascriptFunction(const std::string
& function_name
) {
142 DCHECK(base::IsStringASCII(function_name
));
143 base::string16 javascript
= base::ASCIIToUTF16(function_name
+ "();");
144 ExecuteJavascript(javascript
);
147 void WebUIImpl::CallJavascriptFunction(const std::string
& function_name
,
148 const base::Value
& arg
) {
149 DCHECK(base::IsStringASCII(function_name
));
150 std::vector
<const base::Value
*> args
;
151 args
.push_back(&arg
);
152 ExecuteJavascript(GetJavascriptCall(function_name
, args
));
155 void WebUIImpl::CallJavascriptFunction(
156 const std::string
& function_name
,
157 const base::Value
& arg1
, const base::Value
& arg2
) {
158 DCHECK(base::IsStringASCII(function_name
));
159 std::vector
<const base::Value
*> args
;
160 args
.push_back(&arg1
);
161 args
.push_back(&arg2
);
162 ExecuteJavascript(GetJavascriptCall(function_name
, args
));
165 void WebUIImpl::CallJavascriptFunction(
166 const std::string
& function_name
,
167 const base::Value
& arg1
, const base::Value
& arg2
, const base::Value
& arg3
) {
168 DCHECK(base::IsStringASCII(function_name
));
169 std::vector
<const base::Value
*> args
;
170 args
.push_back(&arg1
);
171 args
.push_back(&arg2
);
172 args
.push_back(&arg3
);
173 ExecuteJavascript(GetJavascriptCall(function_name
, args
));
176 void WebUIImpl::CallJavascriptFunction(
177 const std::string
& function_name
,
178 const base::Value
& arg1
,
179 const base::Value
& arg2
,
180 const base::Value
& arg3
,
181 const base::Value
& arg4
) {
182 DCHECK(base::IsStringASCII(function_name
));
183 std::vector
<const base::Value
*> args
;
184 args
.push_back(&arg1
);
185 args
.push_back(&arg2
);
186 args
.push_back(&arg3
);
187 args
.push_back(&arg4
);
188 ExecuteJavascript(GetJavascriptCall(function_name
, args
));
191 void WebUIImpl::CallJavascriptFunction(
192 const std::string
& function_name
,
193 const std::vector
<const base::Value
*>& args
) {
194 DCHECK(base::IsStringASCII(function_name
));
195 ExecuteJavascript(GetJavascriptCall(function_name
, args
));
198 void WebUIImpl::RegisterMessageCallback(const std::string
&message
,
199 const MessageCallback
& callback
) {
200 message_callbacks_
.insert(std::make_pair(message
, callback
));
203 void WebUIImpl::ProcessWebUIMessage(const GURL
& source_url
,
204 const std::string
& message
,
205 const base::ListValue
& args
) {
206 if (controller_
->OverrideHandleWebUIMessage(source_url
, message
, args
))
209 // Look up the callback for this message.
210 MessageCallbackMap::const_iterator callback
=
211 message_callbacks_
.find(message
);
212 if (callback
!= message_callbacks_
.end()) {
213 // Forward this message and content on.
214 callback
->second
.Run(&args
);
216 NOTREACHED() << "Unhandled chrome.send(\"" << message
<< "\");";
220 // WebUIImpl, protected: -------------------------------------------------------
222 void WebUIImpl::AddMessageHandler(WebUIMessageHandler
* handler
) {
223 DCHECK(!handler
->web_ui());
224 handler
->set_web_ui(this);
225 handler
->RegisterMessages();
226 handlers_
.push_back(handler
);
229 void WebUIImpl::ExecuteJavascript(const base::string16
& javascript
) {
230 RenderFrameHost
* target_frame
= TargetFrame();
232 target_frame
->ExecuteJavaScript(javascript
);
235 RenderFrameHost
* WebUIImpl::TargetFrame() {
236 if (frame_name_
.empty())
237 return web_contents_
->GetMainFrame();
239 std::set
<RenderFrameHost
*> frame_set
;
240 web_contents_
->ForEachFrame(base::Bind(&WebUIImpl::AddToSetIfFrameNameMatches
,
241 base::Unretained(this),
244 // It happens that some sub-pages attempt to send JavaScript messages before
245 // their frames are loaded.
246 DCHECK_GE(1U, frame_set
.size());
247 if (frame_set
.empty())
249 return *frame_set
.begin();
252 void WebUIImpl::AddToSetIfFrameNameMatches(
253 std::set
<RenderFrameHost
*>* frame_set
,
254 RenderFrameHost
* host
) {
255 if (host
->GetFrameName() == frame_name_
)
256 frame_set
->insert(host
);
259 } // namespace content