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. 4 5 #include "chrome/browser/search/local_ntp_source.h" 6 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/strings/string_util.h" 12 #include "base/strings/stringprintf.h" 13 #include "base/values.h" 14 #include "chrome/browser/search/instant_io_context.h" 15 #include "chrome/browser/search/search.h" 16 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" 17 #include "chrome/browser/search_engines/template_url_service.h" 18 #include "chrome/browser/search_engines/template_url_service_factory.h" 19 #include "chrome/common/url_constants.h" 20 #include "grit/browser_resources.h" 21 #include "grit/generated_resources.h" 22 #include "grit/theme_resources.h" 23 #include "grit/ui_resources.h" 24 #include "net/url_request/url_request.h" 25 #include "ui/base/l10n/l10n_util.h" 26 #include "ui/base/resource/resource_bundle.h" 27 #include "ui/base/webui/jstemplate_builder.h" 28 #include "ui/base/webui/web_ui_util.h" 29 #include "url/gurl.h" 30 31 namespace { 32 33 // Signifies a locally constructed resource, i.e. not from grit/. 34 const int kLocalResource = -1; 35 36 const char kConfigDataFilename[] = "config.js"; 37 38 const struct Resource{ 39 const char* filename; 40 int identifier; 41 const char* mime_type; 42 } kResources[] = { 43 { "local-ntp.html", IDR_LOCAL_NTP_HTML, "text/html" }, 44 { "local-ntp.js", IDR_LOCAL_NTP_JS, "application/javascript" }, 45 { kConfigDataFilename, kLocalResource, "application/javascript" }, 46 { "local-ntp.css", IDR_LOCAL_NTP_CSS, "text/css" }, 47 { "images/close_2.png", IDR_CLOSE_2, "image/png" }, 48 { "images/close_2_hover.png", IDR_CLOSE_2_H, "image/png" }, 49 { "images/close_2_active.png", IDR_CLOSE_2_P, "image/png" }, 50 { "images/close_2_white.png", IDR_CLOSE_2_MASK, "image/png" }, 51 { "images/google_logo.png", IDR_LOCAL_NTP_IMAGES_LOGO_PNG, "image/png" }, 52 { "images/white_google_logo.png", 53 IDR_LOCAL_NTP_IMAGES_WHITE_LOGO_PNG, "image/png" }, 54 }; 55 56 // Strips any query parameters from the specified path. 57 std::string StripParameters(const std::string& path) { 58 return path.substr(0, path.find("?")); 59 } 60 61 bool DefaultSearchProviderIsGoogle(Profile* profile) { 62 if (!profile) 63 return false; 64 65 TemplateURLService* template_url_service = 66 TemplateURLServiceFactory::GetForProfile(profile); 67 if (!template_url_service) 68 return false; 69 70 const TemplateURL* default_provider = 71 template_url_service->GetDefaultSearchProvider(); 72 return default_provider && 73 (TemplateURLPrepopulateData::GetEngineType( 74 *default_provider, template_url_service->search_terms_data()) == 75 SEARCH_ENGINE_GOOGLE); 76 } 77 78 // Adds a localized string keyed by resource id to the dictionary. 79 void AddString(base::DictionaryValue* dictionary, 80 const std::string& key, 81 int resource_id) { 82 dictionary->SetString(key, l10n_util::GetStringUTF16(resource_id)); 83 } 84 85 // Populates |translated_strings| dictionary for the local NTP. 86 scoped_ptr<base::DictionaryValue> GetTranslatedStrings() { 87 scoped_ptr<base::DictionaryValue> translated_strings( 88 new base::DictionaryValue()); 89 90 AddString(translated_strings.get(), "thumbnailRemovedNotification", 91 IDS_NEW_TAB_THUMBNAIL_REMOVED_NOTIFICATION); 92 AddString(translated_strings.get(), "removeThumbnailTooltip", 93 IDS_NEW_TAB_REMOVE_THUMBNAIL_TOOLTIP); 94 AddString(translated_strings.get(), "undoThumbnailRemove", 95 IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE); 96 AddString(translated_strings.get(), "restoreThumbnailsShort", 97 IDS_NEW_TAB_RESTORE_THUMBNAILS_SHORT_LINK); 98 AddString(translated_strings.get(), "attributionIntro", 99 IDS_NEW_TAB_ATTRIBUTION_INTRO); 100 AddString(translated_strings.get(), "title", IDS_NEW_TAB_TITLE); 101 102 return translated_strings.Pass(); 103 } 104 105 // Returns a JS dictionary of configuration data for the local NTP. 106 std::string GetConfigData(Profile* profile) { 107 base::DictionaryValue config_data; 108 config_data.Set("translatedStrings", GetTranslatedStrings().release()); 109 config_data.SetBoolean("isGooglePage", 110 DefaultSearchProviderIsGoogle(profile) && 111 chrome::ShouldShowGoogleLocalNTP()); 112 113 // Serialize the dictionary. 114 std::string js_text; 115 JSONStringValueSerializer serializer(&js_text); 116 serializer.Serialize(config_data); 117 118 std::string config_data_js; 119 config_data_js.append("var configData = "); 120 config_data_js.append(js_text); 121 config_data_js.append(";"); 122 return config_data_js; 123 } 124 125 std::string GetLocalNtpPath() { 126 return std::string(chrome::kChromeSearchScheme) + "://" + 127 std::string(chrome::kChromeSearchLocalNtpHost) + "/"; 128 } 129 130 } // namespace 131 132 LocalNtpSource::LocalNtpSource(Profile* profile) : profile_(profile) { 133 } 134 135 LocalNtpSource::~LocalNtpSource() { 136 } 137 138 std::string LocalNtpSource::GetSource() const { 139 return chrome::kChromeSearchLocalNtpHost; 140 } 141 142 void LocalNtpSource::StartDataRequest( 143 const std::string& path, 144 int render_process_id, 145 int render_frame_id, 146 const content::URLDataSource::GotDataCallback& callback) { 147 const std::string stripped_path = StripParameters(path); 148 if (stripped_path == kConfigDataFilename) { 149 std::string config_data_js = GetConfigData(profile_); 150 callback.Run(base::RefCountedString::TakeString(&config_data_js)); 151 return; 152 } 153 float scale = 1.0f; 154 std::string filename; 155 webui::ParsePathAndScale( 156 GURL(GetLocalNtpPath() + stripped_path), &filename, &scale); 157 ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactor(scale); 158 for (size_t i = 0; i < arraysize(kResources); ++i) { 159 if (filename == kResources[i].filename) { 160 scoped_refptr<base::RefCountedStaticMemory> response( 161 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( 162 kResources[i].identifier, scale_factor)); 163 callback.Run(response.get()); 164 return; 165 } 166 } 167 callback.Run(NULL); 168 } 169 170 std::string LocalNtpSource::GetMimeType( 171 const std::string& path) const { 172 const std::string stripped_path = StripParameters(path); 173 for (size_t i = 0; i < arraysize(kResources); ++i) { 174 if (stripped_path == kResources[i].filename) 175 return kResources[i].mime_type; 176 } 177 return std::string(); 178 } 179 180 bool LocalNtpSource::ShouldServiceRequest( 181 const net::URLRequest* request) const { 182 DCHECK(request->url().host() == chrome::kChromeSearchLocalNtpHost); 183 if (!InstantIOContext::ShouldServiceRequest(request)) 184 return false; 185 186 if (request->url().SchemeIs(chrome::kChromeSearchScheme)) { 187 std::string filename; 188 webui::ParsePathAndScale(request->url(), &filename, NULL); 189 for (size_t i = 0; i < arraysize(kResources); ++i) { 190 if (filename == kResources[i].filename) 191 return true; 192 } 193 } 194 return false; 195 } 196 197 std::string LocalNtpSource::GetContentSecurityPolicyFrameSrc() const { 198 // Allow embedding of most visited iframes. 199 return base::StringPrintf("frame-src %s;", 200 chrome::kChromeSearchMostVisitedUrl); 201 } 202