1// Copyright (c) 2012 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 "content/renderer/pepper/host_array_buffer_var.h"
6
7#include <stdio.h>
8#include <string.h>
9
10#include "base/logging.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/memory/shared_memory.h"
13#include "base/process/process_handle.h"
14#include "content/common/sandbox_util.h"
15#include "content/renderer/pepper/host_globals.h"
16#include "content/renderer/pepper/plugin_module.h"
17#include "content/renderer/render_thread_impl.h"
18#include "ppapi/c/pp_instance.h"
19
20using ppapi::ArrayBufferVar;
21using blink::WebArrayBuffer;
22
23namespace content {
24
25HostArrayBufferVar::HostArrayBufferVar(uint32 size_in_bytes)
26    : buffer_(WebArrayBuffer::create(size_in_bytes, 1 /* element_size */)),
27      valid_(true) {}
28
29HostArrayBufferVar::HostArrayBufferVar(const WebArrayBuffer& buffer)
30    : buffer_(buffer), valid_(true) {}
31
32HostArrayBufferVar::HostArrayBufferVar(uint32 size_in_bytes,
33                                       base::SharedMemoryHandle handle)
34    : buffer_(WebArrayBuffer::create(size_in_bytes, 1 /* element_size */)) {
35  base::SharedMemory s(handle, true);
36  valid_ = s.Map(size_in_bytes);
37  if (valid_) {
38    memcpy(buffer_.data(), s.memory(), size_in_bytes);
39    s.Unmap();
40  }
41}
42
43HostArrayBufferVar::~HostArrayBufferVar() {}
44
45void* HostArrayBufferVar::Map() {
46  if (!valid_)
47    return NULL;
48  return buffer_.data();
49}
50
51void HostArrayBufferVar::Unmap() {
52  // We do not used shared memory on the host side. Nothing to do.
53}
54
55uint32 HostArrayBufferVar::ByteLength() { return buffer_.byteLength(); }
56
57bool HostArrayBufferVar::CopyToNewShmem(
58    PP_Instance instance,
59    int* host_shm_handle_id,
60    base::SharedMemoryHandle* plugin_shm_handle) {
61  scoped_ptr<base::SharedMemory> shm(
62      RenderThread::Get()
63          ->HostAllocateSharedMemoryBuffer(ByteLength())
64          .release());
65  if (!shm)
66    return false;
67
68  shm->Map(ByteLength());
69  memcpy(shm->memory(), Map(), ByteLength());
70  shm->Unmap();
71
72  // Duplicate the handle here; the SharedMemory destructor closes
73  // its handle on us.
74  HostGlobals* hg = HostGlobals::Get();
75  PluginModule* pm = hg->GetModule(hg->GetModuleForInstance(instance));
76  base::ProcessId p = pm->GetPeerProcessId();
77  if (p == base::kNullProcessId) {
78    // In-process, clone for ourselves.
79    p = base::GetCurrentProcId();
80  }
81
82  base::PlatformFile platform_file =
83#if defined(OS_WIN)
84      shm->handle();
85#elif defined(OS_POSIX)
86      shm->handle().fd;
87#else
88#error Not implemented.
89#endif
90
91  *plugin_shm_handle = BrokerGetFileHandleForProcess(platform_file, p, false);
92  *host_shm_handle_id = -1;
93  return true;
94}
95
96}  // namespace content
97