Home | History | Annotate | Download | only in options
      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/help_overlay_handler.h"
     37 #include "chrome/browser/ui/webui/options/home_page_overlay_handler.h"
     38 #include "chrome/browser/ui/webui/options/import_data_handler.h"
     39 #include "chrome/browser/ui/webui/options/language_dictionary_overlay_handler.h"
     40 #include "chrome/browser/ui/webui/options/language_options_handler.h"
     41 #include "chrome/browser/ui/webui/options/manage_profile_handler.h"
     42 #include "chrome/browser/ui/webui/options/media_devices_selection_handler.h"
     43 #include "chrome/browser/ui/webui/options/password_manager_handler.h"
     44 #include "chrome/browser/ui/webui/options/reset_profile_settings_handler.h"
     45 #include "chrome/browser/ui/webui/options/search_engine_manager_handler.h"
     46 #include "chrome/browser/ui/webui/options/startup_pages_handler.h"
     47 #include "chrome/browser/ui/webui/options/supervised_user_create_confirm_handler.h"
     48 #include "chrome/browser/ui/webui/options/supervised_user_import_handler.h"
     49 #include "chrome/browser/ui/webui/options/supervised_user_learn_more_handler.h"
     50 #include "chrome/browser/ui/webui/options/website_settings_handler.h"
     51 #include "chrome/browser/ui/webui/sync_setup_handler.h"
     52 #include "chrome/browser/ui/webui/theme_source.h"
     53 #include "chrome/common/url_constants.h"
     54 #include "chrome/grit/generated_resources.h"
     55 #include "chrome/grit/locale_settings.h"
     56 #include "components/omnibox/autocomplete_match.h"
     57 #include "components/omnibox/autocomplete_result.h"
     58 #include "content/public/browser/notification_types.h"
     59 #include "content/public/browser/render_frame_host.h"
     60 #include "content/public/browser/url_data_source.h"
     61 #include "content/public/browser/web_contents.h"
     62 #include "content/public/browser/web_contents_delegate.h"
     63 #include "content/public/browser/web_ui.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 #endif
     94 
     95 #if defined(USE_NSS)
     96 #include "chrome/browser/ui/webui/options/certificate_manager_handler.h"
     97 #endif
     98 
     99 #if defined(ENABLE_GOOGLE_NOW)
    100 #include "chrome/browser/ui/webui/options/geolocation_options_handler.h"
    101 #endif
    102 
    103 using content::RenderViewHost;
    104 
    105 namespace {
    106 
    107 const char kLocalizedStringsFile[] = "strings.js";
    108 const char kOptionsBundleJsFile[]  = "options_bundle.js";
    109 
    110 }  // namespace
    111 
    112 namespace options {
    113 
    114 ////////////////////////////////////////////////////////////////////////////////
    115 //
    116 // OptionsUIHTMLSource
    117 //
    118 ////////////////////////////////////////////////////////////////////////////////
    119 
    120 class OptionsUIHTMLSource : public content::URLDataSource {
    121  public:
    122   // The constructor takes over ownership of |localized_strings|.
    123   explicit OptionsUIHTMLSource(base::DictionaryValue* localized_strings);
    124 
    125   // content::URLDataSource implementation.
    126   virtual std::string GetSource() const OVERRIDE;
    127   virtual void StartDataRequest(
    128       const std::string& path,
    129       int render_process_id,
    130       int render_frame_id,
    131       const content::URLDataSource::GotDataCallback& callback) OVERRIDE;
    132   virtual std::string GetMimeType(const std::string&) const OVERRIDE;
    133   virtual bool ShouldDenyXFrameOptions() const OVERRIDE;
    134 
    135  private:
    136   virtual ~OptionsUIHTMLSource();
    137 
    138   // Localized strings collection.
    139   scoped_ptr<base::DictionaryValue> localized_strings_;
    140 
    141   DISALLOW_COPY_AND_ASSIGN(OptionsUIHTMLSource);
    142 };
    143 
    144 OptionsUIHTMLSource::OptionsUIHTMLSource(
    145     base::DictionaryValue* localized_strings) {
    146   DCHECK(localized_strings);
    147   localized_strings_.reset(localized_strings);
    148 }
    149 
    150 std::string OptionsUIHTMLSource::GetSource() const {
    151   return chrome::kChromeUISettingsFrameHost;
    152 }
    153 
    154 void OptionsUIHTMLSource::StartDataRequest(
    155     const std::string& path,
    156     int render_process_id,
    157     int render_frame_id,
    158     const content::URLDataSource::GotDataCallback& callback) {
    159   scoped_refptr<base::RefCountedMemory> response_bytes;
    160   webui::SetFontAndTextDirection(localized_strings_.get());
    161 
    162   if (path == kLocalizedStringsFile) {
    163     // Return dynamically-generated strings from memory.
    164     webui::UseVersion2 version;
    165     std::string strings_js;
    166     webui::AppendJsonJS(localized_strings_.get(), &strings_js);
    167     response_bytes = base::RefCountedString::TakeString(&strings_js);
    168   } else if (path == kOptionsBundleJsFile) {
    169     // Return (and cache) the options javascript code.
    170     response_bytes = ui::ResourceBundle::GetSharedInstance().
    171         LoadDataResourceBytes(IDR_OPTIONS_BUNDLE_JS);
    172   } else {
    173     // Return (and cache) the main options html page as the default.
    174     response_bytes = ui::ResourceBundle::GetSharedInstance().
    175         LoadDataResourceBytes(IDR_OPTIONS_HTML);
    176   }
    177 
    178   callback.Run(response_bytes.get());
    179 }
    180 
    181 std::string OptionsUIHTMLSource::GetMimeType(const std::string& path) const {
    182   if (path == kLocalizedStringsFile || path == kOptionsBundleJsFile)
    183     return "application/javascript";
    184 
    185   return "text/html";
    186 }
    187 
    188 bool OptionsUIHTMLSource::ShouldDenyXFrameOptions() const {
    189   return false;
    190 }
    191 
    192 OptionsUIHTMLSource::~OptionsUIHTMLSource() {}
    193 
    194 ////////////////////////////////////////////////////////////////////////////////
    195 //
    196 // OptionsPageUIHandler
    197 //
    198 ////////////////////////////////////////////////////////////////////////////////
    199 
    200 const char OptionsPageUIHandler::kSettingsAppKey[] = "settingsApp";
    201 
    202 OptionsPageUIHandler::OptionsPageUIHandler() {
    203 }
    204 
    205 OptionsPageUIHandler::~OptionsPageUIHandler() {
    206 }
    207 
    208 bool OptionsPageUIHandler::IsEnabled() {
    209   return true;
    210 }
    211 
    212 // static
    213 void OptionsPageUIHandler::RegisterStrings(
    214     base::DictionaryValue* localized_strings,
    215     const OptionsStringResource* resources,
    216     size_t length) {
    217   for (size_t i = 0; i < length; ++i) {
    218     base::string16 value;
    219     if (resources[i].substitution_id == 0) {
    220       value = l10n_util::GetStringUTF16(resources[i].id);
    221     } else {
    222       value = l10n_util::GetStringFUTF16(
    223           resources[i].id,
    224           l10n_util::GetStringUTF16(resources[i].substitution_id));
    225     }
    226     localized_strings->SetString(resources[i].name, value);
    227   }
    228 }
    229 
    230 void OptionsPageUIHandler::RegisterTitle(
    231     base::DictionaryValue* localized_strings,
    232     const std::string& variable_name,
    233     int title_id) {
    234   localized_strings->SetString(variable_name,
    235       l10n_util::GetStringUTF16(title_id));
    236   localized_strings->SetString(variable_name + "TabTitle",
    237       l10n_util::GetStringFUTF16(IDS_OPTIONS_TAB_TITLE,
    238           l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE),
    239           l10n_util::GetStringUTF16(title_id)));
    240 }
    241 
    242 ////////////////////////////////////////////////////////////////////////////////
    243 //
    244 // OptionsUI
    245 //
    246 ////////////////////////////////////////////////////////////////////////////////
    247 
    248 OptionsUI::OptionsUI(content::WebUI* web_ui)
    249     : WebUIController(web_ui),
    250       WebContentsObserver(web_ui->GetWebContents()),
    251       initialized_handlers_(false) {
    252   base::DictionaryValue* localized_strings = new base::DictionaryValue();
    253   localized_strings->Set(OptionsPageUIHandler::kSettingsAppKey,
    254                          new base::DictionaryValue());
    255 
    256   CoreOptionsHandler* core_handler;
    257 #if defined(OS_CHROMEOS)
    258   core_handler = new chromeos::options::CoreChromeOSOptionsHandler();
    259 #else
    260   core_handler = new CoreOptionsHandler();
    261 #endif
    262   core_handler->set_handlers_host(this);
    263   AddOptionsPageUIHandler(localized_strings, core_handler);
    264 
    265   AddOptionsPageUIHandler(localized_strings, new AutofillOptionsHandler());
    266   AddOptionsPageUIHandler(localized_strings,
    267                           new AutomaticSettingsResetHandler());
    268 
    269   BrowserOptionsHandler* browser_options_handler = new BrowserOptionsHandler();
    270   AddOptionsPageUIHandler(localized_strings, browser_options_handler);
    271 
    272   AddOptionsPageUIHandler(localized_strings, new ClearBrowserDataHandler());
    273   AddOptionsPageUIHandler(localized_strings, new ContentSettingsHandler());
    274   AddOptionsPageUIHandler(localized_strings, new CookiesViewHandler());
    275   AddOptionsPageUIHandler(localized_strings, new CreateProfileHandler());
    276   AddOptionsPageUIHandler(localized_strings, new EasyUnlockHandler());
    277   AddOptionsPageUIHandler(localized_strings, new FontSettingsHandler());
    278 #if defined(ENABLE_GOOGLE_NOW)
    279   AddOptionsPageUIHandler(localized_strings, new GeolocationOptionsHandler());
    280 #endif
    281   AddOptionsPageUIHandler(localized_strings, new options::HelpOverlayHandler());
    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,
    321                           new chromeos::options::KeyboardHandler());
    322 
    323   chromeos::options::PointerHandler* pointer_handler =
    324       new chromeos::options::PointerHandler();
    325   AddOptionsPageUIHandler(localized_strings, pointer_handler);
    326 
    327   AddOptionsPageUIHandler(localized_strings,
    328                           new chromeos::options::ProxyHandler());
    329   AddOptionsPageUIHandler(
    330       localized_strings,
    331       new chromeos::options::ChangePictureOptionsHandler());
    332   AddOptionsPageUIHandler(localized_strings,
    333                           new chromeos::options::StatsOptionsHandler());
    334 
    335   policy::ConsumerManagementService* consumer_management =
    336       g_browser_process->platform_part()->browser_policy_connector_chromeos()->
    337           GetConsumerManagementService();
    338   chromeos::options::ConsumerManagementHandler* consumer_management_handler =
    339       new chromeos::options::ConsumerManagementHandler(consumer_management);
    340   AddOptionsPageUIHandler(localized_strings, consumer_management_handler);
    341 #endif
    342 #if defined(USE_NSS)
    343   AddOptionsPageUIHandler(localized_strings,
    344                           new CertificateManagerHandler(false));
    345 #endif
    346   AddOptionsPageUIHandler(localized_strings, new HandlerOptionsHandler());
    347 
    348   web_ui->AddMessageHandler(new MetricsHandler());
    349 
    350   // |localized_strings| ownership is taken over by this constructor.
    351   OptionsUIHTMLSource* html_source =
    352       new OptionsUIHTMLSource(localized_strings);
    353 
    354   // Set up the chrome://settings-frame/ source.
    355   Profile* profile = Profile::FromWebUI(web_ui);
    356   content::URLDataSource::Add(profile, html_source);
    357 
    358   // Set up the chrome://theme/ source.
    359   ThemeSource* theme = new ThemeSource(profile);
    360   content::URLDataSource::Add(profile, theme);
    361 
    362 #if defined(OS_CHROMEOS)
    363   // Set up the chrome://userimage/ source.
    364   chromeos::options::UserImageSource* user_image_source =
    365       new chromeos::options::UserImageSource();
    366   content::URLDataSource::Add(profile, user_image_source);
    367 
    368   pointer_device_observer_.reset(
    369       new chromeos::system::PointerDeviceObserver());
    370   pointer_device_observer_->AddObserver(browser_options_handler);
    371   pointer_device_observer_->AddObserver(pointer_handler);
    372 #endif
    373 }
    374 
    375 OptionsUI::~OptionsUI() {
    376   // Uninitialize all registered handlers. Deleted by WebUIImpl.
    377   for (size_t i = 0; i < handlers_.size(); ++i)
    378     handlers_[i]->Uninitialize();
    379 }
    380 
    381 scoped_ptr<OptionsUI::OnFinishedLoadingCallbackList::Subscription>
    382 OptionsUI::RegisterOnFinishedLoadingCallback(const base::Closure& callback) {
    383   return on_finished_loading_callbacks_.Add(callback);
    384 }
    385 
    386 // static
    387 void OptionsUI::ProcessAutocompleteSuggestions(
    388     const AutocompleteResult& result,
    389     base::ListValue* const suggestions) {
    390   for (size_t i = 0; i < result.size(); ++i) {
    391     const AutocompleteMatch& match = result.match_at(i);
    392     AutocompleteMatchType::Type type = match.type;
    393     if (type != AutocompleteMatchType::HISTORY_URL &&
    394         type != AutocompleteMatchType::HISTORY_TITLE &&
    395         type != AutocompleteMatchType::HISTORY_BODY &&
    396         type != AutocompleteMatchType::HISTORY_KEYWORD &&
    397         type != AutocompleteMatchType::NAVSUGGEST &&
    398         type != AutocompleteMatchType::NAVSUGGEST_PERSONALIZED) {
    399       continue;
    400     }
    401     base::DictionaryValue* entry = new base::DictionaryValue();
    402     entry->SetString("title", match.description);
    403     entry->SetString("displayURL", match.contents);
    404     entry->SetString("url", match.destination_url.spec());
    405     suggestions->Append(entry);
    406   }
    407 }
    408 
    409 // static
    410 base::RefCountedMemory* OptionsUI::GetFaviconResourceBytes(
    411       ui::ScaleFactor scale_factor) {
    412   return ui::ResourceBundle::GetSharedInstance().
    413       LoadDataResourceBytesForScale(IDR_SETTINGS_FAVICON, scale_factor);
    414 }
    415 
    416 void OptionsUI::DidStartProvisionalLoadForFrame(
    417     content::RenderFrameHost* render_frame_host,
    418     const GURL& validated_url,
    419     bool is_error_page,
    420     bool is_iframe_srcdoc) {
    421   if (render_frame_host->GetRenderViewHost() ==
    422           web_ui()->GetWebContents()->GetRenderViewHost() &&
    423       validated_url.host() == chrome::kChromeUISettingsFrameHost) {
    424     for (size_t i = 0; i < handlers_.size(); ++i)
    425       handlers_[i]->PageLoadStarted();
    426   }
    427 }
    428 
    429 void OptionsUI::InitializeHandlers() {
    430   Profile* profile = Profile::FromWebUI(web_ui());
    431   DCHECK(!profile->IsOffTheRecord() || profile->IsGuestSession());
    432 
    433   // A new web page DOM has been brought up in an existing renderer, causing
    434   // this method to be called twice. If that happens, ignore the second call.
    435   if (!initialized_handlers_) {
    436     for (size_t i = 0; i < handlers_.size(); ++i)
    437       handlers_[i]->InitializeHandler();
    438     initialized_handlers_ = true;
    439 
    440 #if defined(OS_CHROMEOS)
    441     pointer_device_observer_->Init();
    442 #endif
    443   }
    444 
    445 #if defined(OS_CHROMEOS)
    446   pointer_device_observer_->CheckDevices();
    447 #endif
    448 
    449   // Always initialize the page as when handlers are left over we still need to
    450   // do various things like show/hide sections and send data to the Javascript.
    451   for (size_t i = 0; i < handlers_.size(); ++i)
    452     handlers_[i]->InitializePage();
    453 
    454   web_ui()->CallJavascriptFunction(
    455       "BrowserOptions.notifyInitializationComplete");
    456 }
    457 
    458 void OptionsUI::OnFinishedLoading() {
    459   on_finished_loading_callbacks_.Notify();
    460 }
    461 
    462 void OptionsUI::AddOptionsPageUIHandler(
    463     base::DictionaryValue* localized_strings,
    464     OptionsPageUIHandler* handler_raw) {
    465   scoped_ptr<OptionsPageUIHandler> handler(handler_raw);
    466   DCHECK(handler.get());
    467   // Add only if handler's service is enabled.
    468   if (handler->IsEnabled()) {
    469     // Add handler to the list and also pass the ownership.
    470     web_ui()->AddMessageHandler(handler.release());
    471     handler_raw->GetLocalizedValues(localized_strings);
    472     handlers_.push_back(handler_raw);
    473   }
    474 }
    475 
    476 }  // namespace options
    477