Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <python2.7/Python.h> | 5 #include <python2.7/Python.h> |
| 6 #include <dlfcn.h> | 6 #include <dlfcn.h> |
| 7 | 7 |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/files/scoped_temp_dir.h" | 9 #include "base/files/scoped_temp_dir.h" |
| 10 #include "base/i18n/icu_util.h" | 10 #include "base/i18n/icu_util.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "base/strings/stringprintf.h" | |
| 12 #include "mojo/application/application_runner_chromium.h" | 13 #include "mojo/application/application_runner_chromium.h" |
| 13 #include "mojo/application/content_handler_factory.h" | 14 #include "mojo/application/content_handler_factory.h" |
| 14 #include "mojo/common/common_type_converters.h" | 15 #include "mojo/common/common_type_converters.h" |
| 15 #include "mojo/common/data_pipe_utils.h" | 16 #include "mojo/common/data_pipe_utils.h" |
| 16 #include "mojo/public/c/system/main.h" | 17 #include "mojo/public/c/system/main.h" |
| 17 #include "mojo/public/cpp/application/application_delegate.h" | 18 #include "mojo/public/cpp/application/application_delegate.h" |
| 18 #include "mojo/public/cpp/application/application_impl.h" | 19 #include "mojo/public/cpp/application/application_impl.h" |
| 19 #include "mojo/public/cpp/application/interface_factory_impl.h" | 20 #include "mojo/public/cpp/application/interface_factory_impl.h" |
| 20 #include "mojo/public/python/src/common.h" | 21 #include "mojo/public/python/src/common.h" |
| 21 #include "third_party/zlib/google/zip_reader.h" | 22 #include "third_party/zlib/google/zip_reader.h" |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 CHECK(reader.OpenFromString(input_data)); | 79 CHECK(reader.OpenFromString(input_data)); |
| 79 base::FilePath temp_dir_path = temp_dir->path(); | 80 base::FilePath temp_dir_path = temp_dir->path(); |
| 80 while (reader.HasMore()) { | 81 while (reader.HasMore()) { |
| 81 CHECK(reader.OpenCurrentEntryInZip()); | 82 CHECK(reader.OpenCurrentEntryInZip()); |
| 82 CHECK(reader.ExtractCurrentEntryIntoDirectory(temp_dir_path)); | 83 CHECK(reader.ExtractCurrentEntryIntoDirectory(temp_dir_path)); |
| 83 CHECK(reader.AdvanceToNextEntry()); | 84 CHECK(reader.AdvanceToNextEntry()); |
| 84 } | 85 } |
| 85 return temp_dir; | 86 return temp_dir; |
| 86 } | 87 } |
| 87 | 88 |
| 88 bool RunPythonCommand(std::string command, PyObject* globals) { | 89 ScopedPyRef RunString(std::string command, PyObject* globals, int mode) { |
| 89 ScopedPyRef result( | 90 ScopedPyRef result(PyRun_String(command.c_str(), mode, globals, nullptr)); |
| 90 PyRun_String(command.c_str(), Py_file_input, globals, NULL)); | |
| 91 | 91 |
| 92 if (result == nullptr) { | 92 if (!result) { |
| 93 LOG(ERROR) << "Error while running command: '" << command << "'"; | 93 LOG(ERROR) << "Error while running command: '" << command << "'"; |
| 94 PyErr_Print(); | 94 PyErr_Print(); |
| 95 return false; | |
| 96 } | 95 } |
| 97 return true; | 96 return result; |
| 97 } | |
| 98 | |
| 99 bool Exec(std::string command, PyObject* globals) { | |
| 100 return RunString(command, globals, Py_file_input); | |
| 101 } | |
| 102 | |
| 103 ScopedPyRef Eval(std::string command, PyObject* globals) { | |
| 104 return RunString(command, globals, Py_eval_input); | |
| 98 } | 105 } |
| 99 | 106 |
| 100 // Sets up the Python interpreter and loads mojo system modules. This method | 107 // Sets up the Python interpreter and loads mojo system modules. This method |
| 101 // returns the global dictionary for the python environment that should be | 108 // returns the global dictionary for the python environment that should be |
| 102 // used for subsequent calls. Takes as input the path of the unpacked | 109 // used for subsequent calls. Takes as input the path of the unpacked |
| 103 // application files. | 110 // application files. |
| 104 PyObject* SetupPythonEnvironment(const std::string& application_path) { | 111 PyObject* SetupPythonEnvironment(const std::string& application_path) { |
| 105 // TODO(etiennej): Build python ourselves so we don't have to rely on | 112 // TODO(etiennej): Build python ourselves so we don't have to rely on |
| 106 // dynamically loading a system library. | 113 // dynamically loading a system library. |
| 107 dlopen("libpython2.7.so", RTLD_LAZY | RTLD_GLOBAL); | 114 dlopen("libpython2.7.so", RTLD_LAZY | RTLD_GLOBAL); |
| 108 | 115 |
| 109 PyImport_AppendInittab(kMojoSystemImpl, &initmojo_system_impl); | 116 PyImport_AppendInittab(kMojoSystemImpl, &initmojo_system_impl); |
| 110 PyImport_AppendInittab(kMojoSystem, &initmojo_system); | 117 PyImport_AppendInittab(kMojoSystem, &initmojo_system); |
| 111 | 118 |
| 112 Py_Initialize(); | 119 Py_Initialize(); |
| 113 | 120 |
| 114 PyObject *m, *d; | 121 PyObject *m, *d; |
| 115 m = PyImport_AddModule("__main__"); | 122 m = PyImport_AddModule("__main__"); |
| 116 if (m == NULL) | 123 if (!m) |
| 117 return NULL; | 124 return nullptr; |
| 118 d = PyModule_GetDict(m); | 125 d = PyModule_GetDict(m); |
| 119 | 126 |
| 120 // Enable debug information if requested. | 127 // Enable debug information if requested. |
| 121 if (debug_) { | 128 if (debug_) { |
| 122 std::string enable_logging = | 129 std::string enable_logging = |
| 123 "import logging;" | 130 "import logging;" |
| 124 "logging.basicConfig();" | 131 "logging.basicConfig();" |
| 125 "logging.getLogger().setLevel(logging.DEBUG)"; | 132 "logging.getLogger().setLevel(logging.DEBUG)"; |
| 126 if (!RunPythonCommand(enable_logging, d)) | 133 if (!Exec(enable_logging, d)) |
| 127 return NULL; | 134 return nullptr; |
| 128 } | 135 } |
| 129 | 136 |
| 130 // Inject the application path into the python search path so that imports | 137 // Inject the application path into the python search path so that imports |
| 131 // from the application work as expected. | 138 // from the application work as expected. |
| 132 std::string search_path_py_command = | 139 std::string search_path_py_command = |
| 133 "import sys; sys.path.append('" + application_path + "');"; | 140 "import sys; sys.path.append('" + application_path + "');"; |
| 134 if (!RunPythonCommand(search_path_py_command, d)) | 141 if (!Exec(search_path_py_command, d)) |
| 135 return NULL; | 142 return nullptr; |
| 136 | 143 |
| 137 return d; | 144 return d; |
| 138 } | 145 } |
| 139 | 146 |
| 140 // Overridden from ContentHandlerFactory::ManagedDelegate: | 147 // Overridden from ContentHandlerFactory::ManagedDelegate: |
| 141 void RunApplication(InterfaceRequest<Application> application_request, | 148 void RunApplication(InterfaceRequest<Application> application_request, |
| 142 URLResponsePtr response) override { | 149 URLResponsePtr response) override { |
| 143 std::unique_ptr<base::ScopedTempDir> temp_dir = | 150 std::unique_ptr<base::ScopedTempDir> temp_dir = |
| 144 ExtractApplication(response.Pass()); | 151 ExtractApplication(response.Pass()); |
| 145 base::FilePath directory_path = temp_dir->path(); | 152 base::FilePath directory_path = temp_dir->path(); |
| 146 | 153 |
| 147 PyObject* d = SetupPythonEnvironment(directory_path.value()); | 154 PyObject* d = SetupPythonEnvironment(directory_path.value()); |
| 148 DCHECK(d); | 155 DCHECK(d); |
| 149 | 156 |
| 150 base::FilePath entry_path = directory_path.Append("__mojo__.py"); | 157 base::FilePath entry_path = directory_path.Append("__mojo__.py"); |
| 151 | 158 |
| 152 FILE* entry_file = base::OpenFile(entry_path, "r"); | 159 FILE* entry_file = base::OpenFile(entry_path, "r"); |
| 153 DCHECK(entry_file); | 160 DCHECK(entry_file); |
| 154 | 161 |
| 155 // Ensure that all created objects are destroyed before calling Py_Finalize. | 162 // Ensure that all created objects are destroyed before calling Py_Finalize. |
| 156 { | 163 { |
| 157 // Load the __mojo__.py file into the interpreter. MojoMain hasn't run | 164 // Load the __mojo__.py file into the interpreter. MojoMain hasn't run |
| 158 // yet. | 165 // yet. |
| 159 ScopedPyRef result(PyRun_File(entry_file, entry_path.value().c_str(), | 166 ScopedPyRef result(PyRun_File(entry_file, entry_path.value().c_str(), |
| 160 Py_file_input, d, d)); | 167 Py_file_input, d, d)); |
| 161 if (result == nullptr) { | 168 if (!result) { |
| 162 LOG(ERROR) << "Error while loading script"; | 169 LOG(ERROR) << "Error while loading script"; |
| 163 PyErr_Print(); | 170 PyErr_Print(); |
| 164 return; | 171 return; |
| 165 } | 172 } |
| 166 | 173 |
| 167 // Find MojoMain. | 174 // Find MojoMain. |
| 168 ScopedPyRef py_function(PyMapping_GetItemString(d, kMojoMain)); | 175 ScopedPyRef py_function(PyMapping_GetItemString(d, kMojoMain)); |
| 169 | 176 |
| 170 if (py_function == NULL) { | 177 if (!py_function) { |
| 171 LOG(ERROR) << "Locals size: " << PyMapping_Size(d); | 178 LOG(ERROR) << "Locals size: " << PyMapping_Size(d); |
| 172 LOG(ERROR) << "MojoMain not found"; | 179 LOG(ERROR) << "MojoMain not found"; |
| 173 PyErr_Print(); | 180 PyErr_Print(); |
| 174 return; | 181 return; |
| 175 } | 182 } |
| 176 | 183 |
| 177 if (PyCallable_Check(py_function)) { | 184 if (PyCallable_Check(py_function)) { |
| 178 MojoHandle application_request_handle = | 185 MojoHandle application_request_handle = |
| 179 application_request.PassMessagePipe().release().value(); | 186 application_request.PassMessagePipe().release().value(); |
| 180 ScopedPyRef py_input(PyInt_FromLong(application_request_handle)); | 187 std::string handle_command = base::StringPrintf( |
| 188 "mojo_system.Handle(%u)", application_request_handle); | |
| 189 ScopedPyRef py_input = Eval(handle_command, d); | |
|
etiennej
2015/02/24 09:20:54
Why can't you use ScopedPyRef py_input(Eval(handle
qsr
2015/02/24 13:25:16
I can. Done.
| |
| 190 if (!py_input) { | |
| 191 MojoClose(application_request_handle); | |
| 192 return; | |
| 193 } | |
| 181 ScopedPyRef py_arguments(PyTuple_New(1)); | 194 ScopedPyRef py_arguments(PyTuple_New(1)); |
| 182 // py_input reference is stolen by py_arguments | 195 // py_input reference is stolen by py_arguments |
| 183 PyTuple_SetItem(py_arguments, 0, py_input.Release()); | 196 PyTuple_SetItem(py_arguments, 0, py_input.Release()); |
| 184 // Run MojoMain with application_request_handle as the first and only | 197 // Run MojoMain with application_request_handle as the first and only |
| 185 // argument. | 198 // argument. |
| 186 ScopedPyRef py_output(PyObject_CallObject(py_function, py_arguments)); | 199 ScopedPyRef py_output(PyObject_CallObject(py_function, py_arguments)); |
| 187 | 200 |
| 188 if (!py_output) { | 201 if (!py_output) { |
| 189 LOG(ERROR) << "Error while executing MojoMain"; | 202 LOG(ERROR) << "Error while executing MojoMain"; |
| 190 PyErr_Print(); | 203 PyErr_Print(); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 212 | 225 |
| 213 } // namespace content_handler | 226 } // namespace content_handler |
| 214 } // namespace python | 227 } // namespace python |
| 215 } // namespace services | 228 } // namespace services |
| 216 | 229 |
| 217 MojoResult MojoMain(MojoHandle shell_handle) { | 230 MojoResult MojoMain(MojoHandle shell_handle) { |
| 218 mojo::ApplicationRunnerChromium runner( | 231 mojo::ApplicationRunnerChromium runner( |
| 219 new services::python::content_handler::PythonContentHandler()); | 232 new services::python::content_handler::PythonContentHandler()); |
| 220 return runner.Run(shell_handle); | 233 return runner.Run(shell_handle); |
| 221 } | 234 } |
| OLD | NEW |