Home | History | Annotate | Download | only in webui
      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 // A helper function for using JsTemplate. See jstemplate_builder.h for more
      6 // info.
      7 
      8 #include "ui/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