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. 4 5 #include "content/browser/webui/web_ui_impl.h" 6 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/renderer_host/render_view_host_impl.h" 14 #include "content/browser/web_contents/web_contents_impl.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/web_contents_delegate.h" 19 #include "content/public/browser/web_contents_view.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" 24 25 namespace content { 26 27 const WebUI::TypeID WebUI::kNoWebUI = NULL; 28 29 // static 30 base::string16 WebUI::GetJavascriptCall( 31 const std::string& function_name, 32 const std::vector<const 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 += char16(','); 38 39 base::JSONWriter::Write(arg_list[i], &json); 40 parameters += UTF8ToUTF16(json); 41 } 42 return ASCIIToUTF16(function_name) + 43 char16('(') + parameters + char16(')') + char16(';'); 44 } 45 46 WebUIImpl::WebUIImpl(WebContents* contents) 47 : link_transition_type_(PAGE_TRANSITION_LINK), 48 bindings_(BINDINGS_POLICY_WEB_UI), 49 web_contents_(contents) { 50 DCHECK(contents); 51 } 52 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(); 57 } 58 59 // WebUIImpl, public: ---------------------------------------------------------- 60 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; 68 } 69 70 void WebUIImpl::OnWebUISend(const GURL& source_url, 71 const std::string& message, 72 const ListValue& args) { 73 WebContentsDelegate* delegate = web_contents_->GetDelegate(); 74 bool data_urls_allowed = delegate && delegate->CanLoadDataURLsInWebUI(); 75 if (!ChildProcessSecurityPolicyImpl::GetInstance()-> 76 HasWebUIBindings(web_contents_->GetRenderProcessHost()->GetID()) || 77 !WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI( 78 web_contents_->GetBrowserContext(), source_url, data_urls_allowed)) { 79 NOTREACHED() << "Blocked unauthorized use of WebUIBindings."; 80 return; 81 } 82 83 ProcessWebUIMessage(source_url, message, args); 84 } 85 86 void WebUIImpl::RenderViewCreated(RenderViewHost* render_view_host) { 87 controller_->RenderViewCreated(render_view_host); 88 89 // Do not attempt to set the toolkit property if WebUI is not enabled, e.g., 90 // the bookmarks manager page. 91 if (!(bindings_ & BINDINGS_POLICY_WEB_UI)) 92 return; 93 94 #if defined(TOOLKIT_VIEWS) 95 render_view_host->SetWebUIProperty("toolkit", "views"); 96 #elif defined(TOOLKIT_GTK) 97 render_view_host->SetWebUIProperty("toolkit", "GTK"); 98 #endif // defined(TOOLKIT_VIEWS) 99 } 100 101 WebContents* WebUIImpl::GetWebContents() const { 102 return web_contents_; 103 } 104 105 ui::ScaleFactor WebUIImpl::GetDeviceScaleFactor() const { 106 return GetScaleFactorForView(web_contents_->GetRenderWidgetHostView()); 107 } 108 109 const base::string16& WebUIImpl::GetOverriddenTitle() const { 110 return overridden_title_; 111 } 112 113 void WebUIImpl::OverrideTitle(const base::string16& title) { 114 overridden_title_ = title; 115 } 116 117 PageTransition WebUIImpl::GetLinkTransitionType() const { 118 return link_transition_type_; 119 } 120 121 void WebUIImpl::SetLinkTransitionType(PageTransition type) { 122 link_transition_type_ = type; 123 } 124 125 int WebUIImpl::GetBindings() const { 126 return bindings_; 127 } 128 129 void WebUIImpl::SetBindings(int bindings) { 130 bindings_ = bindings; 131 } 132 133 void WebUIImpl::SetFrameXPath(const std::string& xpath) { 134 frame_xpath_ = xpath; 135 } 136 137 WebUIController* WebUIImpl::GetController() const { 138 return controller_.get(); 139 } 140 141 void WebUIImpl::SetController(WebUIController* controller) { 142 controller_.reset(controller); 143 } 144 145 void WebUIImpl::CallJavascriptFunction(const std::string& function_name) { 146 DCHECK(IsStringASCII(function_name)); 147 base::string16 javascript = ASCIIToUTF16(function_name + "();"); 148 ExecuteJavascript(javascript); 149 } 150 151 void WebUIImpl::CallJavascriptFunction(const std::string& function_name, 152 const Value& arg) { 153 DCHECK(IsStringASCII(function_name)); 154 std::vector<const Value*> args; 155 args.push_back(&arg); 156 ExecuteJavascript(GetJavascriptCall(function_name, args)); 157 } 158 159 void WebUIImpl::CallJavascriptFunction( 160 const std::string& function_name, 161 const Value& arg1, const Value& arg2) { 162 DCHECK(IsStringASCII(function_name)); 163 std::vector<const Value*> args; 164 args.push_back(&arg1); 165 args.push_back(&arg2); 166 ExecuteJavascript(GetJavascriptCall(function_name, args)); 167 } 168 169 void WebUIImpl::CallJavascriptFunction( 170 const std::string& function_name, 171 const Value& arg1, const Value& arg2, const Value& arg3) { 172 DCHECK(IsStringASCII(function_name)); 173 std::vector<const Value*> args; 174 args.push_back(&arg1); 175 args.push_back(&arg2); 176 args.push_back(&arg3); 177 ExecuteJavascript(GetJavascriptCall(function_name, args)); 178 } 179 180 void WebUIImpl::CallJavascriptFunction( 181 const std::string& function_name, 182 const Value& arg1, 183 const Value& arg2, 184 const Value& arg3, 185 const Value& arg4) { 186 DCHECK(IsStringASCII(function_name)); 187 std::vector<const Value*> args; 188 args.push_back(&arg1); 189 args.push_back(&arg2); 190 args.push_back(&arg3); 191 args.push_back(&arg4); 192 ExecuteJavascript(GetJavascriptCall(function_name, args)); 193 } 194 195 void WebUIImpl::CallJavascriptFunction( 196 const std::string& function_name, 197 const std::vector<const Value*>& args) { 198 DCHECK(IsStringASCII(function_name)); 199 ExecuteJavascript(GetJavascriptCall(function_name, args)); 200 } 201 202 void WebUIImpl::RegisterMessageCallback(const std::string &message, 203 const MessageCallback& callback) { 204 message_callbacks_.insert(std::make_pair(message, callback)); 205 } 206 207 void WebUIImpl::ProcessWebUIMessage(const GURL& source_url, 208 const std::string& message, 209 const base::ListValue& args) { 210 if (controller_->OverrideHandleWebUIMessage(source_url, message, args)) 211 return; 212 213 // Look up the callback for this message. 214 MessageCallbackMap::const_iterator callback = 215 message_callbacks_.find(message); 216 if (callback != message_callbacks_.end()) { 217 // Forward this message and content on. 218 callback->second.Run(&args); 219 } else { 220 NOTREACHED() << "Unhandled chrome.send(\"" << message << "\");"; 221 } 222 } 223 224 // WebUIImpl, protected: ------------------------------------------------------- 225 226 void WebUIImpl::AddMessageHandler(WebUIMessageHandler* handler) { 227 DCHECK(!handler->web_ui()); 228 handler->set_web_ui(this); 229 handler->RegisterMessages(); 230 handlers_.push_back(handler); 231 } 232 233 void WebUIImpl::ExecuteJavascript(const base::string16& javascript) { 234 static_cast<RenderViewHostImpl*>( 235 web_contents_->GetRenderViewHost())->ExecuteJavascriptInWebFrame( 236 ASCIIToUTF16(frame_xpath_), javascript); 237 } 238 239 } // namespace content 240