OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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/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 "base/basictypes.h" | |
14 #include "base/command_line.h" | |
15 #include "base/environment.h" | |
16 #include "base/file_util.h" | |
17 #include "base/path_service.h" | |
18 #include "base/process_util.h" | |
19 #include "base/string_tokenizer.h" | |
20 #include "base/nix/xdg_util.h" | |
21 #include "chrome/browser/browser_list.h" | |
22 #include "chrome/browser/browser_process.h" | |
23 #include "chrome/browser/download/download_manager.h" | |
24 #include "chrome/browser/download/download_prefs.h" | |
25 #include "chrome/browser/fonts_languages_window.h" | |
26 #include "chrome/browser/google/google_util.h" | |
27 #include "chrome/browser/prefs/pref_member.h" | |
28 #include "chrome/browser/prefs/pref_set_observer.h" | |
29 #include "chrome/browser/profiles/profile.h" | |
30 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | |
31 #include "chrome/browser/ui/gtk/clear_browsing_data_dialog_gtk.h" | |
32 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h" | |
33 #include "chrome/browser/ui/gtk/gtk_util.h" | |
34 #include "chrome/browser/ui/gtk/options/content_settings_window_gtk.h" | |
35 #include "chrome/browser/ui/gtk/options/options_layout_gtk.h" | |
36 #include "chrome/browser/ui/options/options_page_base.h" | |
37 #include "chrome/browser/ui/options/options_util.h" | |
38 #include "chrome/browser/ui/options/show_options_url.h" | |
39 #include "chrome/common/chrome_paths.h" | |
40 #include "chrome/common/pref_names.h" | |
41 #include "chrome/common/process_watcher.h" | |
42 #include "chrome/common/url_constants.h" | |
43 #include "content/browser/renderer_host/resource_dispatcher_host.h" | |
44 #include "grit/chromium_strings.h" | |
45 #include "grit/generated_resources.h" | |
46 #include "grit/locale_settings.h" | |
47 #include "ui/base/gtk/gtk_signal.h" | |
48 #include "ui/base/l10n/l10n_util.h" | |
49 | |
50 namespace { | |
51 | |
52 // Command used to configure GNOME proxy settings. The command was renamed | |
53 // in January 2009, so both are used to work on both old and new systems. | |
54 const char* kOldGNOMEProxyConfigCommand[] = {"gnome-network-preferences", NULL}; | |
55 const char* kGNOMEProxyConfigCommand[] = {"gnome-network-properties", NULL}; | |
56 // KDE3 and KDE4 are only slightly different, but incompatible. Go figure. | |
57 const char* kKDE3ProxyConfigCommand[] = {"kcmshell", "proxy", NULL}; | |
58 const char* kKDE4ProxyConfigCommand[] = {"kcmshell4", "proxy", NULL}; | |
59 | |
60 // The URL for Linux ssl certificate configuration help. | |
61 const char* const kLinuxCertificatesConfigUrl = | |
62 "http://code.google.com/p/chromium/wiki/LinuxCertManagement"; | |
63 | |
64 // The URL for Linux proxy configuration help when not running under a | |
65 // supported desktop environment. | |
66 const char kLinuxProxyConfigUrl[] = "about:linux-proxy-config"; | |
67 | |
68 // The pixel width we wrap labels at. | |
69 // TODO(evanm): make the labels wrap at the appropriate width. | |
70 #if defined(OS_CHROMEOS) | |
71 // ChromeOS uses IDS_OPTIONS_DIALOG_WIDTH_CHARS for options dialog width, which | |
72 // is slightly smaller than the Gtk options dialog's 500px. | |
73 const int kWrapWidth = 445; | |
74 #else | |
75 const int kWrapWidth = 475; | |
76 #endif | |
77 | |
78 GtkWidget* CreateWrappedLabel(int string_id) { | |
79 GtkWidget* label = gtk_label_new( | |
80 l10n_util::GetStringUTF8(string_id).c_str()); | |
81 gtk_util::SetLabelWidth(label, kWrapWidth); | |
82 return label; | |
83 } | |
84 | |
85 GtkWidget* CreateCheckButtonWithWrappedLabel(int string_id) { | |
86 GtkWidget* checkbox = gtk_check_button_new(); | |
87 gtk_container_add(GTK_CONTAINER(checkbox), | |
88 CreateWrappedLabel(string_id)); | |
89 return checkbox; | |
90 } | |
91 | |
92 GtkWidget* AddCheckButtonWithWrappedLabel(int string_id, | |
93 GtkWidget* container, | |
94 GCallback handler, | |
95 gpointer data) { | |
96 GtkWidget* checkbox = CreateCheckButtonWithWrappedLabel(string_id); | |
97 gtk_box_pack_start(GTK_BOX(container), checkbox, FALSE, FALSE, 0); | |
98 g_signal_connect(checkbox, "toggled", handler, data); | |
99 | |
100 return checkbox; | |
101 } | |
102 | |
103 // Don't let the widget handle scroll events. Instead, pass it on to the | |
104 // parent widget. | |
105 gboolean PassScrollToParent(GtkWidget* widget, GdkEvent* event, | |
106 gpointer unused) { | |
107 if (widget->parent) | |
108 gtk_propagate_event(widget->parent, event); | |
109 | |
110 return TRUE; | |
111 } | |
112 | |
113 // Recursively search for a combo box among the children of |widget|. | |
114 void SearchForComboBox(GtkWidget* widget, gpointer data) { | |
115 if (GTK_IS_COMBO_BOX(widget)) { | |
116 *reinterpret_cast<GtkWidget**>(data) = widget; | |
117 } else if (GTK_IS_CONTAINER(widget)) { | |
118 gtk_container_foreach(GTK_CONTAINER(widget), SearchForComboBox, data); | |
119 } | |
120 } | |
121 | |
122 // Letting the combo boxes in the advanced options page handle scroll events is | |
123 // annoying because they fight with the scrolled window. Also, | |
124 // GtkFileChooserButton is buggy in that if you scroll on it very quickly it | |
125 // spews Gtk-WARNINGs, which causes us to crash in debug. This function disables | |
126 // scrolling for the combo box in |widget| (the first one it finds in a DFS). | |
127 void DisableScrolling(GtkWidget* widget) { | |
128 gpointer combo_box_ptr = NULL; | |
129 SearchForComboBox(widget, &combo_box_ptr); | |
130 | |
131 if (!combo_box_ptr) { | |
132 NOTREACHED() << " Did not find a combo box in this widget."; | |
133 return; | |
134 } | |
135 | |
136 g_signal_connect(GTK_WIDGET(combo_box_ptr), "scroll-event", | |
137 G_CALLBACK(PassScrollToParent), NULL); | |
138 } | |
139 | |
140 } // anonymous namespace | |
141 | |
142 | |
143 /////////////////////////////////////////////////////////////////////////////// | |
144 // DownloadSection | |
145 | |
146 class DownloadSection : public OptionsPageBase { | |
147 public: | |
148 explicit DownloadSection(Profile* profile); | |
149 virtual ~DownloadSection() {} | |
150 | |
151 GtkWidget* get_page_widget() const { | |
152 return page_; | |
153 } | |
154 | |
155 private: | |
156 // Overridden from OptionsPageBase. | |
157 virtual void NotifyPrefChanged(const std::string* pref_name); | |
158 | |
159 // Helper function for reacting to managed prefs. | |
160 void UpdateWidgetsForManagedPrefs(); | |
161 | |
162 // Callbacks for the widgets. | |
163 static void OnDownloadLocationChanged(GtkFileChooser* widget, | |
164 DownloadSection* section); | |
165 static void OnDownloadAskForSaveLocationChanged(GtkWidget* widget, | |
166 DownloadSection* section); | |
167 static void OnResetFileHandlersClicked(GtkButton *button, | |
168 DownloadSection* section); | |
169 | |
170 // The widgets for the download options. | |
171 GtkWidget* download_location_button_; | |
172 GtkWidget* download_ask_for_save_location_checkbox_; | |
173 GtkWidget* reset_file_handlers_label_; | |
174 GtkWidget* reset_file_handlers_button_; | |
175 | |
176 // The widget containing the options for this section. | |
177 GtkWidget* page_; | |
178 | |
179 // Pref members. | |
180 FilePathPrefMember default_download_location_; | |
181 BooleanPrefMember ask_for_save_location_; | |
182 StringPrefMember auto_open_files_; | |
183 | |
184 // Flag to ignore gtk callbacks while we are loading prefs, to avoid | |
185 // then turning around and saving them again. | |
186 bool pref_changing_; | |
187 | |
188 DISALLOW_COPY_AND_ASSIGN(DownloadSection); | |
189 }; | |
190 | |
191 DownloadSection::DownloadSection(Profile* profile) | |
192 : OptionsPageBase(profile), | |
193 pref_changing_(true) { | |
194 page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
195 | |
196 // Download location options. | |
197 download_location_button_ = gtk_file_chooser_button_new( | |
198 l10n_util::GetStringUTF8( | |
199 IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_WINDOW_TITLE).c_str(), | |
200 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); | |
201 g_signal_connect(download_location_button_, "selection-changed", | |
202 G_CALLBACK(OnDownloadLocationChanged), this); | |
203 DisableScrolling(download_location_button_); | |
204 | |
205 // Add the default download path to the list of shortcuts in the selector. | |
206 FilePath default_download_path; | |
207 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, | |
208 &default_download_path)) { | |
209 NOTREACHED(); | |
210 } else { | |
211 if (!gtk_file_chooser_add_shortcut_folder( | |
212 GTK_FILE_CHOOSER(download_location_button_), | |
213 default_download_path.value().c_str(), | |
214 NULL)) { | |
215 NOTREACHED(); | |
216 } | |
217 } | |
218 | |
219 GtkWidget* download_location_control = gtk_util::CreateLabeledControlsGroup( | |
220 NULL, | |
221 l10n_util::GetStringUTF8( | |
222 IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_TITLE).c_str(), | |
223 download_location_button_, | |
224 NULL); | |
225 gtk_box_pack_start(GTK_BOX(page_), download_location_control, | |
226 FALSE, FALSE, 0); | |
227 | |
228 download_ask_for_save_location_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
229 IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION); | |
230 gtk_box_pack_start(GTK_BOX(page_), download_ask_for_save_location_checkbox_, | |
231 FALSE, FALSE, 0); | |
232 g_signal_connect(download_ask_for_save_location_checkbox_, "clicked", | |
233 G_CALLBACK(OnDownloadAskForSaveLocationChanged), this); | |
234 | |
235 // Option for resetting file handlers. | |
236 reset_file_handlers_label_ = CreateWrappedLabel( | |
237 IDS_OPTIONS_AUTOOPENFILETYPES_INFO); | |
238 gtk_misc_set_alignment(GTK_MISC(reset_file_handlers_label_), 0, 0); | |
239 gtk_box_pack_start(GTK_BOX(page_), reset_file_handlers_label_, | |
240 FALSE, FALSE, 0); | |
241 | |
242 reset_file_handlers_button_ = gtk_button_new_with_label( | |
243 l10n_util::GetStringUTF8( | |
244 IDS_OPTIONS_AUTOOPENFILETYPES_RESETTODEFAULT).c_str()); | |
245 g_signal_connect(reset_file_handlers_button_, "clicked", | |
246 G_CALLBACK(OnResetFileHandlersClicked), this); | |
247 // Stick it in an hbox so it doesn't expand to the whole width. | |
248 GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0); | |
249 gtk_box_pack_start(GTK_BOX(button_hbox), | |
250 reset_file_handlers_button_, | |
251 FALSE, FALSE, 0); | |
252 gtk_box_pack_start(GTK_BOX(page_), | |
253 gtk_util::IndentWidget(button_hbox), | |
254 FALSE, FALSE, 0); | |
255 | |
256 // Init prefs watchers. | |
257 default_download_location_.Init(prefs::kDownloadDefaultDirectory, | |
258 profile->GetPrefs(), this); | |
259 ask_for_save_location_.Init(prefs::kPromptForDownload, | |
260 profile->GetPrefs(), this); | |
261 auto_open_files_.Init(prefs::kDownloadExtensionsToOpen, profile->GetPrefs(), | |
262 this); | |
263 | |
264 NotifyPrefChanged(NULL); | |
265 } | |
266 | |
267 void DownloadSection::NotifyPrefChanged(const std::string* pref_name) { | |
268 pref_changing_ = true; | |
269 if (!pref_name || *pref_name == prefs::kDownloadDefaultDirectory) { | |
270 gtk_file_chooser_set_current_folder( | |
271 GTK_FILE_CHOOSER(download_location_button_), | |
272 default_download_location_.GetValue().value().c_str()); | |
273 } | |
274 | |
275 if (!pref_name || *pref_name == prefs::kPromptForDownload) { | |
276 gtk_toggle_button_set_active( | |
277 GTK_TOGGLE_BUTTON(download_ask_for_save_location_checkbox_), | |
278 ask_for_save_location_.GetValue()); | |
279 } | |
280 | |
281 if (!pref_name || *pref_name == prefs::kDownloadExtensionsToOpen) { | |
282 DownloadPrefs* prefs = profile()->GetDownloadManager()->download_prefs(); | |
283 bool enabled = prefs->IsAutoOpenUsed(); | |
284 gtk_widget_set_sensitive(reset_file_handlers_label_, enabled); | |
285 gtk_widget_set_sensitive(reset_file_handlers_button_, enabled); | |
286 } | |
287 UpdateWidgetsForManagedPrefs(); | |
288 pref_changing_ = false; | |
289 } | |
290 | |
291 void DownloadSection::UpdateWidgetsForManagedPrefs() { | |
292 const bool enabled = !default_download_location_.IsManaged(); | |
293 gtk_widget_set_sensitive(download_location_button_, enabled); | |
294 gtk_widget_set_sensitive(download_ask_for_save_location_checkbox_, enabled); | |
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 DISALLOW_COPY_AND_ASSIGN(TranslateSection); | |
565 }; | |
566 | |
567 TranslateSection::TranslateSection(Profile* profile) | |
568 : OptionsPageBase(profile), | |
569 pref_changing_(true) { | |
570 page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
571 | |
572 translate_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
573 IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE); | |
574 gtk_box_pack_start(GTK_BOX(page_), translate_checkbox_, | |
575 FALSE, FALSE, 0); | |
576 g_signal_connect(translate_checkbox_, "clicked", | |
577 G_CALLBACK(OnTranslateClickedThunk), this); | |
578 | |
579 // Init member prefs so we can update the controls if prefs change. | |
580 enable_translate_.Init(prefs::kEnableTranslate, profile->GetPrefs(), this); | |
581 | |
582 NotifyPrefChanged(NULL); | |
583 } | |
584 | |
585 void TranslateSection::NotifyPrefChanged(const std::string* pref_name) { | |
586 pref_changing_ = true; | |
587 if (!pref_name || *pref_name == prefs::kEnableTranslate) { | |
588 gtk_toggle_button_set_active( | |
589 GTK_TOGGLE_BUTTON(translate_checkbox_), enable_translate_.GetValue()); | |
590 } | |
591 pref_changing_ = false; | |
592 } | |
593 | |
594 void TranslateSection::OnTranslateClicked(GtkWidget* widget) { | |
595 if (pref_changing_) | |
596 return; | |
597 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
598 UserMetricsRecordAction( | |
599 enabled ? | |
600 UserMetricsAction("Options_Translate_Enable") : | |
601 UserMetricsAction("Options_Translate_Disable"), | |
602 profile()->GetPrefs()); | |
603 enable_translate_.SetValue(enabled); | |
604 } | |
605 | |
606 /////////////////////////////////////////////////////////////////////////////// | |
607 // PrivacySection | |
608 | |
609 class PrivacySection : public OptionsPageBase { | |
610 public: | |
611 explicit PrivacySection(Profile* profile); | |
612 virtual ~PrivacySection() {} | |
613 | |
614 GtkWidget* get_page_widget() const { | |
615 return page_; | |
616 } | |
617 | |
618 private: | |
619 // Overridden from OptionsPageBase. | |
620 virtual void NotifyPrefChanged(const std::string* pref_name); | |
621 | |
622 // Try to make the the crash stats consent and the metrics upload | |
623 // permission match the |reporting_enabled_checkbox_|. | |
624 void ResolveMetricsReportingEnabled(); | |
625 | |
626 // The callback functions for the options widgets. | |
627 static void OnContentSettingsClicked(GtkButton* button, | |
628 PrivacySection* privacy_section); | |
629 static void OnClearBrowsingDataButtonClicked(GtkButton* widget, | |
630 PrivacySection* page); | |
631 static void OnLearnMoreLinkClicked(GtkButton *button, | |
632 PrivacySection* privacy_section); | |
633 static void OnEnableLinkDoctorChange(GtkWidget* widget, | |
634 PrivacySection* options_window); | |
635 static void OnEnableSuggestChange(GtkWidget* widget, | |
636 PrivacySection* options_window); | |
637 static void OnDNSPrefetchingChange(GtkWidget* widget, | |
638 PrivacySection* options_window); | |
639 static void OnSafeBrowsingChange(GtkWidget* widget, | |
640 PrivacySection* options_window); | |
641 static void OnLoggingChange(GtkWidget* widget, | |
642 PrivacySection* options_window); | |
643 | |
644 // The widget containing the options for this section. | |
645 GtkWidget* page_; | |
646 | |
647 // The widgets for the privacy options. | |
648 GtkWidget* enable_link_doctor_checkbox_; | |
649 GtkWidget* enable_suggest_checkbox_; | |
650 GtkWidget* enable_dns_prefetching_checkbox_; | |
651 GtkWidget* enable_safe_browsing_checkbox_; | |
652 #if defined(GOOGLE_CHROME_BUILD) | |
653 GtkWidget* reporting_enabled_checkbox_; | |
654 #endif | |
655 | |
656 // Preferences for this section: | |
657 BooleanPrefMember alternate_error_pages_; | |
658 BooleanPrefMember use_suggest_; | |
659 BooleanPrefMember dns_prefetch_enabled_; | |
660 BooleanPrefMember safe_browsing_; | |
661 BooleanPrefMember enable_metrics_recording_; | |
662 | |
663 // Flag to ignore gtk callbacks while we are loading prefs, to avoid | |
664 // then turning around and saving them again. | |
665 bool pref_changing_; | |
666 | |
667 DISALLOW_COPY_AND_ASSIGN(PrivacySection); | |
668 }; | |
669 | |
670 PrivacySection::PrivacySection(Profile* profile) | |
671 : OptionsPageBase(profile), | |
672 pref_changing_(true) { | |
673 page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
674 | |
675 GtkWidget* content_button = gtk_button_new_with_label( | |
676 l10n_util::GetStringUTF8( | |
677 IDS_OPTIONS_PRIVACY_CONTENT_SETTINGS_BUTTON).c_str()); | |
678 g_signal_connect(content_button, "clicked", | |
679 G_CALLBACK(OnContentSettingsClicked), this); | |
680 | |
681 GtkWidget* clear_data_button = gtk_button_new_with_label( | |
682 l10n_util::GetStringUTF8(IDS_OPTIONS_PRIVACY_CLEAR_DATA_BUTTON).c_str()); | |
683 g_signal_connect(clear_data_button, "clicked", | |
684 G_CALLBACK(OnClearBrowsingDataButtonClicked), this); | |
685 | |
686 // Stick it in an hbox so it doesn't expand to the whole width. | |
687 GtkWidget* button_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing); | |
688 gtk_box_pack_start(GTK_BOX(button_hbox), content_button, FALSE, FALSE, 0); | |
689 gtk_box_pack_start(GTK_BOX(button_hbox), clear_data_button, FALSE, FALSE, 0); | |
690 gtk_box_pack_start(GTK_BOX(page_), gtk_util::IndentWidget(button_hbox), | |
691 FALSE, FALSE, 0); | |
692 | |
693 GtkWidget* section_description_label = CreateWrappedLabel( | |
694 IDS_OPTIONS_DISABLE_SERVICES); | |
695 gtk_misc_set_alignment(GTK_MISC(section_description_label), 0, 0); | |
696 gtk_box_pack_start(GTK_BOX(page_), section_description_label, | |
697 FALSE, FALSE, 0); | |
698 | |
699 GtkWidget* learn_more_link = gtk_chrome_link_button_new( | |
700 l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str()); | |
701 // Stick it in an hbox so it doesn't expand to the whole width. | |
702 GtkWidget* learn_more_hbox = gtk_hbox_new(FALSE, 0); | |
703 gtk_box_pack_start(GTK_BOX(learn_more_hbox), learn_more_link, | |
704 FALSE, FALSE, 0); | |
705 gtk_box_pack_start(GTK_BOX(page_), learn_more_hbox, | |
706 FALSE, FALSE, 0); | |
707 g_signal_connect(learn_more_link, "clicked", | |
708 G_CALLBACK(OnLearnMoreLinkClicked), this); | |
709 | |
710 enable_link_doctor_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
711 IDS_OPTIONS_LINKDOCTOR_PREF); | |
712 gtk_box_pack_start(GTK_BOX(page_), enable_link_doctor_checkbox_, | |
713 FALSE, FALSE, 0); | |
714 g_signal_connect(enable_link_doctor_checkbox_, "clicked", | |
715 G_CALLBACK(OnEnableLinkDoctorChange), this); | |
716 | |
717 enable_suggest_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
718 IDS_OPTIONS_SUGGEST_PREF); | |
719 gtk_box_pack_start(GTK_BOX(page_), enable_suggest_checkbox_, | |
720 FALSE, FALSE, 0); | |
721 g_signal_connect(enable_suggest_checkbox_, "clicked", | |
722 G_CALLBACK(OnEnableSuggestChange), this); | |
723 | |
724 enable_dns_prefetching_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
725 IDS_NETWORK_DNS_PREFETCH_ENABLED_DESCRIPTION); | |
726 gtk_box_pack_start(GTK_BOX(page_), enable_dns_prefetching_checkbox_, | |
727 FALSE, FALSE, 0); | |
728 g_signal_connect(enable_dns_prefetching_checkbox_, "clicked", | |
729 G_CALLBACK(OnDNSPrefetchingChange), this); | |
730 | |
731 enable_safe_browsing_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
732 IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION); | |
733 gtk_box_pack_start(GTK_BOX(page_), enable_safe_browsing_checkbox_, | |
734 FALSE, FALSE, 0); | |
735 g_signal_connect(enable_safe_browsing_checkbox_, "clicked", | |
736 G_CALLBACK(OnSafeBrowsingChange), this); | |
737 | |
738 #if defined(GOOGLE_CHROME_BUILD) | |
739 reporting_enabled_checkbox_ = CreateCheckButtonWithWrappedLabel( | |
740 IDS_OPTIONS_ENABLE_LOGGING); | |
741 gtk_box_pack_start(GTK_BOX(page_), reporting_enabled_checkbox_, | |
742 FALSE, FALSE, 0); | |
743 g_signal_connect(reporting_enabled_checkbox_, "clicked", | |
744 G_CALLBACK(OnLoggingChange), this); | |
745 #endif | |
746 | |
747 // Init member prefs so we can update the controls if prefs change. | |
748 alternate_error_pages_.Init(prefs::kAlternateErrorPagesEnabled, | |
749 profile->GetPrefs(), this); | |
750 use_suggest_.Init(prefs::kSearchSuggestEnabled, | |
751 profile->GetPrefs(), this); | |
752 dns_prefetch_enabled_.Init(prefs::kDnsPrefetchingEnabled, | |
753 profile->GetPrefs(), this); | |
754 safe_browsing_.Init(prefs::kSafeBrowsingEnabled, profile->GetPrefs(), this); | |
755 enable_metrics_recording_.Init(prefs::kMetricsReportingEnabled, | |
756 g_browser_process->local_state(), this); | |
757 NotifyPrefChanged(NULL); | |
758 } | |
759 | |
760 // static | |
761 void PrivacySection::OnContentSettingsClicked(GtkButton* button, | |
762 PrivacySection* privacy_section) { | |
763 ContentSettingsWindowGtk::Show( | |
764 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))), | |
765 CONTENT_SETTINGS_TYPE_DEFAULT, | |
766 privacy_section->profile()); | |
767 } | |
768 | |
769 // static | |
770 void PrivacySection::OnClearBrowsingDataButtonClicked(GtkButton* widget, | |
771 PrivacySection* section) { | |
772 ClearBrowsingDataDialogGtk::Show( | |
773 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(widget))), | |
774 section->profile()); | |
775 } | |
776 | |
777 // static | |
778 void PrivacySection::OnLearnMoreLinkClicked(GtkButton *button, | |
779 PrivacySection* privacy_section) { | |
780 GURL url = google_util::AppendGoogleLocaleParam( | |
781 GURL(chrome::kPrivacyLearnMoreURL)); | |
782 browser::ShowOptionsURL(privacy_section->profile(), url); | |
783 } | |
784 | |
785 // static | |
786 void PrivacySection::OnEnableLinkDoctorChange(GtkWidget* widget, | |
787 PrivacySection* privacy_section) { | |
788 if (privacy_section->pref_changing_) | |
789 return; | |
790 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
791 privacy_section->UserMetricsRecordAction( | |
792 enabled ? | |
793 UserMetricsAction("Options_LinkDoctorCheckbox_Enable") : | |
794 UserMetricsAction("Options_LinkDoctorCheckbox_Disable"), | |
795 privacy_section->profile()->GetPrefs()); | |
796 privacy_section->alternate_error_pages_.SetValue(enabled); | |
797 } | |
798 | |
799 // static | |
800 void PrivacySection::OnEnableSuggestChange(GtkWidget* widget, | |
801 PrivacySection* privacy_section) { | |
802 if (privacy_section->pref_changing_) | |
803 return; | |
804 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
805 privacy_section->UserMetricsRecordAction( | |
806 enabled ? | |
807 UserMetricsAction("Options_UseSuggestCheckbox_Enable") : | |
808 UserMetricsAction("Options_UseSuggestCheckbox_Disable"), | |
809 privacy_section->profile()->GetPrefs()); | |
810 privacy_section->use_suggest_.SetValue(enabled); | |
811 } | |
812 | |
813 // static | |
814 void PrivacySection::OnDNSPrefetchingChange(GtkWidget* widget, | |
815 PrivacySection* privacy_section) { | |
816 if (privacy_section->pref_changing_) | |
817 return; | |
818 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
819 privacy_section->UserMetricsRecordAction( | |
820 enabled ? | |
821 UserMetricsAction("Options_DnsPrefetchCheckbox_Enable") : | |
822 UserMetricsAction("Options_DnsPrefetchCheckbox_Disable"), | |
823 privacy_section->profile()->GetPrefs()); | |
824 privacy_section->dns_prefetch_enabled_.SetValue(enabled); | |
825 } | |
826 | |
827 // static | |
828 void PrivacySection::OnSafeBrowsingChange(GtkWidget* widget, | |
829 PrivacySection* privacy_section) { | |
830 if (privacy_section->pref_changing_) | |
831 return; | |
832 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
833 privacy_section->UserMetricsRecordAction( | |
834 enabled ? | |
835 UserMetricsAction("Options_SafeBrowsingCheckbox_Enable") : | |
836 UserMetricsAction("Options_SafeBrowsingCheckbox_Disable"), | |
837 privacy_section->profile()->GetPrefs()); | |
838 privacy_section->safe_browsing_.SetValue(enabled); | |
839 SafeBrowsingService* safe_browsing_service = | |
840 g_browser_process->resource_dispatcher_host()->safe_browsing_service(); | |
841 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | |
842 safe_browsing_service, &SafeBrowsingService::OnEnable, enabled)); | |
843 } | |
844 | |
845 // static | |
846 void PrivacySection::OnLoggingChange(GtkWidget* widget, | |
847 PrivacySection* privacy_section) { | |
848 if (privacy_section->pref_changing_) | |
849 return; | |
850 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
851 privacy_section->UserMetricsRecordAction( | |
852 enabled ? | |
853 UserMetricsAction("Options_MetricsReportingCheckbox_Enable") : | |
854 UserMetricsAction("Options_MetricsReportingCheckbox_Disable"), | |
855 privacy_section->profile()->GetPrefs()); | |
856 // Prevent us from being called again by ResolveMetricsReportingEnabled | |
857 // resetting the checkbox if there was a problem. | |
858 g_signal_handlers_block_by_func(widget, | |
859 reinterpret_cast<gpointer>(OnLoggingChange), | |
860 privacy_section); | |
861 privacy_section->ResolveMetricsReportingEnabled(); | |
862 g_signal_handlers_unblock_by_func(widget, | |
863 reinterpret_cast<gpointer>(OnLoggingChange), | |
864 privacy_section); | |
865 privacy_section->enable_metrics_recording_.SetValue(enabled); | |
866 } | |
867 | |
868 void PrivacySection::NotifyPrefChanged(const std::string* pref_name) { | |
869 pref_changing_ = true; | |
870 if (!pref_name || *pref_name == prefs::kAlternateErrorPagesEnabled) { | |
871 gtk_widget_set_sensitive( | |
872 GTK_WIDGET(enable_link_doctor_checkbox_), | |
873 !alternate_error_pages_.IsManaged()); | |
874 gtk_toggle_button_set_active( | |
875 GTK_TOGGLE_BUTTON(enable_link_doctor_checkbox_), | |
876 alternate_error_pages_.GetValue()); | |
877 } | |
878 if (!pref_name || *pref_name == prefs::kSearchSuggestEnabled) { | |
879 gtk_widget_set_sensitive( | |
880 GTK_WIDGET(enable_suggest_checkbox_), | |
881 !use_suggest_.IsManaged()); | |
882 gtk_toggle_button_set_active( | |
883 GTK_TOGGLE_BUTTON(enable_suggest_checkbox_), | |
884 use_suggest_.GetValue()); | |
885 } | |
886 if (!pref_name || *pref_name == prefs::kDnsPrefetchingEnabled) { | |
887 gtk_widget_set_sensitive( | |
888 GTK_WIDGET(enable_dns_prefetching_checkbox_), | |
889 !dns_prefetch_enabled_.IsManaged()); | |
890 bool enabled = dns_prefetch_enabled_.GetValue(); | |
891 gtk_toggle_button_set_active( | |
892 GTK_TOGGLE_BUTTON(enable_dns_prefetching_checkbox_), enabled); | |
893 } | |
894 if (!pref_name || *pref_name == prefs::kSafeBrowsingEnabled) { | |
895 gtk_widget_set_sensitive( | |
896 GTK_WIDGET(enable_safe_browsing_checkbox_), | |
897 !safe_browsing_.IsManaged()); | |
898 gtk_toggle_button_set_active( | |
899 GTK_TOGGLE_BUTTON(enable_safe_browsing_checkbox_), | |
900 safe_browsing_.GetValue()); | |
901 } | |
902 #if defined(GOOGLE_CHROME_BUILD) | |
903 if (!pref_name || *pref_name == prefs::kMetricsReportingEnabled) { | |
904 gtk_widget_set_sensitive( | |
905 GTK_WIDGET(reporting_enabled_checkbox_), | |
906 !enable_metrics_recording_.IsManaged()); | |
907 gtk_toggle_button_set_active( | |
908 GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_), | |
909 enable_metrics_recording_.GetValue()); | |
910 ResolveMetricsReportingEnabled(); | |
911 } | |
912 #endif | |
913 pref_changing_ = false; | |
914 } | |
915 | |
916 void PrivacySection::ResolveMetricsReportingEnabled() { | |
917 #if defined(GOOGLE_CHROME_BUILD) | |
918 bool enabled = gtk_toggle_button_get_active( | |
919 GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_)); | |
920 | |
921 enabled = OptionsUtil::ResolveMetricsReportingEnabled(enabled); | |
922 | |
923 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_), | |
924 enabled); | |
925 #endif | |
926 } | |
927 | |
928 /////////////////////////////////////////////////////////////////////////////// | |
929 // SecuritySection | |
930 | |
931 class SecuritySection : public OptionsPageBase { | |
932 public: | |
933 explicit SecuritySection(Profile* profile); | |
934 virtual ~SecuritySection() {} | |
935 | |
936 GtkWidget* get_page_widget() const { | |
937 return page_; | |
938 } | |
939 | |
940 private: | |
941 // Overridden from OptionsPageBase. | |
942 virtual void NotifyPrefChanged(const std::string* pref_name); | |
943 | |
944 // The callback functions for the options widgets. | |
945 static void OnManageCertificatesClicked(GtkButton* button, | |
946 SecuritySection* section); | |
947 static void OnRevCheckingEnabledToggled(GtkToggleButton* togglebutton, | |
948 SecuritySection* section); | |
949 static void OnSSL3EnabledToggled(GtkToggleButton* togglebutton, | |
950 SecuritySection* section); | |
951 static void OnTLS1EnabledToggled(GtkToggleButton* togglebutton, | |
952 SecuritySection* section); | |
953 | |
954 // The widget containing the options for this section. | |
955 GtkWidget* page_; | |
956 GtkWidget* rev_checking_enabled_checkbox_; | |
957 GtkWidget* ssl3_enabled_checkbox_; | |
958 GtkWidget* tls1_enabled_checkbox_; | |
959 | |
960 // SSLConfigService prefs. | |
961 BooleanPrefMember rev_checking_enabled_; | |
962 BooleanPrefMember ssl3_enabled_; | |
963 BooleanPrefMember tls1_enabled_; | |
964 | |
965 // Flag to ignore gtk callbacks while we are loading prefs, to avoid | |
966 // then turning around and saving them again. | |
967 bool pref_changing_; | |
968 | |
969 DISALLOW_COPY_AND_ASSIGN(SecuritySection); | |
970 }; | |
971 | |
972 SecuritySection::SecuritySection(Profile* profile) | |
973 : OptionsPageBase(profile), | |
974 pref_changing_(true) { | |
975 page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
976 | |
977 GtkWidget* manage_certificates_label = CreateWrappedLabel( | |
978 IDS_OPTIONS_CERTIFICATES_LABEL); | |
979 gtk_misc_set_alignment(GTK_MISC(manage_certificates_label), 0, 0); | |
980 gtk_box_pack_start(GTK_BOX(page_), manage_certificates_label, | |
981 FALSE, FALSE, 0); | |
982 | |
983 // TODO(mattm): change this to a button to launch the system certificate | |
984 // manager, when one exists. | |
985 GtkWidget* manage_certificates_link = gtk_chrome_link_button_new( | |
986 l10n_util::GetStringUTF8(IDS_OPTIONS_CERTIFICATES_MANAGE_BUTTON).c_str()); | |
987 // Stick it in an hbox so it doesn't expand to the whole width. | |
988 GtkWidget* manage_certificates_hbox = gtk_hbox_new(FALSE, 0); | |
989 gtk_box_pack_start(GTK_BOX(manage_certificates_hbox), | |
990 manage_certificates_link, FALSE, FALSE, 0); | |
991 gtk_box_pack_start(GTK_BOX(page_), | |
992 gtk_util::IndentWidget(manage_certificates_hbox), | |
993 FALSE, FALSE, 0); | |
994 g_signal_connect(manage_certificates_link, "clicked", | |
995 G_CALLBACK(OnManageCertificatesClicked), this); | |
996 | |
997 // TODO(mattm): should have a description label here and have the checkboxes | |
998 // indented, but IDS_OPTIONS_SSL_GROUP_DESCRIPTION isn't appropriate and | |
999 // didn't think of adding a Linux specific one before the string freeze. | |
1000 rev_checking_enabled_checkbox_ = AddCheckButtonWithWrappedLabel( | |
1001 IDS_OPTIONS_SSL_CHECKREVOCATION, page_, | |
1002 G_CALLBACK(OnRevCheckingEnabledToggled), this); | |
1003 ssl3_enabled_checkbox_ = AddCheckButtonWithWrappedLabel( | |
1004 IDS_OPTIONS_SSL_USESSL3, page_, G_CALLBACK(OnSSL3EnabledToggled), this); | |
1005 tls1_enabled_checkbox_ = AddCheckButtonWithWrappedLabel( | |
1006 IDS_OPTIONS_SSL_USETLS1, page_, G_CALLBACK(OnTLS1EnabledToggled), this); | |
1007 | |
1008 rev_checking_enabled_.Init(prefs::kCertRevocationCheckingEnabled, | |
1009 profile->GetPrefs(), this); | |
1010 ssl3_enabled_.Init(prefs::kSSL3Enabled, profile->GetPrefs(), this); | |
1011 tls1_enabled_.Init(prefs::kTLS1Enabled, profile->GetPrefs(), this); | |
1012 | |
1013 NotifyPrefChanged(NULL); | |
1014 } | |
1015 | |
1016 void SecuritySection::NotifyPrefChanged(const std::string* pref_name) { | |
1017 pref_changing_ = true; | |
1018 if (!pref_name || *pref_name == prefs::kCertRevocationCheckingEnabled) { | |
1019 gtk_toggle_button_set_active( | |
1020 GTK_TOGGLE_BUTTON(rev_checking_enabled_checkbox_), | |
1021 rev_checking_enabled_.GetValue()); | |
1022 } | |
1023 if (!pref_name || *pref_name == prefs::kSSL3Enabled) { | |
1024 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ssl3_enabled_checkbox_), | |
1025 ssl3_enabled_.GetValue()); | |
1026 } | |
1027 if (!pref_name || *pref_name == prefs::kTLS1Enabled) { | |
1028 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tls1_enabled_checkbox_), | |
1029 tls1_enabled_.GetValue()); | |
1030 } | |
1031 pref_changing_ = false; | |
1032 } | |
1033 | |
1034 | |
1035 // static | |
1036 void SecuritySection::OnManageCertificatesClicked(GtkButton* button, | |
1037 SecuritySection* section) { | |
1038 browser::ShowOptionsURL(section->profile(), | |
1039 GURL(kLinuxCertificatesConfigUrl)); | |
1040 } | |
1041 | |
1042 // static | |
1043 void SecuritySection::OnRevCheckingEnabledToggled(GtkToggleButton* togglebutton, | |
1044 SecuritySection* section) { | |
1045 if (section->pref_changing_) | |
1046 return; | |
1047 | |
1048 bool enabled = gtk_toggle_button_get_active(togglebutton); | |
1049 if (enabled) { | |
1050 section->UserMetricsRecordAction( | |
1051 UserMetricsAction("Options_CheckCertRevocation_Enable"), | |
1052 NULL); | |
1053 } else { | |
1054 section->UserMetricsRecordAction( | |
1055 UserMetricsAction("Options_CheckCertRevocation_Disable"), | |
1056 NULL); | |
1057 } | |
1058 section->rev_checking_enabled_.SetValue(enabled); | |
1059 } | |
1060 | |
1061 // static | |
1062 void SecuritySection::OnSSL3EnabledToggled(GtkToggleButton* togglebutton, | |
1063 SecuritySection* section) { | |
1064 if (section->pref_changing_) | |
1065 return; | |
1066 | |
1067 bool enabled = gtk_toggle_button_get_active(togglebutton); | |
1068 if (enabled) { | |
1069 section->UserMetricsRecordAction(UserMetricsAction("Options_SSL3_Enable"), | |
1070 NULL); | |
1071 } else { | |
1072 section->UserMetricsRecordAction(UserMetricsAction("Options_SSL3_Disable"), | |
1073 NULL); | |
1074 } | |
1075 section->ssl3_enabled_.SetValue(enabled); | |
1076 } | |
1077 | |
1078 // static | |
1079 void SecuritySection::OnTLS1EnabledToggled(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(UserMetricsAction("Options_TLS1_Enable"), | |
1087 NULL); | |
1088 } else { | |
1089 section->UserMetricsRecordAction(UserMetricsAction("Options_TLS1_Disable"), | |
1090 NULL); | |
1091 } | |
1092 section->tls1_enabled_.SetValue(enabled); | |
1093 } | |
1094 | |
1095 /////////////////////////////////////////////////////////////////////////////// | |
1096 // WebContentSection | |
1097 | |
1098 class WebContentSection : public OptionsPageBase { | |
1099 public: | |
1100 explicit WebContentSection(Profile* profile); | |
1101 virtual ~WebContentSection() {} | |
1102 | |
1103 GtkWidget* get_page_widget() const { | |
1104 return page_; | |
1105 } | |
1106 | |
1107 private: | |
1108 // The callback functions for the options widgets. | |
1109 static void OnFontsAndLanguagesButtonClicked(GtkButton *button, | |
1110 WebContentSection* section); | |
1111 | |
1112 // The widget containing the options for this section. | |
1113 GtkWidget* page_; | |
1114 | |
1115 DISALLOW_COPY_AND_ASSIGN(WebContentSection); | |
1116 }; | |
1117 | |
1118 WebContentSection::WebContentSection(Profile* profile) | |
1119 : OptionsPageBase(profile) { | |
1120 page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
1121 | |
1122 GtkWidget* fonts_and_languages_label = CreateWrappedLabel( | |
1123 IDS_OPTIONS_FONTSETTINGS_INFO); | |
1124 gtk_misc_set_alignment(GTK_MISC(fonts_and_languages_label), 0, 0); | |
1125 gtk_box_pack_start(GTK_BOX(page_), fonts_and_languages_label, | |
1126 FALSE, FALSE, 0); | |
1127 | |
1128 GtkWidget* fonts_and_languages_button = gtk_button_new_with_label( | |
1129 l10n_util::GetStringUTF8( | |
1130 IDS_OPTIONS_FONTSETTINGS_CONFIGUREFONTS_BUTTON).c_str()); | |
1131 g_signal_connect(fonts_and_languages_button, "clicked", | |
1132 G_CALLBACK(OnFontsAndLanguagesButtonClicked), this); | |
1133 // Stick it in an hbox so it doesn't expand to the whole width. | |
1134 GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0); | |
1135 gtk_box_pack_start(GTK_BOX(button_hbox), | |
1136 fonts_and_languages_button, | |
1137 FALSE, FALSE, 0); | |
1138 gtk_box_pack_start(GTK_BOX(page_), | |
1139 gtk_util::IndentWidget(button_hbox), | |
1140 FALSE, FALSE, 0); | |
1141 | |
1142 // TODO(mattm): gears options would go here if we supported gears | |
1143 } | |
1144 | |
1145 // static | |
1146 void WebContentSection::OnFontsAndLanguagesButtonClicked( | |
1147 GtkButton *button, WebContentSection* section) { | |
1148 ShowFontsLanguagesWindow(GTK_WINDOW(gtk_widget_get_toplevel(section->page_)), | |
1149 FONTS_ENCODING_PAGE, | |
1150 section->profile()); | |
1151 } | |
1152 | |
1153 /////////////////////////////////////////////////////////////////////////////// | |
1154 // AdvancedContentsGtk | |
1155 | |
1156 AdvancedContentsGtk::AdvancedContentsGtk(Profile* profile) | |
1157 : profile_(profile) { | |
1158 Init(); | |
1159 } | |
1160 | |
1161 AdvancedContentsGtk::~AdvancedContentsGtk() { | |
1162 } | |
1163 | |
1164 void AdvancedContentsGtk::Init() { | |
1165 scoped_ptr<OptionsLayoutBuilderGtk> | |
1166 options_builder(OptionsLayoutBuilderGtk::Create()); | |
1167 | |
1168 privacy_section_.reset(new PrivacySection(profile_)); | |
1169 options_builder->AddOptionGroup( | |
1170 l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY), | |
1171 privacy_section_->get_page_widget(), false); | |
1172 | |
1173 network_section_.reset(new NetworkSection(profile_)); | |
1174 options_builder->AddOptionGroup( | |
1175 l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_NETWORK), | |
1176 network_section_->get_page_widget(), false); | |
1177 | |
1178 translate_section_.reset(new TranslateSection(profile_)); | |
1179 options_builder->AddOptionGroup( | |
1180 l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_TRANSLATE), | |
1181 translate_section_->get_page_widget(), false); | |
1182 | |
1183 download_section_.reset(new DownloadSection(profile_)); | |
1184 options_builder->AddOptionGroup( | |
1185 l10n_util::GetStringUTF8(IDS_OPTIONS_DOWNLOADLOCATION_GROUP_NAME), | |
1186 download_section_->get_page_widget(), false); | |
1187 | |
1188 web_content_section_.reset(new WebContentSection(profile_)); | |
1189 options_builder->AddOptionGroup( | |
1190 l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_CONTENT), | |
1191 web_content_section_->get_page_widget(), false); | |
1192 | |
1193 security_section_.reset(new SecuritySection(profile_)); | |
1194 options_builder->AddOptionGroup( | |
1195 l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_SECURITY), | |
1196 security_section_->get_page_widget(), false); | |
1197 | |
1198 page_ = options_builder->get_page_widget(); | |
1199 } | |
OLD | NEW |