Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: mojo/python/content_handler/content_handler_main.cc

Issue 796373006: Content handler for python. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include <python2.7/Python.h>
6 #include <dlfcn.h>
7
8 #include "base/files/file_path.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/i18n/icu_util.h"
11 #include "mojo/application/application_runner_chromium.h"
12 #include "mojo/application/content_handler_factory.h"
13 #include "mojo/common/common_type_converters.h"
14 #include "mojo/common/data_pipe_utils.h"
15 #include "mojo/public/c/system/main.h"
16 #include "mojo/public/cpp/application/application_delegate.h"
17 #include "mojo/public/cpp/application/application_impl.h"
18 #include "mojo/public/cpp/application/interface_factory_impl.h"
19 #include "third_party/zlib/google/zip_reader.h"
20
21 char kMojoContext[] = "mojo";
22 char kMojoSystemContext[] = "mojo.system";
23 char kMojoSystemImplContext[] = "mojo.system_impl";
24 char kSystem[] = "system";
25 char kSystemImpl[] = "system_impl";
26 char kMojoMain[] = "MojoMain";
27
28 extern "C" {
29 void initsystem();
30 void initsystem_impl();
31 extern char* _Py_PackageContext;
32 }
33
34 namespace mojo {
35 namespace python {
36
37 class PythonContentHandler : public ApplicationDelegate,
38 public ContentHandlerFactory::Delegate {
39 public:
40 PythonContentHandler() : content_handler_factory_(this) {}
41
42 private:
43 // Overridden from ApplicationDelegate:
44 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
45 connection->AddService(&content_handler_factory_);
46 return true;
47 }
48
49 // Extracts the target application into a temporary directory. This directory
50 // is deleted at the end of the life of the PythonContentHandler object.
51 void ExtractApplication(URLResponsePtr response) {
52 MOJO_CHECK(temp_dir_.CreateUniqueTempDir());
qsr 2015/01/07 15:14:46 You cannot use a class member for temp_dir_, as th
etiennej 2015/01/08 11:23:13 Done.
53
54 zip::ZipReader reader;
55 const std::string input_data = CopyToString(response->body.Pass());
56 MOJO_DCHECK(reader.OpenFromString(input_data));
57 base::FilePath temp_dir_path = temp_dir_.path();
58 while (reader.HasMore()) {
59 MOJO_DCHECK(reader.OpenCurrentEntryInZip());
60 MOJO_DCHECK(reader.ExtractCurrentEntryIntoDirectory(temp_dir_path));
61 MOJO_DCHECK(reader.AdvanceToNextEntry());
62 }
63 }
64
65 // Sets up the Python interpreter and loads mojo system modules. This method
66 // returns the global dictionary for the python environment that should be
67 // used for subsequent calls. Takes as input the path of the unpacked
68 // application files.
69 PyObject* SetupPythonEnvironment(const std::string& application_path) {
qsr 2015/01/07 15:14:46 Could you use there and below the helper scoped cl
etiennej 2015/01/08 11:23:13 I am not sure what you mean by "helper scoped clas
etiennej 2015/01/08 17:14:28 Done.
70 dlopen("libpython2.7.so", RTLD_LAZY | RTLD_GLOBAL);
71
72 Py_Initialize();
73
74 PyObject *m, *d;
75 m = PyImport_AddModule("__main__");
76 if (m == NULL)
77 return NULL;
78 d = PyModule_GetDict(m);
79
80 // Inject the application path into the python search path so that imports
81 // from the application work as expected.
82 std::string search_path_py_command =
83 "import sys; sys.path.append('" + application_path + "'); import mojo";
84 PyObject* result =
85 PyRun_String(search_path_py_command.c_str(), Py_file_input, d, d);
86
87 if (result == nullptr) {
88 LOG(ERROR) << "Error while configuring path";
89 PyErr_Print();
90 return NULL;
91 }
92 Py_DECREF(result);
93
94 // Initializing dummy mojo module
95 char* oldcontext = _Py_PackageContext;
96 _Py_PackageContext = kMojoContext;
97 PyObject* mojo_module = Py_InitModule(kMojoContext, nullptr);
98
99 // Initializing injected mojo.system_impl
100 _Py_PackageContext = kMojoSystemImplContext;
101 initsystem_impl();
102 _Py_PackageContext = oldcontext;
103 PyObject* system_impl_module =
104 PyDict_GetItemString(PyImport_GetModuleDict(), kMojoSystemImplContext);
105 PyObject_SetAttrString(mojo_module, kSystemImpl, system_impl_module);
106
107 // Initializing injected mojo.system
108 _Py_PackageContext = kMojoSystemContext;
109 initsystem();
110 _Py_PackageContext = oldcontext;
111 PyObject* system_module =
112 PyDict_GetItemString(PyImport_GetModuleDict(), kMojoSystemContext);
113 PyObject_SetAttrString(mojo_module, kSystem, system_module);
114
115 return d;
116 }
117
118 // Overridden from ContentHandlerFactory::ManagedDelegate:
119 void RunApplication(ShellPtr shell, URLResponsePtr response) override {
120 ExtractApplication(response.Pass());
121 base::FilePath directory_path = temp_dir_.path();
122
123 PyObject* d = SetupPythonEnvironment(directory_path.value());
124 MOJO_DCHECK(d);
125
126 base::FilePath entry_path = directory_path.Append("__mojo__.py");
127
128 FILE* entry_file = base::OpenFile(entry_path, "r");
129 MOJO_DCHECK(entry_file);
130
131 // Load the __mojo__.py file into the interpreter. MojoMain hasn't run yet.
132 PyObject* result =
133 PyRun_File(entry_file, entry_path.value().c_str(), Py_file_input, d, d);
134 if (result == nullptr) {
135 LOG(ERROR) << "Error while loading script";
136 PyErr_Print();
137 return;
138 }
139 Py_DECREF(result);
140
141 // Find MojoMain.
142 PyObject* py_function = PyMapping_GetItemString(d, kMojoMain);
143
144 if (py_function == NULL) {
145 LOG(ERROR) << "Locals size: " << PyMapping_Size(d);
146 LOG(ERROR) << "MojoMain not found";
147 PyErr_Print();
148 return;
149 }
150
151 if (PyCallable_Check(py_function)) {
152 MojoHandle shell_handle = shell.PassMessagePipe().release().value();
153 PyObject* py_input = PyInt_FromLong(shell_handle);
154 PyObject* py_arguments = PyTuple_New(1);
155 // py_input reference is stolen by py_arguments
156 PyTuple_SetItem(py_arguments, 0, py_input);
157 // Run MojoMain with shell_handle as the first and only argument.
158 PyObject* py_output = PyObject_CallObject(py_function, py_arguments);
159
160 Py_DECREF(py_function);
161 Py_DECREF(py_arguments);
162
163 if (py_output) {
164 Py_DECREF(py_output);
165 } else {
166 LOG(ERROR) << "Error while executing MojoMain";
167 PyErr_Print();
168 return;
169 }
170 } else {
171 LOG(ERROR) << "MojoMain is not callable; it should be a function";
172 }
173
174 Py_Finalize();
175 }
176
177 std::string CopyToString(ScopedDataPipeConsumerHandle body) {
178 std::string body_str;
179 bool result = common::BlockingCopyToString(body.Pass(), &body_str);
180 DCHECK(result);
181 return body_str;
182 }
183
184 ContentHandlerFactory content_handler_factory_;
185 base::ScopedTempDir temp_dir_;
186
187 DISALLOW_COPY_AND_ASSIGN(PythonContentHandler);
188 };
189
190 } // namespace python
191 } // namespace mojo
192
193 MojoResult MojoMain(MojoHandle shell_handle) {
194 mojo::ApplicationRunnerChromium runner(
195 new mojo::python::PythonContentHandler());
196 return runner.Run(shell_handle);
197 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698