Home | History | Annotate | Download | only in webui
      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