• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/browser_about_handler.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/ui/webui/metrics_handler.h"
25 #include "chrome/browser/ui/webui/options/autofill_options_handler.h"
26 #include "chrome/browser/ui/webui/options/automatic_settings_reset_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/easy_unlock_handler.h"
34 #include "chrome/browser/ui/webui/options/font_settings_handler.h"
35 #include "chrome/browser/ui/webui/options/handler_options_handler.h"
36 #include "chrome/browser/ui/webui/options/help_overlay_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/media_devices_selection_handler.h"
43 #include "chrome/browser/ui/webui/options/password_manager_handler.h"
44 #include "chrome/browser/ui/webui/options/reset_profile_settings_handler.h"
45 #include "chrome/browser/ui/webui/options/search_engine_manager_handler.h"
46 #include "chrome/browser/ui/webui/options/startup_pages_handler.h"
47 #include "chrome/browser/ui/webui/options/supervised_user_create_confirm_handler.h"
48 #include "chrome/browser/ui/webui/options/supervised_user_import_handler.h"
49 #include "chrome/browser/ui/webui/options/supervised_user_learn_more_handler.h"
50 #include "chrome/browser/ui/webui/options/website_settings_handler.h"
51 #include "chrome/browser/ui/webui/sync_setup_handler.h"
52 #include "chrome/browser/ui/webui/theme_source.h"
53 #include "chrome/common/url_constants.h"
54 #include "chrome/grit/generated_resources.h"
55 #include "chrome/grit/locale_settings.h"
56 #include "components/omnibox/autocomplete_match.h"
57 #include "components/omnibox/autocomplete_result.h"
58 #include "content/public/browser/notification_types.h"
59 #include "content/public/browser/render_frame_host.h"
60 #include "content/public/browser/url_data_source.h"
61 #include "content/public/browser/web_contents.h"
62 #include "content/public/browser/web_contents_delegate.h"
63 #include "content/public/browser/web_ui.h"
64 #include "grit/options_resources.h"
65 #include "grit/theme_resources.h"
66 #include "net/base/escape.h"
67 #include "ui/base/l10n/l10n_util.h"
68 #include "ui/base/resource/resource_bundle.h"
69 #include "ui/base/webui/jstemplate_builder.h"
70 #include "ui/base/webui/web_ui_util.h"
71 #include "url/gurl.h"
72 
73 #if defined(OS_CHROMEOS)
74 #include "chrome/browser/browser_process_platform_part.h"
75 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
76 #include "chrome/browser/chromeos/policy/consumer_management_service.h"
77 #include "chrome/browser/chromeos/system/pointer_device_observer.h"
78 #include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h"
79 #include "chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h"
80 #include "chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.h"
81 #include "chrome/browser/ui/webui/options/chromeos/consumer_management_handler.h"
82 #include "chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h"
83 #include "chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.h"
84 #include "chrome/browser/ui/webui/options/chromeos/date_time_options_handler.h"
85 #include "chrome/browser/ui/webui/options/chromeos/display_options_handler.h"
86 #include "chrome/browser/ui/webui/options/chromeos/display_overscan_handler.h"
87 #include "chrome/browser/ui/webui/options/chromeos/internet_options_handler.h"
88 #include "chrome/browser/ui/webui/options/chromeos/keyboard_handler.h"
89 #include "chrome/browser/ui/webui/options/chromeos/pointer_handler.h"
90 #include "chrome/browser/ui/webui/options/chromeos/proxy_handler.h"
91 #include "chrome/browser/ui/webui/options/chromeos/stats_options_handler.h"
92 #include "chrome/browser/ui/webui/options/chromeos/user_image_source.h"
93 #endif
94 
95 #if defined(USE_NSS)
96 #include "chrome/browser/ui/webui/options/certificate_manager_handler.h"
97 #endif
98 
99 #if defined(ENABLE_GOOGLE_NOW)
100 #include "chrome/browser/ui/webui/options/geolocation_options_handler.h"
101 #endif
102 
103 using content::RenderViewHost;
104 
105 namespace {
106 
107 const char kLocalizedStringsFile[] = "strings.js";
108 const char kOptionsBundleJsFile[]  = "options_bundle.js";
109 
110 }  // namespace
111 
112 namespace options {
113 
114 ////////////////////////////////////////////////////////////////////////////////
115 //
116 // OptionsUIHTMLSource
117 //
118 ////////////////////////////////////////////////////////////////////////////////
119 
120 class OptionsUIHTMLSource : public content::URLDataSource {
121  public:
122   // The constructor takes over ownership of |localized_strings|.
123   explicit OptionsUIHTMLSource(base::DictionaryValue* localized_strings);
124 
125   // content::URLDataSource implementation.
126   virtual std::string GetSource() const OVERRIDE;
127   virtual void StartDataRequest(
128       const std::string& path,
129       int render_process_id,
130       int render_frame_id,
131       const content::URLDataSource::GotDataCallback& callback) OVERRIDE;
132   virtual std::string GetMimeType(const std::string&) const OVERRIDE;
133   virtual bool ShouldDenyXFrameOptions() const OVERRIDE;
134 
135  private:
136   virtual ~OptionsUIHTMLSource();
137 
138   // Localized strings collection.
139   scoped_ptr<base::DictionaryValue> localized_strings_;
140 
141   DISALLOW_COPY_AND_ASSIGN(OptionsUIHTMLSource);
142 };
143 
OptionsUIHTMLSource(base::DictionaryValue * localized_strings)144 OptionsUIHTMLSource::OptionsUIHTMLSource(
145     base::DictionaryValue* localized_strings) {
146   DCHECK(localized_strings);
147   localized_strings_.reset(localized_strings);
148 }
149 
GetSource() const150 std::string OptionsUIHTMLSource::GetSource() const {
151   return chrome::kChromeUISettingsFrameHost;
152 }
153 
StartDataRequest(const std::string & path,int render_process_id,int render_frame_id,const content::URLDataSource::GotDataCallback & callback)154 void OptionsUIHTMLSource::StartDataRequest(
155     const std::string& path,
156     int render_process_id,
157     int render_frame_id,
158     const content::URLDataSource::GotDataCallback& callback) {
159   scoped_refptr<base::RefCountedMemory> response_bytes;
160   webui::SetFontAndTextDirection(localized_strings_.get());
161 
162   if (path == kLocalizedStringsFile) {
163     // Return dynamically-generated strings from memory.
164     webui::UseVersion2 version;
165     std::string strings_js;
166     webui::AppendJsonJS(localized_strings_.get(), &strings_js);
167     response_bytes = base::RefCountedString::TakeString(&strings_js);
168   } else if (path == kOptionsBundleJsFile) {
169     // Return (and cache) the options javascript code.
170     response_bytes = ui::ResourceBundle::GetSharedInstance().
171         LoadDataResourceBytes(IDR_OPTIONS_BUNDLE_JS);
172   } else {
173     // Return (and cache) the main options html page as the default.
174     response_bytes = ui::ResourceBundle::GetSharedInstance().
175         LoadDataResourceBytes(IDR_OPTIONS_HTML);
176   }
177 
178   callback.Run(response_bytes.get());
179 }
180 
GetMimeType(const std::string & path) const181 std::string OptionsUIHTMLSource::GetMimeType(const std::string& path) const {
182   if (path == kLocalizedStringsFile || path == kOptionsBundleJsFile)
183     return "application/javascript";
184 
185   return "text/html";
186 }
187 
ShouldDenyXFrameOptions() const188 bool OptionsUIHTMLSource::ShouldDenyXFrameOptions() const {
189   return false;
190 }
191 
~OptionsUIHTMLSource()192 OptionsUIHTMLSource::~OptionsUIHTMLSource() {}
193 
194 ////////////////////////////////////////////////////////////////////////////////
195 //
196 // OptionsPageUIHandler
197 //
198 ////////////////////////////////////////////////////////////////////////////////
199 
200 const char OptionsPageUIHandler::kSettingsAppKey[] = "settingsApp";
201 
OptionsPageUIHandler()202 OptionsPageUIHandler::OptionsPageUIHandler() {
203 }
204 
~OptionsPageUIHandler()205 OptionsPageUIHandler::~OptionsPageUIHandler() {
206 }
207 
IsEnabled()208 bool OptionsPageUIHandler::IsEnabled() {
209   return true;
210 }
211 
212 // static
RegisterStrings(base::DictionaryValue * localized_strings,const OptionsStringResource * resources,size_t length)213 void OptionsPageUIHandler::RegisterStrings(
214     base::DictionaryValue* localized_strings,
215     const OptionsStringResource* resources,
216     size_t length) {
217   for (size_t i = 0; i < length; ++i) {
218     base::string16 value;
219     if (resources[i].substitution_id == 0) {
220       value = l10n_util::GetStringUTF16(resources[i].id);
221     } else {
222       value = l10n_util::GetStringFUTF16(
223           resources[i].id,
224           l10n_util::GetStringUTF16(resources[i].substitution_id));
225     }
226     localized_strings->SetString(resources[i].name, value);
227   }
228 }
229 
RegisterTitle(base::DictionaryValue * localized_strings,const std::string & variable_name,int title_id)230 void OptionsPageUIHandler::RegisterTitle(
231     base::DictionaryValue* localized_strings,
232     const std::string& variable_name,
233     int title_id) {
234   localized_strings->SetString(variable_name,
235       l10n_util::GetStringUTF16(title_id));
236   localized_strings->SetString(variable_name + "TabTitle",
237       l10n_util::GetStringFUTF16(IDS_OPTIONS_TAB_TITLE,
238           l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE),
239           l10n_util::GetStringUTF16(title_id)));
240 }
241 
242 ////////////////////////////////////////////////////////////////////////////////
243 //
244 // OptionsUI
245 //
246 ////////////////////////////////////////////////////////////////////////////////
247 
OptionsUI(content::WebUI * web_ui)248 OptionsUI::OptionsUI(content::WebUI* web_ui)
249     : WebUIController(web_ui),
250       WebContentsObserver(web_ui->GetWebContents()),
251       initialized_handlers_(false) {
252   base::DictionaryValue* localized_strings = new base::DictionaryValue();
253   localized_strings->Set(OptionsPageUIHandler::kSettingsAppKey,
254                          new base::DictionaryValue());
255 
256   CoreOptionsHandler* core_handler;
257 #if defined(OS_CHROMEOS)
258   core_handler = new chromeos::options::CoreChromeOSOptionsHandler();
259 #else
260   core_handler = new CoreOptionsHandler();
261 #endif
262   core_handler->set_handlers_host(this);
263   AddOptionsPageUIHandler(localized_strings, core_handler);
264 
265   AddOptionsPageUIHandler(localized_strings, new AutofillOptionsHandler());
266   AddOptionsPageUIHandler(localized_strings,
267                           new AutomaticSettingsResetHandler());
268 
269   BrowserOptionsHandler* browser_options_handler = new BrowserOptionsHandler();
270   AddOptionsPageUIHandler(localized_strings, browser_options_handler);
271 
272   AddOptionsPageUIHandler(localized_strings, new ClearBrowserDataHandler());
273   AddOptionsPageUIHandler(localized_strings, new ContentSettingsHandler());
274   AddOptionsPageUIHandler(localized_strings, new CookiesViewHandler());
275   AddOptionsPageUIHandler(localized_strings, new CreateProfileHandler());
276   AddOptionsPageUIHandler(localized_strings, new EasyUnlockHandler());
277   AddOptionsPageUIHandler(localized_strings, new FontSettingsHandler());
278 #if defined(ENABLE_GOOGLE_NOW)
279   AddOptionsPageUIHandler(localized_strings, new GeolocationOptionsHandler());
280 #endif
281   AddOptionsPageUIHandler(localized_strings, new options::HelpOverlayHandler());
282   AddOptionsPageUIHandler(localized_strings, new HomePageOverlayHandler());
283   AddOptionsPageUIHandler(localized_strings,
284                           new MediaDevicesSelectionHandler());
285 #if defined(OS_CHROMEOS)
286   AddOptionsPageUIHandler(localized_strings,
287                           new chromeos::options::CrosLanguageOptionsHandler());
288 #else
289   AddOptionsPageUIHandler(localized_strings, new LanguageOptionsHandler());
290 #endif
291   AddOptionsPageUIHandler(localized_strings,
292                           new LanguageDictionaryOverlayHandler());
293   AddOptionsPageUIHandler(localized_strings, new ManageProfileHandler());
294   AddOptionsPageUIHandler(localized_strings, new PasswordManagerHandler());
295   AddOptionsPageUIHandler(localized_strings, new ResetProfileSettingsHandler());
296   AddOptionsPageUIHandler(localized_strings, new SearchEngineManagerHandler());
297   AddOptionsPageUIHandler(localized_strings, new ImportDataHandler());
298   AddOptionsPageUIHandler(localized_strings, new StartupPagesHandler());
299   AddOptionsPageUIHandler(localized_strings,
300                           new SupervisedUserCreateConfirmHandler());
301   AddOptionsPageUIHandler(localized_strings, new SupervisedUserImportHandler());
302   AddOptionsPageUIHandler(localized_strings,
303                           new SupervisedUserLearnMoreHandler());
304   AddOptionsPageUIHandler(localized_strings, new SyncSetupHandler(
305       g_browser_process->profile_manager()));
306   AddOptionsPageUIHandler(localized_strings, new WebsiteSettingsHandler());
307 #if defined(OS_CHROMEOS)
308   AddOptionsPageUIHandler(localized_strings,
309                           new chromeos::options::AccountsOptionsHandler());
310   AddOptionsPageUIHandler(localized_strings,
311                           new chromeos::options::BluetoothOptionsHandler());
312   AddOptionsPageUIHandler(localized_strings,
313                           new chromeos::options::DateTimeOptionsHandler());
314   AddOptionsPageUIHandler(localized_strings,
315                           new chromeos::options::DisplayOptionsHandler());
316   AddOptionsPageUIHandler(localized_strings,
317                           new chromeos::options::DisplayOverscanHandler());
318   AddOptionsPageUIHandler(localized_strings,
319                           new chromeos::options::InternetOptionsHandler());
320   AddOptionsPageUIHandler(localized_strings,
321                           new chromeos::options::KeyboardHandler());
322 
323   chromeos::options::PointerHandler* pointer_handler =
324       new chromeos::options::PointerHandler();
325   AddOptionsPageUIHandler(localized_strings, pointer_handler);
326 
327   AddOptionsPageUIHandler(localized_strings,
328                           new chromeos::options::ProxyHandler());
329   AddOptionsPageUIHandler(
330       localized_strings,
331       new chromeos::options::ChangePictureOptionsHandler());
332   AddOptionsPageUIHandler(localized_strings,
333                           new chromeos::options::StatsOptionsHandler());
334 
335   policy::ConsumerManagementService* consumer_management =
336       g_browser_process->platform_part()->browser_policy_connector_chromeos()->
337           GetConsumerManagementService();
338   chromeos::options::ConsumerManagementHandler* consumer_management_handler =
339       new chromeos::options::ConsumerManagementHandler(consumer_management);
340   AddOptionsPageUIHandler(localized_strings, consumer_management_handler);
341 #endif
342 #if defined(USE_NSS)
343   AddOptionsPageUIHandler(localized_strings,
344                           new CertificateManagerHandler(false));
345 #endif
346   AddOptionsPageUIHandler(localized_strings, new HandlerOptionsHandler());
347 
348   web_ui->AddMessageHandler(new MetricsHandler());
349 
350   // |localized_strings| ownership is taken over by this constructor.
351   OptionsUIHTMLSource* html_source =
352       new OptionsUIHTMLSource(localized_strings);
353 
354   // Set up the chrome://settings-frame/ source.
355   Profile* profile = Profile::FromWebUI(web_ui);
356   content::URLDataSource::Add(profile, html_source);
357 
358   // Set up the chrome://theme/ source.
359   ThemeSource* theme = new ThemeSource(profile);
360   content::URLDataSource::Add(profile, theme);
361 
362 #if defined(OS_CHROMEOS)
363   // Set up the chrome://userimage/ source.
364   chromeos::options::UserImageSource* user_image_source =
365       new chromeos::options::UserImageSource();
366   content::URLDataSource::Add(profile, user_image_source);
367 
368   pointer_device_observer_.reset(
369       new chromeos::system::PointerDeviceObserver());
370   pointer_device_observer_->AddObserver(browser_options_handler);
371   pointer_device_observer_->AddObserver(pointer_handler);
372 #endif
373 }
374 
~OptionsUI()375 OptionsUI::~OptionsUI() {
376   // Uninitialize all registered handlers. Deleted by WebUIImpl.
377   for (size_t i = 0; i < handlers_.size(); ++i)
378     handlers_[i]->Uninitialize();
379 }
380 
381 scoped_ptr<OptionsUI::OnFinishedLoadingCallbackList::Subscription>
RegisterOnFinishedLoadingCallback(const base::Closure & callback)382 OptionsUI::RegisterOnFinishedLoadingCallback(const base::Closure& callback) {
383   return on_finished_loading_callbacks_.Add(callback);
384 }
385 
386 // static
ProcessAutocompleteSuggestions(const AutocompleteResult & result,base::ListValue * const suggestions)387 void OptionsUI::ProcessAutocompleteSuggestions(
388     const AutocompleteResult& result,
389     base::ListValue* const suggestions) {
390   for (size_t i = 0; i < result.size(); ++i) {
391     const AutocompleteMatch& match = result.match_at(i);
392     AutocompleteMatchType::Type type = match.type;
393     if (type != AutocompleteMatchType::HISTORY_URL &&
394         type != AutocompleteMatchType::HISTORY_TITLE &&
395         type != AutocompleteMatchType::HISTORY_BODY &&
396         type != AutocompleteMatchType::HISTORY_KEYWORD &&
397         type != AutocompleteMatchType::NAVSUGGEST &&
398         type != AutocompleteMatchType::NAVSUGGEST_PERSONALIZED) {
399       continue;
400     }
401     base::DictionaryValue* entry = new base::DictionaryValue();
402     entry->SetString("title", match.description);
403     entry->SetString("displayURL", match.contents);
404     entry->SetString("url", match.destination_url.spec());
405     suggestions->Append(entry);
406   }
407 }
408 
409 // static
GetFaviconResourceBytes(ui::ScaleFactor scale_factor)410 base::RefCountedMemory* OptionsUI::GetFaviconResourceBytes(
411       ui::ScaleFactor scale_factor) {
412   return ui::ResourceBundle::GetSharedInstance().
413       LoadDataResourceBytesForScale(IDR_SETTINGS_FAVICON, scale_factor);
414 }
415 
DidStartProvisionalLoadForFrame(content::RenderFrameHost * render_frame_host,const GURL & validated_url,bool is_error_page,bool is_iframe_srcdoc)416 void OptionsUI::DidStartProvisionalLoadForFrame(
417     content::RenderFrameHost* render_frame_host,
418     const GURL& validated_url,
419     bool is_error_page,
420     bool is_iframe_srcdoc) {
421   if (render_frame_host->GetRenderViewHost() ==
422           web_ui()->GetWebContents()->GetRenderViewHost() &&
423       validated_url.host() == chrome::kChromeUISettingsFrameHost) {
424     for (size_t i = 0; i < handlers_.size(); ++i)
425       handlers_[i]->PageLoadStarted();
426   }
427 }
428 
InitializeHandlers()429 void OptionsUI::InitializeHandlers() {
430   Profile* profile = Profile::FromWebUI(web_ui());
431   DCHECK(!profile->IsOffTheRecord() || profile->IsGuestSession());
432 
433   // A new web page DOM has been brought up in an existing renderer, causing
434   // this method to be called twice. If that happens, ignore the second call.
435   if (!initialized_handlers_) {
436     for (size_t i = 0; i < handlers_.size(); ++i)
437       handlers_[i]->InitializeHandler();
438     initialized_handlers_ = true;
439 
440 #if defined(OS_CHROMEOS)
441     pointer_device_observer_->Init();
442 #endif
443   }
444 
445 #if defined(OS_CHROMEOS)
446   pointer_device_observer_->CheckDevices();
447 #endif
448 
449   // Always initialize the page as when handlers are left over we still need to
450   // do various things like show/hide sections and send data to the Javascript.
451   for (size_t i = 0; i < handlers_.size(); ++i)
452     handlers_[i]->InitializePage();
453 
454   web_ui()->CallJavascriptFunction(
455       "BrowserOptions.notifyInitializationComplete");
456 }
457 
OnFinishedLoading()458 void OptionsUI::OnFinishedLoading() {
459   on_finished_loading_callbacks_.Notify();
460 }
461 
AddOptionsPageUIHandler(base::DictionaryValue * localized_strings,OptionsPageUIHandler * handler_raw)462 void OptionsUI::AddOptionsPageUIHandler(
463     base::DictionaryValue* localized_strings,
464     OptionsPageUIHandler* handler_raw) {
465   scoped_ptr<OptionsPageUIHandler> handler(handler_raw);
466   DCHECK(handler.get());
467   // Add only if handler's service is enabled.
468   if (handler->IsEnabled()) {
469     // Add handler to the list and also pass the ownership.
470     web_ui()->AddMessageHandler(handler.release());
471     handler_raw->GetLocalizedValues(localized_strings);
472     handlers_.push_back(handler_raw);
473   }
474 }
475 
476 }  // namespace options
477