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.
5 #include "chrome/browser/ui/webui/options/options_ui.h"
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/extensions/tab_helper.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/ui/webui/metrics_handler.h"
26 #include "chrome/browser/ui/webui/options/autofill_options_handler.h"
27 #include "chrome/browser/ui/webui/options/automatic_settings_reset_handler.h"
28 #include "chrome/browser/ui/webui/options/browser_options_handler.h"
29 #include "chrome/browser/ui/webui/options/clear_browser_data_handler.h"
30 #include "chrome/browser/ui/webui/options/content_settings_handler.h"
31 #include "chrome/browser/ui/webui/options/cookies_view_handler.h"
32 #include "chrome/browser/ui/webui/options/core_options_handler.h"
33 #include "chrome/browser/ui/webui/options/create_profile_handler.h"
34 #include "chrome/browser/ui/webui/options/easy_unlock_handler.h"
35 #include "chrome/browser/ui/webui/options/font_settings_handler.h"
36 #include "chrome/browser/ui/webui/options/handler_options_handler.h"
37 #include "chrome/browser/ui/webui/options/help_overlay_handler.h"
38 #include "chrome/browser/ui/webui/options/home_page_overlay_handler.h"
39 #include "chrome/browser/ui/webui/options/import_data_handler.h"
40 #include "chrome/browser/ui/webui/options/language_dictionary_overlay_handler.h"
41 #include "chrome/browser/ui/webui/options/language_options_handler.h"
42 #include "chrome/browser/ui/webui/options/manage_profile_handler.h"
43 #include "chrome/browser/ui/webui/options/media_devices_selection_handler.h"
44 #include "chrome/browser/ui/webui/options/password_manager_handler.h"
45 #include "chrome/browser/ui/webui/options/reset_profile_settings_handler.h"
46 #include "chrome/browser/ui/webui/options/search_engine_manager_handler.h"
47 #include "chrome/browser/ui/webui/options/startup_pages_handler.h"
48 #include "chrome/browser/ui/webui/options/sync_setup_handler.h"
49 #include "chrome/browser/ui/webui/theme_source.h"
50 #include "chrome/common/url_constants.h"
51 #include "chrome/grit/generated_resources.h"
52 #include "chrome/grit/locale_settings.h"
53 #include "components/omnibox/browser/autocomplete_match.h"
54 #include "components/omnibox/browser/autocomplete_result.h"
55 #include "content/public/browser/notification_types.h"
56 #include "content/public/browser/render_frame_host.h"
57 #include "content/public/browser/url_data_source.h"
58 #include "content/public/browser/web_contents.h"
59 #include "content/public/browser/web_contents_delegate.h"
60 #include "content/public/browser/web_ui.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"
70 #if defined(ENABLE_SUPERVISED_USERS)
71 #include "chrome/browser/ui/webui/options/supervised_user_create_confirm_handler.h"
72 #include "chrome/browser/ui/webui/options/supervised_user_import_handler.h"
73 #include "chrome/browser/ui/webui/options/supervised_user_learn_more_handler.h"
76 #if defined(OS_CHROMEOS)
77 #include "chrome/browser/browser_process_platform_part.h"
78 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
79 #include "chrome/browser/chromeos/policy/consumer_management_service.h"
80 #include "chrome/browser/chromeos/system/pointer_device_observer.h"
81 #include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h"
82 #include "chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h"
83 #include "chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.h"
84 #include "chrome/browser/ui/webui/options/chromeos/consumer_management_handler.h"
85 #include "chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h"
86 #include "chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.h"
87 #include "chrome/browser/ui/webui/options/chromeos/date_time_options_handler.h"
88 #include "chrome/browser/ui/webui/options/chromeos/display_options_handler.h"
89 #include "chrome/browser/ui/webui/options/chromeos/display_overscan_handler.h"
90 #include "chrome/browser/ui/webui/options/chromeos/internet_options_handler.h"
91 #include "chrome/browser/ui/webui/options/chromeos/keyboard_handler.h"
92 #include "chrome/browser/ui/webui/options/chromeos/pointer_handler.h"
93 #include "chrome/browser/ui/webui/options/chromeos/power_handler.h"
94 #include "chrome/browser/ui/webui/options/chromeos/proxy_handler.h"
95 #include "chrome/browser/ui/webui/options/chromeos/stats_options_handler.h"
96 #include "chrome/browser/ui/webui/options/chromeos/user_image_source.h"
99 #if defined(USE_NSS_CERTS)
100 #include "chrome/browser/ui/webui/options/certificate_manager_handler.h"
103 #if defined(ENABLE_GOOGLE_NOW)
104 #include "chrome/browser/ui/webui/options/geolocation_options_handler.h"
107 using content::RenderViewHost
;
111 const char kLocalizedStringsFile
[] = "strings.js";
112 const char kOptionsBundleJsFile
[] = "options_bundle.js";
118 ////////////////////////////////////////////////////////////////////////////////
120 // OptionsUIHTMLSource
122 ////////////////////////////////////////////////////////////////////////////////
124 class OptionsUIHTMLSource
: public content::URLDataSource
{
126 // The constructor takes over ownership of |localized_strings|.
127 explicit OptionsUIHTMLSource(base::DictionaryValue
* localized_strings
);
129 // content::URLDataSource implementation.
130 std::string
GetSource() const override
;
131 void StartDataRequest(
132 const std::string
& path
,
133 int render_process_id
,
135 const content::URLDataSource::GotDataCallback
& callback
) override
;
136 std::string
GetMimeType(const std::string
&) const override
;
137 bool ShouldDenyXFrameOptions() const override
;
140 ~OptionsUIHTMLSource() override
;
142 // Localized strings collection.
143 scoped_ptr
<base::DictionaryValue
> localized_strings_
;
145 DISALLOW_COPY_AND_ASSIGN(OptionsUIHTMLSource
);
148 OptionsUIHTMLSource::OptionsUIHTMLSource(
149 base::DictionaryValue
* localized_strings
) {
150 DCHECK(localized_strings
);
151 localized_strings_
.reset(localized_strings
);
154 std::string
OptionsUIHTMLSource::GetSource() const {
155 return chrome::kChromeUISettingsFrameHost
;
158 void OptionsUIHTMLSource::StartDataRequest(
159 const std::string
& path
,
160 int render_process_id
,
162 const content::URLDataSource::GotDataCallback
& callback
) {
163 scoped_refptr
<base::RefCountedMemory
> response_bytes
;
164 const std::string
& app_locale
= g_browser_process
->GetApplicationLocale();
165 webui::SetLoadTimeDataDefaults(app_locale
, localized_strings_
.get());
167 if (path
== kLocalizedStringsFile
) {
168 // Return dynamically-generated strings from memory.
169 std::string strings_js
;
170 webui::AppendJsonJS(localized_strings_
.get(), &strings_js
);
171 response_bytes
= base::RefCountedString::TakeString(&strings_js
);
172 } else if (path
== kOptionsBundleJsFile
) {
173 // Return (and cache) the options javascript code.
174 response_bytes
= ui::ResourceBundle::GetSharedInstance().
175 LoadDataResourceBytes(IDR_OPTIONS_BUNDLE_JS
);
177 // Return (and cache) the main options html page as the default.
178 response_bytes
= ui::ResourceBundle::GetSharedInstance().
179 LoadDataResourceBytes(IDR_OPTIONS_HTML
);
182 callback
.Run(response_bytes
.get());
185 std::string
OptionsUIHTMLSource::GetMimeType(const std::string
& path
) const {
186 if (path
== kLocalizedStringsFile
|| path
== kOptionsBundleJsFile
)
187 return "application/javascript";
192 bool OptionsUIHTMLSource::ShouldDenyXFrameOptions() const {
196 OptionsUIHTMLSource::~OptionsUIHTMLSource() {}
198 ////////////////////////////////////////////////////////////////////////////////
200 // OptionsPageUIHandler
202 ////////////////////////////////////////////////////////////////////////////////
204 const char OptionsPageUIHandler::kSettingsAppKey
[] = "settingsApp";
206 OptionsPageUIHandler::OptionsPageUIHandler() {
209 OptionsPageUIHandler::~OptionsPageUIHandler() {
212 bool OptionsPageUIHandler::IsEnabled() {
217 void OptionsPageUIHandler::RegisterStrings(
218 base::DictionaryValue
* localized_strings
,
219 const OptionsStringResource
* resources
,
221 for (size_t i
= 0; i
< length
; ++i
) {
222 base::string16 value
;
223 if (resources
[i
].substitution_id
== 0) {
224 value
= l10n_util::GetStringUTF16(resources
[i
].id
);
226 value
= l10n_util::GetStringFUTF16(
228 l10n_util::GetStringUTF16(resources
[i
].substitution_id
));
230 localized_strings
->SetString(resources
[i
].name
, value
);
234 void OptionsPageUIHandler::RegisterTitle(
235 base::DictionaryValue
* localized_strings
,
236 const std::string
& variable_name
,
238 localized_strings
->SetString(variable_name
,
239 l10n_util::GetStringUTF16(title_id
));
240 localized_strings
->SetString(variable_name
+ "TabTitle",
241 l10n_util::GetStringFUTF16(IDS_OPTIONS_TAB_TITLE
,
242 l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE
),
243 l10n_util::GetStringUTF16(title_id
)));
246 ////////////////////////////////////////////////////////////////////////////////
250 ////////////////////////////////////////////////////////////////////////////////
252 OptionsUI::OptionsUI(content::WebUI
* web_ui
)
253 : WebUIController(web_ui
),
254 WebContentsObserver(web_ui
->GetWebContents()),
255 initialized_handlers_(false) {
256 base::DictionaryValue
* localized_strings
= new base::DictionaryValue();
257 localized_strings
->Set(OptionsPageUIHandler::kSettingsAppKey
,
258 new base::DictionaryValue());
260 CoreOptionsHandler
* core_handler
;
261 #if defined(OS_CHROMEOS)
262 core_handler
= new chromeos::options::CoreChromeOSOptionsHandler();
264 core_handler
= new CoreOptionsHandler();
266 core_handler
->set_handlers_host(this);
267 AddOptionsPageUIHandler(localized_strings
, core_handler
);
269 AddOptionsPageUIHandler(localized_strings
, new AutofillOptionsHandler());
270 AddOptionsPageUIHandler(localized_strings
,
271 new AutomaticSettingsResetHandler());
273 BrowserOptionsHandler
* browser_options_handler
= new BrowserOptionsHandler();
274 AddOptionsPageUIHandler(localized_strings
, browser_options_handler
);
276 AddOptionsPageUIHandler(localized_strings
, new ClearBrowserDataHandler());
277 AddOptionsPageUIHandler(localized_strings
, new ContentSettingsHandler());
278 AddOptionsPageUIHandler(localized_strings
, new CookiesViewHandler());
279 AddOptionsPageUIHandler(localized_strings
, new CreateProfileHandler());
280 AddOptionsPageUIHandler(localized_strings
, new EasyUnlockHandler());
281 AddOptionsPageUIHandler(localized_strings
, new FontSettingsHandler());
282 #if defined(ENABLE_GOOGLE_NOW)
283 AddOptionsPageUIHandler(localized_strings
, new GeolocationOptionsHandler());
285 AddOptionsPageUIHandler(localized_strings
, new options::HelpOverlayHandler());
286 AddOptionsPageUIHandler(localized_strings
, new HomePageOverlayHandler());
287 AddOptionsPageUIHandler(localized_strings
,
288 new MediaDevicesSelectionHandler());
289 #if defined(OS_CHROMEOS)
290 AddOptionsPageUIHandler(localized_strings
,
291 new chromeos::options::CrosLanguageOptionsHandler());
293 AddOptionsPageUIHandler(localized_strings
, new LanguageOptionsHandler());
295 AddOptionsPageUIHandler(localized_strings
,
296 new LanguageDictionaryOverlayHandler());
297 AddOptionsPageUIHandler(localized_strings
, new ManageProfileHandler());
298 AddOptionsPageUIHandler(localized_strings
, new PasswordManagerHandler());
299 AddOptionsPageUIHandler(localized_strings
, new ResetProfileSettingsHandler());
300 AddOptionsPageUIHandler(localized_strings
, new SearchEngineManagerHandler());
301 AddOptionsPageUIHandler(localized_strings
, new ImportDataHandler());
302 AddOptionsPageUIHandler(localized_strings
, new StartupPagesHandler());
303 #if defined(ENABLE_SUPERVISED_USERS)
304 AddOptionsPageUIHandler(localized_strings
,
305 new SupervisedUserCreateConfirmHandler());
306 AddOptionsPageUIHandler(localized_strings
, new SupervisedUserImportHandler());
307 AddOptionsPageUIHandler(localized_strings
,
308 new SupervisedUserLearnMoreHandler());
310 AddOptionsPageUIHandler(localized_strings
, new SyncSetupHandler());
311 #if defined(OS_CHROMEOS)
312 AddOptionsPageUIHandler(localized_strings
,
313 new chromeos::options::AccountsOptionsHandler());
314 AddOptionsPageUIHandler(localized_strings
,
315 new chromeos::options::BluetoothOptionsHandler());
316 AddOptionsPageUIHandler(localized_strings
,
317 new chromeos::options::DateTimeOptionsHandler());
318 AddOptionsPageUIHandler(localized_strings
,
319 new chromeos::options::DisplayOptionsHandler());
320 AddOptionsPageUIHandler(localized_strings
,
321 new chromeos::options::DisplayOverscanHandler());
322 AddOptionsPageUIHandler(localized_strings
,
323 new chromeos::options::PowerHandler());
324 AddOptionsPageUIHandler(localized_strings
,
325 new chromeos::options::InternetOptionsHandler());
326 AddOptionsPageUIHandler(localized_strings
,
327 new chromeos::options::KeyboardHandler());
329 chromeos::options::PointerHandler
* pointer_handler
=
330 new chromeos::options::PointerHandler();
331 AddOptionsPageUIHandler(localized_strings
, pointer_handler
);
333 AddOptionsPageUIHandler(localized_strings
,
334 new chromeos::options::ProxyHandler());
335 AddOptionsPageUIHandler(
337 new chromeos::options::ChangePictureOptionsHandler());
338 AddOptionsPageUIHandler(localized_strings
,
339 new chromeos::options::StatsOptionsHandler());
341 policy::ConsumerManagementService
* consumer_management
=
342 g_browser_process
->platform_part()->browser_policy_connector_chromeos()->
343 GetConsumerManagementService();
344 chromeos::options::ConsumerManagementHandler
* consumer_management_handler
=
345 new chromeos::options::ConsumerManagementHandler(consumer_management
);
346 AddOptionsPageUIHandler(localized_strings
, consumer_management_handler
);
348 #if defined(USE_NSS_CERTS)
349 AddOptionsPageUIHandler(localized_strings
,
350 new CertificateManagerHandler(false));
352 AddOptionsPageUIHandler(localized_strings
, new HandlerOptionsHandler());
354 web_ui
->AddMessageHandler(new MetricsHandler());
356 // Enable extension API calls in the WebUI.
357 extensions::TabHelper::CreateForWebContents(web_ui
->GetWebContents());
359 // |localized_strings| ownership is taken over by this constructor.
360 OptionsUIHTMLSource
* html_source
=
361 new OptionsUIHTMLSource(localized_strings
);
363 // Set up the chrome://settings-frame/ source.
364 Profile
* profile
= Profile::FromWebUI(web_ui
);
365 content::URLDataSource::Add(profile
, html_source
);
367 // Set up the chrome://theme/ source.
368 ThemeSource
* theme
= new ThemeSource(profile
);
369 content::URLDataSource::Add(profile
, theme
);
371 #if defined(OS_CHROMEOS)
372 // Set up the chrome://userimage/ source.
373 chromeos::options::UserImageSource
* user_image_source
=
374 new chromeos::options::UserImageSource();
375 content::URLDataSource::Add(profile
, user_image_source
);
377 pointer_device_observer_
.reset(
378 new chromeos::system::PointerDeviceObserver());
379 pointer_device_observer_
->AddObserver(browser_options_handler
);
380 pointer_device_observer_
->AddObserver(pointer_handler
);
384 OptionsUI::~OptionsUI() {
385 // Uninitialize all registered handlers. Deleted by WebUIImpl.
386 for (size_t i
= 0; i
< handlers_
.size(); ++i
)
387 handlers_
[i
]->Uninitialize();
390 scoped_ptr
<OptionsUI::OnFinishedLoadingCallbackList::Subscription
>
391 OptionsUI::RegisterOnFinishedLoadingCallback(const base::Closure
& callback
) {
392 return on_finished_loading_callbacks_
.Add(callback
);
396 void OptionsUI::ProcessAutocompleteSuggestions(
397 const AutocompleteResult
& result
,
398 base::ListValue
* const suggestions
) {
399 for (size_t i
= 0; i
< result
.size(); ++i
) {
400 const AutocompleteMatch
& match
= result
.match_at(i
);
401 AutocompleteMatchType::Type type
= match
.type
;
402 if (type
!= AutocompleteMatchType::HISTORY_URL
&&
403 type
!= AutocompleteMatchType::HISTORY_TITLE
&&
404 type
!= AutocompleteMatchType::HISTORY_BODY
&&
405 type
!= AutocompleteMatchType::HISTORY_KEYWORD
&&
406 type
!= AutocompleteMatchType::NAVSUGGEST
&&
407 type
!= AutocompleteMatchType::NAVSUGGEST_PERSONALIZED
) {
410 base::DictionaryValue
* entry
= new base::DictionaryValue();
411 entry
->SetString("title", match
.description
);
412 entry
->SetString("displayURL", match
.contents
);
413 entry
->SetString("url", match
.destination_url
.spec());
414 suggestions
->Append(entry
);
419 base::RefCountedMemory
* OptionsUI::GetFaviconResourceBytes(
420 ui::ScaleFactor scale_factor
) {
421 return ui::ResourceBundle::GetSharedInstance().
422 LoadDataResourceBytesForScale(IDR_SETTINGS_FAVICON
, scale_factor
);
425 void OptionsUI::DidStartProvisionalLoadForFrame(
426 content::RenderFrameHost
* render_frame_host
,
427 const GURL
& validated_url
,
429 bool is_iframe_srcdoc
) {
430 if (render_frame_host
->GetRenderViewHost() ==
431 web_ui()->GetWebContents()->GetRenderViewHost() &&
432 validated_url
.host() == chrome::kChromeUISettingsFrameHost
) {
433 for (size_t i
= 0; i
< handlers_
.size(); ++i
)
434 handlers_
[i
]->PageLoadStarted();
438 void OptionsUI::InitializeHandlers() {
439 Profile
* profile
= Profile::FromWebUI(web_ui());
440 DCHECK(!profile
->IsOffTheRecord() || profile
->IsGuestSession());
442 // A new web page DOM has been brought up in an existing renderer, causing
443 // this method to be called twice. If that happens, ignore the second call.
444 if (!initialized_handlers_
) {
445 for (size_t i
= 0; i
< handlers_
.size(); ++i
)
446 handlers_
[i
]->InitializeHandler();
447 initialized_handlers_
= true;
449 #if defined(OS_CHROMEOS)
450 pointer_device_observer_
->Init();
454 #if defined(OS_CHROMEOS)
455 pointer_device_observer_
->CheckDevices();
458 // Always initialize the page as when handlers are left over we still need to
459 // do various things like show/hide sections and send data to the Javascript.
460 for (size_t i
= 0; i
< handlers_
.size(); ++i
)
461 handlers_
[i
]->InitializePage();
463 web_ui()->CallJavascriptFunction(
464 "BrowserOptions.notifyInitializationComplete");
467 void OptionsUI::OnFinishedLoading() {
468 on_finished_loading_callbacks_
.Notify();
471 void OptionsUI::AddOptionsPageUIHandler(
472 base::DictionaryValue
* localized_strings
,
473 OptionsPageUIHandler
* handler_raw
) {
474 scoped_ptr
<OptionsPageUIHandler
> handler(handler_raw
);
475 DCHECK(handler
.get());
476 // Add only if handler's service is enabled.
477 if (handler
->IsEnabled()) {
478 // Add handler to the list and also pass the ownership.
479 web_ui()->AddMessageHandler(handler
.release());
480 handler_raw
->GetLocalizedValues(localized_strings
);
481 handlers_
.push_back(handler_raw
);
485 } // namespace options