• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 // A helper function for using JsTemplate. See jstemplate_builder.h for more
6 // info.
7 
8 #include "ui/base/webui/jstemplate_builder.h"
9 
10 #include "base/json/json_file_value_serializer.h"
11 #include "base/json/json_string_value_serializer.h"
12 #include "base/logging.h"
13 #include "base/strings/string_util.h"
14 #include "ui/base/layout.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "ui/resources/grit/webui_resources.h"
17 
18 namespace {
19 
20 // Non-zero when building version 2 templates. See UseVersion2 class.
21 int g_version2 = 0;
22 
23 }  // namespace
24 
25 namespace webui {
26 
UseVersion2()27 UseVersion2::UseVersion2() {
28   g_version2++;
29 }
30 
~UseVersion2()31 UseVersion2::~UseVersion2() {
32   g_version2--;
33 }
34 
GetTemplateHtml(const base::StringPiece & html_template,const base::DictionaryValue * json,const base::StringPiece & template_id)35 std::string GetTemplateHtml(const base::StringPiece& html_template,
36                             const base::DictionaryValue* json,
37                             const base::StringPiece& template_id) {
38   std::string output(html_template.data(), html_template.size());
39   AppendJsonHtml(json, &output);
40   AppendJsTemplateSourceHtml(&output);
41   AppendJsTemplateProcessHtml(template_id, &output);
42   return output;
43 }
44 
GetI18nTemplateHtml(const base::StringPiece & html_template,const base::DictionaryValue * json)45 std::string GetI18nTemplateHtml(const base::StringPiece& html_template,
46                                 const base::DictionaryValue* json) {
47   std::string output(html_template.data(), html_template.size());
48   AppendJsonHtml(json, &output);
49   AppendI18nTemplateSourceHtml(&output);
50   AppendI18nTemplateProcessHtml(&output);
51   return output;
52 }
53 
GetTemplatesHtml(const base::StringPiece & html_template,const base::DictionaryValue * json,const base::StringPiece & template_id)54 std::string GetTemplatesHtml(const base::StringPiece& html_template,
55                              const base::DictionaryValue* json,
56                              const base::StringPiece& template_id) {
57   std::string output(html_template.data(), html_template.size());
58   AppendI18nTemplateSourceHtml(&output);
59   AppendJsTemplateSourceHtml(&output);
60   AppendJsonHtml(json, &output);
61   AppendI18nTemplateProcessHtml(&output);
62   AppendJsTemplateProcessHtml(template_id, &output);
63   return output;
64 }
65 
AppendJsonHtml(const base::DictionaryValue * json,std::string * output)66 void AppendJsonHtml(const base::DictionaryValue* json, std::string* output) {
67   std::string javascript_string;
68   AppendJsonJS(json, &javascript_string);
69 
70   // </ confuses the HTML parser because it could be a </script> tag.  So we
71   // replace </ with <\/.  The extra \ will be ignored by the JS engine.
72   ReplaceSubstringsAfterOffset(&javascript_string, 0, "</", "<\\/");
73 
74   output->append("<script>");
75   output->append(javascript_string);
76   output->append("</script>");
77 }
78 
AppendJsonJS(const base::DictionaryValue * json,std::string * output)79 void AppendJsonJS(const base::DictionaryValue* json, std::string* output) {
80   // Convert the template data to a json string.
81   DCHECK(json) << "must include json data structure";
82 
83   std::string jstext;
84   JSONStringValueSerializer serializer(&jstext);
85   serializer.Serialize(*json);
86   output->append(g_version2 ? "loadTimeData.data = " : "var templateData = ");
87   output->append(jstext);
88   output->append(";");
89 }
90 
AppendJsTemplateSourceHtml(std::string * output)91 void AppendJsTemplateSourceHtml(std::string* output) {
92   // fetch and cache the pointer of the jstemplate resource source text.
93   static const base::StringPiece jstemplate_src(
94       ResourceBundle::GetSharedInstance().GetRawDataResource(
95           IDR_WEBUI_JSTEMPLATE_JS));
96 
97   if (jstemplate_src.empty()) {
98     NOTREACHED() << "Unable to get jstemplate src";
99     return;
100   }
101 
102   output->append("<script>");
103   output->append(jstemplate_src.data(), jstemplate_src.size());
104   output->append("</script>");
105 }
106 
AppendJsTemplateProcessHtml(const base::StringPiece & template_id,std::string * output)107 void AppendJsTemplateProcessHtml(const base::StringPiece& template_id,
108                                  std::string* output) {
109   output->append("<script>");
110   output->append("var tp = document.getElementById('");
111   output->append(template_id.data(), template_id.size());
112   output->append("');");
113   output->append("jstProcess(new JsEvalContext(templateData), tp);");
114   output->append("</script>");
115 }
116 
AppendI18nTemplateSourceHtml(std::string * output)117 void AppendI18nTemplateSourceHtml(std::string* output) {
118   // fetch and cache the pointer of the jstemplate resource source text.
119   static const base::StringPiece i18n_template_src(
120       ResourceBundle::GetSharedInstance().GetRawDataResource(
121           IDR_WEBUI_I18N_TEMPLATE_JS));
122   static const base::StringPiece i18n_template2_src(
123       ResourceBundle::GetSharedInstance().GetRawDataResource(
124           IDR_WEBUI_I18N_TEMPLATE2_JS));
125   const base::StringPiece* template_src = g_version2 ?
126       &i18n_template2_src : &i18n_template_src;
127 
128   if (template_src->empty()) {
129     NOTREACHED() << "Unable to get i18n template src";
130     return;
131   }
132 
133   output->append("<script>");
134   output->append(template_src->data(), template_src->size());
135   output->append("</script>");
136 }
137 
AppendI18nTemplateProcessHtml(std::string * output)138 void AppendI18nTemplateProcessHtml(std::string* output) {
139   if (g_version2)
140     return;
141 
142   static const base::StringPiece i18n_process_src(
143       ResourceBundle::GetSharedInstance().GetRawDataResource(
144           IDR_WEBUI_I18N_PROCESS_JS));
145 
146   if (i18n_process_src.empty()) {
147     NOTREACHED() << "Unable to get i18n process src";
148     return;
149   }
150 
151   output->append("<script>");
152   output->append(i18n_process_src.data(), i18n_process_src.size());
153   output->append("</script>");
154 }
155 
156 }  // namespace webui
157