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/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