• 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/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"
69 #include "url/gurl.h"
70 
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"
87 #endif
88 
89 #if defined(USE_NSS)
90 #include "chrome/browser/ui/webui/options/certificate_manager_handler.h"
91 #endif
92 
93 #if defined(ENABLE_GOOGLE_NOW)
94 #include "chrome/browser/ui/webui/options/geolocation_options_handler.h"
95 #endif
96 
97 using content::RenderViewHost;
98 
99 namespace {
100 
101 const char kLocalizedStringsFile[] = "strings.js";
102 const char kOptionsBundleJsFile[]  = "options_bundle.js";
103 
104 }  // namespace
105 
106 namespace options {
107 
108 ////////////////////////////////////////////////////////////////////////////////
109 //
110 // OptionsUIHTMLSource
111 //
112 ////////////////////////////////////////////////////////////////////////////////
113 
114 class OptionsUIHTMLSource : public content::URLDataSource {
115  public:
116   // The constructor takes over ownership of |localized_strings|.
117   explicit OptionsUIHTMLSource(base::DictionaryValue* localized_strings);
118 
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,
124       int render_frame_id,
125       const content::URLDataSource::GotDataCallback& callback) OVERRIDE;
126   virtual std::string GetMimeType(const std::string&) const OVERRIDE;
127   virtual bool ShouldDenyXFrameOptions() const OVERRIDE;
128 
129  private:
130   virtual ~OptionsUIHTMLSource();
131 
132   // Localized strings collection.
133   scoped_ptr<base::DictionaryValue> localized_strings_;
134 
135   DISALLOW_COPY_AND_ASSIGN(OptionsUIHTMLSource);
136 };
137 
OptionsUIHTMLSource(base::DictionaryValue * localized_strings)138 OptionsUIHTMLSource::OptionsUIHTMLSource(
139     base::DictionaryValue* localized_strings) {
140   DCHECK(localized_strings);
141   localized_strings_.reset(localized_strings);
142 }
143 
GetSource() const144 std::string OptionsUIHTMLSource::GetSource() const {
145   return chrome::kChromeUISettingsFrameHost;
146 }
147 
StartDataRequest(const std::string & path,int render_process_id,int render_frame_id,const content::URLDataSource::GotDataCallback & callback)148 void OptionsUIHTMLSource::StartDataRequest(
149     const std::string& path,
150     int render_process_id,
151     int render_frame_id,
152     const content::URLDataSource::GotDataCallback& callback) {
153   scoped_refptr<base::RefCountedMemory> response_bytes;
154   webui::SetFontAndTextDirection(localized_strings_.get());
155 
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);
166   } else {
167     // Return (and cache) the main options html page as the default.
168     response_bytes = ui::ResourceBundle::GetSharedInstance().
169         LoadDataResourceBytes(IDR_OPTIONS_HTML);
170   }
171 
172   callback.Run(response_bytes.get());
173 }
174 
GetMimeType(const std::string & path) const175 std::string OptionsUIHTMLSource::GetMimeType(const std::string& path) const {
176   if (path == kLocalizedStringsFile || path == kOptionsBundleJsFile)
177     return "application/javascript";
178 
179   return "text/html";
180 }
181 
ShouldDenyXFrameOptions() const182 bool OptionsUIHTMLSource::ShouldDenyXFrameOptions() const {
183   return false;
184 }
185 
~OptionsUIHTMLSource()186 OptionsUIHTMLSource::~OptionsUIHTMLSource() {}
187 
188 ////////////////////////////////////////////////////////////////////////////////
189 //
190 // OptionsPageUIHandler
191 //
192 ////////////////////////////////////////////////////////////////////////////////
193 
194 const char OptionsPageUIHandler::kSettingsAppKey[] = "settingsApp";
195 
OptionsPageUIHandler()196 OptionsPageUIHandler::OptionsPageUIHandler() {
197 }
198 
~OptionsPageUIHandler()199 OptionsPageUIHandler::~OptionsPageUIHandler() {
200 }
201 
IsEnabled()202 bool OptionsPageUIHandler::IsEnabled() {
203   return true;
204 }
205 
206 // static
RegisterStrings(base::DictionaryValue * localized_strings,const OptionsStringResource * resources,size_t length)207 void OptionsPageUIHandler::RegisterStrings(
208     base::DictionaryValue* localized_strings,
209     const OptionsStringResource* resources,
210     size_t length) {
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);
215     } else {
216       value = l10n_util::GetStringFUTF16(
217           resources[i].id,
218           l10n_util::GetStringUTF16(resources[i].substitution_id));
219     }
220     localized_strings->SetString(resources[i].name, value);
221   }
222 }
223 
RegisterTitle(base::DictionaryValue * localized_strings,const std::string & variable_name,int title_id)224 void OptionsPageUIHandler::RegisterTitle(
225     base::DictionaryValue* localized_strings,
226     const std::string& variable_name,
227     int title_id) {
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)));
234 }
235 
236 ////////////////////////////////////////////////////////////////////////////////
237 //
238 // OptionsUI
239 //
240 ////////////////////////////////////////////////////////////////////////////////
241 
OptionsUI(content::WebUI * web_ui)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());
249 
250   CoreOptionsHandler* core_handler;
251 #if defined(OS_CHROMEOS)
252   core_handler = new chromeos::options::CoreChromeOSOptionsHandler();
253 #else
254   core_handler = new CoreOptionsHandler();
255 #endif
256   core_handler->set_handlers_host(this);
257   AddOptionsPageUIHandler(localized_strings, core_handler);
258 
259   AddOptionsPageUIHandler(localized_strings, new AutofillOptionsHandler());
260   AddOptionsPageUIHandler(localized_strings,
261                           new AutomaticSettingsResetHandler());
262 
263   BrowserOptionsHandler* browser_options_handler = new BrowserOptionsHandler();
264   AddOptionsPageUIHandler(localized_strings, browser_options_handler);
265 
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());
273 #endif
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());
280 #else
281   AddOptionsPageUIHandler(localized_strings, new LanguageOptionsHandler());
282 #endif
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());
312 
313   chromeos::options::PointerHandler* pointer_handler =
314       new chromeos::options::PointerHandler();
315   AddOptionsPageUIHandler(localized_strings, pointer_handler);
316 
317   AddOptionsPageUIHandler(localized_strings,
318                           new chromeos::options::ProxyHandler());
319   AddOptionsPageUIHandler(
320       localized_strings,
321       new chromeos::options::ChangePictureOptionsHandler());
322   AddOptionsPageUIHandler(localized_strings,
323                           new chromeos::options::StatsOptionsHandler());
324 #endif
325 #if defined(USE_NSS)
326   AddOptionsPageUIHandler(localized_strings,
327                           new CertificateManagerHandler(false));
328 #endif
329   AddOptionsPageUIHandler(localized_strings, new HandlerOptionsHandler());
330 
331   web_ui->AddMessageHandler(new MetricsHandler());
332 
333   // |localized_strings| ownership is taken over by this constructor.
334   OptionsUIHTMLSource* html_source =
335       new OptionsUIHTMLSource(localized_strings);
336 
337   // Set up the chrome://settings-frame/ source.
338   Profile* profile = Profile::FromWebUI(web_ui);
339   content::URLDataSource::Add(profile, html_source);
340 
341   // Set up the chrome://theme/ source.
342   ThemeSource* theme = new ThemeSource(profile);
343   content::URLDataSource::Add(profile, theme);
344 
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);
350 
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);
355 #endif
356 }
357 
~OptionsUI()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();
362 }
363 
364 scoped_ptr<OptionsUI::OnFinishedLoadingCallbackList::Subscription>
RegisterOnFinishedLoadingCallback(const base::Closure & callback)365 OptionsUI::RegisterOnFinishedLoadingCallback(const base::Closure& callback) {
366   return on_finished_loading_callbacks_.Add(callback);
367 }
368 
369 // static
ProcessAutocompleteSuggestions(const AutocompleteResult & result,base::ListValue * const suggestions)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 &&
381         type != AutocompleteMatchType::NAVSUGGEST_PERSONALIZED) {
382       continue;
383     }
384     base::DictionaryValue* entry = new base::DictionaryValue();
385     entry->SetString("title", match.description);
386     entry->SetString("displayURL", match.contents);
387     entry->SetString("url", match.destination_url.spec());
388     suggestions->Append(entry);
389   }
390 }
391 
392 // static
GetFaviconResourceBytes(ui::ScaleFactor scale_factor)393 base::RefCountedMemory* OptionsUI::GetFaviconResourceBytes(
394       ui::ScaleFactor scale_factor) {
395   return ui::ResourceBundle::GetSharedInstance().
396       LoadDataResourceBytesForScale(IDR_SETTINGS_FAVICON, scale_factor);
397 }
398 
DidStartProvisionalLoadForFrame(int64 frame_id,int64 parent_frame_id,bool is_main_frame,const GURL & validated_url,bool is_error_page,bool is_iframe_srcdoc,content::RenderViewHost * render_view_host)399 void OptionsUI::DidStartProvisionalLoadForFrame(
400     int64 frame_id,
401     int64 parent_frame_id,
402     bool is_main_frame,
403     const GURL& validated_url,
404     bool is_error_page,
405     bool is_iframe_srcdoc,
406     content::RenderViewHost* render_view_host) {
407   if (render_view_host == web_ui()->GetWebContents()->GetRenderViewHost() &&
408       validated_url.host() == chrome::kChromeUISettingsFrameHost) {
409     for (size_t i = 0; i < handlers_.size(); ++i)
410       handlers_[i]->PageLoadStarted();
411   }
412 }
413 
InitializeHandlers()414 void OptionsUI::InitializeHandlers() {
415   Profile* profile = Profile::FromWebUI(web_ui());
416   DCHECK(!profile->IsOffTheRecord() || profile->IsGuestSession());
417 
418   // A new web page DOM has been brought up in an existing renderer, causing
419   // this method to be called twice. If that happens, ignore the second call.
420   if (!initialized_handlers_) {
421     for (size_t i = 0; i < handlers_.size(); ++i)
422       handlers_[i]->InitializeHandler();
423     initialized_handlers_ = true;
424 
425 #if defined(OS_CHROMEOS)
426     pointer_device_observer_->Init();
427 #endif
428   }
429 
430 #if defined(OS_CHROMEOS)
431   pointer_device_observer_->CheckDevices();
432 #endif
433 
434   // Always initialize the page as when handlers are left over we still need to
435   // do various things like show/hide sections and send data to the Javascript.
436   for (size_t i = 0; i < handlers_.size(); ++i)
437     handlers_[i]->InitializePage();
438 
439   web_ui()->CallJavascriptFunction(
440       "BrowserOptions.notifyInitializationComplete");
441 }
442 
OnFinishedLoading()443 void OptionsUI::OnFinishedLoading() {
444   on_finished_loading_callbacks_.Notify();
445 }
446 
AddOptionsPageUIHandler(base::DictionaryValue * localized_strings,OptionsPageUIHandler * handler_raw)447 void OptionsUI::AddOptionsPageUIHandler(
448     base::DictionaryValue* localized_strings,
449     OptionsPageUIHandler* handler_raw) {
450   scoped_ptr<OptionsPageUIHandler> handler(handler_raw);
451   DCHECK(handler.get());
452   // Add only if handler's service is enabled.
453   if (handler->IsEnabled()) {
454     // Add handler to the list and also pass the ownership.
455     web_ui()->AddMessageHandler(handler.release());
456     handler_raw->GetLocalizedValues(localized_strings);
457     handlers_.push_back(handler_raw);
458   }
459 }
460 
461 }  // namespace options
462