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