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