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_data_source_impl.h"
      6 
      7 #include <string>
      8 
      9 #include "base/bind.h"
     10 #include "base/memory/ref_counted_memory.h"
     11 #include "base/strings/string_util.h"
     12 #include "content/grit/content_resources.h"
     13 #include "content/public/common/content_client.h"
     14 #include "mojo/public/js/bindings/constants.h"
     15 #include "ui/base/webui/jstemplate_builder.h"
     16 #include "ui/base/webui/web_ui_util.h"
     17 
     18 namespace content {
     19 
     20 // static
     21 WebUIDataSource* WebUIDataSource::Create(const std::string& source_name) {
     22   return new WebUIDataSourceImpl(source_name);
     23 }
     24 
     25 // static
     26 WebUIDataSource* WebUIDataSource::AddMojoDataSource(
     27     BrowserContext* browser_context) {
     28   WebUIDataSource* mojo_source = Create("mojo");
     29 
     30   static const struct {
     31     const char* path;
     32     int id;
     33   } resources[] = {
     34     { mojo::kBufferModuleName, IDR_MOJO_BUFFER_JS },
     35     { mojo::kCodecModuleName, IDR_MOJO_CODEC_JS },
     36     { mojo::kConnectionModuleName, IDR_MOJO_CONNECTION_JS },
     37     { mojo::kConnectorModuleName, IDR_MOJO_CONNECTOR_JS },
     38     { mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS },
     39     { mojo::kUnicodeModuleName, IDR_MOJO_UNICODE_JS },
     40     { mojo::kValidatorModuleName, IDR_MOJO_VALIDATOR_JS },
     41   };
     42   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(resources); ++i)
     43     mojo_source->AddResourcePath(resources[i].path, resources[i].id);
     44 
     45   URLDataManager::AddWebUIDataSource(browser_context, mojo_source);
     46   return mojo_source;
     47 }
     48 
     49 // static
     50 void WebUIDataSource::Add(BrowserContext* browser_context,
     51                           WebUIDataSource* source) {
     52   URLDataManager::AddWebUIDataSource(browser_context, source);
     53 }
     54 
     55 // Internal class to hide the fact that WebUIDataSourceImpl implements
     56 // URLDataSource.
     57 class WebUIDataSourceImpl::InternalDataSource : public URLDataSource {
     58  public:
     59   InternalDataSource(WebUIDataSourceImpl* parent) : parent_(parent) {
     60   }
     61 
     62   virtual ~InternalDataSource() {
     63   }
     64 
     65   // URLDataSource implementation.
     66   virtual std::string GetSource() const OVERRIDE {
     67     return parent_->GetSource();
     68   }
     69   virtual std::string GetMimeType(const std::string& path) const OVERRIDE {
     70     return parent_->GetMimeType(path);
     71   }
     72   virtual void StartDataRequest(
     73       const std::string& path,
     74       int render_process_id,
     75       int render_frame_id,
     76       const URLDataSource::GotDataCallback& callback) OVERRIDE {
     77     return parent_->StartDataRequest(path, render_process_id, render_frame_id,
     78                                      callback);
     79   }
     80   virtual bool ShouldReplaceExistingSource() const OVERRIDE {
     81     return parent_->replace_existing_source_;
     82   }
     83   virtual bool AllowCaching() const OVERRIDE {
     84     return false;
     85   }
     86   virtual bool ShouldAddContentSecurityPolicy() const OVERRIDE {
     87     return parent_->add_csp_;
     88   }
     89   virtual std::string GetContentSecurityPolicyObjectSrc() const OVERRIDE {
     90     if (parent_->object_src_set_)
     91       return parent_->object_src_;
     92     return URLDataSource::GetContentSecurityPolicyObjectSrc();
     93   }
     94   virtual std::string GetContentSecurityPolicyFrameSrc() const OVERRIDE {
     95     if (parent_->frame_src_set_)
     96       return parent_->frame_src_;
     97     return URLDataSource::GetContentSecurityPolicyFrameSrc();
     98   }
     99   virtual bool ShouldDenyXFrameOptions() const OVERRIDE {
    100     return parent_->deny_xframe_options_;
    101   }
    102 
    103  private:
    104   WebUIDataSourceImpl* parent_;
    105 };
    106 
    107 WebUIDataSourceImpl::WebUIDataSourceImpl(const std::string& source_name)
    108     : URLDataSourceImpl(
    109           source_name,
    110           new InternalDataSource(this)),
    111       source_name_(source_name),
    112       default_resource_(-1),
    113       json_js_format_v2_(false),
    114       add_csp_(true),
    115       object_src_set_(false),
    116       frame_src_set_(false),
    117       deny_xframe_options_(true),
    118       disable_set_font_strings_(false),
    119       replace_existing_source_(true) {
    120 }
    121 
    122 WebUIDataSourceImpl::~WebUIDataSourceImpl() {
    123 }
    124 
    125 void WebUIDataSourceImpl::AddString(const std::string& name,
    126                                     const base::string16& value) {
    127   localized_strings_.SetString(name, value);
    128 }
    129 
    130 void WebUIDataSourceImpl::AddString(const std::string& name,
    131                                     const std::string& value) {
    132   localized_strings_.SetString(name, value);
    133 }
    134 
    135 void WebUIDataSourceImpl::AddLocalizedString(const std::string& name,
    136                                              int ids) {
    137   localized_strings_.SetString(
    138       name, GetContentClient()->GetLocalizedString(ids));
    139 }
    140 
    141 void WebUIDataSourceImpl::AddLocalizedStrings(
    142     const base::DictionaryValue& localized_strings) {
    143   localized_strings_.MergeDictionary(&localized_strings);
    144 }
    145 
    146 void WebUIDataSourceImpl::AddBoolean(const std::string& name, bool value) {
    147   localized_strings_.SetBoolean(name, value);
    148 }
    149 
    150 void WebUIDataSourceImpl::SetJsonPath(const std::string& path) {
    151   json_path_ = path;
    152 }
    153 
    154 void WebUIDataSourceImpl::SetUseJsonJSFormatV2() {
    155   json_js_format_v2_ = true;
    156 }
    157 
    158 void WebUIDataSourceImpl::AddResourcePath(const std::string &path,
    159                                           int resource_id) {
    160   path_to_idr_map_[path] = resource_id;
    161 }
    162 
    163 void WebUIDataSourceImpl::SetDefaultResource(int resource_id) {
    164   default_resource_ = resource_id;
    165 }
    166 
    167 void WebUIDataSourceImpl::SetRequestFilter(
    168     const WebUIDataSource::HandleRequestCallback& callback) {
    169   filter_callback_ = callback;
    170 }
    171 
    172 void WebUIDataSourceImpl::DisableReplaceExistingSource() {
    173   replace_existing_source_ = false;
    174 }
    175 
    176 void WebUIDataSourceImpl::DisableContentSecurityPolicy() {
    177   add_csp_ = false;
    178 }
    179 
    180 void WebUIDataSourceImpl::OverrideContentSecurityPolicyObjectSrc(
    181     const std::string& data) {
    182   object_src_set_ = true;
    183   object_src_ = data;
    184 }
    185 
    186 void WebUIDataSourceImpl::OverrideContentSecurityPolicyFrameSrc(
    187     const std::string& data) {
    188   frame_src_set_ = true;
    189   frame_src_ = data;
    190 }
    191 
    192 void WebUIDataSourceImpl::DisableDenyXFrameOptions() {
    193   deny_xframe_options_ = false;
    194 }
    195 
    196 std::string WebUIDataSourceImpl::GetSource() const {
    197   return source_name_;
    198 }
    199 
    200 std::string WebUIDataSourceImpl::GetMimeType(const std::string& path) const {
    201   if (EndsWith(path, ".js", false))
    202     return "application/javascript";
    203 
    204   if (EndsWith(path, ".json", false))
    205     return "application/json";
    206 
    207   if (EndsWith(path, ".pdf", false))
    208     return "application/pdf";
    209 
    210   if (EndsWith(path, ".svg", false))
    211     return "image/svg+xml";
    212 
    213   return "text/html";
    214 }
    215 
    216 void WebUIDataSourceImpl::StartDataRequest(
    217     const std::string& path,
    218     int render_process_id,
    219     int render_frame_id,
    220     const URLDataSource::GotDataCallback& callback) {
    221   if (!filter_callback_.is_null() &&
    222       filter_callback_.Run(path, callback)) {
    223     return;
    224   }
    225 
    226   if (!json_path_.empty() && path == json_path_) {
    227     SendLocalizedStringsAsJSON(callback);
    228     return;
    229   }
    230 
    231   int resource_id = default_resource_;
    232   std::map<std::string, int>::iterator result;
    233   result = path_to_idr_map_.find(path);
    234   if (result != path_to_idr_map_.end())
    235     resource_id = result->second;
    236   DCHECK_NE(resource_id, -1);
    237   SendFromResourceBundle(callback, resource_id);
    238 }
    239 
    240 void WebUIDataSourceImpl::SendLocalizedStringsAsJSON(
    241     const URLDataSource::GotDataCallback& callback) {
    242   std::string template_data;
    243   if (!disable_set_font_strings_)
    244     webui::SetFontAndTextDirection(&localized_strings_);
    245 
    246   scoped_ptr<webui::UseVersion2> version2;
    247   if (json_js_format_v2_)
    248     version2.reset(new webui::UseVersion2);
    249 
    250   webui::AppendJsonJS(&localized_strings_, &template_data);
    251   callback.Run(base::RefCountedString::TakeString(&template_data));
    252 }
    253 
    254 void WebUIDataSourceImpl::SendFromResourceBundle(
    255     const URLDataSource::GotDataCallback& callback, int idr) {
    256   scoped_refptr<base::RefCountedStaticMemory> response(
    257       GetContentClient()->GetDataResourceBytes(idr));
    258   callback.Run(response.get());
    259 }
    260 
    261 }  // namespace content
    262