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