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