Apply _RELATIVE relocations ahead of others.
[chromium-blink-merge.git] / content / browser / webui / web_ui_impl.cc
bloba9194a992fd6884880577a21aaa7749ec175780b
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"
25 namespace content {
27 const WebUI::TypeID WebUI::kNoWebUI = NULL;
29 // static
30 base::string16 WebUI::GetJavascriptCall(
31 const std::string& function_name,
32 const std::vector<const base::Value*>& arg_list) {
33 base::string16 parameters;
34 std::string json;
35 for (size_t i = 0; i < arg_list.size(); ++i) {
36 if (i > 0)
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) {
50 DCHECK(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.
56 controller_.reset();
59 // WebUIImpl, public: ----------------------------------------------------------
61 bool WebUIImpl::OnMessageReceived(const IPC::Message& message) {
62 bool handled = true;
63 IPC_BEGIN_MESSAGE_MAP(WebUIImpl, message)
64 IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend)
65 IPC_MESSAGE_UNHANDLED(handled = false)
66 IPC_END_MESSAGE_MAP()
67 return handled;
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.";
78 return;
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))
90 return;
92 #if defined(TOOLKIT_VIEWS)
93 render_view_host->SetWebUIProperty("toolkit", "views");
94 #endif // defined(TOOLKIT_VIEWS)
97 WebContents* WebUIImpl::GetWebContents() const {
98 return web_contents_;
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 ui::PageTransition WebUIImpl::GetLinkTransitionType() const {
114 return link_transition_type_;
117 void WebUIImpl::SetLinkTransitionType(ui::PageTransition type) {
118 link_transition_type_ = type;
121 int WebUIImpl::GetBindings() const {
122 return bindings_;
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))
207 return;
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);
215 } else {
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();
231 if (target_frame)
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),
242 &frame_set));
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())
248 return NULL;
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