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
Create(const std::string & source_name)21 WebUIDataSource* WebUIDataSource::Create(const std::string& source_name) {
22 return new WebUIDataSourceImpl(source_name);
23 }
24
25 // static
AddMojoDataSource(BrowserContext * browser_context)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
Add(BrowserContext * browser_context,WebUIDataSource * source)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:
InternalDataSource(WebUIDataSourceImpl * parent)59 InternalDataSource(WebUIDataSourceImpl* parent) : parent_(parent) {
60 }
61
~InternalDataSource()62 virtual ~InternalDataSource() {
63 }
64
65 // URLDataSource implementation.
GetSource() const66 virtual std::string GetSource() const OVERRIDE {
67 return parent_->GetSource();
68 }
GetMimeType(const std::string & path) const69 virtual std::string GetMimeType(const std::string& path) const OVERRIDE {
70 return parent_->GetMimeType(path);
71 }
StartDataRequest(const std::string & path,int render_process_id,int render_frame_id,const URLDataSource::GotDataCallback & callback)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 }
ShouldReplaceExistingSource() const80 virtual bool ShouldReplaceExistingSource() const OVERRIDE {
81 return parent_->replace_existing_source_;
82 }
AllowCaching() const83 virtual bool AllowCaching() const OVERRIDE {
84 return false;
85 }
ShouldAddContentSecurityPolicy() const86 virtual bool ShouldAddContentSecurityPolicy() const OVERRIDE {
87 return parent_->add_csp_;
88 }
GetContentSecurityPolicyObjectSrc() const89 virtual std::string GetContentSecurityPolicyObjectSrc() const OVERRIDE {
90 if (parent_->object_src_set_)
91 return parent_->object_src_;
92 return URLDataSource::GetContentSecurityPolicyObjectSrc();
93 }
GetContentSecurityPolicyFrameSrc() const94 virtual std::string GetContentSecurityPolicyFrameSrc() const OVERRIDE {
95 if (parent_->frame_src_set_)
96 return parent_->frame_src_;
97 return URLDataSource::GetContentSecurityPolicyFrameSrc();
98 }
ShouldDenyXFrameOptions() const99 virtual bool ShouldDenyXFrameOptions() const OVERRIDE {
100 return parent_->deny_xframe_options_;
101 }
102
103 private:
104 WebUIDataSourceImpl* parent_;
105 };
106
WebUIDataSourceImpl(const std::string & source_name)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
~WebUIDataSourceImpl()122 WebUIDataSourceImpl::~WebUIDataSourceImpl() {
123 }
124
AddString(const std::string & name,const base::string16 & value)125 void WebUIDataSourceImpl::AddString(const std::string& name,
126 const base::string16& value) {
127 localized_strings_.SetString(name, value);
128 }
129
AddString(const std::string & name,const std::string & value)130 void WebUIDataSourceImpl::AddString(const std::string& name,
131 const std::string& value) {
132 localized_strings_.SetString(name, value);
133 }
134
AddLocalizedString(const std::string & name,int ids)135 void WebUIDataSourceImpl::AddLocalizedString(const std::string& name,
136 int ids) {
137 localized_strings_.SetString(
138 name, GetContentClient()->GetLocalizedString(ids));
139 }
140
AddLocalizedStrings(const base::DictionaryValue & localized_strings)141 void WebUIDataSourceImpl::AddLocalizedStrings(
142 const base::DictionaryValue& localized_strings) {
143 localized_strings_.MergeDictionary(&localized_strings);
144 }
145
AddBoolean(const std::string & name,bool value)146 void WebUIDataSourceImpl::AddBoolean(const std::string& name, bool value) {
147 localized_strings_.SetBoolean(name, value);
148 }
149
SetJsonPath(const std::string & path)150 void WebUIDataSourceImpl::SetJsonPath(const std::string& path) {
151 json_path_ = path;
152 }
153
SetUseJsonJSFormatV2()154 void WebUIDataSourceImpl::SetUseJsonJSFormatV2() {
155 json_js_format_v2_ = true;
156 }
157
AddResourcePath(const std::string & path,int resource_id)158 void WebUIDataSourceImpl::AddResourcePath(const std::string &path,
159 int resource_id) {
160 path_to_idr_map_[path] = resource_id;
161 }
162
SetDefaultResource(int resource_id)163 void WebUIDataSourceImpl::SetDefaultResource(int resource_id) {
164 default_resource_ = resource_id;
165 }
166
SetRequestFilter(const WebUIDataSource::HandleRequestCallback & callback)167 void WebUIDataSourceImpl::SetRequestFilter(
168 const WebUIDataSource::HandleRequestCallback& callback) {
169 filter_callback_ = callback;
170 }
171
DisableReplaceExistingSource()172 void WebUIDataSourceImpl::DisableReplaceExistingSource() {
173 replace_existing_source_ = false;
174 }
175
DisableContentSecurityPolicy()176 void WebUIDataSourceImpl::DisableContentSecurityPolicy() {
177 add_csp_ = false;
178 }
179
OverrideContentSecurityPolicyObjectSrc(const std::string & data)180 void WebUIDataSourceImpl::OverrideContentSecurityPolicyObjectSrc(
181 const std::string& data) {
182 object_src_set_ = true;
183 object_src_ = data;
184 }
185
OverrideContentSecurityPolicyFrameSrc(const std::string & data)186 void WebUIDataSourceImpl::OverrideContentSecurityPolicyFrameSrc(
187 const std::string& data) {
188 frame_src_set_ = true;
189 frame_src_ = data;
190 }
191
DisableDenyXFrameOptions()192 void WebUIDataSourceImpl::DisableDenyXFrameOptions() {
193 deny_xframe_options_ = false;
194 }
195
GetSource() const196 std::string WebUIDataSourceImpl::GetSource() const {
197 return source_name_;
198 }
199
GetMimeType(const std::string & path) const200 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
StartDataRequest(const std::string & path,int render_process_id,int render_frame_id,const URLDataSource::GotDataCallback & callback)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
SendLocalizedStringsAsJSON(const URLDataSource::GotDataCallback & callback)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
SendFromResourceBundle(const URLDataSource::GotDataCallback & callback,int idr)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