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 "net/test/python_utils.h"
6
7 #include "base/base_paths.h"
8 #include "base/environment.h"
9 #include "base/file_path.h"
10 #include "base/file_util.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/path_service.h"
14 #include "base/utf_string_conversions.h"
15
16 const char kPythonPathEnv[] = "PYTHONPATH";
17
AppendToPythonPath(const FilePath & dir)18 void AppendToPythonPath(const FilePath& dir) {
19 scoped_ptr<base::Environment> env(base::Environment::Create());
20 std::string old_path;
21 std::string dir_path;
22 #if defined(OS_WIN)
23 dir_path = WideToUTF8(dir.value());
24 #elif defined(OS_POSIX)
25 dir_path = dir.value();
26 #endif
27 if (!env->GetVar(kPythonPathEnv, &old_path)) {
28 env->SetVar(kPythonPathEnv, dir_path.c_str());
29 } else if (old_path.find(dir_path) == std::string::npos) {
30 std::string new_path(old_path);
31 #if defined(OS_WIN)
32 new_path.append(";");
33 #elif defined(OS_POSIX)
34 new_path.append(":");
35 #endif
36 new_path.append(dir_path.c_str());
37 env->SetVar(kPythonPathEnv, new_path);
38 }
39 }
40
41 namespace {
42
43 // Search for |to_try|, rolling up the directory tree from
44 // |start_dir|. If found, return true and put the path to |to_try| in
45 // |out_dir|. If not, return false and leave |out_dir| untouched.
TryRelativeToDir(const FilePath & start_dir,const FilePath & to_try,FilePath * out_dir)46 bool TryRelativeToDir(const FilePath& start_dir,
47 const FilePath& to_try,
48 FilePath* out_dir) {
49 FilePath dir(start_dir);
50 while (!file_util::DirectoryExists(dir.Append(to_try))) {
51 FilePath parent = dir.DirName();
52 if (parent == dir) {
53 // We hit the root directory.
54 return false;
55 }
56 dir = parent;
57 }
58 *out_dir = dir;
59 return true;
60 }
61
62 } // namespace
63
GetPyProtoPath(FilePath * dir)64 bool GetPyProtoPath(FilePath* dir) {
65 // Locate the Python code generated by the protocol buffers compiler.
66 FilePath generated_code_dir;
67 if (!PathService::Get(base::DIR_EXE, &generated_code_dir)) {
68 LOG(ERROR) << "Can't find " << generated_code_dir.value();
69 return false;
70 }
71
72 const FilePath kPyProto(FILE_PATH_LITERAL("pyproto"));
73
74 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
75 FilePath source_dir;
76 if (!PathService::Get(base::DIR_SOURCE_ROOT, &source_dir)) {
77 LOG(ERROR) << "Can't find " << source_dir.value();
78 return false;
79 }
80 // On Mac, and possibly Chrome OS, DIR_EXE might be pointing deep
81 // into the Release/ (or Debug/) directory and we can't depend on
82 // how far down it goes. So we walk upwards from DIR_EXE until we
83 // find a likely looking spot.
84 if (!TryRelativeToDir(generated_code_dir, kPyProto, dir)) {
85 LOG(WARNING) << "Can't find " << kPyProto.value()
86 << " next to " << generated_code_dir.value();
87 // On Chrome OS, we may have installed the test binaries and support tools
88 // in a wholly separate location, relative to DIR_SOURCE_ROOT. We'll want
89 // to do a similar investigation from that point as well.
90 generated_code_dir = source_dir
91 .Append(FILE_PATH_LITERAL("out"))
92 .Append(FILE_PATH_LITERAL("Release"));
93 if (!TryRelativeToDir(generated_code_dir, kPyProto, dir)) {
94 LOG(WARNING) << "Can't find " << kPyProto.value()
95 << " next to " << generated_code_dir.value();
96 return false;
97 }
98 }
99 generated_code_dir = *dir;
100 #endif
101 *dir = generated_code_dir.Append(kPyProto);
102 VLOG(2) << "Found " << kPyProto.value() << " in " << dir->value();
103 return true;
104 }
105
GetPythonRunTime(FilePath * dir)106 bool GetPythonRunTime(FilePath* dir) {
107 #if defined(OS_WIN)
108 if (!PathService::Get(base::DIR_SOURCE_ROOT, dir))
109 return false;
110 *dir = dir->Append(FILE_PATH_LITERAL("third_party"))
111 .Append(FILE_PATH_LITERAL("python_26"))
112 .Append(FILE_PATH_LITERAL("python.exe"));
113 #elif defined(OS_POSIX)
114 *dir = FilePath("python");
115 #endif
116 return true;
117 }
118