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

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

Issue 901203002: Move python content handler to //services/ (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 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 "mojo/public/python/src/common.h"
20 #include "third_party/zlib/google/zip_reader.h"
21
22 char kMojoSystem[] = "mojo_system";
23 char kMojoSystemImpl[] = "mojo_system_impl";
24 char kMojoMain[] = "MojoMain";
25
26 extern "C" {
27 void initmojo_system();
28 void initmojo_system_impl();
29 }
30
31 namespace mojo {
32 namespace python {
33
34 class PythonContentHandler : public ApplicationDelegate,
35 public ContentHandlerFactory::Delegate {
36 public:
37 PythonContentHandler() : content_handler_factory_(this) {}
38
39 private:
40 // Overridden from ApplicationDelegate:
41 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
42 connection->AddService(&content_handler_factory_);
43 return true;
44 }
45
46 // Extracts the target application into a temporary directory. This directory
47 // is deleted at the end of the life of the PythonContentHandler object.
48 std::unique_ptr<base::ScopedTempDir> ExtractApplication(
49 URLResponsePtr response) {
50 std::unique_ptr<base::ScopedTempDir> temp_dir(new base::ScopedTempDir);
51 CHECK(temp_dir->CreateUniqueTempDir());
52
53 zip::ZipReader reader;
54 const std::string input_data = CopyToString(response->body.Pass());
55 CHECK(reader.OpenFromString(input_data));
56 base::FilePath temp_dir_path = temp_dir->path();
57 while (reader.HasMore()) {
58 CHECK(reader.OpenCurrentEntryInZip());
59 CHECK(reader.ExtractCurrentEntryIntoDirectory(temp_dir_path));
60 CHECK(reader.AdvanceToNextEntry());
61 }
62 return temp_dir;
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) {
70 // TODO(etiennej): Build python ourselves so we don't have to rely on
71 // dynamically loading a system library.
72 dlopen("libpython2.7.so", RTLD_LAZY | RTLD_GLOBAL);
73
74 PyImport_AppendInittab(kMojoSystemImpl, &initmojo_system_impl);
75 PyImport_AppendInittab(kMojoSystem, &initmojo_system);
76
77 Py_Initialize();
78
79 PyObject *m, *d;
80 m = PyImport_AddModule("__main__");
81 if (m == NULL)
82 return NULL;
83 d = PyModule_GetDict(m);
84
85 // Inject the application path into the python search path so that imports
86 // from the application work as expected.
87 std::string search_path_py_command =
88 "import sys; sys.path.append('" + application_path + "');";
89 ScopedPyRef result(
90 PyRun_String(search_path_py_command.c_str(), Py_file_input, d, d));
91
92 if (result == nullptr) {
93 LOG(ERROR) << "Error while configuring path";
94 PyErr_Print();
95 return NULL;
96 }
97
98 return d;
99 }
100
101 // Overridden from ContentHandlerFactory::ManagedDelegate:
102 void RunApplication(InterfaceRequest<Application> application_request,
103 URLResponsePtr response) override {
104 std::unique_ptr<base::ScopedTempDir> temp_dir =
105 ExtractApplication(response.Pass());
106 base::FilePath directory_path = temp_dir->path();
107
108 PyObject* d = SetupPythonEnvironment(directory_path.value());
109 DCHECK(d);
110
111 base::FilePath entry_path = directory_path.Append("__mojo__.py");
112
113 FILE* entry_file = base::OpenFile(entry_path, "r");
114 DCHECK(entry_file);
115
116 // Ensure that all created objects are destroyed before calling Py_Finalize.
117 {
118 // Load the __mojo__.py file into the interpreter. MojoMain hasn't run
119 // yet.
120 ScopedPyRef result(PyRun_File(entry_file, entry_path.value().c_str(),
121 Py_file_input, d, d));
122 if (result == nullptr) {
123 LOG(ERROR) << "Error while loading script";
124 PyErr_Print();
125 return;
126 }
127
128 // Find MojoMain.
129 ScopedPyRef py_function(PyMapping_GetItemString(d, kMojoMain));
130
131 if (py_function == NULL) {
132 LOG(ERROR) << "Locals size: " << PyMapping_Size(d);
133 LOG(ERROR) << "MojoMain not found";
134 PyErr_Print();
135 return;
136 }
137
138 if (PyCallable_Check(py_function)) {
139 MojoHandle application_request_handle =
140 application_request.PassMessagePipe().release().value();
141 ScopedPyRef py_input(PyInt_FromLong(application_request_handle));
142 ScopedPyRef py_arguments(PyTuple_New(1));
143 // py_input reference is stolen by py_arguments
144 PyTuple_SetItem(py_arguments, 0, py_input.Release());
145 // Run MojoMain with application_request_handle as the first and only
146 // argument.
147 ScopedPyRef py_output(PyObject_CallObject(py_function, py_arguments));
148
149 if (!py_output) {
150 LOG(ERROR) << "Error while executing MojoMain";
151 PyErr_Print();
152 return;
153 }
154 } else {
155 LOG(ERROR) << "MojoMain is not callable; it should be a function";
156 }
157 }
158 Py_Finalize();
159 }
160
161 std::string CopyToString(ScopedDataPipeConsumerHandle body) {
162 std::string body_str;
163 bool result = common::BlockingCopyToString(body.Pass(), &body_str);
164 DCHECK(result);
165 return body_str;
166 }
167
168 ContentHandlerFactory content_handler_factory_;
169
170 DISALLOW_COPY_AND_ASSIGN(PythonContentHandler);
171 };
172
173 } // namespace python
174 } // namespace mojo
175
176 MojoResult MojoMain(MojoHandle shell_handle) {
177 mojo::ApplicationRunnerChromium runner(
178 new mojo::python::PythonContentHandler());
179 return runner.Run(shell_handle);
180 }
OLDNEW
« no previous file with comments | « mojo/python/content_handler/c_base.pxd ('k') | mojo/python/content_handler/mojo_system_impl.pyx » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698