Home | History | Annotate | Download | only in common
      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 "mojo/common/data_pipe_utils.h"
      6 
      7 #include <stddef.h>
      8 #include <stdint.h>
      9 #include <stdio.h>
     10 #include <utility>
     11 
     12 #include "base/files/file_path.h"
     13 #include "base/files/file_util.h"
     14 #include "base/files/scoped_file.h"
     15 #include "base/message_loop/message_loop.h"
     16 #include "base/task_runner_util.h"
     17 
     18 namespace mojo {
     19 namespace common {
     20 namespace {
     21 
     22 bool BlockingCopyHelper(ScopedDataPipeConsumerHandle source,
     23     const base::Callback<size_t(const void*, uint32_t)>& write_bytes) {
     24   for (;;) {
     25     const void* buffer;
     26     uint32_t num_bytes;
     27     MojoResult result = BeginReadDataRaw(
     28         source.get(), &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
     29     if (result == MOJO_RESULT_OK) {
     30       size_t bytes_written = write_bytes.Run(buffer, num_bytes);
     31       result = EndReadDataRaw(source.get(), num_bytes);
     32       if (bytes_written < num_bytes || result != MOJO_RESULT_OK)
     33         return false;
     34     } else if (result == MOJO_RESULT_SHOULD_WAIT) {
     35       result = Wait(source.get(),
     36                     MOJO_HANDLE_SIGNAL_READABLE,
     37                     MOJO_DEADLINE_INDEFINITE,
     38                     nullptr);
     39       if (result != MOJO_RESULT_OK) {
     40         // If the producer handle was closed, then treat as EOF.
     41         return result == MOJO_RESULT_FAILED_PRECONDITION;
     42       }
     43     } else if (result == MOJO_RESULT_FAILED_PRECONDITION) {
     44       // If the producer handle was closed, then treat as EOF.
     45       return true;
     46     } else {
     47       // Some other error occurred.
     48       break;
     49     }
     50   }
     51 
     52   return false;
     53 }
     54 
     55 size_t CopyToStringHelper(
     56     std::string* result, const void* buffer, uint32_t num_bytes) {
     57   result->append(static_cast<const char*>(buffer), num_bytes);
     58   return num_bytes;
     59 }
     60 
     61 size_t CopyToFileHelper(FILE* fp, const void* buffer, uint32_t num_bytes) {
     62   return fwrite(buffer, 1, num_bytes, fp);
     63 }
     64 
     65 } // namespace
     66 
     67 
     68 // TODO(hansmuller): Add a max_size parameter.
     69 bool BlockingCopyToString(ScopedDataPipeConsumerHandle source,
     70                           std::string* result) {
     71   CHECK(result);
     72   result->clear();
     73   return BlockingCopyHelper(std::move(source),
     74                             base::Bind(&CopyToStringHelper, result));
     75 }
     76 
     77 bool MOJO_COMMON_EXPORT BlockingCopyFromString(
     78     const std::string& source,
     79     const ScopedDataPipeProducerHandle& destination) {
     80   auto it = source.begin();
     81   for (;;) {
     82     void* buffer = nullptr;
     83     uint32_t buffer_num_bytes = 0;
     84     MojoResult result =
     85         BeginWriteDataRaw(destination.get(), &buffer, &buffer_num_bytes,
     86                           MOJO_WRITE_DATA_FLAG_NONE);
     87     if (result == MOJO_RESULT_OK) {
     88       char* char_buffer = static_cast<char*>(buffer);
     89       uint32_t byte_index = 0;
     90       while (it != source.end() && byte_index < buffer_num_bytes) {
     91         char_buffer[byte_index++] = *it++;
     92       }
     93       EndWriteDataRaw(destination.get(), byte_index);
     94       if (it == source.end())
     95         return true;
     96     } else if (result == MOJO_RESULT_SHOULD_WAIT) {
     97       result = Wait(destination.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
     98                     MOJO_DEADLINE_INDEFINITE, nullptr);
     99       if (result != MOJO_RESULT_OK) {
    100         // If the consumer handle was closed, then treat as EOF.
    101         return result == MOJO_RESULT_FAILED_PRECONDITION;
    102       }
    103     } else {
    104       // If the consumer handle was closed, then treat as EOF.
    105       return result == MOJO_RESULT_FAILED_PRECONDITION;
    106     }
    107   }
    108 }
    109 
    110 bool BlockingCopyToFile(ScopedDataPipeConsumerHandle source,
    111                         const base::FilePath& destination) {
    112   base::ScopedFILE fp(base::OpenFile(destination, "wb"));
    113   if (!fp)
    114     return false;
    115   return BlockingCopyHelper(std::move(source),
    116                             base::Bind(&CopyToFileHelper, fp.get()));
    117 }
    118 
    119 void CopyToFile(ScopedDataPipeConsumerHandle source,
    120                 const base::FilePath& destination,
    121                 base::TaskRunner* task_runner,
    122                 const base::Callback<void(bool)>& callback) {
    123   base::PostTaskAndReplyWithResult(
    124       task_runner,
    125       FROM_HERE,
    126       base::Bind(&BlockingCopyToFile, base::Passed(&source), destination),
    127       callback);
    128 }
    129 
    130 }  // namespace common
    131 }  // namespace mojo
    132