Unwind the URL-based experiment IDs.
[chromium-blink-merge.git] / chrome / browser / search / local_ntp_source.cc
blobf19084040e4d2fb9a666fc5bb37035f31bdaae5d
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.
5 #include "chrome/browser/search/local_ntp_source.h"
7 #include "base/command_line.h"
8 #include "base/json/json_string_value_serializer.h"
9 #include "base/logging.h"
10 #include "base/memory/ref_counted_memory.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/values.h"
17 #include "chrome/browser/search/instant_io_context.h"
18 #include "chrome/browser/search/search.h"
19 #include "chrome/browser/search_engines/template_url_service_factory.h"
20 #include "chrome/common/url_constants.h"
21 #include "chrome/grit/generated_resources.h"
22 #include "components/search_engines/template_url_prepopulate_data.h"
23 #include "components/search_engines/template_url_service.h"
24 #include "grit/browser_resources.h"
25 #include "grit/theme_resources.h"
26 #include "net/url_request/url_request.h"
27 #include "ui/base/l10n/l10n_util.h"
28 #include "ui/base/resource/resource_bundle.h"
29 #include "ui/base/ui_base_switches.h"
30 #include "ui/base/webui/jstemplate_builder.h"
31 #include "ui/base/webui/web_ui_util.h"
32 #include "ui/resources/grit/ui_resources.h"
33 #include "url/gurl.h"
35 namespace {
37 // Signifies a locally constructed resource, i.e. not from grit/.
38 const int kLocalResource = -1;
40 const char kConfigDataFilename[] = "config.js";
42 const struct Resource{
43 const char* filename;
44 int identifier;
45 const char* mime_type;
46 } kResources[] = {
47 { "local-ntp.html", IDR_LOCAL_NTP_HTML, "text/html" },
48 { "local-ntp.js", IDR_LOCAL_NTP_JS, "application/javascript" },
49 { kConfigDataFilename, kLocalResource, "application/javascript" },
50 { "local-ntp.css", IDR_LOCAL_NTP_CSS, "text/css" },
51 { "images/close_2.png", IDR_CLOSE_2, "image/png" },
52 { "images/close_2_hover.png", IDR_CLOSE_2_H, "image/png" },
53 { "images/close_2_active.png", IDR_CLOSE_2_P, "image/png" },
54 { "images/close_2_white.png", IDR_CLOSE_2_MASK, "image/png" },
55 { "images/close_3_mask.png", IDR_CLOSE_3_MASK, "image/png" },
56 { "images/close_4_button.png", IDR_CLOSE_4_BUTTON, "image/png" },
57 { "images/google_logo.png", IDR_LOCAL_NTP_IMAGES_LOGO_PNG, "image/png" },
58 { "images/white_google_logo.png",
59 IDR_LOCAL_NTP_IMAGES_WHITE_LOGO_PNG, "image/png" },
60 { "images/ntp_default_favicon.png", IDR_NTP_DEFAULT_FAVICON, "image/png" },
63 // Strips any query parameters from the specified path.
64 std::string StripParameters(const std::string& path) {
65 return path.substr(0, path.find("?"));
68 bool DefaultSearchProviderIsGoogle(Profile* profile) {
69 if (!profile)
70 return false;
72 TemplateURLService* template_url_service =
73 TemplateURLServiceFactory::GetForProfile(profile);
74 if (!template_url_service)
75 return false;
77 const TemplateURL* default_provider =
78 template_url_service->GetDefaultSearchProvider();
79 return default_provider &&
80 (TemplateURLPrepopulateData::GetEngineType(
81 *default_provider, template_url_service->search_terms_data()) ==
82 SEARCH_ENGINE_GOOGLE);
85 // Returns whether icon NTP is enabled by experiment.
86 // TODO(huangs): Remove all 3 copies of this routine once Icon NTP launches.
87 bool IsIconNTPEnabled() {
88 // Note: It's important to query the field trial state first, to ensure that
89 // UMA reports the correct group.
90 const std::string group_name = base::FieldTrialList::FindFullName("IconNTP");
91 using base::CommandLine;
92 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableIconNtp))
93 return false;
94 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableIconNtp))
95 return true;
97 return StartsWithASCII(group_name, "Enabled", true);
100 // Returns whether we are in the Fast NTP experiment or not.
101 bool IsLocalNTPFastEnabled() {
102 return StartsWithASCII(base::FieldTrialList::FindFullName("LocalNTPFast"),
103 "Enabled", true);
106 // Serves a particular resource.
107 // Used for bypassing the default resources when we are in an experiment.
108 void SendResource(int resource_id,
109 const content::URLDataSource::GotDataCallback& callback) {
110 scoped_refptr<base::RefCountedStaticMemory> response(
111 ResourceBundle::GetSharedInstance().LoadDataResourceBytes(resource_id));
112 callback.Run(response.get());
115 // Adds a localized string keyed by resource id to the dictionary.
116 void AddString(base::DictionaryValue* dictionary,
117 const std::string& key,
118 int resource_id) {
119 dictionary->SetString(key, l10n_util::GetStringUTF16(resource_id));
122 // Adds a localized string for the Google searchbox placeholder text.
123 void AddGoogleSearchboxPlaceholderString(base::DictionaryValue* dictionary) {
124 base::string16 placeholder = l10n_util::GetStringFUTF16(
125 IDS_OMNIBOX_EMPTY_HINT_WITH_DEFAULT_SEARCH_PROVIDER,
126 base::ASCIIToUTF16("Google"));
127 dictionary->SetString("searchboxPlaceholder", placeholder);
130 // Populates |translated_strings| dictionary for the local NTP. |is_google|
131 // indicates that this page is the Google Local NTP.
132 scoped_ptr<base::DictionaryValue> GetTranslatedStrings(bool is_google) {
133 scoped_ptr<base::DictionaryValue> translated_strings(
134 new base::DictionaryValue());
136 AddString(translated_strings.get(), "thumbnailRemovedNotification",
137 IDS_NEW_TAB_THUMBNAIL_REMOVED_NOTIFICATION);
138 AddString(translated_strings.get(), "removeThumbnailTooltip",
139 IDS_NEW_TAB_REMOVE_THUMBNAIL_TOOLTIP);
140 AddString(translated_strings.get(), "undoThumbnailRemove",
141 IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE);
142 AddString(translated_strings.get(), "restoreThumbnailsShort",
143 IDS_NEW_TAB_RESTORE_THUMBNAILS_SHORT_LINK);
144 AddString(translated_strings.get(), "attributionIntro",
145 IDS_NEW_TAB_ATTRIBUTION_INTRO);
146 AddString(translated_strings.get(), "title", IDS_NEW_TAB_TITLE);
147 if (is_google)
148 AddGoogleSearchboxPlaceholderString(translated_strings.get());
150 return translated_strings.Pass();
153 // Returns a JS dictionary of configuration data for the local NTP.
154 std::string GetConfigData(Profile* profile) {
155 base::DictionaryValue config_data;
156 bool is_google = DefaultSearchProviderIsGoogle(profile) &&
157 chrome::ShouldShowGoogleLocalNTP();
158 config_data.Set("translatedStrings",
159 GetTranslatedStrings(is_google).release());
160 config_data.SetBoolean("isGooglePage", is_google);
161 config_data.SetBoolean("useIcons", IsIconNTPEnabled());
163 // Serialize the dictionary.
164 std::string js_text;
165 JSONStringValueSerializer serializer(&js_text);
166 serializer.Serialize(config_data);
168 std::string config_data_js;
169 config_data_js.append("var configData = ");
170 config_data_js.append(js_text);
171 config_data_js.append(";");
172 return config_data_js;
175 std::string GetLocalNtpPath() {
176 return std::string(chrome::kChromeSearchScheme) + "://" +
177 std::string(chrome::kChromeSearchLocalNtpHost) + "/";
180 } // namespace
182 LocalNtpSource::LocalNtpSource(Profile* profile) : profile_(profile) {
185 LocalNtpSource::~LocalNtpSource() {
188 std::string LocalNtpSource::GetSource() const {
189 return chrome::kChromeSearchLocalNtpHost;
192 void LocalNtpSource::StartDataRequest(
193 const std::string& path,
194 int render_process_id,
195 int render_frame_id,
196 const content::URLDataSource::GotDataCallback& callback) {
197 const std::string stripped_path = StripParameters(path);
198 if (stripped_path == kConfigDataFilename) {
199 std::string config_data_js = GetConfigData(profile_);
200 callback.Run(base::RefCountedString::TakeString(&config_data_js));
201 return;
203 if (IsLocalNTPFastEnabled()) {
204 if (stripped_path == "local-ntp.html") {
205 return SendResource(IDR_LOCAL_NTP_FAST_HTML, callback);
206 } else if (stripped_path == "local-ntp.js") {
207 return SendResource(IDR_LOCAL_NTP_FAST_JS, callback);
208 } else if (stripped_path == "local-ntp.css") {
209 return SendResource(IDR_LOCAL_NTP_FAST_CSS, callback);
212 float scale = 1.0f;
213 std::string filename;
214 webui::ParsePathAndScale(
215 GURL(GetLocalNtpPath() + stripped_path), &filename, &scale);
216 ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactor(scale);
217 for (size_t i = 0; i < arraysize(kResources); ++i) {
218 if (filename == kResources[i].filename) {
219 scoped_refptr<base::RefCountedStaticMemory> response(
220 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
221 kResources[i].identifier, scale_factor));
222 callback.Run(response.get());
223 return;
226 callback.Run(NULL);
229 std::string LocalNtpSource::GetMimeType(
230 const std::string& path) const {
231 const std::string stripped_path = StripParameters(path);
232 for (size_t i = 0; i < arraysize(kResources); ++i) {
233 if (stripped_path == kResources[i].filename)
234 return kResources[i].mime_type;
236 return std::string();
239 bool LocalNtpSource::ShouldServiceRequest(
240 const net::URLRequest* request) const {
241 DCHECK(request->url().host() == chrome::kChromeSearchLocalNtpHost);
242 if (!InstantIOContext::ShouldServiceRequest(request))
243 return false;
245 if (request->url().SchemeIs(chrome::kChromeSearchScheme)) {
246 std::string filename;
247 webui::ParsePathAndScale(request->url(), &filename, NULL);
248 for (size_t i = 0; i < arraysize(kResources); ++i) {
249 if (filename == kResources[i].filename)
250 return true;
253 return false;
256 std::string LocalNtpSource::GetContentSecurityPolicyFrameSrc() const {
257 // Allow embedding of most visited iframes.
258 return base::StringPrintf("frame-src %s;",
259 chrome::kChromeSearchMostVisitedUrl);