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