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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: mojo/python/content_handler/content_handler_main.cc
diff --git a/mojo/python/content_handler/content_handler_main.cc b/mojo/python/content_handler/content_handler_main.cc
new file mode 100644
index 0000000000000000000000000000000000000000..53df8254e0560ac45c3a20e32843d0800417e196
--- /dev/null
+++ b/mojo/python/content_handler/content_handler_main.cc
@@ -0,0 +1,197 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <python2.7/Python.h>
+#include <dlfcn.h>
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/i18n/icu_util.h"
+#include "mojo/application/application_runner_chromium.h"
+#include "mojo/application/content_handler_factory.h"
+#include "mojo/common/common_type_converters.h"
+#include "mojo/common/data_pipe_utils.h"
+#include "mojo/public/c/system/main.h"
+#include "mojo/public/cpp/application/application_delegate.h"
+#include "mojo/public/cpp/application/application_impl.h"
+#include "mojo/public/cpp/application/interface_factory_impl.h"
+#include "third_party/zlib/google/zip_reader.h"
+
+char kMojoContext[] = "mojo";
+char kMojoSystemContext[] = "mojo.system";
+char kMojoSystemImplContext[] = "mojo.system_impl";
+char kSystem[] = "system";
+char kSystemImpl[] = "system_impl";
+char kMojoMain[] = "MojoMain";
+
+extern "C" {
+ void initsystem();
+ void initsystem_impl();
+ extern char* _Py_PackageContext;
+}
+
+namespace mojo {
+namespace python {
+
+class PythonContentHandler : public ApplicationDelegate,
+ public ContentHandlerFactory::Delegate {
+ public:
+ PythonContentHandler() : content_handler_factory_(this) {}
+
+ private:
+ // Overridden from ApplicationDelegate:
+ bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
+ connection->AddService(&content_handler_factory_);
+ return true;
+ }
+
+ // Extracts the target application into a temporary directory. This directory
+ // is deleted at the end of the life of the PythonContentHandler object.
+ void ExtractApplication(URLResponsePtr response) {
+ 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.
+
+ zip::ZipReader reader;
+ const std::string input_data = CopyToString(response->body.Pass());
+ MOJO_DCHECK(reader.OpenFromString(input_data));
+ base::FilePath temp_dir_path = temp_dir_.path();
+ while (reader.HasMore()) {
+ MOJO_DCHECK(reader.OpenCurrentEntryInZip());
+ MOJO_DCHECK(reader.ExtractCurrentEntryIntoDirectory(temp_dir_path));
+ MOJO_DCHECK(reader.AdvanceToNextEntry());
+ }
+ }
+
+ // Sets up the Python interpreter and loads mojo system modules. This method
+ // returns the global dictionary for the python environment that should be
+ // used for subsequent calls. Takes as input the path of the unpacked
+ // application files.
+ 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.
+ dlopen("libpython2.7.so", RTLD_LAZY | RTLD_GLOBAL);
+
+ Py_Initialize();
+
+ PyObject *m, *d;
+ m = PyImport_AddModule("__main__");
+ if (m == NULL)
+ return NULL;
+ d = PyModule_GetDict(m);
+
+ // Inject the application path into the python search path so that imports
+ // from the application work as expected.
+ std::string search_path_py_command =
+ "import sys; sys.path.append('" + application_path + "'); import mojo";
+ PyObject* result =
+ PyRun_String(search_path_py_command.c_str(), Py_file_input, d, d);
+
+ if (result == nullptr) {
+ LOG(ERROR) << "Error while configuring path";
+ PyErr_Print();
+ return NULL;
+ }
+ Py_DECREF(result);
+
+ // Initializing dummy mojo module
+ char* oldcontext = _Py_PackageContext;
+ _Py_PackageContext = kMojoContext;
+ PyObject* mojo_module = Py_InitModule(kMojoContext, nullptr);
+
+ // Initializing injected mojo.system_impl
+ _Py_PackageContext = kMojoSystemImplContext;
+ initsystem_impl();
+ _Py_PackageContext = oldcontext;
+ PyObject* system_impl_module =
+ PyDict_GetItemString(PyImport_GetModuleDict(), kMojoSystemImplContext);
+ PyObject_SetAttrString(mojo_module, kSystemImpl, system_impl_module);
+
+ // Initializing injected mojo.system
+ _Py_PackageContext = kMojoSystemContext;
+ initsystem();
+ _Py_PackageContext = oldcontext;
+ PyObject* system_module =
+ PyDict_GetItemString(PyImport_GetModuleDict(), kMojoSystemContext);
+ PyObject_SetAttrString(mojo_module, kSystem, system_module);
+
+ return d;
+ }
+
+ // Overridden from ContentHandlerFactory::ManagedDelegate:
+ void RunApplication(ShellPtr shell, URLResponsePtr response) override {
+ ExtractApplication(response.Pass());
+ base::FilePath directory_path = temp_dir_.path();
+
+ PyObject* d = SetupPythonEnvironment(directory_path.value());
+ MOJO_DCHECK(d);
+
+ base::FilePath entry_path = directory_path.Append("__mojo__.py");
+
+ FILE* entry_file = base::OpenFile(entry_path, "r");
+ MOJO_DCHECK(entry_file);
+
+ // Load the __mojo__.py file into the interpreter. MojoMain hasn't run yet.
+ PyObject* result =
+ PyRun_File(entry_file, entry_path.value().c_str(), Py_file_input, d, d);
+ if (result == nullptr) {
+ LOG(ERROR) << "Error while loading script";
+ PyErr_Print();
+ return;
+ }
+ Py_DECREF(result);
+
+ // Find MojoMain.
+ PyObject* py_function = PyMapping_GetItemString(d, kMojoMain);
+
+ if (py_function == NULL) {
+ LOG(ERROR) << "Locals size: " << PyMapping_Size(d);
+ LOG(ERROR) << "MojoMain not found";
+ PyErr_Print();
+ return;
+ }
+
+ if (PyCallable_Check(py_function)) {
+ MojoHandle shell_handle = shell.PassMessagePipe().release().value();
+ PyObject* py_input = PyInt_FromLong(shell_handle);
+ PyObject* py_arguments = PyTuple_New(1);
+ // py_input reference is stolen by py_arguments
+ PyTuple_SetItem(py_arguments, 0, py_input);
+ // Run MojoMain with shell_handle as the first and only argument.
+ PyObject* py_output = PyObject_CallObject(py_function, py_arguments);
+
+ Py_DECREF(py_function);
+ Py_DECREF(py_arguments);
+
+ if (py_output) {
+ Py_DECREF(py_output);
+ } else {
+ LOG(ERROR) << "Error while executing MojoMain";
+ PyErr_Print();
+ return;
+ }
+ } else {
+ LOG(ERROR) << "MojoMain is not callable; it should be a function";
+ }
+
+ Py_Finalize();
+ }
+
+ std::string CopyToString(ScopedDataPipeConsumerHandle body) {
+ std::string body_str;
+ bool result = common::BlockingCopyToString(body.Pass(), &body_str);
+ DCHECK(result);
+ return body_str;
+ }
+
+ ContentHandlerFactory content_handler_factory_;
+ base::ScopedTempDir temp_dir_;
+
+ DISALLOW_COPY_AND_ASSIGN(PythonContentHandler);
+};
+
+} // namespace python
+} // namespace mojo
+
+MojoResult MojoMain(MojoHandle shell_handle) {
+ mojo::ApplicationRunnerChromium runner(
+ new mojo::python::PythonContentHandler());
+ return runner.Run(shell_handle);
+}

Powered by Google App Engine
This is Rietveld 408576698