1// Copyright 2014 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 "chrome/browser/search/contextual_search_promo_source_android.h"
6
7#include <string>
8
9#include "base/json/json_string_value_serializer.h"
10#include "base/memory/ref_counted_memory.h"
11#include "base/strings/string_util.h"
12#include "base/strings/stringprintf.h"
13#include "base/values.h"
14#include "chrome/common/url_constants.h"
15#include "chrome/grit/chromium_strings.h"
16#include "components/variations/variations_associated_data.h"
17#include "grit/browser_resources.h"
18#include "ui/base/l10n/l10n_util.h"
19#include "ui/base/resource/resource_bundle.h"
20#include "ui/base/webui/jstemplate_builder.h"
21#include "url/gurl.h"
22
23namespace {
24
25const char kPromoConfigPath[] = "/config.js";
26const char kPromoHTMLPath[] = "/promo.html";
27const char kPromoCSSPath[] = "/promo.css";
28const char kPromoJSPath[] = "/promo.js";
29const char kRobotoWoffPath[] = "/roboto.woff";
30const char kRobotoWoff2Path[] = "/roboto.woff2";
31
32// Field trial related constants.
33const char kContextualSearchFieldTrialName[] = "ContextualSearch";
34const char kContextualSearchHidePromoHeaderParam[] = "hide_promo_header";
35const char kContextualSearchEnabledValue[] = "enabled";
36
37// Returns whether we should hide the first-run promo header.
38bool ShouldHidePromoHeader() {
39  return variations::GetVariationParamValue(
40      kContextualSearchFieldTrialName, kContextualSearchHidePromoHeaderParam) ==
41          kContextualSearchEnabledValue;
42}
43
44// Returns a JS dictionary of configuration data for the Contextual Search
45// promo.
46std::string GetConfigData() {
47  base::DictionaryValue config_data;
48  config_data.SetBoolean("hideHeader", ShouldHidePromoHeader());
49
50  // Serialize the dictionary.
51  std::string js_text;
52  JSONStringValueSerializer serializer(&js_text);
53  serializer.Serialize(config_data);
54
55  std::string config_data_js;
56  config_data_js.append("var config = ");
57  config_data_js.append(js_text);
58  config_data_js.append(";");
59  return config_data_js;
60}
61
62}  // namespace
63
64ContextualSearchPromoSourceAndroid::ContextualSearchPromoSourceAndroid() {}
65
66ContextualSearchPromoSourceAndroid::~ContextualSearchPromoSourceAndroid() {}
67
68void ContextualSearchPromoSourceAndroid::StartDataRequest(
69    const std::string& path_and_query, int render_process_id,
70    int render_frame_id,
71    const content::URLDataSource::GotDataCallback& callback) {
72  GURL url(std::string(chrome::kChromeUIContextualSearchPromoURL) + "/" +
73           path_and_query);
74  std::string path(url.path());
75  if (path == kPromoHTMLPath) {
76    SendHtmlWithStrings(callback);
77  } else if (path == kPromoCSSPath) {
78    SendResource(IDR_CONTEXTUAL_SEARCH_PROMO_CSS, callback);
79  } else if (path == kPromoJSPath) {
80    SendResource(IDR_CONTEXTUAL_SEARCH_PROMO_JS, callback);
81  } else if (path == kPromoConfigPath) {
82    SendConfigResource(callback);
83  } else if (path == kRobotoWoffPath) {
84    SendResource(IDR_ROBOTO_WOFF, callback);
85  } else if (path == kRobotoWoff2Path) {
86    SendResource(IDR_ROBOTO_WOFF2, callback);
87  } else {
88    callback.Run(NULL);
89  }
90}
91
92std::string ContextualSearchPromoSourceAndroid::GetSource() const {
93  return chrome::kChromeUIContextualSearchPromoHost;
94}
95
96std::string ContextualSearchPromoSourceAndroid::GetMimeType(
97    const std::string& path_and_query) const {
98  std::string path(GURL("chrome://host/" + path_and_query).path());
99  if (EndsWith(path, ".js", false)) return "application/javascript";
100  if (EndsWith(path, ".png", false)) return "image/png";
101  if (EndsWith(path, ".css", false)) return "text/css";
102  if (EndsWith(path, ".html", false)) return "text/html";
103  if (EndsWith(path, ".woff", false)) return "font/woff";
104  if (EndsWith(path, ".woff2", false)) return "font/woff2";
105  return "";
106}
107
108bool ContextualSearchPromoSourceAndroid::ShouldDenyXFrameOptions() const {
109  return false;
110}
111
112bool
113ContextualSearchPromoSourceAndroid::ShouldAddContentSecurityPolicy() const {
114  return false;
115}
116
117void ContextualSearchPromoSourceAndroid::SendResource(
118    int resource_id, const content::URLDataSource::GotDataCallback& callback) {
119  scoped_refptr<base::RefCountedStaticMemory> response(
120      ResourceBundle::GetSharedInstance().LoadDataResourceBytes(resource_id));
121  callback.Run(response.get());
122}
123
124void ContextualSearchPromoSourceAndroid::SendConfigResource(
125    const content::URLDataSource::GotDataCallback& callback) {
126  std::string response = GetConfigData();
127  callback.Run(base::RefCountedString::TakeString(&response));
128}
129
130void ContextualSearchPromoSourceAndroid::SendHtmlWithStrings(
131    const content::URLDataSource::GotDataCallback& callback) {
132  base::DictionaryValue strings_data;
133  // The three following statements are part of the description paragraph.
134  strings_data.SetString(
135      "description-1",
136      l10n_util::GetStringUTF16(IDS_CONTEXTUAL_SEARCH_PROMO_DESCRIPTION_1));
137  strings_data.SetString(
138      "feature-name",
139      l10n_util::GetStringUTF16(IDS_CONTEXTUAL_SEARCH_PROMO_FEATURE_NAME));
140  strings_data.SetString(
141      "description-2",
142      l10n_util::GetStringUTF16(IDS_CONTEXTUAL_SEARCH_PROMO_DESCRIPTION_2));
143
144  strings_data.SetString(
145      "heading", l10n_util::GetStringUTF16(IDS_CONTEXTUAL_SEARCH_HEADER));
146  strings_data.SetString(
147      "optIn", l10n_util::GetStringUTF16(IDS_CONTEXTUAL_SEARCH_PROMO_OPTIN));
148  strings_data.SetString(
149      "optOut", l10n_util::GetStringUTF16(IDS_CONTEXTUAL_SEARCH_PROMO_OPTOUT));
150  base::StringPiece html(
151      ResourceBundle::GetSharedInstance().GetRawDataResource(
152         IDR_CONTEXTUAL_SEARCH_PROMO_HTML));
153  webui::UseVersion2 version;
154  std::string response(webui::GetI18nTemplateHtml(html, &strings_data));
155  callback.Run(base::RefCountedString::TakeString(&response));
156}
157