options_ui.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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/autocomplete/autocomplete_match.h"
22#include "chrome/browser/autocomplete/autocomplete_result.h"
23#include "chrome/browser/browser_about_handler.h"
24#include "chrome/browser/browser_process.h"
25#include "chrome/browser/profiles/profile.h"
26#include "chrome/browser/ui/webui/options/autofill_options_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/font_settings_handler.h"
34#include "chrome/browser/ui/webui/options/handler_options_handler.h"
35#include "chrome/browser/ui/webui/options/home_page_overlay_handler.h"
36#include "chrome/browser/ui/webui/options/import_data_handler.h"
37#include "chrome/browser/ui/webui/options/language_dictionary_overlay_handler.h"
38#include "chrome/browser/ui/webui/options/language_options_handler.h"
39#include "chrome/browser/ui/webui/options/manage_profile_handler.h"
40#include "chrome/browser/ui/webui/options/managed_user_create_confirm_handler.h"
41#include "chrome/browser/ui/webui/options/managed_user_import_handler.h"
42#include "chrome/browser/ui/webui/options/managed_user_learn_more_handler.h"
43#include "chrome/browser/ui/webui/options/media_devices_selection_handler.h"
44#include "chrome/browser/ui/webui/options/media_galleries_handler.h"
45#include "chrome/browser/ui/webui/options/password_manager_handler.h"
46#include "chrome/browser/ui/webui/options/reset_profile_settings_handler.h"
47#include "chrome/browser/ui/webui/options/search_engine_manager_handler.h"
48#include "chrome/browser/ui/webui/options/startup_pages_handler.h"
49#include "chrome/browser/ui/webui/sync_setup_handler.h"
50#include "chrome/browser/ui/webui/theme_source.h"
51#include "chrome/common/url_constants.h"
52#include "content/public/browser/notification_types.h"
53#include "content/public/browser/render_view_host.h"
54#include "content/public/browser/url_data_source.h"
55#include "content/public/browser/web_contents.h"
56#include "content/public/browser/web_contents_delegate.h"
57#include "content/public/browser/web_ui.h"
58#include "grit/chromium_strings.h"
59#include "grit/generated_resources.h"
60#include "grit/locale_settings.h"
61#include "grit/options_resources.h"
62#include "grit/theme_resources.h"
63#include "net/base/escape.h"
64#include "ui/base/l10n/l10n_util.h"
65#include "ui/base/resource/resource_bundle.h"
66#include "ui/base/webui/jstemplate_builder.h"
67#include "ui/base/webui/web_ui_util.h"
68#include "url/gurl.h"
69
70#if defined(OS_CHROMEOS)
71#include "chrome/browser/chromeos/system/pointer_device_observer.h"
72#include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h"
73#include "chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h"
74#include "chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.h"
75#include "chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h"
76#include "chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.h"
77#include "chrome/browser/ui/webui/options/chromeos/display_options_handler.h"
78#include "chrome/browser/ui/webui/options/chromeos/display_overscan_handler.h"
79#include "chrome/browser/ui/webui/options/chromeos/internet_options_handler.h"
80#include "chrome/browser/ui/webui/options/chromeos/keyboard_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
95using content::RenderViewHost;
96
97namespace {
98
99const char kLocalizedStringsFile[] = "strings.js";
100const char kOptionsBundleJsFile[]  = "options_bundle.js";
101
102}  // namespace
103
104namespace options {
105
106////////////////////////////////////////////////////////////////////////////////
107//
108// OptionsUIHTMLSource
109//
110////////////////////////////////////////////////////////////////////////////////
111
112class 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
136OptionsUIHTMLSource::OptionsUIHTMLSource(DictionaryValue* localized_strings) {
137  DCHECK(localized_strings);
138  localized_strings_.reset(localized_strings);
139}
140
141std::string OptionsUIHTMLSource::GetSource() const {
142  return chrome::kChromeUISettingsFrameHost;
143}
144
145void 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
172std::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
179bool OptionsUIHTMLSource::ShouldDenyXFrameOptions() const {
180  return false;
181}
182
183OptionsUIHTMLSource::~OptionsUIHTMLSource() {}
184
185////////////////////////////////////////////////////////////////////////////////
186//
187// OptionsPageUIHandler
188//
189////////////////////////////////////////////////////////////////////////////////
190
191const char OptionsPageUIHandler::kSettingsAppKey[] = "settingsApp";
192
193OptionsPageUIHandler::OptionsPageUIHandler() {
194}
195
196OptionsPageUIHandler::~OptionsPageUIHandler() {
197}
198
199bool OptionsPageUIHandler::IsEnabled() {
200  return true;
201}
202
203// static
204void OptionsPageUIHandler::RegisterStrings(
205    DictionaryValue* localized_strings,
206    const OptionsStringResource* resources,
207    size_t length) {
208  for (size_t i = 0; i < length; ++i) {
209    base::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
221void 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
238OptionsUI::OptionsUI(content::WebUI* web_ui)
239    : WebUIController(web_ui),
240      WebContentsObserver(web_ui->GetWebContents()),
241      initialized_handlers_(false) {
242  DictionaryValue* localized_strings = new DictionaryValue();
243  localized_strings->Set(OptionsPageUIHandler::kSettingsAppKey,
244                         new DictionaryValue());
245
246  CoreOptionsHandler* core_handler;
247#if defined(OS_CHROMEOS)
248  core_handler = new chromeos::options::CoreChromeOSOptionsHandler();
249#else
250  core_handler = new CoreOptionsHandler();
251#endif
252  core_handler->set_handlers_host(this);
253  AddOptionsPageUIHandler(localized_strings, core_handler);
254
255  AddOptionsPageUIHandler(localized_strings, new AutofillOptionsHandler());
256
257  BrowserOptionsHandler* browser_options_handler = new BrowserOptionsHandler();
258  AddOptionsPageUIHandler(localized_strings, browser_options_handler);
259
260  AddOptionsPageUIHandler(localized_strings, new ClearBrowserDataHandler());
261  AddOptionsPageUIHandler(localized_strings, new ContentSettingsHandler());
262  AddOptionsPageUIHandler(localized_strings, new CookiesViewHandler());
263  AddOptionsPageUIHandler(localized_strings, new CreateProfileHandler());
264  AddOptionsPageUIHandler(localized_strings, new FontSettingsHandler());
265#if defined(ENABLE_GOOGLE_NOW)
266  AddOptionsPageUIHandler(localized_strings, new GeolocationOptionsHandler());
267#endif
268  AddOptionsPageUIHandler(localized_strings, new HomePageOverlayHandler());
269  AddOptionsPageUIHandler(localized_strings,
270                          new MediaDevicesSelectionHandler());
271  AddOptionsPageUIHandler(localized_strings, new MediaGalleriesHandler());
272#if defined(OS_CHROMEOS)
273  AddOptionsPageUIHandler(localized_strings,
274                          new chromeos::options::CrosLanguageOptionsHandler());
275#else
276  AddOptionsPageUIHandler(localized_strings, new LanguageOptionsHandler());
277#endif
278  AddOptionsPageUIHandler(localized_strings,
279                          new LanguageDictionaryOverlayHandler());
280  AddOptionsPageUIHandler(localized_strings, new ManageProfileHandler());
281  AddOptionsPageUIHandler(localized_strings,
282                          new ManagedUserCreateConfirmHandler());
283  AddOptionsPageUIHandler(localized_strings, new ManagedUserImportHandler());
284  AddOptionsPageUIHandler(localized_strings, new ManagedUserLearnMoreHandler());
285  AddOptionsPageUIHandler(localized_strings, new PasswordManagerHandler());
286  AddOptionsPageUIHandler(localized_strings, new ResetProfileSettingsHandler());
287  AddOptionsPageUIHandler(localized_strings, new SearchEngineManagerHandler());
288  AddOptionsPageUIHandler(localized_strings, new ImportDataHandler());
289  AddOptionsPageUIHandler(localized_strings, new StartupPagesHandler());
290  AddOptionsPageUIHandler(localized_strings, new SyncSetupHandler(
291      g_browser_process->profile_manager()));
292#if defined(OS_CHROMEOS)
293  AddOptionsPageUIHandler(localized_strings,
294                          new chromeos::options::AccountsOptionsHandler());
295  AddOptionsPageUIHandler(localized_strings,
296                          new chromeos::options::BluetoothOptionsHandler());
297  AddOptionsPageUIHandler(localized_strings,
298                          new chromeos::options::DisplayOptionsHandler());
299  AddOptionsPageUIHandler(localized_strings,
300                          new chromeos::options::DisplayOverscanHandler());
301  AddOptionsPageUIHandler(localized_strings,
302                          new chromeos::options::InternetOptionsHandler());
303  AddOptionsPageUIHandler(localized_strings,
304                          new chromeos::options::KeyboardHandler());
305
306  chromeos::options::PointerHandler* pointer_handler =
307      new chromeos::options::PointerHandler();
308  AddOptionsPageUIHandler(localized_strings, pointer_handler);
309
310  AddOptionsPageUIHandler(localized_strings,
311                          new chromeos::options::ProxyHandler());
312  AddOptionsPageUIHandler(
313      localized_strings,
314      new chromeos::options::ChangePictureOptionsHandler());
315  AddOptionsPageUIHandler(localized_strings,
316                          new chromeos::options::StatsOptionsHandler());
317#endif
318#if defined(USE_NSS)
319  AddOptionsPageUIHandler(localized_strings, new CertificateManagerHandler());
320#endif
321  AddOptionsPageUIHandler(localized_strings, new HandlerOptionsHandler());
322
323  // |localized_strings| ownership is taken over by this constructor.
324  OptionsUIHTMLSource* html_source =
325      new OptionsUIHTMLSource(localized_strings);
326
327  // Set up the chrome://settings-frame/ source.
328  Profile* profile = Profile::FromWebUI(web_ui);
329  content::URLDataSource::Add(profile, html_source);
330
331  // Set up the chrome://theme/ source.
332  ThemeSource* theme = new ThemeSource(profile);
333  content::URLDataSource::Add(profile, theme);
334
335#if defined(OS_CHROMEOS)
336  // Set up the chrome://userimage/ source.
337  chromeos::options::UserImageSource* user_image_source =
338      new chromeos::options::UserImageSource();
339  content::URLDataSource::Add(profile, user_image_source);
340
341  pointer_device_observer_.reset(
342      new chromeos::system::PointerDeviceObserver());
343  pointer_device_observer_->AddObserver(browser_options_handler);
344  pointer_device_observer_->AddObserver(pointer_handler);
345#endif
346}
347
348OptionsUI::~OptionsUI() {
349  // Uninitialize all registered handlers. Deleted by WebUIImpl.
350  for (size_t i = 0; i < handlers_.size(); ++i)
351    handlers_[i]->Uninitialize();
352}
353
354// static
355void OptionsUI::ProcessAutocompleteSuggestions(
356    const AutocompleteResult& result,
357    base::ListValue* const suggestions) {
358  for (size_t i = 0; i < result.size(); ++i) {
359    const AutocompleteMatch& match = result.match_at(i);
360    AutocompleteMatchType::Type type = match.type;
361    if (type != AutocompleteMatchType::HISTORY_URL &&
362        type != AutocompleteMatchType::HISTORY_TITLE &&
363        type != AutocompleteMatchType::HISTORY_BODY &&
364        type != AutocompleteMatchType::HISTORY_KEYWORD &&
365        type != AutocompleteMatchType::NAVSUGGEST)
366      continue;
367    base::DictionaryValue* entry = new base::DictionaryValue();
368    entry->SetString("title", match.description);
369    entry->SetString("displayURL", match.contents);
370    entry->SetString("url", match.destination_url.spec());
371    suggestions->Append(entry);
372  }
373}
374
375// static
376base::RefCountedMemory* OptionsUI::GetFaviconResourceBytes(
377      ui::ScaleFactor scale_factor) {
378  return ui::ResourceBundle::GetSharedInstance().
379      LoadDataResourceBytesForScale(IDR_SETTINGS_FAVICON, scale_factor);
380}
381
382void OptionsUI::DidStartProvisionalLoadForFrame(
383    int64 frame_id,
384    int64 parent_frame_id,
385    bool is_main_frame,
386    const GURL& validated_url,
387    bool is_error_page,
388    bool is_iframe_srcdoc,
389    content::RenderViewHost* render_view_host) {
390  if (render_view_host == web_ui()->GetWebContents()->GetRenderViewHost() &&
391      validated_url.host() == chrome::kChromeUISettingsFrameHost) {
392    for (size_t i = 0; i < handlers_.size(); ++i)
393      handlers_[i]->PageLoadStarted();
394  }
395}
396
397void OptionsUI::InitializeHandlers() {
398  Profile* profile = Profile::FromWebUI(web_ui());
399  DCHECK(!profile->IsOffTheRecord() || profile->IsGuestSession());
400
401  // A new web page DOM has been brought up in an existing renderer, causing
402  // this method to be called twice. If that happens, ignore the second call.
403  if (!initialized_handlers_) {
404    for (size_t i = 0; i < handlers_.size(); ++i)
405      handlers_[i]->InitializeHandler();
406    initialized_handlers_ = true;
407
408#if defined(OS_CHROMEOS)
409    pointer_device_observer_->Init();
410#endif
411  }
412
413#if defined(OS_CHROMEOS)
414  pointer_device_observer_->CheckDevices();
415#endif
416
417  // Always initialize the page as when handlers are left over we still need to
418  // do various things like show/hide sections and send data to the Javascript.
419  for (size_t i = 0; i < handlers_.size(); ++i)
420    handlers_[i]->InitializePage();
421
422  web_ui()->CallJavascriptFunction(
423      "BrowserOptions.notifyInitializationComplete");
424}
425
426void OptionsUI::AddOptionsPageUIHandler(DictionaryValue* localized_strings,
427                                        OptionsPageUIHandler* handler_raw) {
428  scoped_ptr<OptionsPageUIHandler> handler(handler_raw);
429  DCHECK(handler.get());
430  // Add only if handler's service is enabled.
431  if (handler->IsEnabled()) {
432    // Add handler to the list and also pass the ownership.
433    web_ui()->AddMessageHandler(handler.release());
434    handler_raw->GetLocalizedValues(localized_strings);
435    handlers_.push_back(handler_raw);
436  }
437}
438
439}  // namespace options
440