Home | History | Annotate | Download | only in options
      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|.
     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.
     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.
     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.
     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 
    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