options_ui.cc revision bb1529ce867d8845a77ec7cdf3e3003ef1771a40
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
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    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      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
353OptionsUI::~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
360void 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
381base::RefCountedMemory* OptionsUI::GetFaviconResourceBytes(
382      ui::ScaleFactor scale_factor) {
383  return ui::ResourceBundle::GetSharedInstance().
384      LoadDataResourceBytesForScale(IDR_SETTINGS_FAVICON, scale_factor);
385}
386
387void 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
416void 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
422void 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
428void 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