Python handler: Pass a python object to content handled application.

R=etiennej@chromium.org

Review URL: https://codereview.chromium.org/942013003
diff --git a/mojo/public/python/mojo_application/application_runner.py b/mojo/public/python/mojo_application/application_runner.py
index 94f472c..e43a518 100644
--- a/mojo/public/python/mojo_application/application_runner.py
+++ b/mojo/public/python/mojo_application/application_runner.py
@@ -11,8 +11,7 @@
 def RunMojoApplication(application_delegate, app_request_handle):
   loop = mojo_system.RunLoop()
 
-  application = ApplicationImpl(application_delegate,
-                                mojo_system.Handle(app_request_handle))
+  application = ApplicationImpl(application_delegate, app_request_handle)
   application.manager.AddOnErrorCallback(loop.Quit)
 
   loop.Run()
diff --git a/mojo/public/python/src/common.cc b/mojo/public/python/src/common.cc
index e2a832a..d14d718 100644
--- a/mojo/public/python/src/common.cc
+++ b/mojo/public/python/src/common.cc
@@ -41,7 +41,12 @@
 
 ScopedPyRef::ScopedPyRef(PyObject* object, ScopedPyRefAcquire)
     : object_(object) {
-  Py_XINCREF(object_);
+  if (object_)
+    Py_XINCREF(object_);
+}
+
+ScopedPyRef::ScopedPyRef(const ScopedPyRef& other)
+    : ScopedPyRef(other, kAcquire) {
 }
 
 PyObject* ScopedPyRef::Release() {
@@ -57,8 +62,14 @@
   }
 }
 
-ScopedPyRef::operator PyObject*() const {
-  return object_;
+ScopedPyRef& ScopedPyRef::operator=(const ScopedPyRef& other) {
+  if (other)
+    Py_XINCREF(other);
+  PyObject* old = object_;
+  object_ = other;
+  if (old)
+    Py_DECREF(old);
+  return *this;
 }
 
 PythonClosure::PythonClosure(PyObject* callable, const mojo::Closure& quit)
diff --git a/mojo/public/python/src/common.h b/mojo/public/python/src/common.h
index 4eae72e..2ada2a4 100644
--- a/mojo/public/python/src/common.h
+++ b/mojo/public/python/src/common.h
@@ -37,18 +37,19 @@
  public:
   explicit ScopedPyRef(PyObject* object);
   ScopedPyRef(PyObject* object, ScopedPyRefAcquire);
+  ScopedPyRef(const ScopedPyRef& other);
 
   ~ScopedPyRef();
 
   // Releases ownership of the python object contained by this instance.
   PyObject* Release();
 
-  operator PyObject*() const;
+  operator PyObject*() const { return object_; }
+
+  ScopedPyRef& operator=(const ScopedPyRef& other);
 
  private:
   PyObject* object_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedPyRef);
 };
 
 
diff --git a/services/python/content_handler/content_handler_main.cc b/services/python/content_handler/content_handler_main.cc
index f9199ad..39e8b0e 100644
--- a/services/python/content_handler/content_handler_main.cc
+++ b/services/python/content_handler/content_handler_main.cc
@@ -9,6 +9,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/i18n/icu_util.h"
 #include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "mojo/application/application_runner_chromium.h"
 #include "mojo/application/content_handler_factory.h"
 #include "mojo/common/common_type_converters.h"
@@ -85,16 +86,22 @@
     return temp_dir;
   }
 
-  bool RunPythonCommand(std::string command, PyObject* globals) {
-    ScopedPyRef result(
-        PyRun_String(command.c_str(), Py_file_input, globals, NULL));
+  ScopedPyRef RunString(std::string command, PyObject* globals, int mode) {
+    ScopedPyRef result(PyRun_String(command.c_str(), mode, globals, nullptr));
 
-    if (result == nullptr) {
+    if (!result) {
       LOG(ERROR) << "Error while running command: '" << command << "'";
       PyErr_Print();
-      return false;
     }
-    return true;
+    return result;
+  }
+
+  bool Exec(std::string command, PyObject* globals) {
+    return RunString(command, globals, Py_file_input);
+  }
+
+  ScopedPyRef Eval(std::string command, PyObject* globals) {
+    return RunString(command, globals, Py_eval_input);
   }
 
   // Sets up the Python interpreter and loads mojo system modules. This method
@@ -113,8 +120,8 @@
 
     PyObject *m, *d;
     m = PyImport_AddModule("__main__");
-    if (m == NULL)
-        return NULL;
+    if (!m)
+      return nullptr;
     d = PyModule_GetDict(m);
 
     // Enable debug information if requested.
@@ -123,16 +130,16 @@
           "import logging;"
           "logging.basicConfig();"
           "logging.getLogger().setLevel(logging.DEBUG)";
-      if (!RunPythonCommand(enable_logging, d))
-        return NULL;
+      if (!Exec(enable_logging, d))
+        return nullptr;
     }
 
     // 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 + "');";
-    if (!RunPythonCommand(search_path_py_command, d))
-      return NULL;
+    if (!Exec(search_path_py_command, d))
+      return nullptr;
 
     return d;
   }
@@ -158,7 +165,7 @@
       // yet.
       ScopedPyRef result(PyRun_File(entry_file, entry_path.value().c_str(),
                                     Py_file_input, d, d));
-      if (result == nullptr) {
+      if (!result) {
         LOG(ERROR) << "Error while loading script";
         PyErr_Print();
         return;
@@ -167,7 +174,7 @@
       // Find MojoMain.
       ScopedPyRef py_function(PyMapping_GetItemString(d, kMojoMain));
 
-      if (py_function == NULL) {
+      if (!py_function) {
         LOG(ERROR) << "Locals size: " << PyMapping_Size(d);
         LOG(ERROR) << "MojoMain not found";
         PyErr_Print();
@@ -177,7 +184,13 @@
       if (PyCallable_Check(py_function)) {
         MojoHandle application_request_handle =
             application_request.PassMessagePipe().release().value();
-        ScopedPyRef py_input(PyInt_FromLong(application_request_handle));
+        std::string handle_command = base::StringPrintf(
+            "mojo_system.Handle(%u)", application_request_handle);
+        ScopedPyRef py_input(Eval(handle_command, d));
+        if (!py_input) {
+          MojoClose(application_request_handle);
+          return;
+        }
         ScopedPyRef py_arguments(PyTuple_New(1));
         // py_input reference is stolen by py_arguments
         PyTuple_SetItem(py_arguments, 0, py_input.Release());