• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #if !defined(OS_CHROMEOS)
6 
7 #include "chrome/browser/ui/webui/options/advanced_options_utils.h"
8 
9 #include "base/environment.h"
10 #include "base/file_util.h"
11 #include "base/nix/xdg_util.h"
12 #include "base/process_util.h"
13 #include "base/string_tokenizer.h"
14 #include "chrome/browser/ui/browser_list.h"
15 #include "content/browser/browser_thread.h"
16 #include "content/browser/tab_contents/tab_contents.h"
17 #include "content/common/process_watcher.h"
18 #include "ui/base/gtk/gtk_signal.h"
19 
20 // Command used to configure GNOME proxy settings. The command was renamed
21 // in January 2009, so both are used to work on both old and new systems.
22 const char* kOldGNOMEProxyConfigCommand[] = {"gnome-network-preferences", NULL};
23 const char* kGNOMEProxyConfigCommand[] = {"gnome-network-properties", NULL};
24 // KDE3 and KDE4 are only slightly different, but incompatible. Go figure.
25 const char* kKDE3ProxyConfigCommand[] = {"kcmshell", "proxy", NULL};
26 const char* kKDE4ProxyConfigCommand[] = {"kcmshell4", "proxy", NULL};
27 
28 // The URL for Linux proxy configuration help when not running under a
29 // supported desktop environment.
30 const char kLinuxProxyConfigUrl[] = "about:linux-proxy-config";
31 
32 struct ProxyConfigCommand {
33   std::string binary;
34   const char** argv;
35 };
36 
37 namespace {
38 
39 // Search $PATH to find one of the commands. Store the full path to
40 // it in the |binary| field and the command array index in in |index|.
SearchPATH(ProxyConfigCommand * commands,size_t ncommands,size_t * index)41 bool SearchPATH(ProxyConfigCommand* commands, size_t ncommands, size_t* index) {
42   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
43   const char* path = getenv("PATH");
44   if (!path)
45     return false;
46   FilePath bin_path;
47   CStringTokenizer tk(path, path + strlen(path), ":");
48   // Search $PATH looking for the commands in order.
49   while (tk.GetNext()) {
50     for (size_t i = 0; i < ncommands; i++) {
51       bin_path = FilePath(tk.token()).Append(commands[i].argv[0]);
52       if (file_util::PathExists(bin_path)) {
53         commands[i].binary = bin_path.value();
54         if (index)
55           *index = i;
56         return true;
57       }
58     }
59   }
60   // Did not find any of the binaries in $PATH.
61   return false;
62 }
63 
64 // Show the proxy config URL in the given tab.
ShowLinuxProxyConfigUrl(TabContents * tab_contents)65 void ShowLinuxProxyConfigUrl(TabContents* tab_contents) {
66   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
67   scoped_ptr<base::Environment> env(base::Environment::Create());
68   const char* name = base::nix::GetDesktopEnvironmentName(env.get());
69   if (name)
70     LOG(ERROR) << "Could not find " << name << " network settings in $PATH";
71   tab_contents->OpenURL(GURL(kLinuxProxyConfigUrl), GURL(),
72                         NEW_FOREGROUND_TAB, PageTransition::LINK);
73 }
74 
75 // Start the given proxy configuration utility.
StartProxyConfigUtil(TabContents * tab_contents,const ProxyConfigCommand & command)76 void StartProxyConfigUtil(TabContents* tab_contents,
77                           const ProxyConfigCommand& command) {
78   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
79   std::vector<std::string> argv;
80   argv.push_back(command.binary);
81   for (size_t i = 1; command.argv[i]; i++)
82     argv.push_back(command.argv[i]);
83   base::file_handle_mapping_vector no_files;
84   base::ProcessHandle handle;
85   if (!base::LaunchApp(argv, no_files, false, &handle)) {
86     LOG(ERROR) << "StartProxyConfigUtil failed to start " << command.binary;
87     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
88         NewRunnableFunction(&ShowLinuxProxyConfigUrl, tab_contents));
89     return;
90   }
91   ProcessWatcher::EnsureProcessGetsReaped(handle);
92 }
93 
94 // Detect, and if possible, start the appropriate proxy config utility. On
95 // failure to do so, show the Linux proxy config URL in a new tab instead.
DetectAndStartProxyConfigUtil(TabContents * tab_contents)96 void DetectAndStartProxyConfigUtil(TabContents* tab_contents) {
97   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
98   scoped_ptr<base::Environment> env(base::Environment::Create());
99 
100   ProxyConfigCommand command;
101   bool found_command = false;
102   switch (base::nix::GetDesktopEnvironment(env.get())) {
103     case base::nix::DESKTOP_ENVIRONMENT_GNOME: {
104       size_t index;
105       ProxyConfigCommand commands[2];
106       commands[0].argv = kGNOMEProxyConfigCommand;
107       commands[1].argv = kOldGNOMEProxyConfigCommand;
108       found_command = SearchPATH(commands, 2, &index);
109       if (found_command)
110         command = commands[index];
111       break;
112     }
113 
114     case base::nix::DESKTOP_ENVIRONMENT_KDE3:
115       command.argv = kKDE3ProxyConfigCommand;
116       found_command = SearchPATH(&command, 1, NULL);
117       break;
118 
119     case base::nix::DESKTOP_ENVIRONMENT_KDE4:
120       command.argv = kKDE4ProxyConfigCommand;
121       found_command = SearchPATH(&command, 1, NULL);
122       break;
123 
124     case base::nix::DESKTOP_ENVIRONMENT_XFCE:
125     case base::nix::DESKTOP_ENVIRONMENT_OTHER:
126       break;
127   }
128 
129   if (found_command) {
130     StartProxyConfigUtil(tab_contents, command);
131   } else {
132     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
133         NewRunnableFunction(&ShowLinuxProxyConfigUrl, tab_contents));
134   }
135 }
136 
137 }  // anonymous namespace
138 
ShowNetworkProxySettings(TabContents * tab_contents)139 void AdvancedOptionsUtilities::ShowNetworkProxySettings(
140     TabContents* tab_contents) {
141   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
142       NewRunnableFunction(&DetectAndStartProxyConfigUtil, tab_contents));
143 }
144 
145 #endif  // !defined(OS_CHROMEOS)
146