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 "grit/webui_resources.h" 15 #include "ui/base/layout.h" 16 #include "ui/base/resource/resource_bundle.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 27 UseVersion2::UseVersion2() { 28 g_version2++; 29 } 30 31 UseVersion2::~UseVersion2() { 32 g_version2--; 33 } 34 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 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 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 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 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 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 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 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 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