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/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/metrics_handler.h"
27 #include "chrome/browser/ui/webui/options/autofill_options_handler.h"
28 #include "chrome/browser/ui/webui/options/automatic_settings_reset_handler.h"
29 #include "chrome/browser/ui/webui/options/browser_options_handler.h"
30 #include "chrome/browser/ui/webui/options/clear_browser_data_handler.h"
31 #include "chrome/browser/ui/webui/options/content_settings_handler.h"
32 #include "chrome/browser/ui/webui/options/cookies_view_handler.h"
33 #include "chrome/browser/ui/webui/options/core_options_handler.h"
34 #include "chrome/browser/ui/webui/options/create_profile_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/home_page_overlay_handler.h"
38 #include "chrome/browser/ui/webui/options/import_data_handler.h"
39 #include "chrome/browser/ui/webui/options/language_dictionary_overlay_handler.h"
40 #include "chrome/browser/ui/webui/options/language_options_handler.h"
41 #include "chrome/browser/ui/webui/options/manage_profile_handler.h"
42 #include "chrome/browser/ui/webui/options/managed_user_create_confirm_handler.h"
43 #include "chrome/browser/ui/webui/options/managed_user_import_handler.h"
44 #include "chrome/browser/ui/webui/options/managed_user_learn_more_handler.h"
45 #include "chrome/browser/ui/webui/options/media_devices_selection_handler.h"
46 #include "chrome/browser/ui/webui/options/password_manager_handler.h"
47 #include "chrome/browser/ui/webui/options/reset_profile_settings_handler.h"
48 #include "chrome/browser/ui/webui/options/search_engine_manager_handler.h"
49 #include "chrome/browser/ui/webui/options/startup_pages_handler.h"
50 #include "chrome/browser/ui/webui/sync_setup_handler.h"
51 #include "chrome/browser/ui/webui/theme_source.h"
52 #include "chrome/common/url_constants.h"
53 #include "content/public/browser/notification_types.h"
54 #include "content/public/browser/render_view_host.h"
55 #include "content/public/browser/url_data_source.h"
56 #include "content/public/browser/web_contents.h"
57 #include "content/public/browser/web_contents_delegate.h"
58 #include "content/public/browser/web_ui.h"
59 #include "grit/chromium_strings.h"
60 #include "grit/generated_resources.h"
61 #include "grit/locale_settings.h"
62 #include "grit/options_resources.h"
63 #include "grit/theme_resources.h"
64 #include "net/base/escape.h"
65 #include "ui/base/l10n/l10n_util.h"
66 #include "ui/base/resource/resource_bundle.h"
67 #include "ui/base/webui/jstemplate_builder.h"
68 #include "ui/base/webui/web_ui_util.h"
71 #if defined(OS_CHROMEOS)
72 #include "chrome/browser/chromeos/system/pointer_device_observer.h"
73 #include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h"
74 #include "chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h"
75 #include "chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.h"
76 #include "chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h"
77 #include "chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.h"
78 #include "chrome/browser/ui/webui/options/chromeos/date_time_options_handler.h"
79 #include "chrome/browser/ui/webui/options/chromeos/display_options_handler.h"
80 #include "chrome/browser/ui/webui/options/chromeos/display_overscan_handler.h"
81 #include "chrome/browser/ui/webui/options/chromeos/internet_options_handler.h"
82 #include "chrome/browser/ui/webui/options/chromeos/keyboard_handler.h"
83 #include "chrome/browser/ui/webui/options/chromeos/pointer_handler.h"
84 #include "chrome/browser/ui/webui/options/chromeos/proxy_handler.h"
85 #include "chrome/browser/ui/webui/options/chromeos/stats_options_handler.h"
86 #include "chrome/browser/ui/webui/options/chromeos/user_image_source.h"
90 #include "chrome/browser/ui/webui/options/certificate_manager_handler.h"
93 #if defined(ENABLE_GOOGLE_NOW)
94 #include "chrome/browser/ui/webui/options/geolocation_options_handler.h"
97 using content::RenderViewHost
;
101 const char kLocalizedStringsFile
[] = "strings.js";
102 const char kOptionsBundleJsFile
[] = "options_bundle.js";
108 ////////////////////////////////////////////////////////////////////////////////
110 // OptionsUIHTMLSource
112 ////////////////////////////////////////////////////////////////////////////////
114 class OptionsUIHTMLSource
: public content::URLDataSource
{
116 // The constructor takes over ownership of |localized_strings|.
117 explicit OptionsUIHTMLSource(base::DictionaryValue
* localized_strings
);
119 // content::URLDataSource implementation.
120 virtual std::string
GetSource() const OVERRIDE
;
121 virtual void StartDataRequest(
122 const std::string
& path
,
123 int render_process_id
,
125 const content::URLDataSource::GotDataCallback
& callback
) OVERRIDE
;
126 virtual std::string
GetMimeType(const std::string
&) const OVERRIDE
;
127 virtual bool ShouldDenyXFrameOptions() const OVERRIDE
;
130 virtual ~OptionsUIHTMLSource();
132 // Localized strings collection.
133 scoped_ptr
<base::DictionaryValue
> localized_strings_
;
135 DISALLOW_COPY_AND_ASSIGN(OptionsUIHTMLSource
);
138 OptionsUIHTMLSource::OptionsUIHTMLSource(
139 base::DictionaryValue
* localized_strings
) {
140 DCHECK(localized_strings
);
141 localized_strings_
.reset(localized_strings
);
144 std::string
OptionsUIHTMLSource::GetSource() const {
145 return chrome::kChromeUISettingsFrameHost
;
148 void OptionsUIHTMLSource::StartDataRequest(
149 const std::string
& path
,
150 int render_process_id
,
152 const content::URLDataSource::GotDataCallback
& callback
) {
153 scoped_refptr
<base::RefCountedMemory
> response_bytes
;
154 webui::SetFontAndTextDirection(localized_strings_
.get());
156 if (path
== kLocalizedStringsFile
) {
157 // Return dynamically-generated strings from memory.
158 webui::UseVersion2 version
;
159 std::string strings_js
;
160 webui::AppendJsonJS(localized_strings_
.get(), &strings_js
);
161 response_bytes
= base::RefCountedString::TakeString(&strings_js
);
162 } else if (path
== kOptionsBundleJsFile
) {
163 // Return (and cache) the options javascript code.
164 response_bytes
= ui::ResourceBundle::GetSharedInstance().
165 LoadDataResourceBytes(IDR_OPTIONS_BUNDLE_JS
);
167 // Return (and cache) the main options html page as the default.
168 response_bytes
= ui::ResourceBundle::GetSharedInstance().
169 LoadDataResourceBytes(IDR_OPTIONS_HTML
);
172 callback
.Run(response_bytes
.get());
175 std::string
OptionsUIHTMLSource::GetMimeType(const std::string
& path
) const {
176 if (path
== kLocalizedStringsFile
|| path
== kOptionsBundleJsFile
)
177 return "application/javascript";
182 bool OptionsUIHTMLSource::ShouldDenyXFrameOptions() const {
186 OptionsUIHTMLSource::~OptionsUIHTMLSource() {}
188 ////////////////////////////////////////////////////////////////////////////////
190 // OptionsPageUIHandler
192 ////////////////////////////////////////////////////////////////////////////////
194 const char OptionsPageUIHandler::kSettingsAppKey
[] = "settingsApp";
196 OptionsPageUIHandler::OptionsPageUIHandler() {
199 OptionsPageUIHandler::~OptionsPageUIHandler() {
202 bool OptionsPageUIHandler::IsEnabled() {
207 void OptionsPageUIHandler::RegisterStrings(
208 base::DictionaryValue
* localized_strings
,
209 const OptionsStringResource
* resources
,
211 for (size_t i
= 0; i
< length
; ++i
) {
212 base::string16 value
;
213 if (resources
[i
].substitution_id
== 0) {
214 value
= l10n_util::GetStringUTF16(resources
[i
].id
);
216 value
= l10n_util::GetStringFUTF16(
218 l10n_util::GetStringUTF16(resources
[i
].substitution_id
));
220 localized_strings
->SetString(resources
[i
].name
, value
);
224 void OptionsPageUIHandler::RegisterTitle(
225 base::DictionaryValue
* localized_strings
,
226 const std::string
& variable_name
,
228 localized_strings
->SetString(variable_name
,
229 l10n_util::GetStringUTF16(title_id
));
230 localized_strings
->SetString(variable_name
+ "TabTitle",
231 l10n_util::GetStringFUTF16(IDS_OPTIONS_TAB_TITLE
,
232 l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE
),
233 l10n_util::GetStringUTF16(title_id
)));
236 ////////////////////////////////////////////////////////////////////////////////
240 ////////////////////////////////////////////////////////////////////////////////
242 OptionsUI::OptionsUI(content::WebUI
* web_ui
)
243 : WebUIController(web_ui
),
244 WebContentsObserver(web_ui
->GetWebContents()),
245 initialized_handlers_(false) {
246 base::DictionaryValue
* localized_strings
= new base::DictionaryValue();
247 localized_strings
->Set(OptionsPageUIHandler::kSettingsAppKey
,
248 new base::DictionaryValue());
250 CoreOptionsHandler
* core_handler
;
251 #if defined(OS_CHROMEOS)
252 core_handler
= new chromeos::options::CoreChromeOSOptionsHandler();
254 core_handler
= new CoreOptionsHandler();
256 core_handler
->set_handlers_host(this);
257 AddOptionsPageUIHandler(localized_strings
, core_handler
);
259 AddOptionsPageUIHandler(localized_strings
, new AutofillOptionsHandler());
260 AddOptionsPageUIHandler(localized_strings
,
261 new AutomaticSettingsResetHandler());
263 BrowserOptionsHandler
* browser_options_handler
= new BrowserOptionsHandler();
264 AddOptionsPageUIHandler(localized_strings
, browser_options_handler
);
266 AddOptionsPageUIHandler(localized_strings
, new ClearBrowserDataHandler());
267 AddOptionsPageUIHandler(localized_strings
, new ContentSettingsHandler());
268 AddOptionsPageUIHandler(localized_strings
, new CookiesViewHandler());
269 AddOptionsPageUIHandler(localized_strings
, new CreateProfileHandler());
270 AddOptionsPageUIHandler(localized_strings
, new FontSettingsHandler());
271 #if defined(ENABLE_GOOGLE_NOW)
272 AddOptionsPageUIHandler(localized_strings
, new GeolocationOptionsHandler());
274 AddOptionsPageUIHandler(localized_strings
, new HomePageOverlayHandler());
275 AddOptionsPageUIHandler(localized_strings
,
276 new MediaDevicesSelectionHandler());
277 #if defined(OS_CHROMEOS)
278 AddOptionsPageUIHandler(localized_strings
,
279 new chromeos::options::CrosLanguageOptionsHandler());
281 AddOptionsPageUIHandler(localized_strings
, new LanguageOptionsHandler());
283 AddOptionsPageUIHandler(localized_strings
,
284 new LanguageDictionaryOverlayHandler());
285 AddOptionsPageUIHandler(localized_strings
, new ManageProfileHandler());
286 AddOptionsPageUIHandler(localized_strings
,
287 new ManagedUserCreateConfirmHandler());
288 AddOptionsPageUIHandler(localized_strings
, new ManagedUserImportHandler());
289 AddOptionsPageUIHandler(localized_strings
, new ManagedUserLearnMoreHandler());
290 AddOptionsPageUIHandler(localized_strings
, new PasswordManagerHandler());
291 AddOptionsPageUIHandler(localized_strings
, new ResetProfileSettingsHandler());
292 AddOptionsPageUIHandler(localized_strings
, new SearchEngineManagerHandler());
293 AddOptionsPageUIHandler(localized_strings
, new ImportDataHandler());
294 AddOptionsPageUIHandler(localized_strings
, new StartupPagesHandler());
295 AddOptionsPageUIHandler(localized_strings
, new SyncSetupHandler(
296 g_browser_process
->profile_manager()));
297 #if defined(OS_CHROMEOS)
298 AddOptionsPageUIHandler(localized_strings
,
299 new chromeos::options::AccountsOptionsHandler());
300 AddOptionsPageUIHandler(localized_strings
,
301 new chromeos::options::BluetoothOptionsHandler());
302 AddOptionsPageUIHandler(localized_strings
,
303 new chromeos::options::DateTimeOptionsHandler());
304 AddOptionsPageUIHandler(localized_strings
,
305 new chromeos::options::DisplayOptionsHandler());
306 AddOptionsPageUIHandler(localized_strings
,
307 new chromeos::options::DisplayOverscanHandler());
308 AddOptionsPageUIHandler(localized_strings
,
309 new chromeos::options::InternetOptionsHandler());
310 AddOptionsPageUIHandler(localized_strings
,
311 new chromeos::options::KeyboardHandler());
313 chromeos::options::PointerHandler
* pointer_handler
=
314 new chromeos::options::PointerHandler();
315 AddOptionsPageUIHandler(localized_strings
, pointer_handler
);
317 AddOptionsPageUIHandler(localized_strings
,
318 new chromeos::options::ProxyHandler());
319 AddOptionsPageUIHandler(
321 new chromeos::options::ChangePictureOptionsHandler());
322 AddOptionsPageUIHandler(localized_strings
,
323 new chromeos::options::StatsOptionsHandler());
326 AddOptionsPageUIHandler(localized_strings
,
327 new CertificateManagerHandler(false));
329 AddOptionsPageUIHandler(localized_strings
, new HandlerOptionsHandler());
331 web_ui
->AddMessageHandler(new MetricsHandler());
333 // |localized_strings| ownership is taken over by this constructor.
334 OptionsUIHTMLSource
* html_source
=
335 new OptionsUIHTMLSource(localized_strings
);
337 // Set up the chrome://settings-frame/ source.
338 Profile
* profile
= Profile::FromWebUI(web_ui
);
339 content::URLDataSource::Add(profile
, html_source
);
341 // Set up the chrome://theme/ source.
342 ThemeSource
* theme
= new ThemeSource(profile
);
343 content::URLDataSource::Add(profile
, theme
);
345 #if defined(OS_CHROMEOS)
346 // Set up the chrome://userimage/ source.
347 chromeos::options::UserImageSource
* user_image_source
=
348 new chromeos::options::UserImageSource();
349 content::URLDataSource::Add(profile
, user_image_source
);
351 pointer_device_observer_
.reset(
352 new chromeos::system::PointerDeviceObserver());
353 pointer_device_observer_
->AddObserver(browser_options_handler
);
354 pointer_device_observer_
->AddObserver(pointer_handler
);
358 OptionsUI::~OptionsUI() {
359 // Uninitialize all registered handlers. Deleted by WebUIImpl.
360 for (size_t i
= 0; i
< handlers_
.size(); ++i
)
361 handlers_
[i
]->Uninitialize();
364 scoped_ptr
<OptionsUI::OnFinishedLoadingCallbackList::Subscription
>
365 OptionsUI::RegisterOnFinishedLoadingCallback(const base::Closure
& callback
) {
366 return on_finished_loading_callbacks_
.Add(callback
);
370 void OptionsUI::ProcessAutocompleteSuggestions(
371 const AutocompleteResult
& result
,
372 base::ListValue
* const suggestions
) {
373 for (size_t i
= 0; i
< result
.size(); ++i
) {
374 const AutocompleteMatch
& match
= result
.match_at(i
);
375 AutocompleteMatchType::Type type
= match
.type
;
376 if (type
!= AutocompleteMatchType::HISTORY_URL
&&
377 type
!= AutocompleteMatchType::HISTORY_TITLE
&&
378 type
!= AutocompleteMatchType::HISTORY_BODY
&&
379 type
!= AutocompleteMatchType::HISTORY_KEYWORD
&&
380 type
!= AutocompleteMatchType::NAVSUGGEST
)
382 base::DictionaryValue
* entry
= new base::DictionaryValue();
383 entry
->SetString("title", match
.description
);
384 entry
->SetString("displayURL", match
.contents
);
385 entry
->SetString("url", match
.destination_url
.spec());
386 suggestions
->Append(entry
);
391 base::RefCountedMemory
* OptionsUI::GetFaviconResourceBytes(
392 ui::ScaleFactor scale_factor
) {
393 return ui::ResourceBundle::GetSharedInstance().
394 LoadDataResourceBytesForScale(IDR_SETTINGS_FAVICON
, scale_factor
);
397 void OptionsUI::DidStartProvisionalLoadForFrame(
399 int64 parent_frame_id
,
401 const GURL
& validated_url
,
403 bool is_iframe_srcdoc
,
404 content::RenderViewHost
* render_view_host
) {
405 if (render_view_host
== web_ui()->GetWebContents()->GetRenderViewHost() &&
406 validated_url
.host() == chrome::kChromeUISettingsFrameHost
) {
407 for (size_t i
= 0; i
< handlers_
.size(); ++i
)
408 handlers_
[i
]->PageLoadStarted();
412 void OptionsUI::InitializeHandlers() {
413 Profile
* profile
= Profile::FromWebUI(web_ui());
414 DCHECK(!profile
->IsOffTheRecord() || profile
->IsGuestSession());
416 // A new web page DOM has been brought up in an existing renderer, causing
417 // this method to be called twice. If that happens, ignore the second call.
418 if (!initialized_handlers_
) {
419 for (size_t i
= 0; i
< handlers_
.size(); ++i
)
420 handlers_
[i
]->InitializeHandler();
421 initialized_handlers_
= true;
423 #if defined(OS_CHROMEOS)
424 pointer_device_observer_
->Init();
428 #if defined(OS_CHROMEOS)
429 pointer_device_observer_
->CheckDevices();
432 // Always initialize the page as when handlers are left over we still need to
433 // do various things like show/hide sections and send data to the Javascript.
434 for (size_t i
= 0; i
< handlers_
.size(); ++i
)
435 handlers_
[i
]->InitializePage();
437 web_ui()->CallJavascriptFunction(
438 "BrowserOptions.notifyInitializationComplete");
441 void OptionsUI::OnFinishedLoading() {
442 on_finished_loading_callbacks_
.Notify();
445 void OptionsUI::AddOptionsPageUIHandler(
446 base::DictionaryValue
* localized_strings
,
447 OptionsPageUIHandler
* handler_raw
) {
448 scoped_ptr
<OptionsPageUIHandler
> handler(handler_raw
);
449 DCHECK(handler
.get());
450 // Add only if handler's service is enabled.
451 if (handler
->IsEnabled()) {
452 // Add handler to the list and also pass the ownership.
453 web_ui()->AddMessageHandler(handler
.release());
454 handler_raw
->GetLocalizedValues(localized_strings
);
455 handlers_
.push_back(handler_raw
);
459 } // namespace options