OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/search/local_ntp_source.h" | 5 #include "chrome/browser/search/local_ntp_source.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 | 10 |
11 #include "base/base64.h" | |
11 #include "base/command_line.h" | 12 #include "base/command_line.h" |
12 #include "base/json/json_string_value_serializer.h" | 13 #include "base/json/json_string_value_serializer.h" |
13 #include "base/logging.h" | 14 #include "base/logging.h" |
14 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
15 #include "base/memory/ref_counted_memory.h" | 16 #include "base/memory/ref_counted_memory.h" |
16 #include "base/metrics/field_trial.h" | 17 #include "base/metrics/field_trial.h" |
17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
18 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
19 #include "base/values.h" | 20 #include "base/values.h" |
20 #include "build/build_config.h" | 21 #include "build/build_config.h" |
21 #include "chrome/browser/search/instant_io_context.h" | 22 #include "chrome/browser/search/instant_io_context.h" |
22 #include "chrome/browser/search/local_files_ntp_source.h" | 23 #include "chrome/browser/search/local_files_ntp_source.h" |
23 #include "chrome/browser/search_engines/template_url_service_factory.h" | 24 #include "chrome/browser/search_engines/template_url_service_factory.h" |
24 #include "chrome/browser/themes/theme_properties.h" | 25 #include "chrome/browser/themes/theme_properties.h" |
25 #include "chrome/browser/themes/theme_service.h" | 26 #include "chrome/browser/themes/theme_service.h" |
26 #include "chrome/browser/themes/theme_service_factory.h" | 27 #include "chrome/browser/themes/theme_service_factory.h" |
27 #include "chrome/common/chrome_switches.h" | 28 #include "chrome/common/chrome_switches.h" |
28 #include "chrome/common/url_constants.h" | 29 #include "chrome/common/url_constants.h" |
29 #include "chrome/grit/browser_resources.h" | 30 #include "chrome/grit/browser_resources.h" |
30 #include "chrome/grit/generated_resources.h" | 31 #include "chrome/grit/generated_resources.h" |
31 #include "chrome/grit/theme_resources.h" | 32 #include "chrome/grit/theme_resources.h" |
32 #include "components/search_engines/template_url_service.h" | 33 #include "components/search_engines/template_url_service.h" |
33 #include "components/strings/grit/components_strings.h" | 34 #include "components/strings/grit/components_strings.h" |
35 #include "crypto/secure_hash.h" | |
36 #include "net/base/hash_value.h" | |
34 #include "net/url_request/url_request.h" | 37 #include "net/url_request/url_request.h" |
35 #include "third_party/skia/include/core/SkColor.h" | 38 #include "third_party/skia/include/core/SkColor.h" |
36 #include "ui/base/l10n/l10n_util.h" | 39 #include "ui/base/l10n/l10n_util.h" |
37 #include "ui/base/resource/resource_bundle.h" | 40 #include "ui/base/resource/resource_bundle.h" |
38 #include "ui/base/webui/web_ui_util.h" | 41 #include "ui/base/webui/web_ui_util.h" |
39 #include "ui/resources/grit/ui_resources.h" | 42 #include "ui/resources/grit/ui_resources.h" |
40 #include "url/gurl.h" | 43 #include "url/gurl.h" |
41 | 44 |
42 namespace { | 45 namespace { |
43 | 46 |
44 // Signifies a locally constructed resource, i.e. not from grit/. | 47 // Signifies a locally constructed resource, i.e. not from grit/. |
45 const int kLocalResource = -1; | 48 const int kLocalResource = -1; |
46 | 49 |
47 const char kConfigDataFilename[] = "config.js"; | 50 const char kConfigDataFilename[] = "config.js"; |
48 const char kThemeCSSFilename[] = "theme.css"; | 51 const char kThemeCSSFilename[] = "theme.css"; |
52 const char kMainHtmlFilename[] = "local-ntp.html"; | |
49 | 53 |
50 const struct Resource{ | 54 const struct Resource{ |
51 const char* filename; | 55 const char* filename; |
52 int identifier; | 56 int identifier; |
53 const char* mime_type; | 57 const char* mime_type; |
54 } kResources[] = { | 58 } kResources[] = { |
55 {"local-ntp.html", IDR_LOCAL_NTP_HTML, "text/html"}, | 59 {kMainHtmlFilename, kLocalResource, "text/html"}, |
56 {"local-ntp.js", IDR_LOCAL_NTP_JS, "application/javascript"}, | 60 {"local-ntp.js", IDR_LOCAL_NTP_JS, "application/javascript"}, |
57 {kConfigDataFilename, kLocalResource, "application/javascript"}, | 61 {kConfigDataFilename, kLocalResource, "application/javascript"}, |
58 {kThemeCSSFilename, kLocalResource, "text/css"}, | 62 {kThemeCSSFilename, kLocalResource, "text/css"}, |
59 {"local-ntp.css", IDR_LOCAL_NTP_CSS, "text/css"}, | 63 {"local-ntp.css", IDR_LOCAL_NTP_CSS, "text/css"}, |
60 {"images/close_3_mask.png", IDR_CLOSE_3_MASK, "image/png"}, | 64 {"images/close_3_mask.png", IDR_CLOSE_3_MASK, "image/png"}, |
61 {"images/close_4_button.png", IDR_CLOSE_4_BUTTON, "image/png"}, | 65 {"images/close_4_button.png", IDR_CLOSE_4_BUTTON, "image/png"}, |
62 {"images/ntp_default_favicon.png", IDR_NTP_DEFAULT_FAVICON, "image/png"}, | 66 {"images/ntp_default_favicon.png", IDR_NTP_DEFAULT_FAVICON, "image/png"}, |
63 }; | 67 }; |
64 | 68 |
65 // Strips any query parameters from the specified path. | 69 // Strips any query parameters from the specified path. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
127 JSONStringValueSerializer serializer(&js_text); | 131 JSONStringValueSerializer serializer(&js_text); |
128 serializer.Serialize(config_data); | 132 serializer.Serialize(config_data); |
129 | 133 |
130 std::string config_data_js; | 134 std::string config_data_js; |
131 config_data_js.append("var configData = "); | 135 config_data_js.append("var configData = "); |
132 config_data_js.append(js_text); | 136 config_data_js.append(js_text); |
133 config_data_js.append(";"); | 137 config_data_js.append(";"); |
134 return config_data_js; | 138 return config_data_js; |
135 } | 139 } |
136 | 140 |
141 std::string GetIntegritySha256Value(const std::string& data) { | |
142 // Compute the sha256 hash. | |
143 net::SHA256HashValue hash_value; | |
144 std::unique_ptr<crypto::SecureHash> hash( | |
145 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); | |
146 hash->Update(data.data(), data.size()); | |
147 hash->Finish(&hash_value, sizeof(hash_value)); | |
148 | |
149 // Base64-encode it. | |
150 base::StringPiece hash_value_str(reinterpret_cast<char*>(hash_value.data), | |
151 sizeof(hash_value)); | |
152 std::string result; | |
153 base::Base64Encode(hash_value_str, &result); | |
154 return result; | |
155 } | |
156 | |
137 std::string GetThemeCSS(Profile* profile) { | 157 std::string GetThemeCSS(Profile* profile) { |
138 SkColor background_color = | 158 SkColor background_color = |
139 ThemeService::GetThemeProviderForProfile(profile) | 159 ThemeService::GetThemeProviderForProfile(profile) |
140 .GetColor(ThemeProperties::COLOR_NTP_BACKGROUND); | 160 .GetColor(ThemeProperties::COLOR_NTP_BACKGROUND); |
141 | 161 |
142 return base::StringPrintf("body { background-color: #%02X%02X%02X; }", | 162 return base::StringPrintf("body { background-color: #%02X%02X%02X; }", |
143 SkColorGetR(background_color), | 163 SkColorGetR(background_color), |
144 SkColorGetG(background_color), | 164 SkColorGetG(background_color), |
145 SkColorGetB(background_color)); | 165 SkColorGetB(background_color)); |
146 } | 166 } |
(...skipping 27 matching lines...) Expand all Loading... | |
174 std::string theme_css = GetThemeCSS(profile_); | 194 std::string theme_css = GetThemeCSS(profile_); |
175 callback.Run(base::RefCountedString::TakeString(&theme_css)); | 195 callback.Run(base::RefCountedString::TakeString(&theme_css)); |
176 return; | 196 return; |
177 } | 197 } |
178 | 198 |
179 #if !defined(GOOGLE_CHROME_BUILD) | 199 #if !defined(GOOGLE_CHROME_BUILD) |
180 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 200 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
181 if (command_line->HasSwitch(switches::kLocalNtpReload)) { | 201 if (command_line->HasSwitch(switches::kLocalNtpReload)) { |
182 if (stripped_path == "local-ntp.html" || stripped_path == "local-ntp.js" || | 202 if (stripped_path == "local-ntp.html" || stripped_path == "local-ntp.js" || |
183 stripped_path == "local-ntp.css") { | 203 stripped_path == "local-ntp.css") { |
204 // TODO(treib): This is now broken for the html file - need to insert the | |
205 // config hash. | |
Marc Treib
2017/04/07 16:46:15
...which would be somewhat annoying in terms of pl
sfiera
2017/04/10 08:53:21
What's it actually for? Live-editing the files in
Marc Treib
2017/04/10 10:11:18
Yup, it's for live-editing.
Good idea, I'll turn o
| |
184 base::ReplaceChars(stripped_path, "-", "_", &stripped_path); | 206 base::ReplaceChars(stripped_path, "-", "_", &stripped_path); |
185 local_ntp::SendLocalFileResource(stripped_path, callback); | 207 local_ntp::SendLocalFileResource(stripped_path, callback); |
186 return; | 208 return; |
187 } | 209 } |
188 } | 210 } |
189 #endif // !defined(GOOGLE_CHROME_BUILD) | 211 #endif // !defined(GOOGLE_CHROME_BUILD) |
190 | 212 |
213 if (stripped_path == kMainHtmlFilename) { | |
214 std::string html = ResourceBundle::GetSharedInstance() | |
215 .GetRawDataResource(IDR_LOCAL_NTP_HTML) | |
216 .as_string(); | |
217 std::string config_sha256 = | |
218 "sha256-" + GetIntegritySha256Value(GetConfigData(profile_)); | |
219 base::ReplaceFirstSubstringAfterOffset(&html, 0, "{{CONFIG_INTEGRITY}}", | |
220 config_sha256); | |
221 callback.Run(base::RefCountedString::TakeString(&html)); | |
222 return; | |
223 } | |
224 | |
191 float scale = 1.0f; | 225 float scale = 1.0f; |
192 std::string filename; | 226 std::string filename; |
193 webui::ParsePathAndScale( | 227 webui::ParsePathAndScale( |
194 GURL(GetLocalNtpPath() + stripped_path), &filename, &scale); | 228 GURL(GetLocalNtpPath() + stripped_path), &filename, &scale); |
195 ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactor(scale); | 229 ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactor(scale); |
196 | 230 |
197 for (size_t i = 0; i < arraysize(kResources); ++i) { | 231 for (size_t i = 0; i < arraysize(kResources); ++i) { |
198 if (filename == kResources[i].filename) { | 232 if (filename == kResources[i].filename) { |
199 scoped_refptr<base::RefCountedMemory> response( | 233 scoped_refptr<base::RefCountedMemory> response( |
200 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( | 234 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( |
201 kResources[i].identifier, scale_factor)); | 235 kResources[i].identifier, scale_factor)); |
202 callback.Run(response.get()); | 236 callback.Run(response.get()); |
203 return; | 237 return; |
204 } | 238 } |
205 } | 239 } |
206 callback.Run(NULL); | 240 callback.Run(nullptr); |
207 } | 241 } |
208 | 242 |
209 std::string LocalNtpSource::GetMimeType( | 243 std::string LocalNtpSource::GetMimeType( |
210 const std::string& path) const { | 244 const std::string& path) const { |
211 const std::string stripped_path = StripParameters(path); | 245 const std::string stripped_path = StripParameters(path); |
212 for (size_t i = 0; i < arraysize(kResources); ++i) { | 246 for (size_t i = 0; i < arraysize(kResources); ++i) { |
213 if (stripped_path == kResources[i].filename) | 247 if (stripped_path == kResources[i].filename) |
214 return kResources[i].mime_type; | 248 return kResources[i].mime_type; |
215 } | 249 } |
216 return std::string(); | 250 return std::string(); |
217 } | 251 } |
218 | 252 |
219 bool LocalNtpSource::AllowCaching() const { | 253 bool LocalNtpSource::AllowCaching() const { |
220 // Some resources served by LocalNtpSource, i.e. config.js, are dynamically | 254 // Some resources served by LocalNtpSource, i.e. config.js, are dynamically |
221 // generated and could differ on each access. To avoid using old cached | 255 // generated and could differ on each access. To avoid using old cached |
222 // content on reload, disallow caching here. Otherwise, it fails to reflect | 256 // content on reload, disallow caching here. Otherwise, it fails to reflect |
223 // newly revised user configurations in the page. | 257 // newly revised user configurations in the page. |
224 return false; | 258 return false; |
225 } | 259 } |
226 | 260 |
227 bool LocalNtpSource::ShouldServiceRequest( | 261 bool LocalNtpSource::ShouldServiceRequest( |
228 const net::URLRequest* request) const { | 262 const net::URLRequest* request) const { |
229 DCHECK(request->url().host_piece() == chrome::kChromeSearchLocalNtpHost); | 263 DCHECK(request->url().host_piece() == chrome::kChromeSearchLocalNtpHost); |
230 if (!InstantIOContext::ShouldServiceRequest(request)) | 264 if (!InstantIOContext::ShouldServiceRequest(request)) |
231 return false; | 265 return false; |
232 | 266 |
233 if (request->url().SchemeIs(chrome::kChromeSearchScheme)) { | 267 if (request->url().SchemeIs(chrome::kChromeSearchScheme)) { |
234 std::string filename; | 268 std::string filename; |
235 webui::ParsePathAndScale(request->url(), &filename, NULL); | 269 webui::ParsePathAndScale(request->url(), &filename, nullptr); |
236 for (size_t i = 0; i < arraysize(kResources); ++i) { | 270 for (size_t i = 0; i < arraysize(kResources); ++i) { |
237 if (filename == kResources[i].filename) | 271 if (filename == kResources[i].filename) |
238 return true; | 272 return true; |
239 } | 273 } |
240 } | 274 } |
241 return false; | 275 return false; |
242 } | 276 } |
243 | 277 |
278 std::string LocalNtpSource::GetContentSecurityPolicyScriptSrc() const { | |
279 return "script-src 'strict-dynamic' " | |
Marc Treib
2017/04/07 16:46:15
Could hide this behind a (default-enabled) feature
sfiera
2017/04/10 08:53:21
Right now, users only land on the local NTP if the
Marc Treib
2017/04/10 10:11:18
Even while offline, there should usually be a cach
| |
280 "'sha256-" + | |
281 GetIntegritySha256Value(GetConfigData(profile_)) + | |
sfiera
2017/04/10 08:53:21
Are we going to be computing this hash multiple ti
Marc Treib
2017/04/10 10:11:18
Yes; twice at the very least, probably even more o
sfiera
2017/04/10 10:28:53
I was thinking about computing once when the HTML
Marc Treib
2017/04/10 11:44:03
The CSP is served through HTTP headers, so that ac
| |
282 "' " | |
283 "'sha256-g38WaUaxnOIWY7E2LtLZ5ff9r5sn1dBj80jevt/kmx0=';"; | |
284 } | |
285 | |
244 std::string LocalNtpSource::GetContentSecurityPolicyChildSrc() const { | 286 std::string LocalNtpSource::GetContentSecurityPolicyChildSrc() const { |
245 // Allow embedding of most visited iframes. | 287 // Allow embedding of most visited iframes. |
246 return base::StringPrintf("child-src %s;", | 288 return base::StringPrintf("child-src %s;", |
247 chrome::kChromeSearchMostVisitedUrl); | 289 chrome::kChromeSearchMostVisitedUrl); |
248 } | 290 } |
OLD | NEW |