OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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/gtk/options/advanced_contents_gtk.h" | |
6 | |
7 #include <sys/types.h> | |
8 #include <sys/wait.h> | |
9 | |
10 #include <string> | |
11 #include <vector> | |
12 | |
13 #include "app/gtk_signal.h" | |
14 #include "app/l10n_util.h" | |
15 #include "base/basictypes.h" | |
16 #include "base/command_line.h" | |
17 #include "base/environment.h" | |
18 #include "base/file_util.h" | |
19 #include "base/path_service.h" | |
20 #include "base/process_util.h" | |
21 #include "base/string_tokenizer.h" | |
22 #include "base/nix/xdg_util.h" | |
23 #include "chrome/browser/browser_list.h" | |
24 #include "chrome/browser/browser_process.h" | |
25 #include "chrome/browser/download/download_manager.h" | |
26 #include "chrome/browser/download/download_prefs.h" | |
27 #include "chrome/browser/fonts_languages_window.h" | |
28 #include "chrome/browser/google/google_util.h" | |
29 #include "chrome/browser/gtk/accessible_widget_helper_gtk.h" | |
30 #include "chrome/browser/gtk/clear_browsing_data_dialog_gtk.h" | |
31 #include "chrome/browser/gtk/gtk_chrome_link_button.h" | |
32 #include "chrome/browser/gtk/gtk_util.h" | |
33 #include "chrome/browser/gtk/options/content_settings_window_gtk.h" | |
34 #include "chrome/browser/gtk/options/options_layout_gtk.h" | |
35 #include "chrome/browser/prefs/pref_member.h" | |
36 #include "chrome/browser/prefs/pref_set_observer.h" | |
37 #include "chrome/browser/profiles/profile.h" | |
38 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" | |
39 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | |
40 #include "chrome/browser/ui/options/options_page_base.h" | |
41 #include "chrome/browser/ui/options/options_util.h" | |
42 #include "chrome/browser/ui/options/show_options_url.h" | |
43 #include "chrome/common/chrome_paths.h" | |
44 #include "chrome/common/pref_names.h" | |
45 #include "chrome/common/process_watcher.h" | |
46 #include "chrome/common/url_constants.h" | |
47 #include "grit/chromium_strings.h" | |
48 #include "grit/generated_resources.h" | |
49 #include "grit/locale_settings.h" | |
50 | |
51 namespace { | |
52 | |
53 // Command used to configure GNOME proxy settings. The command was renamed | |
54 // in January 2009, so both are used to work on both old and new systems. | |
55 const char* kOldGNOMEProxyConfigCommand[] = {"gnome-network-preferences", NULL}; | |
56 const char* kGNOMEProxyConfigCommand[] = {"gnome-network-properties", NULL}; | |
57 // KDE3 and KDE4 are only slightly different, but incompatible. Go figure. | |
58 const char* kKDE3ProxyConfigCommand[] = {"kcmshell", "proxy", NULL}; | |
59 const char* kKDE4ProxyConfigCommand[] = {"kcmshell4", "proxy", NULL}; | |
60 | |
61 // The URL for Linux ssl certificate configuration help. | |
62 const char* const kLinuxCertificatesConfigUrl = | |
63 "http://code.google.com/p/chromium/wiki/LinuxCertManagement"; | |
64 | |
65 // The URL for Linux proxy configuration help when not running under a | |
66 // supported desktop environment. | |
67 const char kLinuxProxyConfigUrl[] = "about:linux-proxy-config"; | |
68 | |
69 // The pixel width we wrap labels at. | |
70 // TODO(evanm): make the labels wrap at the appropriate width. | |
71 #if defined(OS_CHROMEOS) | |
72 // ChromeOS uses IDS_OPTIONS_DIALOG_WIDTH_CHARS for options dialog width, which | |
73 // is slightly smaller than the Gtk options dialog's 500px. | |
74 const int kWrapWidth = 445; | |
75 #else | |
76 const int kWrapWidth = 475; | |
77 #endif | |
78 | |
79 GtkWidget* CreateWrappedLabel(int string_id) { | |
80 GtkWidget* label = gtk_label_new( | |
81 l10n_util::GetStringUTF8(string_id).c_str()); | |
82 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | |
83 gtk_util::SetLabelWidth(label, kWrapWidth); | |
84 return label; | |
85 } | |
86 | |
87 GtkWidget* CreateCheckButtonWithWrappedLabel(int string_id) { | |
88 GtkWidget* checkbox = gtk_check_button_new(); | |
89 gtk_container_add(GTK_CONTAINER(checkbox), | |
90 CreateWrappedLabel(string_id)); | |
91 return checkbox; | |
92 } | |
93 | |
94 GtkWidget* AddCheckButtonWithWrappedLabel(int string_id, | |
95 GtkWidget* container, | |
96 GCallback handler, | |
97 gpointer data) { | |
98 GtkWidget* checkbox = CreateCheckButtonWithWrappedLabel(string_id); | |
99 gtk_box_pack_start(GTK_BOX(container), checkbox, FALSE, FALSE, 0); | |
100 g_signal_connect(checkbox, "toggled", handler, data); | |
101 | |
102 return checkbox; | |
103 } | |
104 | |
105 // Don't let the widget handle scroll events. Instead, pass it on to the | |
106 // parent widget. | |
107 gboolean PassScrollToParent(GtkWidget* widget, GdkEvent* event, | |
108 gpointer unused) { | |
109 if (widget->parent) | |
110 gtk_propagate_event(widget->parent, event); | |
111 | |
112 return TRUE; | |
113 } | |
114 | |
115 // Recursively search for a combo box among the children of |widget|. | |
116 void SearchForComboBox(GtkWidget* widget, gpointer data) { | |
117 if (GTK_IS_COMBO_BOX(widget)) { | |
118 *reinterpret_cast<GtkWidget**>(data) = widget; | |
119 } else if (GTK_IS_CONTAINER(widget)) { | |
120 gtk_container_foreach(GTK_CONTAINER(widget), SearchForComboBox, data); | |
121 } | |
122 } | |
123 | |
124 // Letting the combo boxes in the advanced options page handle scroll events is | |
125 // annoying because they fight with the scrolled window. Also, | |
126 // GtkFileChooserButton is buggy in that if you scroll on it very quickly it | |
127 // spews Gtk-WARNINGs, which causes us to crash in debug. This function disables | |
128 // scrolling for the combo box in |widget| (the first one it finds in a DFS). | |
129 void DisableScrolling(GtkWidget* widget) { | |
130 gpointer combo_box_ptr = NULL; | |
131 SearchForComboBox(widget, &combo_box_ptr); | |
132 | |
133 if (!combo_box_ptr) { | |
134 NOTREACHED() << " Did not find a combo box in this widget."; | |
135 return; | |
136 } | |
137 | |
138 g_signal_connect(GTK_WIDGET(combo_box_ptr), "scroll-event", | |
139 G_CALLBACK(PassScrollToParent), NULL); | |
140 } | |
141 | |
142 } // anonymous namespace | |
143 | |
144 | |
145 /////////////////////////////////////////////////////////////////////////////// | |
146 // DownloadSection | |
147 | |
148 class DownloadSection : public OptionsPageBase { | |
149 public: | |
150 explicit DownloadSection(Profile* profile); | |
151 virtual ~DownloadSection() {} | |
152 | |
153 GtkWidget* get_page_widget() const { | |
154 return page_; | |
155 } | |
156 | |
157 private: | |
158 // Overridden from OptionsPageBase. | |
159 virtual void NotifyPrefChanged(const std::string* pref_name); | |
160 | |
161 // Callbacks for the widgets. | |
162 static void OnDownloadLocationChanged(GtkFileChooser* widget, | |
163 DownloadSection* section); | |
164 static void OnDownloadAskForSaveLocationChanged(GtkWidget* widget, | |
165 DownloadSection* section); | |
166 static void OnResetFileHandlersClicked(GtkButton *button, | |
167 DownloadSection* section); | |
168 | |
169 // The widgets for the download options. | |
170 GtkWidget* download_location_button_; | |
171 GtkWidget* download_ask_for_save_location_checkbox_; | |
172 GtkWidget* reset_file_handlers_label_; | |
173 GtkWidget* reset_file_handlers_button_; | |
174 | |
175 // The widget containing the options for this section. | |
176 GtkWidget* page_; | |
177 | |
178 // Pref members. | |
179 FilePathPrefMember default_download_location_; | |
180 BooleanPrefMember ask_for_save_location_; | |
181 StringPrefMember auto_open_files_; | |
182 | |
183 // Flag to ignore gtk callbacks while we are loading prefs, to avoid | |
184 // then turning around and saving them again. | |
185 bool pref_changing_; | |
186 | |
187 scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_; | |
188 | |
189 DISALLOW_COPY_AND_ASSIGN(DownloadSection); | |
190 }; | |
191 | |
192 DownloadSection::DownloadSection(Profile* profile) | |
193 : OptionsPageBase(profile), | |
194 pref_changing_(true) { | |
195 page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
196 | |
197 accessible_widget_helper_.reset(new AccessibleWidgetHelper( | |
198 page_, profile)); | |
199 | |
200 // Download location options. | |
201 download_location_button_ = gtk_file_chooser_button_new( | |
202 l10n_util::GetStringUTF8( | |
203 IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_WINDOW_TITLE).c_str(), | |
204 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); | |
205 g_signal_connect(download_location_button_, "selection-changed", | |
206 G_CALLBACK(OnDownloadLocationChanged), this); | |
207 DisableScrolling(download_location_button_); | |
208 | |
209 // Add the default download path to the list of shortcuts in the selector. | |
210 FilePath default_download_path; | |
211 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, | |
212 &default_download_path)) { | |
213 NOTREACHED(); | |
214 } else { | |
215 if (!gtk_file_chooser_add_shortcut_folder( | |
216 GTK_FILE_CHOOSER(download_location_button_), | |
217 default_download_path.value().c_str(), | |
218 NULL)) { | |
219 NOTREACHED(); | |
220 } | |
221 } | |
222 | |
223 GtkWidget* download_location_control = gtk_util::CreateLabeledControlsGroup( | |
224 NULL, | |
225 l10n_util::GetStringUTF8( | |
226 IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_TITLE).c_str(), | |
227 download_location_button_, | |
228 NULL); | |
229 gtk_box_pack_start(GTK_BOX(page_), download_location_control, | |
230 FALSE, FALSE, 0); | |
231 | |
232 download_ask_for_save_location_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
233 IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION); | |
234 gtk_box_pack_start(GTK_BOX(page_), download_ask_for_save_location_checkbox_, | |
235 FALSE, FALSE, 0); | |
236 g_signal_connect(download_ask_for_save_location_checkbox_, "clicked", | |
237 G_CALLBACK(OnDownloadAskForSaveLocationChanged), this); | |
238 accessible_widget_helper_->SetWidgetName( | |
239 download_ask_for_save_location_checkbox_, | |
240 IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION); | |
241 | |
242 // Option for resetting file handlers. | |
243 reset_file_handlers_label_ = CreateWrappedLabel( | |
244 IDS_OPTIONS_AUTOOPENFILETYPES_INFO); | |
245 gtk_misc_set_alignment(GTK_MISC(reset_file_handlers_label_), 0, 0); | |
246 gtk_box_pack_start(GTK_BOX(page_), reset_file_handlers_label_, | |
247 FALSE, FALSE, 0); | |
248 | |
249 reset_file_handlers_button_ = gtk_button_new_with_label( | |
250 l10n_util::GetStringUTF8( | |
251 IDS_OPTIONS_AUTOOPENFILETYPES_RESETTODEFAULT).c_str()); | |
252 g_signal_connect(reset_file_handlers_button_, "clicked", | |
253 G_CALLBACK(OnResetFileHandlersClicked), this); | |
254 // Stick it in an hbox so it doesn't expand to the whole width. | |
255 GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0); | |
256 gtk_box_pack_start(GTK_BOX(button_hbox), | |
257 reset_file_handlers_button_, | |
258 FALSE, FALSE, 0); | |
259 gtk_box_pack_start(GTK_BOX(page_), | |
260 gtk_util::IndentWidget(button_hbox), | |
261 FALSE, FALSE, 0); | |
262 | |
263 // Init prefs watchers. | |
264 default_download_location_.Init(prefs::kDownloadDefaultDirectory, | |
265 profile->GetPrefs(), this); | |
266 ask_for_save_location_.Init(prefs::kPromptForDownload, | |
267 profile->GetPrefs(), this); | |
268 auto_open_files_.Init(prefs::kDownloadExtensionsToOpen, profile->GetPrefs(), | |
269 this); | |
270 | |
271 NotifyPrefChanged(NULL); | |
272 } | |
273 | |
274 void DownloadSection::NotifyPrefChanged(const std::string* pref_name) { | |
275 pref_changing_ = true; | |
276 if (!pref_name || *pref_name == prefs::kDownloadDefaultDirectory) { | |
277 gtk_file_chooser_set_current_folder( | |
278 GTK_FILE_CHOOSER(download_location_button_), | |
279 default_download_location_.GetValue().value().c_str()); | |
280 } | |
281 | |
282 if (!pref_name || *pref_name == prefs::kPromptForDownload) { | |
283 gtk_toggle_button_set_active( | |
284 GTK_TOGGLE_BUTTON(download_ask_for_save_location_checkbox_), | |
285 ask_for_save_location_.GetValue()); | |
286 } | |
287 | |
288 if (!pref_name || *pref_name == prefs::kDownloadExtensionsToOpen) { | |
289 DownloadPrefs* prefs = profile()->GetDownloadManager()->download_prefs(); | |
290 bool enabled = prefs->IsAutoOpenUsed(); | |
291 gtk_widget_set_sensitive(reset_file_handlers_label_, enabled); | |
292 gtk_widget_set_sensitive(reset_file_handlers_button_, enabled); | |
293 } | |
294 pref_changing_ = false; | |
295 } | |
296 | |
297 // static | |
298 void DownloadSection::OnDownloadLocationChanged(GtkFileChooser* widget, | |
299 DownloadSection* section) { | |
300 if (section->pref_changing_) | |
301 return; | |
302 | |
303 gchar* folder = gtk_file_chooser_get_filename(widget); | |
304 FilePath path(folder); | |
305 g_free(folder); | |
306 // Gtk seems to call this signal multiple times, so we only set the pref and | |
307 // metric if something actually changed. | |
308 if (path != section->default_download_location_.GetValue()) { | |
309 section->default_download_location_.SetValue(path); | |
310 section->UserMetricsRecordAction( | |
311 UserMetricsAction("Options_SetDownloadDirectory"), | |
312 section->profile()->GetPrefs()); | |
313 } | |
314 } | |
315 | |
316 // static | |
317 void DownloadSection::OnDownloadAskForSaveLocationChanged( | |
318 GtkWidget* widget, DownloadSection* section) { | |
319 if (section->pref_changing_) | |
320 return; | |
321 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
322 if (enabled) { | |
323 section->UserMetricsRecordAction( | |
324 UserMetricsAction("Options_AskForSaveLocation_Enable"), | |
325 section->profile()->GetPrefs()); | |
326 } else { | |
327 section->UserMetricsRecordAction( | |
328 UserMetricsAction("Options_AskForSaveLocation_Disable"), | |
329 section->profile()->GetPrefs()); | |
330 } | |
331 section->ask_for_save_location_.SetValue(enabled); | |
332 } | |
333 | |
334 // static | |
335 void DownloadSection::OnResetFileHandlersClicked(GtkButton *button, | |
336 DownloadSection* section) { | |
337 section->profile()->GetDownloadManager()->download_prefs()->ResetAutoOpen(); | |
338 section->UserMetricsRecordAction( | |
339 UserMetricsAction("Options_ResetAutoOpenFiles"), | |
340 section->profile()->GetPrefs()); | |
341 } | |
342 | |
343 /////////////////////////////////////////////////////////////////////////////// | |
344 // NetworkSection | |
345 | |
346 class NetworkSection : public OptionsPageBase { | |
347 public: | |
348 explicit NetworkSection(Profile* profile); | |
349 virtual ~NetworkSection() {} | |
350 | |
351 GtkWidget* get_page_widget() const { | |
352 return page_; | |
353 } | |
354 | |
355 private: | |
356 // Overridden from OptionsPageBase. | |
357 virtual void NotifyPrefChanged(const std::string* pref_name); | |
358 | |
359 struct ProxyConfigCommand { | |
360 std::string binary; | |
361 const char** argv; | |
362 }; | |
363 // The callback functions for invoking the proxy config dialog. | |
364 static void OnChangeProxiesButtonClicked(GtkButton *button, | |
365 NetworkSection* section); | |
366 // Detect, and if possible, start the appropriate proxy config utility. On | |
367 // failure to do so, show the Linux proxy config URL in a new tab instead. | |
368 static void DetectAndStartProxyConfigUtil(Profile* profile); | |
369 // Show the proxy config URL in a new tab. | |
370 static void ShowLinuxProxyConfigUrl(Profile* profile); | |
371 // Search $PATH to find one of the commands. Store the full path to | |
372 // it in the |binary| field and the command array index in in |index|. | |
373 static bool SearchPATH(ProxyConfigCommand* commands, size_t ncommands, | |
374 size_t* index); | |
375 // Start the given proxy configuration utility. | |
376 static void StartProxyConfigUtil(Profile* profile, | |
377 const ProxyConfigCommand& command); | |
378 | |
379 // Tracks the state of proxy preferences. | |
380 scoped_ptr<PrefSetObserver> proxy_prefs_; | |
381 | |
382 // The widget containing the options for this section. | |
383 GtkWidget* page_; | |
384 | |
385 // The proxy configuration button. | |
386 GtkWidget* change_proxies_button_; | |
387 | |
388 DISALLOW_COPY_AND_ASSIGN(NetworkSection); | |
389 }; | |
390 | |
391 NetworkSection::NetworkSection(Profile* profile) | |
392 : OptionsPageBase(profile) { | |
393 page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
394 | |
395 GtkWidget* proxy_description_label = CreateWrappedLabel( | |
396 IDS_OPTIONS_PROXIES_LABEL); | |
397 gtk_misc_set_alignment(GTK_MISC(proxy_description_label), 0, 0); | |
398 gtk_box_pack_start(GTK_BOX(page_), proxy_description_label, | |
399 FALSE, FALSE, 0); | |
400 | |
401 change_proxies_button_ = gtk_button_new_with_label( | |
402 l10n_util::GetStringUTF8( | |
403 IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON).c_str()); | |
404 g_signal_connect(change_proxies_button_, "clicked", | |
405 G_CALLBACK(OnChangeProxiesButtonClicked), this); | |
406 | |
407 // Stick it in an hbox so it doesn't expand to the whole width. | |
408 GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0); | |
409 gtk_box_pack_start(GTK_BOX(button_hbox), | |
410 change_proxies_button_, | |
411 FALSE, FALSE, 0); | |
412 gtk_box_pack_start(GTK_BOX(page_), | |
413 gtk_util::IndentWidget(button_hbox), | |
414 FALSE, FALSE, 0); | |
415 | |
416 proxy_prefs_.reset(PrefSetObserver::CreateProxyPrefSetObserver( | |
417 profile->GetPrefs(), this)); | |
418 NotifyPrefChanged(NULL); | |
419 } | |
420 | |
421 void NetworkSection::NotifyPrefChanged(const std::string* pref_name) { | |
422 if (!pref_name || proxy_prefs_->IsObserved(*pref_name)) | |
423 gtk_widget_set_sensitive(change_proxies_button_, | |
424 !proxy_prefs_->IsManaged()); | |
425 } | |
426 | |
427 // static | |
428 void NetworkSection::DetectAndStartProxyConfigUtil(Profile* profile) { | |
429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
430 scoped_ptr<base::Environment> env(base::Environment::Create()); | |
431 | |
432 ProxyConfigCommand command; | |
433 bool found_command = false; | |
434 switch (base::nix::GetDesktopEnvironment(env.get())) { | |
435 case base::nix::DESKTOP_ENVIRONMENT_GNOME: { | |
436 size_t index; | |
437 ProxyConfigCommand commands[2]; | |
438 commands[0].argv = kGNOMEProxyConfigCommand; | |
439 commands[1].argv = kOldGNOMEProxyConfigCommand; | |
440 found_command = SearchPATH(commands, 2, &index); | |
441 if (found_command) | |
442 command = commands[index]; | |
443 break; | |
444 } | |
445 | |
446 case base::nix::DESKTOP_ENVIRONMENT_KDE3: | |
447 command.argv = kKDE3ProxyConfigCommand; | |
448 found_command = SearchPATH(&command, 1, NULL); | |
449 break; | |
450 | |
451 case base::nix::DESKTOP_ENVIRONMENT_KDE4: | |
452 command.argv = kKDE4ProxyConfigCommand; | |
453 found_command = SearchPATH(&command, 1, NULL); | |
454 break; | |
455 | |
456 case base::nix::DESKTOP_ENVIRONMENT_XFCE: | |
457 case base::nix::DESKTOP_ENVIRONMENT_OTHER: | |
458 break; | |
459 } | |
460 | |
461 if (found_command) { | |
462 StartProxyConfigUtil(profile, command); | |
463 } else { | |
464 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
465 NewRunnableFunction(&NetworkSection::ShowLinuxProxyConfigUrl, profile)); | |
466 } | |
467 } | |
468 | |
469 // static | |
470 void NetworkSection::ShowLinuxProxyConfigUrl(Profile* profile) { | |
471 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
472 scoped_ptr<base::Environment> env(base::Environment::Create()); | |
473 const char* name = base::nix::GetDesktopEnvironmentName(env.get()); | |
474 if (name) | |
475 LOG(ERROR) << "Could not find " << name << " network settings in $PATH"; | |
476 browser::ShowOptionsURL(profile, GURL(kLinuxProxyConfigUrl)); | |
477 } | |
478 | |
479 // static | |
480 void NetworkSection::OnChangeProxiesButtonClicked(GtkButton *button, | |
481 NetworkSection* section) { | |
482 section->UserMetricsRecordAction(UserMetricsAction("Options_ChangeProxies"), | |
483 NULL); | |
484 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
485 NewRunnableFunction(&NetworkSection::DetectAndStartProxyConfigUtil, | |
486 section->profile())); | |
487 } | |
488 | |
489 // static | |
490 bool NetworkSection::SearchPATH(ProxyConfigCommand* commands, size_t ncommands, | |
491 size_t* index) { | |
492 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
493 const char* path = getenv("PATH"); | |
494 if (!path) | |
495 return false; | |
496 FilePath bin_path; | |
497 CStringTokenizer tk(path, path + strlen(path), ":"); | |
498 // Search $PATH looking for the commands in order. | |
499 while (tk.GetNext()) { | |
500 for (size_t i = 0; i < ncommands; i++) { | |
501 bin_path = FilePath(tk.token()).Append(commands[i].argv[0]); | |
502 if (file_util::PathExists(bin_path)) { | |
503 commands[i].binary = bin_path.value(); | |
504 if (index) | |
505 *index = i; | |
506 return true; | |
507 } | |
508 } | |
509 } | |
510 // Did not find any of the binaries in $PATH. | |
511 return false; | |
512 } | |
513 | |
514 // static | |
515 void NetworkSection::StartProxyConfigUtil(Profile* profile, | |
516 const ProxyConfigCommand& command) { | |
517 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
518 std::vector<std::string> argv; | |
519 argv.push_back(command.binary); | |
520 for (size_t i = 1; command.argv[i]; i++) | |
521 argv.push_back(command.argv[i]); | |
522 base::file_handle_mapping_vector no_files; | |
523 base::ProcessHandle handle; | |
524 if (!base::LaunchApp(argv, no_files, false, &handle)) { | |
525 LOG(ERROR) << "StartProxyConfigUtil failed to start " << command.binary; | |
526 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
527 NewRunnableFunction(&NetworkSection::ShowLinuxProxyConfigUrl, profile)); | |
528 return; | |
529 } | |
530 ProcessWatcher::EnsureProcessGetsReaped(handle); | |
531 } | |
532 | |
533 /////////////////////////////////////////////////////////////////////////////// | |
534 // TranslateSection | |
535 | |
536 class TranslateSection : public OptionsPageBase { | |
537 public: | |
538 explicit TranslateSection(Profile* profile); | |
539 virtual ~TranslateSection() {} | |
540 | |
541 GtkWidget* get_page_widget() const { | |
542 return page_; | |
543 } | |
544 | |
545 private: | |
546 // Overridden from OptionsPageBase. | |
547 virtual void NotifyPrefChanged(const std::string* pref_name); | |
548 | |
549 CHROMEGTK_CALLBACK_0(TranslateSection, void, OnTranslateClicked); | |
550 | |
551 // Preferences for this section: | |
552 BooleanPrefMember enable_translate_; | |
553 | |
554 // The widget containing the options for this section. | |
555 GtkWidget* page_; | |
556 | |
557 // The checkbox. | |
558 GtkWidget* translate_checkbox_; | |
559 | |
560 // Flag to ignore gtk callbacks while we are loading prefs, to avoid | |
561 // then turning around and saving them again. | |
562 bool pref_changing_; | |
563 | |
564 scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_; | |
565 | |
566 DISALLOW_COPY_AND_ASSIGN(TranslateSection); | |
567 }; | |
568 | |
569 TranslateSection::TranslateSection(Profile* profile) | |
570 : OptionsPageBase(profile), | |
571 pref_changing_(true) { | |
572 page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
573 | |
574 accessible_widget_helper_.reset(new AccessibleWidgetHelper( | |
575 page_, profile)); | |
576 | |
577 translate_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
578 IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE); | |
579 gtk_box_pack_start(GTK_BOX(page_), translate_checkbox_, | |
580 FALSE, FALSE, 0); | |
581 g_signal_connect(translate_checkbox_, "clicked", | |
582 G_CALLBACK(OnTranslateClickedThunk), this); | |
583 accessible_widget_helper_->SetWidgetName( | |
584 translate_checkbox_, | |
585 IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE); | |
586 | |
587 // Init member prefs so we can update the controls if prefs change. | |
588 enable_translate_.Init(prefs::kEnableTranslate, profile->GetPrefs(), this); | |
589 | |
590 NotifyPrefChanged(NULL); | |
591 } | |
592 | |
593 void TranslateSection::NotifyPrefChanged(const std::string* pref_name) { | |
594 pref_changing_ = true; | |
595 if (!pref_name || *pref_name == prefs::kEnableTranslate) { | |
596 gtk_toggle_button_set_active( | |
597 GTK_TOGGLE_BUTTON(translate_checkbox_), enable_translate_.GetValue()); | |
598 } | |
599 pref_changing_ = false; | |
600 } | |
601 | |
602 void TranslateSection::OnTranslateClicked(GtkWidget* widget) { | |
603 if (pref_changing_) | |
604 return; | |
605 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
606 UserMetricsRecordAction( | |
607 enabled ? | |
608 UserMetricsAction("Options_Translate_Enable") : | |
609 UserMetricsAction("Options_Translate_Disable"), | |
610 profile()->GetPrefs()); | |
611 enable_translate_.SetValue(enabled); | |
612 } | |
613 | |
614 /////////////////////////////////////////////////////////////////////////////// | |
615 // PrivacySection | |
616 | |
617 class PrivacySection : public OptionsPageBase { | |
618 public: | |
619 explicit PrivacySection(Profile* profile); | |
620 virtual ~PrivacySection() {} | |
621 | |
622 GtkWidget* get_page_widget() const { | |
623 return page_; | |
624 } | |
625 | |
626 private: | |
627 // Overridden from OptionsPageBase. | |
628 virtual void NotifyPrefChanged(const std::string* pref_name); | |
629 | |
630 // Try to make the the crash stats consent and the metrics upload | |
631 // permission match the |reporting_enabled_checkbox_|. | |
632 void ResolveMetricsReportingEnabled(); | |
633 | |
634 // The callback functions for the options widgets. | |
635 static void OnContentSettingsClicked(GtkButton* button, | |
636 PrivacySection* privacy_section); | |
637 static void OnClearBrowsingDataButtonClicked(GtkButton* widget, | |
638 PrivacySection* page); | |
639 static void OnLearnMoreLinkClicked(GtkButton *button, | |
640 PrivacySection* privacy_section); | |
641 static void OnEnableLinkDoctorChange(GtkWidget* widget, | |
642 PrivacySection* options_window); | |
643 static void OnEnableSuggestChange(GtkWidget* widget, | |
644 PrivacySection* options_window); | |
645 static void OnDNSPrefetchingChange(GtkWidget* widget, | |
646 PrivacySection* options_window); | |
647 static void OnSafeBrowsingChange(GtkWidget* widget, | |
648 PrivacySection* options_window); | |
649 static void OnLoggingChange(GtkWidget* widget, | |
650 PrivacySection* options_window); | |
651 | |
652 // The widget containing the options for this section. | |
653 GtkWidget* page_; | |
654 | |
655 // The widgets for the privacy options. | |
656 GtkWidget* enable_link_doctor_checkbox_; | |
657 GtkWidget* enable_suggest_checkbox_; | |
658 GtkWidget* enable_dns_prefetching_checkbox_; | |
659 GtkWidget* enable_safe_browsing_checkbox_; | |
660 #if defined(GOOGLE_CHROME_BUILD) | |
661 GtkWidget* reporting_enabled_checkbox_; | |
662 #endif | |
663 | |
664 // Preferences for this section: | |
665 BooleanPrefMember alternate_error_pages_; | |
666 BooleanPrefMember use_suggest_; | |
667 BooleanPrefMember dns_prefetch_enabled_; | |
668 BooleanPrefMember safe_browsing_; | |
669 BooleanPrefMember enable_metrics_recording_; | |
670 | |
671 // Flag to ignore gtk callbacks while we are loading prefs, to avoid | |
672 // then turning around and saving them again. | |
673 bool pref_changing_; | |
674 | |
675 scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_; | |
676 | |
677 DISALLOW_COPY_AND_ASSIGN(PrivacySection); | |
678 }; | |
679 | |
680 PrivacySection::PrivacySection(Profile* profile) | |
681 : OptionsPageBase(profile), | |
682 pref_changing_(true) { | |
683 page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
684 | |
685 accessible_widget_helper_.reset(new AccessibleWidgetHelper( | |
686 page_, profile)); | |
687 | |
688 GtkWidget* content_button = gtk_button_new_with_label( | |
689 l10n_util::GetStringUTF8( | |
690 IDS_OPTIONS_PRIVACY_CONTENT_SETTINGS_BUTTON).c_str()); | |
691 g_signal_connect(content_button, "clicked", | |
692 G_CALLBACK(OnContentSettingsClicked), this); | |
693 | |
694 GtkWidget* clear_data_button = gtk_button_new_with_label( | |
695 l10n_util::GetStringUTF8(IDS_OPTIONS_PRIVACY_CLEAR_DATA_BUTTON).c_str()); | |
696 g_signal_connect(clear_data_button, "clicked", | |
697 G_CALLBACK(OnClearBrowsingDataButtonClicked), this); | |
698 | |
699 // Stick it in an hbox so it doesn't expand to the whole width. | |
700 GtkWidget* button_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing); | |
701 gtk_box_pack_start(GTK_BOX(button_hbox), content_button, FALSE, FALSE, 0); | |
702 gtk_box_pack_start(GTK_BOX(button_hbox), clear_data_button, FALSE, FALSE, 0); | |
703 gtk_box_pack_start(GTK_BOX(page_), gtk_util::IndentWidget(button_hbox), | |
704 FALSE, FALSE, 0); | |
705 | |
706 GtkWidget* section_description_label = CreateWrappedLabel( | |
707 IDS_OPTIONS_DISABLE_SERVICES); | |
708 gtk_misc_set_alignment(GTK_MISC(section_description_label), 0, 0); | |
709 gtk_box_pack_start(GTK_BOX(page_), section_description_label, | |
710 FALSE, FALSE, 0); | |
711 | |
712 GtkWidget* learn_more_link = gtk_chrome_link_button_new( | |
713 l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str()); | |
714 // Stick it in an hbox so it doesn't expand to the whole width. | |
715 GtkWidget* learn_more_hbox = gtk_hbox_new(FALSE, 0); | |
716 gtk_box_pack_start(GTK_BOX(learn_more_hbox), learn_more_link, | |
717 FALSE, FALSE, 0); | |
718 gtk_box_pack_start(GTK_BOX(page_), learn_more_hbox, | |
719 FALSE, FALSE, 0); | |
720 g_signal_connect(learn_more_link, "clicked", | |
721 G_CALLBACK(OnLearnMoreLinkClicked), this); | |
722 | |
723 enable_link_doctor_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
724 IDS_OPTIONS_LINKDOCTOR_PREF); | |
725 gtk_box_pack_start(GTK_BOX(page_), enable_link_doctor_checkbox_, | |
726 FALSE, FALSE, 0); | |
727 g_signal_connect(enable_link_doctor_checkbox_, "clicked", | |
728 G_CALLBACK(OnEnableLinkDoctorChange), this); | |
729 accessible_widget_helper_->SetWidgetName( | |
730 enable_link_doctor_checkbox_, IDS_OPTIONS_LINKDOCTOR_PREF); | |
731 | |
732 enable_suggest_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
733 IDS_OPTIONS_SUGGEST_PREF); | |
734 gtk_box_pack_start(GTK_BOX(page_), enable_suggest_checkbox_, | |
735 FALSE, FALSE, 0); | |
736 g_signal_connect(enable_suggest_checkbox_, "clicked", | |
737 G_CALLBACK(OnEnableSuggestChange), this); | |
738 accessible_widget_helper_->SetWidgetName( | |
739 enable_suggest_checkbox_, IDS_OPTIONS_SUGGEST_PREF); | |
740 | |
741 enable_dns_prefetching_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
742 IDS_NETWORK_DNS_PREFETCH_ENABLED_DESCRIPTION); | |
743 gtk_box_pack_start(GTK_BOX(page_), enable_dns_prefetching_checkbox_, | |
744 FALSE, FALSE, 0); | |
745 g_signal_connect(enable_dns_prefetching_checkbox_, "clicked", | |
746 G_CALLBACK(OnDNSPrefetchingChange), this); | |
747 accessible_widget_helper_->SetWidgetName( | |
748 enable_dns_prefetching_checkbox_, | |
749 IDS_NETWORK_DNS_PREFETCH_ENABLED_DESCRIPTION); | |
750 | |
751 enable_safe_browsing_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
752 IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION); | |
753 gtk_box_pack_start(GTK_BOX(page_), enable_safe_browsing_checkbox_, | |
754 FALSE, FALSE, 0); | |
755 g_signal_connect(enable_safe_browsing_checkbox_, "clicked", | |
756 G_CALLBACK(OnSafeBrowsingChange), this); | |
757 accessible_widget_helper_->SetWidgetName( | |
758 enable_safe_browsing_checkbox_, | |
759 IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION); | |
760 | |
761 #if defined(GOOGLE_CHROME_BUILD) | |
762 reporting_enabled_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
763 IDS_OPTIONS_ENABLE_LOGGING); | |
764 gtk_box_pack_start(GTK_BOX(page_), reporting_enabled_checkbox_, | |
765 FALSE, FALSE, 0); | |
766 g_signal_connect(reporting_enabled_checkbox_, "clicked", | |
767 G_CALLBACK(OnLoggingChange), this); | |
768 accessible_widget_helper_->SetWidgetName( | |
769 reporting_enabled_checkbox_, IDS_OPTIONS_ENABLE_LOGGING); | |
770 #endif | |
771 | |
772 // Init member prefs so we can update the controls if prefs change. | |
773 alternate_error_pages_.Init(prefs::kAlternateErrorPagesEnabled, | |
774 profile->GetPrefs(), this); | |
775 use_suggest_.Init(prefs::kSearchSuggestEnabled, | |
776 profile->GetPrefs(), this); | |
777 dns_prefetch_enabled_.Init(prefs::kDnsPrefetchingEnabled, | |
778 profile->GetPrefs(), this); | |
779 safe_browsing_.Init(prefs::kSafeBrowsingEnabled, profile->GetPrefs(), this); | |
780 enable_metrics_recording_.Init(prefs::kMetricsReportingEnabled, | |
781 g_browser_process->local_state(), this); | |
782 NotifyPrefChanged(NULL); | |
783 } | |
784 | |
785 // static | |
786 void PrivacySection::OnContentSettingsClicked(GtkButton* button, | |
787 PrivacySection* privacy_section) { | |
788 ContentSettingsWindowGtk::Show( | |
789 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))), | |
790 CONTENT_SETTINGS_TYPE_DEFAULT, | |
791 privacy_section->profile()); | |
792 } | |
793 | |
794 // static | |
795 void PrivacySection::OnClearBrowsingDataButtonClicked(GtkButton* widget, | |
796 PrivacySection* section) { | |
797 ClearBrowsingDataDialogGtk::Show( | |
798 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(widget))), | |
799 section->profile()); | |
800 } | |
801 | |
802 // static | |
803 void PrivacySection::OnLearnMoreLinkClicked(GtkButton *button, | |
804 PrivacySection* privacy_section) { | |
805 GURL url = google_util::AppendGoogleLocaleParam( | |
806 GURL(chrome::kPrivacyLearnMoreURL)); | |
807 browser::ShowOptionsURL(privacy_section->profile(), url); | |
808 } | |
809 | |
810 // static | |
811 void PrivacySection::OnEnableLinkDoctorChange(GtkWidget* widget, | |
812 PrivacySection* privacy_section) { | |
813 if (privacy_section->pref_changing_) | |
814 return; | |
815 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
816 privacy_section->UserMetricsRecordAction( | |
817 enabled ? | |
818 UserMetricsAction("Options_LinkDoctorCheckbox_Enable") : | |
819 UserMetricsAction("Options_LinkDoctorCheckbox_Disable"), | |
820 privacy_section->profile()->GetPrefs()); | |
821 privacy_section->alternate_error_pages_.SetValue(enabled); | |
822 } | |
823 | |
824 // static | |
825 void PrivacySection::OnEnableSuggestChange(GtkWidget* widget, | |
826 PrivacySection* privacy_section) { | |
827 if (privacy_section->pref_changing_) | |
828 return; | |
829 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
830 privacy_section->UserMetricsRecordAction( | |
831 enabled ? | |
832 UserMetricsAction("Options_UseSuggestCheckbox_Enable") : | |
833 UserMetricsAction("Options_UseSuggestCheckbox_Disable"), | |
834 privacy_section->profile()->GetPrefs()); | |
835 privacy_section->use_suggest_.SetValue(enabled); | |
836 } | |
837 | |
838 // static | |
839 void PrivacySection::OnDNSPrefetchingChange(GtkWidget* widget, | |
840 PrivacySection* privacy_section) { | |
841 if (privacy_section->pref_changing_) | |
842 return; | |
843 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
844 privacy_section->UserMetricsRecordAction( | |
845 enabled ? | |
846 UserMetricsAction("Options_DnsPrefetchCheckbox_Enable") : | |
847 UserMetricsAction("Options_DnsPrefetchCheckbox_Disable"), | |
848 privacy_section->profile()->GetPrefs()); | |
849 privacy_section->dns_prefetch_enabled_.SetValue(enabled); | |
850 } | |
851 | |
852 // static | |
853 void PrivacySection::OnSafeBrowsingChange(GtkWidget* widget, | |
854 PrivacySection* privacy_section) { | |
855 if (privacy_section->pref_changing_) | |
856 return; | |
857 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
858 privacy_section->UserMetricsRecordAction( | |
859 enabled ? | |
860 UserMetricsAction("Options_SafeBrowsingCheckbox_Enable") : | |
861 UserMetricsAction("Options_SafeBrowsingCheckbox_Disable"), | |
862 privacy_section->profile()->GetPrefs()); | |
863 privacy_section->safe_browsing_.SetValue(enabled); | |
864 SafeBrowsingService* safe_browsing_service = | |
865 g_browser_process->resource_dispatcher_host()->safe_browsing_service(); | |
866 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | |
867 safe_browsing_service, &SafeBrowsingService::OnEnable, enabled)); | |
868 } | |
869 | |
870 // static | |
871 void PrivacySection::OnLoggingChange(GtkWidget* widget, | |
872 PrivacySection* privacy_section) { | |
873 if (privacy_section->pref_changing_) | |
874 return; | |
875 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
876 privacy_section->UserMetricsRecordAction( | |
877 enabled ? | |
878 UserMetricsAction("Options_MetricsReportingCheckbox_Enable") : | |
879 UserMetricsAction("Options_MetricsReportingCheckbox_Disable"), | |
880 privacy_section->profile()->GetPrefs()); | |
881 // Prevent us from being called again by ResolveMetricsReportingEnabled | |
882 // resetting the checkbox if there was a problem. | |
883 g_signal_handlers_block_by_func(widget, | |
884 reinterpret_cast<gpointer>(OnLoggingChange), | |
885 privacy_section); | |
886 privacy_section->ResolveMetricsReportingEnabled(); | |
887 g_signal_handlers_unblock_by_func(widget, | |
888 reinterpret_cast<gpointer>(OnLoggingChange), | |
889 privacy_section); | |
890 privacy_section->enable_metrics_recording_.SetValue(enabled); | |
891 } | |
892 | |
893 void PrivacySection::NotifyPrefChanged(const std::string* pref_name) { | |
894 pref_changing_ = true; | |
895 if (!pref_name || *pref_name == prefs::kAlternateErrorPagesEnabled) { | |
896 gtk_widget_set_sensitive( | |
897 GTK_WIDGET(enable_link_doctor_checkbox_), | |
898 !alternate_error_pages_.IsManaged()); | |
899 gtk_toggle_button_set_active( | |
900 GTK_TOGGLE_BUTTON(enable_link_doctor_checkbox_), | |
901 alternate_error_pages_.GetValue()); | |
902 } | |
903 if (!pref_name || *pref_name == prefs::kSearchSuggestEnabled) { | |
904 gtk_widget_set_sensitive( | |
905 GTK_WIDGET(enable_suggest_checkbox_), | |
906 !use_suggest_.IsManaged()); | |
907 gtk_toggle_button_set_active( | |
908 GTK_TOGGLE_BUTTON(enable_suggest_checkbox_), | |
909 use_suggest_.GetValue()); | |
910 } | |
911 if (!pref_name || *pref_name == prefs::kDnsPrefetchingEnabled) { | |
912 gtk_widget_set_sensitive( | |
913 GTK_WIDGET(enable_dns_prefetching_checkbox_), | |
914 !dns_prefetch_enabled_.IsManaged()); | |
915 bool enabled = dns_prefetch_enabled_.GetValue(); | |
916 gtk_toggle_button_set_active( | |
917 GTK_TOGGLE_BUTTON(enable_dns_prefetching_checkbox_), enabled); | |
918 } | |
919 if (!pref_name || *pref_name == prefs::kSafeBrowsingEnabled) { | |
920 gtk_widget_set_sensitive( | |
921 GTK_WIDGET(enable_safe_browsing_checkbox_), | |
922 !safe_browsing_.IsManaged()); | |
923 gtk_toggle_button_set_active( | |
924 GTK_TOGGLE_BUTTON(enable_safe_browsing_checkbox_), | |
925 safe_browsing_.GetValue()); | |
926 } | |
927 #if defined(GOOGLE_CHROME_BUILD) | |
928 if (!pref_name || *pref_name == prefs::kMetricsReportingEnabled) { | |
929 gtk_widget_set_sensitive( | |
930 GTK_WIDGET(reporting_enabled_checkbox_), | |
931 !enable_metrics_recording_.IsManaged()); | |
932 gtk_toggle_button_set_active( | |
933 GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_), | |
934 enable_metrics_recording_.GetValue()); | |
935 ResolveMetricsReportingEnabled(); | |
936 } | |
937 #endif | |
938 pref_changing_ = false; | |
939 } | |
940 | |
941 void PrivacySection::ResolveMetricsReportingEnabled() { | |
942 #if defined(GOOGLE_CHROME_BUILD) | |
943 bool enabled = gtk_toggle_button_get_active( | |
944 GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_)); | |
945 | |
946 enabled = OptionsUtil::ResolveMetricsReportingEnabled(enabled); | |
947 | |
948 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_), | |
949 enabled); | |
950 #endif | |
951 } | |
952 | |
953 /////////////////////////////////////////////////////////////////////////////// | |
954 // SecuritySection | |
955 | |
956 class SecuritySection : public OptionsPageBase { | |
957 public: | |
958 explicit SecuritySection(Profile* profile); | |
959 virtual ~SecuritySection() {} | |
960 | |
961 GtkWidget* get_page_widget() const { | |
962 return page_; | |
963 } | |
964 | |
965 private: | |
966 // Overridden from OptionsPageBase. | |
967 virtual void NotifyPrefChanged(const std::string* pref_name); | |
968 | |
969 // The callback functions for the options widgets. | |
970 static void OnManageCertificatesClicked(GtkButton* button, | |
971 SecuritySection* section); | |
972 static void OnRevCheckingEnabledToggled(GtkToggleButton* togglebutton, | |
973 SecuritySection* section); | |
974 static void OnSSL3EnabledToggled(GtkToggleButton* togglebutton, | |
975 SecuritySection* section); | |
976 static void OnTLS1EnabledToggled(GtkToggleButton* togglebutton, | |
977 SecuritySection* section); | |
978 | |
979 // The widget containing the options for this section. | |
980 GtkWidget* page_; | |
981 GtkWidget* rev_checking_enabled_checkbox_; | |
982 GtkWidget* ssl3_enabled_checkbox_; | |
983 GtkWidget* tls1_enabled_checkbox_; | |
984 | |
985 // SSLConfigService prefs. | |
986 BooleanPrefMember rev_checking_enabled_; | |
987 BooleanPrefMember ssl3_enabled_; | |
988 BooleanPrefMember tls1_enabled_; | |
989 | |
990 // Flag to ignore gtk callbacks while we are loading prefs, to avoid | |
991 // then turning around and saving them again. | |
992 bool pref_changing_; | |
993 | |
994 scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_; | |
995 | |
996 DISALLOW_COPY_AND_ASSIGN(SecuritySection); | |
997 }; | |
998 | |
999 SecuritySection::SecuritySection(Profile* profile) | |
1000 : OptionsPageBase(profile), | |
1001 pref_changing_(true) { | |
1002 page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
1003 | |
1004 accessible_widget_helper_.reset(new AccessibleWidgetHelper( | |
1005 page_, profile)); | |
1006 | |
1007 GtkWidget* manage_certificates_label = CreateWrappedLabel( | |
1008 IDS_OPTIONS_CERTIFICATES_LABEL); | |
1009 gtk_misc_set_alignment(GTK_MISC(manage_certificates_label), 0, 0); | |
1010 gtk_box_pack_start(GTK_BOX(page_), manage_certificates_label, | |
1011 FALSE, FALSE, 0); | |
1012 | |
1013 // TODO(mattm): change this to a button to launch the system certificate | |
1014 // manager, when one exists. | |
1015 GtkWidget* manage_certificates_link = gtk_chrome_link_button_new( | |
1016 l10n_util::GetStringUTF8(IDS_OPTIONS_CERTIFICATES_MANAGE_BUTTON).c_str()); | |
1017 // Stick it in an hbox so it doesn't expand to the whole width. | |
1018 GtkWidget* manage_certificates_hbox = gtk_hbox_new(FALSE, 0); | |
1019 gtk_box_pack_start(GTK_BOX(manage_certificates_hbox), | |
1020 manage_certificates_link, FALSE, FALSE, 0); | |
1021 gtk_box_pack_start(GTK_BOX(page_), | |
1022 gtk_util::IndentWidget(manage_certificates_hbox), | |
1023 FALSE, FALSE, 0); | |
1024 g_signal_connect(manage_certificates_link, "clicked", | |
1025 G_CALLBACK(OnManageCertificatesClicked), this); | |
1026 | |
1027 // TODO(mattm): should have a description label here and have the checkboxes | |
1028 // indented, but IDS_OPTIONS_SSL_GROUP_DESCRIPTION isn't appropriate and | |
1029 // didn't think of adding a Linux specific one before the string freeze. | |
1030 rev_checking_enabled_checkbox_ = AddCheckButtonWithWrappedLabel( | |
1031 IDS_OPTIONS_SSL_CHECKREVOCATION, page_, | |
1032 G_CALLBACK(OnRevCheckingEnabledToggled), this); | |
1033 accessible_widget_helper_->SetWidgetName( | |
1034 rev_checking_enabled_checkbox_, IDS_OPTIONS_SSL_CHECKREVOCATION); | |
1035 ssl3_enabled_checkbox_ = AddCheckButtonWithWrappedLabel( | |
1036 IDS_OPTIONS_SSL_USESSL3, page_, G_CALLBACK(OnSSL3EnabledToggled), this); | |
1037 accessible_widget_helper_->SetWidgetName( | |
1038 ssl3_enabled_checkbox_, IDS_OPTIONS_SSL_USESSL3); | |
1039 tls1_enabled_checkbox_ = AddCheckButtonWithWrappedLabel( | |
1040 IDS_OPTIONS_SSL_USETLS1, page_, G_CALLBACK(OnTLS1EnabledToggled), this); | |
1041 accessible_widget_helper_->SetWidgetName( | |
1042 tls1_enabled_checkbox_, IDS_OPTIONS_SSL_USETLS1); | |
1043 | |
1044 rev_checking_enabled_.Init(prefs::kCertRevocationCheckingEnabled, | |
1045 profile->GetPrefs(), this); | |
1046 ssl3_enabled_.Init(prefs::kSSL3Enabled, profile->GetPrefs(), this); | |
1047 tls1_enabled_.Init(prefs::kTLS1Enabled, profile->GetPrefs(), this); | |
1048 | |
1049 NotifyPrefChanged(NULL); | |
1050 } | |
1051 | |
1052 void SecuritySection::NotifyPrefChanged(const std::string* pref_name) { | |
1053 pref_changing_ = true; | |
1054 if (!pref_name || *pref_name == prefs::kCertRevocationCheckingEnabled) { | |
1055 gtk_toggle_button_set_active( | |
1056 GTK_TOGGLE_BUTTON(rev_checking_enabled_checkbox_), | |
1057 rev_checking_enabled_.GetValue()); | |
1058 } | |
1059 if (!pref_name || *pref_name == prefs::kSSL3Enabled) { | |
1060 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ssl3_enabled_checkbox_), | |
1061 ssl3_enabled_.GetValue()); | |
1062 } | |
1063 if (!pref_name || *pref_name == prefs::kTLS1Enabled) { | |
1064 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tls1_enabled_checkbox_), | |
1065 tls1_enabled_.GetValue()); | |
1066 } | |
1067 pref_changing_ = false; | |
1068 } | |
1069 | |
1070 | |
1071 // static | |
1072 void SecuritySection::OnManageCertificatesClicked(GtkButton* button, | |
1073 SecuritySection* section) { | |
1074 browser::ShowOptionsURL(section->profile(), | |
1075 GURL(kLinuxCertificatesConfigUrl)); | |
1076 } | |
1077 | |
1078 // static | |
1079 void SecuritySection::OnRevCheckingEnabledToggled(GtkToggleButton* togglebutton, | |
1080 SecuritySection* section) { | |
1081 if (section->pref_changing_) | |
1082 return; | |
1083 | |
1084 bool enabled = gtk_toggle_button_get_active(togglebutton); | |
1085 if (enabled) { | |
1086 section->UserMetricsRecordAction( | |
1087 UserMetricsAction("Options_CheckCertRevocation_Enable"), | |
1088 NULL); | |
1089 } else { | |
1090 section->UserMetricsRecordAction( | |
1091 UserMetricsAction("Options_CheckCertRevocation_Disable"), | |
1092 NULL); | |
1093 } | |
1094 section->rev_checking_enabled_.SetValue(enabled); | |
1095 } | |
1096 | |
1097 // static | |
1098 void SecuritySection::OnSSL3EnabledToggled(GtkToggleButton* togglebutton, | |
1099 SecuritySection* section) { | |
1100 if (section->pref_changing_) | |
1101 return; | |
1102 | |
1103 bool enabled = gtk_toggle_button_get_active(togglebutton); | |
1104 if (enabled) { | |
1105 section->UserMetricsRecordAction(UserMetricsAction("Options_SSL3_Enable"), | |
1106 NULL); | |
1107 } else { | |
1108 section->UserMetricsRecordAction(UserMetricsAction("Options_SSL3_Disable"), | |
1109 NULL); | |
1110 } | |
1111 section->ssl3_enabled_.SetValue(enabled); | |
1112 } | |
1113 | |
1114 // static | |
1115 void SecuritySection::OnTLS1EnabledToggled(GtkToggleButton* togglebutton, | |
1116 SecuritySection* section) { | |
1117 if (section->pref_changing_) | |
1118 return; | |
1119 | |
1120 bool enabled = gtk_toggle_button_get_active(togglebutton); | |
1121 if (enabled) { | |
1122 section->UserMetricsRecordAction(UserMetricsAction("Options_TLS1_Enable"), | |
1123 NULL); | |
1124 } else { | |
1125 section->UserMetricsRecordAction(UserMetricsAction("Options_TLS1_Disable"), | |
1126 NULL); | |
1127 } | |
1128 section->tls1_enabled_.SetValue(enabled); | |
1129 } | |
1130 | |
1131 /////////////////////////////////////////////////////////////////////////////// | |
1132 // WebContentSection | |
1133 | |
1134 class WebContentSection : public OptionsPageBase { | |
1135 public: | |
1136 explicit WebContentSection(Profile* profile); | |
1137 virtual ~WebContentSection() {} | |
1138 | |
1139 GtkWidget* get_page_widget() const { | |
1140 return page_; | |
1141 } | |
1142 | |
1143 private: | |
1144 // The callback functions for the options widgets. | |
1145 static void OnFontsAndLanguagesButtonClicked(GtkButton *button, | |
1146 WebContentSection* section); | |
1147 | |
1148 // The widget containing the options for this section. | |
1149 GtkWidget* page_; | |
1150 | |
1151 DISALLOW_COPY_AND_ASSIGN(WebContentSection); | |
1152 }; | |
1153 | |
1154 WebContentSection::WebContentSection(Profile* profile) | |
1155 : OptionsPageBase(profile) { | |
1156 page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
1157 | |
1158 GtkWidget* fonts_and_languages_label = CreateWrappedLabel( | |
1159 IDS_OPTIONS_FONTSETTINGS_INFO); | |
1160 gtk_misc_set_alignment(GTK_MISC(fonts_and_languages_label), 0, 0); | |
1161 gtk_box_pack_start(GTK_BOX(page_), fonts_and_languages_label, | |
1162 FALSE, FALSE, 0); | |
1163 | |
1164 GtkWidget* fonts_and_languages_button = gtk_button_new_with_label( | |
1165 l10n_util::GetStringUTF8( | |
1166 IDS_OPTIONS_FONTSETTINGS_CONFIGUREFONTS_BUTTON).c_str()); | |
1167 g_signal_connect(fonts_and_languages_button, "clicked", | |
1168 G_CALLBACK(OnFontsAndLanguagesButtonClicked), this); | |
1169 // Stick it in an hbox so it doesn't expand to the whole width. | |
1170 GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0); | |
1171 gtk_box_pack_start(GTK_BOX(button_hbox), | |
1172 fonts_and_languages_button, | |
1173 FALSE, FALSE, 0); | |
1174 gtk_box_pack_start(GTK_BOX(page_), | |
1175 gtk_util::IndentWidget(button_hbox), | |
1176 FALSE, FALSE, 0); | |
1177 | |
1178 // TODO(mattm): gears options would go here if we supported gears | |
1179 } | |
1180 | |
1181 // static | |
1182 void WebContentSection::OnFontsAndLanguagesButtonClicked( | |
1183 GtkButton *button, WebContentSection* section) { | |
1184 ShowFontsLanguagesWindow(GTK_WINDOW(gtk_widget_get_toplevel(section->page_)), | |
1185 FONTS_ENCODING_PAGE, | |
1186 section->profile()); | |
1187 } | |
1188 | |
1189 /////////////////////////////////////////////////////////////////////////////// | |
1190 // AdvancedContentsGtk | |
1191 | |
1192 AdvancedContentsGtk::AdvancedContentsGtk(Profile* profile) | |
1193 : profile_(profile) { | |
1194 Init(); | |
1195 } | |
1196 | |
1197 AdvancedContentsGtk::~AdvancedContentsGtk() { | |
1198 } | |
1199 | |
1200 void AdvancedContentsGtk::Init() { | |
1201 scoped_ptr<OptionsLayoutBuilderGtk> | |
1202 options_builder(OptionsLayoutBuilderGtk::Create()); | |
1203 | |
1204 privacy_section_.reset(new PrivacySection(profile_)); | |
1205 options_builder->AddOptionGroup( | |
1206 l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY), | |
1207 privacy_section_->get_page_widget(), false); | |
1208 | |
1209 network_section_.reset(new NetworkSection(profile_)); | |
1210 options_builder->AddOptionGroup( | |
1211 l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_NETWORK), | |
1212 network_section_->get_page_widget(), false); | |
1213 | |
1214 translate_section_.reset(new TranslateSection(profile_)); | |
1215 options_builder->AddOptionGroup( | |
1216 l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_TRANSLATE), | |
1217 translate_section_->get_page_widget(), false); | |
1218 | |
1219 download_section_.reset(new DownloadSection(profile_)); | |
1220 options_builder->AddOptionGroup( | |
1221 l10n_util::GetStringUTF8(IDS_OPTIONS_DOWNLOADLOCATION_GROUP_NAME), | |
1222 download_section_->get_page_widget(), false); | |
1223 | |
1224 web_content_section_.reset(new WebContentSection(profile_)); | |
1225 options_builder->AddOptionGroup( | |
1226 l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_CONTENT), | |
1227 web_content_section_->get_page_widget(), false); | |
1228 | |
1229 security_section_.reset(new SecuritySection(profile_)); | |
1230 options_builder->AddOptionGroup( | |
1231 l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_SECURITY), | |
1232 security_section_->get_page_widget(), false); | |
1233 | |
1234 page_ = options_builder->get_page_widget(); | |
1235 } | |
OLD | NEW |