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/local_files_ntp_source.h"
19 #include "chrome/browser/search/search.h"
20 #include "chrome/browser/search_engines/template_url_service_factory.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/url_constants.h"
23 #include "chrome/grit/generated_resources.h"
24 #include "components/search_engines/template_url_prepopulate_data.h"
25 #include "components/search_engines/template_url_service.h"
26 #include "grit/browser_resources.h"
27 #include "grit/theme_resources.h"
28 #include "net/url_request/url_request.h"
29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/resource/resource_bundle.h"
31 #include "ui/base/ui_base_switches.h"
32 #include "ui/base/webui/jstemplate_builder.h"
33 #include "ui/base/webui/web_ui_util.h"
34 #include "ui/resources/grit/ui_resources.h"
39 // Signifies a locally constructed resource, i.e. not from grit/.
40 const int kLocalResource
= -1;
42 const char kConfigDataFilename
[] = "config.js";
44 const struct Resource
{
47 const char* mime_type
;
49 { "local-ntp.html", IDR_LOCAL_NTP_HTML
, "text/html" },
50 { "local-ntp.js", IDR_LOCAL_NTP_JS
, "application/javascript" },
51 { kConfigDataFilename
, kLocalResource
, "application/javascript" },
52 { "local-ntp.css", IDR_LOCAL_NTP_CSS
, "text/css" },
53 { "images/close_2.png", IDR_CLOSE_2
, "image/png" },
54 { "images/close_2_hover.png", IDR_CLOSE_2_H
, "image/png" },
55 { "images/close_2_active.png", IDR_CLOSE_2_P
, "image/png" },
56 { "images/close_2_white.png", IDR_CLOSE_2_MASK
, "image/png" },
57 { "images/close_3_mask.png", IDR_CLOSE_3_MASK
, "image/png" },
58 { "images/close_4_button.png", IDR_CLOSE_4_BUTTON
, "image/png" },
59 { "images/google_logo.png", IDR_LOCAL_NTP_IMAGES_LOGO_PNG
, "image/png" },
60 { "images/white_google_logo.png",
61 IDR_LOCAL_NTP_IMAGES_WHITE_LOGO_PNG
, "image/png" },
62 { "images/ntp_default_favicon.png", IDR_NTP_DEFAULT_FAVICON
, "image/png" },
65 // Strips any query parameters from the specified path.
66 std::string
StripParameters(const std::string
& path
) {
67 return path
.substr(0, path
.find("?"));
70 bool DefaultSearchProviderIsGoogle(Profile
* profile
) {
74 TemplateURLService
* template_url_service
=
75 TemplateURLServiceFactory::GetForProfile(profile
);
76 if (!template_url_service
)
79 const TemplateURL
* default_provider
=
80 template_url_service
->GetDefaultSearchProvider();
81 return default_provider
&&
82 (TemplateURLPrepopulateData::GetEngineType(
83 *default_provider
, template_url_service
->search_terms_data()) ==
84 SEARCH_ENGINE_GOOGLE
);
87 // Returns whether icon NTP is enabled by experiment.
88 // TODO(huangs): Remove all 3 copies of this routine once Icon NTP launches.
89 bool IsIconNTPEnabled() {
90 // Note: It's important to query the field trial state first, to ensure that
91 // UMA reports the correct group.
92 const std::string group_name
= base::FieldTrialList::FindFullName("IconNTP");
93 using base::CommandLine
;
94 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableIconNtp
))
96 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableIconNtp
))
99 return base::StartsWith(group_name
, "Enabled", base::CompareCase::SENSITIVE
);
102 // Adds a localized string keyed by resource id to the dictionary.
103 void AddString(base::DictionaryValue
* dictionary
,
104 const std::string
& key
,
106 dictionary
->SetString(key
, l10n_util::GetStringUTF16(resource_id
));
109 // Adds a localized string for the Google searchbox placeholder text.
110 void AddGoogleSearchboxPlaceholderString(base::DictionaryValue
* dictionary
) {
111 base::string16 placeholder
= l10n_util::GetStringFUTF16(
112 IDS_SEARCH_BOX_EMPTY_HINT
,
113 base::ASCIIToUTF16("Google"));
114 dictionary
->SetString("searchboxPlaceholder", placeholder
);
117 // Populates |translated_strings| dictionary for the local NTP. |is_google|
118 // indicates that this page is the Google Local NTP.
119 scoped_ptr
<base::DictionaryValue
> GetTranslatedStrings(bool is_google
) {
120 scoped_ptr
<base::DictionaryValue
> translated_strings(
121 new base::DictionaryValue());
123 AddString(translated_strings
.get(), "thumbnailRemovedNotification",
124 IDS_NEW_TAB_THUMBNAIL_REMOVED_NOTIFICATION
);
125 AddString(translated_strings
.get(), "removeThumbnailTooltip",
126 IDS_NEW_TAB_REMOVE_THUMBNAIL_TOOLTIP
);
127 AddString(translated_strings
.get(), "undoThumbnailRemove",
128 IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE
);
129 AddString(translated_strings
.get(), "restoreThumbnailsShort",
130 IDS_NEW_TAB_RESTORE_THUMBNAILS_SHORT_LINK
);
131 AddString(translated_strings
.get(), "attributionIntro",
132 IDS_NEW_TAB_ATTRIBUTION_INTRO
);
133 AddString(translated_strings
.get(), "title", IDS_NEW_TAB_TITLE
);
135 AddGoogleSearchboxPlaceholderString(translated_strings
.get());
137 return translated_strings
.Pass();
140 // Returns a JS dictionary of configuration data for the local NTP.
141 std::string
GetConfigData(Profile
* profile
) {
142 base::DictionaryValue config_data
;
143 bool is_google
= DefaultSearchProviderIsGoogle(profile
) &&
144 search::ShouldShowGoogleLocalNTP();
145 config_data
.Set("translatedStrings",
146 GetTranslatedStrings(is_google
).release());
147 config_data
.SetBoolean("isGooglePage", is_google
);
148 config_data
.SetBoolean("useIcons", IsIconNTPEnabled());
150 // Serialize the dictionary.
152 JSONStringValueSerializer
serializer(&js_text
);
153 serializer
.Serialize(config_data
);
155 std::string config_data_js
;
156 config_data_js
.append("var configData = ");
157 config_data_js
.append(js_text
);
158 config_data_js
.append(";");
159 return config_data_js
;
162 std::string
GetLocalNtpPath() {
163 return std::string(chrome::kChromeSearchScheme
) + "://" +
164 std::string(chrome::kChromeSearchLocalNtpHost
) + "/";
169 LocalNtpSource::LocalNtpSource(Profile
* profile
) : profile_(profile
) {
172 LocalNtpSource::~LocalNtpSource() {
175 std::string
LocalNtpSource::GetSource() const {
176 return chrome::kChromeSearchLocalNtpHost
;
179 void LocalNtpSource::StartDataRequest(
180 const std::string
& path
,
181 int render_process_id
,
183 const content::URLDataSource::GotDataCallback
& callback
) {
184 std::string stripped_path
= StripParameters(path
);
185 if (stripped_path
== kConfigDataFilename
) {
186 std::string config_data_js
= GetConfigData(profile_
);
187 callback
.Run(base::RefCountedString::TakeString(&config_data_js
));
191 #if !defined(OFFICIAL_BUILD)
192 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
193 if (command_line
->HasSwitch(switches::kLocalNtpReload
)) {
194 if (stripped_path
== "local-ntp.html" || stripped_path
== "local-ntp.js" ||
195 stripped_path
== "local-ntp.css") {
196 base::ReplaceChars(stripped_path
, "-", "_", &stripped_path
);
197 local_ntp::SendLocalFileResource(stripped_path
, callback
);
204 std::string filename
;
205 webui::ParsePathAndScale(
206 GURL(GetLocalNtpPath() + stripped_path
), &filename
, &scale
);
207 ui::ScaleFactor scale_factor
= ui::GetSupportedScaleFactor(scale
);
209 for (size_t i
= 0; i
< arraysize(kResources
); ++i
) {
210 if (filename
== kResources
[i
].filename
) {
211 scoped_refptr
<base::RefCountedStaticMemory
> response(
212 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
213 kResources
[i
].identifier
, scale_factor
));
214 callback
.Run(response
.get());
221 std::string
LocalNtpSource::GetMimeType(
222 const std::string
& path
) const {
223 const std::string stripped_path
= StripParameters(path
);
224 for (size_t i
= 0; i
< arraysize(kResources
); ++i
) {
225 if (stripped_path
== kResources
[i
].filename
)
226 return kResources
[i
].mime_type
;
228 return std::string();
231 bool LocalNtpSource::ShouldServiceRequest(
232 const net::URLRequest
* request
) const {
233 DCHECK(request
->url().host() == chrome::kChromeSearchLocalNtpHost
);
234 if (!InstantIOContext::ShouldServiceRequest(request
))
237 if (request
->url().SchemeIs(chrome::kChromeSearchScheme
)) {
238 std::string filename
;
239 webui::ParsePathAndScale(request
->url(), &filename
, NULL
);
240 for (size_t i
= 0; i
< arraysize(kResources
); ++i
) {
241 if (filename
== kResources
[i
].filename
)
248 std::string
LocalNtpSource::GetContentSecurityPolicyFrameSrc() const {
249 // Allow embedding of most visited iframes.
250 return base::StringPrintf("frame-src %s;",
251 chrome::kChromeSearchMostVisitedUrl
);