1 // Copyright (c) 2012 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/ui/webui/options/options_ui.h" 6 7 #include <algorithm> 8 #include <vector> 9 10 #include "base/callback.h" 11 #include "base/command_line.h" 12 #include "base/memory/ref_counted_memory.h" 13 #include "base/memory/singleton.h" 14 #include "base/message_loop/message_loop.h" 15 #include "base/strings/string_piece.h" 16 #include "base/strings/string_util.h" 17 #include "base/threading/thread.h" 18 #include "base/time/time.h" 19 #include "base/values.h" 20 #include "chrome/browser/autocomplete/autocomplete_match.h" 21 #include "chrome/browser/autocomplete/autocomplete_result.h" 22 #include "chrome/browser/browser_about_handler.h" 23 #include "chrome/browser/browser_process.h" 24 #include "chrome/browser/profiles/profile.h" 25 #include "chrome/browser/ui/webui/options/autofill_options_handler.h" 26 #include "chrome/browser/ui/webui/options/browser_options_handler.h" 27 #include "chrome/browser/ui/webui/options/clear_browser_data_handler.h" 28 #include "chrome/browser/ui/webui/options/content_settings_handler.h" 29 #include "chrome/browser/ui/webui/options/cookies_view_handler.h" 30 #include "chrome/browser/ui/webui/options/core_options_handler.h" 31 #include "chrome/browser/ui/webui/options/font_settings_handler.h" 32 #include "chrome/browser/ui/webui/options/handler_options_handler.h" 33 #include "chrome/browser/ui/webui/options/home_page_overlay_handler.h" 34 #include "chrome/browser/ui/webui/options/import_data_handler.h" 35 #include "chrome/browser/ui/webui/options/language_dictionary_overlay_handler.h" 36 #include "chrome/browser/ui/webui/options/language_options_handler.h" 37 #include "chrome/browser/ui/webui/options/manage_profile_handler.h" 38 #include "chrome/browser/ui/webui/options/managed_user_create_confirm_handler.h" 39 #include "chrome/browser/ui/webui/options/managed_user_learn_more_handler.h" 40 #include "chrome/browser/ui/webui/options/media_devices_selection_handler.h" 41 #include "chrome/browser/ui/webui/options/media_galleries_handler.h" 42 #include "chrome/browser/ui/webui/options/password_manager_handler.h" 43 #include "chrome/browser/ui/webui/options/reset_profile_settings_handler.h" 44 #include "chrome/browser/ui/webui/options/search_engine_manager_handler.h" 45 #include "chrome/browser/ui/webui/options/startup_pages_handler.h" 46 #include "chrome/browser/ui/webui/sync_setup_handler.h" 47 #include "chrome/browser/ui/webui/theme_source.h" 48 #include "chrome/common/url_constants.h" 49 #include "content/public/browser/notification_types.h" 50 #include "content/public/browser/render_view_host.h" 51 #include "content/public/browser/url_data_source.h" 52 #include "content/public/browser/web_contents.h" 53 #include "content/public/browser/web_contents_delegate.h" 54 #include "content/public/browser/web_ui.h" 55 #include "grit/chromium_strings.h" 56 #include "grit/generated_resources.h" 57 #include "grit/locale_settings.h" 58 #include "grit/options_resources.h" 59 #include "grit/theme_resources.h" 60 #include "net/base/escape.h" 61 #include "ui/base/l10n/l10n_util.h" 62 #include "ui/base/resource/resource_bundle.h" 63 #include "ui/webui/jstemplate_builder.h" 64 #include "ui/webui/web_ui_util.h" 65 66 #if defined(OS_CHROMEOS) 67 #include "chrome/browser/chromeos/system/pointer_device_observer.h" 68 #include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h" 69 #include "chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h" 70 #include "chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.h" 71 #include "chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h" 72 #include "chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.h" 73 #include "chrome/browser/ui/webui/options/chromeos/display_options_handler.h" 74 #include "chrome/browser/ui/webui/options/chromeos/display_overscan_handler.h" 75 #include "chrome/browser/ui/webui/options/chromeos/internet_options_handler.h" 76 #include "chrome/browser/ui/webui/options/chromeos/keyboard_handler.h" 77 #include "chrome/browser/ui/webui/options/chromeos/language_chewing_handler.h" 78 #include "chrome/browser/ui/webui/options/chromeos/language_hangul_handler.h" 79 #include "chrome/browser/ui/webui/options/chromeos/language_mozc_handler.h" 80 #include "chrome/browser/ui/webui/options/chromeos/language_pinyin_handler.h" 81 #include "chrome/browser/ui/webui/options/chromeos/pointer_handler.h" 82 #include "chrome/browser/ui/webui/options/chromeos/proxy_handler.h" 83 #include "chrome/browser/ui/webui/options/chromeos/stats_options_handler.h" 84 #include "chrome/browser/ui/webui/options/chromeos/user_image_source.h" 85 #endif 86 87 #if defined(USE_NSS) 88 #include "chrome/browser/ui/webui/options/certificate_manager_handler.h" 89 #endif 90 91 #if defined(ENABLE_GOOGLE_NOW) 92 #include "chrome/browser/ui/webui/options/geolocation_options_handler.h" 93 #endif 94 95 using content::RenderViewHost; 96 97 namespace { 98 99 const char kLocalizedStringsFile[] = "strings.js"; 100 const char kOptionsBundleJsFile[] = "options_bundle.js"; 101 102 } // namespace 103 104 namespace options { 105 106 //////////////////////////////////////////////////////////////////////////////// 107 // 108 // OptionsUIHTMLSource 109 // 110 //////////////////////////////////////////////////////////////////////////////// 111 112 class OptionsUIHTMLSource : public content::URLDataSource { 113 public: 114 // The constructor takes over ownership of |localized_strings|. 115 explicit OptionsUIHTMLSource(DictionaryValue* localized_strings); 116 117 // content::URLDataSource implementation. 118 virtual std::string GetSource() const OVERRIDE; 119 virtual void StartDataRequest( 120 const std::string& path, 121 int render_process_id, 122 int render_view_id, 123 const content::URLDataSource::GotDataCallback& callback) OVERRIDE; 124 virtual std::string GetMimeType(const std::string&) const OVERRIDE; 125 virtual bool ShouldDenyXFrameOptions() const OVERRIDE; 126 127 private: 128 virtual ~OptionsUIHTMLSource(); 129 130 // Localized strings collection. 131 scoped_ptr<DictionaryValue> localized_strings_; 132 133 DISALLOW_COPY_AND_ASSIGN(OptionsUIHTMLSource); 134 }; 135 136 OptionsUIHTMLSource::OptionsUIHTMLSource(DictionaryValue* localized_strings) { 137 DCHECK(localized_strings); 138 localized_strings_.reset(localized_strings); 139 } 140 141 std::string OptionsUIHTMLSource::GetSource() const { 142 return chrome::kChromeUISettingsFrameHost; 143 } 144 145 void OptionsUIHTMLSource::StartDataRequest( 146 const std::string& path, 147 int render_process_id, 148 int render_view_id, 149 const content::URLDataSource::GotDataCallback& callback) { 150 scoped_refptr<base::RefCountedMemory> response_bytes; 151 webui::SetFontAndTextDirection(localized_strings_.get()); 152 153 if (path == kLocalizedStringsFile) { 154 // Return dynamically-generated strings from memory. 155 webui::UseVersion2 version; 156 std::string strings_js; 157 webui::AppendJsonJS(localized_strings_.get(), &strings_js); 158 response_bytes = base::RefCountedString::TakeString(&strings_js); 159 } else if (path == kOptionsBundleJsFile) { 160 // Return (and cache) the options javascript code. 161 response_bytes = ui::ResourceBundle::GetSharedInstance(). 162 LoadDataResourceBytes(IDR_OPTIONS_BUNDLE_JS); 163 } else { 164 // Return (and cache) the main options html page as the default. 165 response_bytes = ui::ResourceBundle::GetSharedInstance(). 166 LoadDataResourceBytes(IDR_OPTIONS_HTML); 167 } 168 169 callback.Run(response_bytes.get()); 170 } 171 172 std::string OptionsUIHTMLSource::GetMimeType(const std::string& path) const { 173 if (path == kLocalizedStringsFile || path == kOptionsBundleJsFile) 174 return "application/javascript"; 175 176 return "text/html"; 177 } 178 179 bool OptionsUIHTMLSource::ShouldDenyXFrameOptions() const { 180 return false; 181 } 182 183 OptionsUIHTMLSource::~OptionsUIHTMLSource() {} 184 185 //////////////////////////////////////////////////////////////////////////////// 186 // 187 // OptionsPageUIHandler 188 // 189 //////////////////////////////////////////////////////////////////////////////// 190 191 const char OptionsPageUIHandler::kSettingsAppKey[] = "settingsApp"; 192 193 OptionsPageUIHandler::OptionsPageUIHandler() { 194 } 195 196 OptionsPageUIHandler::~OptionsPageUIHandler() { 197 } 198 199 bool OptionsPageUIHandler::IsEnabled() { 200 return true; 201 } 202 203 // static 204 void OptionsPageUIHandler::RegisterStrings( 205 DictionaryValue* localized_strings, 206 const OptionsStringResource* resources, 207 size_t length) { 208 for (size_t i = 0; i < length; ++i) { 209 string16 value; 210 if (resources[i].substitution_id == 0) { 211 value = l10n_util::GetStringUTF16(resources[i].id); 212 } else { 213 value = l10n_util::GetStringFUTF16( 214 resources[i].id, 215 l10n_util::GetStringUTF16(resources[i].substitution_id)); 216 } 217 localized_strings->SetString(resources[i].name, value); 218 } 219 } 220 221 void OptionsPageUIHandler::RegisterTitle(DictionaryValue* localized_strings, 222 const std::string& variable_name, 223 int title_id) { 224 localized_strings->SetString(variable_name, 225 l10n_util::GetStringUTF16(title_id)); 226 localized_strings->SetString(variable_name + "TabTitle", 227 l10n_util::GetStringFUTF16(IDS_OPTIONS_TAB_TITLE, 228 l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE), 229 l10n_util::GetStringUTF16(title_id))); 230 } 231 232 //////////////////////////////////////////////////////////////////////////////// 233 // 234 // OptionsUI 235 // 236 //////////////////////////////////////////////////////////////////////////////// 237 238 OptionsUI::OptionsUI(content::WebUI* web_ui) 239 : WebUIController(web_ui), 240 initialized_handlers_(false) { 241 DictionaryValue* localized_strings = new DictionaryValue(); 242 localized_strings->Set(OptionsPageUIHandler::kSettingsAppKey, 243 new DictionaryValue()); 244 245 CoreOptionsHandler* core_handler; 246 #if defined(OS_CHROMEOS) 247 core_handler = new chromeos::options::CoreChromeOSOptionsHandler(); 248 #else 249 core_handler = new CoreOptionsHandler(); 250 #endif 251 core_handler->set_handlers_host(this); 252 AddOptionsPageUIHandler(localized_strings, core_handler); 253 254 AddOptionsPageUIHandler(localized_strings, new AutofillOptionsHandler()); 255 256 BrowserOptionsHandler* browser_options_handler = new BrowserOptionsHandler(); 257 AddOptionsPageUIHandler(localized_strings, browser_options_handler); 258 259 AddOptionsPageUIHandler(localized_strings, new ClearBrowserDataHandler()); 260 AddOptionsPageUIHandler(localized_strings, new ContentSettingsHandler()); 261 AddOptionsPageUIHandler(localized_strings, new CookiesViewHandler()); 262 AddOptionsPageUIHandler(localized_strings, new FontSettingsHandler()); 263 #if defined(ENABLE_GOOGLE_NOW) 264 AddOptionsPageUIHandler(localized_strings, new GeolocationOptionsHandler()); 265 #endif 266 AddOptionsPageUIHandler(localized_strings, new HomePageOverlayHandler()); 267 AddOptionsPageUIHandler(localized_strings, 268 new MediaDevicesSelectionHandler()); 269 AddOptionsPageUIHandler(localized_strings, new MediaGalleriesHandler()); 270 #if defined(OS_CHROMEOS) 271 AddOptionsPageUIHandler(localized_strings, 272 new chromeos::options::CrosLanguageOptionsHandler()); 273 #else 274 AddOptionsPageUIHandler(localized_strings, new LanguageOptionsHandler()); 275 #endif 276 AddOptionsPageUIHandler(localized_strings, 277 new LanguageDictionaryOverlayHandler()); 278 AddOptionsPageUIHandler(localized_strings, new ManageProfileHandler()); 279 AddOptionsPageUIHandler(localized_strings, 280 new ManagedUserCreateConfirmHandler()); 281 AddOptionsPageUIHandler(localized_strings, new ManagedUserLearnMoreHandler()); 282 AddOptionsPageUIHandler(localized_strings, new PasswordManagerHandler()); 283 AddOptionsPageUIHandler(localized_strings, new ResetProfileSettingsHandler()); 284 AddOptionsPageUIHandler(localized_strings, new SearchEngineManagerHandler()); 285 AddOptionsPageUIHandler(localized_strings, new ImportDataHandler()); 286 AddOptionsPageUIHandler(localized_strings, new StartupPagesHandler()); 287 AddOptionsPageUIHandler(localized_strings, new SyncSetupHandler( 288 g_browser_process->profile_manager())); 289 #if defined(OS_CHROMEOS) 290 AddOptionsPageUIHandler(localized_strings, 291 new chromeos::options::AccountsOptionsHandler()); 292 AddOptionsPageUIHandler(localized_strings, 293 new chromeos::options::BluetoothOptionsHandler()); 294 AddOptionsPageUIHandler(localized_strings, 295 new chromeos::options::DisplayOptionsHandler()); 296 AddOptionsPageUIHandler(localized_strings, 297 new chromeos::options::DisplayOverscanHandler()); 298 AddOptionsPageUIHandler(localized_strings, 299 new chromeos::options::InternetOptionsHandler()); 300 AddOptionsPageUIHandler(localized_strings, 301 new chromeos::options::LanguageChewingHandler()); 302 AddOptionsPageUIHandler(localized_strings, 303 new chromeos::options::KeyboardHandler()); 304 AddOptionsPageUIHandler(localized_strings, 305 new chromeos::options::LanguageHangulHandler()); 306 AddOptionsPageUIHandler(localized_strings, 307 new chromeos::options::LanguageMozcHandler()); 308 AddOptionsPageUIHandler(localized_strings, 309 new chromeos::options::LanguagePinyinHandler()); 310 311 chromeos::options::PointerHandler* pointer_handler = 312 new chromeos::options::PointerHandler(); 313 AddOptionsPageUIHandler(localized_strings, pointer_handler); 314 315 AddOptionsPageUIHandler(localized_strings, 316 new chromeos::options::ProxyHandler()); 317 AddOptionsPageUIHandler( 318 localized_strings, 319 new chromeos::options::ChangePictureOptionsHandler()); 320 AddOptionsPageUIHandler(localized_strings, 321 new chromeos::options::StatsOptionsHandler()); 322 #endif 323 #if defined(USE_NSS) 324 AddOptionsPageUIHandler(localized_strings, new CertificateManagerHandler()); 325 #endif 326 AddOptionsPageUIHandler(localized_strings, new HandlerOptionsHandler()); 327 328 // |localized_strings| ownership is taken over by this constructor. 329 OptionsUIHTMLSource* html_source = 330 new OptionsUIHTMLSource(localized_strings); 331 332 // Set up the chrome://settings-frame/ source. 333 Profile* profile = Profile::FromWebUI(web_ui); 334 content::URLDataSource::Add(profile, html_source); 335 336 // Set up the chrome://theme/ source. 337 ThemeSource* theme = new ThemeSource(profile); 338 content::URLDataSource::Add(profile, theme); 339 340 #if defined(OS_CHROMEOS) 341 // Set up the chrome://userimage/ source. 342 chromeos::options::UserImageSource* user_image_source = 343 new chromeos::options::UserImageSource(); 344 content::URLDataSource::Add(profile, user_image_source); 345 346 pointer_device_observer_.reset( 347 new chromeos::system::PointerDeviceObserver()); 348 pointer_device_observer_->AddObserver(browser_options_handler); 349 pointer_device_observer_->AddObserver(pointer_handler); 350 #endif 351 } 352 353 OptionsUI::~OptionsUI() { 354 // Uninitialize all registered handlers. Deleted by WebUIImpl. 355 for (size_t i = 0; i < handlers_.size(); ++i) 356 handlers_[i]->Uninitialize(); 357 } 358 359 // static 360 void OptionsUI::ProcessAutocompleteSuggestions( 361 const AutocompleteResult& result, 362 base::ListValue* const suggestions) { 363 for (size_t i = 0; i < result.size(); ++i) { 364 const AutocompleteMatch& match = result.match_at(i); 365 AutocompleteMatchType::Type type = match.type; 366 if (type != AutocompleteMatchType::HISTORY_URL && 367 type != AutocompleteMatchType::HISTORY_TITLE && 368 type != AutocompleteMatchType::HISTORY_BODY && 369 type != AutocompleteMatchType::HISTORY_KEYWORD && 370 type != AutocompleteMatchType::NAVSUGGEST) 371 continue; 372 base::DictionaryValue* entry = new base::DictionaryValue(); 373 entry->SetString("title", match.description); 374 entry->SetString("displayURL", match.contents); 375 entry->SetString("url", match.destination_url.spec()); 376 suggestions->Append(entry); 377 } 378 } 379 380 // static 381 base::RefCountedMemory* OptionsUI::GetFaviconResourceBytes( 382 ui::ScaleFactor scale_factor) { 383 return ui::ResourceBundle::GetSharedInstance(). 384 LoadDataResourceBytesForScale(IDR_SETTINGS_FAVICON, scale_factor); 385 } 386 387 void OptionsUI::InitializeHandlers() { 388 Profile* profile = Profile::FromWebUI(web_ui()); 389 DCHECK(!profile->IsOffTheRecord() || profile->IsGuestSession()); 390 391 // A new web page DOM has been brought up in an existing renderer, causing 392 // this method to be called twice. If that happens, ignore the second call. 393 if (!initialized_handlers_) { 394 for (size_t i = 0; i < handlers_.size(); ++i) 395 handlers_[i]->InitializeHandler(); 396 initialized_handlers_ = true; 397 398 #if defined(OS_CHROMEOS) 399 pointer_device_observer_->Init(); 400 #endif 401 } 402 403 #if defined(OS_CHROMEOS) 404 pointer_device_observer_->CheckDevices(); 405 #endif 406 407 // Always initialize the page as when handlers are left over we still need to 408 // do various things like show/hide sections and send data to the Javascript. 409 for (size_t i = 0; i < handlers_.size(); ++i) 410 handlers_[i]->InitializePage(); 411 412 web_ui()->CallJavascriptFunction( 413 "BrowserOptions.notifyInitializationComplete"); 414 } 415 416 void OptionsUI::RenderViewCreated(content::RenderViewHost* render_view_host) { 417 content::WebUIController::RenderViewCreated(render_view_host); 418 for (size_t i = 0; i < handlers_.size(); ++i) 419 handlers_[i]->PageLoadStarted(); 420 } 421 422 void OptionsUI::RenderViewReused(content::RenderViewHost* render_view_host) { 423 content::WebUIController::RenderViewReused(render_view_host); 424 for (size_t i = 0; i < handlers_.size(); ++i) 425 handlers_[i]->PageLoadStarted(); 426 } 427 428 void OptionsUI::AddOptionsPageUIHandler(DictionaryValue* localized_strings, 429 OptionsPageUIHandler* handler_raw) { 430 scoped_ptr<OptionsPageUIHandler> handler(handler_raw); 431 DCHECK(handler.get()); 432 // Add only if handler's service is enabled. 433 if (handler->IsEnabled()) { 434 // Add handler to the list and also pass the ownership. 435 web_ui()->AddMessageHandler(handler.release()); 436 handler_raw->GetLocalizedValues(localized_strings); 437 handlers_.push_back(handler_raw); 438 } 439 } 440 441 } // namespace options 442