1// Copyright (c) 2011 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/singleton.h"
13#include "base/message_loop.h"
14#include "base/string_piece.h"
15#include "base/string_util.h"
16#include "base/threading/thread.h"
17#include "base/time.h"
18#include "base/values.h"
19#include "chrome/browser/browser_about_handler.h"
20#include "chrome/browser/metrics/user_metrics.h"
21#include "chrome/browser/profiles/profile.h"
22#include "chrome/browser/ui/webui/options/about_page_handler.h"
23#include "chrome/browser/ui/webui/options/advanced_options_handler.h"
24#include "chrome/browser/ui/webui/options/autofill_options_handler.h"
25#include "chrome/browser/ui/webui/options/browser_options_handler.h"
26#include "chrome/browser/ui/webui/options/clear_browser_data_handler.h"
27#include "chrome/browser/ui/webui/options/content_settings_handler.h"
28#include "chrome/browser/ui/webui/options/cookies_view_handler.h"
29#include "chrome/browser/ui/webui/options/core_options_handler.h"
30#include "chrome/browser/ui/webui/options/font_settings_handler.h"
31#include "chrome/browser/ui/webui/options/import_data_handler.h"
32#include "chrome/browser/ui/webui/options/language_options_handler.h"
33#include "chrome/browser/ui/webui/options/password_manager_handler.h"
34#include "chrome/browser/ui/webui/options/personal_options_handler.h"
35#include "chrome/browser/ui/webui/options/search_engine_manager_handler.h"
36#include "chrome/browser/ui/webui/options/stop_syncing_handler.h"
37#include "chrome/browser/ui/webui/options/sync_setup_handler.h"
38#include "chrome/browser/ui/webui/theme_source.h"
39#include "chrome/common/jstemplate_builder.h"
40#include "chrome/common/time_format.h"
41#include "chrome/common/url_constants.h"
42#include "content/browser/browser_thread.h"
43#include "content/browser/renderer_host/render_view_host.h"
44#include "content/browser/tab_contents/tab_contents.h"
45#include "content/browser/tab_contents/tab_contents_delegate.h"
46#include "content/common/notification_type.h"
47#include "grit/browser_resources.h"
48#include "grit/chromium_strings.h"
49#include "grit/generated_resources.h"
50#include "grit/locale_settings.h"
51#include "grit/theme_resources.h"
52#include "net/base/escape.h"
53#include "ui/base/resource/resource_bundle.h"
54
55#if defined(OS_CHROMEOS)
56#include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h"
57#include "chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.h"
58#include "chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h"
59#include "chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.h"
60#include "chrome/browser/ui/webui/options/chromeos/internet_options_handler.h"
61#include "chrome/browser/ui/webui/options/chromeos/language_chewing_handler.h"
62#include "chrome/browser/ui/webui/options/chromeos/language_customize_modifier_keys_handler.h"
63#include "chrome/browser/ui/webui/options/chromeos/language_hangul_handler.h"
64#include "chrome/browser/ui/webui/options/chromeos/language_mozc_handler.h"
65#include "chrome/browser/ui/webui/options/chromeos/language_pinyin_handler.h"
66#include "chrome/browser/ui/webui/options/chromeos/proxy_handler.h"
67#include "chrome/browser/ui/webui/options/chromeos/stats_options_handler.h"
68#include "chrome/browser/ui/webui/options/chromeos/system_options_handler.h"
69#include "chrome/browser/ui/webui/options/chromeos/user_image_source.h"
70#endif
71
72#if defined(USE_NSS)
73#include "chrome/browser/ui/webui/options/certificate_manager_handler.h"
74#endif
75
76////////////////////////////////////////////////////////////////////////////////
77//
78// OptionsUIHTMLSource
79//
80////////////////////////////////////////////////////////////////////////////////
81
82class OptionsUIHTMLSource : public ChromeURLDataManager::DataSource {
83 public:
84  // The constructor takes over ownership of |localized_strings|.
85  explicit OptionsUIHTMLSource(DictionaryValue* localized_strings);
86  virtual ~OptionsUIHTMLSource();
87
88  // Called when the network layer has requested a resource underneath
89  // the path we registered.
90  virtual void StartDataRequest(const std::string& path,
91                                bool is_incognito,
92                                int request_id);
93  virtual std::string GetMimeType(const std::string&) const;
94
95 private:
96   // Localized strings collection.
97  scoped_ptr<DictionaryValue> localized_strings_;
98
99  DISALLOW_COPY_AND_ASSIGN(OptionsUIHTMLSource);
100};
101
102OptionsUIHTMLSource::OptionsUIHTMLSource(DictionaryValue* localized_strings)
103    : DataSource(chrome::kChromeUISettingsHost, MessageLoop::current()) {
104  DCHECK(localized_strings);
105  localized_strings_.reset(localized_strings);
106}
107
108OptionsUIHTMLSource::~OptionsUIHTMLSource() {}
109
110void OptionsUIHTMLSource::StartDataRequest(const std::string& path,
111                                           bool is_incognito,
112                                           int request_id) {
113  SetFontAndTextDirection(localized_strings_.get());
114
115  static const base::StringPiece options_html(
116      ResourceBundle::GetSharedInstance().GetRawDataResource(
117          IDR_OPTIONS_HTML));
118  const std::string full_html = jstemplate_builder::GetI18nTemplateHtml(
119      options_html, localized_strings_.get());
120
121  scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
122  html_bytes->data.resize(full_html.size());
123  std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
124
125  SendResponse(request_id, html_bytes);
126}
127
128std::string OptionsUIHTMLSource::GetMimeType(const std::string&) const {
129  return "text/html";
130}
131
132////////////////////////////////////////////////////////////////////////////////
133//
134// OptionsPageUIHandler
135//
136////////////////////////////////////////////////////////////////////////////////
137
138OptionsPageUIHandler::OptionsPageUIHandler() {
139}
140
141OptionsPageUIHandler::~OptionsPageUIHandler() {
142}
143
144bool OptionsPageUIHandler::IsEnabled() {
145  return true;
146}
147
148void OptionsPageUIHandler::UserMetricsRecordAction(
149    const UserMetricsAction& action) {
150  UserMetrics::RecordAction(action, web_ui_->GetProfile());
151}
152
153// static
154void OptionsPageUIHandler::RegisterStrings(
155    DictionaryValue* localized_strings,
156    const OptionsStringResource* resources,
157    size_t length) {
158  for (size_t i = 0; i < length; ++i) {
159    localized_strings->SetString(
160        resources[i].name, l10n_util::GetStringUTF16(resources[i].id));
161  }
162}
163
164void OptionsPageUIHandler::RegisterTitle(DictionaryValue* localized_strings,
165                                         const std::string& variable_name,
166                                         int title_id) {
167  localized_strings->SetString(variable_name,
168      l10n_util::GetStringUTF16(title_id));
169  localized_strings->SetString(variable_name + "TabTitle",
170      l10n_util::GetStringFUTF16(IDS_OPTIONS_TAB_TITLE,
171          l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE),
172          l10n_util::GetStringUTF16(title_id)));
173}
174
175////////////////////////////////////////////////////////////////////////////////
176//
177// OptionsUI
178//
179////////////////////////////////////////////////////////////////////////////////
180
181OptionsUI::OptionsUI(TabContents* contents)
182    : WebUI(contents), initialized_handlers_(false) {
183  DictionaryValue* localized_strings = new DictionaryValue();
184
185  CoreOptionsHandler* core_handler;
186#if defined(OS_CHROMEOS)
187  core_handler = new chromeos::CoreChromeOSOptionsHandler();
188#else
189  core_handler = new CoreOptionsHandler();
190#endif
191  core_handler->set_handlers_host(this);
192  AddOptionsPageUIHandler(localized_strings, core_handler);
193
194  AddOptionsPageUIHandler(localized_strings, new AdvancedOptionsHandler());
195  AddOptionsPageUIHandler(localized_strings, new AutofillOptionsHandler());
196  AddOptionsPageUIHandler(localized_strings, new BrowserOptionsHandler());
197  AddOptionsPageUIHandler(localized_strings, new ClearBrowserDataHandler());
198  AddOptionsPageUIHandler(localized_strings, new ContentSettingsHandler());
199  AddOptionsPageUIHandler(localized_strings, new CookiesViewHandler());
200  AddOptionsPageUIHandler(localized_strings, new FontSettingsHandler());
201#if defined(OS_CHROMEOS)
202  AddOptionsPageUIHandler(localized_strings,
203                          new chromeos::CrosLanguageOptionsHandler());
204#else
205  AddOptionsPageUIHandler(localized_strings, new LanguageOptionsHandler());
206#endif
207  AddOptionsPageUIHandler(localized_strings, new PasswordManagerHandler());
208  AddOptionsPageUIHandler(localized_strings, new PersonalOptionsHandler());
209  AddOptionsPageUIHandler(localized_strings, new SearchEngineManagerHandler());
210  AddOptionsPageUIHandler(localized_strings, new ImportDataHandler());
211  AddOptionsPageUIHandler(localized_strings, new StopSyncingHandler());
212  AddOptionsPageUIHandler(localized_strings, new SyncSetupHandler());
213#if defined(OS_CHROMEOS)
214  AddOptionsPageUIHandler(localized_strings, new AboutPageHandler());
215  AddOptionsPageUIHandler(localized_strings,
216                          new chromeos::AccountsOptionsHandler());
217  AddOptionsPageUIHandler(localized_strings, new InternetOptionsHandler());
218  AddOptionsPageUIHandler(localized_strings,
219                          new chromeos::LanguageChewingHandler());
220  AddOptionsPageUIHandler(localized_strings,
221                          new chromeos::LanguageCustomizeModifierKeysHandler());
222  AddOptionsPageUIHandler(localized_strings,
223                          new chromeos::LanguageHangulHandler());
224  AddOptionsPageUIHandler(localized_strings,
225                          new chromeos::LanguageMozcHandler());
226  AddOptionsPageUIHandler(localized_strings,
227                          new chromeos::LanguagePinyinHandler());
228  AddOptionsPageUIHandler(localized_strings, new chromeos::ProxyHandler());
229  AddOptionsPageUIHandler(localized_strings,
230                          new chromeos::ChangePictureOptionsHandler());
231  AddOptionsPageUIHandler(localized_strings,
232                          new chromeos::StatsOptionsHandler());
233  AddOptionsPageUIHandler(localized_strings, new SystemOptionsHandler());
234#endif
235#if defined(USE_NSS)
236  AddOptionsPageUIHandler(localized_strings, new CertificateManagerHandler());
237#endif
238
239  // |localized_strings| ownership is taken over by this constructor.
240  OptionsUIHTMLSource* html_source =
241      new OptionsUIHTMLSource(localized_strings);
242
243  // Set up the chrome://settings/ source.
244  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
245
246  // Set up the chrome://theme/ source.
247  ThemeSource* theme = new ThemeSource(contents->profile());
248  contents->profile()->GetChromeURLDataManager()->AddDataSource(theme);
249
250#if defined(OS_CHROMEOS)
251  // Set up the chrome://userimage/ source.
252  chromeos::UserImageSource* user_image_source =
253      new chromeos::UserImageSource();
254  contents->profile()->GetChromeURLDataManager()->AddDataSource(
255      user_image_source);
256#endif
257
258  // Initialize the chrome://about/ source in case the user clicks the credits
259  // link.
260  InitializeAboutDataSource(contents->profile());
261}
262
263OptionsUI::~OptionsUI() {
264  // Uninitialize all registered handlers. The base class owns them and it will
265  // eventually delete them. Skip over the generic handler.
266  for (std::vector<WebUIMessageHandler*>::iterator iter = handlers_.begin() + 1;
267       iter != handlers_.end();
268       ++iter) {
269    static_cast<OptionsPageUIHandler*>(*iter)->Uninitialize();
270  }
271}
272
273// Override.
274void OptionsUI::RenderViewCreated(RenderViewHost* render_view_host) {
275  std::string command_line_string;
276
277#if defined(OS_WIN)
278  std::wstring wstr = CommandLine::ForCurrentProcess()->command_line_string();
279  command_line_string = WideToASCII(wstr);
280#else
281  command_line_string = CommandLine::ForCurrentProcess()->command_line_string();
282#endif
283
284  render_view_host->SetWebUIProperty("commandLineString", command_line_string);
285  WebUI::RenderViewCreated(render_view_host);
286}
287
288void OptionsUI::DidBecomeActiveForReusedRenderView() {
289  // When the renderer is re-used (e.g., for back/forward navigation within
290  // options), the handlers are torn down and rebuilt, so are no longer
291  // initialized, but the web page's DOM may remain intact, in which case onload
292  // won't fire to initilize the handlers. To make sure initialization always
293  // happens, call reinitializeCore (which is a no-op unless the DOM was already
294  // initialized).
295  CallJavascriptFunction("OptionsPage.reinitializeCore");
296
297  WebUI::DidBecomeActiveForReusedRenderView();
298}
299
300// static
301RefCountedMemory* OptionsUI::GetFaviconResourceBytes() {
302  return ResourceBundle::GetSharedInstance().
303      LoadDataResourceBytes(IDR_SETTINGS_FAVICON);
304}
305
306void OptionsUI::InitializeHandlers() {
307  DCHECK(!GetProfile()->IsOffTheRecord() || Profile::IsGuestSession());
308
309  // The reinitialize call from DidBecomeActiveForReusedRenderView end up being
310  // delivered after a new web page DOM has been brought up in an existing
311  // renderer (due to IPC delays), causing this method to be called twice. If
312  // that happens, ignore the second call.
313  if (initialized_handlers_)
314    return;
315  initialized_handlers_ = true;
316
317  std::vector<WebUIMessageHandler*>::iterator iter;
318  // Skip over the generic handler.
319  for (iter = handlers_.begin() + 1; iter != handlers_.end(); ++iter) {
320    (static_cast<OptionsPageUIHandler*>(*iter))->Initialize();
321  }
322}
323
324void OptionsUI::AddOptionsPageUIHandler(DictionaryValue* localized_strings,
325                                        OptionsPageUIHandler* handler_raw) {
326  scoped_ptr<OptionsPageUIHandler> handler(handler_raw);
327  DCHECK(handler.get());
328  // Add only if handler's service is enabled.
329  if (handler->IsEnabled()) {
330    handler->GetLocalizedValues(localized_strings);
331    // Add handler to the list and also pass the ownership.
332    AddMessageHandler(handler.release()->Attach(this));
333  }
334}
335