Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / mojo / system / raw_channel_win.cc
index ea2231f..515311e 100644 (file)
@@ -6,12 +6,13 @@
 
 #include <windows.h>
 
-#include "base/basictypes.h"
+#include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/lazy_instance.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/synchronization/lock.h"
@@ -70,11 +71,12 @@ base::LazyInstance<VistaOrHigherFunctions> g_vista_or_higher_functions =
 
 class RawChannelWin : public RawChannel {
  public:
-  RawChannelWin(embedder::ScopedPlatformHandle handle,
-                Delegate* delegate,
-                base::MessageLoopForIO* message_loop);
+  RawChannelWin(embedder::ScopedPlatformHandle handle);
   virtual ~RawChannelWin();
 
+  // |RawChannel| public methods:
+  virtual size_t GetSerializedPlatformHandleSize() const OVERRIDE;
+
  private:
   // RawChannelIOHandler receives OS notifications for I/O completion. It must
   // be created on the I/O thread.
@@ -126,11 +128,11 @@ class RawChannelWin : public RawChannel {
     // Must be called on the I/O thread.
     bool ShouldSelfDestruct() const;
 
-    // Must be called on the I/O thread. It could be called before or after
-    // detached from the owner.
+    // Must be called on the I/O thread. It may be called before or after
+    // detaching from the owner.
     void OnReadCompleted(DWORD bytes_read, DWORD error);
-    // Must be called on the I/O thread. It could be called before or after
-    // detached from the owner.
+    // Must be called on the I/O thread. It may be called before or after
+    // detaching from the owner.
     void OnWriteCompleted(DWORD bytes_written, DWORD error);
 
     embedder::ScopedPlatformHandle handle_;
@@ -143,6 +145,7 @@ class RawChannelWin : public RawChannel {
     // The following members must be used on the I/O thread.
     scoped_ptr<ReadBuffer> preserved_read_buffer_after_detach_;
     scoped_ptr<WriteBuffer> preserved_write_buffer_after_detach_;
+    bool suppress_self_destruct_;
 
     bool pending_read_;
     base::MessageLoopForIO::IOContext read_context_;
@@ -156,10 +159,11 @@ class RawChannelWin : public RawChannel {
     DISALLOW_COPY_AND_ASSIGN(RawChannelIOHandler);
   };
 
-  // |RawChannel| implementation:
+  // |RawChannel| private methods:
   virtual IOResult Read(size_t* bytes_read) OVERRIDE;
   virtual IOResult ScheduleRead() OVERRIDE;
-  virtual IOResult WriteNoLock(size_t* bytes_written) OVERRIDE;
+  virtual IOResult WriteNoLock(size_t* platform_handles_written,
+                               size_t* bytes_written) OVERRIDE;
   virtual IOResult ScheduleWriteNoLock() OVERRIDE;
   virtual bool OnInit() OVERRIDE;
   virtual void OnShutdownNoLock(
@@ -180,6 +184,7 @@ RawChannelWin::RawChannelIOHandler::RawChannelIOHandler(
     RawChannelWin* owner,
     embedder::ScopedPlatformHandle handle) : handle_(handle.Pass()),
                                              owner_(owner),
+                                             suppress_self_destruct_(false),
                                              pending_read_(false),
                                              pending_write_(false) {
   memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped));
@@ -241,12 +246,18 @@ void RawChannelWin::RawChannelIOHandler::OnIOCompleted(
   DCHECK(!owner_ ||
          base::MessageLoop::current() == owner_->message_loop_for_io());
 
-  if (context == &read_context_)
-    OnReadCompleted(bytes_transferred, error);
-  else if (context == &write_context_)
-    OnWriteCompleted(bytes_transferred, error);
-  else
-    NOTREACHED();
+  {
+    // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they
+    // result in a call to |Shutdown()|).
+    base::AutoReset<bool> resetter(&suppress_self_destruct_, true);
+
+    if (context == &read_context_)
+      OnReadCompleted(bytes_transferred, error);
+    else if (context == &write_context_)
+      OnWriteCompleted(bytes_transferred, error);
+    else
+      NOTREACHED();
+  }
 
   if (ShouldSelfDestruct())
     delete this;
@@ -271,7 +282,7 @@ void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock(
 }
 
 bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const {
-  if (owner_)
+  if (owner_ || suppress_self_destruct_)
     return false;
 
   // Note: Detached, hence no lock needed for |pending_write_|.
@@ -282,6 +293,7 @@ void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read,
                                                          DWORD error) {
   DCHECK(!owner_ ||
          base::MessageLoop::current() == owner_->message_loop_for_io());
+  DCHECK(suppress_self_destruct_);
 
   CHECK(pending_read_);
   pending_read_ = false;
@@ -290,7 +302,8 @@ void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read,
 
   if (error != ERROR_SUCCESS) {
     DCHECK_EQ(bytes_read, 0u);
-    PLOG_IF(ERROR, error != ERROR_BROKEN_PIPE) << "ReadFile";
+    LOG_IF(ERROR, error != ERROR_BROKEN_PIPE)
+        << "ReadFile: " << logging::SystemErrorCodeToString(error);
     owner_->OnReadCompleted(false, 0);
   } else {
     DCHECK_GT(bytes_read, 0u);
@@ -302,6 +315,7 @@ void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written,
                                                           DWORD error) {
   DCHECK(!owner_ ||
          base::MessageLoop::current() == owner_->message_loop_for_io());
+  DCHECK(suppress_self_destruct_);
 
   if (!owner_) {
     // No lock needed.
@@ -317,18 +331,15 @@ void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written,
   }
 
   if (error != ERROR_SUCCESS) {
-    LOG(ERROR) << "WriteFile failed: " << error;
-    owner_->OnWriteCompleted(false, 0);
+    LOG(ERROR) << "WriteFile: " << logging::SystemErrorCodeToString(error);
+    owner_->OnWriteCompleted(false, 0, 0);
   } else {
-    owner_->OnWriteCompleted(true, bytes_written);
+    owner_->OnWriteCompleted(true, 0, bytes_written);
   }
 }
 
-RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle,
-                             Delegate* delegate,
-                             base::MessageLoopForIO* message_loop)
-    : RawChannel(delegate, message_loop),
-      handle_(handle.Pass()),
+RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle)
+    : handle_(handle.Pass()),
       io_handler_(NULL),
       skip_completion_port_on_success_(
           g_vista_or_higher_functions.Get().is_vista_or_higher()) {
@@ -339,6 +350,11 @@ RawChannelWin::~RawChannelWin() {
   DCHECK(!io_handler_);
 }
 
+size_t RawChannelWin::GetSerializedPlatformHandleSize() const {
+  // TODO(vtl): Implement.
+  return 0;
+}
+
 RawChannel::IOResult RawChannelWin::Read(size_t* bytes_read) {
   DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
   DCHECK(io_handler_);
@@ -358,7 +374,8 @@ RawChannel::IOResult RawChannelWin::Read(size_t* bytes_read) {
     DCHECK_EQ(bytes_read_dword, 0u);
     DWORD error = GetLastError();
     if (error != ERROR_IO_PENDING) {
-      LOG_IF(ERROR, error != ERROR_BROKEN_PIPE) << "ReadFile failed: " << error;
+      LOG_IF(ERROR, error != ERROR_BROKEN_PIPE)
+          << "ReadFile: " << logging::SystemErrorCodeToString(error);
       return IO_FAILED;
     }
   }
@@ -408,12 +425,19 @@ RawChannel::IOResult RawChannelWin::ScheduleRead() {
   return io_result;
 }
 
-RawChannel::IOResult RawChannelWin::WriteNoLock(size_t* bytes_written) {
+RawChannel::IOResult RawChannelWin::WriteNoLock(
+    size_t* platform_handles_written,
+    size_t* bytes_written) {
   write_lock().AssertAcquired();
 
   DCHECK(io_handler_);
   DCHECK(!io_handler_->pending_write_no_lock());
 
+  if (write_buffer_no_lock()->HavePlatformHandlesToSend()) {
+    // TODO(vtl): Implement.
+    NOTIMPLEMENTED();
+  }
+
   std::vector<WriteBuffer::Buffer> buffers;
   write_buffer_no_lock()->GetBuffers(&buffers);
   DCHECK(!buffers.empty());
@@ -431,6 +455,7 @@ RawChannel::IOResult RawChannelWin::WriteNoLock(size_t* bytes_written) {
   }
 
   if (result && skip_completion_port_on_success_) {
+    *platform_handles_written = 0;
     *bytes_written = bytes_written_dword;
     return IO_SUCCEEDED;
   }
@@ -454,8 +479,10 @@ RawChannel::IOResult RawChannelWin::ScheduleWriteNoLock() {
   DCHECK(io_handler_);
   DCHECK(!io_handler_->pending_write_no_lock());
 
+  // TODO(vtl): Do something with |platform_handles_written|.
+  size_t platform_handles_written = 0;
   size_t bytes_written = 0;
-  IOResult io_result = WriteNoLock(&bytes_written);
+  IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written);
   if (io_result == IO_SUCCEEDED) {
     DCHECK(skip_completion_port_on_success_);
 
@@ -521,10 +548,9 @@ void RawChannelWin::OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer,
 
 // Static factory method declared in raw_channel.h.
 // static
-RawChannel* RawChannel::Create(embedder::ScopedPlatformHandle handle,
-                               Delegate* delegate,
-                               base::MessageLoopForIO* message_loop) {
-  return new RawChannelWin(handle.Pass(), delegate, message_loop);
+scoped_ptr<RawChannel> RawChannel::Create(
+    embedder::ScopedPlatformHandle handle) {
+  return scoped_ptr<RawChannel>(new RawChannelWin(handle.Pass()));
 }
 
 }  // namespace system