Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / search / local_ntp_source.cc
blob2485cc65234d9e741a80cfb732005d75816563c1
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/json/json_string_value_serializer.h"
8 #include "base/logging.h"
9 #include "base/memory/ref_counted_memory.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/metrics/field_trial.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "chrome/browser/search/instant_io_context.h"
17 #include "chrome/browser/search/search.h"
18 #include "chrome/browser/search_engines/template_url_service_factory.h"
19 #include "chrome/common/url_constants.h"
20 #include "chrome/grit/generated_resources.h"
21 #include "components/search_engines/template_url_prepopulate_data.h"
22 #include "components/search_engines/template_url_service.h"
23 #include "grit/browser_resources.h"
24 #include "grit/theme_resources.h"
25 #include "net/url_request/url_request.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/base/webui/jstemplate_builder.h"
29 #include "ui/base/webui/web_ui_util.h"
30 #include "ui/resources/grit/ui_resources.h"
31 #include "url/gurl.h"
33 namespace {
35 // Constants related to the Material Design NTP field trial.
36 const char kMaterialDesignNTPFieldTrialName[] = "MaterialDesignNTP";
37 const char kMaterialDesignNTPFieldTrialEnabledPrefix[] = "Enabled";
39 // Names of NTP designs in local resources, also used in CSS.
40 const char kClassicalNTPName[] = "classical";
41 const char kMaterialDesignNTPName[] = "md";
43 // Signifies a locally constructed resource, i.e. not from grit/.
44 const int kLocalResource = -1;
46 const char kConfigDataFilename[] = "config.js";
47 const char kLocalNTPFilename[] = "local-ntp.html";
49 const struct Resource{
50 const char* filename;
51 int identifier;
52 const char* mime_type;
53 } kResources[] = {
54 { kLocalNTPFilename, IDR_LOCAL_NTP_HTML, "text/html" },
55 { "local-ntp.js", IDR_LOCAL_NTP_JS, "application/javascript" },
56 { kConfigDataFilename, kLocalResource, "application/javascript" },
57 { "local-ntp.css", IDR_LOCAL_NTP_CSS, "text/css" },
58 { "images/close_2.png", IDR_CLOSE_2, "image/png" },
59 { "images/close_2_hover.png", IDR_CLOSE_2_H, "image/png" },
60 { "images/close_2_active.png", IDR_CLOSE_2_P, "image/png" },
61 { "images/close_2_white.png", IDR_CLOSE_2_MASK, "image/png" },
62 { "images/close_3_mask.png", IDR_CLOSE_3_MASK, "image/png" },
63 { "images/google_logo.png", IDR_LOCAL_NTP_IMAGES_LOGO_PNG, "image/png" },
64 { "images/white_google_logo.png",
65 IDR_LOCAL_NTP_IMAGES_WHITE_LOGO_PNG, "image/png" },
66 { "images/ntp_default_favicon.png", IDR_NTP_DEFAULT_FAVICON, "image/png" },
69 // Strips any query parameters from the specified path.
70 std::string StripParameters(const std::string& path) {
71 return path.substr(0, path.find("?"));
74 bool DefaultSearchProviderIsGoogle(Profile* profile) {
75 if (!profile)
76 return false;
78 TemplateURLService* template_url_service =
79 TemplateURLServiceFactory::GetForProfile(profile);
80 if (!template_url_service)
81 return false;
83 const TemplateURL* default_provider =
84 template_url_service->GetDefaultSearchProvider();
85 return default_provider &&
86 (TemplateURLPrepopulateData::GetEngineType(
87 *default_provider, template_url_service->search_terms_data()) ==
88 SEARCH_ENGINE_GOOGLE);
91 // Returns whether the user is part of a group where the Material Design NTP is
92 // enabled.
93 bool IsMaterialDesignEnabled() {
94 return StartsWithASCII(
95 base::FieldTrialList::FindFullName(kMaterialDesignNTPFieldTrialName),
96 kMaterialDesignNTPFieldTrialEnabledPrefix, true);
99 // Adds a localized string keyed by resource id to the dictionary.
100 void AddString(base::DictionaryValue* dictionary,
101 const std::string& key,
102 int resource_id) {
103 dictionary->SetString(key, l10n_util::GetStringUTF16(resource_id));
106 // Adds a localized string for the Google searchbox placeholder text.
107 void AddGoogleSearchboxPlaceholderString(base::DictionaryValue* dictionary) {
108 base::string16 placeholder = l10n_util::GetStringFUTF16(
109 IDS_OMNIBOX_EMPTY_HINT_WITH_DEFAULT_SEARCH_PROVIDER,
110 base::ASCIIToUTF16("Google"));
111 dictionary->SetString("searchboxPlaceholder", placeholder);
114 // Populates |translated_strings| dictionary for the local NTP. |is_google|
115 // indicates that this page is the Google Local NTP.
116 scoped_ptr<base::DictionaryValue> GetTranslatedStrings(bool is_google) {
117 scoped_ptr<base::DictionaryValue> translated_strings(
118 new base::DictionaryValue());
120 AddString(translated_strings.get(), "thumbnailRemovedNotification",
121 IDS_NEW_TAB_THUMBNAIL_REMOVED_NOTIFICATION);
122 AddString(translated_strings.get(), "removeThumbnailTooltip",
123 IDS_NEW_TAB_REMOVE_THUMBNAIL_TOOLTIP);
124 AddString(translated_strings.get(), "undoThumbnailRemove",
125 IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE);
126 AddString(translated_strings.get(), "restoreThumbnailsShort",
127 IDS_NEW_TAB_RESTORE_THUMBNAILS_SHORT_LINK);
128 AddString(translated_strings.get(), "attributionIntro",
129 IDS_NEW_TAB_ATTRIBUTION_INTRO);
130 AddString(translated_strings.get(), "title", IDS_NEW_TAB_TITLE);
131 if (is_google)
132 AddGoogleSearchboxPlaceholderString(translated_strings.get());
134 return translated_strings.Pass();
137 // Returns a JS dictionary of configuration data for the local NTP.
138 std::string GetConfigData(Profile* profile) {
139 base::DictionaryValue config_data;
140 bool is_google = DefaultSearchProviderIsGoogle(profile) &&
141 chrome::ShouldShowGoogleLocalNTP();
142 config_data.Set("translatedStrings",
143 GetTranslatedStrings(is_google).release());
144 config_data.SetBoolean("isGooglePage", is_google);
145 if (IsMaterialDesignEnabled()) {
146 scoped_ptr<base::Value> design_value(
147 new base::StringValue(kMaterialDesignNTPName));
148 config_data.Set("ntpDesignName", design_value.release());
151 // Serialize the dictionary.
152 std::string js_text;
153 JSONStringValueSerializer serializer(&js_text);
154 serializer.Serialize(config_data);
156 std::string config_data_js;
157 config_data_js.append("var configData = ");
158 config_data_js.append(js_text);
159 config_data_js.append(";");
160 return config_data_js;
163 std::string GetLocalNtpPath() {
164 return std::string(chrome::kChromeSearchScheme) + "://" +
165 std::string(chrome::kChromeSearchLocalNtpHost) + "/";
168 } // namespace
170 LocalNtpSource::LocalNtpSource(Profile* profile) : profile_(profile) {
173 LocalNtpSource::~LocalNtpSource() {
176 std::string LocalNtpSource::GetSource() const {
177 return chrome::kChromeSearchLocalNtpHost;
180 void LocalNtpSource::StartDataRequest(
181 const std::string& path,
182 int render_process_id,
183 int render_frame_id,
184 const content::URLDataSource::GotDataCallback& callback) {
185 const std::string stripped_path = StripParameters(path);
186 if (stripped_path == kConfigDataFilename) {
187 std::string config_data_js = GetConfigData(profile_);
188 callback.Run(base::RefCountedString::TakeString(&config_data_js));
189 return;
191 if (stripped_path == kLocalNTPFilename) {
192 SendResourceWithClass(
193 IDR_LOCAL_NTP_HTML,
194 IsMaterialDesignEnabled() ? kMaterialDesignNTPName : kClassicalNTPName,
195 callback);
196 return;
198 float scale = 1.0f;
199 std::string filename;
200 webui::ParsePathAndScale(
201 GURL(GetLocalNtpPath() + stripped_path), &filename, &scale);
202 ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactor(scale);
203 for (size_t i = 0; i < arraysize(kResources); ++i) {
204 if (filename == kResources[i].filename) {
205 scoped_refptr<base::RefCountedStaticMemory> response(
206 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
207 kResources[i].identifier, scale_factor));
208 callback.Run(response.get());
209 return;
212 callback.Run(NULL);
215 std::string LocalNtpSource::GetMimeType(
216 const std::string& path) const {
217 const std::string stripped_path = StripParameters(path);
218 for (size_t i = 0; i < arraysize(kResources); ++i) {
219 if (stripped_path == kResources[i].filename)
220 return kResources[i].mime_type;
222 return std::string();
225 bool LocalNtpSource::ShouldServiceRequest(
226 const net::URLRequest* request) const {
227 DCHECK(request->url().host() == chrome::kChromeSearchLocalNtpHost);
228 if (!InstantIOContext::ShouldServiceRequest(request))
229 return false;
231 if (request->url().SchemeIs(chrome::kChromeSearchScheme)) {
232 std::string filename;
233 webui::ParsePathAndScale(request->url(), &filename, NULL);
234 for (size_t i = 0; i < arraysize(kResources); ++i) {
235 if (filename == kResources[i].filename)
236 return true;
239 return false;
242 std::string LocalNtpSource::GetContentSecurityPolicyFrameSrc() const {
243 // Allow embedding of most visited iframes.
244 return base::StringPrintf("frame-src %s;",
245 chrome::kChromeSearchMostVisitedUrl);
248 void LocalNtpSource::SendResourceWithClass(
249 int resource_id,
250 const std::string& class_name,
251 const content::URLDataSource::GotDataCallback& callback) {
252 base::StringPiece resource_data =
253 ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id);
254 std::string response(resource_data.as_string());
255 ReplaceFirstSubstringAfterOffset(&response, 0, "{{CLASS}}", class_name);
256 callback.Run(base::RefCountedString::TakeString(&response));